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