xref: /original-bsd/contrib/gas-1.38/read.c (revision 3b6250d9)
1 /*-
2  * This code is derived from software copyrighted by the Free Software
3  * Foundation.
4  *
5  * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)read.c	6.4 (Berkeley) 05/08/91";
10 #endif /* not lint */
11 
12 /* read.c - read a source file -
13    Copyright (C) 1986,1987 Free Software Foundation, Inc.
14 
15 This file is part of GAS, the GNU Assembler.
16 
17 GAS is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 1, or (at your option)
20 any later version.
21 
22 GAS is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 GNU General Public License for more details.
26 
27 You should have received a copy of the GNU General Public License
28 along with GAS; see the file COPYING.  If not, write to
29 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
30 
31 #define MASK_CHAR (0xFF)	/* If your chars aren't 8 bits, you will
32 				   change this a bit.  But then, GNU isn't
33 				   spozed to run on your machine anyway.
34 				   (RMS is so shortsighted sometimes.)
35 				 */
36 
37 #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
38 				/* This is the largest known floating point */
39 				/* format (for now). It will grow when we */
40 				/* do 4361 style flonums. */
41 
42 
43 /* Routines that read assembler source text to build spagetti in memory. */
44 /* Another group of these functions is in the as-expr.c module */
45 
46 #include <ctype.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include "as.h"
50 #include "read.h"
51 #include "md.h"
52 #include "hash.h"
53 #include "obstack.h"
54 #include "frags.h"
55 #include "flonum.h"
56 #include "struc-symbol.h"
57 #include "expr.h"
58 #include "symbols.h"
59 
60 #ifdef SPARC
61 #include "sparc.h"
62 #define OTHER_ALIGN
63 #endif
64 #ifdef I860
65 #include "i860.h"
66 #endif
67 
68 char *	input_line_pointer;	/* -> next char of source file to parse. */
69 
70 
71 #if BITS_PER_CHAR != 8
72 The following table is indexed by [ (char) ] and will break if
73 a char does not have exactly 256 states (hopefully 0:255!) !
74 #endif
75 
76 const char				/* used by is_... macros. our ctype[] */
77 lex_type [256] = {
78   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* @ABCDEFGHIJKLMNO */
79   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* PQRSTUVWXYZ[\]^_ */
80   0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,       /* _!"#$%&'()*+,-./ */
81   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,       /* 0123456789:;<=>? */
82   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* @ABCDEFGHIJKLMNO */
83   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3,       /* PQRSTUVWXYZ[\]^_ */
84   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* `abcdefghijklmno */
85   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,       /* pqrstuvwxyz{|}~. */
86   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
93 };
94 
95 
96 /*
97  * In: a character.
98  * Out: TRUE if this character ends a line.
99  */
100 #define _ (0)
101 const char is_end_of_line [256] = {
102  _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
103  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
104  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
105  _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
106  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
107  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
108  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
109  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
110  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
111  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
112  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
113  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
114  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _  /*                  */
115 };
116 #undef _
117 
118 				/* Functions private to this file. */
119 void			equals();
120 void			big_cons();
121 void			cons();
122 static char*		demand_copy_C_string();
123 static char*		demand_copy_string();
124 void			demand_empty_rest_of_line();
125 void			float_cons();
126 long int		get_absolute_expression();
127 static char		get_absolute_expression_and_terminator();
128 static segT		get_known_segmented_expression();
129 void			ignore_rest_of_line();
130 static int		is_it_end_of_statement();
131 static void		pobegin();
132 static void		pseudo_set();
133 static void		stab();
134 static void		stringer();
135 
136 extern char line_comment_chars[];
137 
138 static char *	buffer_limit;	/* -> 1 + last char in buffer. */
139 
140 static char *	bignum_low;	/* Lowest char of bignum. */
141 static char *	bignum_limit;	/* 1st illegal address of bignum. */
142 static char *	bignum_high;	/* Highest char of bignum. */
143 				/* May point to (bignum_start-1). */
144 				/* Never >= bignum_limit. */
145 static char *old_buffer = 0;	/* JF a hack */
146 static char *old_input;
147 static char *old_limit;
148 
149 #ifndef WORKING_DOT_WORD
150 struct broken_word *broken_words;
151 int new_broken_words = 0;
152 #endif
153 
154 static void grow_bignum ();
155 static int next_char_of_string ();
156 
157 void
158 read_begin()
159 {
160   pobegin();
161   obstack_begin( &notes, 5000 );
162 #define BIGNUM_BEGIN_SIZE (16)
163   bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
164   bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
165 }
166 
167 /* set up pseudo-op tables */
168 
169 static struct hash_control *
170 po_hash = NULL;			/* use before set up: NULL-> address error */
171 
172 
173 void	s_abort(),	s_align(),	s_comm(),	s_data();
174 void	s_desc(),	s_even(),	s_file(),	s_fill();
175 void	s_globl(),	s_lcomm(),	s_line(),	s_lsym();
176 void	s_org(),	s_set(),	s_space(),	s_text();
177 #ifdef VMS
178 char const_flag = 0;
179 void s_const();
180 #endif
181 
182 #ifdef DONTDEF
183 void	s_gdbline(),	s_gdblinetab();
184 void	s_gdbbeg(),	s_gdbblock(),	s_gdbend(),	s_gdbsym();
185 #endif
186 
187 void	stringer();
188 void	cons();
189 void	float_cons();
190 void	big_cons();
191 void	stab();
192 
193 static const pseudo_typeS
194 potable[] =
195 {
196   { "abort",	s_abort,	0	},
197   { "align",	s_align,	0	},
198   { "ascii",	stringer,	0	},
199   { "asciz",	stringer,	1	},
200   { "byte",	cons,		1	},
201   { "comm",	s_comm,		0	},
202 #ifdef VMS
203   { "const",	s_const,	0	},
204 #endif
205   { "data",	s_data,		0	},
206   { "desc",	s_desc,		0	},
207   { "double",	float_cons,	'd'	},
208   { "file",	s_file,		0	},
209   { "fill",	s_fill,		0	},
210   { "float",	float_cons,	'f'	},
211 #ifdef DONTDEF
212   { "gdbbeg",	s_gdbbeg,	0	},
213   { "gdbblock",	s_gdbblock,	0	},
214   { "gdbend",	s_gdbend,	0	},
215   { "gdbsym",	s_gdbsym,	0	},
216   { "gdbline",	s_gdbline,	0	},
217   { "gdblinetab",s_gdblinetab,	0	},
218 #endif
219   { "globl",	s_globl,	0	},
220   { "int",	cons,		4	},
221   { "lcomm",	s_lcomm,	0	},
222   { "line",	s_line,		0	},
223   { "long",	cons,		4	},
224   { "lsym",	s_lsym,		0	},
225   { "octa",	big_cons,	16	},
226   { "org",	s_org,		0	},
227   { "quad",	big_cons,	8	},
228   { "set",	s_set,		0	},
229   { "short",	cons,		2	},
230   { "single",	float_cons,	'f'	},
231   { "space",	s_space,	0	},
232   { "stabd",	stab,		'd'	},
233   { "stabn",	stab,		'n'	},
234   { "stabs",	stab,		's'	},
235   { "text",	s_text,		0	},
236 #ifndef SPARC
237   { "word",	cons,		2	},
238 #endif
239   { NULL}	/* end sentinel */
240 };
241 
242 static void
243 pobegin()
244 {
245   char *	errtxt;		/* error text */
246   const pseudo_typeS * pop;
247 
248   po_hash = hash_new();
249   errtxt = "";			/* OK so far */
250   for (pop=potable; pop->poc_name && !*errtxt; pop++)
251     {
252       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
253     }
254 
255   for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++)
256       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
257 
258   if (*errtxt)
259     {
260       as_fatal ("error constructing pseudo-op table");
261     }
262 }				/* pobegin() */
263 
264 /*			read_a_source_file()
265  *
266  * File has already been opened, and will be closed by our caller.
267  *
268  * We read the file, putting things into a web that
269  * represents what we have been reading.
270  */
271 void
272 read_a_source_file (buffer)
273      char *	buffer;		/* 1st character of each buffer of lines is here. */
274 {
275   register char		c;
276   register char *	s;	/* string of symbol, '\0' appended */
277   register int		temp;
278   /* register struct frag * fragP; JF unused */	/* a frag we just made */
279   pseudo_typeS	*pop;
280 #ifdef DONTDEF
281   void gdb_block_beg();
282   void gdb_block_position();
283   void gdb_block_end();
284   void gdb_symbols_fixup();
285 #endif
286 
287   subseg_new (SEG_TEXT, 0);
288   while ( buffer_limit = input_scrub_next_buffer (&buffer) )
289     {				/* We have another line to parse. */
290       know( buffer_limit [-1] == '\n' ); /* Must have a sentinel. */
291       input_line_pointer = buffer;
292  contin:	/* JF this goto is my fault I admit it.  Someone brave please re-write
293 		   the whole input section here?  Pleeze??? */
294       while ( input_line_pointer < buffer_limit )
295 	{			/* We have more of this buffer to parse. */
296 	  /*
297 	   * We now have input_line_pointer -> 1st char of next line.
298 	   * If input_line_pointer [-1] == '\n' then we just
299 	   * scanned another line: so bump line counters.
300 	   */
301 	  if (input_line_pointer [-1] == '\n')
302 	    {
303 	      bump_line_counters ();
304 	    }
305 	  /*
306 	   * We are at the begining of a line, or similar place.
307 	   * We expect a well-formed assembler statement.
308 	   * A "symbol-name:" is a statement.
309 	   *
310 	   * Depending on what compiler is used, the order of these tests
311 	   * may vary to catch most common case 1st.
312 	   * Each test is independent of all other tests at the (top) level.
313 	   * PLEASE make a compiler that doesn't use this assembler.
314 	   * It is crufty to waste a compiler's time encoding things for this
315 	   * assembler, which then wastes more time decoding it.
316 	   * (And communicating via (linear) files is silly!
317 	   * If you must pass stuff, please pass a tree!)
318 	   */
319 	  if ( (c= * input_line_pointer ++) == '\t' || c == ' ' || c=='\f')
320 	    {
321 	      c = * input_line_pointer ++;
322 	    }
323 	  know( c != ' ' );	/* No further leading whitespace. */
324 	  /*
325 	   * C is the 1st significant character.
326 	   * Input_line_pointer points after that character.
327 	   */
328 	  if ( is_name_beginner(c) )
329 	    {			/* want user-defined label or pseudo/opcode */
330 	      s = -- input_line_pointer;
331 	      c = get_symbol_end(); /* name's delimiter */
332 	      /*
333 	       * C is character after symbol.
334 	       * That character's place in the input line is now '\0'.
335 	       * S points to the beginning of the symbol.
336 	       *   [In case of pseudo-op, s -> '.'.]
337 	       * Input_line_pointer -> '\0' where c was.
338 	       */
339 	      if ( c == ':' )
340 		{
341 		  if (flagseen['g'])
342 		    /* set line number for function definition */
343 		    funcstab(s);
344 		  colon(s);	/* user-defined label */
345 		  * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */
346 				/* Input_line_pointer -> after ':'. */
347 		  SKIP_WHITESPACE();
348 		}
349 	      else if(c=='=' || input_line_pointer[1]=='=')		/* JF deal with FOO=BAR */
350 	        {
351 		  equals(s);
352 		  demand_empty_rest_of_line();
353 		}
354 	      else
355 		{		/* expect pseudo-op or machine instruction */
356 		  if ( *s=='.' )
357 		    {
358 		      /*
359 		       * PSEUDO - OP.
360 		       *
361 		       * WARNING: c has next char, which may be end-of-line.
362 		       * We lookup the pseudo-op table with s+1 because we
363 		       * already know that the pseudo-op begins with a '.'.
364 		       */
365 
366 		      pop= (pseudo_typeS *) hash_find (po_hash, s+1);
367 
368 		      /* Print the error msg now, while we still can */
369 		      if(!pop)
370 			  as_bad("Unknown pseudo-op:  '%s'",s);
371 
372 				/* Put it back for error messages etc. */
373 		      * input_line_pointer = c;
374 				/* The following skip of whitespace is compulsory. */
375 				/* A well shaped space is sometimes all that seperates keyword from operands. */
376 		      if ( c == ' ' || c == '\t' )
377 			{	/* Skip seperator after keyword. */
378 			  input_line_pointer ++;
379 			}
380 		      /*
381 		       * Input_line is restored.
382 		       * Input_line_pointer -> 1st non-blank char
383 		       * after pseudo-operation.
384 		       */
385 		        if(!pop) {
386 			  ignore_rest_of_line();
387 			  break;
388 			}
389 			else
390 			  (*pop->poc_handler)(pop->poc_val);
391 		    }
392 		  else
393 		    {		/* machine instruction */
394 		      /* If source file debugging, emit a stab. */
395 		      if (flagseen['g'])
396 			linestab();
397 
398 		      /* WARNING: c has char, which may be end-of-line. */
399 		      /* Also: input_line_pointer -> `\0` where c was. */
400 		      * input_line_pointer = c;
401 		      while ( ! is_end_of_line [* input_line_pointer] )
402 			{
403 			  input_line_pointer ++;
404 			}
405 		      c = * input_line_pointer;
406 		      * input_line_pointer = '\0';
407 		      md_assemble (s);	/* Assemble 1 instruction. */
408 		      * input_line_pointer ++ = c;
409 		      /* We resume loop AFTER the end-of-line from this instruction */
410 		    }		/* if (*s=='.') */
411 		}		/* if c==':' */
412 	      continue;
413 	    }			/* if (is_name_beginner(c) */
414 
415 
416 	  if ( is_end_of_line [c] )
417 	    {			/* empty statement */
418 	      continue;
419 	    }
420 
421 	  if ( isdigit(c) )
422 	    {			/* local label  ("4:") */
423 	      temp = c - '0';
424 #ifdef SUN_ASM_SYNTAX
425 	      if( *input_line_pointer=='$')
426 		input_line_pointer++;
427 #endif
428 	      if ( * input_line_pointer ++ == ':' )
429 		{
430 		  local_colon (temp);
431 		}
432 	      else
433 		{
434 		  as_bad( "Spurious digit %d.", temp);
435 		  input_line_pointer -- ;
436 		  ignore_rest_of_line();
437 		}
438 	      continue;
439 	    }
440 	  if(c && index(line_comment_chars,c)) {	/* Its a comment.  Better say APP or NO_APP */
441 		char *ends;
442 		char *strstr();
443 		char	*new_buf;
444 		char	*new_tmp;
445 		int	new_length;
446 		char	*tmp_buf = 0;
447 		extern char *scrub_string,*scrub_last_string;
448 		int	scrub_from_string();
449 		void	scrub_to_string();
450 
451 		bump_line_counters();
452 		s=input_line_pointer;
453 		if(strncmp(s,"APP\n",4))
454 			continue;	/* We ignore it */
455 		s+=4;
456 
457 		ends=strstr(s,"#NO_APP\n");
458 
459 		if(!ends) {
460 			int	tmp_len;
461 			int	num;
462 
463 			/* The end of the #APP wasn't in this buffer.  We
464 			   keep reading in buffers until we find the #NO_APP
465 			   that goes with this #APP  There is one.  The specs
466  			   guarentee it. . .*/
467 			tmp_len=buffer_limit-s;
468 			tmp_buf=xmalloc(tmp_len);
469 			bcopy(s,tmp_buf,tmp_len);
470 			do {
471 				new_tmp = input_scrub_next_buffer(&buffer);
472 				if(!new_tmp)
473 					break;
474 				else
475 					buffer_limit = new_tmp;
476 				input_line_pointer = buffer;
477 				ends = strstr(buffer,"#NO_APP\n");
478 				if(ends)
479 					num=ends-buffer;
480 				else
481 					num=buffer_limit-buffer;
482 
483 				tmp_buf=xrealloc(tmp_buf,tmp_len+num);
484 				bcopy(buffer,tmp_buf+tmp_len,num);
485 				tmp_len+=num;
486 			} while(!ends);
487 
488 			input_line_pointer= ends ? ends+8 : NULL;
489 
490 			s=tmp_buf;
491 			ends=s+tmp_len;
492 
493 		} else {
494 			input_line_pointer=ends+8;
495 		}
496 		new_buf=xmalloc(100);
497 		new_length=100;
498 		new_tmp=new_buf;
499 
500 		scrub_string=s;
501 		scrub_last_string = ends;
502 		for(;;) {
503 			int ch;
504 
505 			ch=do_scrub_next_char(scrub_from_string,scrub_to_string);
506 			if(ch==EOF) break;
507 			*new_tmp++=ch;
508 			if(new_tmp==new_buf+new_length) {
509 				new_buf=xrealloc(new_buf,new_length+100);
510 				new_tmp=new_buf+new_length;
511 				new_length+=100;
512 			}
513 		}
514 
515 		if(tmp_buf)
516 			free(tmp_buf);
517 		old_buffer=buffer;
518 		old_input=input_line_pointer;
519 		old_limit=buffer_limit;
520 		buffer=new_buf;
521 		input_line_pointer=new_buf;
522 		buffer_limit=new_tmp;
523 		continue;
524 	  }
525 
526 	  as_bad("Junk character %d.",c);
527 	  ignore_rest_of_line();
528 	}			/* while (input_line_pointer<buffer_limit )*/
529 	if(old_buffer) {
530 		bump_line_counters();
531 		if(old_input == 0)
532 			return;
533 		buffer=old_buffer;
534 		input_line_pointer=old_input;
535 		buffer_limit=old_limit;
536 		old_buffer = 0;
537 		goto contin;
538 	}
539     }				/* while (more bufrers to scan) */
540 }				/* read_a_source_file() */
541 
542 void
543 s_abort()
544 {
545 	as_fatal(".abort detected.  Abandoning ship.");
546 }
547 
548 #ifdef OTHER_ALIGN
549 static void
550 s_align()
551 {
552     register unsigned int temp;
553     register long int temp_fill;
554     unsigned int i;
555 
556     temp = get_absolute_expression ();
557 #define MAX_ALIGNMENT (1 << 15)
558     if ( temp > MAX_ALIGNMENT ) {
559 	as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
560     }
561 
562     /*
563      * For the sparc, `.align (1<<n)' actually means `.align n'
564      * so we have to convert it.
565      */
566     if (temp != 0) {
567 	for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
568 	    ;
569     }
570     if (temp != 1)
571 	as_bad("Alignment not a power of 2");
572 
573     temp = i;
574     if (*input_line_pointer == ',') {
575 	input_line_pointer ++;
576 	temp_fill = get_absolute_expression ();
577     } else {
578 	temp_fill = 0;
579     }
580     /* Only make a frag if we HAVE to. . . */
581     if (temp && ! need_pass_2)
582 	frag_align (temp, (int)temp_fill);
583 
584     demand_empty_rest_of_line();
585 }
586 #else
587 
588 void
589 s_align()
590 {
591 	register int temp;
592 	register long int temp_fill;
593 
594 	temp = get_absolute_expression ();
595 #define MAX_ALIGNMENT (15)
596 	if ( temp > MAX_ALIGNMENT )
597 		as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
598 	else if ( temp < 0 ) {
599 		as_bad("Alignment negative. 0 assumed.");
600 		temp = 0;
601 	}
602 	if ( *input_line_pointer == ',' ) {
603 		input_line_pointer ++;
604 		temp_fill = get_absolute_expression ();
605 	} else
606 		temp_fill = 0;
607 	/* Only make a frag if we HAVE to. . . */
608 	if ( temp && ! need_pass_2 )
609 		frag_align (temp, (int)temp_fill);
610 	demand_empty_rest_of_line();
611 }
612 #endif
613 
614 void
615 s_comm()
616 {
617 	register char *name;
618 	register char c;
619 	register char *p;
620 	register int temp;
621 	register symbolS *	symbolP;
622 
623 	name = input_line_pointer;
624 	c = get_symbol_end();
625 	/* just after name is now '\0' */
626 	p = input_line_pointer;
627 	*p = c;
628 	SKIP_WHITESPACE();
629 	if ( * input_line_pointer != ',' ) {
630 		as_bad("Expected comma after symbol-name");
631 		ignore_rest_of_line();
632 		return;
633 	}
634 	input_line_pointer ++; /* skip ',' */
635 	if ( (temp = get_absolute_expression ()) < 0 ) {
636 		as_warn(".COMMon length (%d.) <0! Ignored.", temp);
637 		ignore_rest_of_line();
638 		return;
639 	}
640 	*p = 0;
641 	symbolP = symbol_find_or_make (name);
642 	*p = c;
643 	if (   (symbolP -> sy_type & N_TYPE) != N_UNDF ||
644  symbolP -> sy_other != 0 || symbolP -> sy_desc != 0) {
645 		as_warn( "Ignoring attempt to re-define symbol");
646 		ignore_rest_of_line();
647 		return;
648 	}
649 	if (symbolP -> sy_value) {
650 		if (symbolP -> sy_value != temp)
651 			as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
652  symbolP -> sy_name, symbolP -> sy_value, temp);
653 	} else {
654 		symbolP -> sy_value = temp;
655 		symbolP -> sy_type |= N_EXT;
656 	}
657 #ifdef VMS
658 	if(!temp)
659 		symbolP->sy_other = const_flag;
660 #endif
661 	know( symbolP -> sy_frag == &zero_address_frag );
662 	demand_empty_rest_of_line();
663 }
664 
665 #ifdef VMS
666 void
667 s_const()
668 {
669 	register int temp;
670 
671 	temp = get_absolute_expression ();
672 	subseg_new (SEG_DATA, (subsegT)temp);
673 	const_flag = 1;
674 	demand_empty_rest_of_line();
675 }
676 #endif
677 
678 void
679 s_data()
680 {
681 	register int temp;
682 
683 	temp = get_absolute_expression ();
684 	subseg_new (SEG_DATA, (subsegT)temp);
685 #ifdef VMS
686 	const_flag = 0;
687 #endif
688 	demand_empty_rest_of_line();
689 }
690 
691 void
692 s_desc()
693 {
694 	register char *name;
695 	register char c;
696 	register char *p;
697 	register symbolS *	symbolP;
698 	register int temp;
699 
700 	/*
701 	 * Frob invented at RMS' request. Set the n_desc of a symbol.
702 	 */
703 	name = input_line_pointer;
704 	c = get_symbol_end();
705 	p = input_line_pointer;
706 	symbolP = symbol_table_lookup (name);
707 	* p = c;
708 	SKIP_WHITESPACE();
709 	if ( * input_line_pointer != ',' ) {
710 		*p = 0;
711 		as_bad("Expected comma after name \"%s\"", name);
712 		*p = c;
713 		ignore_rest_of_line();
714 	} else {
715 		input_line_pointer ++;
716 		temp = get_absolute_expression ();
717 		*p = 0;
718 		symbolP = symbol_find_or_make (name);
719 		*p = c;
720 		symbolP -> sy_desc = temp;
721 	}
722 	demand_empty_rest_of_line();
723 }
724 
725 void
726 s_file()
727 {
728 	register char *s;
729 	int	length;
730 
731 	/* Some assemblers tolerate immediately following '"' */
732 	if ( s = demand_copy_string( & length ) ) {
733 		new_logical_line (s, -1);
734 		demand_empty_rest_of_line();
735 	}
736 }
737 
738 void
739 s_fill()
740 {
741 	long int temp_repeat;
742 	long int temp_size;
743 	register long int temp_fill;
744 	char	*p;
745 
746 	if ( get_absolute_expression_and_terminator(& temp_repeat) != ',' ) {
747 		input_line_pointer --; /* Backup over what was not a ','. */
748 		as_warn("Expect comma after rep-size in .fill");
749 		ignore_rest_of_line();
750 		return;
751 	}
752 	if ( get_absolute_expression_and_terminator( & temp_size) != ',' ) {
753 		  input_line_pointer --; /* Backup over what was not a ','. */
754 		  as_warn("Expected comma after size in .fill");
755 		  ignore_rest_of_line();
756 		  return;
757 	}
758 	/*
759 	 * This is to be compatible with BSD 4.2 AS, not for any rational reason.
760 	 */
761 #define BSD_FILL_SIZE_CROCK_8 (8)
762 	if ( temp_size > BSD_FILL_SIZE_CROCK_8 ) {
763 		as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
764 		temp_size = BSD_FILL_SIZE_CROCK_8 ;
765 	} if ( temp_size < 0 ) {
766 		as_warn("Size negative: .fill ignored.");
767 		temp_size = 0;
768 	} else if ( temp_repeat <= 0 ) {
769 		as_warn("Repeat < 0, .fill ignored");
770 		temp_size = 0;
771 	}
772 	temp_fill = get_absolute_expression ();
773 	if ( temp_size && !need_pass_2 ) {
774 		p = frag_var (rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
775 		bzero (p, (int)temp_size);
776 /*
777  * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
778  * The following bizzare behaviour is to be compatible with above.
779  * I guess they tried to take up to 8 bytes from a 4-byte expression
780  * and they forgot to sign extend. Un*x Sux.
781  */
782 #define BSD_FILL_SIZE_CROCK_4 (4)
783 		md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
784 /*
785  * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
786  * but emits no error message because it seems a legal thing to do.
787  * It is a degenerate case of .fill but could be emitted by a compiler.
788  */
789 	}
790 	demand_empty_rest_of_line();
791 }
792 
793 #ifdef DONTDEF
794 void
795 s_gdbbeg()
796 {
797 	register int temp;
798 
799 	temp = get_absolute_expression ();
800 	if (temp < 0)
801 		as_warn( "Block number <0. Ignored." );
802 	else if (flagseen ['G'])
803 		gdb_block_beg ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
804 	demand_empty_rest_of_line ();
805 }
806 
807 void
808 s_gdbblock()
809 {
810 	register int	position;
811 	int	temp;
812 
813 	if (get_absolute_expression_and_terminator (&temp) != ',') {
814 		as_warn( "expected comma before position in .gdbblock");
815 		--input_line_pointer;
816 		ignore_rest_of_line ();
817 		return;
818 	}
819 	position = get_absolute_expression ();
820 	if (flagseen ['G'])
821 		gdb_block_position ((long int) temp, (long int) position);
822 	demand_empty_rest_of_line ();
823 }
824 
825 void
826 s_gdbend()
827 {
828 	register int temp;
829 
830 	temp = get_absolute_expression ();
831 	if (temp < 0)
832 		as_warn( "Block number <0. Ignored." );
833 	else if (flagseen ['G'])
834 		gdb_block_end ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
835 	demand_empty_rest_of_line ();
836 }
837 
838 void
839 s_gdbsym()
840 {
841 	register char *name,
842 			*p;
843 	register char c;
844 	register symbolS *	symbolP;
845 	register int temp;
846 
847 	name = input_line_pointer;
848 	c = get_symbol_end();
849 	p = input_line_pointer;
850 	symbolP = symbol_find_or_make (name);
851 	*p = c;
852 	SKIP_WHITESPACE();
853 	if ( * input_line_pointer != ',' ) {
854 		as_warn("Expected comma after name");
855 		ignore_rest_of_line();
856 		return;
857 	}
858 	input_line_pointer ++;
859 	if ( (temp = get_absolute_expression ()) < 0 ) {
860 		as_warn("Bad GDB symbol file offset (%d.) <0! Ignored.", temp);
861 		ignore_rest_of_line();
862 		return;
863 	}
864 	if (flagseen ['G'])
865 		gdb_symbols_fixup (symbolP, (long int)temp);
866 	demand_empty_rest_of_line ();
867 }
868 
869 void
870 s_gdbline()
871 {
872 	int	file_number,
873 		lineno;
874 
875 	if(get_absolute_expression_and_terminator(&file_number) != ',') {
876 		as_warn("expected comman after filenum in .gdbline");
877 		ignore_rest_of_line();
878 		return;
879 	}
880 	lineno=get_absolute_expression();
881 	if(flagseen['G'])
882 		gdb_line(file_number,lineno);
883 	demand_empty_rest_of_line();
884 }
885 
886 
887 void
888 s_gdblinetab()
889 {
890 	int	file_number,
891 		offset;
892 
893 	if(get_absolute_expression_and_terminator(&file_number) != ',') {
894 		as_warn("expected comman after filenum in .gdblinetab");
895 		ignore_rest_of_line();
896 		return;
897 	}
898 	offset=get_absolute_expression();
899 	if(flagseen['G'])
900 		gdb_line_tab(file_number,offset);
901 	demand_empty_rest_of_line();
902 }
903 #endif
904 
905 void
906 s_globl()
907 {
908 	register char *name;
909 	register int c;
910 	register symbolS *	symbolP;
911 
912 	do {
913 		name = input_line_pointer;
914 		c = get_symbol_end();
915 		symbolP = symbol_find_or_make (name);
916 		* input_line_pointer = c;
917 		SKIP_WHITESPACE();
918 		symbolP -> sy_type |= N_EXT;
919 		if(c==',') {
920 			input_line_pointer++;
921 			SKIP_WHITESPACE();
922 			if(*input_line_pointer=='\n')
923 				c='\n';
924 		}
925 	} while(c==',');
926 	demand_empty_rest_of_line();
927 }
928 
929 void
930 s_lcomm()
931 {
932 	register char *name;
933 	register char c;
934 	register char *p;
935 	register int temp;
936 	register symbolS *	symbolP;
937 
938 	name = input_line_pointer;
939 	c = get_symbol_end();
940 	p = input_line_pointer;
941 	*p = c;
942 	SKIP_WHITESPACE();
943 	if ( * input_line_pointer != ',' ) {
944 		as_warn("Expected comma after name");
945 		ignore_rest_of_line();
946 		return;
947 	}
948 	input_line_pointer ++;
949 	if ( (temp = get_absolute_expression ()) < 0 ) {
950 		as_warn("BSS length (%d.) <0! Ignored.", temp);
951 		ignore_rest_of_line();
952 		return;
953 	}
954 	*p = 0;
955 	symbolP = symbol_find_or_make (name);
956 	*p = c;
957 	if (   symbolP -> sy_other == 0
958 	    && symbolP -> sy_desc  == 0
959 	    && (   (   symbolP -> sy_type  == N_BSS
960 	    && symbolP -> sy_value == local_bss_counter)
961 	    || (   (symbolP -> sy_type & N_TYPE) == N_UNDF
962 	    && symbolP -> sy_value == 0))) {
963 		symbolP -> sy_value = local_bss_counter;
964 		symbolP -> sy_type  = N_BSS;
965 		symbolP -> sy_frag  = & bss_address_frag;
966 		local_bss_counter += temp;
967 	} else
968 		as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
969  symbolP -> sy_value, local_bss_counter );
970 	demand_empty_rest_of_line();
971 }
972 
973 void
974 s_line()
975 {
976 	/* Assume delimiter is part of expression. */
977 	/* BSD4.2 as fails with delightful bug, so we */
978 	/* are not being incompatible here. */
979 	new_logical_line ((char *)NULL, (int)(get_absolute_expression ()));
980 	demand_empty_rest_of_line();
981 }
982 
983 void
984 s_long()
985 {
986 	cons(4);
987 }
988 
989 void
990 s_int()
991 {
992 	cons(4);
993 }
994 
995 void
996 s_lsym()
997 {
998 	register char *name;
999 	register char c;
1000 	register char *p;
1001 	register segT segment;
1002 	expressionS exp;
1003 	register symbolS *symbolP;
1004 
1005 	/* we permit ANY expression: BSD4.2 demands constants */
1006 	name = input_line_pointer;
1007 	c = get_symbol_end();
1008 	p = input_line_pointer;
1009 	*p = c;
1010 	SKIP_WHITESPACE();
1011 	if ( * input_line_pointer != ',' ) {
1012 		*p = 0;
1013 		as_warn("Expected comma after name \"%s\"", name);
1014 		*p = c;
1015 		ignore_rest_of_line();
1016 		return;
1017 	}
1018 	input_line_pointer ++;
1019 	segment = expression (& exp);
1020 	if (   segment != SEG_ABSOLUTE && segment != SEG_DATA &&
1021  segment != SEG_TEXT && segment != SEG_BSS) {
1022 		as_bad("Bad expression: %s", seg_name [(int)segment]);
1023 		ignore_rest_of_line();
1024 		return;
1025 	}
1026  know(   segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS );
1027 	*p = 0;
1028 	symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]),
1029  0, 0, (valueT)(exp . X_add_number), & zero_address_frag);
1030 	*p = c;
1031 	demand_empty_rest_of_line();
1032 }
1033 
1034 void
1035 s_org()
1036 {
1037 	register segT segment;
1038 	expressionS exp;
1039 	register long int temp_fill;
1040 	register char *p;
1041 /*
1042  * Don't believe the documentation of BSD 4.2 AS.
1043  * There is no such thing as a sub-segment-relative origin.
1044  * Any absolute origin is given a warning, then assumed to be segment-relative.
1045  * Any segmented origin expression ("foo+42") had better be in the right
1046  * segment or the .org is ignored.
1047  *
1048  * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
1049  * never know sub-segment sizes when we are reading code.
1050  * BSD will crash trying to emit -ve numbers of filler bytes in certain
1051  * .orgs. We don't crash, but see as-write for that code.
1052  */
1053 /*
1054  * Don't make frag if need_pass_2==TRUE.
1055  */
1056 	segment = get_known_segmented_expression(& exp);
1057 	if ( *input_line_pointer == ',' ) {
1058 		input_line_pointer ++;
1059 		temp_fill = get_absolute_expression ();
1060 	} else
1061 		temp_fill = 0;
1062 	if ( ! need_pass_2 ) {
1063 		if (segment != now_seg && segment != SEG_ABSOLUTE)
1064 			as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
1065  seg_name [(int) segment], seg_name [(int) now_seg]);
1066 		p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
1067  exp . X_add_number, (char *)0);
1068 		* p = temp_fill;
1069 	} /* if (ok to make frag) */
1070 	demand_empty_rest_of_line();
1071 }
1072 
1073 void
1074 s_set()
1075 {
1076 	register char *name;
1077 	register char delim;
1078 	register char *end_name;
1079 	register symbolS *symbolP;
1080 
1081 	/*
1082 	 * Especial apologies for the random logic:
1083 	 * this just grew, and could be parsed much more simply!
1084 	 * Dean in haste.
1085 	 */
1086 	name = input_line_pointer;
1087 	delim = get_symbol_end();
1088 	end_name = input_line_pointer;
1089 	*end_name = delim;
1090 	SKIP_WHITESPACE();
1091 	if ( * input_line_pointer != ',' ) {
1092 		*end_name = 0;
1093 		as_warn("Expected comma after name \"%s\"", name);
1094 		*end_name = delim;
1095 		ignore_rest_of_line();
1096 		return;
1097 	}
1098 	input_line_pointer ++;
1099 	*end_name = 0;
1100 	if(name[0]=='.' && name[1]=='\0') {
1101 	  /* Turn '. = mumble' into a .org mumble */
1102 	  register segT segment;
1103 	  expressionS exp;
1104 	  register char *ptr;
1105 
1106 	  segment = get_known_segmented_expression(& exp);
1107 	  if ( ! need_pass_2 ) {
1108 	    if (segment != now_seg && segment != SEG_ABSOLUTE)
1109 	      as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
1110 		      seg_name [(int) segment], seg_name [(int) now_seg]);
1111 	    ptr = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
1112 			  exp.X_add_number, (char *)0);
1113 	    *ptr= 0;
1114 	  } /* if (ok to make frag) */
1115 	  *end_name = delim;
1116 	  return;
1117 	}
1118 	symbolP = symbol_find_or_make (name);
1119 	*end_name = delim;
1120 	pseudo_set (symbolP);
1121 	demand_empty_rest_of_line ();
1122 }
1123 
1124 void
1125 s_space()
1126 {
1127 	long int temp_repeat;
1128 	register long int temp_fill;
1129 	register char *p;
1130 
1131 	/* Just like .fill, but temp_size = 1 */
1132 	if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) {
1133 		temp_fill = get_absolute_expression ();
1134 	} else {
1135 		input_line_pointer --; /* Backup over what was not a ','. */
1136 		temp_fill = 0;
1137 	}
1138 	if ( temp_repeat <= 0 ) {
1139 		as_warn("Repeat < 0, .space ignored");
1140 		ignore_rest_of_line();
1141 		return;
1142 	}
1143 	if ( ! need_pass_2 ) {
1144 		p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
1145  temp_repeat, (char *)0);
1146 		* p = temp_fill;
1147 	}
1148 	demand_empty_rest_of_line();
1149 }
1150 
1151 void
1152 s_text()
1153 {
1154 	register int temp;
1155 
1156 	temp = get_absolute_expression ();
1157 	subseg_new (SEG_TEXT, (subsegT)temp);
1158 	demand_empty_rest_of_line();
1159 }
1160 
1161 
1162 /*( JF was static, but can't be if machine dependent pseudo-ops are to use it */
1163 
1164 void
1165 demand_empty_rest_of_line()
1166 {
1167   SKIP_WHITESPACE();
1168   if ( is_end_of_line [* input_line_pointer] )
1169     {
1170       input_line_pointer ++;
1171     }
1172   else
1173     {
1174       ignore_rest_of_line();
1175     }
1176 				/* Return having already swallowed end-of-line. */
1177 }				/* Return pointing just after end-of-line. */
1178 
1179 
1180 void
1181 ignore_rest_of_line()		/* For suspect lines: gives warning. */
1182 {
1183   if ( ! is_end_of_line [* input_line_pointer])
1184     {
1185       as_warn("Rest of line ignored. 1st junk character valued %d (%c)."
1186 	      , * input_line_pointer, *input_line_pointer);
1187       while (   input_line_pointer < buffer_limit
1188 	     && ! is_end_of_line [* input_line_pointer] )
1189 	{
1190 	  input_line_pointer ++;
1191 	}
1192     }
1193   input_line_pointer ++;	/* Return pointing just after end-of-line. */
1194   know( is_end_of_line [input_line_pointer [-1]] );
1195 }
1196 
1197 /*
1198  *			stab()
1199  *
1200  * Handle .stabX directives, which used to be open-coded.
1201  * So much creeping featurism overloaded the semantics that we decided
1202  * to put all .stabX thinking in one place. Here.
1203  *
1204  * We try to make any .stabX directive legal. Other people's AS will often
1205  * do assembly-time consistency checks: eg assigning meaning to n_type bits
1206  * and "protecting" you from setting them to certain values. (They also zero
1207  * certain bits before emitting symbols. Tut tut.)
1208  *
1209  * If an expression is not absolute we either gripe or use the relocation
1210  * information. Other people's assemblers silently forget information they
1211  * don't need and invent information they need that you didn't supply.
1212  *
1213  * .stabX directives always make a symbol table entry. It may be junk if
1214  * the rest of your .stabX directive is malformed.
1215  */
1216 static void
1217 stab (what)
1218 int what;
1219 {
1220   register symbolS *	symbolP;
1221   register char *	string;
1222 	   int		saved_type;
1223   	   int		length;
1224   	   int		goof;	/* TRUE if we have aborted. */
1225 	   long int	longint;
1226 
1227 /*
1228  * Enter with input_line_pointer pointing past .stabX and any following
1229  * whitespace.
1230  */
1231 	goof = FALSE; /* JF who forgot this?? */
1232 	if (what == 's') {
1233 		string = demand_copy_C_string (& length);
1234 		SKIP_WHITESPACE();
1235 		if (* input_line_pointer == ',')
1236 			input_line_pointer ++;
1237 		else {
1238 			as_warn( "I need a comma after symbol's name" );
1239 			goof = TRUE;
1240 		}
1241 	} else
1242 		string = "";
1243 
1244 /*
1245  * Input_line_pointer->after ','.  String -> symbol name.
1246  */
1247 	if (! goof) {
1248 		symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0);
1249 		switch (what) {
1250 		case 'd':
1251 			symbolP->sy_name = NULL; /* .stabd feature. */
1252 			symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal;
1253 			symbolP->sy_frag = frag_now;
1254 			break;
1255 
1256 		case 'n':
1257 			symbolP->sy_frag = &zero_address_frag;
1258 			break;
1259 
1260 		case 's':
1261 			symbolP->sy_frag = & zero_address_frag;
1262 			break;
1263 
1264 		default:
1265 			BAD_CASE( what );
1266 			break;
1267 		}
1268 		if (get_absolute_expression_and_terminator (& longint) == ',')
1269 			symbolP->sy_type = saved_type = longint;
1270 		else {
1271 			as_warn( "I want a comma after the n_type expression" );
1272 			goof = TRUE;
1273 			input_line_pointer --; /* Backup over a non-',' char. */
1274 		}
1275 	}
1276 	if (! goof) {
1277 		if (get_absolute_expression_and_terminator (& longint) == ',')
1278 			symbolP->sy_other = longint;
1279 		else {
1280 			as_warn( "I want a comma after the n_other expression" );
1281 			goof = TRUE;
1282 			input_line_pointer --; /* Backup over a non-',' char. */
1283 		}
1284 	}
1285 	if (! goof) {
1286 		symbolP->sy_desc = get_absolute_expression ();
1287 		if (what == 's' || what == 'n') {
1288 			if (* input_line_pointer != ',') {
1289 				as_warn( "I want a comma after the n_desc expression" );
1290 				goof = TRUE;
1291 			} else {
1292 				input_line_pointer ++;
1293 			}
1294 		}
1295 	}
1296 	if ((! goof) && (what=='s' || what=='n')) {
1297 		pseudo_set (symbolP);
1298 		symbolP->sy_type = saved_type;
1299 	}
1300 	if (goof)
1301 		ignore_rest_of_line ();
1302 	else
1303 		demand_empty_rest_of_line ();
1304 }
1305 
1306 /*
1307  *			pseudo_set()
1308  *
1309  * In:	Pointer to a symbol.
1310  *	Input_line_pointer -> expression.
1311  *
1312  * Out:	Input_line_pointer -> just after any whitespace after expression.
1313  *	Tried to set symbol to value of expression.
1314  *	Will change sy_type, sy_value, sy_frag;
1315  *	May set need_pass_2 == TRUE.
1316  */
1317 static void
1318 pseudo_set (symbolP)
1319      symbolS *	symbolP;
1320 {
1321   expressionS	exp;
1322   register segT	segment;
1323   int ext;
1324 
1325   know( symbolP );		/* NULL pointer is logic error. */
1326   ext=(symbolP->sy_type&N_EXT);
1327   if ((segment = expression( & exp )) == SEG_NONE)
1328     {
1329       as_warn( "Missing expression: absolute 0 assumed" );
1330       exp . X_seg		= SEG_ABSOLUTE;
1331       exp . X_add_number	= 0;
1332     }
1333   switch (segment)
1334     {
1335     case SEG_BIG:
1336       as_warn( "%s number illegal. Absolute 0 assumed.",
1337 	      exp . X_add_number > 0 ? "Bignum" : "Floating-Point" );
1338       symbolP -> sy_type = N_ABS | ext;
1339       symbolP -> sy_value = 0;
1340       symbolP -> sy_frag = & zero_address_frag;
1341       break;
1342 
1343     case SEG_NONE:
1344       as_warn("No expression:  Using absolute 0");
1345       symbolP -> sy_type = N_ABS | ext;
1346       symbolP -> sy_value = 0;
1347       symbolP -> sy_frag = & zero_address_frag;
1348       break;
1349 
1350     case SEG_DIFFERENCE:
1351       if (exp.X_add_symbol && exp.X_subtract_symbol
1352           &&    (exp.X_add_symbol->sy_type & N_TYPE)
1353 	     == (exp.X_subtract_symbol->sy_type & N_TYPE)) {
1354 	if(exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) {
1355 	  as_bad("Unknown expression: symbols %s and %s are in different frags.",exp.X_add_symbol->sy_name, exp.X_subtract_symbol->sy_name);
1356 	  need_pass_2++;
1357 	}
1358 	exp.X_add_number+=exp.X_add_symbol->sy_value - exp.X_subtract_symbol->sy_value;
1359       } else
1360 	as_warn( "Complex expression. Absolute segment assumed." );
1361     case SEG_ABSOLUTE:
1362       symbolP -> sy_type = N_ABS | ext;
1363       symbolP -> sy_value = exp . X_add_number;
1364       symbolP -> sy_frag = & zero_address_frag;
1365       break;
1366 
1367     case SEG_DATA:
1368     case SEG_TEXT:
1369     case SEG_BSS:
1370       symbolP -> sy_type = seg_N_TYPE [(int) segment] | ext;
1371       symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value;
1372       symbolP -> sy_frag = exp . X_add_symbol -> sy_frag;
1373       break;
1374 
1375     case SEG_PASS1:		/* Not an error. Just try another pass. */
1376       symbolP->sy_forward=exp.X_add_symbol;
1377       as_warn("Unknown expression");
1378       know( need_pass_2 == TRUE );
1379       break;
1380 
1381     case SEG_UNKNOWN:
1382       symbolP->sy_forward=exp.X_add_symbol;
1383       /* as_warn("unknown symbol"); */
1384       /* need_pass_2 = TRUE; */
1385       break;
1386 
1387     default:
1388       BAD_CASE( segment );
1389       break;
1390     }
1391 }
1392 
1393 /*
1394  * stabs(file), stabf(func) and stabd(line) -- for the purpose of
1395  * source file debugging of assembly files, generate file,
1396  * function and line number stabs, respectively.
1397  * These functions have corresponding functions named
1398  * filestab(), funcstab() and linestab() in input-scrub.c,
1399  * where logical files and logical line numbers are handled.
1400  */
1401 
1402 #include <stab.h>
1403 
1404 stabs(file)
1405      char *file;
1406 {
1407   /* .stabs "file",100,0,0,. */
1408   (void) symbol_new(file,
1409 		    N_SO,
1410 		    0,
1411 		    0,
1412 		    obstack_next_free(& frags) - frag_now->fr_literal,
1413 		    frag_now);
1414 }
1415 
1416 stabf(func)
1417      char *func;
1418 {
1419   symbolS *symbolP;
1420   static int void_undefined = 1;
1421 
1422   /* crudely filter uninteresting labels: require an initial '_' */
1423   if (*func++ != '_')
1424     return;
1425 
1426   /* assembly functions are assumed to have void type */
1427   if (void_undefined)
1428     {
1429       /* .stabs "void:t15=15",128,0,0,0 */
1430       (void) symbol_new("void:t1=1",
1431 			N_LSYM,
1432 			0,
1433 			0,
1434 			0,
1435 			&zero_address_frag);
1436       void_undefined = 0;
1437     }
1438 
1439   /* .stabs "func:F1",36,0,0,. */
1440   symbolP = symbol_new((char *) 0,
1441 		       N_FUN,
1442 		       0,
1443 		       0,
1444 		       obstack_next_free(& frags) - frag_now->fr_literal,
1445 		       frag_now);
1446   obstack_grow(&notes, func, strlen(func));
1447   obstack_1grow(&notes, ':');
1448   obstack_1grow(&notes, 'F');
1449   obstack_1grow(&notes, '1');
1450   obstack_1grow(&notes, '\0');
1451   symbolP->sy_name = obstack_finish(&notes);
1452 }
1453 
1454 stabd(line)
1455      unsigned line;
1456 {
1457   /* .stabd 68,0,line */
1458   (void) symbol_new((char *)0,
1459 		    N_SLINE,
1460 		    0,
1461 		    line,
1462 		    obstack_next_free(& frags) - frag_now->fr_literal,
1463 		    frag_now);
1464 }
1465 
1466 /*
1467  *			cons()
1468  *
1469  * CONStruct more frag of .bytes, or .words etc.
1470  * Should need_pass_2 be TRUE then emit no frag(s).
1471  * This understands EXPRESSIONS, as opposed to big_cons().
1472  *
1473  * Bug (?)
1474  *
1475  * This has a split personality. We use expression() to read the
1476  * value. We can detect if the value won't fit in a byte or word.
1477  * But we can't detect if expression() discarded significant digits
1478  * in the case of a long. Not worth the crocks required to fix it.
1479  */
1480 void
1481 cons(nbytes)			/* worker to do .byte etc statements */
1482 				/* clobbers input_line_pointer, checks */
1483 				/* end-of-line. */
1484      register int	nbytes;	/* 1=.byte, 2=.word, 4=.long */
1485 {
1486   register char		c;
1487   register long int	mask;	/* High-order bits we will left-truncate, */
1488 				/* but includes sign bit also. */
1489   register long int     get;	/* what we get */
1490   register long int	use;	/* get after truncation. */
1491   register long int	unmask;	/* what bits we will store */
1492   register char *	p;
1493   register segT		segment;
1494            expressionS	exp;
1495 #ifdef NS32K
1496   void fix_new_ns32k();
1497 #else
1498   void	fix_new();
1499 #endif
1500 
1501   /*
1502    * Input_line_pointer -> 1st char after pseudo-op-code and could legally
1503    * be a end-of-line. (Or, less legally an eof - which we cope with.)
1504    */
1505   /* JF << of >= number of bits in the object is undefined.  In particular
1506      SPARC (Sun 4) has problems */
1507   if(nbytes>=sizeof(long int))
1508     mask = 0;
1509   else
1510     mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
1511   unmask = ~ mask;		/* Do store these bits. */
1512 #ifdef NEVER
1513   "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
1514   mask = ~ (unmask >> 1);	/* Includes sign bit now. */
1515 #endif
1516   /*
1517    * The following awkward logic is to parse ZERO or more expressions,
1518    * comma seperated. Recall an expression includes its leading &
1519    * trailing blanks. We fake a leading ',' if there is (supposed to
1520    * be) a 1st expression, and keep demanding 1 expression for each ','.
1521    */
1522   if (is_it_end_of_statement())
1523     {
1524       c = 0;			/* Skip loop. */
1525       input_line_pointer ++;	/* Matches end-of-loop 'correction'. */
1526     }
1527   else
1528       c = ',';			/* Do loop. */
1529   while ( c == ','  )
1530     {
1531       segment = expression( &exp ); /* At least scan over the expression. */
1532       if ( ! need_pass_2 )
1533 	{			/* Still worthwhile making frags. */
1534 
1535 	  /* Don't call this if we are going to junk this pass anyway! */
1536 	  know( segment != SEG_PASS1 );
1537 
1538 	  if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL )
1539 	    {
1540 	      as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
1541 		      exp . X_subtract_symbol -> sy_name,
1542 		      seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]);
1543 	      segment = SEG_ABSOLUTE;
1544 	      /* Leave exp . X_add_number alone. */
1545 	    }
1546 	  p = frag_more (nbytes);
1547 	  switch (segment)
1548 	    {
1549 	    case SEG_BIG:
1550 	      as_warn( "%s number illegal. Absolute 0 assumed.",
1551 		      exp . X_add_number > 0 ? "Bignum" : "Floating-Point");
1552 	      md_number_to_chars (p, (long)0, nbytes);
1553 	      break;
1554 
1555 	    case SEG_NONE:
1556 	      as_warn( "0 assumed for missing expression" );
1557 	      exp . X_add_number = 0;
1558 	      know( exp . X_add_symbol == NULL );
1559 	      /* fall into SEG_ABSOLUTE */
1560 	    case SEG_ABSOLUTE:
1561 	      get = exp . X_add_number;
1562 	      use = get & unmask;
1563 	      if ( (get & mask) && (get & mask) != mask )
1564 		{		/* Leading bits contain both 0s & 1s. */
1565 		  as_warn("Value x%x truncated to x%x.", get, use);
1566 		}
1567 	      md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
1568 	      break;
1569 
1570 	    case SEG_DIFFERENCE:
1571 #ifndef WORKING_DOT_WORD
1572 	      if(nbytes==2) {
1573 		struct broken_word *x;
1574 
1575 		x=(struct broken_word *)xmalloc(sizeof(struct broken_word));
1576 		x->next_broken_word=broken_words;
1577 		broken_words=x;
1578 		x->frag=frag_now;
1579 		x->word_goes_here=p;
1580 		x->dispfrag=0;
1581 		x->add=exp.X_add_symbol;
1582 		x->sub=exp.X_subtract_symbol;
1583 		x->addnum=exp.X_add_number;
1584 		x->added=0;
1585 		new_broken_words++;
1586 		break;
1587 	      }
1588 	      /* Else Fall through into. . . */
1589 #endif
1590 	    case SEG_BSS:
1591 	    case SEG_UNKNOWN:
1592 	    case SEG_TEXT:
1593 	    case SEG_DATA:
1594 #if defined(SPARC) || defined(I860)
1595 	      fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
1596 		       exp . X_add_symbol, exp . X_subtract_symbol,
1597 		       exp . X_add_number, 0, RELOC_32);
1598 #endif
1599 #ifdef NS32K
1600 	      fix_new_ns32k (frag_now, p - frag_now -> fr_literal, nbytes,
1601 		       exp . X_add_symbol, exp . X_subtract_symbol,
1602 		       exp . X_add_number, 0, 0, 2, 0, 0);
1603 #endif
1604 #if !defined(SPARC) && !defined(NS32K) && !defined(I860)
1605 	      fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
1606 		       exp . X_add_symbol, exp . X_subtract_symbol,
1607 		       exp . X_add_number, 0);
1608 #endif
1609 	      break;
1610 
1611 	    default:
1612 	      BAD_CASE( segment );
1613 	      break;
1614 	    }			/* switch(segment) */
1615 	}			/* if(!need_pass_2) */
1616       c = * input_line_pointer ++;
1617     }				/* while(c==',') */
1618   input_line_pointer --;	/* Put terminator back into stream. */
1619   demand_empty_rest_of_line();
1620 }				/* cons() */
1621 
1622 /*
1623  *			big_cons()
1624  *
1625  * CONStruct more frag(s) of .quads, or .octa etc.
1626  * Makes 0 or more new frags.
1627  * If need_pass_2 == TRUE, generate no frag.
1628  * This understands only bignums, not expressions. Cons() understands
1629  * expressions.
1630  *
1631  * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
1632  *
1633  * This creates objects with struct obstack_control objs, destroying
1634  * any context objs held about a partially completed object. Beware!
1635  *
1636  *
1637  * I think it sucks to have 2 different types of integers, with 2
1638  * routines to read them, store them etc.
1639  * It would be nicer to permit bignums in expressions and only
1640  * complain if the result overflowed. However, due to "efficiency"...
1641  */
1642 void
1643 big_cons(nbytes)		/* worker to do .quad etc statements */
1644 				/* clobbers input_line_pointer, checks */
1645 				/* end-of-line. */
1646      register int	nbytes;	/* 8=.quad 16=.octa ... */
1647 {
1648   register char		c;	/* input_line_pointer -> c. */
1649   register int		radix;
1650   register long int	length;	/* Number of chars in an object. */
1651   register int		digit;	/* Value of 1 digit. */
1652   register int		carry;	/* For multi-precision arithmetic. */
1653   register int		work;	/* For multi-precision arithmetic. */
1654   register char *	p;	/* For multi-precision arithmetic. */
1655 
1656   extern char hex_value[];	/* In hex_value.c. */
1657 
1658   /*
1659    * The following awkward logic is to parse ZERO or more strings,
1660    * comma seperated. Recall an expression includes its leading &
1661    * trailing blanks. We fake a leading ',' if there is (supposed to
1662    * be) a 1st expression, and keep demanding 1 expression for each ','.
1663    */
1664   if (is_it_end_of_statement())
1665     {
1666       c = 0;			/* Skip loop. */
1667     }
1668   else
1669     {
1670       c = ',';			/* Do loop. */
1671       -- input_line_pointer;
1672     }
1673   while (c == ',')
1674     {
1675       ++ input_line_pointer;
1676       SKIP_WHITESPACE();
1677       c = * input_line_pointer;
1678       /* C contains 1st non-blank character of what we hope is a number. */
1679       if (c == '0')
1680 	{
1681 	  c = * ++ input_line_pointer;
1682 	  if (c == 'x' || c=='X')
1683 	    {
1684 	      c = * ++ input_line_pointer;
1685 	      radix = 16;
1686 	    }
1687 	  else
1688 	    {
1689 	      radix = 8;
1690 	    }
1691 	}
1692       else
1693 	{
1694 	  radix = 10;
1695 	}
1696       /*
1697        * This feature (?) is here to stop people worrying about
1698        * mysterious zero constants: which is what they get when
1699        * they completely omit digits.
1700        */
1701       if (hex_value[c] >= radix)
1702 	{
1703 	  as_warn( "Missing digits. 0 assumed." );
1704 	}
1705       bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
1706       for(   ;   (digit = hex_value [c]) < radix;   c = * ++ input_line_pointer)
1707 	{
1708 	  /* Multiply existing number by radix, then add digit. */
1709 	  carry = digit;
1710 	  for (p=bignum_low;   p <= bignum_high;   p++)
1711 	    {
1712 	      work = (*p & MASK_CHAR) * radix + carry;
1713 	      *p = work & MASK_CHAR;
1714 	      carry = work >> BITS_PER_CHAR;
1715 	    }
1716 	  if (carry)
1717 	    {
1718 	      grow_bignum();
1719 	      * bignum_high = carry & MASK_CHAR;
1720 	      know( (carry & ~ MASK_CHAR) == 0);
1721 	    }
1722 	}
1723       length = bignum_high - bignum_low + 1;
1724       if (length > nbytes)
1725 	{
1726 	  as_warn( "Most significant bits truncated in integer constant." );
1727 	}
1728       else
1729 	{
1730 	  register long int	leading_zeroes;
1731 
1732 	  for(leading_zeroes = nbytes - length;
1733 	      leading_zeroes;
1734 	      leading_zeroes --)
1735 	    {
1736 	      grow_bignum();
1737 	      * bignum_high = 0;
1738 	    }
1739 	}
1740       if (! need_pass_2)
1741 	{
1742 	  p = frag_more (nbytes);
1743 	  bcopy (bignum_low, p, (int)nbytes);
1744 	}
1745       /* C contains character after number. */
1746       SKIP_WHITESPACE();
1747       c = * input_line_pointer;
1748       /* C contains 1st non-blank character after number. */
1749     }
1750   demand_empty_rest_of_line();
1751 }				/* big_cons() */
1752 
1753 static void
1754 grow_bignum()			/* Extend bignum by 1 char. */
1755 {
1756   register long int	length;
1757 
1758   bignum_high ++;
1759   if (bignum_high >= bignum_limit)
1760     {
1761       length = bignum_limit - bignum_low;
1762       bignum_low = xrealloc (bignum_low, length + length);
1763       bignum_high = bignum_low + length;
1764       bignum_limit = bignum_low + length + length;
1765     }
1766 }				/* grow_bignum(); */
1767 
1768 /*
1769  *			float_cons()
1770  *
1771  * CONStruct some more frag chars of .floats .ffloats etc.
1772  * Makes 0 or more new frags.
1773  * If need_pass_2 == TRUE, no frags are emitted.
1774  * This understands only floating literals, not expressions. Sorry.
1775  *
1776  * A floating constant is defined by atof_generic(), except it is preceded
1777  * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
1778  * reading, I decided to be incompatible. This always tries to give you
1779  * rounded bits to the precision of the pseudo-op. Former AS did premature
1780  * truncatation, restored noisy bits instead of trailing 0s AND gave you
1781  * a choice of 2 flavours of noise according to which of 2 floating-point
1782  * scanners you directed AS to use.
1783  *
1784  * In:	input_line_pointer -> whitespace before, or '0' of flonum.
1785  *
1786  */
1787 
1788 void	/* JF was static, but can't be if VAX.C is goning to use it */
1789 float_cons(float_type)		/* Worker to do .float etc statements. */
1790 				/* Clobbers input_line-pointer, checks end-of-line. */
1791      register float_type;	/* 'f':.ffloat ... 'F':.float ... */
1792 {
1793   register char *	p;
1794   register char		c;
1795   int	length;	/* Number of chars in an object. */
1796   register char *	err;	/* Error from scanning floating literal. */
1797   char		temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
1798 
1799   /*
1800    * The following awkward logic is to parse ZERO or more strings,
1801    * comma seperated. Recall an expression includes its leading &
1802    * trailing blanks. We fake a leading ',' if there is (supposed to
1803    * be) a 1st expression, and keep demanding 1 expression for each ','.
1804    */
1805   if (is_it_end_of_statement())
1806     {
1807       c = 0;			/* Skip loop. */
1808       ++ input_line_pointer;	/* -> past termintor. */
1809     }
1810   else
1811     {
1812       c = ',';			/* Do loop. */
1813     }
1814   while (c == ',')
1815     {
1816       /* input_line_pointer -> 1st char of a flonum (we hope!). */
1817       SKIP_WHITESPACE();
1818       /* Skip any 0{letter} that may be present. Don't even check if the
1819        * letter is legal. Someone may invent a "z" format and this routine
1820        * has no use for such information. Lusers beware: you get
1821        * diagnostics if your input is ill-conditioned.
1822        */
1823 
1824       if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1]))
1825 	  input_line_pointer+=2;
1826 
1827       err = md_atof (float_type, temp, &length);
1828       know( length <=  MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
1829       know( length > 0 );
1830       if (* err)
1831 	{
1832 	  as_warn( "Bad floating literal: %s", err);
1833 	  ignore_rest_of_line();
1834 	  /* Input_line_pointer -> just after end-of-line. */
1835 	  c = 0;		/* Break out of loop. */
1836 	}
1837       else
1838 	{
1839 	  if ( ! need_pass_2)
1840 	    {
1841 	      p = frag_more (length);
1842 	      bcopy (temp, p, length);
1843 	    }
1844 	  SKIP_WHITESPACE();
1845 	  c = * input_line_pointer ++;
1846 	  /* C contains 1st non-white character after number. */
1847 	  /* input_line_pointer -> just after terminator (c). */
1848 	}
1849     }
1850   -- input_line_pointer;		/* -> terminator (is not ','). */
1851   demand_empty_rest_of_line();
1852 }				/* float_cons() */
1853 
1854 /*
1855  *			stringer()
1856  *
1857  * We read 0 or more ',' seperated, double-quoted strings.
1858  *
1859  * Caller should have checked need_pass_2 is FALSE because we don't check it.
1860  */
1861 static void
1862 stringer(append_zero)		/* Worker to do .ascii etc statements. */
1863 				/* Checks end-of-line. */
1864      register int append_zero;	/* 0: don't append '\0', else 1 */
1865 {
1866   /* register char *	p; JF unused */
1867   /* register int		length; JF unused */	/* Length of string we read, excluding */
1868 				/* trailing '\0' implied by closing quote. */
1869   /* register char *	where; JF unused */
1870   /* register fragS *	fragP; JF unused */
1871   register int c;
1872 
1873   /*
1874    * The following awkward logic is to parse ZERO or more strings,
1875    * comma seperated. Recall a string expression includes spaces
1876    * before the opening '\"' and spaces after the closing '\"'.
1877    * We fake a leading ',' if there is (supposed to be)
1878    * a 1st, expression. We keep demanding expressions for each
1879    * ','.
1880    */
1881   if (is_it_end_of_statement())
1882     {
1883       c = 0;			/* Skip loop. */
1884       ++ input_line_pointer;	/* Compensate for end of loop. */
1885     }
1886   else
1887     {
1888       c = ',';			/* Do loop. */
1889     }
1890   for (   ;   c == ',';   c = *input_line_pointer ++)
1891     {
1892       SKIP_WHITESPACE();
1893       if (* input_line_pointer == '\"')
1894 	{
1895 	  ++ input_line_pointer; /* -> 1st char of string. */
1896 	  while ( (c = next_char_of_string()) >= 0)
1897 	    {
1898 	      FRAG_APPEND_1_CHAR( c );
1899 	    }
1900 	  if (append_zero)
1901 	    {
1902 	      FRAG_APPEND_1_CHAR( 0 );
1903 	    }
1904 	  know( input_line_pointer [-1] == '\"' );
1905 	}
1906       else
1907 	{
1908 	  as_warn( "Expected \"-ed string" );
1909 	}
1910       SKIP_WHITESPACE();
1911     }
1912   -- input_line_pointer;
1913   demand_empty_rest_of_line();
1914 }				/* stringer() */
1915 
1916 static int
1917 next_char_of_string ()
1918 {
1919   register int c;
1920 
1921   c = * input_line_pointer ++;
1922   switch (c)
1923     {
1924     case '\"':
1925       c = -1;
1926       break;
1927 
1928     case '\\':
1929       switch (c = * input_line_pointer ++)
1930 	{
1931 	case 'b':
1932 	  c = '\b';
1933 	  break;
1934 
1935 	case 'f':
1936 	  c = '\f';
1937 	  break;
1938 
1939 	case 'n':
1940 	  c = '\n';
1941 	  break;
1942 
1943 	case 'r':
1944 	  c = '\r';
1945 	  break;
1946 
1947 	case 't':
1948 	  c = '\t';
1949 	  break;
1950 
1951 	case '\\':
1952 	case '"':
1953 	  break;		/* As itself. */
1954 
1955 	case '0':
1956 	case '1':
1957 	case '2':
1958 	case '3':
1959 	case '4':
1960 	case '5':
1961 	case '6':
1962 	case '7':
1963 	case '8':
1964 	case '9':
1965 	  {
1966 	    long int number;
1967 
1968 	    for (number = 0;   isdigit(c);   c = * input_line_pointer ++)
1969 	      {
1970 		number = number * 8 + c - '0';
1971 	      }
1972 	    c = number;
1973 	  }
1974 	  -- input_line_pointer;
1975 	  break;
1976 
1977 	case '\n':
1978 /*	  as_fatal( "Unterminated string - use app!" ); */
1979 /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
1980 	  c = '\n';
1981 	  break;
1982 
1983 	default:
1984 	  as_warn( "Bad escaped character in string, '?' assumed" );
1985 	  c = '?';
1986 	  break;
1987 	}
1988       break;
1989 
1990     default:
1991       break;
1992     }
1993   return (c);
1994 }
1995 
1996 static segT
1997 get_segmented_expression ( expP )
1998      register expressionS *	expP;
1999 {
2000   register segT		retval;
2001 
2002   if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG )
2003     {
2004       as_warn("Expected address expression: absolute 0 assumed");
2005       retval = expP -> X_seg = SEG_ABSOLUTE;
2006       expP -> X_add_number   = 0;
2007       expP -> X_add_symbol   = expP -> X_subtract_symbol = 0;
2008     }
2009   return (retval);		/* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
2010 }
2011 
2012 static segT
2013 get_known_segmented_expression ( expP )
2014      register expressionS *	expP;
2015 {
2016   register segT		retval;
2017   register char *	name1;
2018   register char *	name2;
2019 
2020   if (   (retval = get_segmented_expression (expP)) == SEG_UNKNOWN
2021       )
2022     {
2023       name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : "";
2024       name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : "";
2025       if ( name1 && name2 )
2026 	{
2027 	  as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
2028 		  name1, name2);
2029 	}
2030       else
2031 	{
2032 	  as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
2033 		  name1 ? name1 : name2);
2034 	}
2035       retval = expP -> X_seg = SEG_ABSOLUTE;
2036       expP -> X_add_number   = 0;
2037       expP -> X_add_symbol   = expP -> X_subtract_symbol = NULL;
2038     }
2039  know(   retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE );
2040   return (retval);
2041 }				/* get_known_segmented_expression() */
2042 
2043 
2044 
2045 /* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */
2046 get_absolute_expression ()
2047 {
2048   expressionS	exp;
2049   register segT s;
2050 
2051   if ( (s = expression(& exp)) != SEG_ABSOLUTE )
2052     {
2053       if ( s != SEG_NONE )
2054 	{
2055 	  as_warn( "Bad Absolute Expression, absolute 0 assumed.");
2056 	}
2057       exp . X_add_number = 0;
2058     }
2059   return (exp . X_add_number);
2060 }
2061 
2062 static char			/* return terminator */
2063 get_absolute_expression_and_terminator( val_pointer)
2064      long int *		val_pointer; /* return value of expression */
2065 {
2066   * val_pointer = get_absolute_expression ();
2067   return ( * input_line_pointer ++ );
2068 }
2069 
2070 /*
2071  *			demand_copy_C_string()
2072  *
2073  * Like demand_copy_string, but return NULL if the string contains any '\0's.
2074  * Give a warning if that happens.
2075  */
2076 static char *
2077 demand_copy_C_string (len_pointer)
2078      int *	len_pointer;
2079 {
2080   register char *	s;
2081 
2082   if (s = demand_copy_string (len_pointer))
2083     {
2084       register int	len;
2085 
2086       for (len = * len_pointer;
2087 	   len > 0;
2088 	   len--)
2089 	{
2090 	  if (* s == 0)
2091 	    {
2092 	      s = 0;
2093 	      len = 1;
2094 	      * len_pointer = 0;
2095 	      as_warn( "This string may not contain \'\\0\'" );
2096 	    }
2097 	}
2098     }
2099   return (s);
2100 }
2101 
2102 /*
2103  *			demand_copy_string()
2104  *
2105  * Demand string, but return a safe (=private) copy of the string.
2106  * Return NULL if we can't read a string here.
2107  */
2108 static char *
2109 demand_copy_string (lenP)
2110      int *	lenP;
2111 {
2112   register int		c;
2113   register int		len;
2114 	   char *	retval;
2115 
2116   len = 0;
2117   SKIP_WHITESPACE();
2118   if (* input_line_pointer == '\"')
2119     {
2120       input_line_pointer ++;	/* Skip opening quote. */
2121       while ( (c = next_char_of_string()) >= 0 ) {
2122 	  obstack_1grow ( &notes, c );
2123 	  len ++;
2124 	}
2125       /* JF this next line is so demand_copy_C_string will return a null
2126          termanated string. */
2127       obstack_1grow(&notes,'\0');
2128       retval=obstack_finish( &notes);
2129   } else {
2130       as_warn( "Missing string" );
2131       retval = NULL;
2132       ignore_rest_of_line ();
2133     }
2134   * lenP = len;
2135   return (retval);
2136 }
2137 
2138 /*
2139  *		is_it_end_of_statement()
2140  *
2141  * In:	Input_line_pointer -> next character.
2142  *
2143  * Do:	Skip input_line_pointer over all whitespace.
2144  *
2145  * Out:	TRUE if input_line_pointer -> end-of-line.
2146  */
2147 static int
2148 is_it_end_of_statement()
2149 {
2150   SKIP_WHITESPACE();
2151   return (is_end_of_line [* input_line_pointer]);
2152 }
2153 
2154 void
2155 equals(sym_name)
2156 char *sym_name;
2157 {
2158   register struct symbol * symbolP; /* symbol we are working with */
2159 
2160   input_line_pointer++;
2161   if(*input_line_pointer=='=')
2162     input_line_pointer++;
2163 
2164   while(*input_line_pointer==' ' || *input_line_pointer=='\t')
2165     input_line_pointer++;
2166 
2167   if(sym_name[0]=='.' && sym_name[1]=='\0') {
2168     /* Turn '. = mumble' into a .org mumble */
2169     register segT segment;
2170     expressionS exp;
2171     register char *p;
2172 
2173     segment = get_known_segmented_expression(& exp);
2174     if ( ! need_pass_2 ) {
2175       if (segment != now_seg && segment != SEG_ABSOLUTE)
2176         as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
2177                 seg_name [(int) segment], seg_name [(int) now_seg]);
2178       p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
2179                     exp.X_add_number, (char *)0);
2180       * p = 0;
2181     } /* if (ok to make frag) */
2182   } else {
2183     symbolP=symbol_find_or_make(sym_name);
2184     pseudo_set(symbolP);
2185   }
2186 }
2187 
2188 /* end: read.c */
2189