1 /* read.c - read a source file -
3 Copyright (C) 1986, 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
22 static char rcsid[] = "$FreeBSD$";
25 #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
26 change this a bit. But then, GNU isn't
27 spozed to run on your machine anyway.
28 (RMS is so shortsighted sometimes.)
31 #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
32 /* This is the largest known floating point */
33 /* format (for now). It will grow when we */
34 /* do 4361 style flonums. */
37 /* Routines that read assembler source text to build spagetti in memory. */
38 /* Another group of these functions is in the as-expr.c module */
44 char *input_line_pointer; /*->next char of source file to parse. */
47 # define NOP_OPCODE 0x00
50 #if BITS_PER_CHAR != 8
51 The following table is indexed by [ (char) ] and will break if
52 a char does not have exactly 256 states (hopefully 0:255!) !
64 char /* used by is_... macros. our ctype[] */
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
68 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
69 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
70 AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
71 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
72 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
73 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
86 * Out: 1 if this character ends a line.
89 char is_end_of_line[256] = {
91 _, _, _, _, _, _, _, _, _, _,99, _, _, 99, _, _,/* @abcdefghijklmno */
93 _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
95 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
96 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
97 _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
98 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
99 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
100 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
101 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
102 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
103 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
104 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
105 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
106 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */
110 /* Functions private to this file. */
112 extern const char line_comment_chars[];
113 const char line_separator_chars[1];
115 static char *buffer; /* 1st char of each buffer of lines is here. */
116 static char *buffer_limit; /*->1 + last char in buffer. */
118 static char *bignum_low; /* Lowest char of bignum. */
119 static char *bignum_limit; /* 1st illegal address of bignum. */
120 static char *bignum_high; /* Highest char of bignum. */
121 /* May point to (bignum_start-1). */
122 /* Never >= bignum_limit. */
123 static char *old_buffer = 0; /* JF a hack */
124 static char *old_input;
125 static char *old_limit;
127 /* Variables for handling include file directory list. */
129 char **include_dirs; /* List of pointers to directories to
130 search for .include's */
131 int include_dir_count; /* How many are in the list */
132 int include_dir_maxlen = 1; /* Length of longest in list */
134 #ifndef WORKING_DOT_WORD
135 struct broken_word *broken_words;
136 int new_broken_words = 0;
141 static char *demand_copy_string(int *lenP);
142 int is_it_end_of_statement(void);
143 unsigned int next_char_of_string(void);
144 static segT get_known_segmented_expression(expressionS *expP);
145 static void grow_bignum(void);
146 static void pobegin(void);
147 void stringer(int append_zero);
151 static char *demand_copy_string();
152 int is_it_end_of_statement();
153 unsigned int next_char_of_string();
154 static segT get_known_segmented_expression();
155 static void grow_bignum();
156 static void pobegin();
159 #endif /* not __STDC__ */
170 obj_read_begin_hook();
172 obstack_begin(¬es, 5000);
173 obstack_begin(&cond_obstack, 960);
175 #define BIGNUM_BEGIN_SIZE (16)
176 bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
177 bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
179 /* Use machine dependent syntax */
180 for (p = line_separator_chars; *p; p++)
181 is_end_of_line[*p] = 1;
182 /* Use more. FIXME-SOMEDAY. */
185 /* set up pseudo-op tables */
187 struct hash_control *
188 po_hash = NULL; /* use before set up: NULL->address error */
190 static const pseudo_typeS
193 { "abort", s_abort, 0 },
194 { "align", s_align_ptwo, 0 },
195 { "ascii", stringer, 0 },
196 { "asciz", stringer, 1 },
199 { "comm", s_comm, 0 },
200 { "data", s_data, 0 },
202 { "double", float_cons, 'd' },
205 { "eject", s_ignore, 0 }, /* Formfeed listing */
207 { "eject", listing_eject, 0 }, /* Formfeed listing */
208 #endif /* NO_LISTING */
209 { "else", s_else, 0 },
211 { "endif", s_endif, 0 },
216 { "extern", s_ignore, 0 }, /* We treat all undef as ext */
217 { "appline", s_app_line, 0 },
218 { "appfile", s_app_file, 1 },
219 { "file", s_app_file, 0 },
220 { "fill", s_fill, 0 },
221 { "float", float_cons, 'f' },
222 { "global", s_globl, 0 },
223 { "globl", s_globl, 0 },
224 { "hword", cons, 2 },
226 { "ifdef", s_ifdef, 0 },
227 { "ifeqs", s_ifeqs, 0 },
228 { "ifndef", s_ifdef, 1 },
229 { "ifnes", s_ifeqs, 1 },
230 { "ifnotdef", s_ifdef, 1 },
231 { "include", s_include, 0 },
233 { "lcomm", s_lcomm, 0 },
235 { "lflags", s_ignore, 0 }, /* Listing flags */
236 { "list", s_ignore, 1 }, /* Turn listing on */
238 { "lflags", listing_flags, 0 }, /* Listing flags */
239 { "list", listing_list, 1 }, /* Turn listing on */
240 #endif /* NO_LISTING */
242 { "lsym", s_lsym, 0 },
244 { "nolist", s_ignore, 0 }, /* Turn listing off */
246 { "nolist", listing_list, 0 }, /* Turn listing off */
247 #endif /* NO_LISTING */
248 { "octa", big_cons, 16 },
250 { "p2align", s_align_ptwo, 0 },
252 { "psize", s_ignore, 0 }, /* set paper size */
254 { "psize", listing_psize, 0 }, /* set paper size */
255 #endif /* NO_LISTING */
257 { "quad", big_cons, 8 },
259 { "sbttl", s_ignore, 1 }, /* Subtitle of listing */
261 { "sbttl", listing_title, 1 }, /* Subtitle of listing */
262 #endif /* NO_LISTING */
268 { "short", cons, 2 },
269 { "single", float_cons, 'f' },
271 { "space", s_space, 0 },
273 { "text", s_text, 0 },
275 { "title", s_ignore, 0 }, /* Listing title */
277 { "title", listing_title, 0 }, /* Listing title */
278 #endif /* NO_LISTING */
283 { NULL} /* end sentinel */
286 static void pobegin() {
287 char *errtxt; /* error text */
288 const pseudo_typeS * pop;
290 po_hash = hash_new();
292 /* Do the target-specific pseudo ops. */
293 for (pop = md_pseudo_table; pop->poc_name; pop++) {
294 errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
295 if (errtxt && *errtxt) {
296 as_fatal("error constructing md pseudo-op table");
300 /* Now object specific. Skip any that were in the target table. */
301 for (pop = obj_pseudo_table; pop->poc_name; pop++) {
302 errtxt = hash_insert(po_hash, pop->poc_name, (char *) pop);
303 if (errtxt && *errtxt) {
304 if (!strcmp(errtxt, "exists")) {
305 #ifdef DIE_ON_OVERRIDES
306 as_fatal("pseudo op \".%s\" overridden.\n", pop->poc_name);
307 #endif /* DIE_ON_OVERRIDES */
308 continue; /* OK if target table overrides. */
310 as_fatal("error constructing obj pseudo-op table");
311 } /* if overridden */
315 /* Now portable ones. Skip any that we've seen already. */
316 for (pop = potable; pop->poc_name; pop++) {
317 errtxt = hash_insert(po_hash, pop->poc_name, (char *) pop);
318 if (errtxt && *errtxt) {
319 if (!strcmp (errtxt, "exists")) {
320 #ifdef DIE_ON_OVERRIDES
321 as_fatal("pseudo op \".%s\" overridden.\n", pop->poc_name);
322 #endif /* DIE_ON_OVERRIDES */
323 continue; /* OK if target table overrides. */
325 as_fatal("error constructing obj pseudo-op table");
326 } /* if overridden */
333 #define HANDLE_CONDITIONAL_ASSEMBLY() \
334 if (ignore_input ()) \
336 while (! is_end_of_line[*input_line_pointer++]) \
337 if (input_line_pointer == buffer_limit) \
343 /* read_a_source_file()
345 * We read the file, putting things into a web that
346 * represents what we have been reading.
348 void read_a_source_file(name)
352 register char * s; /* string of symbol, '\0' appended */
354 pseudo_typeS *pop = NULL;
356 buffer = input_scrub_new_file(name);
361 while ((buffer_limit = input_scrub_next_buffer(&input_line_pointer)) != 0) { /* We have another line to parse. */
362 know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */
363 contin: /* JF this goto is my fault I admit it. Someone brave please re-write
364 the whole input section here? Pleeze??? */
365 while (input_line_pointer < buffer_limit) { /* We have more of this buffer to parse. */
368 * We now have input_line_pointer->1st char of next line.
369 * If input_line_pointer[-1] == '\n' then we just
370 * scanned another line: so bump line counters.
372 if (input_line_pointer[-1] == '\n') {
373 bump_line_counters();
374 } /* just passed a newline */
379 * We are at the begining of a line, or similar place.
380 * We expect a well-formed assembler statement.
381 * A "symbol-name:" is a statement.
383 * Depending on what compiler is used, the order of these tests
384 * may vary to catch most common case 1st.
385 * Each test is independent of all other tests at the (top) level.
386 * PLEASE make a compiler that doesn't use this assembler.
387 * It is crufty to waste a compiler's time encoding things for this
388 * assembler, which then wastes more time decoding it.
389 * (And communicating via (linear) files is silly!
390 * If you must pass stuff, please pass a tree!)
392 if ((c = *input_line_pointer++) == '\t' || c == ' ' || c == '\f' || c == 0) {
393 c = *input_line_pointer++;
395 know(c != ' '); /* No further leading whitespace. */
398 * C is the 1st significant character.
399 * Input_line_pointer points after that character.
401 if (is_name_beginner(c)) { /* want user-defined label or pseudo/opcode */
402 HANDLE_CONDITIONAL_ASSEMBLY();
404 s = input_line_pointer - 1;
405 c = get_symbol_end(); /* name's delimiter */
407 * C is character after symbol.
408 * That character's place in the input line is now '\0'.
409 * S points to the beginning of the symbol.
410 * [In case of pseudo-op, s->'.'.]
411 * Input_line_pointer->'\0' where c was.
414 colon(s); /* user-defined label */
415 * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */
416 /* Input_line_pointer->after ':'. */
420 } else if (c == '=' || input_line_pointer[1] == '=') { /* JF deal with FOO=BAR */
422 demand_empty_rest_of_line();
423 } else { /* expect pseudo-op or machine instruction */
425 #ifdef NO_DOT_PSEUDOS
426 || (pop= (pseudo_typeS *) hash_find(po_hash, s))
432 * WARNING: c has next char, which may be end-of-line.
433 * We lookup the pseudo-op table with s+1 because we
434 * already know that the pseudo-op begins with a '.'.
437 #ifdef NO_DOT_PSEUDOS
440 pop = (pseudo_typeS *) hash_find(po_hash, s+1);
442 /* Print the error msg now, while we still can */
444 as_bad("Unknown pseudo-op: `%s'",s);
445 *input_line_pointer = c;
450 /* Put it back for error messages etc. */
451 *input_line_pointer = c;
452 /* The following skip of whitespace is compulsory. */
453 /* A well shaped space is sometimes all that separates keyword from operands. */
454 if (c == ' ' || c == '\t') {
455 input_line_pointer++;
456 } /* Skip seperator after keyword. */
458 * Input_line is restored.
459 * Input_line_pointer->1st non-blank char
460 * after pseudo-operation.
463 ignore_rest_of_line();
466 (*pop->poc_handler)(pop->poc_val);
467 } /* if we have one */
468 } else { /* machine instruction */
469 /* WARNING: c has char, which may be end-of-line. */
470 /* Also: input_line_pointer->`\0` where c was. */
471 * input_line_pointer = c;
472 while (!is_end_of_line[*input_line_pointer]) {
473 input_line_pointer++;
475 c = *input_line_pointer;
476 *input_line_pointer = '\0';
477 md_assemble(s); /* Assemble 1 instruction. */
478 *input_line_pointer++ = c;
479 /* We resume loop AFTER the end-of-line from this instruction */
480 } /* if (*s == '.') */
484 } /* if (is_name_beginner(c) */
487 if (is_end_of_line[c]) {
489 } /* empty statement */
492 if (isdigit(c)) { /* local label ("4:") */
493 HANDLE_CONDITIONAL_ASSEMBLY ();
496 #ifdef LOCAL_LABELS_DOLLAR
497 if (*input_line_pointer == '$')
498 input_line_pointer++;
500 if (*input_line_pointer++ == ':') {
503 as_bad("Spurious digit %d.", temp);
504 input_line_pointer -- ;
505 ignore_rest_of_line();
508 } /* local label ("4:") */
510 if (c && strchr(line_comment_chars, c)) { /* Its a comment. Better say APP or NO_APP */
516 extern char *scrub_string, *scrub_last_string;
518 bump_line_counters();
519 s = input_line_pointer;
520 if (strncmp(s,"APP\n",4))
521 continue; /* We ignore it */
524 ends = strstr(s,"#NO_APP\n");
530 /* The end of the #APP wasn't in this buffer. We
531 keep reading in buffers until we find the #NO_APP
532 that goes with this #APP There is one. The specs
534 tmp_len = buffer_limit - s;
535 tmp_buf = xmalloc(tmp_len);
536 memcpy(tmp_buf, s, tmp_len);
538 new_tmp = input_scrub_next_buffer(&buffer);
542 buffer_limit = new_tmp;
543 input_line_pointer = buffer;
544 ends = strstr(buffer,"#NO_APP\n");
548 num = buffer_limit - buffer;
550 tmp_buf = xrealloc(tmp_buf, tmp_len + num);
551 memcpy(tmp_buf + tmp_len, buffer, num);
555 input_line_pointer = ends ? ends + 8 : NULL;
561 input_line_pointer = ends + 8;
563 new_buf=xmalloc(100);
568 scrub_last_string = ends;
572 ch = do_scrub_next_char(scrub_from_string, scrub_to_string);
573 if (ch == EOF) break;
575 if (new_tmp == new_buf + new_length) {
576 new_buf = xrealloc(new_buf, new_length + 100);
577 new_tmp = new_buf + new_length;
585 old_input = input_line_pointer;
586 old_limit = buffer_limit;
588 input_line_pointer = new_buf;
589 buffer_limit = new_tmp;
593 HANDLE_CONDITIONAL_ASSEMBLY();
595 /* as_warn("Junk character %d.",c); Now done by ignore_rest */
596 input_line_pointer--; /* Report unknown char as ignored. */
597 ignore_rest_of_line();
598 } /* while (input_line_pointer<buffer_limit) */
600 bump_line_counters();
601 if (old_input != 0) {
603 input_line_pointer=old_input;
604 buffer_limit=old_limit;
609 } /* while (more buffers to scan) */
610 input_scrub_close(); /* Close the input file */
612 } /* read_a_source_file() */
615 as_fatal(".abort detected. Abandoning ship.");
618 /* For machines where ".align 4" means align to a 4 byte boundary. */
619 void s_align_bytes(arg)
622 register unsigned int temp;
623 register long temp_fill;
625 unsigned long max_alignment = 1 << 15;
627 if (is_end_of_line[*input_line_pointer])
628 temp = arg; /* Default value from pseudo-op table */
630 temp = get_absolute_expression();
632 if (temp > max_alignment) {
633 as_bad("Alignment too large: %d. assumed.", temp = max_alignment);
637 * For the sparc, `.align (1<<n)' actually means `.align n'
638 * so we have to convert it.
641 for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
645 as_bad("Alignment not a power of 2");
649 if (*input_line_pointer == ',') {
650 input_line_pointer ++;
651 temp_fill = get_absolute_expression();
653 temp_fill = NOP_OPCODE;
655 /* Only make a frag if we HAVE to... */
656 if (temp && ! need_pass_2)
657 frag_align(temp, (int)temp_fill);
659 demand_empty_rest_of_line();
660 } /* s_align_bytes() */
662 /* For machines where ".align 4" means align to 2**4 boundary. */
663 void s_align_ptwo() {
665 register long temp_fill;
666 long max_alignment = 15;
668 temp = get_absolute_expression();
669 if (temp > max_alignment)
670 as_bad("Alignment too large: %d. assumed.", temp = max_alignment);
672 as_bad("Alignment negative. 0 assumed.");
675 if (*input_line_pointer == ',') {
676 input_line_pointer ++;
677 temp_fill = get_absolute_expression();
679 temp_fill = NOP_OPCODE;
680 /* Only make a frag if we HAVE to... */
681 if (temp && ! need_pass_2)
682 frag_align (temp, (int)temp_fill);
684 record_alignment(now_seg, temp);
686 demand_empty_rest_of_line();
687 } /* s_align_ptwo() */
694 register symbolS *symbolP;
696 name = input_line_pointer;
697 c = get_symbol_end();
698 /* just after name is now '\0' */
699 p = input_line_pointer;
702 if (*input_line_pointer != ',') {
703 as_bad("Expected comma after symbol-name: rest of line ignored.");
704 ignore_rest_of_line();
707 input_line_pointer ++; /* skip ',' */
708 if ((temp = get_absolute_expression()) < 0) {
709 as_warn(".COMMon length (%d.) <0! Ignored.", temp);
710 ignore_rest_of_line();
714 symbolP = symbol_find_or_make(name);
716 if (S_IS_DEFINED(symbolP)) {
717 as_bad("Ignoring attempt to re-define symbol");
718 ignore_rest_of_line();
721 if (S_GET_VALUE(symbolP)) {
722 if (S_GET_VALUE(symbolP) != temp)
723 as_bad("Length of .comm \"%s\" is already %d. Not changed to %d.",
725 S_GET_VALUE(symbolP),
728 S_SET_VALUE(symbolP, temp);
729 S_SET_EXTERNAL(symbolP);
732 if ( (!temp) || !flagseen['1'])
733 S_GET_OTHER(symbolP) = const_flag;
734 #endif /* not OBJ_VMS */
735 know(symbolP->sy_frag == &zero_address_frag);
736 demand_empty_rest_of_line();
744 temp = get_absolute_expression();
745 subseg_new (SEG_DATA, (subsegT)temp);
749 #endif /* not OBJ_VMS */
750 demand_empty_rest_of_line();
753 /* Handle the .appfile pseudo-op. This is automatically generated by
754 do_scrub_next_char when a preprocessor # line comment is seen with
755 a file name. This default definition may be overridden by the
756 object or CPU specific pseudo-ops. This function is also the
757 default definition for .file; the APPFILE argument is 1 for
758 .appfile, 0 for .file. */
760 void s_app_file(appfile)
766 /* Some assemblers tolerate immediately following '"' */
767 if ((s = demand_copy_string(&length)) != 0) {
768 /* If this is a fake .appfile, a fake newline was inserted
769 * into the buffer. Passing -2 to new_logical_line tells it
772 new_logical_line (s, appfile ? -2 : -1);
773 demand_empty_rest_of_line();
776 listing_source_file (s);
780 c_dot_file_symbol(s);
781 #endif /* OBJ_COFF */
784 /* Handle the .appline pseudo-op. This is automatically generated by
785 do_scrub_next_char when a preprocessor # line comment is seen.
786 This default definition may be overridden by the object or CPU
787 specific pseudo-ops. */
795 /* The given number is that of the next line. */
796 l = get_absolute_expression () - 1;
797 new_logical_line ((char *) NULL, l);
800 listing_source_line (l);
802 demand_empty_rest_of_line ();
808 register long temp_fill;
811 if (get_absolute_expression_and_terminator(& temp_repeat) != ',') {
812 input_line_pointer --; /* Backup over what was not a ','. */
813 as_bad("Expect comma after rep-size in .fill:");
814 ignore_rest_of_line();
817 if (get_absolute_expression_and_terminator(& temp_size) != ',') {
818 input_line_pointer --; /* Backup over what was not a ','. */
819 as_bad("Expected comma after size in .fill");
820 ignore_rest_of_line();
824 * This is to be compatible with BSD 4.2 AS, not for any rational reason.
826 #define BSD_FILL_SIZE_CROCK_8 (8)
827 if (temp_size > BSD_FILL_SIZE_CROCK_8) {
828 as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
829 temp_size = BSD_FILL_SIZE_CROCK_8 ;
830 } if (temp_size < 0) {
831 as_warn("Size negative: .fill ignored.");
833 } else if (temp_repeat <= 0) {
834 as_warn("Repeat < 0, .fill ignored");
837 temp_fill = get_absolute_expression();
838 if (temp_size && !need_pass_2) {
839 p = frag_var(rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
840 memset(p, '\0', (int) temp_size);
842 * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
843 * The following bizzare behaviour is to be compatible with above.
844 * I guess they tried to take up to 8 bytes from a 4-byte expression
845 * and they forgot to sign extend. Un*x Sux.
847 #define BSD_FILL_SIZE_CROCK_4 (4)
848 md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
850 * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
851 * but emits no error message because it seems a legal thing to do.
852 * It is a degenerate case of .fill but could be emitted by a compiler.
855 demand_empty_rest_of_line();
861 register symbolS * symbolP;
864 name = input_line_pointer;
865 c = get_symbol_end();
866 symbolP = symbol_find_or_make(name);
867 * input_line_pointer = c;
869 S_SET_EXTERNAL(symbolP);
871 input_line_pointer++;
873 if (*input_line_pointer == '\n')
877 demand_empty_rest_of_line();
880 void s_lcomm(needs_align)
881 int needs_align; /* 1 if this was a ".bss" directive, which may require
882 * a 3rd argument (alignment).
883 * 0 if it was an ".lcomm" (2 args only)
890 register symbolS * symbolP;
891 const int max_alignment = 15;
894 name = input_line_pointer;
895 c = get_symbol_end();
896 p = input_line_pointer;
899 if (*input_line_pointer != ',') {
900 as_bad("Expected comma after name");
901 ignore_rest_of_line();
905 ++input_line_pointer;
907 if (*input_line_pointer == '\n') {
908 as_bad("Missing size expression");
912 if ((temp = get_absolute_expression()) < 0) {
913 as_warn("BSS length (%d.) <0! Ignored.", temp);
914 ignore_rest_of_line();
921 if (*input_line_pointer != ',') {
922 as_bad("Expected comma after size");
923 ignore_rest_of_line();
926 input_line_pointer++;
928 if (*input_line_pointer == '\n') {
929 as_bad("Missing alignment");
932 align = get_absolute_expression();
933 if (align > max_alignment){
934 align = max_alignment;
935 as_warn("Alignment too large: %d. assumed.", align);
936 } else if (align < 0) {
938 as_warn("Alignment negative. 0 assumed.");
940 record_alignment(SEG_BSS, align);
941 } /* if needs align */
944 symbolP = symbol_find_or_make(name);
948 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
949 S_GET_OTHER(symbolP) == 0 &&
950 S_GET_DESC(symbolP) == 0 &&
951 #endif /* OBJ_AOUT or OBJ_BOUT */
952 (((S_GET_SEGMENT(symbolP) == SEG_BSS) && (S_GET_VALUE(symbolP) == local_bss_counter))
953 || (!S_IS_DEFINED(symbolP) && S_GET_VALUE(symbolP) == 0))) {
956 align = ~ ((~0) << align); /* Convert to a mask */
958 (local_bss_counter + align) & (~align);
961 S_SET_VALUE(symbolP, local_bss_counter);
962 S_SET_SEGMENT(symbolP, SEG_BSS);
964 /* The symbol may already have been created with a preceding
965 * ".globl" directive -- be careful not to step on storage
966 * class in that case. Otherwise, set it to static.
968 if (S_GET_STORAGE_CLASS(symbolP) != C_EXT){
969 S_SET_STORAGE_CLASS(symbolP, C_STAT);
971 #endif /* OBJ_COFF */
972 symbolP->sy_frag = &bss_address_frag;
973 local_bss_counter += temp;
975 as_bad("Ignoring attempt to re-define symbol from %d. to %d.",
976 S_GET_VALUE(symbolP), local_bss_counter);
978 demand_empty_rest_of_line();
999 register segT segment;
1001 register symbolS *symbolP;
1003 /* we permit ANY defined expression: BSD4.2 demands constants */
1004 name = input_line_pointer;
1005 c = get_symbol_end();
1006 p = input_line_pointer;
1009 if (* input_line_pointer != ',') {
1011 as_bad("Expected comma after name \"%s\"", name);
1013 ignore_rest_of_line();
1016 input_line_pointer ++;
1017 segment = expression(& exp);
1018 if (segment != SEG_ABSOLUTE && !SEG_NORMAL(segment) &&
1019 segment != SEG_REGISTER) {
1020 as_bad("Bad expression: %s", segment_name(segment));
1021 ignore_rest_of_line();
1025 symbolP = symbol_find_or_make(name);
1027 /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0
1028 && symbolP->sy_desc == 0) out of this test
1029 because coff doesn't have those fields, and I
1030 can't see when they'd ever be tripped. I don't
1031 think I understand why they were here so I may
1032 have introduced a bug. As recently as 1.37 didn't
1033 have this test anyway. xoxorich. */
1035 if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN
1036 && S_GET_VALUE(symbolP) == 0) {
1037 /* The name might be an undefined .global symbol; be
1038 sure to keep the "external" bit. */
1039 S_SET_SEGMENT(symbolP, segment);
1040 S_SET_VALUE(symbolP, (valueT)(exp.X_add_number));
1042 as_bad("Symbol %s already defined", name);
1045 demand_empty_rest_of_line();
1049 register segT segment;
1051 register long temp_fill;
1054 * Don't believe the documentation of BSD 4.2 AS.
1055 * There is no such thing as a sub-segment-relative origin.
1056 * Any absolute origin is given a warning, then assumed to be segment-relative.
1057 * Any segmented origin expression ("foo+42") had better be in the right
1058 * segment or the .org is ignored.
1060 * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
1061 * never know sub-segment sizes when we are reading code.
1062 * BSD will crash trying to emit -ve numbers of filler bytes in certain
1063 * .orgs. We don't crash, but see as-write for that code.
1066 * Don't make frag if need_pass_2 == 1.
1068 segment = get_known_segmented_expression(&exp);
1069 if (*input_line_pointer == ',') {
1070 input_line_pointer ++;
1071 temp_fill = get_absolute_expression();
1074 if (! need_pass_2) {
1075 if (segment != now_seg && segment != SEG_ABSOLUTE)
1076 as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.",
1077 segment_name(segment), segment_name(now_seg));
1078 p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
1079 exp.X_add_number, (char *)0);
1081 } /* if (ok to make frag) */
1082 demand_empty_rest_of_line();
1086 register char *name;
1087 register char delim;
1088 register char *end_name;
1089 register symbolS *symbolP;
1092 * Especial apologies for the random logic:
1093 * this just grew, and could be parsed much more simply!
1096 name = input_line_pointer;
1097 delim = get_symbol_end();
1098 end_name = input_line_pointer;
1102 if (*input_line_pointer != ',') {
1104 as_bad("Expected comma after name \"%s\"", name);
1106 ignore_rest_of_line();
1110 input_line_pointer ++;
1113 if (name[0] == '.' && name[1] == '\0') {
1114 /* Turn '. = mumble' into a .org mumble */
1115 register segT segment;
1119 segment = get_known_segmented_expression(& exp);
1122 if (segment != now_seg && segment != SEG_ABSOLUTE)
1123 as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.",
1124 segment_name(segment),
1125 segment_name (now_seg));
1126 ptr = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
1127 exp.X_add_number, (char *)0);
1129 } /* if (ok to make frag) */
1135 if ((symbolP = symbol_find(name)) == NULL
1136 && (symbolP = md_undefined_symbol(name)) == NULL) {
1137 symbolP = symbol_new(name,
1140 &zero_address_frag);
1142 /* "set" symbols are local unless otherwise specified. */
1143 SF_SET_LOCAL(symbolP);
1144 #endif /* OBJ_COFF */
1146 } /* make a new symbol */
1148 symbol_table_insert(symbolP);
1151 pseudo_set(symbolP);
1152 demand_empty_rest_of_line();
1156 register char *name;
1160 register symbolS *symbolP;
1165 name = input_line_pointer;
1166 c = get_symbol_end();
1167 /* just after name is now '\0' */
1168 p = input_line_pointer;
1171 if (*input_line_pointer != ',') {
1172 as_bad("Expected comma after symbol-name: rest of line ignored.");
1173 ignore_rest_of_line();
1176 input_line_pointer ++; /* skip ',' */
1177 if ((exp = (expressionS *)malloc(sizeof(expressionS))) == NULL) {
1178 as_bad("Virtual memory exhausted");
1181 switch (get_known_segmented_expression(exp)) {
1184 case SEG_DIFFERENCE:
1185 if (exp->X_add_symbol == NULL || exp->X_subtract_symbol == NULL
1186 || S_GET_SEGMENT(exp->X_add_symbol) !=
1187 S_GET_SEGMENT(exp->X_subtract_symbol)) {
1188 as_bad("Illegal .size expression");
1189 ignore_rest_of_line();
1194 as_bad("Illegal .size expression");
1195 ignore_rest_of_line();
1199 symbolP = symbol_find_or_make(name);
1201 if (symbolP->sy_sizexp) {
1202 as_warn("\"%s\" already has a size", S_GET_NAME(symbolP));
1204 symbolP->sy_sizexp = (void *)exp;
1206 demand_empty_rest_of_line();
1210 register char *name, *type;
1211 register char c, c1;
1213 register symbolS *symbolP;
1217 name = input_line_pointer;
1218 c = get_symbol_end();
1219 /* just after name is now '\0' */
1220 p = input_line_pointer;
1223 if (*input_line_pointer != ',') {
1224 as_bad("Expected comma after symbol-name: rest of line ignored.");
1225 ignore_rest_of_line();
1228 input_line_pointer ++; /* skip ',' */
1230 if (*input_line_pointer != TYPE_OPERAND_FMT) {
1231 as_bad("Expected `%c' as start of operand: rest of line ignored.", TYPE_OPERAND_FMT);
1232 ignore_rest_of_line();
1235 input_line_pointer ++; /* skip '@' */
1236 type = input_line_pointer;
1237 c1 = get_symbol_end();
1238 if (strcmp(type, "function") == 0) {
1240 } else if (strcmp(type, "object") == 0) {
1243 as_warn("Unrecognized .type operand: \"%s\": rest of line ignored.",
1245 ignore_rest_of_line();
1248 *input_line_pointer = c1;
1251 symbolP = symbol_find_or_make(name);
1254 if (symbolP->sy_aux && symbolP->sy_aux != aux) {
1255 as_bad("Type of \"%s\" is already %d. Not changed to %d.",
1256 S_GET_NAME(symbolP), symbolP->sy_aux, aux);
1258 symbolP->sy_aux = aux;
1260 demand_empty_rest_of_line();
1264 register char *name;
1266 register symbolS * symbolP;
1269 name = input_line_pointer;
1270 c = get_symbol_end();
1271 symbolP = symbol_find_or_make(name);
1272 * input_line_pointer = c;
1274 S_SET_EXTERNAL(symbolP);
1275 symbolP->sy_bind = BIND_WEAK;
1277 input_line_pointer++;
1279 if (*input_line_pointer == '\n')
1283 demand_empty_rest_of_line();
1288 register long temp_fill;
1291 /* Just like .fill, but temp_size = 1 */
1292 if (get_absolute_expression_and_terminator(& temp_repeat) == ',') {
1293 temp_fill = get_absolute_expression();
1295 input_line_pointer --; /* Backup over what was not a ','. */
1298 if (temp_repeat <= 0) {
1299 as_warn("Repeat < 0, .space ignored");
1300 ignore_rest_of_line();
1303 if (! need_pass_2) {
1304 p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
1305 temp_repeat, (char *)0);
1308 demand_empty_rest_of_line();
1316 temp = get_absolute_expression();
1317 subseg_new (SEG_TEXT, (subsegT)temp);
1318 demand_empty_rest_of_line();
1322 /*(JF was static, but can't be if machine dependent pseudo-ops are to use it */
1324 void demand_empty_rest_of_line() {
1326 if (is_end_of_line[*input_line_pointer]) {
1327 input_line_pointer++;
1329 ignore_rest_of_line();
1331 /* Return having already swallowed end-of-line. */
1332 } /* Return pointing just after end-of-line. */
1335 ignore_rest_of_line() /* For suspect lines: gives warning. */
1337 if (!is_end_of_line[*input_line_pointer])
1339 if (isprint(*input_line_pointer))
1340 as_bad("Rest of line ignored. First ignored character is `%c'.",
1341 *input_line_pointer);
1343 as_bad("Rest of line ignored. First ignored character valued 0x%x.",
1344 *input_line_pointer);
1345 while (input_line_pointer < buffer_limit
1346 && !is_end_of_line[*input_line_pointer])
1348 input_line_pointer ++;
1351 input_line_pointer ++; /* Return pointing just after end-of-line. */
1352 know(is_end_of_line[input_line_pointer[-1]]);
1358 * In: Pointer to a symbol.
1359 * Input_line_pointer->expression.
1361 * Out: Input_line_pointer->just after any whitespace after expression.
1362 * Tried to set symbol to value of expression.
1363 * Will change symbols type, value, and frag;
1364 * May set need_pass_2 == 1.
1367 pseudo_set (symbolP)
1371 register segT segment;
1372 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1374 #endif /* OBJ_AOUT or OBJ_BOUT */
1376 know(symbolP); /* NULL pointer is logic error. */
1377 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1378 ext=S_IS_EXTERNAL(symbolP);
1379 #endif /* OBJ_AOUT or OBJ_BOUT */
1381 if ((segment = expression(& exp)) == SEG_ABSENT)
1383 as_bad("Missing expression: absolute 0 assumed");
1384 exp.X_seg = SEG_ABSOLUTE;
1385 exp.X_add_number = 0;
1391 as_bad("%s number invalid. Absolute 0 assumed.",
1392 exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
1393 S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
1394 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1395 ext ? S_SET_EXTERNAL(symbolP) :
1396 S_CLEAR_EXTERNAL(symbolP);
1397 #endif /* OBJ_AOUT or OBJ_BOUT */
1398 S_SET_VALUE(symbolP, 0);
1399 symbolP->sy_frag = & zero_address_frag;
1403 as_warn("No expression: Using absolute 0");
1404 S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
1405 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1406 ext ? S_SET_EXTERNAL(symbolP) :
1407 S_CLEAR_EXTERNAL(symbolP);
1408 #endif /* OBJ_AOUT or OBJ_BOUT */
1409 S_SET_VALUE(symbolP, 0);
1410 symbolP->sy_frag = & zero_address_frag;
1413 case SEG_DIFFERENCE:
1414 if (exp.X_add_symbol && exp.X_subtract_symbol
1415 && (S_GET_SEGMENT(exp.X_add_symbol) ==
1416 S_GET_SEGMENT(exp.X_subtract_symbol))) {
1417 if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) {
1418 as_bad("Unknown expression: symbols %s and %s are in different frags.",
1419 S_GET_NAME(exp.X_add_symbol), S_GET_NAME(exp.X_subtract_symbol));
1422 exp.X_add_number+=S_GET_VALUE(exp.X_add_symbol) -
1423 S_GET_VALUE(exp.X_subtract_symbol);
1425 as_bad("Complex expression. Absolute segment assumed.");
1427 S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
1428 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1429 ext ? S_SET_EXTERNAL(symbolP) :
1430 S_CLEAR_EXTERNAL(symbolP);
1431 #endif /* OBJ_AOUT or OBJ_BOUT */
1432 S_SET_VALUE(symbolP, exp.X_add_number);
1433 symbolP->sy_frag = & zero_address_frag;
1437 know(SEG_NORMAL(segment));
1438 S_SET_SEGMENT(symbolP, segment);
1439 #if defined(OBJ_AOUT) | defined(OBJ_BOUT)
1441 S_SET_EXTERNAL(symbolP);
1443 S_CLEAR_EXTERNAL(symbolP);
1445 #endif /* OBJ_AOUT or OBJ_BOUT */
1447 S_SET_VALUE(symbolP, exp.X_add_number + S_GET_VALUE(exp.X_add_symbol));
1448 symbolP->sy_frag = exp.X_add_symbol->sy_frag;
1449 symbolP->sy_aux = exp.X_add_symbol->sy_aux;
1452 case SEG_PASS1: /* Not an error. Just try another pass. */
1453 symbolP->sy_forward=exp.X_add_symbol;
1454 as_bad("Unknown expression");
1455 know(need_pass_2 == 1);
1459 symbolP->sy_forward=exp.X_add_symbol;
1460 /* as_warn("unknown symbol"); */
1461 /* need_pass_2 = 1; */
1472 * CONStruct more frag of .bytes, or .words etc.
1473 * Should need_pass_2 be 1 then emit no frag(s).
1474 * This understands EXPRESSIONS, as opposed to big_cons().
1478 * This has a split personality. We use expression() to read the
1479 * value. We can detect if the value won't fit in a byte or word.
1480 * But we can't detect if expression() discarded significant digits
1481 * in the case of a long. Not worth the crocks required to fix it.
1484 /* worker to do .byte etc statements */
1485 /* clobbers input_line_pointer, checks */
1488 register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */
1491 register long mask; /* High-order bits we will left-truncate, */
1492 /* but includes sign bit also. */
1493 register long get; /* what we get */
1494 register long use; /* get after truncation. */
1495 register long unmask; /* what bits we will store */
1497 register segT segment;
1501 * Input_line_pointer->1st char after pseudo-op-code and could legally
1502 * be a end-of-line. (Or, less legally an eof - which we cope with.)
1504 /* JF << of >= number of bits in the object is undefined. In particular
1505 SPARC (Sun 4) has problems */
1507 if (nbytes >= sizeof(long)) {
1510 mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
1511 } /* bigger than a long */
1513 unmask = ~mask; /* Do store these bits. */
1516 "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
1517 mask = ~ (unmask >> 1); /* Includes sign bit now. */
1521 * The following awkward logic is to parse ZERO or more expressions,
1522 * comma seperated. Recall an expression includes its leading &
1523 * trailing blanks. We fake a leading ',' if there is (supposed to
1524 * be) a 1st expression, and keep demanding 1 expression for each ','.
1526 if (is_it_end_of_statement()) {
1527 c = 0; /* Skip loop. */
1528 input_line_pointer++; /* Matches end-of-loop 'correction'. */
1531 } /* if the end else fake it */
1535 #ifdef WANT_BITFIELDS
1536 unsigned int bits_available = BITS_PER_CHAR * nbytes;
1537 /* used for error messages and rescanning */
1538 char *hold = input_line_pointer;
1539 #endif /* WANT_BITFIELDS */
1541 /* At least scan over the expression. */
1542 segment = expression(&exp);
1544 #ifdef WANT_BITFIELDS
1545 /* Some other assemblers, (eg, asm960), allow
1546 bitfields after ".byte" as w:x,y:z, where w and
1547 y are bitwidths and x and y are values. They
1548 then pack them all together. We do a little
1549 better in that we allow them in words, longs,
1550 etc. and we'll pack them in target byte order
1553 The rules are: pack least significat bit first,
1554 if a field doesn't entirely fit, put it in the
1555 next unit. Overflowing the bitfield is
1556 explicitly *not* even a warning. The bitwidth
1557 should be considered a "mask".
1559 FIXME-SOMEDAY: If this is considered generally
1560 useful, this logic should probably be reworked.
1563 if (*input_line_pointer == ':') { /* bitfields */
1567 unsigned long width;
1569 if (*input_line_pointer != ':') {
1570 input_line_pointer = hold;
1572 } /* next piece is not a bitfield */
1574 /* In the general case, we can't allow
1575 full expressions with symbol
1576 differences and such. The relocation
1577 entries for symbols not defined in this
1578 assembly would require arbitrary field
1579 widths, positions, and masks which most
1580 of our current object formats don't
1583 In the specific case where a symbol
1584 *is* defined in this assembly, we
1585 *could* build fixups and track it, but
1586 this could lead to confusion for the
1587 backends. I'm lazy. I'll take any
1588 SEG_ABSOLUTE. I think that means that
1589 you can use a previous .set or
1590 .equ type symbol. xoxorich. */
1592 if (segment == SEG_ABSENT) {
1593 as_warn("Using a bit field width of zero.");
1594 exp.X_add_number = 0;
1595 segment = SEG_ABSOLUTE;
1596 } /* implied zero width bitfield */
1598 if (segment != SEG_ABSOLUTE) {
1599 *input_line_pointer = '\0';
1600 as_bad("Field width \"%s\" too complex for a bitfield.\n", hold);
1601 *input_line_pointer = ':';
1602 demand_empty_rest_of_line();
1606 if ((width = exp.X_add_number) > (BITS_PER_CHAR * nbytes)) {
1607 as_warn("Field width %d too big to fit in %d bytes: truncated to %d bits.",
1608 width, nbytes, (BITS_PER_CHAR * nbytes));
1609 width = BITS_PER_CHAR * nbytes;
1612 if (width > bits_available) {
1613 /* FIXME-SOMEDAY: backing up and
1614 reparsing is wasteful */
1615 input_line_pointer = hold;
1616 exp.X_add_number = value;
1620 hold = ++input_line_pointer; /* skip ':' */
1622 if ((segment = expression(&exp)) != SEG_ABSOLUTE) {
1623 char cache = *input_line_pointer;
1625 *input_line_pointer = '\0';
1626 as_bad("Field value \"%s\" too complex for a bitfield.\n", hold);
1627 *input_line_pointer = cache;
1628 demand_empty_rest_of_line();
1632 value |= (~(-1 << width) & exp.X_add_number)
1633 << ((BITS_PER_CHAR * nbytes) - bits_available);
1635 if ((bits_available -= width) == 0
1636 || is_it_end_of_statement()
1637 || *input_line_pointer != ',') {
1639 } /* all the bitfields we're gonna get */
1641 hold = ++input_line_pointer;
1642 segment = expression(&exp);
1643 } /* forever loop */
1645 exp.X_add_number = value;
1646 segment = SEG_ABSOLUTE;
1647 } /* if looks like a bitfield */
1648 #endif /* WANT_BITFIELDS */
1650 if (!need_pass_2) { /* Still worthwhile making frags. */
1652 /* Don't call this if we are going to junk this pass anyway! */
1653 know(segment != SEG_PASS1);
1655 if (segment == SEG_DIFFERENCE && exp.X_add_symbol == NULL) {
1656 as_bad("Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
1657 S_GET_NAME(exp.X_subtract_symbol),
1658 segment_name(S_GET_SEGMENT(exp.X_subtract_symbol)));
1659 segment = SEG_ABSOLUTE;
1660 /* Leave exp.X_add_number alone. */
1663 p = frag_more(nbytes);
1667 as_bad("%s number invalid. Absolute 0 assumed.",
1668 exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
1669 md_number_to_chars (p, (long)0, nbytes);
1673 as_warn("0 assumed for missing expression");
1674 exp.X_add_number = 0;
1675 know(exp.X_add_symbol == NULL);
1676 /* fall into SEG_ABSOLUTE */
1678 get = exp.X_add_number;
1680 if ((get & mask) && (get & mask) != mask)
1681 { /* Leading bits contain both 0s & 1s. */
1682 as_warn("Value 0x%x truncated to 0x%x.", get, use);
1684 md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
1687 case SEG_DIFFERENCE:
1688 #ifndef WORKING_DOT_WORD
1690 struct broken_word *x;
1692 x = (struct broken_word *) xmalloc(sizeof(struct broken_word));
1693 x->next_broken_word = broken_words;
1696 x->word_goes_here = p;
1698 x->add = exp.X_add_symbol;
1699 x->sub = exp.X_subtract_symbol;
1700 x->addnum = exp.X_add_number;
1705 /* Else Fall through into... */
1710 fix_new_ns32k(frag_now, p - frag_now->fr_literal, nbytes,
1711 exp.X_add_symbol, exp.X_subtract_symbol,
1712 exp.X_add_number, 0, 0, 2, 0, 0, RELOC_32);
1715 fix_new(frag_now, p - frag_now->fr_literal, nbytes,
1716 exp.X_add_symbol, exp.X_subtract_symbol,
1717 exp.X_add_number, 0, RELOC_32,
1720 fix_new(frag_now, p - frag_now->fr_literal, nbytes,
1721 exp.X_add_symbol, exp.X_subtract_symbol,
1722 exp.X_add_number, 0, RELOC_32);
1724 #endif /* TC_NS32K */
1726 } /* switch (segment) */
1727 } /* if (!need_pass_2) */
1728 c = *input_line_pointer++;
1729 } /* while (c == ',') */
1730 input_line_pointer--; /* Put terminator back into stream. */
1731 demand_empty_rest_of_line();
1737 * CONStruct more frag(s) of .quads, or .octa etc.
1738 * Makes 0 or more new frags.
1739 * If need_pass_2 == 1, generate no frag.
1740 * This understands only bignums, not expressions. Cons() understands
1743 * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
1745 * This creates objects with struct obstack_control objs, destroying
1746 * any context objs held about a partially completed object. Beware!
1749 * I think it sucks to have 2 different types of integers, with 2
1750 * routines to read them, store them etc.
1751 * It would be nicer to permit bignums in expressions and only
1752 * complain if the result overflowed. However, due to "efficiency"...
1754 /* worker to do .quad etc statements */
1755 /* clobbers input_line_pointer, checks */
1757 /* 8=.quad 16=.octa ... */
1759 void big_cons(nbytes)
1760 register int nbytes;
1762 register char c; /* input_line_pointer->c. */
1764 register long length; /* Number of chars in an object. */
1765 register int digit; /* Value of 1 digit. */
1766 register int carry; /* For multi-precision arithmetic. */
1767 register int work; /* For multi-precision arithmetic. */
1768 register char * p; /* For multi-precision arithmetic. */
1770 extern const char hex_value[]; /* In hex_value.c. */
1773 * The following awkward logic is to parse ZERO or more strings,
1774 * comma seperated. Recall an expression includes its leading &
1775 * trailing blanks. We fake a leading ',' if there is (supposed to
1776 * be) a 1st expression, and keep demanding 1 expression for each ','.
1778 if (is_it_end_of_statement())
1780 c = 0; /* Skip loop. */
1784 c = ','; /* Do loop. */
1785 -- input_line_pointer;
1789 ++ input_line_pointer;
1791 c = * input_line_pointer;
1792 /* C contains 1st non-blank character of what we hope is a number. */
1795 c = * ++ input_line_pointer;
1796 if (c == 'x' || c == 'X')
1798 c = * ++ input_line_pointer;
1811 * This feature (?) is here to stop people worrying about
1812 * mysterious zero constants: which is what they get when
1813 * they completely omit digits.
1815 if (hex_value[c] >= radix) {
1816 as_bad("Missing digits. 0 assumed.");
1818 bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
1819 for (; (digit = hex_value[c]) < radix; c = *++input_line_pointer)
1821 /* Multiply existing number by radix, then add digit. */
1823 for (p=bignum_low; p <= bignum_high; p++)
1825 work = (*p & MASK_CHAR) * radix + carry;
1826 *p = work & MASK_CHAR;
1827 carry = work >> BITS_PER_CHAR;
1832 * bignum_high = carry & MASK_CHAR;
1833 know((carry & ~ MASK_CHAR) == 0);
1836 length = bignum_high - bignum_low + 1;
1837 if (length > nbytes)
1839 as_warn("Most significant bits truncated in integer constant.");
1843 register long leading_zeroes;
1845 for (leading_zeroes = nbytes - length;
1855 p = frag_more (nbytes);
1856 memcpy(p, bignum_low, (int) nbytes);
1858 /* C contains character after number. */
1860 c = *input_line_pointer;
1861 /* C contains 1st non-blank character after number. */
1863 demand_empty_rest_of_line();
1866 /* Extend bignum by 1 char. */
1867 static void grow_bignum() {
1868 register long length;
1871 if (bignum_high >= bignum_limit)
1873 length = bignum_limit - bignum_low;
1874 bignum_low = xrealloc(bignum_low, length + length);
1875 bignum_high = bignum_low + length;
1876 bignum_limit = bignum_low + length + length;
1878 } /* grow_bignum(); */
1883 * CONStruct some more frag chars of .floats .ffloats etc.
1884 * Makes 0 or more new frags.
1885 * If need_pass_2 == 1, no frags are emitted.
1886 * This understands only floating literals, not expressions. Sorry.
1888 * A floating constant is defined by atof_generic(), except it is preceded
1889 * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
1890 * reading, I decided to be incompatible. This always tries to give you
1891 * rounded bits to the precision of the pseudo-op. Former AS did premature
1892 * truncatation, restored noisy bits instead of trailing 0s AND gave you
1893 * a choice of 2 flavours of noise according to which of 2 floating-point
1894 * scanners you directed AS to use.
1896 * In: input_line_pointer->whitespace before, or '0' of flonum.
1900 void /* JF was static, but can't be if VAX.C is goning to use it */
1901 float_cons(float_type) /* Worker to do .float etc statements. */
1902 /* Clobbers input_line-pointer, checks end-of-line. */
1903 register int float_type; /* 'f':.ffloat ... 'F':.float ... */
1907 int length; /* Number of chars in an object. */
1908 register char * err; /* Error from scanning floating literal. */
1909 char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
1912 * The following awkward logic is to parse ZERO or more strings,
1913 * comma seperated. Recall an expression includes its leading &
1914 * trailing blanks. We fake a leading ',' if there is (supposed to
1915 * be) a 1st expression, and keep demanding 1 expression for each ','.
1917 if (is_it_end_of_statement())
1919 c = 0; /* Skip loop. */
1920 ++ input_line_pointer; /*->past termintor. */
1924 c = ','; /* Do loop. */
1927 /* input_line_pointer->1st char of a flonum (we hope!). */
1929 /* Skip any 0{letter} that may be present. Don't even check if the
1930 * letter is legal. Someone may invent a "z" format and this routine
1931 * has no use for such information. Lusers beware: you get
1932 * diagnostics if your input is ill-conditioned.
1935 if (input_line_pointer[0] == '0' && isalpha(input_line_pointer[1]))
1936 input_line_pointer+=2;
1938 err = md_atof (float_type, temp, &length);
1939 know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
1942 as_bad("Bad floating literal: %s", err);
1943 ignore_rest_of_line();
1944 /* Input_line_pointer->just after end-of-line. */
1945 c = 0; /* Break out of loop. */
1947 if (! need_pass_2) {
1948 p = frag_more (length);
1949 memcpy(p, temp, length);
1952 c = *input_line_pointer++;
1953 /* C contains 1st non-white character after number. */
1954 /* input_line_pointer->just after terminator (c). */
1957 --input_line_pointer; /*->terminator (is not ','). */
1958 demand_empty_rest_of_line();
1959 } /* float_cons() */
1962 * stringer() Worker to do .ascii etc statements. Checks end-of-line.
1964 * We read 0 or more ',' seperated, double-quoted strings.
1966 * Caller should have checked need_pass_2 is FALSE because we don't check it.
1969 void stringer(append_zero)
1970 int append_zero; /* 0: don't append '\0', else 1 */
1975 * The following awkward logic is to parse ZERO or more strings,
1976 * comma seperated. Recall a string expression includes spaces
1977 * before the opening '\"' and spaces after the closing '\"'.
1978 * We fake a leading ',' if there is (supposed to be)
1979 * a 1st, expression. We keep demanding expressions for each
1982 if (is_it_end_of_statement()) {
1983 c = 0; /* Skip loop. */
1984 ++ input_line_pointer; /* Compensate for end of loop. */
1986 c = ','; /* Do loop. */
1989 while (c == ',' || c == '<' || c == '"' || ('0' <= c && c <= '9')) {
1993 switch (*input_line_pointer) {
1995 ++input_line_pointer; /* ->1st char of string. */
1996 while (is_a_char(c = next_char_of_string())) {
1997 FRAG_APPEND_1_CHAR(c);
2000 FRAG_APPEND_1_CHAR(0);
2002 know(input_line_pointer[-1] == '\"');
2006 input_line_pointer++;
2007 c = get_single_number();
2008 FRAG_APPEND_1_CHAR(c);
2009 if (*input_line_pointer != '>') {
2010 as_bad("Expected <nn>");
2012 input_line_pointer++;
2016 input_line_pointer++;
2020 i = get_absolute_expression();
2021 FRAG_APPEND_1_CHAR(i);
2023 } /* switch on next char */
2026 c = *input_line_pointer;
2029 demand_empty_rest_of_line();
2032 /* FIXME-SOMEDAY: I had trouble here on characters with the
2033 high bits set. We'll probably also have trouble with
2034 multibyte chars, wide chars, etc. Also be careful about
2035 returning values bigger than 1 byte. xoxorich. */
2037 unsigned int next_char_of_string() {
2038 register unsigned int c;
2040 c = *input_line_pointer++ & CHAR_MASK;
2047 switch (c = *input_line_pointer++) {
2076 break; /* As itself. */
2090 for (number = 0; isdigit(c); c = *input_line_pointer++) {
2091 number = number * 8 + c - '0';
2095 --input_line_pointer;
2099 /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
2100 as_warn("Unterminated string: Newline inserted.");
2106 #ifdef ONLY_STANDARD_ESCAPES
2107 as_bad("Bad escaped character in string, '?' assumed");
2109 #endif /* ONLY_STANDARD_ESCAPES */
2112 } /* switch on escaped char */
2117 } /* switch on char */
2119 } /* next_char_of_string() */
2122 get_segmented_expression (expP)
2123 register expressionS * expP;
2125 register segT retval;
2127 if ((retval = expression(expP)) == SEG_PASS1 || retval == SEG_ABSENT || retval == SEG_BIG)
2129 as_bad("Expected address expression: absolute 0 assumed");
2130 retval = expP->X_seg = SEG_ABSOLUTE;
2131 expP->X_add_number = 0;
2132 expP->X_add_symbol = expP->X_subtract_symbol = 0;
2134 return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
2137 static segT get_known_segmented_expression(expP)
2138 register expressionS *expP;
2140 register segT retval;
2141 register char * name1;
2142 register char * name2;
2144 if ((retval = get_segmented_expression (expP)) == SEG_UNKNOWN)
2146 name1 = expP->X_add_symbol ? S_GET_NAME(expP->X_add_symbol) : "";
2147 name2 = expP->X_subtract_symbol ?
2148 S_GET_NAME(expP->X_subtract_symbol) :
2152 as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
2157 as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
2158 name1 ? name1 : name2);
2160 retval = expP->X_seg = SEG_ABSOLUTE;
2161 expP->X_add_number = 0;
2162 expP->X_add_symbol = expP->X_subtract_symbol = NULL;
2164 #ifndef MANY_SEGMENTS
2165 know(retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE);
2169 } /* get_known_segmented_expression() */
2173 /* static */ long /* JF was static, but can't be if the MD pseudos are to use it */
2174 get_absolute_expression()
2179 if ((s = expression(&exp)) != SEG_ABSOLUTE) {
2180 if (s != SEG_ABSENT) {
2181 as_bad("Bad Absolute Expression, absolute 0 assumed.");
2183 exp.X_add_number = 0;
2185 return(exp.X_add_number);
2186 } /* get_absolute_expression() */
2188 char /* return terminator */
2189 get_absolute_expression_and_terminator(val_pointer)
2190 long * val_pointer; /* return value of expression */
2192 *val_pointer = get_absolute_expression();
2193 return (*input_line_pointer++);
2197 * demand_copy_C_string()
2199 * Like demand_copy_string, but return NULL if the string contains any '\0's.
2200 * Give a warning if that happens.
2203 demand_copy_C_string (len_pointer)
2208 if ((s = demand_copy_string(len_pointer)) != 0) {
2211 for (len = *len_pointer;
2218 as_bad("This string may not contain \'\\0\'");
2226 * demand_copy_string()
2228 * Demand string, but return a safe (=private) copy of the string.
2229 * Return NULL if we can't read a string here.
2231 static char *demand_copy_string(lenP)
2234 register unsigned int c;
2240 if (*input_line_pointer == '\"') {
2241 input_line_pointer++; /* Skip opening quote. */
2243 while (is_a_char(c = next_char_of_string())) {
2244 obstack_1grow(¬es, c);
2247 /* JF this next line is so demand_copy_C_string will return a null
2248 termanated string. */
2249 obstack_1grow(¬es,'\0');
2250 retval=obstack_finish(¬es);
2252 as_warn("Missing string");
2254 ignore_rest_of_line();
2258 } /* demand_copy_string() */
2261 * is_it_end_of_statement()
2263 * In: Input_line_pointer->next character.
2265 * Do: Skip input_line_pointer over all whitespace.
2267 * Out: 1 if input_line_pointer->end-of-line.
2269 int is_it_end_of_statement() {
2271 return(is_end_of_line[*input_line_pointer]);
2272 } /* is_it_end_of_statement() */
2274 void equals(sym_name)
2277 register symbolS *symbolP; /* symbol we are working with */
2279 input_line_pointer++;
2280 if (*input_line_pointer == '=')
2281 input_line_pointer++;
2283 while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
2284 input_line_pointer++;
2286 if (sym_name[0] == '.' && sym_name[1] == '\0') {
2287 /* Turn '. = mumble' into a .org mumble */
2288 register segT segment;
2292 segment = get_known_segmented_expression(& exp);
2293 if (! need_pass_2) {
2294 if (segment != now_seg && segment != SEG_ABSOLUTE)
2295 as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
2296 segment_name(segment),
2297 segment_name(now_seg));
2298 p = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
2299 exp.X_add_number, (char *)0);
2301 } /* if (ok to make frag) */
2303 symbolP=symbol_find_or_make(sym_name);
2304 pseudo_set(symbolP);
2308 /* .include -- include a file at this point. */
2320 filename = demand_copy_string(&i);
2321 demand_empty_rest_of_line();
2322 path = xmalloc(i + include_dir_maxlen + 5 /* slop */);
2323 for (i = 0; i < include_dir_count; i++) {
2324 strcpy(path, include_dirs[i]);
2326 strcat(path, filename);
2327 if (0 != (try = fopen(path, "r")))
2336 /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
2337 newbuf = input_scrub_include_file (path, input_line_pointer);
2338 buffer_limit = input_scrub_next_buffer (&input_line_pointer);
2341 void add_include_dir(path)
2346 if (include_dir_count == 0)
2348 include_dirs = (char **)xmalloc (2 * sizeof (*include_dirs));
2349 include_dirs[0] = "."; /* Current dir */
2350 include_dir_count = 2;
2354 include_dir_count++;
2355 include_dirs = (char **) realloc(include_dirs,
2356 include_dir_count*sizeof (*include_dirs));
2359 include_dirs[include_dir_count-1] = path; /* New one */
2362 if (i > include_dir_maxlen)
2363 include_dir_maxlen = i;
2364 } /* add_include_dir() */
2369 while (!is_end_of_line[*input_line_pointer]) {
2370 ++input_line_pointer;
2372 ++input_line_pointer;