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