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