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