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