diff options
author | Steve Chamberlain <sac@cygnus> | 1992-06-04 19:21:58 +0000 |
---|---|---|
committer | Steve Chamberlain <sac@cygnus> | 1992-06-04 19:21:58 +0000 |
commit | f8701a3ff892202ea34e9a721c66f8dab62f5c7c (patch) | |
tree | d92b8743afc7dc3186763528fe62e99dd43bd8ca /gas/read.c | |
parent | f4a0f42d8ae83b302641b74c3dea1912964e0145 (diff) | |
download | fsf-binutils-gdb-f8701a3ff892202ea34e9a721c66f8dab62f5c7c.zip fsf-binutils-gdb-f8701a3ff892202ea34e9a721c66f8dab62f5c7c.tar.gz fsf-binutils-gdb-f8701a3ff892202ea34e9a721c66f8dab62f5c7c.tar.bz2 |
Thu Jun 4 11:59:13 1992 Steve Chamberlain (sac@thepub.cygnus.com)
* expr.c(expr): allow SEG_REGISTER in expressions.
* read.c(pseudo_set): register expressions can be the source of a
set.
* subsegs.c (subseg_new): Now -R forces all changes to SEG_DATA to
goto SEG_TEXT (if a.out)
* write.c (write_object_file): If a.out don't use the old way for
-R.
* config/obj-a.out (s_sect): complain if the user tries to use a
subsegment with a value which might interfere with out -R hackery.
* config/tc-m68k.c (m68k_reg_parse): lookup names in symbol table
rather than use ugly if tree. (init_regtable): insert register
names into symbol table.
Diffstat (limited to 'gas/read.c')
-rw-r--r-- | gas/read.c | 2744 |
1 files changed, 1479 insertions, 1265 deletions
@@ -1,22 +1,21 @@ /* read.c - read a source file - + Copyright (C) 1986, 1987, 1990, 1991 Free Software Foundation, Inc. - Copyright (C) 1986, 1987, 1990, 1991, 1992 Free Software Foundation, Inc. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +This file is part of GAS, the GNU Assembler. + +GAS is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GAS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will change this a bit. But then, GNU isn't @@ -25,9 +24,9 @@ */ #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) -/* This is the largest known floating point */ -/* format (for now). It will grow when we */ -/* do 4361 style flonums. */ + /* This is the largest known floating point */ + /* format (for now). It will grow when we */ + /* do 4361 style flonums. */ /* Routines that read assembler source text to build spagetti in memory. */ @@ -36,36 +35,33 @@ #include "as.h" #include "obstack.h" - +#include "listing.h" char *input_line_pointer; /*->next char of source file to parse. */ -#ifndef NOP_OPCODE -# define NOP_OPCODE 0x00 -#endif #if BITS_PER_CHAR != 8 The following table is indexed by [ (char) ] and will break if - a char does not have exactly 256 states (hopefully 0:255!) ! +a char does not have exactly 256 states (hopefully 0:255!) ! #endif - - const char /* used by is_... macros. our ctype[] */ - lex_type [256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ - 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */ - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + +const char /* used by is_... macros. our ctype[] */ +lex_type [256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */ + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; /* @@ -75,26 +71,26 @@ The following table is indexed by [ (char) ] and will break if #define _ (0) char is_end_of_line [256] = { #ifdef CR_EOL - _, _, _, _, _, _, _, _, _, _,99, _, _, 99, _, _,/* @abcdefghijklmno */ + _, _, _, _, _, _, _, _, _, _,99, _, _, 99, _, _,/* @abcdefghijklmno */ #else - _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */ + _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */ #endif - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */ - }; + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */ +}; #undef _ -/* Functions private to this file. */ + /* Functions private to this file. */ char line_comment_chars[1]; char line_separator_chars[1]; @@ -105,8 +101,8 @@ static char *buffer_limit; /*->1 + last char in buffer. */ static char *bignum_low; /* Lowest char of bignum. */ static char *bignum_limit; /* 1st illegal address of bignum. */ static char *bignum_high; /* Highest char of bignum. */ -/* May point to (bignum_start-1). */ -/* Never >= bignum_limit. */ + /* May point to (bignum_start-1). */ + /* Never >= bignum_limit. */ static char *old_buffer = 0; /* JF a hack */ static char *old_input; static char *old_limit; @@ -123,7 +119,7 @@ struct broken_word *broken_words; int new_broken_words = 0; #endif -#if __STDC__ == 1 +#ifdef __STDC__ static char *demand_copy_string(int *lenP); int is_it_end_of_statement(void); @@ -131,7 +127,7 @@ unsigned int next_char_of_string(void); static segT get_known_segmented_expression(expressionS *expP); static void grow_bignum(void); static void pobegin(void); -void stringer(int append_zero); + void stringer(int append_zero); #else /* __STDC__ */ @@ -141,138 +137,125 @@ unsigned int next_char_of_string(); static segT get_known_segmented_expression(); static void grow_bignum(); static void pobegin(); -void stringer(); + void stringer(); -#endif /* not __STDC__ */ +#endif /* __STDC__ */ extern int listing; void - read_begin() +read_begin() { - char *p; - - pobegin(); - obj_read_begin_hook(); - - obstack_begin(¬es, 5000); - obstack_begin(&cond_obstack, 960); - + char *p; + + pobegin(); + obj_read_begin_hook(); + + obstack_begin(¬es, 5000); + obstack_begin(&cond_obstack, 960); + #define BIGNUM_BEGIN_SIZE (16) - bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE); - bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE; - - /* Use machine dependent syntax */ - for (p = line_separator_chars; *p; p++) - is_end_of_line[*p] = 1; - /* Use more. FIXME-SOMEDAY. */ + bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE); + bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE; + + /* Use machine dependent syntax */ + for (p = line_separator_chars; *p; p++) + is_end_of_line[*p] = 1; + /* Use more. FIXME-SOMEDAY. */ } /* set up pseudo-op tables */ struct hash_control * - po_hash = NULL; /* use before set up: NULL->address error */ +po_hash = NULL; /* use before set up: NULL->address error */ + +#ifdef DONTDEF +void s_gdbline(), s_gdblinetab(); +void s_gdbbeg(), s_gdbblock(), s_gdbend(), s_gdbsym(); +#endif static const pseudo_typeS - potable[] = +potable[] = { - { "abort", s_abort, 0 }, - { "align", s_align_ptwo, 0 }, - { "ascii", stringer, 0 }, - { "asciz", stringer, 1 }, - /* block */ - { "byte", cons, 1 }, - { "bss", s_bss, 0 }, - { "comm", s_comm, 0 }, - { "data", s_data, 0 }, - /* dim */ - { "double", float_cons, 'd' }, - /* dsect */ -#ifdef NO_LISTING - { "eject", s_ignore, 0 }, /* Formfeed listing */ -#else - { "eject", listing_eject, 0 }, /* Formfeed listing */ -#endif /* NO_LISTING */ - { "else", s_else, 0 }, - { "end", s_end, 0 }, - { "endif", s_endif, 0 }, - /* endef */ - { "equ", s_set, 0 }, - /* err */ - /* extend */ - { "extern", s_ignore, 0 }, /* We treat all undef as ext */ - { "app-file", s_app_file, 0 }, - { "file", s_app_file, 0 }, - { "fill", s_fill, 0 }, - { "float", float_cons, 'f' }, - { "global", s_globl, 0 }, - { "globl", s_globl, 0 }, - { "hword", cons, 2 }, - { "if", s_if, 0 }, - { "ifdef", s_ifdef, 0 }, - { "ifeqs", s_ifeqs, 0 }, - { "ifndef", s_ifdef, 1 }, - { "ifnes", s_ifeqs, 1 }, - { "ifnotdef", s_ifdef, 1 }, - { "include", s_include, 0 }, - { "int", cons, 4 }, - { "lcomm", s_lcomm, 0 }, -#ifdef NO_LISTING - { "lflags", s_ignore, 0 }, /* Listing flags */ - { "list", s_ignore, 1 }, /* Turn listing on */ -#else - { "lflags", listing_flags, 0 }, /* Listing flags */ - { "list", listing_list, 1 }, /* Turn listing on */ -#endif /* NO_LISTING */ - { "long", cons, 4 }, - { "lsym", s_lsym, 0 }, -#ifdef NO_LISTING - { "nolist", s_ignore, 0 }, /* Turn listing off */ -#else - { "nolist", listing_list, 0 }, /* Turn listing off */ -#endif /* NO_LISTING */ - { "octa", big_cons, 16 }, - { "org", s_org, 0 }, -#ifdef NO_LISTING - { "psize", s_ignore, 0 }, /* set paper size */ -#else - { "psize", listing_psize, 0 }, /* set paper size */ -#endif /* NO_LISTING */ - /* print */ - { "quad", big_cons, 8 }, -#ifdef NO_LISTING - { "sbttl", s_ignore, 1 }, /* Subtitle of listing */ -#else - { "sbttl", listing_title, 1 }, /* Subtitle of listing */ -#endif /* NO_LISTING */ - /* scl */ - /* sect */ - { "set", s_set, 0 }, - { "short", cons, 2 }, - { "single", float_cons, 'f' }, - /* size */ - { "space", s_space, 0 }, - /* tag */ - { "text", s_text, 0 }, -#ifdef NO_LISTING - { "title", s_ignore, 0 }, /* Listing title */ -#else - { "title", listing_title, 0 }, /* Listing title */ -#endif /* NO_LISTING */ - /* type */ - /* use */ - /* val */ - { "word", cons, 2 }, - { NULL} /* end sentinel */ + { "abort", s_abort, 0 }, + { "align", s_align_ptwo, 0 }, + { "ascii", stringer, 0 }, + { "asciz", stringer, 1 }, +/* block */ + { "byte", cons, 1 }, + { "comm", s_comm, 0 }, + { "data", s_data, 0 }, +/* dim */ + { "double", float_cons, 'd' }, +/* dsect */ + { "eject", listing_eject, 0 }, /* Formfeed listing */ + { "else", s_else, 0 }, + { "end", s_end, 0 }, + { "endif", s_endif, 0 }, +/* endef */ + { "equ", s_set, 0 }, +/* err */ +/* extend */ + { "extern", s_ignore, 0 }, /* We treat all undef as ext */ + { "app-file", s_app_file, 0 }, + { "file", s_app_file, 0 }, + { "fill", s_fill, 0 }, + { "float", float_cons, 'f' }, +#ifdef DONTDEF + { "gdbbeg", s_gdbbeg, 0 }, + { "gdbblock", s_gdbblock, 0 }, + { "gdbend", s_gdbend, 0 }, + { "gdbsym", s_gdbsym, 0 }, + { "gdbline", s_gdbline, 0 }, + { "gdblinetab",s_gdblinetab, 0 }, +#endif + { "global", s_globl, 0 }, + { "globl", s_globl, 0 }, + { "hword", cons, 2 }, + { "if", s_if, 0 }, + { "ifdef", s_ifdef, 0 }, + { "ifeqs", s_ifeqs, 0 }, + { "ifndef", s_ifdef, 1 }, + { "ifnes", s_ifeqs, 1 }, + { "ifnotdef", s_ifdef, 1 }, + { "include", s_include, 0 }, + { "int", cons, 4 }, + { "lcomm", s_lcomm, 0 }, + { "lflags", listing_flags, 0 }, /* Listing flags */ + { "list", listing_list, 1 }, /* Turn listing on */ + { "long", cons, 4 }, + { "lsym", s_lsym, 0 }, + { "nolist", listing_list, 0 }, /* Turn listing off */ + { "octa", big_cons, 16 }, + { "org", s_org, 0 }, + { "psize", listing_psize, 0 }, /* set paper size */ +/* print */ + { "quad", big_cons, 8 }, + { "sbttl", listing_title, 1 }, /* Subtitle of listing */ +/* scl */ +/* sect */ + { "set", s_set, 0 }, + { "short", cons, 2 }, + { "single", float_cons, 'f' }, +/* size */ + { "space", s_space, 0 }, +/* tag */ + { "text", s_text, 0 }, + { "title", listing_title, 0 }, /* Listing title */ +/* type */ +/* use */ +/* val */ + { "word", cons, 2 }, + { NULL} /* end sentinel */ }; static void pobegin() { char *errtxt; /* error text */ const pseudo_typeS * pop; - + po_hash = hash_new(); - + /* Do the target-specific pseudo ops. */ for (pop = md_pseudo_table; pop->poc_name; pop++) { errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop); @@ -280,7 +263,7 @@ static void pobegin() { as_fatal("error constructing md pseudo-op table"); } /* on error */ } /* for each op */ - + /* Now object specific. Skip any that were in the target table. */ for (pop=obj_pseudo_table; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); @@ -295,7 +278,7 @@ static void pobegin() { } /* if overridden */ } /* on error */ } /* for each op */ - + /* Now portable ones. Skip any that we've seen already. */ for (pop=potable; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); @@ -310,18 +293,18 @@ static void pobegin() { } /* if overridden */ } /* on error */ } /* for each op */ - + return; } /* pobegin() */ #define HANDLE_CONDITIONAL_ASSEMBLY() \ - if (ignore_input ()) \ -{ \ - while (! is_end_of_line[*input_line_pointer++]) \ - if (input_line_pointer == buffer_limit) \ - break; \ - continue; \ - } + if (ignore_input ()) \ + { \ + while (! is_end_of_line[*input_line_pointer++]) \ + if (input_line_pointer == buffer_limit) \ + break; \ + continue; \ + } /* read_a_source_file() @@ -332,264 +315,315 @@ static void pobegin() { void read_a_source_file(name) char *name; { - register char c; - register char * s; /* string of symbol, '\0' appended */ - register int temp; - /* register struct frag * fragP; JF unused */ /* a frag we just made */ - pseudo_typeS *pop; - - buffer = input_scrub_new_file(name); - - listing_file(name); - listing_newline(""); - - while ((buffer_limit = input_scrub_next_buffer(&input_line_pointer)) != 0) { /* We have another line to parse. */ - know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */ - contin: /* JF this goto is my fault I admit it. Someone brave please re-write - the whole input section here? Pleeze??? */ - while (input_line_pointer < buffer_limit) { /* We have more of this buffer to parse. */ - - /* - * We now have input_line_pointer->1st char of next line. - * If input_line_pointer [-1] == '\n' then we just - * scanned another line: so bump line counters. - */ - if (input_line_pointer[-1] == '\n') { - bump_line_counters(); - } /* just passed a newline */ - - + register char c; + register char * s; /* string of symbol, '\0' appended */ + register int temp; + /* register struct frag * fragP; JF unused */ /* a frag we just made */ + pseudo_typeS *pop; +#ifdef DONTDEF + void gdb_block_beg(); + void gdb_block_position(); + void gdb_block_end(); + void gdb_symbols_fixup(); +#endif + + buffer = input_scrub_new_file(name); + + listing_file(name); + listing_newline(""); + + while ((buffer_limit = input_scrub_next_buffer(&input_line_pointer)) != 0) { /* We have another line to parse. */ + know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */ + contin: /* JF this goto is my fault I admit it. Someone brave please re-write + the whole input section here? Pleeze??? */ + while (input_line_pointer < buffer_limit) { /* We have more of this buffer to parse. */ + + /* + * We now have input_line_pointer->1st char of next line. + * If input_line_pointer [-1] == '\n' then we just + * scanned another line: so bump line counters. + */ + if (input_line_pointer[-1] == '\n') { + bump_line_counters(); + +#ifdef MRI + /* Text at the start of a line must be a label, we run down and stick a colon in */ + if (is_name_beginner(*input_line_pointer)) + { + char *line_start = input_line_pointer; + char c = get_symbol_end(); + colon(line_start); + *input_line_pointer = c; + if (c == ':') + input_line_pointer++; + + } +#endif + } /* just passed a newline */ + + + + - /* - * We are at the begining of a line, or similar place. - * We expect a well-formed assembler statement. - * A "symbol-name:" is a statement. - * - * Depending on what compiler is used, the order of these tests - * may vary to catch most common case 1st. - * Each test is independent of all other tests at the (top) level. - * PLEASE make a compiler that doesn't use this assembler. - * It is crufty to waste a compiler's time encoding things for this - * assembler, which then wastes more time decoding it. - * (And communicating via (linear) files is silly! - * If you must pass stuff, please pass a tree!) - */ - if ((c = *input_line_pointer++) == '\t' || c == ' ' || c=='\f' || c == 0) { - c = *input_line_pointer++; - } - know(c != ' '); /* No further leading whitespace. */ - LISTING_NEWLINE(); - /* - * C is the 1st significant character. - * Input_line_pointer points after that character. - */ - if (is_name_beginner(c)) { /* want user-defined label or pseudo/opcode */ - HANDLE_CONDITIONAL_ASSEMBLY(); + /* + * We are at the begining of a line, or similar place. + * We expect a well-formed assembler statement. + * A "symbol-name:" is a statement. + * + * Depending on what compiler is used, the order of these tests + * may vary to catch most common case 1st. + * Each test is independent of all other tests at the (top) level. + * PLEASE make a compiler that doesn't use this assembler. + * It is crufty to waste a compiler's time encoding things for this + * assembler, which then wastes more time decoding it. + * (And communicating via (linear) files is silly! + * If you must pass stuff, please pass a tree!) + */ + if ((c = *input_line_pointer++) == '\t' || c == ' ' || c=='\f' || c == 0) { + c = *input_line_pointer++; + } + know(c != ' '); /* No further leading whitespace. */ + LISTING_NEWLINE(); + /* + * C is the 1st significant character. + * Input_line_pointer points after that character. + */ + if (is_name_beginner(c)) { /* want user-defined label or pseudo/opcode */ + HANDLE_CONDITIONAL_ASSEMBLY(); - s = --input_line_pointer; - c = get_symbol_end(); /* name's delimiter */ - /* - * C is character after symbol. - * That character's place in the input line is now '\0'. - * S points to the beginning of the symbol. - * [In case of pseudo-op, s->'.'.] - * Input_line_pointer->'\0' where c was. - */ - if (c == ':') { - colon(s); /* user-defined label */ - * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */ - /* Input_line_pointer->after ':'. */ - SKIP_WHITESPACE(); - + s = --input_line_pointer; + c = get_symbol_end(); /* name's delimiter */ + /* + * C is character after symbol. + * That character's place in the input line is now '\0'. + * S points to the beginning of the symbol. + * [In case of pseudo-op, s->'.'.] + * Input_line_pointer->'\0' where c was. + */ + if (c == ':') { + colon(s); /* user-defined label */ + * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */ + /* Input_line_pointer->after ':'. */ + SKIP_WHITESPACE(); + - } else if (c == '=' || input_line_pointer[1] == '=') { /* JF deal with FOO=BAR */ - equals(s); - demand_empty_rest_of_line(); - } else { /* expect pseudo-op or machine instruction */ - if (*s == '.') { - /* - * PSEUDO - OP. - * - * WARNING: c has next char, which may be end-of-line. - * We lookup the pseudo-op table with s+1 because we - * already know that the pseudo-op begins with a '.'. - */ + } else if (c == '=' || input_line_pointer[1] == '=') { /* JF deal with FOO=BAR */ + equals(s); + demand_empty_rest_of_line(); + } else { /* expect pseudo-op or machine instruction */ +#ifdef MRI + if(!done_pseudo(s)) + +#else + if (*s == '.') { + /* + * PSEUDO - OP. + * + * WARNING: c has next char, which may be end-of-line. + * We lookup the pseudo-op table with s+1 because we + * already know that the pseudo-op begins with a '.'. + */ - pop = (pseudo_typeS *) hash_find(po_hash, s+1); + pop = (pseudo_typeS *) hash_find(po_hash, s+1); - /* Print the error msg now, while we still can */ - if (!pop) { - as_bad("Unknown pseudo-op: `%s'",s); - *input_line_pointer = c; - s_ignore(0); - break; - } + /* Print the error msg now, while we still can */ + if (!pop) { + as_bad("Unknown pseudo-op: `%s'",s); + *input_line_pointer = c; + s_ignore(0); + break; + } - /* Put it back for error messages etc. */ - *input_line_pointer = c; - /* The following skip of whitespace is compulsory. */ - /* A well shaped space is sometimes all that separates keyword from operands. */ - if (c == ' ' || c == '\t') { - input_line_pointer++; - } /* Skip seperator after keyword. */ - /* - * Input_line is restored. - * Input_line_pointer->1st non-blank char - * after pseudo-operation. - */ - if (!pop) { - ignore_rest_of_line(); - break; - } else { - (*pop->poc_handler)(pop->poc_val); - } /* if we have one */ - } else { /* machine instruction */ - /* WARNING: c has char, which may be end-of-line. */ - /* Also: input_line_pointer->`\0` where c was. */ - * input_line_pointer = c; - while (!is_end_of_line[*input_line_pointer]) { - input_line_pointer++; - } - c = *input_line_pointer; - *input_line_pointer = '\0'; - md_assemble(s); /* Assemble 1 instruction. */ - *input_line_pointer++ = c; - /* We resume loop AFTER the end-of-line from this instruction */ - } /* if (*s=='.') */ - - } /* if c==':' */ - continue; - } /* if (is_name_beginner(c) */ - + /* Put it back for error messages etc. */ + *input_line_pointer = c; + /* The following skip of whitespace is compulsory. */ + /* A well shaped space is sometimes all that separates keyword from operands. */ + if (c == ' ' || c == '\t') { + input_line_pointer++; + } /* Skip seperator after keyword. */ + /* + * Input_line is restored. + * Input_line_pointer->1st non-blank char + * after pseudo-operation. + */ + if (!pop) { + ignore_rest_of_line(); + break; + } else { + (*pop->poc_handler)(pop->poc_val); + } /* if we have one */ + } else +#endif + { /* machine instruction */ + /* WARNING: c has char, which may be end-of-line. */ + /* Also: input_line_pointer->`\0` where c was. */ + * input_line_pointer = c; + while (!is_end_of_line[*input_line_pointer]) { + input_line_pointer++; + } + + c = *input_line_pointer; + *input_line_pointer = '\0'; + + md_assemble(s); /* Assemble 1 instruction. */ + + *input_line_pointer++ = c; + + /* We resume loop AFTER the end-of-line from this instruction */ + } /* if (*s=='.') */ + + } /* if c==':' */ + continue; + } /* if (is_name_beginner(c) */ - if (is_end_of_line [c]) { - continue; - } /* empty statement */ + if (is_end_of_line [c]) { + continue; + } /* empty statement */ - if (isdigit(c)) { /* local label ("4:") */ - HANDLE_CONDITIONAL_ASSEMBLY (); - - temp = c - '0'; + +#if defined(LOCAL_LABELS_DOLLAR) || defined(LOCAL_LABELS_FB) + if (isdigit(c)) { /* local label ("4:") */ + char *backup = input_line_pointer; + + HANDLE_CONDITIONAL_ASSEMBLY (); + + temp = c - '0'; + + while (isdigit(*input_line_pointer)) { + temp = (temp * 10) + *input_line_pointer - '0'; + ++input_line_pointer; + } /* read the whole number */ + #ifdef LOCAL_LABELS_DOLLAR - if (*input_line_pointer=='$') - input_line_pointer++; -#endif - if (* input_line_pointer ++ == ':') - { - local_colon (temp); - } - else - { - as_bad("Spurious digit %d.", temp); - input_line_pointer -- ; - ignore_rest_of_line(); - } - continue; - } /* local label ("4:") */ - - if (c && strchr(line_comment_chars,c)) { /* Its a comment. Better say APP or NO_APP */ - char *ends; - char *new_buf; - char *new_tmp; - int new_length; - char *tmp_buf = 0; - extern char *scrub_string,*scrub_last_string; + if (*input_line_pointer == '$' + && *(input_line_pointer + 1) == ':') { + input_line_pointer += 2; + + if (dollar_label_defined(temp)) { + as_fatal("label \"%d$\" redefined", temp); + } + + define_dollar_label(temp); + colon(dollar_label_name(temp, 0)); + continue; + } +#endif /* LOCAL_LABELS_DOLLAR */ + +#ifdef LOCAL_LABELS_FB + if (*input_line_pointer++ == ':') { + fb_label_instance_inc(temp); + colon(fb_label_name(temp, 0)); + continue; + } +#endif /* LOCAL_LABELS_FB */ + + input_line_pointer = backup; + } /* local label ("4:") */ +#endif /* LOCAL_LABELS_DOLLAR or LOCAL_LABELS_FB */ + + if (c && strchr(line_comment_chars,c)) { /* Its a comment. Better say APP or NO_APP */ + char *ends; + char *new_buf; + char *new_tmp; + int new_length; + char *tmp_buf = 0; + extern char *scrub_string,*scrub_last_string; - bump_line_counters(); - s=input_line_pointer; - if (strncmp(s,"APP\n",4)) - continue; /* We ignore it */ - s+=4; + bump_line_counters(); + s=input_line_pointer; + if (strncmp(s,"APP\n",4)) + continue; /* We ignore it */ + s+=4; - ends=strstr(s,"#NO_APP\n"); + ends=strstr(s,"#NO_APP\n"); - if (!ends) { - int tmp_len; - int num; + if (!ends) { + int tmp_len; + int num; - /* The end of the #APP wasn't in this buffer. We - keep reading in buffers until we find the #NO_APP - that goes with this #APP There is one. The specs - guarentee it. . . */ - tmp_len=buffer_limit-s; - tmp_buf=xmalloc(tmp_len); - memcpy(tmp_buf, s, tmp_len); - do { - new_tmp = input_scrub_next_buffer(&buffer); - if (!new_tmp) - break; - else - buffer_limit = new_tmp; - input_line_pointer = buffer; - ends = strstr(buffer,"#NO_APP\n"); - if (ends) - num=ends-buffer; - else - num=buffer_limit-buffer; + /* The end of the #APP wasn't in this buffer. We + keep reading in buffers until we find the #NO_APP + that goes with this #APP There is one. The specs + guarentee it. . . */ + tmp_len=buffer_limit-s; + tmp_buf=xmalloc(tmp_len); + bcopy(s,tmp_buf,tmp_len); + do { + new_tmp = input_scrub_next_buffer(&buffer); + if (!new_tmp) + break; + else + buffer_limit = new_tmp; + input_line_pointer = buffer; + ends = strstr(buffer,"#NO_APP\n"); + if (ends) + num=ends-buffer; + else + num=buffer_limit-buffer; - tmp_buf = xrealloc(tmp_buf, tmp_len + num); - memcpy(tmp_buf + tmp_len, buffer, num); - tmp_len+=num; - } while(!ends); + tmp_buf = xrealloc(tmp_buf, tmp_len + num); + bcopy(buffer,tmp_buf+tmp_len,num); + tmp_len+=num; + } while(!ends); - input_line_pointer= ends ? ends+8 : NULL; + input_line_pointer= ends ? ends+8 : NULL; - s=tmp_buf; - ends=s+tmp_len; + s=tmp_buf; + ends=s+tmp_len; - } else { - input_line_pointer=ends+8; - } - new_buf=xmalloc(100); - new_length=100; - new_tmp=new_buf; - - scrub_string=s; - scrub_last_string = ends; - for(;;) { - int ch; - - ch = do_scrub_next_char(scrub_from_string, scrub_to_string); - if (ch==EOF) break; - *new_tmp++=ch; - if (new_tmp==new_buf+new_length) { - new_buf=xrealloc(new_buf,new_length+100); - new_tmp=new_buf+new_length; - new_length+=100; - } - } - - if (tmp_buf) - free(tmp_buf); - old_buffer=buffer; - old_input=input_line_pointer; - old_limit=buffer_limit; - buffer=new_buf; - input_line_pointer=new_buf; - buffer_limit=new_tmp; - continue; - } - - HANDLE_CONDITIONAL_ASSEMBLY(); - - /* as_warn("Junk character %d.",c); Now done by ignore_rest */ - input_line_pointer--; /* Report unknown char as ignored. */ - ignore_rest_of_line(); - } /* while (input_line_pointer<buffer_limit) */ - if (old_buffer) { - bump_line_counters(); - if (old_input != 0) { - buffer=old_buffer; - input_line_pointer=old_input; - buffer_limit=old_limit; - old_buffer = 0; - goto contin; - } + } else { + input_line_pointer=ends+8; + } + new_buf=xmalloc(100); + new_length=100; + new_tmp=new_buf; + + scrub_string=s; + scrub_last_string = ends; + for(;;) { + int ch; + + ch = do_scrub_next_char(scrub_from_string, scrub_to_string); + if (ch==EOF) break; + *new_tmp++=ch; + if (new_tmp==new_buf+new_length) { + new_buf=xrealloc(new_buf,new_length+100); + new_tmp=new_buf+new_length; + new_length+=100; + } } - } /* while (more buffers to scan) */ - input_scrub_close(); /* Close the input file */ - + + if (tmp_buf) + free(tmp_buf); + old_buffer=buffer; + old_input=input_line_pointer; + old_limit=buffer_limit; + buffer=new_buf; + input_line_pointer=new_buf; + buffer_limit=new_tmp; + continue; + } + + HANDLE_CONDITIONAL_ASSEMBLY(); + + /* as_warn("Junk character %d.",c); Now done by ignore_rest */ + input_line_pointer--; /* Report unknown char as ignored. */ + ignore_rest_of_line(); + } /* while (input_line_pointer<buffer_limit) */ + if (old_buffer) { + bump_line_counters(); + if (old_input != 0) { + buffer=old_buffer; + input_line_pointer=old_input; + buffer_limit=old_limit; + old_buffer = 0; + goto contin; + } + } + } /* while (more buffers to scan) */ + input_scrub_close(); /* Close the input file */ + } /* read_a_source_file() */ void s_abort() { @@ -600,43 +634,43 @@ void s_abort() { void s_align_bytes(arg) int arg; { - register unsigned int temp; - register long temp_fill; - unsigned int i = 0; - unsigned long max_alignment = 1 << 15; - - if (is_end_of_line[*input_line_pointer]) - temp = arg; /* Default value from pseudo-op table */ - else - temp = get_absolute_expression (); - - if (temp > max_alignment) { - as_bad("Alignment too large: %d. assumed.", temp = max_alignment); - } - - /* - * For the sparc, `.align (1<<n)' actually means `.align n' - * so we have to convert it. - */ - if (temp != 0) { - for (i = 0; (temp & 1) == 0; temp >>= 1, ++i) - ; - } - if (temp != 1) - as_bad("Alignment not a power of 2"); - - temp = i; - if (*input_line_pointer == ',') { - input_line_pointer ++; - temp_fill = get_absolute_expression (); - } else { - temp_fill = NOP_OPCODE; - } - /* Only make a frag if we HAVE to. . . */ - if (temp && ! need_pass_2) - frag_align(temp, (int)temp_fill); - - demand_empty_rest_of_line(); + register unsigned int temp; + register long temp_fill; + unsigned int i = 0; + unsigned long max_alignment = 1 << 15; + + if (is_end_of_line[*input_line_pointer]) + temp = arg; /* Default value from pseudo-op table */ + else + temp = get_absolute_expression (); + + if (temp > max_alignment) { + as_bad("Alignment too large: %d. assumed.", temp = max_alignment); + } + + /* + * For the sparc, `.align (1<<n)' actually means `.align n' + * so we have to convert it. + */ + if (temp != 0) { + for (i = 0; (temp & 1) == 0; temp >>= 1, ++i) + ; + } + if (temp != 1) + as_bad("Alignment not a power of 2"); + + temp = i; + if (*input_line_pointer == ',') { + input_line_pointer ++; + temp_fill = get_absolute_expression (); + } else { + temp_fill = 0; + } + /* Only make a frag if we HAVE to. . . */ + if (temp && ! need_pass_2) + frag_align(temp, (int)temp_fill); + + demand_empty_rest_of_line(); } /* s_align_bytes() */ /* For machines where ".align 4" means align to 2**4 boundary. */ @@ -644,10 +678,10 @@ void s_align_ptwo() { register int temp; register long temp_fill; long max_alignment = 15; - + temp = get_absolute_expression (); if (temp > max_alignment) - as_bad("Alignment too large: %d. assumed.", temp = max_alignment); + as_bad("Alignment too large: %d. assumed.", temp = max_alignment); else if (temp < 0) { as_bad("Alignment negative. 0 assumed."); temp = 0; @@ -656,34 +690,23 @@ void s_align_ptwo() { input_line_pointer ++; temp_fill = get_absolute_expression (); } else - temp_fill = NOP_OPCODE; + temp_fill = 0; /* Only make a frag if we HAVE to. . . */ if (temp && ! need_pass_2) - frag_align (temp, (int)temp_fill); - + frag_align (temp, (int)temp_fill); + record_alignment(now_seg, temp); - + demand_empty_rest_of_line(); } /* s_align_ptwo() */ - -void s_bss() -{ - register int temp; - - temp = get_absolute_expression (); - subseg_new (SEG_BSS, (subsegT)temp); - demand_empty_rest_of_line(); -} - - void s_comm() { register char *name; register char c; register char *p; register int temp; register symbolS * symbolP; - + name = input_line_pointer; c = get_symbol_end(); /* just after name is now '\0' */ @@ -711,34 +734,34 @@ void s_comm() { } if (S_GET_VALUE(symbolP)) { if (S_GET_VALUE(symbolP) != temp) - as_bad("Length of .comm \"%s\" is already %d. Not changed to %d.", - S_GET_NAME(symbolP), - S_GET_VALUE(symbolP), - temp); + as_bad("Length of .comm \"%s\" is already %d. Not changed to %d.", + S_GET_NAME(symbolP), + S_GET_VALUE(symbolP), + temp); } else { S_SET_VALUE(symbolP, temp); S_SET_EXTERNAL(symbolP); } #ifdef VMS if (!temp) - symbolP->sy_other = const_flag; + symbolP->sy_other = const_flag; #endif know(symbolP->sy_frag == &zero_address_frag); demand_empty_rest_of_line(); } /* s_comm() */ void - s_data() +s_data() { register int temp; - + temp = get_absolute_expression (); #ifdef MANY_SEGMENTS subseg_new (SEG_E1, (subsegT)temp); #else subseg_new (SEG_DATA, (subsegT)temp); #endif - + #ifdef VMS const_flag = 0; #endif @@ -748,7 +771,7 @@ void void s_app_file() { register char *s; int length; - + /* Some assemblers tolerate immediately following '"' */ if ((s = demand_copy_string(&length)) != 0) { new_logical_line(s, -1); @@ -764,7 +787,7 @@ void s_fill() { long temp_size; register long temp_fill; char *p; - + if (get_absolute_expression_and_terminator(& temp_repeat) != ',') { input_line_pointer --; /* Backup over what was not a ','. */ as_bad("Expect comma after rep-size in .fill:"); @@ -772,10 +795,10 @@ void s_fill() { return; } if (get_absolute_expression_and_terminator(& temp_size) != ',') { - input_line_pointer --; /* Backup over what was not a ','. */ - as_bad("Expected comma after size in .fill"); - ignore_rest_of_line(); - return; + input_line_pointer --; /* Backup over what was not a ','. */ + as_bad("Expected comma after size in .fill"); + ignore_rest_of_line(); + return; } /* * This is to be compatible with BSD 4.2 AS, not for any rational reason. @@ -794,29 +817,141 @@ void s_fill() { temp_fill = get_absolute_expression (); if (temp_size && !need_pass_2) { p = frag_var(rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0); - memset(p, '\0', (int) temp_size); - /* - * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS. - * The following bizzare behaviour is to be compatible with above. - * I guess they tried to take up to 8 bytes from a 4-byte expression - * and they forgot to sign extend. Un*x Sux. - */ + bzero (p, (int)temp_size); +/* + * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS. + * The following bizzare behaviour is to be compatible with above. + * I guess they tried to take up to 8 bytes from a 4-byte expression + * and they forgot to sign extend. Un*x Sux. + */ #define BSD_FILL_SIZE_CROCK_4 (4) md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size); - /* - * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) - * but emits no error message because it seems a legal thing to do. - * It is a degenerate case of .fill but could be emitted by a compiler. - */ +/* + * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) + * but emits no error message because it seems a legal thing to do. + * It is a degenerate case of .fill but could be emitted by a compiler. + */ + } + demand_empty_rest_of_line(); +} + +#ifdef DONTDEF +void +s_gdbbeg() +{ + register int temp; + + temp = get_absolute_expression (); + if (temp < 0) + as_warn("Block number <0. Ignored."); + else if (flagseen ['G']) + gdb_block_beg ((long) temp, frag_now, (long)(obstack_next_free(& frags) - frag_now->fr_literal)); + demand_empty_rest_of_line (); +} + +void +s_gdbblock() +{ + register int position; + int temp; + + if (get_absolute_expression_and_terminator (&temp) != ',') { + as_bad("expected comma before position in .gdbblock"); + --input_line_pointer; + ignore_rest_of_line (); + return; + } + position = get_absolute_expression (); + if (flagseen ['G']) + gdb_block_position ((long) temp, (long) position); + demand_empty_rest_of_line (); +} + +void +s_gdbend() +{ + register int temp; + + temp = get_absolute_expression (); + if (temp < 0) + as_warn("Block number <0. Ignored."); + else if (flagseen ['G']) + gdb_block_end ((long) temp, frag_now, (long)(obstack_next_free(& frags) - frag_now->fr_literal)); + demand_empty_rest_of_line (); +} + +void +s_gdbsym() +{ + register char *name, + *p; + register char c; + register symbolS * symbolP; + register int temp; + + name = input_line_pointer; + c = get_symbol_end(); + p = input_line_pointer; + symbolP = symbol_find_or_make(name); + *p = c; + SKIP_WHITESPACE(); + if (* input_line_pointer != ',') { + as_bad("Expected comma after name"); + ignore_rest_of_line(); + return; } + input_line_pointer ++; + if ((temp = get_absolute_expression ()) < 0) { + as_bad("Bad GDB symbol file offset (%d.) <0! Ignored.", temp); + ignore_rest_of_line(); + return; + } + if (flagseen ['G']) + gdb_symbols_fixup (symbolP, (long)temp); + demand_empty_rest_of_line (); +} + +void +s_gdbline() +{ + int file_number, + lineno; + + if (get_absolute_expression_and_terminator(&file_number) != ',') { + as_bad("expected comman after filenum in .gdbline"); + ignore_rest_of_line(); + return; + } + lineno=get_absolute_expression(); + if (flagseen['G']) + gdb_line(file_number,lineno); demand_empty_rest_of_line(); } + +void +s_gdblinetab() +{ + int file_number, + offset; + + if (get_absolute_expression_and_terminator(&file_number) != ',') { + as_bad("expected comma after filenum in .gdblinetab"); + ignore_rest_of_line(); + return; + } + offset=get_absolute_expression(); + if (flagseen['G']) + gdb_line_tab(file_number,offset); + demand_empty_rest_of_line(); +} +#endif + void s_globl() { register char *name; register int c; register symbolS * symbolP; - + do { name = input_line_pointer; c = get_symbol_end(); @@ -828,7 +963,7 @@ void s_globl() { input_line_pointer++; SKIP_WHITESPACE(); if (*input_line_pointer=='\n') - c='\n'; + c='\n'; } } while(c==','); demand_empty_rest_of_line(); @@ -847,7 +982,7 @@ int needs_align; /* 1 if this was a ".bss" directive, which may require register symbolS * symbolP; const int max_alignment = 15; int align = 0; - + name = input_line_pointer; c = get_symbol_end(); p = input_line_pointer; @@ -858,20 +993,20 @@ int needs_align; /* 1 if this was a ".bss" directive, which may require ignore_rest_of_line(); return; } - + ++input_line_pointer; - + if (*input_line_pointer == '\n') { as_bad("Missing size expression"); return; } - + if ((temp = get_absolute_expression ()) < 0) { as_warn("BSS length (%d.) <0! Ignored.", temp); ignore_rest_of_line(); return; } - + if (needs_align) { align = 0; SKIP_WHITESPACE(); @@ -901,11 +1036,11 @@ int needs_align; /* 1 if this was a ".bss" directive, which may require record_alignment(SEG_BSS, align); #endif } /* if needs align */ - + *p = 0; symbolP = symbol_find_or_make(name); *p = c; - + if ( #if defined(OBJ_AOUT) | defined(OBJ_BOUT) S_GET_OTHER(symbolP) == 0 && @@ -919,7 +1054,7 @@ int needs_align; /* 1 if this was a ".bss" directive, which may require local_bss_counter = (local_bss_counter + align) & (~align); } - + S_SET_VALUE(symbolP,local_bss_counter); S_SET_SEGMENT(symbolP, SEG_BSS); #ifdef OBJ_COFF @@ -935,21 +1070,21 @@ int needs_align; /* 1 if this was a ".bss" directive, which may require local_bss_counter += temp; } else { as_bad("Ignoring attempt to re-define symbol from %d. to %d.", - S_GET_VALUE(symbolP), local_bss_counter); + S_GET_VALUE(symbolP), local_bss_counter); } demand_empty_rest_of_line(); - + return; } /* s_lcomm() */ void - s_long() +s_long() { cons(4); } void - s_int() +s_int() { cons(4); } @@ -961,7 +1096,7 @@ void s_lsym() { register segT segment; expressionS exp; register symbolS *symbolP; - + /* we permit ANY defined expression: BSD4.2 demands constants */ name = input_line_pointer; c = get_symbol_end(); @@ -979,20 +1114,20 @@ void s_lsym() { segment = expression(& exp); if (segment != SEG_ABSOLUTE #ifdef MANY_SEGMENTS - && ! ( segment >= SEG_E0 && segment <= SEG_UNKNOWN) + && ! ( segment >= SEG_E0 && segment <= SEG_UNKNOWN) #else - && segment != SEG_DATA - && segment != SEG_TEXT - && segment != SEG_BSS + && segment != SEG_DATA + && segment != SEG_TEXT + && segment != SEG_BSS #endif - && segment != SEG_REGISTER) { + && segment != SEG_REGISTER) { as_bad("Bad expression: %s", segment_name(segment)); ignore_rest_of_line(); return; } *p = 0; symbolP = symbol_find_or_make(name); - + /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 && symbolP->sy_desc == 0) out of this test because coff doesn't have those fields, and I @@ -1000,7 +1135,7 @@ void s_lsym() { think I understand why they were here so I may have introduced a bug. As recently as 1.37 didn't have this test anyway. xoxorich. */ - + if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN && S_GET_VALUE(symbolP) == 0) { /* The name might be an undefined .global symbol; be @@ -1019,27 +1154,27 @@ void s_org() { expressionS exp; register long temp_fill; register char *p; - /* - * Don't believe the documentation of BSD 4.2 AS. - * There is no such thing as a sub-segment-relative origin. - * Any absolute origin is given a warning, then assumed to be segment-relative. - * Any segmented origin expression ("foo+42") had better be in the right - * segment or the .org is ignored. - * - * BSD 4.2 AS warns if you try to .org backwards. We cannot because we - * never know sub-segment sizes when we are reading code. - * BSD will crash trying to emit -ve numbers of filler bytes in certain - * .orgs. We don't crash, but see as-write for that code. - */ - /* - * Don't make frag if need_pass_2==1. - */ +/* + * Don't believe the documentation of BSD 4.2 AS. + * There is no such thing as a sub-segment-relative origin. + * Any absolute origin is given a warning, then assumed to be segment-relative. + * Any segmented origin expression ("foo+42") had better be in the right + * segment or the .org is ignored. + * + * BSD 4.2 AS warns if you try to .org backwards. We cannot because we + * never know sub-segment sizes when we are reading code. + * BSD will crash trying to emit -ve numbers of filler bytes in certain + * .orgs. We don't crash, but see as-write for that code. + */ +/* + * Don't make frag if need_pass_2==1. + */ segment = get_known_segmented_expression(&exp); if (*input_line_pointer == ',') { input_line_pointer ++; temp_fill = get_absolute_expression (); } else - temp_fill = 0; + temp_fill = 0; if (! need_pass_2) { if (segment != now_seg && segment != SEG_ABSOLUTE) as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.", @@ -1056,7 +1191,7 @@ void s_set() { register char delim; register char *end_name; register symbolS *symbolP; - + /* * Especial apologies for the random logic: * this just grew, and could be parsed much more simply! @@ -1067,7 +1202,7 @@ void s_set() { end_name = input_line_pointer; *end_name = delim; SKIP_WHITESPACE(); - + if (*input_line_pointer != ',') { *end_name = 0; as_bad("Expected comma after name \"%s\"", name); @@ -1075,32 +1210,32 @@ void s_set() { ignore_rest_of_line(); return; } - + input_line_pointer ++; *end_name = 0; - + if (name[0]=='.' && name[1]=='\0') { /* Turn '. = mumble' into a .org mumble */ register segT segment; expressionS exp; register char *ptr; - + segment = get_known_segmented_expression(& exp); - + if (!need_pass_2) { if (segment != now_seg && segment != SEG_ABSOLUTE) as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.", - segment_name(segment), - segment_name (now_seg)); + segment_name(segment), + segment_name (now_seg)); ptr = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, exp.X_add_number, (char *)0); *ptr= 0; } /* if (ok to make frag) */ - + *end_name = delim; return; } - + if ((symbolP = symbol_find(name)) == NULL && (symbolP = md_undefined_symbol(name)) == NULL) { symbolP = symbol_new(name, @@ -1111,11 +1246,11 @@ void s_set() { /* "set" symbols are local unless otherwise specified. */ SF_SET_LOCAL(symbolP); #endif /* OBJ_COFF */ - + } /* make a new symbol */ - + symbol_table_insert(symbolP); - + *end_name = delim; pseudo_set(symbolP); demand_empty_rest_of_line(); @@ -1125,7 +1260,7 @@ void s_space() { long temp_repeat; register long temp_fill; register char *p; - + /* Just like .fill, but temp_size = 1 */ if (get_absolute_expression_and_terminator(& temp_repeat) == ',') { temp_fill = get_absolute_expression (); @@ -1140,17 +1275,17 @@ void s_space() { } if (! need_pass_2) { p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0, - temp_repeat, (char *)0); + temp_repeat, (char *)0); * p = temp_fill; } demand_empty_rest_of_line(); } /* s_space() */ void - s_text() +s_text() { register int temp; - + temp = get_absolute_expression (); #ifdef MANY_SEGMENTS subseg_new (SEG_E0, (subsegT)temp); @@ -1174,24 +1309,24 @@ void demand_empty_rest_of_line() { } /* Return pointing just after end-of-line. */ void - ignore_rest_of_line() /* For suspect lines: gives warning. */ +ignore_rest_of_line() /* For suspect lines: gives warning. */ { - if (! is_end_of_line [* input_line_pointer]) - { - if (isprint(*input_line_pointer)) - as_bad("Rest of line ignored. First ignored character is `%c'.", - *input_line_pointer); - else - as_bad("Rest of line ignored. First ignored character valued 0x%x.", - *input_line_pointer); - while (input_line_pointer < buffer_limit - && ! is_end_of_line [* input_line_pointer]) - { - input_line_pointer ++; - } - } - input_line_pointer ++; /* Return pointing just after end-of-line. */ - know(is_end_of_line [input_line_pointer [-1]]); + if (! is_end_of_line [* input_line_pointer]) + { + if (isprint(*input_line_pointer)) + as_bad("Rest of line ignored. First ignored character is `%c'.", + *input_line_pointer); + else + as_bad("Rest of line ignored. First ignored character valued 0x%x.", + *input_line_pointer); + while (input_line_pointer < buffer_limit + && ! is_end_of_line [* input_line_pointer]) + { + input_line_pointer ++; + } + } + input_line_pointer ++; /* Return pointing just after end-of-line. */ + know(is_end_of_line [input_line_pointer [-1]]); } /* @@ -1206,113 +1341,120 @@ void * May set need_pass_2 == 1. */ void - pseudo_set (symbolP) -symbolS * symbolP; +pseudo_set (symbolP) + symbolS * symbolP; { - expressionS exp; - register segT segment; + expressionS exp; + register segT segment; #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - int ext; + int ext; #endif /* OBJ_AOUT or OBJ_BOUT */ - - know(symbolP); /* NULL pointer is logic error. */ + + know(symbolP); /* NULL pointer is logic error. */ #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - ext=S_IS_EXTERNAL(symbolP); + ext=S_IS_EXTERNAL(symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ - - if ((segment = expression(& exp)) == SEG_ABSENT) - { - as_bad("Missing expression: absolute 0 assumed"); - exp . X_seg = SEG_ABSOLUTE; - exp . X_add_number = 0; - } - - switch (segment) - { - case SEG_BIG: - as_bad("%s number invalid. Absolute 0 assumed.", - exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); - S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); + + if ((segment = expression(& exp)) == SEG_ABSENT) + { + as_bad("Missing expression: absolute 0 assumed"); + exp . X_seg = SEG_ABSOLUTE; + exp . X_add_number = 0; + } + + switch (segment) + { + case SEG_REGISTER: + S_SET_SEGMENT(symbolP, SEG_REGISTER); + S_SET_VALUE(symbolP, exp.X_add_number); + symbolP->sy_frag = & zero_address_frag; + break; + + case SEG_BIG: + as_bad("%s number invalid. Absolute 0 assumed.", + exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); + S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - ext ? S_SET_EXTERNAL(symbolP) : - S_CLEAR_EXTERNAL(symbolP); + ext ? S_SET_EXTERNAL(symbolP) : + S_CLEAR_EXTERNAL(symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ - S_SET_VALUE(symbolP, 0); - symbolP->sy_frag = & zero_address_frag; - break; - - case SEG_ABSENT: - as_warn("No expression: Using absolute 0"); - S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); + S_SET_VALUE(symbolP, 0); + symbolP->sy_frag = & zero_address_frag; + break; + + case SEG_ABSENT: + as_warn("No expression: Using absolute 0"); + S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - ext ? S_SET_EXTERNAL(symbolP) : - S_CLEAR_EXTERNAL(symbolP); + ext ? S_SET_EXTERNAL(symbolP) : + S_CLEAR_EXTERNAL(symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ - S_SET_VALUE(symbolP, 0); - symbolP->sy_frag = & zero_address_frag; - break; - - case SEG_DIFFERENCE: - if (exp.X_add_symbol && exp.X_subtract_symbol - && (S_GET_SEGMENT(exp.X_add_symbol) == - S_GET_SEGMENT(exp.X_subtract_symbol))) { - if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) { - as_bad("Unknown expression: symbols %s and %s are in different frags.", - S_GET_NAME(exp.X_add_symbol), S_GET_NAME(exp.X_subtract_symbol)); - need_pass_2++; - } - exp.X_add_number+=S_GET_VALUE(exp.X_add_symbol) - - S_GET_VALUE(exp.X_subtract_symbol); - } else - as_bad("Complex expression. Absolute segment assumed."); - case SEG_ABSOLUTE: - S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); + S_SET_VALUE(symbolP, 0); + symbolP->sy_frag = & zero_address_frag; + break; + + case SEG_DIFFERENCE: + if (exp.X_add_symbol && exp.X_subtract_symbol + && (S_GET_SEGMENT(exp.X_add_symbol) == + S_GET_SEGMENT(exp.X_subtract_symbol))) { + if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) { + as_bad("Unknown expression: symbols %s and %s are in different frags.", + S_GET_NAME(exp.X_add_symbol), S_GET_NAME(exp.X_subtract_symbol)); + need_pass_2++; + } + exp.X_add_number+=S_GET_VALUE(exp.X_add_symbol) - + S_GET_VALUE(exp.X_subtract_symbol); + } else + as_bad("Complex expression. Absolute segment assumed."); + case SEG_ABSOLUTE: + S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - ext ? S_SET_EXTERNAL(symbolP) : - S_CLEAR_EXTERNAL(symbolP); + ext ? S_SET_EXTERNAL(symbolP) : + S_CLEAR_EXTERNAL(symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ - S_SET_VALUE(symbolP, exp.X_add_number); - symbolP->sy_frag = & zero_address_frag; - break; - - default: + S_SET_VALUE(symbolP, exp.X_add_number); + symbolP->sy_frag = & zero_address_frag; + break; + + default: #ifdef MANY_SEGMENTS - S_SET_SEGMENT(symbolP, segment); + S_SET_SEGMENT(symbolP, segment); #else - switch(segment) { - case SEG_DATA: S_SET_SEGMENT(symbolP, SEG_DATA); break; - case SEG_TEXT: S_SET_SEGMENT(symbolP, SEG_TEXT); break; - case SEG_BSS: S_SET_SEGMENT(symbolP, SEG_BSS); break; - default: as_fatal("failed sanity check."); - } /* switch on segment */ + switch(segment) { + case SEG_DATA: S_SET_SEGMENT(symbolP, SEG_DATA); break; + case SEG_TEXT: S_SET_SEGMENT(symbolP, SEG_TEXT); break; + case SEG_BSS: S_SET_SEGMENT(symbolP, SEG_BSS); break; + + default: as_fatal("failed sanity check."); + } /* switch on segment */ #endif #if defined(OBJ_AOUT) | defined(OBJ_BOUT) - if (ext) { - S_SET_EXTERNAL(symbolP); - } else { - S_CLEAR_EXTERNAL(symbolP); - } /* if external */ + if (ext) { + S_SET_EXTERNAL(symbolP); + } else { + S_CLEAR_EXTERNAL(symbolP); + } /* if external */ #endif /* OBJ_AOUT or OBJ_BOUT */ - - S_SET_VALUE(symbolP, exp.X_add_number + S_GET_VALUE(exp.X_add_symbol)); - symbolP->sy_frag = exp . X_add_symbol->sy_frag; - break; - - case SEG_PASS1: /* Not an error. Just try another pass. */ - symbolP->sy_forward=exp.X_add_symbol; - as_bad("Unknown expression"); - know(need_pass_2 == 1); - break; - - case SEG_UNKNOWN: - symbolP->sy_forward=exp.X_add_symbol; - /* as_warn("unknown symbol"); */ - /* need_pass_2 = 1; */ - break; - - - - } + + S_SET_VALUE(symbolP, exp.X_add_number + S_GET_VALUE(exp.X_add_symbol)); + symbolP->sy_frag = exp . X_add_symbol->sy_frag; + break; + + case SEG_PASS1: /* Not an error. Just try another pass. */ + symbolP->sy_forward=exp.X_add_symbol; + as_bad("Unknown expression"); + know(need_pass_2 == 1); + break; + + case SEG_UNKNOWN: + symbolP->sy_forward=exp.X_add_symbol; + /* as_warn("unknown symbol"); */ + /* need_pass_2 = 1; */ + break; + + + + } } /* @@ -1330,245 +1472,305 @@ symbolS * symbolP; * in the case of a long. Not worth the crocks required to fix it. */ -/* worker to do .byte etc statements */ -/* clobbers input_line_pointer, checks */ -/* end-of-line. */ + /* worker to do .byte etc statements */ + /* clobbers input_line_pointer, checks */ + /* end-of-line. */ void cons(nbytes) register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */ { - register char c; - register long mask; /* High-order bits we will left-truncate, */ - /* but includes sign bit also. */ - register long get; /* what we get */ - register long use; /* get after truncation. */ - register long unmask; /* what bits we will store */ - register char * p; - register segT segment; - expressionS exp; - - /* - * Input_line_pointer->1st char after pseudo-op-code and could legally - * be a end-of-line. (Or, less legally an eof - which we cope with.) - */ - /* JF << of >= number of bits in the object is undefined. In particular - SPARC (Sun 4) has problems */ - - if (nbytes>=sizeof(long)) { - mask = 0; - } else { - mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ - } /* bigger than a long */ - - unmask = ~mask; /* Do store these bits. */ - + register char c; + register long mask; /* High-order bits we will left-truncate, */ + /* but includes sign bit also. */ + register long get; /* what we get */ + register long use; /* get after truncation. */ + register long unmask; /* what bits we will store */ + register char * p; + register segT segment; + expressionS exp; + + /* + * Input_line_pointer->1st char after pseudo-op-code and could legally + * be a end-of-line. (Or, less legally an eof - which we cope with.) + */ + /* JF << of >= number of bits in the object is undefined. In particular + SPARC (Sun 4) has problems */ + + if (nbytes>=sizeof(long)) { + mask = 0; + } else { + mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ + } /* bigger than a long */ + + unmask = ~mask; /* Do store these bits. */ + #ifdef NEVER - "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; - mask = ~ (unmask >> 1); /* Includes sign bit now. */ + "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; + mask = ~ (unmask >> 1); /* Includes sign bit now. */ #endif - - /* - * The following awkward logic is to parse ZERO or more expressions, - * comma seperated. Recall an expression includes its leading & - * trailing blanks. We fake a leading ',' if there is (supposed to - * be) a 1st expression, and keep demanding 1 expression for each ','. - */ - if (is_it_end_of_statement()) { - c = 0; /* Skip loop. */ - input_line_pointer++; /* Matches end-of-loop 'correction'. */ - } else { - c = ','; - } /* if the end else fake it */ - - /* Do loop. */ - while (c == ',') { + + /* + * The following awkward logic is to parse ZERO or more expressions, + * comma seperated. Recall an expression includes its leading & + * trailing blanks. We fake a leading ',' if there is (supposed to + * be) a 1st expression, and keep demanding 1 expression for each ','. + */ + if (is_it_end_of_statement()) { + c = 0; /* Skip loop. */ + input_line_pointer++; /* Matches end-of-loop 'correction'. */ + } else { + c = ','; + } /* if the end else fake it */ + + /* Do loop. */ + while (c == ',') { #ifdef WANT_BITFIELDS - unsigned int bits_available = BITS_PER_CHAR * nbytes; - /* used for error messages and rescanning */ - char *hold = input_line_pointer; + unsigned int bits_available = BITS_PER_CHAR * nbytes; + /* used for error messages and rescanning */ + char *hold = input_line_pointer; #endif /* WANT_BITFIELDS */ - - /* At least scan over the expression. */ - segment = expression(&exp); - +#ifdef MRI + if (*input_line_pointer == '\'') + { + /* An MRI style string, cut into as many bytes as will fit + into a nbyte chunk, left justify if necessary, and sepatate + with commas so we can try again later */ + int scan = 0; + unsigned int result = 0; + input_line_pointer++; + for (scan = 0; scan < nbytes; scan++) + { + if (*input_line_pointer == '\'') + { + if (input_line_pointer[1] == '\'') + { + input_line_pointer++; + } + else + break; + } + result = (result << 8) | (*input_line_pointer++); + } + + /* Left justify */ + while (scan < nbytes) + { + result <<=8; + scan++; + } + /* Create correct expression */ + exp.X_add_symbol = 0; + exp.X_add_number = result; + exp.X_seg = segment = SEG_ABSOLUTE; + /* Fake it so that we can read the next char too */ + if (input_line_pointer[0] != '\'' || + (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\'')) + { + input_line_pointer-=2; + input_line_pointer[0] = ','; + input_line_pointer[1] = '\''; + } + else + input_line_pointer++; + + } + else +#endif + /* At least scan over the expression. */ + segment = expression(&exp); + #ifdef WANT_BITFIELDS - /* Some other assemblers, (eg, asm960), allow - bitfields after ".byte" as w:x,y:z, where w and - y are bitwidths and x and y are values. They - then pack them all together. We do a little - better in that we allow them in words, longs, - etc. and we'll pack them in target byte order - for you. - - The rules are: pack least significat bit first, - if a field doesn't entirely fit, put it in the - next unit. Overflowing the bitfield is - explicitly *not* even a warning. The bitwidth - should be considered a "mask". - - FIXME-SOMEDAY: If this is considered generally - useful, this logic should probably be reworked. - xoxorich. */ - - if (*input_line_pointer == ':') { /* bitfields */ - long value = 0; - - for (;;) { - unsigned long width; - - if (*input_line_pointer != ':') { - input_line_pointer = hold; - break; - } /* next piece is not a bitfield */ - - /* In the general case, we can't allow - full expressions with symbol - differences and such. The relocation - entries for symbols not defined in this - assembly would require arbitrary field - widths, positions, and masks which most - of our current object formats don't - support. - - In the specific case where a symbol - *is* defined in this assembly, we - *could* build fixups and track it, but - this could lead to confusion for the - backends. I'm lazy. I'll take any - SEG_ABSOLUTE. I think that means that - you can use a previous .set or - .equ type symbol. xoxorich. */ - - if (segment == SEG_ABSENT) { - as_warn("Using a bit field width of zero."); - exp.X_add_number = 0; - segment = SEG_ABSOLUTE; - } /* implied zero width bitfield */ - - if (segment != SEG_ABSOLUTE) { - *input_line_pointer = '\0'; - as_bad("Field width \"%s\" too complex for a bitfield.\n", hold); - *input_line_pointer = ':'; - demand_empty_rest_of_line(); - return; - } /* too complex */ - - if ((width = exp.X_add_number) > (BITS_PER_CHAR * nbytes)) { - as_warn("Field width %d too big to fit in %d bytes: truncated to %d bits.", - width, nbytes, (BITS_PER_CHAR * nbytes)); - width = BITS_PER_CHAR * nbytes; - } /* too big */ - - if (width > bits_available) { - /* FIXME-SOMEDAY: backing up and - reparsing is wasteful */ - input_line_pointer = hold; - exp.X_add_number = value; - break; - } /* won't fit */ - - hold = ++input_line_pointer; /* skip ':' */ - - if ((segment = expression(&exp)) != SEG_ABSOLUTE) { - char cache = *input_line_pointer; - - *input_line_pointer = '\0'; - as_bad("Field value \"%s\" too complex for a bitfield.\n", hold); - *input_line_pointer = cache; - demand_empty_rest_of_line(); - return; - } /* too complex */ - - value |= (~(-1 << width) & exp.X_add_number) - << ((BITS_PER_CHAR * nbytes) - bits_available); - - if ((bits_available -= width) == 0 - || is_it_end_of_statement() - || *input_line_pointer != ',') { - break; - } /* all the bitfields we're gonna get */ - - hold = ++input_line_pointer; - segment = expression(&exp); - } /* forever loop */ - - exp.X_add_number = value; - segment = SEG_ABSOLUTE; - } /* if looks like a bitfield */ + /* Some other assemblers, (eg, asm960), allow + bitfields after ".byte" as w:x,y:z, where w and + y are bitwidths and x and y are values. They + then pack them all together. We do a little + better in that we allow them in words, longs, + etc. and we'll pack them in target byte order + for you. + + The rules are: pack least significat bit first, + if a field doesn't entirely fit, put it in the + next unit. Overflowing the bitfield is + explicitly *not* even a warning. The bitwidth + should be considered a "mask". + + FIXME-SOMEDAY: If this is considered generally + useful, this logic should probably be reworked. + xoxorich. */ + + if (*input_line_pointer == ':') { /* bitfields */ + long value = 0; + + for (;;) { + unsigned long width; + + if (*input_line_pointer != ':') { + input_line_pointer = hold; + break; + } /* next piece is not a bitfield */ + + /* In the general case, we can't allow + full expressions with symbol + differences and such. The relocation + entries for symbols not defined in this + assembly would require arbitrary field + widths, positions, and masks which most + of our current object formats don't + support. + + In the specific case where a symbol + *is* defined in this assembly, we + *could* build fixups and track it, but + this could lead to confusion for the + backends. I'm lazy. I'll take any + SEG_ABSOLUTE. I think that means that + you can use a previous .set or + .equ type symbol. xoxorich. */ + + if (segment == SEG_ABSENT) { + as_warn("Using a bit field width of zero."); + exp.X_add_number = 0; + segment = SEG_ABSOLUTE; + } /* implied zero width bitfield */ + + if (segment != SEG_ABSOLUTE) { + *input_line_pointer = '\0'; + as_bad("Field width \"%s\" too complex for a bitfield.\n", hold); + *input_line_pointer = ':'; + demand_empty_rest_of_line(); + return; + } /* too complex */ + + if ((width = exp.X_add_number) > (BITS_PER_CHAR * nbytes)) { + as_warn("Field width %d too big to fit in %d bytes: truncated to %d bits.", + width, nbytes, (BITS_PER_CHAR * nbytes)); + width = BITS_PER_CHAR * nbytes; + } /* too big */ + + if (width > bits_available) { + /* FIXME-SOMEDAY: backing up and + reparsing is wasteful */ + input_line_pointer = hold; + exp.X_add_number = value; + break; + } /* won't fit */ + + hold = ++input_line_pointer; /* skip ':' */ + + if ((segment = expression(&exp)) != SEG_ABSOLUTE) { + char cache = *input_line_pointer; + + *input_line_pointer = '\0'; + as_bad("Field value \"%s\" too complex for a bitfield.\n", hold); + *input_line_pointer = cache; + demand_empty_rest_of_line(); + return; + } /* too complex */ + + value |= (~(-1 << width) & exp.X_add_number) + << ((BITS_PER_CHAR * nbytes) - bits_available); + + if ((bits_available -= width) == 0 + || is_it_end_of_statement() + || *input_line_pointer != ',') { + break; + } /* all the bitfields we're gonna get */ + + hold = ++input_line_pointer; + segment = expression(&exp); + } /* forever loop */ + + exp.X_add_number = value; + segment = SEG_ABSOLUTE; + } /* if looks like a bitfield */ #endif /* WANT_BITFIELDS */ - - if (!need_pass_2) { /* Still worthwhile making frags. */ - - /* Don't call this if we are going to junk this pass anyway! */ - know(segment != SEG_PASS1); - - if (segment == SEG_DIFFERENCE && exp.X_add_symbol == NULL) { - as_bad("Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.", - S_GET_NAME(exp.X_subtract_symbol), - segment_name(S_GET_SEGMENT(exp.X_subtract_symbol))); - segment = SEG_ABSOLUTE; - /* Leave exp . X_add_number alone. */ - } - p = frag_more(nbytes); - switch (segment) { - case SEG_BIG: - as_bad("%s number invalid. Absolute 0 assumed.", - exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); - md_number_to_chars (p, (long)0, nbytes); - break; - - case SEG_ABSENT: - as_warn("0 assumed for missing expression"); - exp . X_add_number = 0; - know(exp . X_add_symbol == NULL); - /* fall into SEG_ABSOLUTE */ - case SEG_ABSOLUTE: - get = exp . X_add_number; - use = get & unmask; - if ((get & mask) && (get & mask) != mask) - { /* Leading bits contain both 0s & 1s. */ - as_warn("Value 0x%x truncated to 0x%x.", get, use); - } - md_number_to_chars (p, use, nbytes); /* put bytes in right order. */ - break; - - case SEG_DIFFERENCE: + + if (!need_pass_2) { /* Still worthwhile making frags. */ + + /* Don't call this if we are going to junk this pass anyway! */ + know(segment != SEG_PASS1); + + if (segment == SEG_DIFFERENCE && exp.X_add_symbol == NULL) { + as_bad("Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.", + S_GET_NAME(exp.X_subtract_symbol), + segment_name(S_GET_SEGMENT(exp.X_subtract_symbol))); + segment = SEG_ABSOLUTE; + /* Leave exp . X_add_number alone. */ + } + p = frag_more(nbytes); + switch (segment) { + case SEG_BIG: + as_bad("%s number invalid. Absolute 0 assumed.", + exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); + md_number_to_chars (p, (long)0, nbytes); + break; + + case SEG_ABSENT: + as_warn("0 assumed for missing expression"); + exp . X_add_number = 0; + know(exp . X_add_symbol == NULL); + /* fall into SEG_ABSOLUTE */ + case SEG_ABSOLUTE: + get = exp . X_add_number; + use = get & unmask; + if ((get & mask) && (get & mask) != mask) + { /* Leading bits contain both 0s & 1s. */ + as_warn("Value 0x%x truncated to 0x%x.", get, use); + } + md_number_to_chars (p, use, nbytes); /* put bytes in right order. */ + break; + + case SEG_DIFFERENCE: #ifndef WORKING_DOT_WORD - if (nbytes==2) { - struct broken_word *x; - - x=(struct broken_word *)xmalloc(sizeof(struct broken_word)); - x->next_broken_word=broken_words; - broken_words=x; - x->frag=frag_now; - x->word_goes_here=p; - x->dispfrag=0; - x->add=exp.X_add_symbol; - x->sub=exp.X_subtract_symbol; - x->addnum=exp.X_add_number; - x->added=0; - new_broken_words++; - break; - } - /* Else Fall through into. . . */ + if (nbytes==2) { + struct broken_word *x; + + x=(struct broken_word *)xmalloc(sizeof(struct broken_word)); + x->next_broken_word=broken_words; + broken_words=x; + x->frag=frag_now; + x->word_goes_here=p; + x->dispfrag=0; + x->add=exp.X_add_symbol; + x->sub=exp.X_subtract_symbol; + x->addnum=exp.X_add_number; + x->added=0; + new_broken_words++; + break; + } + /* Else Fall through into. . . */ #endif - default: - case SEG_UNKNOWN: + default: + case SEG_UNKNOWN: #ifdef TC_NS32K - fix_new_ns32k(frag_now, p - frag_now->fr_literal, nbytes, - exp.X_add_symbol, exp.X_subtract_symbol, - exp.X_add_number, 0, 0, 2, 0, 0); + fix_new_ns32k (frag_now, p - frag_now->fr_literal, nbytes, + exp . X_add_symbol, exp . X_subtract_symbol, + exp . X_add_number, 0, 0, 2, 0, 0); #else - fix_new(frag_now, p - frag_now->fr_literal, nbytes, - exp.X_add_symbol, exp.X_subtract_symbol, - exp.X_add_number, 0, RELOC_32); +# if defined(TC_SPARC) || defined(TC_A29K) + fix_new (frag_now, p - frag_now->fr_literal, nbytes, + exp . X_add_symbol, exp . X_subtract_symbol, + exp . X_add_number, 0, RELOC_32); +# else +# if defined(TC_H8300) + fix_new (frag_now, p - frag_now->fr_literal, nbytes, + exp . X_add_symbol, exp . X_subtract_symbol, + exp . X_add_number, 0, R_RELWORD); + +# else + fix_new (frag_now, p - frag_now->fr_literal, nbytes, + exp . X_add_symbol, exp . X_subtract_symbol, + exp . X_add_number, 0, 0); + +# endif /* tc_h8300 */ +# endif /* tc_sparc|tc_a29k */ #endif /* TC_NS32K */ - break; - } /* switch(segment) */ - } /* if (!need_pass_2) */ - c = *input_line_pointer++; - } /* while(c==',') */ - input_line_pointer--; /* Put terminator back into stream. */ - demand_empty_rest_of_line(); + break; + } /* switch(segment) */ + } /* if (!need_pass_2) */ + c = *input_line_pointer++; + } /* while(c==',') */ + input_line_pointer--; /* Put terminator back into stream. */ + demand_empty_rest_of_line(); } /* cons() */ /* @@ -1597,124 +1799,124 @@ register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */ /* 8=.quad 16=.octa ... */ void big_cons(nbytes) -register int nbytes; + register int nbytes; { - register char c; /* input_line_pointer->c. */ - register int radix; - register long length; /* Number of chars in an object. */ - register int digit; /* Value of 1 digit. */ - register int carry; /* For multi-precision arithmetic. */ - register int work; /* For multi-precision arithmetic. */ - register char * p; /* For multi-precision arithmetic. */ - - extern char hex_value[]; /* In hex_value.c. */ - - /* - * The following awkward logic is to parse ZERO or more strings, - * comma seperated. Recall an expression includes its leading & - * trailing blanks. We fake a leading ',' if there is (supposed to - * be) a 1st expression, and keep demanding 1 expression for each ','. - */ - if (is_it_end_of_statement()) + register char c; /* input_line_pointer->c. */ + register int radix; + register long length; /* Number of chars in an object. */ + register int digit; /* Value of 1 digit. */ + register int carry; /* For multi-precision arithmetic. */ + register int work; /* For multi-precision arithmetic. */ + register char * p; /* For multi-precision arithmetic. */ + + extern char hex_value[]; /* In hex_value.c. */ + + /* + * The following awkward logic is to parse ZERO or more strings, + * comma seperated. Recall an expression includes its leading & + * trailing blanks. We fake a leading ',' if there is (supposed to + * be) a 1st expression, and keep demanding 1 expression for each ','. + */ + if (is_it_end_of_statement()) + { + c = 0; /* Skip loop. */ + } + else + { + c = ','; /* Do loop. */ + -- input_line_pointer; + } + while (c == ',') + { + ++ input_line_pointer; + SKIP_WHITESPACE(); + c = * input_line_pointer; + /* C contains 1st non-blank character of what we hope is a number. */ + if (c == '0') + { + c = * ++ input_line_pointer; + if (c == 'x' || c=='X') { - c = 0; /* Skip loop. */ + c = * ++ input_line_pointer; + radix = 16; } - else + else { - c = ','; /* Do loop. */ - -- input_line_pointer; + radix = 8; } - while (c == ',') + } + else + { + radix = 10; + } + /* + * This feature (?) is here to stop people worrying about + * mysterious zero constants: which is what they get when + * they completely omit digits. + */ + if (hex_value[c] >= radix) { + as_bad("Missing digits. 0 assumed."); + } + bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ + for(; (digit = hex_value [c]) < radix; c = * ++ input_line_pointer) + { + /* Multiply existing number by radix, then add digit. */ + carry = digit; + for (p=bignum_low; p <= bignum_high; p++) { - ++ input_line_pointer; - SKIP_WHITESPACE(); - c = * input_line_pointer; - /* C contains 1st non-blank character of what we hope is a number. */ - if (c == '0') - { - c = * ++ input_line_pointer; - if (c == 'x' || c=='X') - { - c = * ++ input_line_pointer; - radix = 16; - } - else - { - radix = 8; - } - } - else - { - radix = 10; - } - /* - * This feature (?) is here to stop people worrying about - * mysterious zero constants: which is what they get when - * they completely omit digits. - */ - if (hex_value[c] >= radix) { - as_bad("Missing digits. 0 assumed."); - } - bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ - for(; (digit = hex_value [c]) < radix; c = * ++ input_line_pointer) - { - /* Multiply existing number by radix, then add digit. */ - carry = digit; - for (p=bignum_low; p <= bignum_high; p++) - { - work = (*p & MASK_CHAR) * radix + carry; - *p = work & MASK_CHAR; - carry = work >> BITS_PER_CHAR; - } - if (carry) - { - grow_bignum(); - * bignum_high = carry & MASK_CHAR; - know((carry & ~ MASK_CHAR) == 0); - } - } - length = bignum_high - bignum_low + 1; - if (length > nbytes) - { - as_warn("Most significant bits truncated in integer constant."); - } - else - { - register long leading_zeroes; - - for(leading_zeroes = nbytes - length; - leading_zeroes; - leading_zeroes --) - { - grow_bignum(); - * bignum_high = 0; - } - } - if (! need_pass_2) - { - p = frag_more (nbytes); - memcpy(p, bignum_low, (int) nbytes); - } - /* C contains character after number. */ - SKIP_WHITESPACE(); - c = *input_line_pointer; - /* C contains 1st non-blank character after number. */ + work = (*p & MASK_CHAR) * radix + carry; + *p = work & MASK_CHAR; + carry = work >> BITS_PER_CHAR; } - demand_empty_rest_of_line(); -} /* big_cons() */ + if (carry) + { + grow_bignum(); + * bignum_high = carry & MASK_CHAR; + know((carry & ~ MASK_CHAR) == 0); + } + } + length = bignum_high - bignum_low + 1; + if (length > nbytes) + { + as_warn("Most significant bits truncated in integer constant."); + } + else + { + register long leading_zeroes; -/* Extend bignum by 1 char. */ -static void grow_bignum() { - register long length; - - bignum_high ++; - if (bignum_high >= bignum_limit) + for(leading_zeroes = nbytes - length; + leading_zeroes; + leading_zeroes --) { - length = bignum_limit - bignum_low; - bignum_low = xrealloc(bignum_low, length + length); - bignum_high = bignum_low + length; - bignum_limit = bignum_low + length + length; + grow_bignum(); + * bignum_high = 0; } + } + if (! need_pass_2) + { + p = frag_more (nbytes); + bcopy (bignum_low, p, (int)nbytes); + } + /* C contains character after number. */ + SKIP_WHITESPACE(); + c = * input_line_pointer; + /* C contains 1st non-blank character after number. */ + } + demand_empty_rest_of_line(); +} /* big_cons() */ + + /* Extend bignum by 1 char. */ +static void grow_bignum() { + register long length; + + bignum_high ++; + if (bignum_high >= bignum_limit) + { + length = bignum_limit - bignum_low; + bignum_low = xrealloc(bignum_low, length + length); + bignum_high = bignum_low + length; + bignum_limit = bignum_low + length + length; + } } /* grow_bignum(); */ /* @@ -1738,65 +1940,70 @@ static void grow_bignum() { */ void /* JF was static, but can't be if VAX.C is goning to use it */ - float_cons(float_type) /* Worker to do .float etc statements. */ -/* Clobbers input_line-pointer, checks end-of-line. */ -register int float_type; /* 'f':.ffloat ... 'F':.float ... */ +float_cons(float_type) /* Worker to do .float etc statements. */ + /* Clobbers input_line-pointer, checks end-of-line. */ + register int float_type; /* 'f':.ffloat ... 'F':.float ... */ { - register char * p; - register char c; - int length; /* Number of chars in an object. */ - register char * err; /* Error from scanning floating literal. */ - char temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; - - /* - * The following awkward logic is to parse ZERO or more strings, - * comma seperated. Recall an expression includes its leading & - * trailing blanks. We fake a leading ',' if there is (supposed to - * be) a 1st expression, and keep demanding 1 expression for each ','. - */ - if (is_it_end_of_statement()) - { - c = 0; /* Skip loop. */ - ++ input_line_pointer; /*->past termintor. */ - } - else + register char * p; + register char c; + int length; /* Number of chars in an object. */ + register char * err; /* Error from scanning floating literal. */ + char temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; + + /* + * The following awkward logic is to parse ZERO or more strings, + * comma seperated. Recall an expression includes its leading & + * trailing blanks. We fake a leading ',' if there is (supposed to + * be) a 1st expression, and keep demanding 1 expression for each ','. + */ + if (is_it_end_of_statement()) + { + c = 0; /* Skip loop. */ + ++ input_line_pointer; /*->past termintor. */ + } + else + { + c = ','; /* Do loop. */ + } + while (c == ',') + { + /* input_line_pointer->1st char of a flonum (we hope!). */ + SKIP_WHITESPACE(); + /* Skip any 0{letter} that may be present. Don't even check if the + * letter is legal. Someone may invent a "z" format and this routine + * has no use for such information. Lusers beware: you get + * diagnostics if your input is ill-conditioned. + */ + + if (input_line_pointer[0]=='0' && isalpha(input_line_pointer[1])) + input_line_pointer+=2; + + err = md_atof (float_type, temp, &length); + know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); + know(length > 0); + if (* err) + { + as_bad("Bad floating literal: %s", err); + ignore_rest_of_line(); + /* Input_line_pointer->just after end-of-line. */ + c = 0; /* Break out of loop. */ + } + else + { + if (! need_pass_2) { - c = ','; /* Do loop. */ + p = frag_more (length); + bcopy (temp, p, length); } - while (c == ',') { - /* input_line_pointer->1st char of a flonum (we hope!). */ - SKIP_WHITESPACE(); - /* Skip any 0{letter} that may be present. Don't even check if the - * letter is legal. Someone may invent a "z" format and this routine - * has no use for such information. Lusers beware: you get - * diagnostics if your input is ill-conditioned. - */ - - if (input_line_pointer[0]=='0' && isalpha(input_line_pointer[1])) - input_line_pointer+=2; - - err = md_atof (float_type, temp, &length); - know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); - know(length > 0); - if (* err) { - as_bad("Bad floating literal: %s", err); - ignore_rest_of_line(); - /* Input_line_pointer->just after end-of-line. */ - c = 0; /* Break out of loop. */ - } else { - if (! need_pass_2) { - p = frag_more (length); - memcpy(p, temp, length); - } - SKIP_WHITESPACE(); - c = *input_line_pointer++; - /* C contains 1st non-white character after number. */ - /* input_line_pointer->just after terminator (c). */ - } + SKIP_WHITESPACE(); + c = * input_line_pointer ++; + /* C contains 1st non-white character after number. */ + /* input_line_pointer->just after terminator (c). */ } - --input_line_pointer; /*->terminator (is not ','). */ - demand_empty_rest_of_line(); -} /* float_cons() */ + } + -- input_line_pointer; /*->terminator (is not ','). */ + demand_empty_rest_of_line(); +} /* float_cons() */ /* * stringer() @@ -1808,65 +2015,72 @@ register int float_type; /* 'f':.ffloat ... 'F':.float ... */ void stringer(append_zero ) /* Worker to do .ascii etc statements. */ -/* Checks end-of-line. */ -register int append_zero; /* 0: don't append '\0', else 1 */ + /* Checks end-of-line. */ + register int append_zero; /* 0: don't append '\0', else 1 */ { - unsigned int c; - - /* - * The following awkward logic is to parse ZERO or more strings, - * comma seperated. Recall a string expression includes spaces - * before the opening '\"' and spaces after the closing '\"'. - * We fake a leading ',' if there is (supposed to be) - * a 1st, expression. We keep demanding expressions for each - * ','. - */ - if (is_it_end_of_statement()) { - c = 0; /* Skip loop. */ - ++ input_line_pointer; /* Compensate for end of loop. */ - } else { - c = ','; /* Do loop. */ - } - - while (c == ',' || c == '<' || c == '"') { - SKIP_WHITESPACE(); - switch (*input_line_pointer) { - case '\"': - ++input_line_pointer; /*->1st char of string. */ - while (is_a_char(c = next_char_of_string())) { - FRAG_APPEND_1_CHAR(c); - } - if (append_zero) { - FRAG_APPEND_1_CHAR(0); - } - know(input_line_pointer [-1] == '\"'); - break; - case '<': - input_line_pointer++; - c =get_single_number(); - FRAG_APPEND_1_CHAR(c); - if(*input_line_pointer != '>') { - as_bad("Expected <nn>"); - } - input_line_pointer++; - break; - case ',': - input_line_pointer++; - break; - } - SKIP_WHITESPACE(); - c = *input_line_pointer; - } - - demand_empty_rest_of_line(); + /* register char * p; JF unused */ + /* register int length; JF unused */ /* Length of string we read, excluding */ + /* trailing '\0' implied by closing quote. */ + /* register char * where; JF unused */ + /* register fragS * fragP; JF unused */ + register unsigned int c; + + /* + * The following awkward logic is to parse ZERO or more strings, + * comma seperated. Recall a string expression includes spaces + * before the opening '\"' and spaces after the closing '\"'. + * We fake a leading ',' if there is (supposed to be) + * a 1st, expression. We keep demanding expressions for each + * ','. + */ + if (is_it_end_of_statement()) + { + c = 0; /* Skip loop. */ + ++ input_line_pointer; /* Compensate for end of loop. */ + } + else + { + c = ','; /* Do loop. */ + } + while (c == ',' || c == '<' || c == '"' ) { + SKIP_WHITESPACE(); + switch (*input_line_pointer) { + case '\"': + ++input_line_pointer; /*->1st char of string. */ + while (is_a_char(c = next_char_of_string())) { + FRAG_APPEND_1_CHAR(c); + } + if (append_zero) { + FRAG_APPEND_1_CHAR(0); + } + know(input_line_pointer [-1] == '\"'); + break; + case '<': + input_line_pointer++; + c =get_single_number(); + FRAG_APPEND_1_CHAR(c); + if(*input_line_pointer != '>') { + as_bad("Expected <nn>"); + } + input_line_pointer++; + break; + case ',': + input_line_pointer++; + break; + } + SKIP_WHITESPACE(); + c = *input_line_pointer; + } + + demand_empty_rest_of_line(); } /* stringer() */ -/* FIXME-SOMEDAY: I had trouble here on characters with the - high bits set. We'll probably also have trouble with - multibyte chars, wide chars, etc. Also be careful about - returning values bigger than 1 byte. xoxorich. */ + /* FIXME-SOMEDAY: I had trouble here on characters with the + high bits set. We'll probably also have trouble with + multibyte chars, wide chars, etc. Also be careful about + returning values bigger than 1 byte. xoxorich. */ -unsigned int next_char_of_string() { + unsigned int next_char_of_string() { register unsigned int c; c = *input_line_pointer++ & CHAR_MASK; @@ -1951,80 +2165,80 @@ unsigned int next_char_of_string() { } /* next_char_of_string() */ static segT - get_segmented_expression (expP) -register expressionS * expP; +get_segmented_expression (expP) + register expressionS * expP; { - register segT retval; - - if ((retval = expression(expP)) == SEG_PASS1 || retval == SEG_ABSENT || retval == SEG_BIG) - { - as_bad("Expected address expression: absolute 0 assumed"); - retval = expP->X_seg = SEG_ABSOLUTE; - expP->X_add_number = 0; - expP->X_add_symbol = expP->X_subtract_symbol = 0; - } - return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */ + register segT retval; + + if ((retval = expression(expP)) == SEG_PASS1 || retval == SEG_ABSENT || retval == SEG_BIG) + { + as_bad("Expected address expression: absolute 0 assumed"); + retval = expP->X_seg = SEG_ABSOLUTE; + expP->X_add_number = 0; + expP->X_add_symbol = expP->X_subtract_symbol = 0; + } + return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */ } static segT get_known_segmented_expression(expP) register expressionS *expP; { - register segT retval; - register char * name1; - register char * name2; - - if ((retval = get_segmented_expression (expP)) == SEG_UNKNOWN) - { - name1 = expP->X_add_symbol ? S_GET_NAME(expP->X_add_symbol) : ""; - name2 = expP->X_subtract_symbol ? - S_GET_NAME(expP->X_subtract_symbol) : - ""; - if (name1 && name2) - { - as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.", - name1, name2); - } - else - { - as_warn("Symbol \"%s\" undefined: absolute 0 assumed.", - name1 ? name1 : name2); - } - retval = expP->X_seg = SEG_ABSOLUTE; - expP->X_add_number = 0; - expP->X_add_symbol = expP->X_subtract_symbol = NULL; - } + register segT retval; + register char * name1; + register char * name2; + + if ((retval = get_segmented_expression (expP)) == SEG_UNKNOWN) + { + name1 = expP->X_add_symbol ? S_GET_NAME(expP->X_add_symbol) : ""; + name2 = expP->X_subtract_symbol ? + S_GET_NAME(expP->X_subtract_symbol) : + ""; + if (name1 && name2) + { + as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.", + name1, name2); + } + else + { + as_warn("Symbol \"%s\" undefined: absolute 0 assumed.", + name1 ? name1 : name2); + } + retval = expP->X_seg = SEG_ABSOLUTE; + expP->X_add_number = 0; + expP->X_add_symbol = expP->X_subtract_symbol = NULL; + } #ifndef MANY_SEGMENTS - know(retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE); + know(retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE); #endif - return (retval); - + return (retval); + } /* get_known_segmented_expression() */ /* static */ long /* JF was static, but can't be if the MD pseudos are to use it */ - get_absolute_expression () +get_absolute_expression () { - expressionS exp; - register segT s; - - if ((s = expression(& exp)) != SEG_ABSOLUTE) - { - if (s != SEG_ABSENT) - { - as_bad("Bad Absolute Expression, absolute 0 assumed."); - } - exp . X_add_number = 0; - } - return (exp . X_add_number); + expressionS exp; + register segT s; + + if ((s = expression(& exp)) != SEG_ABSOLUTE) + { + if (s != SEG_ABSENT) + { + as_bad("Bad Absolute Expression, absolute 0 assumed."); + } + exp . X_add_number = 0; + } + return (exp . X_add_number); } char /* return terminator */ - get_absolute_expression_and_terminator(val_pointer) -long * val_pointer; /* return value of expression */ +get_absolute_expression_and_terminator(val_pointer) + long * val_pointer; /* return value of expression */ { - * val_pointer = get_absolute_expression (); - return (* input_line_pointer ++); + * val_pointer = get_absolute_expression (); + return (* input_line_pointer ++); } /* @@ -2034,29 +2248,29 @@ long * val_pointer; /* return value of expression */ * Give a warning if that happens. */ char * - demand_copy_C_string (len_pointer) -int * len_pointer; +demand_copy_C_string (len_pointer) + int * len_pointer; { - register char * s; - - if ((s = demand_copy_string(len_pointer)) != 0) + register char * s; + + if ((s = demand_copy_string(len_pointer)) != 0) + { + register int len; + + for (len = * len_pointer; + len > 0; + len--) + { + if (* s == 0) { - register int len; - - for (len = * len_pointer; - len > 0; - len--) - { - if (* s == 0) - { - s = 0; - len = 1; - * len_pointer = 0; - as_bad("This string may not contain \'\\0\'"); - } - } + s = 0; + len = 1; + * len_pointer = 0; + as_bad("This string may not contain \'\\0\'"); } - return (s); + } + } + return (s); } /* @@ -2102,44 +2316,44 @@ int *lenP; * Do: Skip input_line_pointer over all whitespace. * * Out: 1 if input_line_pointer->end-of-line. - */ +*/ int is_it_end_of_statement() { - SKIP_WHITESPACE(); - return (is_end_of_line [* input_line_pointer]); + SKIP_WHITESPACE(); + return (is_end_of_line [* input_line_pointer]); } /* is_it_end_of_statement() */ void equals(sym_name) char *sym_name; { - register symbolS *symbolP; /* symbol we are working with */ - - input_line_pointer++; - if (*input_line_pointer=='=') - input_line_pointer++; - - while(*input_line_pointer==' ' || *input_line_pointer=='\t') - input_line_pointer++; - - if (sym_name[0]=='.' && sym_name[1]=='\0') { - /* Turn '. = mumble' into a .org mumble */ - register segT segment; - expressionS exp; - register char *p; - - segment = get_known_segmented_expression(& exp); - if (! need_pass_2) { - if (segment != now_seg && segment != SEG_ABSOLUTE) - as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", - segment_name(segment), - segment_name(now_seg)); - p = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, - exp.X_add_number, (char *)0); - * p = 0; - } /* if (ok to make frag) */ - } else { - symbolP=symbol_find_or_make(sym_name); - pseudo_set(symbolP); - } + register symbolS *symbolP; /* symbol we are working with */ + + input_line_pointer++; + if (*input_line_pointer=='=') + input_line_pointer++; + + while(*input_line_pointer==' ' || *input_line_pointer=='\t') + input_line_pointer++; + + if (sym_name[0]=='.' && sym_name[1]=='\0') { + /* Turn '. = mumble' into a .org mumble */ + register segT segment; + expressionS exp; + register char *p; + + segment = get_known_segmented_expression(& exp); + if (! need_pass_2) { + if (segment != now_seg && segment != SEG_ABSOLUTE) + as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", + segment_name(segment), + segment_name(now_seg)); + p = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, + exp.X_add_number, (char *)0); + * p = 0; + } /* if (ok to make frag) */ + } else { + symbolP=symbol_find_or_make(sym_name); + pseudo_set(symbolP); + } } /* equals() */ /* .include -- include a file at this point. */ @@ -2148,68 +2362,68 @@ char *sym_name; void s_include(arg) int arg; { - char *newbuf; - char *filename; - int i; - FILE *try; - char *path; - - filename = demand_copy_string(&i); - demand_empty_rest_of_line(); - path = xmalloc(i + include_dir_maxlen + 5 /* slop */); - for (i = 0; i < include_dir_count; i++) { - strcpy(path, include_dirs[i]); - strcat(path, "/"); - strcat(path, filename); - if (0 != (try = fopen(path, "r"))) - { - fclose (try); - goto gotit; - } - } - free(path); - path = filename; - gotit: - /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ - newbuf = input_scrub_include_file (path, input_line_pointer); - buffer_limit = input_scrub_next_buffer (&input_line_pointer); + char *newbuf; + char *filename; + int i; + FILE *try; + char *path; + + filename = demand_copy_string(&i); + demand_empty_rest_of_line(); + path = xmalloc(i + include_dir_maxlen + 5 /* slop */); + for (i = 0; i < include_dir_count; i++) { + strcpy(path, include_dirs[i]); + strcat(path, "/"); + strcat(path, filename); + if (0 != (try = fopen(path, "r"))) + { + fclose (try); + goto gotit; + } + } + free(path); + path = filename; +gotit: + /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ + newbuf = input_scrub_include_file (path, input_line_pointer); + buffer_limit = input_scrub_next_buffer (&input_line_pointer); } /* s_include() */ void add_include_dir(path) char *path; { - int i; - - if (include_dir_count == 0) - { - include_dirs = (char **)xmalloc (2 * sizeof (*include_dirs)); - include_dirs[0] = "."; /* Current dir */ - include_dir_count = 2; - } - else - { - include_dir_count++; - include_dirs = (char **) realloc(include_dirs, - include_dir_count*sizeof (*include_dirs)); - } - - include_dirs[include_dir_count-1] = path; /* New one */ - - i = strlen (path); - if (i > include_dir_maxlen) - include_dir_maxlen = i; + int i; + + if (include_dir_count == 0) + { + include_dirs = (char **)xmalloc (2 * sizeof (*include_dirs)); + include_dirs[0] = "."; /* Current dir */ + include_dir_count = 2; + } + else + { + include_dir_count++; + include_dirs = (char **) realloc(include_dirs, + include_dir_count*sizeof (*include_dirs)); + } + + include_dirs[include_dir_count-1] = path; /* New one */ + + i = strlen (path); + if (i > include_dir_maxlen) + include_dir_maxlen = i; } /* add_include_dir() */ void s_ignore(arg) int arg; { extern char is_end_of_line[]; - + while (!is_end_of_line[*input_line_pointer]) { ++input_line_pointer; } ++input_line_pointer; - + return; } /* s_ignore() */ |