X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fread.c;h=f8d5d7e0066d4964e3e43fede782d38aa21ad01c;hb=053c44e1bfece752ad00adbab7a4ceb57726eb1c;hp=08084af71113abace1d834f78e30a3ea35041c61;hpb=20868ec6471a8307f1c8650aa274437919136d6c;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/read.c b/gas/read.c index 08084af711..f8d5d7e006 100644 --- a/gas/read.c +++ b/gas/read.c @@ -1,6 +1,6 @@ /* read.c - read a source file - - Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996 - Free Software Foundation, Inc. + Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, + 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -15,32 +15,28 @@ 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with GAS; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ #if 0 -#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will - change this a bit. But then, GNU isn't - spozed to run on your machine anyway. - (RMS is so shortsighted sometimes.) - */ +/* If your chars aren't 8 bits, you will change this a bit. + But then, GNU isn't spozed to run on your machine anyway. + (RMS is so shortsighted sometimes.) */ +#define MASK_CHAR (0xFF) #else -#define MASK_CHAR ((int)(unsigned char)-1) +#define MASK_CHAR ((int)(unsigned char) -1) #endif - /* This is the largest known floating point format (for now). It will - grow when we do 4361 style flonums. */ - + grow when we do 4361 style flonums. */ #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) /* Routines that read assembler source text to build spagetti in memory. Another group of these functions is in the expr.c module. */ -/* for isdigit() */ -#include - #include "as.h" +#include "safe-ctype.h" #include "subsegs.h" #include "sb.h" #include "macro.h" @@ -49,20 +45,27 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 #include "ecoff.h" #ifndef TC_START_LABEL -#define TC_START_LABEL(x,y) (x==':') +#define TC_START_LABEL(x,y) (x == ':') #endif -/* The NOP_OPCODE is for the alignment fill value. - * fill it a nop instruction so that the disassembler does not choke - * on it - */ -#ifndef NOP_OPCODE -#define NOP_OPCODE 0x00 +/* Set by the object-format or the target. */ +#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT +#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ + do \ + { \ + if ((SIZE) >= 8) \ + (P2VAR) = 3; \ + else if ((SIZE) >= 4) \ + (P2VAR) = 2; \ + else if ((SIZE) >= 2) \ + (P2VAR) = 1; \ + else \ + (P2VAR) = 0; \ + } \ + while (0) #endif -char *input_line_pointer; /*->next char of source file to parse. */ - -int generate_asm_lineno = 0; /* flag to generate line stab for .s file */ +char *input_line_pointer; /*->next char of source file to parse. */ #if BITS_PER_CHAR != 8 /* The following table is indexed by[(char)] and will break if @@ -90,91 +93,95 @@ die horribly; #define LEX_QM 0 #endif +#ifndef LEX_HASH +/* The IA-64 assembler uses # as a suffix designating a symbol. We include + it in the symbol and strip it out in tc_canonicalize_symbol_name. */ +#define LEX_HASH 0 +#endif + #ifndef LEX_DOLLAR /* The a29k assembler does not permits labels to start with $. */ #define LEX_DOLLAR 3 #endif -/* used by is_... macros. our ctype[] */ -char lex_type[256] = -{ +#ifndef LEX_TILDE +/* The Delta 68k assembler permits ~ at start of label names. */ +#define LEX_TILDE 0 +#endif + +/* Used by is_... macros. our ctype[]. */ +char 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, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ + 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 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, LEX_QM, /* 0123456789:;<=>? */ LEX_AT, 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, LEX_BR, 0, LEX_BR, 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, LEX_BR, 0, LEX_BR, 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; - -/* - * In: a character. - * Out: 1 if this character ends a line. - */ -#define _ (0) -char is_end_of_line[256] = -{ +/* In: a character. + Out: 1 if this character ends a line. */ +char is_end_of_line[256] = { #ifdef CR_EOL - _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */ -#else - _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */ -#endif - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ -#ifdef TC_HPPA - _,99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* _!"#$%&'()*+,-./ */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0123456789:;<=>? */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */ #else - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */ #endif - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ + 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, /* 0123456789:;<=>? */ + 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, /* */ + 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 /* */ }; -#undef _ -/* Functions private to this file. */ +#ifdef IGNORE_OPCODE_CASE +char original_case_string[128]; +#endif + +/* Functions private to this file. */ -static char *buffer; /* 1st char of each buffer of lines is here. */ -static char *buffer_limit; /*->1 + last char in buffer. */ +static char *buffer; /* 1st char of each buffer of lines is here. */ +static char *buffer_limit; /*->1 + last char in buffer. */ -#ifdef TARGET_BYTES_BIG_ENDIAN -/* Hack to deal with tc-*.h defining TARGET_BYTES_BIG_ENDIAN to empty - instead of to 0 or 1. */ -#if 5 - TARGET_BYTES_BIG_ENDIAN - 5 == 10 -#undef TARGET_BYTES_BIG_ENDIAN -#define TARGET_BYTES_BIG_ENDIAN 1 -#endif +/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 + in the tc-.h file. See the "Porting GAS" section of the + internals manual. */ int target_big_endian = TARGET_BYTES_BIG_ENDIAN; -#else -int target_big_endian /* = 0 */; -#endif -static char *old_buffer; /* JF a hack */ +static char *old_buffer; /* JF a hack. */ static char *old_input; static char *old_limit; -/* Variables for handling include file directory list. */ +/* Variables for handling include file directory table. */ + +/* Table of pointers to directories to search for .include's. */ +char **include_dirs; + +/* How many are in the table. */ +int include_dir_count; -char **include_dirs; /* List of pointers to directories to - search for .include's */ -int include_dir_count; /* How many are in the list */ -int include_dir_maxlen = 1;/* Length of longest in list */ +/* Length of longest in table. */ +int include_dir_maxlen = 1; #ifndef WORKING_DOT_WORD struct broken_word *broken_words; @@ -201,17 +208,36 @@ symbolS *mri_common_symbol; may be needed. */ static int mri_pending_align; -static int scrub_from_string PARAMS ((char **)); -static void do_align PARAMS ((int, char *, int)); +#ifndef NO_LISTING +#ifdef OBJ_ELF +/* This variable is set to be non-zero if the next string we see might + be the name of the source file in DWARF debugging information. See + the comment in emit_expr for the format we look for. */ +static int dwarf_file_string; +#endif +#endif + +static void cons_worker PARAMS ((int, int)); +static int scrub_from_string PARAMS ((char *, int)); +static void do_align PARAMS ((int, char *, int, int)); +static void s_align PARAMS ((int, int)); +static void s_lcomm_internal PARAMS ((int, int)); static int hex_float PARAMS ((int, char *)); +static inline int sizeof_sleb128 PARAMS ((offsetT)); +static inline int sizeof_uleb128 PARAMS ((valueT)); +static inline int output_sleb128 PARAMS ((char *, offsetT)); +static inline int output_uleb128 PARAMS ((char *, valueT)); +static inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int)); +static inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int)); +static int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int)); static void do_org PARAMS ((segT, expressionS *, int)); char *demand_copy_string PARAMS ((int *lenP)); static segT get_segmented_expression PARAMS ((expressionS *expP)); static segT get_known_segmented_expression PARAMS ((expressionS * expP)); static void pobegin PARAMS ((void)); static int get_line_sb PARAMS ((sb *)); +static void generate_file_debug PARAMS ((void)); - void read_begin () { @@ -225,21 +251,20 @@ read_begin () obstack_begin (¬es, chunksize); obstack_begin (&cond_obstack, chunksize); - /* Use machine dependent syntax */ + /* Use machine dependent syntax. */ for (p = line_separator_chars; *p; p++) is_end_of_line[(unsigned char) *p] = 1; - /* Use more. FIXME-SOMEDAY. */ + /* Use more. FIXME-SOMEDAY. */ if (flag_mri) lex_type['?'] = 3; } -/* set up pseudo-op tables */ +/* Set up pseudo-op tables. */ static struct hash_control *po_hash; -static const pseudo_typeS potable[] = -{ +static const pseudo_typeS potable[] = { {"abort", s_abort, 0}, {"align", s_align_ptwo, 0}, {"ascii", stringer, 0}, @@ -247,7 +272,7 @@ static const pseudo_typeS potable[] = {"balign", s_align_bytes, 0}, {"balignw", s_align_bytes, -2}, {"balignl", s_align_bytes, -4}, -/* block */ +/* block */ {"byte", cons, 1}, {"comm", s_comm, 0}, {"common", s_mri_common, 0}, @@ -279,21 +304,25 @@ static const pseudo_typeS potable[] = #ifdef S_SET_DESC {"desc", s_desc, 0}, #endif -/* dim */ +/* dim */ {"double", float_cons, 'd'}, -/* dsect */ - {"eject", listing_eject, 0}, /* Formfeed listing */ +/* dsect */ + {"eject", listing_eject, 0}, /* Formfeed listing. */ {"else", s_else, 0}, {"elsec", s_else, 0}, + {"elseif", s_elseif, (int) O_ne}, {"end", s_end, 0}, {"endc", s_endif, 0}, + {"endfunc", s_func, 1}, {"endif", s_endif, 0}, -/* endef */ + {"endr", s_bad_endr, 0}, +/* endef */ {"equ", s_set, 0}, + {"equiv", s_set, 1}, {"err", s_err, 0}, {"exitm", s_mexit, 0}, -/* extend */ - {"extern", s_ignore, 0}, /* We treat all undef as ext */ +/* extend */ + {"extern", s_ignore, 0}, /* We treat all undef as ext. */ {"appfile", s_app_file, 1}, {"appline", s_app_line, 0}, {"fail", s_fail, 0}, @@ -301,6 +330,7 @@ static const pseudo_typeS potable[] = {"fill", s_fill, 0}, {"float", float_cons, 'f'}, {"format", s_ignore, 0}, + {"func", s_func, 0}, {"global", s_globl, 0}, {"globl", s_globl, 0}, {"hword", cons, 2}, @@ -318,6 +348,7 @@ static const pseudo_typeS potable[] = {"ifne", s_if, (int) O_ne}, {"ifnes", s_ifeqs, 1}, {"ifnotdef", s_ifdef, 1}, + {"incbin", s_incbin, 0}, {"include", s_include, 0}, {"int", cons, 4}, {"irp", s_irp, 0}, @@ -325,9 +356,9 @@ static const pseudo_typeS potable[] = {"irpc", s_irp, 1}, {"irepc", s_irp, 1}, {"lcomm", s_lcomm, 0}, - {"lflags", listing_flags, 0}, /* Listing flags */ + {"lflags", listing_flags, 0}, /* Listing flags. */ {"linkonce", s_linkonce, 0}, - {"list", listing_list, 1}, /* Turn listing on */ + {"list", listing_list, 1}, /* Turn listing on. */ {"llen", listing_psize, 1}, {"long", cons, 4}, {"lsym", s_lsym, 0}, @@ -337,7 +368,7 @@ static const pseudo_typeS potable[] = {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */ {"name", s_ignore, 0}, {"noformat", s_ignore, 0}, - {"nolist", listing_list, 0}, /* Turn listing off */ + {"nolist", listing_list, 0}, /* Turn listing off. */ {"nopage", listing_nopage, 0}, {"octa", cons, 16}, {"offset", s_struct, 0}, @@ -348,28 +379,29 @@ static const pseudo_typeS potable[] = {"page", listing_eject, 0}, {"plen", listing_psize, 0}, {"print", s_print, 0}, - {"psize", listing_psize, 0}, /* set paper size */ + {"psize", listing_psize, 0}, /* Set paper size. */ {"purgem", s_purgem, 0}, {"quad", cons, 8}, {"rep", s_rept, 0}, {"rept", s_rept, 0}, {"rva", s_rva, 4}, - {"sbttl", listing_title, 1}, /* Subtitle of listing */ -/* scl */ -/* sect */ + {"sbttl", listing_title, 1}, /* Subtitle of listing. */ +/* scl */ +/* sect */ {"set", s_set, 0}, {"short", cons, 2}, {"single", float_cons, 'f'}, -/* size */ +/* size */ {"space", s_space, 0}, {"skip", s_space, 0}, + {"sleb128", s_leb128, 1}, {"spc", s_ignore, 0}, {"stabd", s_stab, 'd'}, {"stabn", s_stab, 'n'}, {"stabs", s_stab, 's'}, {"string", stringer, 1}, {"struct", s_struct, 0}, -/* tag */ +/* tag */ {"text", s_text, 0}, /* This is for gcc to use. It's only just been added (2/94), so gcc @@ -382,18 +414,19 @@ static const pseudo_typeS potable[] = this one. Match it either way... */ {"this_gcc_requires_the_gnu_assembler", s_ignore, 0}, - {"title", listing_title, 0}, /* Listing title */ + {"title", listing_title, 0}, /* Listing title. */ {"ttl", listing_title, 0}, -/* type */ -/* use */ -/* val */ +/* type */ + {"uleb128", s_leb128, 0}, +/* use */ +/* val */ {"xcom", s_comm, 0}, {"xdef", s_globl, 0}, {"xref", s_ignore, 0}, {"xstabs", s_xstab, 's'}, {"word", cons, 2}, {"zero", s_space, 0}, - {NULL} /* end sentinel */ + {NULL, NULL, 0} /* End sentinel. */ }; static int pop_override_ok = 0; @@ -409,7 +442,7 @@ pop_insert (table) { errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists"))) - as_fatal ("error constructing %s pseudo-op table: %s", pop_table_name, + as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name, errtxt); } } @@ -422,21 +455,21 @@ pop_insert (table) #define obj_pop_insert() pop_insert(obj_pseudo_table) #endif -static void +static void pobegin () { po_hash = hash_new (); - /* Do the target-specific pseudo ops. */ + /* Do the target-specific pseudo ops. */ pop_table_name = "md"; md_pop_insert (); - /* Now object specific. Skip any that were in the target table. */ + /* Now object specific. Skip any that were in the target table. */ pop_table_name = "obj"; pop_override_ok = 1; obj_pop_insert (); - /* Now portable ones. Skip any that we've seen already. */ + /* Now portable ones. Skip any that we've seen already. */ pop_table_name = "standard"; pop_insert (potable); } @@ -444,13 +477,12 @@ pobegin () #define HANDLE_CONDITIONAL_ASSEMBLY() \ if (ignore_input ()) \ { \ - while (! is_end_of_line[(unsigned char) *input_line_pointer++]) \ + while (!is_end_of_line[(unsigned char) *input_line_pointer++]) \ if (input_line_pointer == buffer_limit) \ break; \ continue; \ } - /* This function is used when scrubbing the characters between #APP and #NO_APP. */ @@ -458,67 +490,70 @@ static char *scrub_string; static char *scrub_string_end; static int -scrub_from_string (from) - char **from; +scrub_from_string (buf, buflen) + char *buf; + int buflen; { - int size; - - *from = scrub_string; - size = scrub_string_end - scrub_string; - scrub_string = scrub_string_end; - return size; + int copy; + + copy = scrub_string_end - scrub_string; + if (copy > buflen) + copy = buflen; + memcpy (buf, scrub_string, copy); + scrub_string += copy; + return copy; } -/* read_a_source_file() - * - * We read the file, putting things into a web that - * represents what we have been reading. - */ -void +/* We read the file, putting things into a web that represents what we + have been reading. */ +void read_a_source_file (name) char *name; { register char c; - register char *s; /* string of symbol, '\0' appended */ + register char *s; /* String of symbol, '\0' appended. */ register int temp; pseudo_typeS *pop; +#ifdef WARN_COMMENTS + found_comment = 0; +#endif + buffer = input_scrub_new_file (name); listing_file (name); - listing_newline (""); + listing_newline (NULL); + register_dependency (name); + + /* Generate debugging information before we've read anything in to denote + this file as the "main" source file and not a subordinate one + (e.g. N_SO vs N_SOL in stabs). */ + generate_file_debug (); 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. */ + { /* 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 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. - */ + /* 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 (is_end_of_line[(unsigned char) input_line_pointer[-1]]) { #ifdef md_start_line_hook md_start_line_hook (); #endif - if (input_line_pointer[-1] == '\n') bump_line_counters (); line_label = NULL; - if (flag_m68k_mri -#ifdef LABELS_WITHOUT_COLONS - || 1 -#endif - ) + if (LABELS_WITHOUT_COLONS || flag_m68k_mri) { /* Text at the start of a line must be a label, we run down and stick a colon in. */ @@ -526,13 +561,16 @@ read_a_source_file (name) { char *line_start = input_line_pointer; char c; + int mri_line_macro; + LISTING_NEWLINE (); HANDLE_CONDITIONAL_ASSEMBLY (); c = get_symbol_end (); - /* In MRI mode, the EQU pseudoop must be - handled specially. */ + /* In MRI mode, the EQU and MACRO pseudoops must + be handled specially. */ + mri_line_macro = 0; if (flag_m68k_mri) { char *rest = input_line_pointer + 1; @@ -546,12 +584,32 @@ read_a_source_file (name) && (rest[3] == ' ' || rest[3] == '\t')) { input_line_pointer = rest + 3; - equals (line_start); + equals (line_start, + strncasecmp (rest, "SET", 3) == 0); continue; } + if (strncasecmp (rest, "MACRO", 5) == 0 + && (rest[5] == ' ' + || rest[5] == '\t' + || is_end_of_line[(unsigned char) rest[5]])) + mri_line_macro = 1; } - line_label = colon (line_start); + /* In MRI mode, we need to handle the MACRO + pseudo-op specially: we don't want to put the + symbol in the symbol table. */ + if (!mri_line_macro +#ifdef TC_START_LABEL_WITHOUT_COLON + && TC_START_LABEL_WITHOUT_COLON(c, + input_line_pointer) +#endif + ) + line_label = colon (line_start); + else + line_label = symbol_create (line_start, + absolute_section, + (valueT) 0, + &zero_address_frag); *input_line_pointer = c; if (c == ':') @@ -560,108 +618,132 @@ read_a_source_file (name) } } - /* - * 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!) - */ + /* 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. */ + +#ifndef NO_LISTING + /* If listing is on, and we are expanding a macro, then give + the listing code the contents of the expanded line. */ + if (listing) { - c = *input_line_pointer++; + if ((listing & LISTING_MACEXP) && macro_nest > 0) + { + char *copy; + int len; + + /* Find the end of the current expanded macro line. */ + for (s = input_line_pointer - 1; *s; ++s) + if (is_end_of_line[(unsigned char) *s]) + break; + + /* Copy it for safe keeping. Also give an indication of + how much macro nesting is involved at this point. */ + len = s - (input_line_pointer - 1); + copy = (char *) xmalloc (len + macro_nest + 2); + memset (copy, '>', macro_nest); + copy[macro_nest] = ' '; + memcpy (copy + macro_nest + 1, input_line_pointer - 1, len); + copy[macro_nest + 1 + len] = '\0'; + + /* Install the line with the listing facility. */ + listing_newline (copy); + } + else + listing_newline (NULL); } - know (c != ' '); /* No further leading whitespace. */ - LISTING_NEWLINE (); - /* - * C is the 1st significant character. - * Input_line_pointer points after that character. - */ +#endif + /* 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 */ + /* 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 (TC_START_LABEL(c, 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 (TC_START_LABEL (c, input_line_pointer)) { if (flag_m68k_mri) { char *rest = input_line_pointer + 1; /* In MRI mode, \tsym: set 0 is permitted. */ - if (*rest == ':') ++rest; + if (*rest == ' ' || *rest == '\t') ++rest; + if ((strncasecmp (rest, "EQU", 3) == 0 || strncasecmp (rest, "SET", 3) == 0) && (rest[3] == ' ' || rest[3] == '\t')) { input_line_pointer = rest + 3; - equals (s); + equals (s, 1); continue; } } - line_label = colon (s); /* user-defined label */ - *input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */ - /* Input_line_pointer->after ':'. */ + line_label = colon (s); /* User-defined label. */ + /* Put ':' back for error messages' sake. */ + *input_line_pointer++ = ':'; + /* Input_line_pointer->after ':'. */ SKIP_WHITESPACE (); - - } else if (c == '=' - || (input_line_pointer[1] == '=' + || ((c == ' ' || c == '\t') + && input_line_pointer[1] == '=' #ifdef TC_EQUAL_IN_INSN - && ! TC_EQUAL_IN_INSN (c, input_line_pointer) + && !TC_EQUAL_IN_INSN (c, input_line_pointer) #endif )) { - equals (s); + equals (s, 1); demand_empty_rest_of_line (); } else - { /* expect pseudo-op or machine instruction */ + { + /* Expect pseudo-op or machine instruction. */ pop = NULL; -#define IGNORE_OPCODE_CASE #ifdef IGNORE_OPCODE_CASE { char *s2 = s; + + strncpy (original_case_string, s2, sizeof (original_case_string)); + original_case_string[sizeof (original_case_string) - 1] = 0; + while (*s2) { - if (isupper (*s2)) - *s2 = tolower (*s2); + *s2 = TOLOWER (*s2); s2++; } } #endif - - if (flag_m68k_mri -#ifdef NO_PSEUDO_DOT - || 1 -#endif - ) + if (NO_PSEUDO_DOT || flag_m68k_mri) { /* The MRI assembler and the m88k use pseudo-ops without a period. */ @@ -671,15 +753,13 @@ read_a_source_file (name) } if (pop != NULL - || (! flag_m68k_mri && *s == '.')) + || (!flag_m68k_mri && *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 '.'. - */ + /* 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 '.'. */ if (pop == NULL) pop = (pseudo_typeS *) hash_find (po_hash, s + 1); @@ -689,36 +769,52 @@ read_a_source_file (name) this is. */ if (mri_pending_align && (pop == NULL - || ! ((pop->poc_handler == cons - && pop->poc_val == 1) - || (pop->poc_handler == s_space - && pop->poc_val == 1)))) + || !((pop->poc_handler == cons + && pop->poc_val == 1) + || (pop->poc_handler == s_space + && pop->poc_val == 1) +#ifdef tc_conditional_pseudoop + || tc_conditional_pseudoop (pop) +#endif + || pop->poc_handler == s_if + || pop->poc_handler == s_ifdef + || pop->poc_handler == s_ifc + || pop->poc_handler == s_ifeqs + || pop->poc_handler == s_else + || pop->poc_handler == s_endif + || pop->poc_handler == s_globl + || pop->poc_handler == s_ignore))) { - do_align (1, (char *) NULL, 0); + do_align (1, (char *) NULL, 0, 0); mri_pending_align = 0; + + if (line_label != NULL) + { + symbol_set_frag (line_label, frag_now); + S_SET_VALUE (line_label, frag_now_fix ()); + } } - /* Print the error msg now, while we still can */ + /* Print the error msg now, while we still can. */ if (pop == NULL) { - as_bad ("Unknown pseudo-op: `%s'", s); + as_bad (_("unknown pseudo-op: `%s'"), s); *input_line_pointer = c; s_ignore (0); continue; } - /* Put it back for error messages etc. */ + /* 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. */ + keyword from operands. */ if (c == ' ' || c == '\t') input_line_pointer++; - /* - * Input_line is restored. - * Input_line_pointer->1st non-blank char - * after pseudo-operation. - */ + + /* Input_line is restored. + Input_line_pointer->1st non-blank char + after pseudo-operation. */ (*pop->poc_handler) (pop->poc_val); /* If that was .end, just get out now. */ @@ -728,9 +824,12 @@ read_a_source_file (name) else { int inquote = 0; +#ifdef QUOTES_IN_INSN + int inescape = 0; +#endif - /* WARNING: c has char, which may be end-of-line. */ - /* Also: input_line_pointer->`\0` where c was. */ + /* 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[(unsigned char) *input_line_pointer] || inquote @@ -740,85 +839,87 @@ read_a_source_file (name) ) { if (flag_m68k_mri && *input_line_pointer == '\'') - inquote = ! inquote; + inquote = !inquote; +#ifdef QUOTES_IN_INSN + if (inescape) + inescape = 0; + else if (*input_line_pointer == '"') + inquote = !inquote; + else if (*input_line_pointer == '\\') + inescape = 1; +#endif input_line_pointer++; } c = *input_line_pointer; *input_line_pointer = '\0'; -#ifdef OBJ_GENERATE_ASM_LINENO - if (generate_asm_lineno == 0) - { - if (ecoff_no_current_file ()) - generate_asm_lineno = 1; - } - if (generate_asm_lineno == 1) - { - unsigned int lineno; - char *s; - - as_where (&s, &lineno); - OBJ_GENERATE_ASM_LINENO (s, lineno); - } -#endif + generate_lineno_debug (); if (macro_defined) { sb out; const char *err; + macro_entry *macro; - if (check_macro (s, &out, '\0', &err)) + if (check_macro (s, &out, &err, ¯o)) { if (err != NULL) - as_bad (err); + as_bad ("%s", err); *input_line_pointer++ = c; input_scrub_include_sb (&out, - input_line_pointer); + input_line_pointer, 1); sb_kill (&out); buffer_limit = input_scrub_next_buffer (&input_line_pointer); +#ifdef md_macro_info + md_macro_info (macro); +#endif continue; } } if (mri_pending_align) { - do_align (1, (char *) NULL, 0); + do_align (1, (char *) NULL, 0, 0); mri_pending_align = 0; + if (line_label != NULL) + { + symbol_set_frag (line_label, frag_now); + S_SET_VALUE (line_label, frag_now_fix ()); + } } - md_assemble (s); /* Assemble 1 instruction. */ + 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==':' */ + this instruction. */ + } + } continue; - } /* if (is_name_beginner(c) */ - + } /* Empty statement? */ if (is_end_of_line[(unsigned char) c]) continue; - if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) - && isdigit (c)) + if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) { - /* local label ("4:") */ + /* local label ("4:") */ char *backup = input_line_pointer; HANDLE_CONDITIONAL_ASSEMBLY (); temp = c - '0'; - while (isdigit (*input_line_pointer)) + /* Read the whole number. */ + while (ISDIGIT (*input_line_pointer)) { temp = (temp * 10) + *input_line_pointer - '0'; ++input_line_pointer; - } /* read the whole number */ + } if (LOCAL_LABELS_DOLLAR && *input_line_pointer == '$' @@ -828,7 +929,7 @@ read_a_source_file (name) if (dollar_label_defined (temp)) { - as_fatal ("label \"%d$\" redefined", temp); + as_fatal (_("label \"%d$\" redefined"), temp); } define_dollar_label (temp); @@ -848,7 +949,7 @@ read_a_source_file (name) } /* local label ("4:") */ if (c && strchr (line_comment_chars, c)) - { /* Its a comment. Better say APP or NO_APP */ + { /* Its a comment. Better say APP or NO_APP. */ char *ends; char *new_buf; char *new_tmp; @@ -871,7 +972,7 @@ read_a_source_file (name) /* 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. . . */ + guarentee it... */ tmp_len = buffer_limit - s; tmp_buf = xmalloc (tmp_len + 1); memcpy (tmp_buf, s, tmp_len); @@ -939,6 +1040,7 @@ read_a_source_file (name) buffer = new_buf; input_line_pointer = new_buf; buffer_limit = new_tmp; + continue; } @@ -948,11 +1050,10 @@ read_a_source_file (name) if (tc_unrecognized_line (c)) continue; #endif - - /* as_warn("Junk character %d.",c); Now done by ignore_rest */ - input_line_pointer--; /* Report unknown char as ignored. */ + input_line_pointer--; + /* Report unknown char as ignored. */ ignore_rest_of_line (); - } /* while (input_line_pointer 0) + if (*fill++ != '\0') + { + as_warn (_("ignoring fill value in absolute section")); + break; + } + fill = NULL; + len = 0; + } + #ifdef md_do_align - md_do_align (n, fill, len, just_record_alignment); + md_do_align (n, fill, len, max, just_record_alignment); #endif - if (!fill) - { - /* @@ Fix this right for BFD! */ - static char zero; - static char nop_opcode = NOP_OPCODE; - if (now_seg != data_section && now_seg != bss_section) - { - fill = &nop_opcode; - } - else + /* Only make a frag if we HAVE to... */ + if (n != 0 && !need_pass_2) + { + if (fill == NULL) { - fill = &zero; + if (subseg_text_p (now_seg)) + frag_align_code (n, max); + else + frag_align (n, 0, max); } - len = 1; - } - - /* Only make a frag if we HAVE to. . . */ - if (n && !need_pass_2) - { - if (len <= 1) - frag_align (n, *fill); + else if (len <= 1) + frag_align (n, *fill, max); else - frag_align_pattern (n, fill, len); + frag_align_pattern (n, fill, len, max); } #ifdef md_do_align - just_record_alignment: + just_record_alignment: ATTRIBUTE_UNUSED_LABEL #endif - record_alignment (now_seg, n); + record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER); } -/* For machines where ".align 4" means align to a 4 byte boundary. */ -void -s_align_bytes (arg) +/* Handle the .align pseudo-op. A positive ARG is a default alignment + (in bytes). A negative ARG is the negative of the length of the + fill pattern. BYTES_P is non-zero if the alignment value should be + interpreted as the byte boundary, rather than the power of 2. */ + +static void +s_align (arg, bytes_p) int arg; + int bytes_p; { - register unsigned int temp; - char temp_fill; - unsigned int i = 0; - unsigned long max_alignment = 1 << 15; + register unsigned int align; char *stop = NULL; char stopc; + offsetT fill = 0; + int max; + int fill_p; if (flag_mri) stop = mri_comment_field (&stopc); @@ -1109,132 +1226,125 @@ s_align_bytes (arg) if (is_end_of_line[(unsigned char) *input_line_pointer]) { if (arg < 0) - temp = 0; + align = 0; else - temp = arg; /* Default value from pseudo-op table */ + align = 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); + align = get_absolute_expression (); + SKIP_WHITESPACE (); } - /* For the sparc, `.align (1<>= 1, ++i) - ; + /* Convert to a power of 2. */ + if (align != 0) + { + unsigned int i; + + for (i = 0; (align & 1) == 0; align >>= 1, ++i) + ; + if (align != 1) + as_bad (_("alignment not a power of 2")); + + align = i; + } } - if (temp != 1) - as_bad ("Alignment not a power of 2"); - temp = i; - if (*input_line_pointer == ',') + if (align > 15) { - offsetT fillval; - int len; + align = 15; + as_warn (_("alignment too large: %u assumed"), align); + } - input_line_pointer++; - fillval = get_absolute_expression (); - if (arg >= 0) - len = 1; + if (*input_line_pointer != ',') + { + fill_p = 0; + max = 0; + } + else + { + ++input_line_pointer; + if (*input_line_pointer == ',') + fill_p = 0; else - len = - arg; - if (len <= 1) { - temp_fill = fillval; - do_align (temp, &temp_fill, len); + fill = get_absolute_expression (); + SKIP_WHITESPACE (); + fill_p = 1; } + + if (*input_line_pointer != ',') + max = 0; else { - char ab[16]; - - if (len > sizeof ab) - abort (); - md_number_to_chars (ab, fillval, len); - do_align (temp, ab, len); + ++input_line_pointer; + max = get_absolute_expression (); } } - else - { - if (arg < 0) - as_warn ("expected fill pattern missing"); - do_align (temp, (char *) NULL, 0); - } - - if (flag_mri) - mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); -} - -/* For machines where ".align 4" means align to 2**4 boundary. */ -void -s_align_ptwo (arg) - int arg; -{ - register int temp; - char temp_fill; - long max_alignment = 15; - char *stop = NULL; - char stopc; - - if (flag_mri) - stop = mri_comment_field (&stopc); - temp = get_absolute_expression (); - if (temp > max_alignment) - as_bad ("Alignment too large: %d. assumed.", temp = max_alignment); - else if (temp < 0) + if (!fill_p) { - as_bad ("Alignment negative. 0 assumed."); - temp = 0; + if (arg < 0) + as_warn (_("expected fill pattern missing")); + do_align (align, (char *) NULL, 0, max); } - if (*input_line_pointer == ',') + else { - offsetT fillval; - int len; + int fill_len; - input_line_pointer++; - fillval = get_absolute_expression (); if (arg >= 0) - len = 1; + fill_len = 1; else - len = - arg; - if (len <= 1) + fill_len = -arg; + if (fill_len <= 1) { - temp_fill = fillval; - do_align (temp, &temp_fill, len); + char fill_char; + + fill_char = fill; + do_align (align, &fill_char, fill_len, max); } else { char ab[16]; - if (len > sizeof ab) + if ((size_t) fill_len > sizeof ab) abort (); - md_number_to_chars (ab, fillval, len); - do_align (temp, ab, len); + md_number_to_chars (ab, fill, fill_len); + do_align (align, ab, fill_len, max); } } - else - { - if (arg < 0) - as_warn ("expected fill pattern missing"); - do_align (temp, (char *) NULL, 0); - } + + demand_empty_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); +} - demand_empty_rest_of_line (); +/* Handle the .align pseudo-op on machines where ".align 4" means + align to a 4 byte boundary. */ + +void +s_align_bytes (arg) + int arg; +{ + s_align (arg, 1); +} + +/* Handle the .align pseudo-op on machines where ".align 4" means align + to a 2**4 boundary. */ + +void +s_align_ptwo (arg) + int arg; +{ + s_align (arg, 0); } -void +void s_comm (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { register char *name; register char c; @@ -1249,43 +1359,59 @@ s_comm (ignore) name = input_line_pointer; c = get_symbol_end (); - /* just after name is now '\0' */ + /* Just after name is now '\0'. */ p = input_line_pointer; *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') { - as_bad ("Expected comma after symbol-name: rest of line ignored."); + *p = 0; + as_bad (_("expected comma after \"%s\""), name); + *p = c; + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } + input_line_pointer++; /* skip ',' */ + if ((temp = get_absolute_expression ()) < 0) { - as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); + as_warn (_(".COMMon length (%ld) < 0 ignored"), (long) temp); + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } + *p = 0; symbolP = symbol_find_or_make (name); *p = c; - if (S_IS_DEFINED (symbolP)) + + if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP)) { - as_bad ("Ignoring attempt to re-define symbol `%s'.", + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } + if (S_GET_VALUE (symbolP)) { if (S_GET_VALUE (symbolP) != (valueT) temp) - as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", + as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"), S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) temp); @@ -1298,16 +1424,16 @@ s_comm (ignore) #ifdef OBJ_VMS { extern int flag_one; - if ( (!temp) || !flag_one) + if (!temp || !flag_one) S_GET_OTHER(symbolP) = const_flag; } #endif /* not OBJ_VMS */ know (symbolP->sy_frag == &zero_address_frag); + demand_empty_rest_of_line (); + if (flag_mri) mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); } /* s_comm() */ /* The MRI COMMON pseudo-op. We handle this by creating a common @@ -1316,7 +1442,7 @@ s_comm (ignore) void s_mri_common (small) - int small; + int small ATTRIBUTE_UNUSED; { char *name; char c; @@ -1326,7 +1452,7 @@ s_mri_common (small) char *stop = NULL; char stopc; - if (! flag_mri) + if (!flag_mri) { s_comm (0); return; @@ -1337,7 +1463,7 @@ s_mri_common (small) SKIP_WHITESPACE (); name = input_line_pointer; - if (! isdigit ((unsigned char) *name)) + if (!ISDIGIT (*name)) c = get_symbol_end (); else { @@ -1345,7 +1471,8 @@ s_mri_common (small) { ++input_line_pointer; } - while (isdigit ((unsigned char) *input_line_pointer)); + while (ISDIGIT (*input_line_pointer)); + c = *input_line_pointer; *input_line_pointer = '\0'; @@ -1372,17 +1499,12 @@ s_mri_common (small) align = get_absolute_expression (); } - if (S_IS_DEFINED (sym)) + if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym)) { -#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER) - if (! S_IS_COMMON (sym)) -#endif - { - as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym)); - mri_comment_end (stop, stopc); - ignore_rest_of_line (); - return; - } + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym)); + ignore_rest_of_line (); + mri_comment_end (stop, stopc); + return; } S_SET_EXTERNAL (sym); @@ -1395,10 +1517,12 @@ s_mri_common (small) if (line_label != NULL) { - line_label->sy_value.X_op = O_symbol; - line_label->sy_value.X_add_symbol = sym; - line_label->sy_value.X_add_number = S_GET_VALUE (sym); - line_label->sy_frag = &zero_address_frag; + expressionS exp; + exp.X_op = O_symbol; + exp.X_add_symbol = sym; + exp.X_add_number = 0; + symbol_set_value_expression (line_label, &exp); + symbol_set_frag (line_label, &zero_address_frag); S_SET_SEGMENT (line_label, expr_section); } @@ -1411,14 +1535,14 @@ s_mri_common (small) if (*input_line_pointer == ',') input_line_pointer += 2; - mri_comment_end (stop, stopc); - demand_empty_rest_of_line (); + + mri_comment_end (stop, stopc); } void s_data (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { segT section; register int temp; @@ -1447,20 +1571,35 @@ s_data (ignore) definition for .file; the APPFILE argument is 1 for .appfile, 0 for .file. */ -void +void +s_app_file_string (file) + char *file; +{ +#ifdef LISTING + if (listing) + listing_source_file (file); +#endif + register_dependency (file); +#ifdef obj_app_file + obj_app_file (file); +#endif +} + +void s_app_file (appfile) int appfile; { register char *s; int length; - /* Some assemblers tolerate immediately following '"' */ + /* Some assemblers tolerate immediately following '"'. */ if ((s = demand_copy_string (&length)) != 0) { /* If this is a fake .appfile, a fake newline was inserted into the buffer. Passing -2 to new_logical_line tells it to account for it. */ - new_logical_line (s, appfile ? -2 : -1); + int may_omit + = (!new_logical_line (s, appfile ? -2 : -1) && appfile); /* In MRI mode, the preprocessor may have inserted an extraneous backquote. */ @@ -1470,14 +1609,9 @@ s_app_file (appfile) ++input_line_pointer; demand_empty_rest_of_line (); -#ifdef LISTING - if (listing) - listing_source_file (s); -#endif + if (!may_omit) + s_app_file_string (s); } -#ifdef obj_app_file - obj_app_file (s); -#endif } /* Handle the .appline pseudo-op. This is automatically generated by @@ -1487,7 +1621,7 @@ s_app_file (appfile) void s_app_line (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { int l; @@ -1496,7 +1630,8 @@ s_app_line (ignore) if (l < 0) /* Some of the back ends can't deal with non-positive line numbers. Besides, it's silly. */ - as_warn ("Line numbers must be positive; line number %d rejected.", l+1); + as_warn (_("line numbers must be positive; line number %d rejected"), + l + 1); else { new_logical_line ((char *) NULL, l); @@ -1513,17 +1648,17 @@ s_app_line (ignore) void s_end (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { if (flag_mri) { /* The MRI assembler permits the start symbol to follow .end, but we don't support that. */ SKIP_WHITESPACE (); - if (! is_end_of_line[(unsigned char) *input_line_pointer] + if (!is_end_of_line[(unsigned char) *input_line_pointer] && *input_line_pointer != '*' && *input_line_pointer != '!') - as_warn ("start address not supported"); + as_warn (_("start address not supported")); } } @@ -1531,9 +1666,9 @@ s_end (ignore) void s_err (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { - as_bad (".err encountered"); + as_bad (_(".err encountered")); demand_empty_rest_of_line (); } @@ -1541,7 +1676,7 @@ s_err (ignore) void s_fail (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { offsetT temp; char *stop = NULL; @@ -1552,84 +1687,118 @@ s_fail (ignore) temp = get_absolute_expression (); if (temp >= 500) - as_warn (".fail %ld encountered", (long) temp); + as_warn (_(".fail %ld encountered"), (long) temp); else - as_bad (".fail %ld encountered", (long) temp); + as_bad (_(".fail %ld encountered"), (long) temp); + + demand_empty_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); } -void +void s_fill (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { - long temp_repeat = 0; - long temp_size = 1; - register long temp_fill = 0; + expressionS rep_exp; + long size = 1; + register long fill = 0; char *p; #ifdef md_flush_pending_output md_flush_pending_output (); #endif - temp_repeat = get_absolute_expression (); + get_known_segmented_expression (&rep_exp); if (*input_line_pointer == ',') { input_line_pointer++; - temp_size = get_absolute_expression (); + size = get_absolute_expression (); if (*input_line_pointer == ',') { input_line_pointer++; - temp_fill = get_absolute_expression (); + fill = get_absolute_expression (); } } + /* This is to be compatible with BSD 4.2 AS, not for any rational reason. */ #define BSD_FILL_SIZE_CROCK_8 (8) - if (temp_size > BSD_FILL_SIZE_CROCK_8) + if (size > BSD_FILL_SIZE_CROCK_8) { - as_warn (".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8); - temp_size = BSD_FILL_SIZE_CROCK_8; + as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8); + size = BSD_FILL_SIZE_CROCK_8; } - if (temp_size < 0) + if (size < 0) { - as_warn ("Size negative: .fill ignored."); - temp_size = 0; + as_warn (_("size negative; .fill ignored")); + size = 0; } - else if (temp_repeat <= 0) + else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0) { - if (temp_repeat < 0) - as_warn ("Repeat < 0, .fill ignored"); - temp_size = 0; + if (rep_exp.X_add_number < 0) + as_warn (_("repeat < 0; .fill ignored")); + size = 0; } - if (temp_size && !need_pass_2) + if (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, (unsigned 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, (valueT) 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. - */ + if (rep_exp.X_op == O_constant) + { + p = frag_var (rs_fill, (int) size, (int) size, + (relax_substateT) 0, (symbolS *) 0, + (offsetT) rep_exp.X_add_number, + (char *) 0); + } + else + { + /* We don't have a constant repeat count, so we can't use + rs_fill. We can get the same results out of rs_space, + but its argument is in bytes, so we must multiply the + repeat count by size. */ + + symbolS *rep_sym; + rep_sym = make_expr_symbol (&rep_exp); + if (size != 1) + { + expressionS size_exp; + size_exp.X_op = O_constant; + size_exp.X_add_number = size; + + rep_exp.X_op = O_multiply; + rep_exp.X_add_symbol = rep_sym; + rep_exp.X_op_symbol = make_expr_symbol (&size_exp); + rep_exp.X_add_number = 0; + rep_sym = make_expr_symbol (&rep_exp); + } + + p = frag_var (rs_space, (int) size, (int) size, + (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0); + } + + memset (p, 0, (unsigned int) size); + + /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX + flavoured AS. The following bizarre 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. */ +#define BSD_FILL_SIZE_CROCK_4 (4) + md_number_to_chars (p, (valueT) fill, + (size > BSD_FILL_SIZE_CROCK_4 + ? BSD_FILL_SIZE_CROCK_4 + : (int) 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. */ } demand_empty_rest_of_line (); } -void +void s_globl (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { char *name; int c; @@ -1645,23 +1814,25 @@ s_globl (ignore) name = input_line_pointer; c = get_symbol_end (); symbolP = symbol_find_or_make (name); + S_SET_EXTERNAL (symbolP); + *input_line_pointer = c; SKIP_WHITESPACE (); - S_SET_EXTERNAL (symbolP); + c = *input_line_pointer; if (c == ',') { input_line_pointer++; SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') + if (is_end_of_line[(unsigned char) *input_line_pointer]) c = '\n'; } } while (c == ','); + demand_empty_rest_of_line (); + if (flag_mri) mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); } /* Handle the MRI IRP and IRPC pseudo-ops. */ @@ -1679,18 +1850,18 @@ s_irp (irpc) as_where (&file, &line); sb_new (&s); - while (! is_end_of_line[(unsigned char) *input_line_pointer]) + while (!is_end_of_line[(unsigned char) *input_line_pointer]) sb_add_char (&s, *input_line_pointer++); sb_new (&out); - err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0'); + err = expand_irp (irpc, 0, &s, &out, get_line_sb); if (err != NULL) as_bad_where (file, line, "%s", err); sb_kill (&s); - input_scrub_include_sb (&out, input_line_pointer); + input_scrub_include_sb (&out, input_line_pointer, 1); sb_kill (&out); buffer_limit = input_scrub_next_buffer (&input_line_pointer); } @@ -1702,7 +1873,7 @@ s_irp (irpc) void s_linkonce (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { enum linkonce_type type; @@ -1710,7 +1881,7 @@ s_linkonce (ignore) type = LINKONCE_DISCARD; - if (! is_end_of_line[(unsigned char) *input_line_pointer]) + if (!is_end_of_line[(unsigned char) *input_line_pointer]) { char *s; char c; @@ -1726,7 +1897,7 @@ s_linkonce (ignore) else if (strcasecmp (s, "same_contents") == 0) type = LINKONCE_SAME_CONTENTS; else - as_warn ("unrecognized .linkonce type `%s'", s); + as_warn (_("unrecognized .linkonce type `%s'"), s); *input_line_pointer = c; } @@ -1739,7 +1910,7 @@ s_linkonce (ignore) flagword flags; if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0) - as_warn (".linkonce is not supported for this object file format"); + as_warn (_(".linkonce is not supported for this object file format")); flags = bfd_get_section_flags (stdoutput, now_seg); flags |= SEC_LINK_ONCE; @@ -1760,23 +1931,26 @@ s_linkonce (ignore) flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS; break; } - if (! bfd_set_section_flags (stdoutput, now_seg, flags)) - as_bad ("bfd_set_section_flags: %s", + if (!bfd_set_section_flags (stdoutput, now_seg, flags)) + as_bad (_("bfd_set_section_flags: %s"), bfd_errmsg (bfd_get_error ())); } #else /* ! defined (BFD_ASSEMBLER) */ - as_warn (".linkonce is not supported for this object file format"); + as_warn (_(".linkonce is not supported for this object file format")); #endif /* ! defined (BFD_ASSEMBLER) */ #endif /* ! defined (obj_handle_link_once) */ demand_empty_rest_of_line (); } -void -s_lcomm (needs_align) +static void +s_lcomm_internal (needs_align, bytes_p) /* 1 if this was a ".bss" directive, which may require a 3rd argument - (alignment); 0 if it was an ".lcomm" (2 args only) */ + (alignment); 0 if it was an ".lcomm" (2 args only). */ int needs_align; + /* 1 if the alignment value should be interpreted as the byte boundary, + rather than the power of 2. */ + int bytes_p; { register char *name; register char c; @@ -1793,6 +1967,14 @@ s_lcomm (needs_align) c = get_symbol_end (); p = input_line_pointer; *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); /* Accept an optional comma after the name. The comma used to be @@ -1803,15 +1985,15 @@ s_lcomm (needs_align) SKIP_WHITESPACE (); } - if (*input_line_pointer == '\n') + if (is_end_of_line[(unsigned char) *input_line_pointer]) { - as_bad ("Missing size expression"); + as_bad (_("missing size expression")); return; } if ((temp = get_absolute_expression ()) < 0) { - as_warn ("BSS length (%d.) <0! Ignored.", temp); + as_warn (_("BSS length (%d) < 0 ignored"), temp); ignore_rest_of_line (); return; } @@ -1821,68 +2003,79 @@ s_lcomm (needs_align) || OUTPUT_FLAVOR == bfd_target_elf_flavour) { /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */ - if (temp <= bfd_get_gp_size (stdoutput)) + if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) { bss_seg = subseg_new (".sbss", 1); seg_info (bss_seg)->bss = 1; #ifdef BFD_ASSEMBLER - if (! bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) - as_warn ("error setting flags for \".sbss\": %s", + if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) + as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ())); #endif } } #endif - if (!needs_align) - { - /* FIXME. This needs to be machine independent. */ - if (temp >= 8) - align = 3; - else if (temp >= 4) - align = 2; - else if (temp >= 2) - align = 1; - else - align = 0; - -#ifdef OBJ_EVAX - /* FIXME: This needs to be done in a more general fashion. */ - align = 3; -#endif - record_alignment(bss_seg, align); - } + if (!needs_align) + { + TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); + + /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ + if (align) + record_alignment (bss_seg, align); + } if (needs_align) { align = 0; SKIP_WHITESPACE (); + if (*input_line_pointer != ',') { - as_bad ("Expected comma after size"); + as_bad (_("expected comma after size")); ignore_rest_of_line (); return; } + input_line_pointer++; SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') + + if (is_end_of_line[(unsigned char) *input_line_pointer]) { - as_bad ("Missing alignment"); + as_bad (_("missing alignment")); return; } + align = get_absolute_expression (); + + if (bytes_p) + { + /* Convert to a power of 2. */ + if (align != 0) + { + unsigned int i; + + for (i = 0; (align & 1) == 0; align >>= 1, ++i) + ; + if (align != 1) + as_bad (_("alignment not a power of 2")); + align = i; + } + } + if (align > max_alignment) { align = max_alignment; - as_warn ("Alignment too large: %d. assumed.", align); + as_warn (_("alignment too large; %d assumed"), align); } else if (align < 0) { align = 0; - as_warn ("Alignment negative. 0 assumed."); + as_warn (_("alignment negative; 0 assumed")); } + record_alignment (bss_seg, align); - } /* if needs align */ + } else { /* Assume some objects may require alignment on some systems. */ @@ -1901,26 +2094,32 @@ s_lcomm (needs_align) *p = c; if ( -#if defined(OBJ_AOUT) | defined(OBJ_BOUT) - S_GET_OTHER (symbolP) == 0 && - S_GET_DESC (symbolP) == 0 && -#endif /* OBJ_AOUT or OBJ_BOUT */ - (S_GET_SEGMENT (symbolP) == bss_seg - || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) +#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ + || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) +#ifdef BFD_ASSEMBLER + (OUTPUT_FLAVOR != bfd_target_aout_flavour + || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && +#else + (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && +#endif +#endif + (S_GET_SEGMENT (symbolP) == bss_seg + || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) { char *pfrag; subseg_set (bss_seg, 1); if (align) - frag_align (align, 0); - /* detach from old frag */ + frag_align (align, 0, 0); + + /* Detach from old frag. */ if (S_GET_SEGMENT (symbolP) == bss_seg) - symbolP->sy_frag->fr_symbol = NULL; + symbol_get_frag (symbolP)->fr_symbol = NULL; - symbolP->sy_frag = frag_now; - pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, - temp, (char *)0); + symbol_set_frag (symbolP, frag_now); + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, + (offsetT) temp, (char *) 0); *pfrag = 0; S_SET_SEGMENT (symbolP, bss_seg); @@ -1928,7 +2127,7 @@ s_lcomm (needs_align) #ifdef OBJ_COFF /* The symbol may already have been created with a preceding ".globl" directive -- be careful not to step on storage class - in that case. Otherwise, set it to static. */ + in that case. Otherwise, set it to static. */ if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) { S_SET_STORAGE_CLASS (symbolP, C_STAT); @@ -1940,17 +2139,30 @@ s_lcomm (needs_align) #endif } else - as_bad ("Ignoring attempt to re-define symbol `%s'.", - S_GET_NAME (symbolP)); + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); subseg_set (current_seg, current_subseg); demand_empty_rest_of_line (); -} /* s_lcomm() */ +} + +void +s_lcomm (needs_align) + int needs_align; +{ + s_lcomm_internal (needs_align, 0); +} -void +void +s_lcomm_bytes (needs_align) + int needs_align; +{ + s_lcomm_internal (needs_align, 1); +} + +void s_lsym (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { register char *name; register char c; @@ -1958,29 +2170,41 @@ s_lsym (ignore) expressionS exp; register symbolS *symbolP; - /* we permit ANY defined expression: BSD4.2 demands constants */ + /* We permit ANY defined expression: BSD4.2 demands constants. */ name = input_line_pointer; c = get_symbol_end (); p = input_line_pointer; *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') { *p = 0; - as_bad ("Expected comma after name \"%s\"", name); + as_bad (_("expected comma after \"%s\""), name); *p = c; ignore_rest_of_line (); return; } + input_line_pointer++; expression (&exp); + if (exp.X_op != O_constant && exp.X_op != O_register) { - as_bad ("bad expression"); + as_bad (_("bad expression")); ignore_rest_of_line (); return; } + *p = 0; symbolP = symbol_find_or_make (name); @@ -1989,13 +2213,13 @@ s_lsym (ignore) those fields, and I can't see when they'd ever be tripped. I don't 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. */ + anyway. xoxorich. */ if (S_GET_SEGMENT (symbolP) == undefined_section && S_GET_VALUE (symbolP) == 0) { /* The name might be an undefined .global symbol; be sure to - keep the "external" bit. */ + keep the "external" bit. */ S_SET_SEGMENT (symbolP, (exp.X_op == O_constant ? absolute_section @@ -2004,11 +2228,12 @@ s_lsym (ignore) } else { - as_bad ("Symbol %s already defined", name); + as_bad (_("symbol `%s' is already defined"), name); } + *p = c; demand_empty_rest_of_line (); -} /* s_lsym() */ +} /* Read a line into an sb. */ @@ -2016,6 +2241,8 @@ static int get_line_sb (line) sb *line; { + char quote1, quote2, inquote; + if (input_line_pointer[-1] == '\n') bump_line_counters (); @@ -2026,8 +2253,38 @@ get_line_sb (line) return 0; } - while (! is_end_of_line[(unsigned char) *input_line_pointer]) - sb_add_char (line, *input_line_pointer++); + /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this + code needs to be changed. */ + if (!flag_m68k_mri) + quote1 = '"'; + else + quote1 = '\0'; + + quote2 = '\0'; + if (flag_m68k_mri) + quote2 = '\''; +#ifdef LEX_IS_STRINGQUOTE + quote2 = '\''; +#endif + + inquote = '\0'; + + while (!is_end_of_line[(unsigned char) *input_line_pointer] + || (inquote != '\0' && *input_line_pointer != '\n')) + { + if (inquote == *input_line_pointer) + inquote = '\0'; + else if (inquote == '\0') + { + if (*input_line_pointer == quote1) + inquote = quote1; + else if (*input_line_pointer == quote2) + inquote = quote2; + } + + sb_add_char (line, *input_line_pointer++); + } + while (input_line_pointer < buffer_limit && is_end_of_line[(unsigned char) *input_line_pointer]) { @@ -2035,15 +2292,15 @@ get_line_sb (line) bump_line_counters (); ++input_line_pointer; } + return 1; } -/* Define a macro. This is an interface to macro.c, which is shared - between gas and gasp. */ +/* Define a macro. This is an interface to macro.c. */ void s_macro (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { char *file; unsigned int line; @@ -2055,7 +2312,7 @@ s_macro (ignore) as_where (&file, &line); sb_new (&s); - while (! is_end_of_line[(unsigned char) *input_line_pointer]) + while (!is_end_of_line[(unsigned char) *input_line_pointer]) sb_add_char (&s, *input_line_pointer++); sb_new (&label); @@ -2071,19 +2328,15 @@ s_macro (ignore) { S_SET_SEGMENT (line_label, undefined_section); S_SET_VALUE (line_label, 0); - line_label->sy_frag = &zero_address_frag; + symbol_set_frag (line_label, &zero_address_frag); } - if (((flag_m68k_mri -#ifdef NO_PSEUDO_DOT - || 1 -#endif - ) + if (((NO_PSEUDO_DOT || flag_m68k_mri) && hash_find (po_hash, name) != NULL) - || (! flag_m68k_mri + || (!flag_m68k_mri && *name == '.' && hash_find (po_hash, name + 1) != NULL)) - as_warn ("attempt to redefine pseudo-op `%s' ignored", + as_warn (_("attempt to redefine pseudo-op `%s' ignored"), name); } @@ -2095,8 +2348,9 @@ s_macro (ignore) void s_mexit (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { + cond_exit_macro (macro_nest); buffer_limit = input_scrub_next_buffer (&input_line_pointer); } @@ -2104,7 +2358,7 @@ s_mexit (ignore) void s_mri (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { int on, old_flag; @@ -2116,13 +2370,21 @@ s_mri (ignore) #ifdef TC_M68K flag_m68k_mri = 1; #endif + macro_mri_mode (1); } else { flag_mri = 0; +#ifdef TC_M68K flag_m68k_mri = 0; +#endif + macro_mri_mode (0); } + /* Operator precedence changes in m68k MRI mode, so we need to + update the operator rankings. */ + expr_set_precedence (); + #ifdef MRI_MODE_CHANGE if (on != old_flag) MRI_MODE_CHANGE (on); @@ -2140,16 +2402,15 @@ do_org (segment, exp, fill) int fill; { if (segment != now_seg && segment != absolute_section) - as_bad ("invalid segment \"%s\"; segment \"%s\" assumed", - segment_name (segment), segment_name (now_seg)); + as_bad (_("invalid segment \"%s\""), segment_name (segment)); if (now_seg == absolute_section) { if (fill != 0) - as_warn ("ignoring fill value in absolute section"); + as_warn (_("ignoring fill value in absolute section")); if (exp->X_op != O_constant) { - as_bad ("only constant offsets supported in absolute section"); + as_bad (_("only constant offsets supported in absolute section")); exp->X_add_number = 0; } abs_section_offset = exp->X_add_number; @@ -2157,27 +2418,39 @@ do_org (segment, exp, fill) else { char *p; + symbolS *sym = exp->X_add_symbol; + offsetT off = exp->X_add_number * OCTETS_PER_BYTE; - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol, - exp->X_add_number, (char *) NULL); + if (exp->X_op != O_constant && exp->X_op != O_symbol) + { + /* Handle complex expressions. */ + sym = make_expr_symbol (exp); + off = 0; + } + + p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0); *p = fill; } } -void +void s_org (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { register segT segment; expressionS exp; register long temp_fill; +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + /* The m68k MRI assembler has a different meaning for .org. It means to create an absolute section at a given address. We can't support that--use a linker script instead. */ if (flag_m68k_mri) { - as_bad ("MRI style ORG pseudo-op not supported"); + as_bad (_("MRI style ORG pseudo-op not supported")); ignore_rest_of_line (); return; } @@ -2207,7 +2480,7 @@ s_org (ignore) do_org (segment, &exp, temp_fill); demand_empty_rest_of_line (); -} /* s_org() */ +} /* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be called by the obj-format routine which handles section changing @@ -2218,7 +2491,7 @@ s_org (ignore) void s_mri_sect (type) - char *type; + char *type ATTRIBUTE_UNUSED; { #ifdef TC_M68K @@ -2227,9 +2500,9 @@ s_mri_sect (type) segT seg; SKIP_WHITESPACE (); - + name = input_line_pointer; - if (! isdigit ((unsigned char) *name)) + if (!ISDIGIT (*name)) c = get_symbol_end (); else { @@ -2237,7 +2510,8 @@ s_mri_sect (type) { ++input_line_pointer; } - while (isdigit ((unsigned char) *input_line_pointer)); + while (ISDIGIT (*input_line_pointer)); + c = *input_line_pointer; *input_line_pointer = '\0'; } @@ -2261,11 +2535,11 @@ s_mri_sect (type) if (*input_line_pointer == ',') { c = *++input_line_pointer; - c = toupper ((unsigned char) c); + c = TOUPPER (c); if (c == 'C' || c == 'D' || c == 'M' || c == 'R') *type = c; else - as_bad ("unrecognized section type"); + as_bad (_("unrecognized section type")); ++input_line_pointer; #ifdef BFD_ASSEMBLER @@ -2281,8 +2555,8 @@ s_mri_sect (type) flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM; if (flags != SEC_NO_FLAGS) { - if (! bfd_set_section_flags (stdoutput, seg, flags)) - as_warn ("error setting flags for \"%s\": %s", + if (!bfd_set_section_flags (stdoutput, seg, flags)) + as_warn (_("error setting flags for \"%s\": %s"), bfd_section_name (stdoutput, seg), bfd_errmsg (bfd_get_error ())); } @@ -2333,7 +2607,7 @@ s_mri_sect (type) else if (strcasecmp (sectype, "romdata") == 0) *type = 'R'; else - as_warn ("unrecognized section type `%s'", sectype); + as_warn (_("unrecognized section type `%s'"), sectype); *input_line_pointer = c; } @@ -2347,7 +2621,7 @@ s_mri_sect (type) c = get_symbol_end (); if (strcasecmp (seccmd, "absolute") == 0) { - as_bad ("absolute sections are not supported"); + as_bad (_("absolute sections are not supported")); *input_line_pointer = c; ignore_rest_of_line (); return; @@ -2362,17 +2636,18 @@ s_mri_sect (type) } else { - as_warn ("unrecognized section command `%s'", seccmd); + as_warn (_("unrecognized section command `%s'"), seccmd); *input_line_pointer = c; } } - demand_empty_rest_of_line (); + demand_empty_rest_of_line (); #else /* ! TC_I960 */ /* The MRI assembler seems to use different forms of .sect for different targets. */ - abort (); + as_bad ("MRI mode not supported for this target"); + ignore_rest_of_line (); #endif /* ! TC_I960 */ #endif /* ! TC_M68K */ } @@ -2381,7 +2656,7 @@ s_mri_sect (type) void s_print (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { char *s; int len; @@ -2395,7 +2670,7 @@ s_print (ignore) void s_purgem (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { if (is_it_end_of_statement ()) { @@ -2423,20 +2698,43 @@ s_purgem (ignore) /* Handle the .rept pseudo-op. */ +void +s_bad_endr (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp")); + demand_empty_rest_of_line (); +} + +/* Handle the .rept pseudo-op. */ + void s_rept (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { int count; - sb one; - sb many; count = get_absolute_expression (); + do_repeat (count, "REPT", "ENDR"); +} + +/* This function provides a generic repeat block implementation. It allows + different directives to be used as the start/end keys. */ + +void +do_repeat (count, start, end) + int count; + const char *start; + const char *end; +{ + sb one; + sb many; + sb_new (&one); - if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb)) + if (!buffer_and_nest (start, end, &one, get_line_sb)) { - as_bad ("rept without endr"); + as_bad (_("%s without %s"), start, end); return; } @@ -2446,35 +2744,62 @@ s_rept (ignore) sb_kill (&one); - input_scrub_include_sb (&many, input_line_pointer); + input_scrub_include_sb (&many, input_line_pointer, 1); sb_kill (&many); buffer_limit = input_scrub_next_buffer (&input_line_pointer); } -void -s_set (ignore) - int ignore; +/* Skip to end of current repeat loop; EXTRA indicates how many additional + input buffers to skip. Assumes that conditionals preceding the loop end + are properly nested. + + This function makes it easier to implement a premature "break" out of the + loop. The EXTRA arg accounts for other buffers we might have inserted, + such as line substitutions. */ + +void +end_repeat (extra) + int extra; +{ + cond_exit_macro (macro_nest); + while (extra-- >= 0) + buffer_limit = input_scrub_next_buffer (&input_line_pointer); +} + +/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then + this is .equiv, and it is an error if the symbol is already + defined. */ + +void +s_set (equiv) + int equiv; { register char *name; 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! - * Dean in haste. - */ + /* Especial apologies for the random logic: + this just grew, and could be parsed much more simply! + Dean in haste. */ name = input_line_pointer; delim = get_symbol_end (); end_name = input_line_pointer; *end_name = delim; + + if (name == end_name) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); if (*input_line_pointer != ',') { *end_name = 0; - as_bad ("Expected comma after name \"%s\"", name); + as_bad (_("expected comma after \"%s\""), name); *end_name = delim; ignore_rest_of_line (); return; @@ -2485,7 +2810,7 @@ s_set (ignore) if (name[0] == '.' && name[1] == '\0') { - /* Turn '. = mumble' into a .org mumble */ + /* Turn '. = mumble' into a .org mumble. */ register segT segment; expressionS exp; @@ -2501,22 +2826,44 @@ s_set (ignore) if ((symbolP = symbol_find (name)) == NULL && (symbolP = md_undefined_symbol (name)) == NULL) { - symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); +#ifndef NO_LISTING + /* When doing symbol listings, play games with dummy fragments living + outside the normal fragment chain to record the file and line info + for this symbol. */ + if (listing & LISTING_SYMBOLS) + { + extern struct list_info_struct *listing_tail; + fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS)); + memset (dummy_frag, 0, sizeof (fragS)); + dummy_frag->fr_type = rs_fill; + dummy_frag->line = listing_tail; + symbolP = symbol_new (name, undefined_section, 0, dummy_frag); + dummy_frag->fr_symbol = symbolP; + } + else +#endif + symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); + #ifdef OBJ_COFF - /* "set" symbols are local unless otherwise specified. */ + /* "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; + + if (equiv + && S_IS_DEFINED (symbolP) + && S_GET_SEGMENT (symbolP) != reg_section) + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); + pseudo_set (symbolP); demand_empty_rest_of_line (); -} /* s_set() */ +} -void +void s_space (mult) int mult; { @@ -2525,6 +2872,7 @@ s_space (mult) char *p = 0; char *stop = NULL; char stopc; + int bytes; #ifdef md_flush_pending_output md_flush_pending_output (); @@ -2553,23 +2901,28 @@ s_space (mult) S_SET_VALUE (mri_common_symbol, val + 1); if (line_label != NULL) { - know (line_label->sy_value.X_op == O_symbol); - know (line_label->sy_value.X_add_symbol == mri_common_symbol); - line_label->sy_value.X_add_number += 1; + expressionS *symexp; + + symexp = symbol_get_value_expression (line_label); + know (symexp->X_op == O_symbol); + know (symexp->X_add_symbol == mri_common_symbol); + symexp->X_add_number += 1; } } } else { - do_align (1, (char *) NULL, 0); + do_align (1, (char *) NULL, 0, 0); if (line_label != NULL) { - line_label->sy_frag = frag_now; + symbol_set_frag (line_label, frag_now); S_SET_VALUE (line_label, frag_now_fix ()); } } } + bytes = mult; + expression (&exp); SKIP_WHITESPACE (); @@ -2590,13 +2943,14 @@ s_space (mult) || (mult != 0 && mult != 1 && val.X_add_number != 0)) { if (exp.X_op != O_constant) - as_bad ("Unsupported variable size or fill value"); + as_bad (_("unsupported variable size or fill value")); else { offsetT i; if (mult == 0) mult = 1; + bytes = mult * exp.X_add_number; for (i = 0; i < exp.X_add_number; i++) emit_expr (&val, mult); } @@ -2610,11 +2964,13 @@ s_space (mult) repeat = exp.X_add_number; if (mult) repeat *= mult; + bytes = repeat; if (repeat <= 0) { - if (! flag_mri || repeat < 0) - as_warn (".space repeat count is %s, ignored", - repeat ? "negative" : "zero"); + if (!flag_mri) + as_warn (_(".space repeat count is zero, ignored")); + else if (repeat < 0) + as_warn (_(".space repeat count is negative, ignored")); goto getout; } @@ -2637,23 +2993,25 @@ s_space (mult) if (!need_pass_2) p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, - repeat, (char *) 0); + (offsetT) repeat, (char *) 0); } else { if (now_seg == absolute_section) { - as_bad ("space allocation too complex in absolute section"); + as_bad (_("space allocation too complex in absolute section")); subseg_set (text_section, 0); } + if (mri_common_symbol != NULL) { - as_bad ("space allocation too complex in common section"); + as_bad (_("space allocation too complex in common section")); mri_common_symbol = NULL; } + if (!need_pass_2) p = frag_var (rs_space, 1, 1, (relax_substateT) 0, - make_expr_symbol (&exp), 0L, (char *) 0); + make_expr_symbol (&exp), (offsetT) 0, (char *) 0); } if (p) @@ -2661,10 +3019,17 @@ s_space (mult) } getout: - if (flag_mri) - mri_comment_end (stop, stopc); + + /* In MRI mode, after an odd number of bytes, we must align to an + even word boundary, unless the next instruction is a dc.b, ds.b + or dcb.b. */ + if (flag_mri && (bytes & 1) != 0) + mri_pending_align = 1; demand_empty_rest_of_line (); + + if (flag_mri) + mri_comment_end (stop, stopc); } /* This is like s_space, but the value is a floating point number with @@ -2689,10 +3054,10 @@ s_float_space (float_type) SKIP_WHITESPACE (); if (*input_line_pointer != ',') { - as_bad ("missing value"); + as_bad (_("missing value")); + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } @@ -2702,7 +3067,8 @@ s_float_space (float_type) /* Skip any 0{letter} that may be present. Don't even check if the * letter is legal. */ - if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1])) + if (input_line_pointer[0] == '0' + && ISALPHA (input_line_pointer[1])) input_line_pointer += 2; /* Accept :xxxx, where the x's are hex digits, for a floating point @@ -2712,9 +3078,9 @@ s_float_space (float_type) flen = hex_float (float_type, temp); if (flen < 0) { + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } } @@ -2727,10 +3093,10 @@ s_float_space (float_type) know (flen > 0); if (err) { - as_bad ("Bad floating literal: %s", err); + as_bad (_("bad floating literal: %s"), err); + ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - ignore_rest_of_line (); return; } } @@ -2743,17 +3109,17 @@ s_float_space (float_type) memcpy (p, temp, (unsigned int) flen); } + demand_empty_rest_of_line (); + if (flag_mri) mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); } /* Handle the .struct pseudo-op, as found in MIPS assemblers. */ void s_struct (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { char *stop = NULL; char stopc; @@ -2762,14 +3128,14 @@ s_struct (ignore) stop = mri_comment_field (&stopc); abs_section_offset = get_absolute_expression (); subseg_set (absolute_section, 0); + demand_empty_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - demand_empty_rest_of_line (); } void s_text (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { register int temp; @@ -2779,55 +3145,64 @@ s_text (ignore) #ifdef OBJ_VMS const_flag &= ~IN_DEFAULT_SECTION; #endif -} /* s_text() */ +} - -void +void demand_empty_rest_of_line () { SKIP_WHITESPACE (); if (is_end_of_line[(unsigned char) *input_line_pointer]) - { - input_line_pointer++; - } + input_line_pointer++; else - { - ignore_rest_of_line (); - } - /* Return having already swallowed end-of-line. */ -} /* Return pointing just after end-of-line. */ + ignore_rest_of_line (); + + /* Return having already swallowed 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[(unsigned char) *input_line_pointer]) { - if (isprint (*input_line_pointer)) - as_bad ("Rest of line ignored. First ignored character is `%c'.", - *input_line_pointer); + if (ISPRINT (*input_line_pointer)) + as_warn (_("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); + as_warn (_("rest of line ignored; first ignored character valued 0x%x"), + *input_line_pointer); + while (input_line_pointer < buffer_limit && !is_end_of_line[(unsigned char) *input_line_pointer]) - { - input_line_pointer++; - } + input_line_pointer++; } - input_line_pointer++; /* Return pointing just after end-of-line. */ + + input_line_pointer++; + + /* Return pointing just after end-of-line. */ + know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); +} + +void +discard_rest_of_line () +{ + while (input_line_pointer < buffer_limit + && !is_end_of_line[(unsigned char) *input_line_pointer]) + input_line_pointer++; + + input_line_pointer++; + + /* Return pointing just after end-of-line. */ know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); } -/* - * pseudo_set() - * - * In: Pointer to a symbol. - * Input_line_pointer->expression. - * - * Out: Input_line_pointer->just after any whitespace after expression. - * Tried to set symbol to value of expression. - * Will change symbols type, value, and frag; - */ +/* In: Pointer to a symbol. + Input_line_pointer->expression. + + Out: Input_line_pointer->just after any whitespace after expression. + Tried to set symbol to value of expression. + Will change symbols type, value, and frag; */ + void pseudo_set (symbolP) symbolS *symbolP; @@ -2837,7 +3212,7 @@ pseudo_set (symbolP) 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)) && ! defined (BFD_ASSEMBLER) ext = S_IS_EXTERNAL (symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ @@ -2845,17 +3220,20 @@ pseudo_set (symbolP) (void) expression (&exp); if (exp.X_op == O_illegal) - as_bad ("illegal expression; zero assumed"); + as_bad (_("illegal expression")); else if (exp.X_op == O_absent) - as_bad ("missing expression; zero assumed"); + as_bad (_("missing expression")); else if (exp.X_op == O_big) - as_bad ("%s number invalid; zero assumed", - exp.X_add_number > 0 ? "bignum" : "floating point"); + { + if (exp.X_add_number > 0) + as_bad (_("bignum invalid")); + else + as_bad (_("floating point number invalid")); + } else if (exp.X_op == O_subtract - && (S_GET_SEGMENT (exp.X_add_symbol) - == S_GET_SEGMENT (exp.X_op_symbol)) && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol)) - && exp.X_add_symbol->sy_frag == exp.X_op_symbol->sy_frag) + && (symbol_get_frag (exp.X_add_symbol) + == symbol_get_frag (exp.X_op_symbol))) { exp.X_op = O_constant; exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol) @@ -2878,19 +3256,22 @@ pseudo_set (symbolP) S_CLEAR_EXTERNAL (symbolP); #endif /* OBJ_AOUT or OBJ_BOUT */ S_SET_VALUE (symbolP, (valueT) exp.X_add_number); - symbolP->sy_frag = &zero_address_frag; + if (exp.X_op != O_constant) + symbol_set_frag (symbolP, &zero_address_frag); break; case O_register: S_SET_SEGMENT (symbolP, reg_section); S_SET_VALUE (symbolP, (valueT) exp.X_add_number); - symbolP->sy_frag = &zero_address_frag; + symbol_set_frag (symbolP, &zero_address_frag); break; case O_symbol: if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section || exp.X_add_number != 0) - symbolP->sy_value = exp; + symbol_set_value_expression (symbolP, &exp); + else if (symbol_section_p (symbolP)) + as_bad ("attempt to set value of section symbol"); else { symbolS *s = exp.X_add_symbol; @@ -2904,7 +3285,7 @@ pseudo_set (symbolP) #endif /* OBJ_AOUT or OBJ_BOUT */ S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s)); - symbolP->sy_frag = s->sy_frag; + symbol_set_frag (symbolP, symbol_get_frag (s)); copy_symbol_attributes (symbolP, s); } break; @@ -2912,25 +3293,23 @@ pseudo_set (symbolP) default: /* The value is some complex expression. FIXME: Should we set the segment to anything? */ - symbolP->sy_value = exp; + symbol_set_value_expression (symbolP, &exp); break; } } -/* - * cons() - * - * CONStruct more frag of .bytes, or .words etc. - * Should need_pass_2 be 1 then emit no frag(s). - * This understands EXPRESSIONS. - * - * Bug (?) - * - * This has a split personality. We use expression() to read the - * value. We can detect if the value won't fit in a byte or word. - * But we can't detect if expression() discarded significant digits - * in the case of a long. Not worth the crocks required to fix it. - */ +/* cons() + + CONStruct more frag of .bytes, or .words etc. + Should need_pass_2 be 1 then emit no frag(s). + This understands EXPRESSIONS. + + Bug (?) + + This has a split personality. We use expression() to read the + value. We can detect if the value won't fit in a byte or word. + But we can't detect if expression() discarded significant digits + in the case of a long. Not worth the crocks required to fix it. */ /* Select a parser for cons expressions. */ @@ -2942,13 +3321,15 @@ pseudo_set (symbolP) are defined, which is the normal case, then only simple expressions are permitted. */ +#ifdef TC_M68K static void parse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes)); +#endif #ifndef TC_PARSE_CONS_EXPRESSION #ifdef BITFIELD_CONS_EXPRESSIONS #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) -static void +static void parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes)); #endif #ifdef REPEAT_CONS_EXPRESSIONS @@ -2963,12 +3344,12 @@ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes)); #endif #endif -/* worker to do .byte etc statements */ -/* clobbers input_line_pointer, checks */ -/* end-of-line. */ -static void +/* Worker to do .byte etc statements. + Clobbers input_line_pointer and checks end-of-line. */ + +static void cons_worker (nbytes, rva) - register int nbytes; /* 1=.byte, 2=.word, 4=.long */ + register int nbytes; /* 1=.byte, 2=.word, 4=.long. */ int rva; { int c; @@ -2985,9 +3366,9 @@ cons_worker (nbytes, rva) if (is_it_end_of_statement ()) { + demand_empty_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - demand_empty_rest_of_line (); return; } @@ -2998,9 +3379,11 @@ cons_worker (nbytes, rva) c = 0; do { +#ifdef TC_M68K if (flag_m68k_mri) parse_mri_cons (&exp, (unsigned int) nbytes); else +#endif TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); if (rva) @@ -3008,7 +3391,7 @@ cons_worker (nbytes, rva) if (exp.X_op == O_symbol) exp.X_op = O_symbol_rva; else - as_fatal ("rva without symbol"); + as_fatal (_("rva without symbol")); } emit_expr (&exp, (unsigned int) nbytes); ++c; @@ -3021,15 +3404,14 @@ cons_worker (nbytes, rva) if (flag_mri && nbytes == 1 && (c & 1) != 0) mri_pending_align = 1; - input_line_pointer--; /* Put terminator back into stream. */ + input_line_pointer--; /* Put terminator back into stream. */ + + demand_empty_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); - - demand_empty_rest_of_line (); } - void cons (size) int size; @@ -3037,14 +3419,13 @@ cons (size) cons_worker (size, 0); } -void +void s_rva (size) int size; { cons_worker (size, 1); } - /* Put the contents of expression EXP into the object file using NBYTES bytes. If need_pass_2 is 1, this does nothing. */ @@ -3061,13 +3442,80 @@ emit_expr (exp, nbytes) if (need_pass_2) return; +#ifndef NO_LISTING +#ifdef OBJ_ELF + /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will + appear as a four byte positive constant in the .line section, + followed by a 2 byte 0xffff. Look for that case here. */ + { + static int dwarf_line = -1; + + if (strcmp (segment_name (now_seg), ".line") != 0) + dwarf_line = -1; + else if (dwarf_line >= 0 + && nbytes == 2 + && exp->X_op == O_constant + && (exp->X_add_number == -1 || exp->X_add_number == 0xffff)) + listing_source_line ((unsigned int) dwarf_line); + else if (nbytes == 4 + && exp->X_op == O_constant + && exp->X_add_number >= 0) + dwarf_line = exp->X_add_number; + else + dwarf_line = -1; + } + + /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will + appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte + AT_sibling (0x12) followed by a four byte address of the sibling + followed by a 2 byte AT_name (0x38) followed by the name of the + file. We look for that case here. */ + { + static int dwarf_file = 0; + + if (strcmp (segment_name (now_seg), ".debug") != 0) + dwarf_file = 0; + else if (dwarf_file == 0 + && nbytes == 2 + && exp->X_op == O_constant + && exp->X_add_number == 0x11) + dwarf_file = 1; + else if (dwarf_file == 1 + && nbytes == 2 + && exp->X_op == O_constant + && exp->X_add_number == 0x12) + dwarf_file = 2; + else if (dwarf_file == 2 + && nbytes == 4) + dwarf_file = 3; + else if (dwarf_file == 3 + && nbytes == 2 + && exp->X_op == O_constant + && exp->X_add_number == 0x38) + dwarf_file = 4; + else + dwarf_file = 0; + + /* The variable dwarf_file_string tells stringer that the string + may be the name of the source file. */ + if (dwarf_file == 4) + dwarf_file_string = 1; + else + dwarf_file_string = 0; + } +#endif +#endif + + if (check_eh_frame (exp, &nbytes)) + return; + op = exp->X_op; /* Allow `.word 0' in the absolute section. */ if (now_seg == absolute_section) { if (op != O_constant || exp->X_add_number != 0) - as_bad ("attempt to store value in absolute section"); + as_bad (_("attempt to store value in absolute section")); abs_section_offset += nbytes; return; } @@ -3075,13 +3523,13 @@ emit_expr (exp, nbytes) /* Handle a negative bignum. */ if (op == O_uminus && exp->X_add_number == 0 - && exp->X_add_symbol->sy_value.X_op == O_big - && exp->X_add_symbol->sy_value.X_add_number > 0) + && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big + && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0) { int i; unsigned long carry; - exp = &exp->X_add_symbol->sy_value; + exp = symbol_get_value_expression (exp->X_add_symbol); /* Negate the bignum: one's complement each digit and add 1. */ carry = 1; @@ -3089,7 +3537,7 @@ emit_expr (exp, nbytes) { unsigned long next; - next = (((~ (generic_bignum[i] & LITTLENUM_MASK)) + next = (((~(generic_bignum[i] & LITTLENUM_MASK)) & LITTLENUM_MASK) + carry); generic_bignum[i] = next & LITTLENUM_MASK; @@ -3105,19 +3553,19 @@ emit_expr (exp, nbytes) if (op == O_absent || op == O_illegal) { - as_warn ("zero assumed for missing expression"); + as_warn (_("zero assumed for missing expression")); exp->X_add_number = 0; op = O_constant; } else if (op == O_big && exp->X_add_number <= 0) { - as_bad ("floating point number invalid; zero assumed"); + as_bad (_("floating point number invalid")); exp->X_add_number = 0; op = O_constant; } else if (op == O_register) { - as_warn ("register value used as expression"); + as_warn (_("register value used as expression")); op = O_constant; } @@ -3133,6 +3581,8 @@ emit_expr (exp, nbytes) x = (struct broken_word *) xmalloc (sizeof (struct broken_word)); x->next_broken_word = broken_words; broken_words = x; + x->seg = now_seg; + x->subseg = now_subseg; x->frag = frag_now; x->word_goes_here = p; x->dispfrag = 0; @@ -3140,6 +3590,7 @@ emit_expr (exp, nbytes) x->sub = exp->X_op_symbol; x->addnum = exp->X_add_number; x->added = 0; + x->use_jump = 0; new_broken_words++; return; } @@ -3152,7 +3603,7 @@ emit_expr (exp, nbytes) valueT val; int gencnt; - if (! exp->X_unsigned && exp->X_add_number < 0) + if (!exp->X_unsigned && exp->X_add_number < 0) extra_digit = (valueT) -1; val = (valueT) exp->X_add_number; gencnt = 0; @@ -3172,35 +3623,48 @@ emit_expr (exp, nbytes) register valueT get; register valueT use; register valueT mask; + valueT hibit; register valueT unmask; /* JF << of >= number of bits in the object is undefined. In - particular SPARC (Sun 4) has problems */ + particular SPARC (Sun 4) has problems. */ if (nbytes >= sizeof (valueT)) - mask = 0; + { + mask = 0; + if (nbytes > sizeof (valueT)) + hibit = 0; + else + hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); + } else - mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ + { + /* Don't store these bits. */ + mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); + hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); + } - unmask = ~mask; /* Do store these bits. */ + 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. */ + mask = ~(unmask >> 1); /* Includes sign bit now. */ #endif get = exp->X_add_number; use = get & unmask; - if ((get & mask) != 0 && (get & mask) != mask) - { /* Leading bits contain both 0s & 1s. */ - as_warn ("Value 0x%lx truncated to 0x%lx.", + if ((get & mask) != 0 + && ((get & mask) != mask + || (get & hibit) == 0)) + { /* Leading bits contain both 0s & 1s. */ + as_warn (_("value 0x%lx truncated to 0x%lx"), (unsigned long) get, (unsigned long) use); } - /* put bytes in right order. */ + /* Put bytes in right order. */ md_number_to_chars (p, use, (int) nbytes); } else if (op == O_big) { - int size; + unsigned int size; LITTLENUM_TYPE *nums; know (nbytes % CHARS_PER_LITTLENUM == 0); @@ -3208,7 +3672,7 @@ emit_expr (exp, nbytes) size = exp->X_add_number * CHARS_PER_LITTLENUM; if (nbytes < size) { - as_warn ("Bignum truncated to %d bytes", nbytes); + as_warn (_("bignum truncated to %d bytes"), nbytes); size = nbytes; } @@ -3222,7 +3686,7 @@ emit_expr (exp, nbytes) } nums = generic_bignum + size / CHARS_PER_LITTLENUM; - while (size > 0) + while (size >= CHARS_PER_LITTLENUM) { --nums; md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); @@ -3233,7 +3697,7 @@ emit_expr (exp, nbytes) else { nums = generic_bignum; - while (size > 0) + while (size >= CHARS_PER_LITTLENUM) { md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); ++nums; @@ -3242,7 +3706,7 @@ emit_expr (exp, nbytes) nbytes -= CHARS_PER_LITTLENUM; } - while (nbytes > 0) + while (nbytes >= CHARS_PER_LITTLENUM) { md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); nbytes -= CHARS_PER_LITTLENUM; @@ -3285,7 +3749,7 @@ emit_expr (exp, nbytes) r = BFD_RELOC_64; break; default: - as_bad ("unsupported BFD relocation size %u", nbytes); + as_bad (_("unsupported BFD relocation size %u"), nbytes); r = BFD_RELOC_32; break; } @@ -3330,7 +3794,7 @@ emit_expr (exp, nbytes) To use this function the tc-XXX.h file should define BITFIELD_CONS_EXPRESSIONS. */ -static void +static void parse_bitfield_cons (exp, nbytes) expressionS *exp; unsigned int nbytes; @@ -3341,7 +3805,8 @@ parse_bitfield_cons (exp, nbytes) (void) expression (exp); if (*input_line_pointer == ':') - { /* bitfields */ + { + /* Bitfields. */ long value = 0; for (;;) @@ -3352,7 +3817,7 @@ parse_bitfield_cons (exp, nbytes) { input_line_pointer = hold; break; - } /* next piece is not a bitfield */ + } /* Next piece is not a bitfield. */ /* In the general case, we can't allow full expressions with symbol @@ -3370,30 +3835,30 @@ parse_bitfield_cons (exp, nbytes) 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. */ + .equ type symbol. xoxorich. */ if (exp->X_op == O_absent) { - as_warn ("using a bit field width of zero"); + as_warn (_("using a bit field width of zero")); exp->X_add_number = 0; exp->X_op = O_constant; - } /* implied zero width bitfield */ + } /* Implied zero width bitfield. */ if (exp->X_op != O_constant) { *input_line_pointer = '\0'; - as_bad ("field width \"%s\" too complex for a bitfield", hold); + as_bad (_("field width \"%s\" too complex for a bitfield"), hold); *input_line_pointer = ':'; demand_empty_rest_of_line (); return; - } /* too complex */ + } /* Too complex. */ if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) { - as_warn ("field width %lu too big to fit in %d bytes: truncated to %d bits", + as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), width, nbytes, (BITS_PER_CHAR * nbytes)); width = BITS_PER_CHAR * nbytes; - } /* too big */ + } /* Too big. */ if (width > bits_available) { @@ -3401,9 +3866,10 @@ parse_bitfield_cons (exp, nbytes) input_line_pointer = hold; exp->X_add_number = value; break; - } /* won't fit */ + } /* Won't fit. */ - hold = ++input_line_pointer; /* skip ':' */ + /* Skip ':'. */ + hold = ++input_line_pointer; (void) expression (exp); if (exp->X_op != O_constant) @@ -3411,11 +3877,11 @@ parse_bitfield_cons (exp, nbytes) char cache = *input_line_pointer; *input_line_pointer = '\0'; - as_bad ("field value \"%s\" too complex for a bitfield", hold); + as_bad (_("field value \"%s\" too complex for a bitfield"), hold); *input_line_pointer = cache; demand_empty_rest_of_line (); return; - } /* too complex */ + } /* Too complex. */ value |= ((~(-1 << width) & exp->X_add_number) << ((BITS_PER_CHAR * nbytes) - bits_available)); @@ -3425,22 +3891,23 @@ parse_bitfield_cons (exp, nbytes) || *input_line_pointer != ',') { break; - } /* all the bitfields we're gonna get */ + } /* All the bitfields we're gonna get. */ hold = ++input_line_pointer; (void) expression (exp); - } /* forever loop */ + } exp->X_add_number = value; exp->X_op = O_constant; exp->X_unsigned = 1; - } /* if looks like a bitfield */ -} /* parse_bitfield_cons() */ - + } +} + #endif /* BITFIELD_CONS_EXPRESSIONS */ /* Handle an MRI style string expression. */ +#ifdef TC_M68K static void parse_mri_cons (exp, nbytes) expressionS *exp; @@ -3453,7 +3920,7 @@ parse_mri_cons (exp, nbytes) TC_PARSE_CONS_EXPRESSION (exp, nbytes); else { - int scan = 0; + unsigned int scan; unsigned int result = 0; /* An MRI style string. Cut into as many bytes as will fit into @@ -3463,7 +3930,7 @@ parse_mri_cons (exp, nbytes) ++input_line_pointer; else if (*input_line_pointer == 'E') { - as_bad ("EBCDIC constants are not supported"); + as_bad (_("EBCDIC constants are not supported")); ++input_line_pointer; } @@ -3482,16 +3949,18 @@ parse_mri_cons (exp, nbytes) result = (result << 8) | (*input_line_pointer++); } - /* Left justify */ + /* Left justify. */ while (scan < nbytes) { result <<= 8; scan++; } - /* Create correct expression */ + + /* Create correct expression. */ exp->X_op = O_constant; exp->X_add_number = result; - /* Fake it so that we can read the next char too */ + + /* Fake it so that we can read the next char too. */ if (input_line_pointer[0] != '\'' || (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\'')) { @@ -3503,6 +3972,7 @@ parse_mri_cons (exp, nbytes) input_line_pointer++; } } +#endif /* TC_M68K */ #ifdef REPEAT_CONS_EXPRESSIONS @@ -3533,7 +4003,7 @@ parse_repeat_cons (exp, nbytes) if (count.X_op != O_constant || count.X_add_number <= 0) { - as_warn ("Unresolvable or nonpositive repeat count; using 1"); + as_warn (_("unresolvable or nonpositive repeat count; using 1")); return; } @@ -3584,7 +4054,7 @@ hex_float (float_type, bytes) break; default: - as_bad ("Unknown floating type type '%c'", float_type); + as_bad (_("unknown floating type type '%c'"), float_type); return -1; } @@ -3597,7 +4067,7 @@ hex_float (float_type, bytes) int d; /* The MRI assembler accepts arbitrary underscores strewn about - through the hex constant, so we ignore them as well. */ + through the hex constant, so we ignore them as well. */ if (*input_line_pointer == '_') { ++input_line_pointer; @@ -3606,7 +4076,7 @@ hex_float (float_type, bytes) if (i >= length) { - as_warn ("Floating point constant too large"); + as_warn (_("floating point constant too large")); return -1; } d = hex_value (*input_line_pointer) << 4; @@ -3636,34 +4106,31 @@ hex_float (float_type, bytes) return length; } -/* - * float_cons() - * - * CONStruct some more frag chars of .floats .ffloats etc. - * Makes 0 or more new frags. - * If need_pass_2 == 1, no frags are emitted. - * This understands only floating literals, not expressions. Sorry. - * - * A floating constant is defined by atof_generic(), except it is preceded - * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its - * reading, I decided to be incompatible. This always tries to give you - * rounded bits to the precision of the pseudo-op. Former AS did premature - * truncatation, restored noisy bits instead of trailing 0s AND gave you - * a choice of 2 flavours of noise according to which of 2 floating-point - * scanners you directed AS to use. - * - * In: input_line_pointer->whitespace before, or '0' of flonum. - * - */ +/* float_cons() + + CONStruct some more frag chars of .floats .ffloats etc. + Makes 0 or more new frags. + If need_pass_2 == 1, no frags are emitted. + This understands only floating literals, not expressions. Sorry. + + A floating constant is defined by atof_generic(), except it is preceded + by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its + reading, I decided to be incompatible. This always tries to give you + rounded bits to the precision of the pseudo-op. Former AS did premature + truncatation, restored noisy bits instead of trailing 0s AND gave you + a choice of 2 flavours of noise according to which of 2 floating-point + scanners you directed AS to use. + + In: input_line_pointer->whitespace before, or '0' of flonum. */ void float_cons (float_type) - /* Clobbers input_line-pointer, checks end-of-line. */ - register int float_type; /* 'f':.ffloat ... 'F':.float ... */ + /* Clobbers input_line-pointer, checks end-of-line. */ + register int float_type; /* 'f':.ffloat ... 'F':.float ... */ { register char *p; - int length; /* Number of chars in an object. */ - register char *err; /* Error from scanning floating literal. */ + int length; /* Number of chars in an object. */ + register char *err; /* Error from scanning floating literal. */ char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; if (is_it_end_of_statement ()) @@ -3678,15 +4145,15 @@ float_cons (float_type) do { - /* input_line_pointer->1st char of a flonum (we hope!). */ + /* 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])) + 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; /* Accept :xxxx, where the x's are hex digits, for a floating @@ -3708,7 +4175,7 @@ float_cons (float_type) know (length > 0); if (err) { - as_bad ("Bad floating literal: %s", err); + as_bad (_("bad floating literal: %s"), err); ignore_rest_of_line (); return; } @@ -3727,11 +4194,10 @@ float_cons (float_type) ++input_line_pointer; expression (&count_exp); + if (count_exp.X_op != O_constant || count_exp.X_add_number <= 0) - { - as_warn ("unresolvable or nonpositive repeat count; using 1"); - } + as_warn (_("unresolvable or nonpositive repeat count; using 1")); else count = count_exp.X_add_number; } @@ -3747,54 +4213,372 @@ float_cons (float_type) } while (*input_line_pointer++ == ','); - --input_line_pointer; /* Put terminator back into stream. */ + /* Put terminator back into stream. */ + --input_line_pointer; demand_empty_rest_of_line (); -} /* float_cons() */ +} -/* - * stringer() - * - * We read 0 or more ',' seperated, double-quoted strings. - * - * Caller should have checked need_pass_2 is FALSE because we don't check it. - */ - - -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 */ +/* Return the size of a LEB128 value. */ + +static inline int +sizeof_sleb128 (value) + offsetT value; +{ + register int size = 0; + register unsigned byte; + + do + { + byte = (value & 0x7f); + /* Sadly, we cannot rely on typical arithmetic right shift behaviour. + Fortunately, we can structure things so that the extra work reduces + to a noop on systems that do things "properly". */ + value = (value >> 7) | ~(-(offsetT)1 >> 7); + size += 1; + } + while (!(((value == 0) && ((byte & 0x40) == 0)) + || ((value == -1) && ((byte & 0x40) != 0)))); + + return size; +} + +static inline int +sizeof_uleb128 (value) + valueT value; +{ + register int size = 0; + register unsigned byte; + + do + { + byte = (value & 0x7f); + value >>= 7; + size += 1; + } + while (value != 0); + + return size; +} + +int +sizeof_leb128 (value, sign) + valueT value; + int sign; +{ + if (sign) + return sizeof_sleb128 ((offsetT) value); + else + return sizeof_uleb128 (value); +} + +/* Output a LEB128 value. */ + +static inline int +output_sleb128 (p, value) + char *p; + offsetT value; +{ + register char *orig = p; + register int more; + + do + { + unsigned byte = (value & 0x7f); + + /* Sadly, we cannot rely on typical arithmetic right shift behaviour. + Fortunately, we can structure things so that the extra work reduces + to a noop on systems that do things "properly". */ + value = (value >> 7) | ~(-(offsetT)1 >> 7); + + more = !((((value == 0) && ((byte & 0x40) == 0)) + || ((value == -1) && ((byte & 0x40) != 0)))); + if (more) + byte |= 0x80; + + *p++ = byte; + } + while (more); + + return p - orig; +} + +static inline int +output_uleb128 (p, value) + char *p; + valueT value; +{ + char *orig = p; + + do + { + unsigned byte = (value & 0x7f); + value >>= 7; + if (value != 0) + /* More bytes to follow. */ + byte |= 0x80; + + *p++ = byte; + } + while (value != 0); + + return p - orig; +} + +int +output_leb128 (p, value, sign) + char *p; + valueT value; + int sign; +{ + if (sign) + return output_sleb128 (p, (offsetT) value); + else + return output_uleb128 (p, value); +} + +/* Do the same for bignums. We combine sizeof with output here in that + we don't output for NULL values of P. It isn't really as critical as + for "normal" values that this be streamlined. */ + +static inline int +output_big_sleb128 (p, bignum, size) + char *p; + LITTLENUM_TYPE *bignum; + int size; +{ + char *orig = p; + valueT val = 0; + int loaded = 0; + unsigned byte; + + /* Strip leading sign extensions off the bignum. */ + while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1) + size--; + + do + { + if (loaded < 7 && size > 0) + { + val |= (*bignum << loaded); + loaded += 8 * CHARS_PER_LITTLENUM; + size--; + bignum++; + } + + byte = val & 0x7f; + loaded -= 7; + val >>= 7; + + if (size == 0) + { + if ((val == 0 && (byte & 0x40) == 0) + || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0 + && (byte & 0x40) != 0)) + byte |= 0x80; + } + + if (orig) + *p = byte; + p++; + } + while (byte & 0x80); + + return p - orig; +} + +static inline int +output_big_uleb128 (p, bignum, size) + char *p; + LITTLENUM_TYPE *bignum; + int size; +{ + char *orig = p; + valueT val = 0; + int loaded = 0; + unsigned byte; + + /* Strip leading zeros off the bignum. */ + /* XXX: Is this needed? */ + while (size > 0 && bignum[size - 1] == 0) + size--; + + do + { + if (loaded < 7 && size > 0) + { + val |= (*bignum << loaded); + loaded += 8 * CHARS_PER_LITTLENUM; + size--; + bignum++; + } + + byte = val & 0x7f; + loaded -= 7; + val >>= 7; + + if (size > 0 || val) + byte |= 0x80; + + if (orig) + *p = byte; + p++; + } + while (byte & 0x80); + + return p - orig; +} + +static int +output_big_leb128 (p, bignum, size, sign) + char *p; + LITTLENUM_TYPE *bignum; + int size, sign; +{ + if (sign) + return output_big_sleb128 (p, bignum, size); + else + return output_big_uleb128 (p, bignum, size); +} + +/* Generate the appropriate fragments for a given expression to emit a + leb128 value. */ + +void +emit_leb128_expr (exp, sign) + expressionS *exp; + int sign; +{ + operatorT op = exp->X_op; + int nbytes; + + if (op == O_absent || op == O_illegal) + { + as_warn (_("zero assumed for missing expression")); + exp->X_add_number = 0; + op = O_constant; + } + else if (op == O_big && exp->X_add_number <= 0) + { + as_bad (_("floating point number invalid")); + exp->X_add_number = 0; + op = O_constant; + } + else if (op == O_register) + { + as_warn (_("register value used as expression")); + op = O_constant; + } + + /* Let check_eh_frame know that data is being emitted. nbytes == -1 is + a signal that this is leb128 data. It shouldn't optimize this away. */ + nbytes = -1; + if (check_eh_frame (exp, &nbytes)) + abort (); + + /* Let the backend know that subsequent data may be byte aligned. */ +#ifdef md_cons_align + md_cons_align (1); +#endif + + if (op == O_constant) + { + /* If we've got a constant, emit the thing directly right now. */ + + valueT value = exp->X_add_number; + int size; + char *p; + + size = sizeof_leb128 (value, sign); + p = frag_more (size); + output_leb128 (p, value, sign); + } + else if (op == O_big) + { + /* O_big is a different sort of constant. */ + + int size; + char *p; + + size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign); + p = frag_more (size); + output_big_leb128 (p, generic_bignum, exp->X_add_number, sign); + } + else + { + /* Otherwise, we have to create a variable sized fragment and + resolve things later. */ + + frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign, + make_expr_symbol (exp), 0, (char *) NULL); + } +} + +/* Parse the .sleb128 and .uleb128 pseudos. */ + +void +s_leb128 (sign) + int sign; +{ + expressionS exp; + + do + { + expression (&exp); + emit_leb128_expr (&exp, sign); + } + while (*input_line_pointer++ == ','); + + input_line_pointer--; + demand_empty_rest_of_line (); +} + +/* We read 0 or more ',' separated, double-quoted strings. + Caller should have checked need_pass_2 is FALSE because we don't + check it. */ + +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. */ { register unsigned int c; + char *start; #ifdef md_flush_pending_output md_flush_pending_output (); #endif - /* - * 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 - * ','. - */ + /* The following awkward logic is to parse ZERO or more strings, + comma separated. 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. */ + c = 0; /* Skip loop. */ + ++input_line_pointer; /* Compensate for end of loop. */ } else { - c = ','; /* Do loop. */ + c = ','; /* Do loop. */ } + /* If we have been switched into the abs_section then we + will not have an obstack onto which we can hang strings. */ + if (now_seg == absolute_section) + { + as_bad (_("strings must be placed into a section")); + c = 0; + ignore_rest_of_line (); + } + while (c == ',' || c == '<' || c == '"') { SKIP_WHITESPACE (); switch (*input_line_pointer) { case '\"': - ++input_line_pointer; /*->1st char of string. */ + ++input_line_pointer; /*->1st char of string. */ + start = input_line_pointer; while (is_a_char (c = next_char_of_string ())) { FRAG_APPEND_1_CHAR (c); @@ -3804,6 +4588,27 @@ stringer (append_zero) /* Worker to do .ascii etc statements. */ FRAG_APPEND_1_CHAR (0); } know (input_line_pointer[-1] == '\"'); + +#ifndef NO_LISTING +#ifdef OBJ_ELF + /* In ELF, when gcc is emitting DWARF 1 debugging output, it + will emit .string with a filename in the .debug section + after a sequence of constants. See the comment in + emit_expr for the sequence. emit_expr will set + dwarf_file_string to non-zero if this string might be a + source file name. */ + if (strcmp (segment_name (now_seg), ".debug") != 0) + dwarf_file_string = 0; + else if (dwarf_file_string) + { + c = input_line_pointer[-1]; + input_line_pointer[-1] = '\0'; + listing_source_file (start); + input_line_pointer[-1] = c; + } +#endif +#endif + break; case '<': input_line_pointer++; @@ -3811,7 +4616,7 @@ stringer (append_zero) /* Worker to do .ascii etc statements. */ FRAG_APPEND_1_CHAR (c); if (*input_line_pointer != '>') { - as_bad ("Expected "); + as_bad (_("expected ")); } input_line_pointer++; break; @@ -3829,9 +4634,9 @@ stringer (append_zero) /* Worker to do .ascii etc statements. */ /* 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. */ + returning values bigger than 1 byte. xoxorich. */ -unsigned int +unsigned int next_char_of_string () { register unsigned int c; @@ -3844,7 +4649,7 @@ next_char_of_string () break; case '\n': - as_warn ("Unterminated string: Newline inserted."); + as_warn (_("unterminated string; newline inserted")); bump_line_counters (); break; @@ -3878,7 +4683,7 @@ next_char_of_string () case '\\': case '"': - break; /* As itself. */ + break; /* As itself. */ case '0': case '1': @@ -3894,10 +4699,13 @@ next_char_of_string () long number; int i; - for (i = 0, number = 0; isdigit (c) && i < 3; c = *input_line_pointer++, i++) + for (i = 0, number = 0; + ISDIGIT (c) && i < 3; + c = *input_line_pointer++, i++) { number = number * 8 + c - '0'; } + c = number & 0xff; } --input_line_pointer; @@ -3910,11 +4718,11 @@ next_char_of_string () number = 0; c = *input_line_pointer++; - while (isxdigit (c)) + while (ISXDIGIT (c)) { - if (isdigit (c)) + if (ISDIGIT (c)) number = number * 16 + c - '0'; - else if (isupper (c)) + else if (ISUPPER (c)) number = number * 16 + c - 'A' + 10; else number = number * 16 + c - 'a' + 10; @@ -3926,8 +4734,8 @@ next_char_of_string () break; case '\n': - /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ - as_warn ("Unterminated string: Newline inserted."); + /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ + as_warn (_("unterminated string; newline inserted")); c = '\n'; bump_line_counters (); break; @@ -3935,20 +4743,20 @@ next_char_of_string () default: #ifdef ONLY_STANDARD_ESCAPES - as_bad ("Bad escaped character in string, '?' assumed"); + as_bad (_("bad escaped character in string")); c = '?'; #endif /* ONLY_STANDARD_ESCAPES */ break; - } /* switch on escaped char */ + } break; #endif /* ! defined (NO_STRING_ESCAPES) */ default: break; - } /* switch on char */ + } return (c); -} /* next_char_of_string() */ +} static segT get_segmented_expression (expP) @@ -3961,7 +4769,7 @@ get_segmented_expression (expP) || expP->X_op == O_absent || expP->X_op == O_big) { - as_bad ("expected address expression; zero assumed"); + as_bad (_("expected address expression")); expP->X_op = O_constant; expP->X_add_number = 0; retval = absolute_section; @@ -3969,7 +4777,7 @@ get_segmented_expression (expP) return retval; } -static segT +static segT get_known_segmented_expression (expP) register expressionS *expP; { @@ -3981,48 +4789,52 @@ get_known_segmented_expression (expP) expression. */ if (expP->X_add_symbol != NULL && S_GET_SEGMENT (expP->X_add_symbol) != expr_section) - as_warn ("symbol \"%s\" undefined; zero assumed", + as_warn (_("symbol \"%s\" undefined; zero assumed"), S_GET_NAME (expP->X_add_symbol)); else - as_warn ("some symbol undefined; zero assumed"); + as_warn (_("some symbol undefined; zero assumed")); retval = absolute_section; expP->X_op = O_constant; expP->X_add_number = 0; } know (retval == absolute_section || SEG_NORMAL (retval)); return (retval); -} /* get_known_segmented_expression() */ +} + +offsetT +get_absolute_expr (exp) + expressionS *exp; +{ + expression (exp); + if (exp->X_op != O_constant) + { + if (exp->X_op != O_absent) + as_bad (_("bad or irreducible absolute expression")); + exp->X_add_number = 0; + } + return exp->X_add_number; +} offsetT get_absolute_expression () { expressionS exp; - expression (&exp); - if (exp.X_op != O_constant) - { - if (exp.X_op != O_absent) - as_bad ("bad or irreducible absolute expression; zero assumed"); - exp.X_add_number = 0; - } - return exp.X_add_number; + return get_absolute_expr (&exp); } -char /* return terminator */ +char /* Return terminator. */ get_absolute_expression_and_terminator (val_pointer) - long *val_pointer; /* return value of expression */ + long *val_pointer; /* Return value of expression. */ { /* FIXME: val_pointer should probably be offsetT *. */ *val_pointer = (long) get_absolute_expression (); return (*input_line_pointer++); } -/* - * demand_copy_C_string() - * - * Like demand_copy_string, but return NULL if the string contains any '\0's. - * Give a warning if that happens. - */ +/* Like demand_copy_string, but return NULL if the string contains any '\0's. + Give a warning if that happens. */ + char * demand_copy_C_string (len_pointer) int *len_pointer; @@ -4040,19 +4852,17 @@ demand_copy_C_string (len_pointer) s = 0; len = 1; *len_pointer = 0; - as_bad ("This string may not contain \'\\0\'"); + as_bad (_("this string may not contain \'\\0\'")); } } } + return s; } -/* - * demand_copy_string() - * - * Demand string, but return a safe (=private) copy of the string. - * Return NULL if we can't read a string here. - */ +/* Demand string, but return a safe (=private) copy of the string. + Return NULL if we can't read a string here. */ + char * demand_copy_string (lenP) int *lenP; @@ -4065,7 +4875,7 @@ demand_copy_string (lenP) SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { - input_line_pointer++; /* Skip opening quote. */ + input_line_pointer++; /* Skip opening quote. */ while (is_a_char (c = next_char_of_string ())) { @@ -4073,42 +4883,40 @@ demand_copy_string (lenP) len++; } /* JF this next line is so demand_copy_C_string will return a - null terminated string. */ + null terminated string. */ obstack_1grow (¬es, '\0'); retval = obstack_finish (¬es); } else { - as_warn ("Missing string"); + as_warn (_("missing string")); retval = NULL; ignore_rest_of_line (); } *lenP = len; return (retval); -} /* demand_copy_string() */ +} -/* - * is_it_end_of_statement() - * - * In: Input_line_pointer->next character. - * - * Do: Skip input_line_pointer over all whitespace. - * - * Out: 1 if input_line_pointer->end-of-line. -*/ -int +/* In: Input_line_pointer->next character. + + 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[(unsigned char) *input_line_pointer]); -} /* is_it_end_of_statement() */ +} -void -equals (sym_name) +void +equals (sym_name, reassign) char *sym_name; + int reassign; { - register symbolS *symbolP; /* symbol we are working with */ - char *stop; + register symbolS *symbolP; /* Symbol we are working with. */ + char *stop = NULL; char stopc; input_line_pointer++; @@ -4123,7 +4931,7 @@ equals (sym_name) if (sym_name[0] == '.' && sym_name[1] == '\0') { - /* Turn '. = mumble' into a .org mumble */ + /* Turn '. = mumble' into a .org mumble. */ register segT segment; expressionS exp; @@ -4133,34 +4941,180 @@ equals (sym_name) } else { +#ifdef OBJ_COFF + int local; + + symbolP = symbol_find (sym_name); + local = symbolP == NULL; + if (local) +#endif /* OBJ_COFF */ symbolP = symbol_find_or_make (sym_name); + /* Permit register names to be redefined. */ + if (!reassign + && S_IS_DEFINED (symbolP) + && S_GET_SEGMENT (symbolP) != reg_section) + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); + +#ifdef OBJ_COFF + /* "set" symbols are local unless otherwise specified. */ + if (local) + SF_SET_LOCAL (symbolP); +#endif /* OBJ_COFF */ + pseudo_set (symbolP); } if (flag_mri) - mri_comment_end (stop, stopc); -} /* equals() */ + { + /* Check garbage after the expression. */ + ignore_rest_of_line (); + mri_comment_end (stop, stopc); + } +} + +/* .incbin -- include a file verbatim at the current location. */ + +void +s_incbin (x) + int x ATTRIBUTE_UNUSED; +{ + FILE * binfile; + char * path; + char * filename; + char * binfrag; + long skip = 0; + long count = 0; + long bytes; + int len; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + SKIP_WHITESPACE (); + filename = demand_copy_string (& len); + if (filename == NULL) + return; + + SKIP_WHITESPACE (); + + /* Look for optional skip and count. */ + if (* input_line_pointer == ',') + { + ++ input_line_pointer; + skip = get_absolute_expression (); -/* .include -- include a file at this point. */ + SKIP_WHITESPACE (); + + if (* input_line_pointer == ',') + { + ++ input_line_pointer; + + count = get_absolute_expression (); + if (count == 0) + as_warn (_(".incbin count zero, ignoring `%s'"), filename); + + SKIP_WHITESPACE (); + } + } + + demand_empty_rest_of_line (); -/* ARGSUSED */ -void + /* Try opening absolute path first, then try include dirs. */ + binfile = fopen (filename, FOPEN_RB); + if (binfile == NULL) + { + int i; + + path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); + + for (i = 0; i < include_dir_count; i++) + { + sprintf (path, "%s/%s", include_dirs[i], filename); + + binfile = fopen (path, FOPEN_RB); + if (binfile != NULL) + break; + } + + if (binfile == NULL) + as_bad (_("file not found: %s"), filename); + } + else + path = xstrdup (filename); + + if (binfile) + { + long file_len; + + register_dependency (path); + + /* Compute the length of the file. */ + if (fseek (binfile, 0, SEEK_END) != 0) + { + as_bad (_("seek to end of .incbin file failed `%s'"), path); + goto done; + } + file_len = ftell (binfile); + + /* If a count was not specified use the size of the file. */ + if (count == 0) + count = file_len; + + if (skip + count > file_len) + { + as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"), + skip, count, file_len); + goto done; + } + + if (fseek (binfile, skip, SEEK_SET) != 0) + { + as_bad (_("could not skip to %ld in file `%s'"), skip, path); + goto done; + } + + /* Allocate frag space and store file contents in it. */ + binfrag = frag_more (count); + + bytes = fread (binfrag, 1, count, binfile); + if (bytes < count) + as_warn (_("truncated file `%s', %ld of %ld bytes read"), + path, bytes, count); + } +done: + if (binfile != NULL) + fclose (binfile); + if (path) + free (path); +} + +/* .include -- include a file at this point. */ + +void s_include (arg) - int arg; + int arg ATTRIBUTE_UNUSED; { - char *newbuf; char *filename; int i; FILE *try; char *path; - if (! flag_m68k_mri) - filename = demand_copy_string (&i); + if (!flag_m68k_mri) + { + filename = demand_copy_string (&i); + if (filename == NULL) + { + /* demand_copy_string has already printed an error and + called ignore_rest_of_line. */ + return; + } + } else { SKIP_WHITESPACE (); i = 0; - while (! is_end_of_line[(unsigned char) *input_line_pointer] + while (!is_end_of_line[(unsigned char) *input_line_pointer] && *input_line_pointer != ' ' && *input_line_pointer != '\t') { @@ -4168,33 +5122,37 @@ s_include (arg) ++input_line_pointer; ++i; } + obstack_1grow (¬es, '\0'); filename = obstack_finish (¬es); - while (! is_end_of_line[(unsigned char) *input_line_pointer]) + while (!is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; } + demand_empty_rest_of_line (); path = xmalloc ((unsigned long) 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"))) + if (0 != (try = fopen (path, FOPEN_RT))) { 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() */ + /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ + register_dependency (path); + input_scrub_insert_file (path); +} -void +void add_include_dir (path) char *path; { @@ -4203,26 +5161,155 @@ add_include_dir (path) if (include_dir_count == 0) { include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs)); - include_dirs[0] = "."; /* Current dir */ + 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 = + (char **) realloc (include_dirs, + include_dir_count * sizeof (*include_dirs)); } - include_dirs[include_dir_count - 1] = path; /* New one */ + include_dirs[include_dir_count - 1] = path; /* New one. */ i = strlen (path); if (i > include_dir_maxlen) include_dir_maxlen = i; -} /* add_include_dir() */ +} + +/* Output debugging information to denote the source file. */ + +static void +generate_file_debug () +{ + if (debug_type == DEBUG_STABS) + stabs_generate_asm_file (); +} + +/* Output line number debugging information for the current source line. */ + +void +generate_lineno_debug () +{ + switch (debug_type) + { + case DEBUG_UNSPECIFIED: + case DEBUG_NONE: + case DEBUG_DWARF: + break; + case DEBUG_STABS: + stabs_generate_asm_lineno (); + break; + case DEBUG_ECOFF: + ecoff_generate_asm_lineno (); + break; + case DEBUG_DWARF2: + /* ??? We could here indicate to dwarf2dbg.c that something + has changed. However, since there is additional backend + support that is required (calling dwarf2_emit_insn), we + let dwarf2dbg.c call as_where on its own. */ + break; + } +} + +/* Output debugging information to mark a function entry point or end point. + END_P is zero for .func, and non-zero for .endfunc. */ + +void +s_func (end_p) + int end_p; +{ + do_s_func (end_p, NULL); +} + +/* Subroutine of s_func so targets can choose a different default prefix. + If DEFAULT_PREFIX is NULL, use the target's "leading char". */ + +void +do_s_func (end_p, default_prefix) + int end_p; + const char *default_prefix; +{ + /* Record the current function so that we can issue an error message for + misplaced .func,.endfunc, and also so that .endfunc needs no + arguments. */ + static char *current_name; + static char *current_label; + + if (end_p) + { + if (current_name == NULL) + { + as_bad (_("missing .func")); + ignore_rest_of_line (); + return; + } + + if (debug_type == DEBUG_STABS) + stabs_generate_asm_endfunc (current_name, current_label); + + current_name = current_label = NULL; + } + else /* ! end_p */ + { + char *name, *label; + char delim1, delim2; -void + if (current_name != NULL) + { + as_bad (_(".endfunc missing for previous .func")); + ignore_rest_of_line (); + return; + } + + name = input_line_pointer; + delim1 = get_symbol_end (); + name = xstrdup (name); + *input_line_pointer = delim1; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + if (default_prefix) + asprintf (&label, "%s%s", default_prefix, name); + else + { + char leading_char = 0; +#ifdef BFD_ASSEMBLER + leading_char = bfd_get_symbol_leading_char (stdoutput); +#endif + /* Missing entry point, use function's name with the leading + char prepended. */ + if (leading_char) + asprintf (&label, "%c%s", leading_char, name); + else + label = name; + } + } + else + { + ++input_line_pointer; + SKIP_WHITESPACE (); + label = input_line_pointer; + delim2 = get_symbol_end (); + label = xstrdup (label); + *input_line_pointer = delim2; + } + + if (debug_type == DEBUG_STABS) + stabs_generate_asm_func (name, label); + + current_name = name; + current_label = label; + } + + demand_empty_rest_of_line (); +} + +void s_ignore (arg) - int arg; + int arg ATTRIBUTE_UNUSED; { while (!is_end_of_line[(unsigned char) *input_line_pointer]) { @@ -4231,7 +5318,6 @@ s_ignore (arg) ++input_line_pointer; } - void read_print_statistics (file) FILE *file; @@ -4239,4 +5325,34 @@ read_print_statistics (file) hash_print_statistics (file, "pseudo-op table", po_hash); } -/* end of read.c */ +/* Inserts the given line into the input stream. + + This call avoids macro/conditionals nesting checking, since the contents of + the line are assumed to replace the contents of a line already scanned. + + An appropriate use of this function would be substition of input lines when + called by md_start_line_hook(). The given line is assumed to already be + properly scrubbed. */ + +void +input_scrub_insert_line (line) + const char *line; +{ + sb newline; + sb_new (&newline); + sb_add_string (&newline, line); + input_scrub_include_sb (&newline, input_line_pointer, 0); + sb_kill (&newline); + buffer_limit = input_scrub_next_buffer (&input_line_pointer); +} + +/* Insert a file into the input stream; the path must resolve to an actual + file; no include path searching or dependency registering is performed. */ + +void +input_scrub_insert_file (path) + char *path; +{ + input_scrub_include_file (path, input_line_pointer); + buffer_limit = input_scrub_next_buffer (&input_line_pointer); +}