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