1/* hppa-aux.c -- Assembler for the PA - PA-RISC specific support routines
2   Copyright (C) 1989 Free Software Foundation, Inc.
3
4This file is part of GAS, the GNU Assembler.
5
6GAS is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GAS is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GAS; see the file COPYING.  If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20/*
21   HP PA-RISC support was contributed by the Center for Software Science
22   at the University of Utah.
23 */
24
25#include <stdio.h>
26#include <string.h>
27#include <ctype.h>
28
29#include "obstack.h"
30#include "as.h"
31#include "frags.h"
32#include "flonum.h"
33#include "expr.h"
34#include "hash.h"
35#include "md.h"
36#include "symbols.h"
37#include "messages.h"
38#include "hppa-aux.h"
39#include "stuff/hppa.h"
40
41extern char *expr_end; /* defined in hppa.c */
42
43static const int print_errors = 1;
44
45static int reg_name_search(
46    char *name);
47
48int pa_parse_number(s)
49	char **s;
50{
51	int num;
52	char *name;
53	char c;
54	symbolS *sym;
55	int status;
56	char * p = *s;
57
58	while ( *p == ' ' || *p == '\t' )
59		p = p + 1;
60	num=-1; /* assume invalid number to begin with */
61	if (isdigit(*p)) {
62		num = 0; /* now we know it is a number */
63
64		if ( *p == '0'
65			&& ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
66			p = p + 2;
67			while ( isdigit(*p)	|| ( (*p >= 'a') && (*p <= 'f') )
68				|| ( (*p >= 'A') && (*p <= 'F') ) ){
69				if ( isdigit(*p) )
70					num = num*16 + *p-'0';
71				else if ( *p >= 'a' && *p <= 'f' )
72					num = num*16 + *p-'a' + 10;
73				else
74					num = num*16 + *p-'A' + 10;
75				++p;
76			}
77		}
78		else {
79			while (isdigit(*p)) {
80				num= num*10 + *p-'0';
81				++p;
82			}
83		}
84	}
85	else if ( *p == '%' ) {   /* could be a pre-defined register */
86		num = 0;
87		name = p;
88		p++;
89		c = *p;
90
91		/*
92		 * tege hack: Special case for general registers as the
93		 * general code makes a binary search with case translation,
94		 * and is VERY slow.
95		 */
96		if (c == 'r') {
97			p++;
98			if (!isdigit(*p))
99				as_bad("Undefined register: '%s'. ASSUMING 0",name);
100			else {
101				do
102					num= num*10 + *p++ - '0';
103				while (isdigit(*p));
104			}
105		}
106		else {
107	    	while ( is_part_of_name(c) ) {
108		    	p = p + 1;
109		    	c = *p;
110	    	}
111	    	/* Terminate string with \0.  Restore below.  */
112	    	*p = 0;
113	    	status = reg_name_search(name);
114	    	if ( status >= 0 )
115				num = status;
116	    	else {
117		    	if ( print_errors )
118			    	as_bad("Undefined register: '%s'. ASSUMING 0",name);
119		    	else
120			    	num = -1;
121	    	}
122	    	/* Restore orignal value of string.  */
123	    	*p = c;
124		}
125	}
126	else {
127		num = 0;
128		name = p;
129		c = *p;
130		while ( is_part_of_name(c) ) {
131			p = p + 1;
132			c = *p;
133		}
134		*p = 0;
135		if ( (sym = symbol_table_lookup(name)) != NULL ) {
136			if ( sym->sy_type == N_ABS &&  sym->sy_other == NO_SECT ) {
137				num = sym->sy_value;
138			}
139			else {
140				if ( print_errors )
141					as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
142				else
143					num = -1;
144			}
145		}
146		else {
147			if ( print_errors )
148				as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
149			else
150				num = -1;
151		}
152		*p = c;
153	}
154
155	*s = p;
156	return num;
157}
158
159struct pd_reg {
160	char	*name;
161	int	value;
162};
163
164/*	List of registers that are pre-defined:
165
166	General Registers:
167
168	Name	Value		Name	Value
169	%r0			0		%r16	16
170	%r1			1		%r17	17
171	%r2			2		%r18	18
172	%r3			3		%r19	19
173	%r4			4		%r20	20
174	%r5			5		%r21	21
175	%r6			6		%r22	22
176	%r7			7		%r23	23
177	%r8			8		%r24	24
178	%r9			9		%r25	25
179	%r10		10		%r26	26
180	%r11		11		%r27	27
181	%r12		12		%r28	28
182	%r13		13		%r29	29
183	%r14		14		%r30	30
184	%r15		15		%r31	31
185
186	Floating-point Registers:
187	[NOTE:  Also includes L and R versions of these (e.g. %fr19L, %fr19R)]
188
189	Name	Value		Name	Value
190	%fr0	0		%fr16	16
191	%fr1	1		%fr17	17
192	%fr2	2		%fr18	18
193	%fr3	3		%fr19	19
194	%fr4	4		%fr20	20
195	%fr5	5		%fr21	21
196	%fr6	6		%fr22	22
197	%fr7	7		%fr23	23
198	%fr8	8		%fr24	24
199	%fr9	9		%fr25	25
200	%fr10	10		%fr26	26
201	%fr11	11		%fr27	27
202	%fr12	12		%fr28	28
203	%fr13	13		%fr29	29
204	%fr14	14		%fr30	30
205	%fr15	15		%fr31	31
206
207	Space Registers:
208
209	Name	Value		Name	Value
210	%sr0	0		%sr4	4
211	%sr1	1		%sr5	5
212	%sr2	2		%sr6	6
213	%sr3	3		%sr7	7
214
215	Control registers and their synonyms:
216
217	Names			Value
218	%cr0	%rctr		0
219	%cr8	%pidr1		8
220	%cr9	%pidr2		9
221	%cr10	%ccr		10
222	%cr11	%sar		11
223	%cr12	%pidr3		12
224	%cr13	%pidr4		13
225	%cr14	%iva		14
226	%cr15	%eiem		15
227	%cr16	%itmr		16
228	%cr17	%pcsq		17
229	%cr18	%pcoq		18
230	%cr19	%iir		19
231	%cr20	%isr		20
232	%cr21	%ior		21
233	%cr22	%ipsw		22
234	%cr23	%eirr		23
235	%cr24	%tr0 %ppda	24
236	%cr25	%tr1 %hta	25
237	%cr26	%tr2		26
238	%cr27	%tr3		27
239	%cr28	%tr4		28
240	%cr29	%tr5		29
241	%cr30	%tr6		30
242	%cr31	%tr7		31
243
244*/
245
246/* This table is sorted. Suitable for searching by a binary search. */
247
248static struct pd_reg pre_defined_registers[] = {
249	{	"%ccr",		10	},
250	{	"%cr0",		0	},
251	{	"%cr10",	10	},
252	{	"%cr11",	11	},
253	{	"%cr12",	12	},
254	{	"%cr13",	13	},
255	{	"%cr14",	14	},
256	{	"%cr15",	15	},
257	{	"%cr16",	16	},
258	{	"%cr17",	17	},
259	{	"%cr18",	18	},
260	{	"%cr19",	19	},
261	{	"%cr20",	20	},
262	{	"%cr21",	21	},
263	{	"%cr22",	22	},
264	{	"%cr23",	23	},
265	{	"%cr24",	24	},
266	{	"%cr25",	25	},
267	{	"%cr26",	26	},
268	{	"%cr27",	27	},
269	{	"%cr28",	28	},
270	{	"%cr29",	29	},
271	{	"%cr30",	30	},
272	{	"%cr31",	31	},
273	{	"%cr8",		8	},
274	{	"%cr9",		9	},
275	{	"%eiem",	15	},
276	{	"%eirr",	23	},
277	{	"%fr0",		0	},
278	{	"%fr0L",	0	},
279	{	"%fr0R",	0	},
280	{	"%fr1",		1	},
281	{	"%fr10",	10	},
282	{	"%fr10L",	10	},
283	{	"%fr10R",	10	},
284	{	"%fr11",	11	},
285	{	"%fr11L",	11	},
286	{	"%fr11R",	11	},
287	{	"%fr12",	12	},
288	{	"%fr12L",	12	},
289	{	"%fr12R",	12	},
290	{	"%fr13",	13	},
291	{	"%fr13L",	13	},
292	{	"%fr13R",	13	},
293	{	"%fr14",	14	},
294	{	"%fr14L",	14	},
295	{	"%fr14R",	14	},
296	{	"%fr15",	15	},
297	{	"%fr15L",	15	},
298	{	"%fr15R",	15	},
299	{	"%fr16",	16	},
300	{	"%fr16L",	16	},
301	{	"%fr16R",	16	},
302	{	"%fr17",	17	},
303	{	"%fr17L",	17	},
304	{	"%fr17R",	17	},
305	{	"%fr18",	18	},
306	{	"%fr18L",	18	},
307	{	"%fr18R",	18	},
308	{	"%fr19",	19	},
309	{	"%fr19L",	19	},
310	{	"%fr19R",	19	},
311	{	"%fr1L",	1	},
312	{	"%fr1R",	1	},
313	{	"%fr2",		2	},
314	{	"%fr20",	20	},
315	{	"%fr20L",	20	},
316	{	"%fr20R",	20	},
317	{	"%fr21",	21	},
318	{	"%fr21L",	21	},
319	{	"%fr21R",	21	},
320	{	"%fr22",	22	},
321	{	"%fr22L",	22	},
322	{	"%fr22R",	22	},
323	{	"%fr23",	23	},
324	{	"%fr23L",	23	},
325	{	"%fr23R",	23	},
326	{	"%fr24",	24	},
327	{	"%fr24L",	24	},
328	{	"%fr24R",	24	},
329	{	"%fr25",	25	},
330	{	"%fr25L",	25	},
331	{	"%fr25R",	25	},
332	{	"%fr26",	26	},
333	{	"%fr26L",	26	},
334	{	"%fr26R",	26	},
335	{	"%fr27",	27	},
336	{	"%fr27L",	27	},
337	{	"%fr27R",	27	},
338	{	"%fr28",	28	},
339	{	"%fr28L",	28	},
340	{	"%fr28R",	28	},
341	{	"%fr29",	29	},
342	{	"%fr29L",	29	},
343	{	"%fr29R",	29	},
344	{	"%fr2L",	2	},
345	{	"%fr2R",	2	},
346	{	"%fr3",		3	},
347	{	"%fr30",	30	},
348	{	"%fr30L",	30	},
349	{	"%fr30R",	30	},
350	{	"%fr31",	31	},
351	{	"%fr31L",	31	},
352	{	"%fr31R",	31	},
353	{	"%fr3L",	3	},
354	{	"%fr3R",	3	},
355	{	"%fr4",		4	},
356	{	"%fr4L",	4	},
357	{	"%fr4R",	4	},
358	{	"%fr5",		5	},
359	{	"%fr5L",	5	},
360	{	"%fr5R",	5	},
361	{	"%fr6",		6	},
362	{	"%fr6L",	6	},
363	{	"%fr6R",	6	},
364	{	"%fr7",		7	},
365	{	"%fr7L",	7	},
366	{	"%fr7R",	7	},
367	{	"%fr8",		8	},
368	{	"%fr8L",	8	},
369	{	"%fr8R",	8	},
370	{	"%fr9",		9	},
371	{	"%fr9L",	9	},
372	{	"%fr9R",	9	},
373	{	"%hta",		25	},
374	{	"%iir",		19	},
375	{	"%ior",		21	},
376	{	"%ipsw",	22	},
377	{	"%isr",		20	},
378	{	"%itmr",	16	},
379	{	"%iva",		14	},
380	{	"%pcoq",	18	},
381	{	"%pcsq",	17	},
382	{	"%pidr1",	8	},
383	{	"%pidr2",	9	},
384	{	"%pidr3",	12	},
385	{	"%pidr4",	13	},
386	{	"%ppda",	24	},
387	{	"%r0",		0	},
388	{	"%r1",		1	},
389	{	"%r10",		10	},
390	{	"%r11",		11	},
391	{	"%r12",		12	},
392	{	"%r13",		13	},
393	{	"%r14",		14	},
394	{	"%r15",		15	},
395	{	"%r16",		16	},
396	{	"%r17",		17	},
397	{	"%r18",		18	},
398	{	"%r19",		19	},
399	{	"%r2",		2	},
400	{	"%r20",		20	},
401	{	"%r21",		21	},
402	{	"%r22",		22	},
403	{	"%r23",		23	},
404	{	"%r24",		24	},
405	{	"%r25",		25	},
406	{	"%r26",		26	},
407	{	"%r27",		27	},
408	{	"%r28",		28	},
409	{	"%r29",		29	},
410	{	"%r3",		3	},
411	{	"%r30",		30	},
412	{	"%r31",		31	},
413	{	"%r4",		4	},
414	{	"%r4L",		4	},
415	{	"%r4R",		4	},
416	{	"%r5",		5	},
417	{	"%r5L",		5	},
418	{	"%r5R",		5	},
419	{	"%r6",		6	},
420	{	"%r6L",		6	},
421	{	"%r6R",		6	},
422	{	"%r7",		7	},
423	{	"%r7L",		7	},
424	{	"%r7R",		7	},
425	{	"%r8",		8	},
426	{	"%r8L",		8	},
427	{	"%r8R",		8	},
428	{	"%r9",		9	},
429	{	"%r9L",		9	},
430	{	"%r9R",		9	},
431	{	"%rctr",	0	},
432	{	"%sar",		11	},
433	{	"%sr0",		0	},
434	{	"%sr1",		1	},
435	{	"%sr2",		2	},
436	{	"%sr3",		3	},
437	{	"%sr4",		4	},
438	{	"%sr5",		5	},
439	{	"%sr6",		6	},
440	{	"%sr7",		7	},
441	{	"%tr0",		24	},
442	{	"%tr1",		25	},
443	{	"%tr2",		26	},
444	{	"%tr3",		27	},
445	{	"%tr4",		28	},
446	{	"%tr5",		9	},
447	{	"%tr6",		30	},
448	{	"%tr7",		31	}
449};
450
451#define REG_NAME_CNT	(sizeof(pre_defined_registers) / sizeof(struct pd_reg))
452
453static
454int
455reg_name_search(
456char *name)
457{
458	int x,l,r;
459
460	l = 0;
461	r = REG_NAME_CNT - 1;
462
463	do {
464		x = (l + r) / 2;
465		if (strcasecmp(name,pre_defined_registers[x].name) < 0)
466			r = x - 1;
467		else
468			l = x + 1;
469	} while ( !( (strcasecmp(name,pre_defined_registers[x].name) == 0) ||
470		     (l > r) ) );
471
472	if ( strcasecmp(name,pre_defined_registers[x].name) == 0 )
473		return(pre_defined_registers[x].value);
474	else
475		return(-1);
476
477}
478
479static
480int
481is_R_select(
482char *s)
483{
484
485  if ( *s == 'R' || *s == 'r' )
486    return(TRUE);
487  else
488    return(FALSE);
489}
490
491static
492int
493is_L_select(
494char *s)
495{
496
497  if ( *s == 'L' || *s == 'l' )
498    return(TRUE);
499  else
500    return(FALSE);
501}
502
503int need_89_opcode(insn,result)
504     struct pa_it *insn;
505     struct pa_89_fp_reg_struct *result;
506{
507  if ( result->L_R_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL) )
508    return TRUE;
509  else
510    return FALSE;
511}
512
513int
514pa_89_parse_number(s,result)
515     char **s;
516     struct pa_89_fp_reg_struct *result;
517{
518  int num;
519  char *name;
520  char c;
521  symbolS *sym;
522  int status;
523  char * p = *s;
524
525  while ( *p == ' ' || *p == '\t' )
526    p = p + 1;
527  num=-1; /* assume invalid number to begin with */
528  result->number_part = -1;
529  result->L_R_select  = -1;
530
531  if (isdigit(*p)) {
532    num = 0; /* now we know it is a number */
533
534    if ( *p == '0' && ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
535      p = p + 2;
536      while ( isdigit(*p)
537	     || ( (*p >= 'a') && (*p <= 'f') )
538	     || ( (*p >= 'A') && (*p <= 'F') ) ){
539	if ( isdigit(*p) )
540	  num = num*16 + *p-'0';
541	else if ( *p >= 'a' && *p <= 'f' )
542	  num = num*16 + *p-'a' + 10;
543	else
544	  num = num*16 + *p-'A' + 10;
545	++p;
546      }
547    }
548    else {
549      while (isdigit(*p)) {
550	num= num*10 + *p-'0';
551	++p;
552      }
553    }
554
555    result->number_part = num;
556
557    if ( is_R_select(p) ) {
558      result->L_R_select = 1;
559      ++p;
560    }
561    else if ( is_L_select(p) ) {
562      result->L_R_select = 0;
563      ++p;
564    }
565    else
566      result->L_R_select = 0;
567
568  }
569  else if ( *p == '%' ) {          /* could be a pre-defined register */
570    num = 0;
571    name = p;
572    p = p + 1;
573    c = *p;
574    /* tege hack: Special case for general registers
575       as the general code makes a binary search with case translation,
576       and is VERY slow.  */
577    if (c == 'r') {
578      p++;
579      if (!isdigit(*p))
580        as_bad("Undefined register: '%s'. ASSUMING 0",name);
581      else {
582          do
583            num= num*10 + *p++ - '0';
584          while (isdigit(*p));
585        }
586      }
587    else {
588      while ( is_part_of_name(c) ) {
589	p = p + 1;
590	c = *p;
591      }
592      /* Terminate string with \0.  Restore below.  */
593      *p = 0;
594      status = reg_name_search(name);
595      if ( status >= 0 )
596	num = status;
597      else {
598        if ( print_errors )
599	  as_bad("Undefined register: '%s'. ASSUMING 0",name);
600	else
601	  num = -1;
602      }
603      *p = c;
604    }
605
606    result->number_part = num;
607
608    if ( is_R_select(p-1) )
609      result->L_R_select = 1;
610    else if ( is_L_select(p-1) )
611      result->L_R_select = 0;
612    else
613      result->L_R_select = 0;
614
615  }
616  else {
617    num = 0;
618    name = p;
619    c = *p;
620    while ( is_part_of_name(c) ) {
621	    p = p + 1;
622	    c = *p;
623    }
624    *p = 0;
625    if ( (sym = symbol_table_lookup(name)) != NULL ) {
626      if ( sym->sy_type == N_ABS &&  sym->sy_other == NO_SECT ) {
627	num = sym->sy_value;
628      }
629      else {
630	if ( print_errors )
631	  as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
632	else
633	  num = -1;
634      }
635    }
636    else {
637      if ( print_errors )
638	as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
639      else
640	num = -1;
641    }
642    *p = c;
643
644    result->number_part = num;
645
646    if ( is_R_select(p-1) ) {
647      result->L_R_select = 1;
648    }
649    else if ( is_L_select(p-1) ) {
650      result->L_R_select = 0;
651    }
652    else
653      result->L_R_select = 0;
654  }
655
656  *s = p;
657  return num;
658
659}
660
661int pa_parse_fp_cmp_cond(s)
662  char **s;
663{
664  int cond,i;
665  struct possibleS {
666    char *string;
667    int cond;
668  };
669
670  /*
671     This table is sorted by order of the length of the string. This is so we
672     check for <> before we check for <. If we had a <> and checked for < first,
673     we would get a false match.
674   */
675  static struct possibleS poss[] =
676    {
677      { "false?", 0 },
678      { "false",  1 },
679      { "true?",  30 },
680      { "true",   31 },
681      { "!<=>",   3 },
682      { "!?>=",   8 },
683      { "!?<=",   16 },
684      { "!<>",    7 },
685      { "!>=",    11 },
686      { "!?>",    12 },
687      { "?<=",    14 },
688      { "!<=",    19 },
689      { "!?<",    20 },
690      { "?>=",    22 },
691      { "!?=",    24 },
692      { "!=t",    27 },
693      { "<=>",    29 },
694      { "=t",     5 },
695      { "?=",     6 },
696      { "?<",     10 },
697      { "<=",     13 },
698      { "!>",     15 },
699      { "?>",     18 },
700      { ">=",     21 },
701      { "!<",     23 },
702      { "<>",     25 },
703      { "!=",     26 },
704      { "!?",     28 },
705      { "?",      2 },
706      { "=",      4 },
707      { "<",      9 },
708      { ">",      17 }
709    };
710
711  cond=0;
712
713  for ( i = 0; i < 32; i++ ) {
714    if ( strncasecmp(*s,poss[i].string,strlen(poss[i].string)) == 0 ) {
715      cond = poss[i].cond;
716      *s += strlen(poss[i].string);
717      while ( **s == ' ' || **s == '\t' )
718	*s = *s + 1;
719      return cond;
720    }
721  }
722
723  as_bad("Illegal FP Compare Condition: %c",**s);
724  return 0;
725}
726
727FP_Operand_Format pa_parse_fp_format(s)
728     char **s;
729{
730  int f;
731
732  f = SGL;
733  if ( **s == ',' ) {
734    *s += 1;
735    if ( strncasecmp(*s,"sgl",3) == 0 ) {
736      f = SGL;
737      *s += 4;
738    }
739    else if ( strncasecmp(*s,"dbl",3) == 0 ) {
740      f = DBL;
741      *s += 4;
742    }
743    else if ( strncasecmp(*s,"quad",4) == 0 ) {
744      f = QUAD;
745      *s += 5;
746    }
747    else {
748      f = ILLEGAL_FMT;
749      as_bad("Unrecognized FP Operand Format: %3s",*s);
750    }
751  }
752  while ( **s == ' ' || **s == '\t' || **s == 0 )
753    *s = *s + 1;
754
755  return f;
756}
757
758int
759getExpression(
760char *str)
761{
762    char *save_in;
763    segT seg;
764
765    save_in = input_line_pointer;
766    input_line_pointer = str;
767    switch (seg = expression(&the_insn.exp)) {
768
769    case SEG_ABSOLUTE:
770    case SEG_SECT:
771    case SEG_DIFFSECT:
772    case SEG_UNKNOWN:
773    case SEG_NONE:
774    case SEG_BIG:
775	break;
776
777    default:
778	the_insn.error = "illegal segment";
779	expr_end = input_line_pointer;
780	input_line_pointer=save_in;
781	return 1;
782    }
783    expr_end = input_line_pointer;
784    input_line_pointer = save_in;
785    return 0;
786}
787
788int
789getAbsoluteExpression(
790char *str)
791{
792    char *save_in;
793    segT seg;
794
795	for ( ; *str == ' ' || *str == '\t' ; str++)
796		;	/* do nothing */
797    save_in = input_line_pointer;
798    input_line_pointer = str;
799    switch (seg = expression(&the_insn.exp)) {
800    case SEG_ABSOLUTE:
801		break;
802    default:
803		the_insn.error = "segment should be ABSOLUTE";
804		expr_end = input_line_pointer;
805		input_line_pointer=save_in;
806		return 1;
807    }
808    expr_end = input_line_pointer;
809    input_line_pointer = save_in;
810    return 0;
811}
812
813int
814evaluateAbsolute(
815expressionS exp,
816int field_selector)
817{
818	int value;
819	uint32_t left21, right14;
820
821	value = exp.X_add_number;
822	calc_hppa_HILO(0, value, &left21, &right14);
823
824	if ( exp.X_add_symbol ) {
825		value += exp.X_add_symbol->sy_value;
826	}
827	if ( exp.X_subtract_symbol ) {
828		value -= exp.X_subtract_symbol->sy_value;
829	}
830
831	switch (field_selector) {
832	case /* no selector */ 0:
833		break;
834	case /* e_lsel */  1:	/* L` 	*/
835		value = left21;
836		break;
837
838	case /* e_rsel */  2:	/* R`	*/
839		value = right14;
840		break;
841	default:
842		BAD_CASE(field_selector);
843		break;
844  }
845  return value;
846}
847
848int pa_parse_nullif(s)
849     char **s;
850{
851  int nullif;
852
853  nullif = 0;
854  if ( **s == ',' ) {
855    *s = *s + 1;
856    if ( strncasecmp(*s,"n",1) == 0 )
857      nullif = 1;
858    else {
859      as_bad("Unrecognized Nullification: (%c)",**s);
860      nullif = 0;
861    }
862    *s = *s + 1;
863  }
864  while ( **s == ' ' || **s == '\t' )
865    *s = *s + 1;
866
867  return nullif;
868}
869
870int pa_parse_nonneg_cmpsub_cmpltr(s)
871     char **s;
872{
873  int cmpltr;
874  char *name;
875  char c;
876
877  cmpltr = 0;
878  if ( **s == ',' ) {
879    *s+=1;
880    name = *s;
881    while ( **s != ',' && **s != ' ' && **s != '\t' )
882      *s += 1;
883    c = **s;
884    **s = 0x00;
885    if ( strcmp(name,"=") == 0 ) {
886      cmpltr = 1;
887    }
888    else if ( strcmp(name,"<") == 0 ) {
889      cmpltr = 2;
890    }
891    else if ( strcmp(name,"<=") == 0 ) {
892      cmpltr = 3;
893    }
894    else if ( strcmp(name,"<<") == 0 ) {
895      cmpltr = 4;
896    }
897    else if ( strcmp(name,"<<=") == 0 ) {
898      cmpltr = 5;
899    }
900    else if ( strcasecmp(name,"sv") == 0 ) {
901      cmpltr = 6;
902    }
903    else if ( strcasecmp(name,"od") == 0 ) {
904      cmpltr = 7;
905    }
906    else
907      cmpltr = -1;
908    **s = c;
909  }
910  if ( cmpltr >= 0 ) {
911    while ( **s == ' ' || **s == '\t' )
912      *s = *s + 1;
913  }
914
915  return cmpltr;
916}
917
918int pa_parse_neg_cmpsub_cmpltr(s)
919     char **s;
920{
921  int cmpltr;
922  char *name;
923  char c;
924
925  cmpltr = -1;
926  if ( **s == ',' ) {
927    *s+=1;
928    name = *s;
929    while ( **s != ',' && **s != ' ' && **s != '\t' )
930      *s += 1;
931    c = **s;
932    **s = 0x00;
933    if ( strcasecmp(name,"tr") == 0 ) {
934      cmpltr = 0;
935    }
936    else if ( strcmp(name,"<>") == 0 ) {
937      cmpltr = 1;
938    }
939    else if ( strcmp(name,">=") == 0 ) {
940      cmpltr = 2;
941    }
942    else if ( strcmp(name,">") == 0 ) {
943      cmpltr = 3;
944    }
945    else if ( strcmp(name,">>=") == 0 ) {
946      cmpltr = 4;
947    }
948    else if ( strcmp(name,">>") == 0 ) {
949      cmpltr = 5;
950    }
951    else if ( strcasecmp(name,"nsv") == 0 ) {
952      cmpltr = 6;
953    }
954    else if ( strcasecmp(name,"ev") == 0 ) {
955      cmpltr = 7;
956    }
957    **s = c;
958  }
959  if ( cmpltr >= 0 ) {
960    while ( **s == ' ' || **s == '\t' )
961      *s = *s + 1;
962  }
963
964  return cmpltr;
965}
966
967int pa_parse_nonneg_add_cmpltr(s)
968     char **s;
969{
970  int cmpltr;
971  char *name;
972  char c;
973
974  cmpltr = -1;
975  if ( **s == ',' ) {
976    *s+=1;
977    name = *s;
978    while ( **s != ',' && **s != ' ' && **s != '\t' )
979      *s += 1;
980    c = **s;
981    **s = 0x00;
982    if ( strcmp(name,"=") == 0 ) {
983      cmpltr = 1;
984    }
985    else if ( strcmp(name,"<") == 0 ) {
986      cmpltr = 2;
987    }
988    else if ( strcmp(name,"<=") == 0 ) {
989      cmpltr = 3;
990    }
991    else if ( strcasecmp(name,"nuv") == 0 ) {
992      cmpltr = 4;
993    }
994    else if ( strcasecmp(name,"znv") == 0 ) {
995      cmpltr = 5;
996    }
997    else if ( strcasecmp(name,"sv") == 0 ) {
998      cmpltr = 6;
999    }
1000    else if ( strcasecmp(name,"od") == 0 ) {
1001      cmpltr = 7;
1002    }
1003    **s = c;
1004  }
1005  if ( cmpltr >= 0 ) {
1006    while ( **s == ' ' || **s == '\t' )
1007      *s = *s + 1;
1008  }
1009
1010  return cmpltr;
1011}
1012
1013int pa_parse_neg_add_cmpltr(s)
1014     char **s;
1015{
1016  int cmpltr;
1017  char *name;
1018  char c;
1019
1020  cmpltr = -1;
1021  if ( **s == ',' ) {
1022    *s+=1;
1023    name = *s;
1024    while ( **s != ',' && **s != ' ' && **s != '\t' )
1025      *s += 1;
1026    c = **s;
1027    **s = 0x00;
1028    if ( strcasecmp(name,"tr") == 0 ) {
1029      cmpltr = 0;
1030    }
1031    else if ( strcmp(name,"<>") == 0 ) {
1032      cmpltr = 1;
1033    }
1034    else if ( strcmp(name,">=") == 0 ) {
1035      cmpltr = 2;
1036    }
1037    else if ( strcmp(name,">") == 0 ) {
1038      cmpltr = 3;
1039    }
1040    else if ( strcmp(name,"uv") == 0 ) {
1041      cmpltr = 4;
1042    }
1043    else if ( strcmp(name,"vnz") == 0 ) {
1044      cmpltr = 5;
1045    }
1046    else if ( strcasecmp(name,"nsv") == 0 ) {
1047      cmpltr = 6;
1048    }
1049    else if ( strcasecmp(name,"ev") == 0 ) {
1050      cmpltr = 7;
1051    }
1052    **s = c;
1053  }
1054  if ( cmpltr >= 0 ) {
1055    while ( **s == ' ' || **s == '\t' )
1056      *s = *s + 1;
1057  }
1058
1059  return cmpltr;
1060}
1061
1062#if 0
1063static int
1064is_same_frag(frag1P,frag2P)
1065     fragS *frag1P;
1066     fragS *frag2P;
1067{
1068
1069  if ( frag1P == NULL )
1070    return (FALSE);
1071  else if ( frag2P == NULL )
1072    return (FALSE);
1073  else if ( frag1P == frag2P )
1074    return (TRUE);
1075  else if ( frag2P->fr_type == rs_fill && frag2P->fr_fix == 0 )
1076    return is_same_frag(frag1P,frag2P->fr_next);
1077  else if ( frag2P->fr_type == rs_align )
1078    return is_same_frag(frag1P,frag2P->fr_next);
1079  else
1080    return (FALSE);
1081}
1082#endif
1083
1084/* end hppa-aux.c */
1085