/* read.c - read a source file -
- Copyright (C) 1986, 1987, 1990, 1991, 1993, 1994
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 1998
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GAS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+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
#include "as.h"
#include "subsegs.h"
-
+#include "sb.h"
+#include "macro.h"
#include "obstack.h"
#include "listing.h"
+#include "ecoff.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x==':')
char *input_line_pointer; /*->next char of source file to parse. */
-int generate_asm_lineno = 0; /* flag to generate line stab for .s file */
-
#if BITS_PER_CHAR != 8
/* The following table is indexed by[(char)] and will break if
a char does not have exactly 256 states (hopefully 0:255!)! */
#define LEX_PCT 0
#endif
+#ifndef LEX_QM
+/* The PowerPC Windows NT assemblers permits ? inside label names. */
+#define LEX_QM 0
+#endif
+
+#ifndef LEX_DOLLAR
+/* The a29k assembler does not permits labels to start with $. */
+#define LEX_DOLLAR 3
+#endif
+
+#ifndef LEX_TILDE
+/* The Delta 68k assembler permits ~ at start of label names. */
+#define LEX_TILDE 0
+#endif
+
/* used by is_... macros. our ctype[] */
-const char lex_type[256] =
+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, 3, 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, 0, /* 0123456789:;<=>? */
+ 0, 0, 0, 0, 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{|}~. */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 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,
* In: a character.
* Out: 1 if this character ends a line.
*/
-#define _ (0)
+#define Z_ (0)
char is_end_of_line[256] =
{
#ifdef CR_EOL
- _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */
+ 99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, 99, Z_, Z_, /* @abcdefghijklmno */
#else
- _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
+ 99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, Z_, /* @abcdefghijklmno */
#endif
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
#ifdef TC_HPPA
- _,99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* _!"#$%&'()*+,-./ */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0123456789:;<=>? */
+ Z_,99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* _!"#$%&'()*+,-./ */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* 0123456789:;<=>? */
#else
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */
-#endif
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, /* 0123456789:;<=>? */
+#endif
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
};
-#undef _
+#undef Z_
/* 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. */
-int target_big_endian;
+/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
+ tc-<CPU>.h file. See the "Porting GAS" section of the internals manual. */
+int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
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. */
-char **include_dirs; /* List of pointers to directories to
+char **include_dirs; /* Table 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 */
+int include_dir_count; /* How many are in the table */
+int include_dir_maxlen = 1;/* Length of longest in table */
#ifndef WORKING_DOT_WORD
struct broken_word *broken_words;
int new_broken_words;
#endif
+/* The current offset into the absolute section. We don't try to
+ build frags in the absolute section, since no data can be stored
+ there. We just keep track of the current offset. */
+addressT abs_section_offset;
+
+/* If this line had an MRI style label, it is stored in this variable.
+ This is used by some of the MRI pseudo-ops. */
+symbolS *line_label;
+
+/* This global variable is used to support MRI common sections. We
+ translate such sections into a common symbol. This variable is
+ non-NULL when we are in an MRI common section. */
+symbolS *mri_common_symbol;
+
+/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
+ need to align to an even byte boundary unless the next pseudo-op is
+ dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment
+ may be needed. */
+static int mri_pending_align;
+
+#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 **));
+static void do_align PARAMS ((int, char *, int, int));
+static void s_align PARAMS ((int, int));
+static int hex_float PARAMS ((int, char *));
+static void do_org PARAMS ((segT, expressionS *, int));
char *demand_copy_string PARAMS ((int *lenP));
-int is_it_end_of_statement PARAMS ((void));
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));
+static void generate_lineno_debug PARAMS ((void));
\f
void
/* Something close -- but not too close -- to a multiple of 1024.
The debugging malloc I'm using has 24 bytes of overhead. */
- obstack_begin (¬es, 5090);
- obstack_begin (&cond_obstack, 990);
+ obstack_begin (¬es, chunksize);
+ obstack_begin (&cond_obstack, chunksize);
/* Use machine dependent syntax */
for (p = line_separator_chars; *p; p++)
is_end_of_line[(unsigned char) *p] = 1;
/* Use more. FIXME-SOMEDAY. */
+
+ if (flag_mri)
+ lex_type['?'] = 3;
}
\f
/* set up pseudo-op tables */
-struct hash_control *po_hash;
+static struct hash_control *po_hash;
static const pseudo_typeS potable[] =
{
{"align", s_align_ptwo, 0},
{"ascii", stringer, 0},
{"asciz", stringer, 1},
+ {"balign", s_align_bytes, 0},
+ {"balignw", s_align_bytes, -2},
+ {"balignl", s_align_bytes, -4},
/* block */
{"byte", cons, 1},
{"comm", s_comm, 0},
+ {"common", s_mri_common, 0},
+ {"common.s", s_mri_common, 1},
{"data", s_data, 0},
+ {"dc", cons, 2},
+ {"dc.b", cons, 1},
+ {"dc.d", float_cons, 'd'},
+ {"dc.l", cons, 4},
+ {"dc.s", float_cons, 'f'},
+ {"dc.w", cons, 2},
+ {"dc.x", float_cons, 'x'},
+ {"dcb", s_space, 2},
+ {"dcb.b", s_space, 1},
+ {"dcb.d", s_float_space, 'd'},
+ {"dcb.l", s_space, 4},
+ {"dcb.s", s_float_space, 'f'},
+ {"dcb.w", s_space, 2},
+ {"dcb.x", s_float_space, 'x'},
+ {"ds", s_space, 2},
+ {"ds.b", s_space, 1},
+ {"ds.d", s_space, 8},
+ {"ds.l", s_space, 4},
+ {"ds.p", s_space, 12},
+ {"ds.s", s_space, 4},
+ {"ds.w", s_space, 2},
+ {"ds.x", s_space, 12},
+ {"debug", s_ignore, 0},
#ifdef S_SET_DESC
{"desc", s_desc, 0},
#endif
/* dsect */
{"eject", listing_eject, 0}, /* Formfeed listing */
{"else", s_else, 0},
+ {"elsec", s_else, 0},
{"end", s_end, 0},
+ {"endc", s_endif, 0},
{"endif", s_endif, 0},
/* endef */
{"equ", s_set, 0},
-/* err */
+ {"equiv", s_set, 1},
+ {"err", s_err, 0},
+ {"exitm", s_mexit, 0},
/* 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},
{"file", s_app_file, 0},
{"fill", s_fill, 0},
{"float", float_cons, 'f'},
+ {"format", s_ignore, 0},
{"global", s_globl, 0},
{"globl", s_globl, 0},
{"hword", cons, 2},
- {"if", s_if, 0},
+ {"if", s_if, (int) O_ne},
+ {"ifc", s_ifc, 0},
{"ifdef", s_ifdef, 0},
+ {"ifeq", s_if, (int) O_eq},
{"ifeqs", s_ifeqs, 0},
+ {"ifge", s_if, (int) O_ge},
+ {"ifgt", s_if, (int) O_gt},
+ {"ifle", s_if, (int) O_le},
+ {"iflt", s_if, (int) O_lt},
+ {"ifnc", s_ifc, 1},
{"ifndef", s_ifdef, 1},
+ {"ifne", s_if, (int) O_ne},
{"ifnes", s_ifeqs, 1},
{"ifnotdef", s_ifdef, 1},
{"include", s_include, 0},
{"int", cons, 4},
+ {"irp", s_irp, 0},
+ {"irep", s_irp, 0},
+ {"irpc", s_irp, 1},
+ {"irepc", s_irp, 1},
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0}, /* Listing flags */
+ {"linkonce", s_linkonce, 0},
{"list", listing_list, 1}, /* Turn listing on */
+ {"llen", listing_psize, 1},
{"long", cons, 4},
{"lsym", s_lsym, 0},
+ {"macro", s_macro, 0},
+ {"mexit", s_mexit, 0},
+ {"mri", s_mri, 0},
+ {".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 */
+ {"nopage", listing_nopage, 0},
{"octa", cons, 16},
+ {"offset", s_struct, 0},
{"org", s_org, 0},
+ {"p2align", s_align_ptwo, 0},
+ {"p2alignw", s_align_ptwo, -2},
+ {"p2alignl", s_align_ptwo, -4},
+ {"page", listing_eject, 0},
+ {"plen", listing_psize, 0},
+ {"print", s_print, 0},
{"psize", listing_psize, 0}, /* set paper size */
-/* print */
+ {"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 */
{"single", float_cons, 'f'},
/* 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 */
{"text", s_text, 0},
{"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
{"title", listing_title, 0}, /* Listing title */
+ {"ttl", listing_title, 0},
/* 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 */
};
-static void
-pobegin ()
+static int pop_override_ok = 0;
+static const char *pop_table_name;
+
+void
+pop_insert (table)
+ const pseudo_typeS *table;
{
- const char *errtxt; /* error text */
+ const char *errtxt;
const pseudo_typeS *pop;
+ for (pop = table; pop->poc_name; pop++)
+ {
+ 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,
+ errtxt);
+ }
+}
+
+#ifndef md_pop_insert
+#define md_pop_insert() pop_insert(md_pseudo_table)
+#endif
+#ifndef obj_pop_insert
+#define obj_pop_insert() pop_insert(obj_pseudo_table)
+#endif
+
+static void
+pobegin ()
+{
po_hash = hash_new ();
/* Do the target-specific pseudo ops. */
- for (pop = md_pseudo_table; pop->poc_name; pop++)
- {
- errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt)
- {
- as_fatal ("error constructing md pseudo-op table");
- } /* on error */
- } /* for each op */
+ pop_table_name = "md";
+ md_pop_insert ();
/* Now object specific. Skip any that were in the target table. */
- for (pop = obj_pseudo_table; pop->poc_name; pop++)
- {
- errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt)
- {
- if (!strcmp (errtxt, "exists"))
- {
-#ifdef DIE_ON_OVERRIDES
- as_fatal ("pseudo op \".%s\" overridden.\n", pop->poc_name);
-#endif /* DIE_ON_OVERRIDES */
- continue; /* OK if target table overrides. */
- }
- else
- {
- as_fatal ("error constructing obj pseudo-op table");
- } /* if overridden */
- } /* on error */
- } /* for each op */
+ pop_table_name = "obj";
+ pop_override_ok = 1;
+ obj_pop_insert ();
/* Now portable ones. Skip any that we've seen already. */
- for (pop = potable; pop->poc_name; pop++)
- {
- errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt)
- {
- if (!strcmp (errtxt, "exists"))
- {
-#ifdef DIE_ON_OVERRIDES
- as_fatal ("pseudo op \".%s\" overridden.\n", pop->poc_name);
-#endif /* DIE_ON_OVERRIDES */
- continue; /* OK if target table overrides. */
- }
- else
- {
- as_fatal ("error constructing obj pseudo-op table");
- } /* if overridden */
- } /* on error */
- } /* for each op */
-
- return;
-} /* pobegin() */
+ pop_table_name = "standard";
+ pop_insert (potable);
+}
\f
#define HANDLE_CONDITIONAL_ASSEMBLY() \
if (ignore_input ()) \
}
+/* This function is used when scrubbing the characters between #APP
+ and #NO_APP. */
+
+static char *scrub_string;
+static char *scrub_string_end;
+
+static int
+scrub_from_string (from)
+ char **from;
+{
+ int size;
+
+ *from = scrub_string;
+ size = scrub_string_end - scrub_string;
+ scrub_string = scrub_string_end;
+ return size;
+}
+
/* read_a_source_file()
*
* We read the file, putting things into a web that
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. */
*/
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 ();
-#if defined (MRI) || defined (LABELS_WITHOUT_COLONS)
- /* Text at the start of a line must be a label, we run down
- and stick a colon in. */
- if (is_name_beginner (*input_line_pointer))
+ line_label = NULL;
+
+ if (flag_m68k_mri
+#ifdef LABELS_WITHOUT_COLONS
+ || 1
+#endif
+ )
{
- char *line_start = input_line_pointer;
- char c = get_symbol_end ();
- colon (line_start);
- *input_line_pointer = c;
- if (c == ':')
- input_line_pointer++;
+ /* Text at the start of a line must be a label, we
+ run down and stick a colon in. */
+ if (is_name_beginner (*input_line_pointer))
+ {
+ char *line_start = input_line_pointer;
+ char c;
+ int mri_line_macro;
+ LISTING_NEWLINE ();
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+ c = get_symbol_end ();
+
+ /* 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;
+
+ 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 (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;
+ }
+
+ /* 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)
+ 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 == ':')
+ input_line_pointer++;
+ }
}
-#endif
}
-
/*
* We are at the begining of a line, or similar place.
* We expect a well-formed assembler statement.
c = *input_line_pointer++;
}
know (c != ' '); /* No further leading whitespace. */
- LISTING_NEWLINE ();
+
+#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)
+ {
+ 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);
+ }
+#endif
+
/*
* C is the 1st significant character.
* Input_line_pointer points after that character.
*/
if (TC_START_LABEL(c, input_line_pointer))
{
- colon (s); /* user-defined label */
+ 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, 1);
+ continue;
+ }
+ }
+
+ line_label = colon (s); /* user-defined label */
*input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */
/* Input_line_pointer->after ':'. */
SKIP_WHITESPACE ();
}
else if (c == '='
- || (input_line_pointer[1] == '='
+ || ((c == ' ' || c == '\t')
+ && input_line_pointer[1] == '='
#ifdef TC_EQUAL_IN_INSN
&& ! 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 */
-#ifdef MRI
- if (!done_pseudo (s))
-
-#else
-
pop = NULL;
#define IGNORE_OPCODE_CASE
char *s2 = s;
while (*s2)
{
- if (isupper (*s2))
+ if (isupper ((unsigned char) *s2))
*s2 = tolower (*s2);
s2++;
}
}
#endif
+ if (flag_m68k_mri
#ifdef NO_PSEUDO_DOT
- /* The m88k uses pseudo-ops without a period. */
- pop = (pseudo_typeS *) hash_find (po_hash, s);
- if (pop != NULL && pop->poc_handler == NULL)
- pop = NULL;
+ || 1
#endif
+ )
+ {
+ /* The MRI assembler and the m88k use pseudo-ops
+ without a period. */
+ pop = (pseudo_typeS *) hash_find (po_hash, s);
+ if (pop != NULL && pop->poc_handler == NULL)
+ pop = NULL;
+ }
- if (pop != NULL || *s == '.')
+ if (pop != NULL
+ || (! flag_m68k_mri && *s == '.'))
{
/*
* PSEUDO - OP.
if (pop == NULL)
pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
+ /* In MRI mode, we may need to insert an
+ automatic alignment directive. What a hack
+ 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)
+#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, 0);
+ mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+
/* 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;
* after pseudo-operation.
*/
(*pop->poc_handler) (pop->poc_val);
+
+ /* If that was .end, just get out now. */
+ if (pop->poc_handler == s_end)
+ goto quit;
}
else
-#endif
- { /* machine instruction */
+ {
+ int inquote = 0;
+
/* 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
#ifdef TC_EOL_IN_INSN
|| TC_EOL_IN_INSN (input_line_pointer)
#endif
)
{
+ if (flag_m68k_mri && *input_line_pointer == '\'')
+ inquote = ! inquote;
input_line_pointer++;
}
c = *input_line_pointer;
*input_line_pointer = '\0';
-#ifdef OBJ_GENERATE_ASM_LINENO
- if (generate_asm_lineno == 0)
+ generate_lineno_debug ();
+
+ if (macro_defined)
{
- if (ecoff_no_current_file())
- generate_asm_lineno = 1;
+ sb out;
+ const char *err;
+
+ if (check_macro (s, &out, '\0', &err))
+ {
+ if (err != NULL)
+ as_bad (err);
+ *input_line_pointer++ = c;
+ input_scrub_include_sb (&out,
+ input_line_pointer);
+ sb_kill (&out);
+ buffer_limit =
+ input_scrub_next_buffer (&input_line_pointer);
+ continue;
+ }
}
- else
- {
- unsigned int lineno;
- char *s;
- as_where (&s, &lineno);
- OBJ_GENERATE_ASM_LINENO (s, lineno);
+ if (mri_pending_align)
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
}
-#endif
md_assemble (s); /* Assemble 1 instruction. */
if (is_end_of_line[(unsigned char) c])
continue;
-#if defined(LOCAL_LABELS_DOLLAR) || defined(LOCAL_LABELS_FB)
- if (isdigit (c))
+ if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
+ && isdigit ((unsigned char) c))
{
/* local label ("4:") */
char *backup = input_line_pointer;
temp = c - '0';
- while (isdigit (*input_line_pointer))
+ while (isdigit ((unsigned char) *input_line_pointer))
{
temp = (temp * 10) + *input_line_pointer - '0';
++input_line_pointer;
} /* read the whole number */
-#ifdef LOCAL_LABELS_DOLLAR
- if (*input_line_pointer == '$'
+ if (LOCAL_LABELS_DOLLAR
+ && *input_line_pointer == '$'
&& *(input_line_pointer + 1) == ':')
{
input_line_pointer += 2;
if (dollar_label_defined (temp))
{
- as_fatal ("label \"%d$\" redefined", temp);
+ as_fatal (_("label \"%d$\" redefined"), temp);
}
define_dollar_label (temp);
colon (dollar_label_name (temp, 0));
continue;
}
-#endif /* LOCAL_LABELS_DOLLAR */
-#ifdef LOCAL_LABELS_FB
- if (*input_line_pointer++ == ':')
+ if (LOCAL_LABELS_FB
+ && *input_line_pointer++ == ':')
{
fb_label_instance_inc (temp);
colon (fb_label_name (temp, 0));
continue;
}
-#endif /* LOCAL_LABELS_FB */
input_line_pointer = backup;
} /* local label ("4:") */
-#endif /* LOCAL_LABELS_DOLLAR or LOCAL_LABELS_FB */
if (c && strchr (line_comment_chars, c))
{ /* Its a comment. Better say APP or NO_APP */
char *new_tmp;
unsigned int new_length;
char *tmp_buf = 0;
- extern char *scrub_string, *scrub_last_string;
bump_line_counters ();
s = input_line_pointer;
{
input_line_pointer = ends + 8;
}
- new_buf = xmalloc (100);
- new_length = 100;
- new_tmp = new_buf;
scrub_string = s;
- scrub_last_string = ends;
+ scrub_string_end = ends;
+
+ new_length = ends - s;
+ new_buf = (char *) xmalloc (new_length);
+ new_tmp = new_buf;
for (;;)
{
- int ch;
+ int space;
+ int size;
- ch = do_scrub_next_char (scrub_from_string, scrub_to_string);
- if (ch == EOF)
- break;
- *new_tmp++ = ch;
- if (new_tmp == new_buf + new_length)
+ space = (new_buf + new_length) - new_tmp;
+ size = do_scrub_chars (scrub_from_string, new_tmp, space);
+
+ if (size < space)
{
- new_buf = xrealloc (new_buf, new_length + 100);
- new_tmp = new_buf + new_length;
- new_length += 100;
+ new_tmp += size;
+ break;
}
+
+ new_buf = xrealloc (new_buf, new_length + 100);
+ new_tmp = new_buf + new_length;
+ new_length += 100;
}
if (tmp_buf)
HANDLE_CONDITIONAL_ASSEMBLY ();
+#ifdef tc_unrecognized_line
+ 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. */
ignore_rest_of_line ();
} /* while (input_line_pointer<buffer_limit) */
+
+#ifdef md_after_pass_hook
+ md_after_pass_hook ();
+#endif
+
if (old_buffer)
{
+ free (buffer);
bump_line_counters ();
if (old_input != 0)
{
}
}
} /* while (more buffers to scan) */
+
+ quit:
+
+#ifdef md_cleanup
+ md_cleanup();
+#endif
input_scrub_close (); /* Close the input file */
+}
+
+/* For most MRI pseudo-ops, the line actually ends at the first
+ nonquoted space. This function looks for that point, stuffs a null
+ in, and sets *STOPCP to the character that used to be there, and
+ returns the location.
+
+ Until I hear otherwise, I am going to assume that this is only true
+ for the m68k MRI assembler. */
+char *
+mri_comment_field (stopcp)
+ char *stopcp;
+{
+#ifdef TC_M68K
+
+ char *s;
+ int inquote = 0;
+
+ know (flag_m68k_mri);
+
+ for (s = input_line_pointer;
+ ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
+ || inquote);
+ s++)
+ {
+ if (*s == '\'')
+ inquote = ! inquote;
+ }
+ *stopcp = *s;
+ *s = '\0';
+ return s;
+
+#else
+
+ char *s;
+
+ for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
+ ;
+ *stopcp = *s;
+ *s = '\0';
+ return s;
+
+#endif
+
+}
+
+/* Skip to the end of an MRI comment field. */
+
+void
+mri_comment_end (stop, stopc)
+ char *stop;
+ int stopc;
+{
+ know (flag_mri);
+
+ input_line_pointer = stop;
+ *stop = stopc;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
}
void
s_abort (ignore)
int ignore;
{
- as_fatal (".abort detected. Abandoning ship.");
+ as_fatal (_(".abort detected. Abandoning ship."));
}
-/* Guts of .align directive. */
+/* Guts of .align directive. N is the power of two to which to align.
+ FILL may be NULL, or it may point to the bytes of the fill pattern.
+ LEN is the length of whatever FILL points to, if anything. MAX is
+ the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
static void
-do_align (n, fill)
+do_align (n, fill, len, max)
int n;
char *fill;
+ int len;
+ int max;
{
+ char default_fill;
+
#ifdef md_do_align
- md_do_align (n, fill, just_record_alignment);
+ md_do_align (n, fill, len, max, just_record_alignment);
#endif
- if (!fill)
+
+ if (fill == NULL)
{
- /* @@ Fix this right for BFD! */
- static char zero;
- static char nop_opcode = NOP_OPCODE;
+ int maybe_text;
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#else
if (now_seg != data_section && now_seg != bss_section)
- {
- fill = &nop_opcode;
- }
+ maybe_text = 1;
else
- {
- fill = &zero;
- }
+ maybe_text = 0;
+#endif
+
+ if (maybe_text)
+ default_fill = NOP_OPCODE;
+ else
+ default_fill = 0;
+ fill = &default_fill;
+ len = 1;
}
+
/* Only make a frag if we HAVE to. . . */
- if (n && !need_pass_2)
- frag_align (n, *fill);
+ if (n != 0 && !need_pass_2)
+ {
+ if (len <= 1)
+ frag_align (n, *fill, max);
+ else
+ frag_align_pattern (n, fill, len, max);
+ }
#ifdef md_do_align
just_record_alignment:
record_alignment (now_seg, n);
}
-/* 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);
if (is_end_of_line[(unsigned char) *input_line_pointer])
- temp = arg; /* Default value from pseudo-op table */
+ {
+ if (arg < 0)
+ align = 0;
+ else
+ align = arg; /* Default value from pseudo-op table */
+ }
else
- temp = get_absolute_expression ();
+ {
+ align = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ }
- if (temp > max_alignment)
+ if (bytes_p)
{
- as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
+ /* 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;
+ }
}
- /* For the sparc, `.align (1<<n)' actually means `.align n' so we
- have to convert it. */
- if (temp != 0)
+ if (align > 15)
{
- for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
- ;
+ align = 15;
+ as_bad (_("Alignment too large: %u assumed"), align);
}
- if (temp != 1)
- as_bad ("Alignment not a power of 2");
- temp = i;
- if (*input_line_pointer == ',')
+ if (*input_line_pointer != ',')
{
- input_line_pointer++;
- temp_fill = get_absolute_expression ();
- do_align (temp, &temp_fill);
+ fill_p = 0;
+ max = 0;
}
else
- do_align (temp, (char *) 0);
-
- demand_empty_rest_of_line ();
-}
+ {
+ ++input_line_pointer;
+ if (*input_line_pointer == ',')
+ fill_p = 0;
+ else
+ {
+ fill = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ fill_p = 1;
+ }
-/* For machines where ".align 4" means align to 2**4 boundary. */
-void
-s_align_ptwo (ignore)
- int ignore;
-{
- register int temp;
- char temp_fill;
- long max_alignment = 15;
+ if (*input_line_pointer != ',')
+ max = 0;
+ else
+ {
+ ++input_line_pointer;
+ max = get_absolute_expression ();
+ }
+ }
- 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
{
- input_line_pointer++;
- temp_fill = get_absolute_expression ();
- do_align (temp, &temp_fill);
+ int fill_len;
+
+ if (arg >= 0)
+ fill_len = 1;
+ else
+ fill_len = - arg;
+ if (fill_len <= 1)
+ {
+ char fill_char;
+
+ fill_char = fill;
+ do_align (align, &fill_char, fill_len, max);
+ }
+ else
+ {
+ char ab[16];
+
+ if ((size_t) fill_len > sizeof ab)
+ abort ();
+ md_number_to_chars (ab, fill, fill_len);
+ do_align (align, ab, fill_len, max);
+ }
}
- else
- do_align (temp, (char *) 0);
+
+ 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
s_comm (ignore)
int ignore;
register char *p;
offsetT temp;
register symbolS *symbolP;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
name = input_line_pointer;
c = get_symbol_end ();
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
- as_bad ("Expected comma after symbol-name: rest of line ignored.");
+ as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+ 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);
+ 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 (_("Ignoring attempt to re-define symbol `%s'."),
S_GET_NAME (symbolP));
+ 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 changed to %ld."),
S_GET_NAME (symbolP),
(long) S_GET_VALUE (symbolP),
(long) temp);
}
#endif /* not OBJ_VMS */
know (symbolP->sy_frag == &zero_address_frag);
+
+ 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
+ symbol with the appropriate name. We make s_space do the right
+ thing by increasing the size. */
+
void
-s_data (ignore)
- int ignore;
+s_mri_common (small)
+ int small;
{
- segT section;
- register int temp;
-
- temp = get_absolute_expression ();
- if (flag_readonly_data_in_text)
+ char *name;
+ char c;
+ char *alc = NULL;
+ symbolS *sym;
+ offsetT align;
+ char *stop = NULL;
+ char stopc;
+
+ if (! flag_mri)
{
- section = text_section;
- temp += 1000;
+ s_comm (0);
+ return;
}
- else
- section = data_section;
- subseg_set (section, (subsegT) temp);
+ stop = mri_comment_field (&stopc);
-#ifdef OBJ_VMS
- const_flag = 0;
-#endif
- demand_empty_rest_of_line ();
-}
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ if (! isdigit ((unsigned char) *name))
+ c = get_symbol_end ();
+ else
+ {
+ do
+ {
+ ++input_line_pointer;
+ }
+ while (isdigit ((unsigned char) *input_line_pointer));
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ if (line_label != NULL)
+ {
+ alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
+ + (input_line_pointer - name)
+ + 1);
+ sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
+ name = alc;
+ }
+ }
+
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ if (alc != NULL)
+ free (alc);
+
+ if (*input_line_pointer != ',')
+ align = 0;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ }
+
+ if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
+ {
+ as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym));
+ mri_comment_end (stop, stopc);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ S_SET_EXTERNAL (sym);
+ mri_common_symbol = sym;
+
+#ifdef S_SET_ALIGN
+ if (align != 0)
+ S_SET_ALIGN (sym, align);
+#endif
+
+ 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;
+ S_SET_SEGMENT (line_label, expr_section);
+ }
+
+ /* FIXME: We just ignore the small argument, which distinguishes
+ COMMON and COMMON.S. I don't know what we can do about it. */
+
+ /* Ignore the type and hptype. */
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+}
+
+void
+s_data (ignore)
+ int ignore;
+{
+ segT section;
+ register int temp;
+
+ temp = get_absolute_expression ();
+ if (flag_readonly_data_in_text)
+ {
+ section = text_section;
+ temp += 1000;
+ }
+ else
+ section = data_section;
+
+ subseg_set (section, (subsegT) temp);
+
+#ifdef OBJ_VMS
+ const_flag = 0;
+#endif
+ demand_empty_rest_of_line ();
+}
/* Handle the .appfile pseudo-op. This is automatically generated by
- do_scrub_next_char when a preprocessor # line comment is seen with
- a file name. This default definition may be overridden by the
- object or CPU specific pseudo-ops. This function is also the
- default definition for .file; the APPFILE argument is 1 for
- .appfile, 0 for .file. */
+ do_scrub_chars when a preprocessor # line comment is seen with a
+ file name. This default definition may be overridden by the object
+ or CPU specific pseudo-ops. This function is also the default
+ definition for .file; the APPFILE argument is 1 for .appfile, 0 for
+ .file. */
void
s_app_file (appfile)
/* 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. */
+ if (flag_m68k_mri
+ && *input_line_pointer == '\''
+ && is_end_of_line[(unsigned char) input_line_pointer[1]])
+ ++input_line_pointer;
+
demand_empty_rest_of_line ();
+ if (! may_omit)
+ {
#ifdef LISTING
- if (listing)
- listing_source_file (s);
+ if (listing)
+ listing_source_file (s);
#endif
- }
-#ifdef OBJ_COFF
- c_dot_file_symbol (s);
-#endif /* OBJ_COFF */
-#ifdef OBJ_ELF
- elf_file_symbol (s);
+ register_dependency (s);
+#ifdef obj_app_file
+ obj_app_file (s);
#endif
+ }
+ }
}
/* Handle the .appline pseudo-op. This is automatically generated by
- do_scrub_next_char when a preprocessor # line comment is seen.
- This default definition may be overridden by the object or CPU
- specific pseudo-ops. */
+ do_scrub_chars when a preprocessor # line comment is seen. This
+ default definition may be overridden by the object or CPU specific
+ pseudo-ops. */
void
s_app_line (ignore)
/* The given number is that of the next line. */
l = get_absolute_expression () - 1;
- new_logical_line ((char *) NULL, l);
+ 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);
+ else
+ {
+ new_logical_line ((char *) NULL, l);
#ifdef LISTING
- if (listing)
- listing_source_line (l);
+ if (listing)
+ listing_source_line (l);
#endif
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .end pseudo-op. Actually, the real work is done in
+ read_a_source_file. */
+
+void
+s_end (ignore)
+ int ignore;
+{
+ 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]
+ && *input_line_pointer != '*'
+ && *input_line_pointer != '!')
+ as_warn (_("start address not supported"));
+ }
+}
+
+/* Handle the .err pseudo-op. */
+
+void
+s_err (ignore)
+ int ignore;
+{
+ as_bad (_(".err encountered"));
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI fail pseudo-op. */
+
+void
+s_fail (ignore)
+ int ignore;
+{
+ offsetT temp;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ temp = get_absolute_expression ();
+ if (temp >= 500)
+ as_warn (_(".fail %ld encountered"), (long) temp);
+ else
+ as_bad (_(".fail %ld encountered"), (long) temp);
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
demand_empty_rest_of_line ();
}
s_fill (ignore)
int ignore;
{
- 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)
{
- 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);
+ 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 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
+ md_number_to_chars (p, (valueT) fill,
+ (size > BSD_FILL_SIZE_CROCK_4
? BSD_FILL_SIZE_CROCK_4
- : (int) temp_size));
+ : (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.
char *name;
int c;
symbolS *symbolP;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
do
{
}
}
while (c == ',');
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
demand_empty_rest_of_line ();
}
-void
-s_lcomm (needs_align)
+/* Handle the MRI IRP and IRPC pseudo-ops. */
+
+void
+s_irp (irpc)
+ int irpc;
+{
+ char *file;
+ unsigned int line;
+ sb s;
+ const char *err;
+ sb out;
+
+ as_where (&file, &line);
+
+ sb_new (&s);
+ 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');
+ if (err != NULL)
+ as_bad_where (file, line, "%s", err);
+
+ sb_kill (&s);
+
+ input_scrub_include_sb (&out, input_line_pointer);
+ sb_kill (&out);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Handle the .linkonce pseudo-op. This tells the assembler to mark
+ the section to only be linked once. However, this is not supported
+ by most object file formats. This takes an optional argument,
+ which is what to do about duplicates. */
+
+void
+s_linkonce (ignore)
+ int ignore;
+{
+ enum linkonce_type type;
+
+ SKIP_WHITESPACE ();
+
+ type = LINKONCE_DISCARD;
+
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ char *s;
+ char c;
+
+ s = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (s, "discard") == 0)
+ type = LINKONCE_DISCARD;
+ else if (strcasecmp (s, "one_only") == 0)
+ type = LINKONCE_ONE_ONLY;
+ else if (strcasecmp (s, "same_size") == 0)
+ type = LINKONCE_SAME_SIZE;
+ else if (strcasecmp (s, "same_contents") == 0)
+ type = LINKONCE_SAME_CONTENTS;
+ else
+ as_warn (_("unrecognized .linkonce type `%s'"), s);
+
+ *input_line_pointer = c;
+ }
+
+#ifdef obj_handle_link_once
+ obj_handle_link_once (type);
+#else /* ! defined (obj_handle_link_once) */
+#ifdef BFD_ASSEMBLER
+ {
+ flagword flags;
+
+ if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
+ as_warn (_(".linkonce is not supported for this object file format"));
+
+ flags = bfd_get_section_flags (stdoutput, now_seg);
+ flags |= SEC_LINK_ONCE;
+ switch (type)
+ {
+ default:
+ abort ();
+ case LINKONCE_DISCARD:
+ flags |= SEC_LINK_DUPLICATES_DISCARD;
+ break;
+ case LINKONCE_ONE_ONLY:
+ flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+ break;
+ case LINKONCE_SAME_SIZE:
+ flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
+ break;
+ case LINKONCE_SAME_CONTENTS:
+ flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
+ break;
+ }
+ 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"));
+#endif /* ! defined (BFD_ASSEMBLER) */
+#endif /* ! defined (obj_handle_link_once) */
+
+ demand_empty_rest_of_line ();
+}
+
+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) */
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;
if (*input_line_pointer == '\n')
{
- 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;
}
#if defined (TC_MIPS) || defined (TC_ALPHA)
-#if defined (OBJ_ECOFF) || defined (OBJ_ELF)
- /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */
- if (temp <= bfd_get_gp_size (stdoutput))
+ if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
- bss_seg = subseg_new (".sbss", 1);
- seg_info (bss_seg)->bss = 1;
- }
+ /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */
+ if (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"),
+ bfd_errmsg (bfd_get_error ()));
#endif
+ }
+ }
#endif
if (!needs_align)
{
else if (temp >= 2)
align = 1;
else
- align = temp;
+ align = 0;
+
+#ifdef OBJ_EVAX
+ /* FIXME: This needs to be done in a more general fashion. */
+ align = 3;
+#endif
record_alignment(bss_seg, align);
}
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
- as_bad ("Expected comma after size");
+ as_bad (_("Expected comma after size"));
ignore_rest_of_line ();
return;
}
SKIP_WHITESPACE ();
if (*input_line_pointer == '\n')
{
- 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. */
-#ifdef TC_ALPHA
+#if defined (TC_ALPHA) && ! defined (VMS)
if (temp > 1)
{
align = ffs (temp) - 1;
subseg_set (bss_seg, 1);
if (align)
- frag_align (align, 0);
+ frag_align (align, 0, 0);
/* detach from old frag */
if (S_GET_SEGMENT (symbolP) == bss_seg)
symbolP->sy_frag->fr_symbol = NULL;
symbolP->sy_frag = frag_now;
pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
- temp, (char *)0);
+ (offsetT) temp, (char *) 0);
*pfrag = 0;
S_SET_SEGMENT (symbolP, bss_seg);
S_SET_STORAGE_CLASS (symbolP, C_STAT);
}
#endif /* OBJ_COFF */
+
+#ifdef S_SET_SIZE
+ S_SET_SIZE (symbolP, temp);
+#endif
}
else
- as_bad ("Ignoring attempt to re-define symbol `%s'.",
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
S_GET_NAME (symbolP));
subseg_set (current_seg, current_subseg);
demand_empty_rest_of_line ();
-} /* s_lcomm() */
+} /* s_lcomm_internal() */
+
+void
+s_lcomm (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 0);
+}
+
+void s_lcomm_bytes (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 1);
+}
void
s_lsym (ignore)
int ignore;
{
- register char *name;
- register char c;
- register char *p;
- expressionS exp;
- register symbolS *symbolP;
-
- /* we permit ANY defined expression: BSD4.2 demands constants */
- name = input_line_pointer;
- c = get_symbol_end ();
- p = input_line_pointer;
- *p = c;
- SKIP_WHITESPACE ();
- if (*input_line_pointer != ',')
- {
- *p = 0;
- as_bad ("Expected comma after name \"%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)
+ register char *name;
+ register char c;
+ register char *p;
+ expressionS exp;
+ register symbolS *symbolP;
+
+ /* we permit ANY defined expression: BSD4.2 demands constants */
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_bad (_("Expected comma after name \"%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"));
+ ignore_rest_of_line ();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+
+ /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
+ symbolP->sy_desc == 0) out of this test because coff doesn't have
+ those fields, and I 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. */
+
+ 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. */
+ S_SET_SEGMENT (symbolP,
+ (exp.X_op == O_constant
+ ? absolute_section
+ : reg_section));
+ S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
+ }
+ else
+ {
+ as_bad (_("Symbol %s already defined"), name);
+ }
+ *p = c;
+ demand_empty_rest_of_line ();
+} /* s_lsym() */
+
+/* Read a line into an sb. */
+
+static int
+get_line_sb (line)
+ sb *line;
+{
+ char quote1, quote2, inquote;
+
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+
+ if (input_line_pointer >= buffer_limit)
+ {
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+ if (buffer_limit == 0)
+ return 0;
+ }
+
+ /* 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])
+ {
+ if (input_line_pointer[-1] == '\n')
+ 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. */
+
+void
+s_macro (ignore)
+ int ignore;
+{
+ char *file;
+ unsigned int line;
+ sb s;
+ sb label;
+ const char *err;
+ const char *name;
+
+ as_where (&file, &line);
+
+ sb_new (&s);
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ sb_add_char (&s, *input_line_pointer++);
+
+ sb_new (&label);
+ if (line_label != NULL)
+ sb_add_string (&label, S_GET_NAME (line_label));
+
+ err = define_macro (0, &s, &label, get_line_sb, &name);
+ if (err != NULL)
+ as_bad_where (file, line, "%s", err);
+ else
+ {
+ if (line_label != NULL)
+ {
+ S_SET_SEGMENT (line_label, undefined_section);
+ S_SET_VALUE (line_label, 0);
+ line_label->sy_frag = &zero_address_frag;
+ }
+
+ if (((flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+ || 1
+#endif
+ )
+ && hash_find (po_hash, name) != NULL)
+ || (! flag_m68k_mri
+ && *name == '.'
+ && hash_find (po_hash, name + 1) != NULL))
+ as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
+ name);
+ }
+
+ sb_kill (&s);
+}
+
+/* Handle the .mexit pseudo-op, which immediately exits a macro
+ expansion. */
+
+void
+s_mexit (ignore)
+ int ignore;
+{
+ cond_exit_macro (macro_nest);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Switch in and out of MRI mode. */
+
+void
+s_mri (ignore)
+ int ignore;
+{
+ int on, old_flag;
+
+ on = get_absolute_expression ();
+ old_flag = flag_mri;
+ if (on != 0)
+ {
+ flag_mri = 1;
+#ifdef TC_M68K
+ flag_m68k_mri = 1;
+#endif
+ }
+ else
+ {
+ flag_mri = 0;
+ flag_m68k_mri = 0;
+ }
+
+#ifdef MRI_MODE_CHANGE
+ if (on != old_flag)
+ MRI_MODE_CHANGE (on);
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle changing the location counter. */
+
+static void
+do_org (segment, exp, fill)
+ segT segment;
+ expressionS *exp;
+ int fill;
+{
+ if (segment != now_seg && segment != absolute_section)
+ as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"),
+ segment_name (segment), segment_name (now_seg));
+
+ if (now_seg == absolute_section)
+ {
+ if (fill != 0)
+ as_warn (_("ignoring fill value in absolute section"));
+ if (exp->X_op != O_constant)
+ {
+ as_bad (_("only constant offsets supported in absolute section"));
+ exp->X_add_number = 0;
+ }
+ abs_section_offset = exp->X_add_number;
+ }
+ else
+ {
+ char *p;
+
+ p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
+ exp->X_add_number, (char *) NULL);
+ *p = fill;
+ }
+}
+
+void
+s_org (ignore)
+ int ignore;
+{
+ register segT segment;
+ expressionS exp;
+ register long temp_fill;
+
+ /* 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"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* Don't believe the documentation of BSD 4.2 AS. There is no such
+ thing as a sub-segment-relative origin. Any absolute origin is
+ given a warning, then assumed to be segment-relative. Any
+ segmented origin expression ("foo+42") had better be in the right
+ segment or the .org is ignored.
+
+ BSD 4.2 AS warns if you try to .org backwards. We cannot because
+ we never know sub-segment sizes when we are reading code. BSD
+ will crash trying to emit negative numbers of filler bytes in
+ certain .orgs. We don't crash, but see as-write for that code.
+
+ Don't make frag if need_pass_2==1. */
+ segment = get_known_segmented_expression (&exp);
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ temp_fill = get_absolute_expression ();
+ }
+ else
+ temp_fill = 0;
+
+ if (!need_pass_2)
+ 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
+ when in MRI mode. It will create a new section, and return it. It
+ will set *TYPE to the section type: one of 'C' (code), 'D' (data),
+ 'M' (mixed), or 'R' (romable). If BFD_ASSEMBLER is defined, the
+ flags will be set in the section. */
+
+void
+s_mri_sect (type)
+ char *type;
+{
+#ifdef TC_M68K
+
+ char *name;
+ char c;
+ segT seg;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ if (! isdigit ((unsigned char) *name))
+ c = get_symbol_end ();
+ else
+ {
+ do
+ {
+ ++input_line_pointer;
+ }
+ while (isdigit ((unsigned char) *input_line_pointer));
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+ }
+
+ name = xstrdup (name);
+
+ *input_line_pointer = c;
+
+ seg = subseg_new (name, 0);
+
+ if (*input_line_pointer == ',')
+ {
+ int align;
+
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ record_alignment (seg, align);
+ }
+
+ *type = 'C';
+ if (*input_line_pointer == ',')
+ {
+ c = *++input_line_pointer;
+ c = toupper ((unsigned char) c);
+ if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
+ *type = c;
+ else
+ as_bad (_("unrecognized section type"));
+ ++input_line_pointer;
+
+#ifdef BFD_ASSEMBLER
+ {
+ flagword flags;
+
+ flags = SEC_NO_FLAGS;
+ if (*type == 'C')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
+ else if (*type == 'D' || *type == 'M')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
+ else if (*type == 'R')
+ 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"),
+ bfd_section_name (stdoutput, seg),
+ bfd_errmsg (bfd_get_error ()));
+ }
+ }
+#endif
+ }
+
+ /* Ignore the HP type. */
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+
+ demand_empty_rest_of_line ();
+
+#else /* ! TC_M68K */
+#ifdef TC_I960
+
+ char *name;
+ char c;
+ segT seg;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xstrdup (name);
+
+ *input_line_pointer = c;
+
+ seg = subseg_new (name, 0);
+
+ if (*input_line_pointer != ',')
+ *type = 'C';
+ else
+ {
+ char *sectype;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ sectype = input_line_pointer;
+ c = get_symbol_end ();
+ if (*sectype == '\0')
+ *type = 'C';
+ else if (strcasecmp (sectype, "text") == 0)
+ *type = 'C';
+ else if (strcasecmp (sectype, "data") == 0)
+ *type = 'D';
+ else if (strcasecmp (sectype, "romdata") == 0)
+ *type = 'R';
+ else
+ as_warn (_("unrecognized section type `%s'"), sectype);
+ *input_line_pointer = c;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ char *seccmd;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ seccmd = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (seccmd, "absolute") == 0)
+ {
+ as_bad (_("absolute sections are not supported"));
+ *input_line_pointer = c;
+ ignore_rest_of_line ();
+ return;
+ }
+ else if (strcasecmp (seccmd, "align") == 0)
+ {
+ int align;
+
+ *input_line_pointer = c;
+ align = get_absolute_expression ();
+ record_alignment (seg, align);
+ }
+ else
+ {
+ as_warn (_("unrecognized section command `%s'"), seccmd);
+ *input_line_pointer = c;
+ }
+ }
+
+ demand_empty_rest_of_line ();
+
+#else /* ! TC_I960 */
+ /* The MRI assembler seems to use different forms of .sect for
+ different targets. */
+ as_bad ("MRI mode not supported for this target");
+ ignore_rest_of_line ();
+#endif /* ! TC_I960 */
+#endif /* ! TC_M68K */
+}
+
+/* Handle the .print pseudo-op. */
+
+void
+s_print (ignore)
+ int ignore;
+{
+ char *s;
+ int len;
+
+ s = demand_copy_C_string (&len);
+ printf ("%s\n", s);
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .purgem pseudo-op. */
+
+void
+s_purgem (ignore)
+ int ignore;
+{
+ if (is_it_end_of_statement ())
{
- as_bad ("bad expression");
- ignore_rest_of_line ();
+ demand_empty_rest_of_line ();
return;
}
- *p = 0;
- symbolP = symbol_find_or_make (name);
-
- /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
- symbolP->sy_desc == 0) out of this test because coff doesn't have
- those fields, and I 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. */
- 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. */
- S_SET_SEGMENT (symbolP,
- (exp.X_op == O_constant
- ? absolute_section
- : reg_section));
- S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
- }
- else
+ do
{
- as_bad ("Symbol %s already defined", name);
+ char *name;
+ char c;
+
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ delete_macro (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
}
- *p = c;
+ while (*input_line_pointer++ == ',');
+
+ --input_line_pointer;
demand_empty_rest_of_line ();
-} /* s_lsym() */
+}
-void
-s_org (ignore)
+/* Handle the .rept pseudo-op. */
+
+void
+s_rept (ignore)
int ignore;
{
- register segT segment;
- expressionS exp;
- register long temp_fill;
- register char *p;
- /* Don't believe the documentation of BSD 4.2 AS. There is no such
- thing as a sub-segment-relative origin. Any absolute origin is
- given a warning, then assumed to be segment-relative. Any
- segmented origin expression ("foo+42") had better be in the right
- segment or the .org is ignored.
+ int count;
+ sb one;
+ sb many;
- BSD 4.2 AS warns if you try to .org backwards. We cannot because
- we never know sub-segment sizes when we are reading code. BSD
- will crash trying to emit negative numbers of filler bytes in
- certain .orgs. We don't crash, but see as-write for that code.
+ count = get_absolute_expression ();
- Don't make frag if need_pass_2==1. */
- segment = get_known_segmented_expression (&exp);
- if (*input_line_pointer == ',')
+ sb_new (&one);
+ if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb))
{
- input_line_pointer++;
- temp_fill = get_absolute_expression ();
+ as_bad (_("rept without endr"));
+ return;
}
- else
- temp_fill = 0;
- if (!need_pass_2)
- {
- if (segment != now_seg && segment != absolute_section)
- as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
- segment_name (segment), segment_name (now_seg));
- p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
- exp.X_add_number, (char *) 0);
- *p = temp_fill;
- } /* if (ok to make frag) */
- demand_empty_rest_of_line ();
-} /* s_org() */
+
+ sb_new (&many);
+ while (count-- > 0)
+ sb_add_sb (&many, &one);
+
+ sb_kill (&one);
+
+ input_scrub_include_sb (&many, input_line_pointer);
+ sb_kill (&many);
+ 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 (ignore)
- int ignore;
+s_set (equiv)
+ int equiv;
{
register char *name;
register char delim;
if (*input_line_pointer != ',')
{
*end_name = 0;
- as_bad ("Expected comma after name \"%s\"", name);
+ as_bad (_("Expected comma after name \"%s\""), name);
*end_name = delim;
ignore_rest_of_line ();
return;
/* Turn '. = mumble' into a .org mumble */
register segT segment;
expressionS exp;
- register char *ptr;
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
- {
- if (segment != now_seg && segment != absolute_section)
- as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
- segment_name (segment),
- segment_name (now_seg));
- ptr = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
- exp.X_add_number, (char *) 0);
- *ptr = 0;
- } /* if (ok to make frag) */
+ do_org (segment, &exp, 0);
*end_name = delim;
return;
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. */
SF_SET_LOCAL (symbolP);
symbol_table_insert (symbolP);
*end_name = delim;
+
+ if (equiv
+ && S_IS_DEFINED (symbolP)
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
+
pseudo_set (symbolP);
demand_empty_rest_of_line ();
} /* s_set() */
s_space (mult)
int mult;
{
- long temp_repeat;
- register long temp_fill;
- register char *p;
+ expressionS exp;
+ expressionS val;
+ char *p = 0;
+ char *stop = NULL;
+ char stopc;
+ int bytes;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
- /* Just like .fill, but temp_size = 1 */
- if (get_absolute_expression_and_terminator (&temp_repeat) == ',')
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ /* In m68k MRI mode, we need to align to a word boundary, unless
+ this is ds.b. */
+ if (flag_m68k_mri && mult > 1)
{
- temp_fill = get_absolute_expression ();
+ if (now_seg == absolute_section)
+ {
+ abs_section_offset += abs_section_offset & 1;
+ if (line_label != NULL)
+ S_SET_VALUE (line_label, abs_section_offset);
+ }
+ else if (mri_common_symbol != NULL)
+ {
+ valueT val;
+
+ val = S_GET_VALUE (mri_common_symbol);
+ if ((val & 1) != 0)
+ {
+ 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;
+ }
+ }
+ }
+ else
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+ }
+
+ bytes = mult;
+
+ expression (&exp);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ expression (&val);
}
else
{
- input_line_pointer--; /* Backup over what was not a ','. */
- temp_fill = 0;
+ val.X_op = O_constant;
+ val.X_add_number = 0;
+ }
+
+ if (val.X_op != O_constant
+ || val.X_add_number < - 0x80
+ || val.X_add_number > 0xff
+ || (mult != 0 && mult != 1 && val.X_add_number != 0))
+ {
+ if (exp.X_op != O_constant)
+ 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);
+ }
}
- if (mult)
+ else
{
- temp_repeat *= mult;
+ if (exp.X_op == O_constant)
+ {
+ long repeat;
+
+ repeat = exp.X_add_number;
+ if (mult)
+ repeat *= mult;
+ bytes = repeat;
+ if (repeat <= 0)
+ {
+ 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;
+ }
+
+ /* If we are in the absolute section, just bump the offset. */
+ if (now_seg == absolute_section)
+ {
+ abs_section_offset += repeat;
+ goto getout;
+ }
+
+ /* If we are secretly in an MRI common section, then
+ creating space just increases the size of the common
+ symbol. */
+ if (mri_common_symbol != NULL)
+ {
+ S_SET_VALUE (mri_common_symbol,
+ S_GET_VALUE (mri_common_symbol) + repeat);
+ goto getout;
+ }
+
+ if (!need_pass_2)
+ p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
+ (offsetT) repeat, (char *) 0);
+ }
+ else
+ {
+ if (now_seg == 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"));
+ mri_common_symbol = NULL;
+ }
+ if (!need_pass_2)
+ p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
+ make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
+ }
+
+ if (p)
+ *p = val.X_add_number;
}
- if (temp_repeat <= 0)
+
+ getout:
+
+ /* 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;
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+}
+
+/* This is like s_space, but the value is a floating point number with
+ the given precision. This is for the MRI dcb.s pseudo-op and
+ friends. */
+
+void
+s_float_space (float_type)
+ int float_type;
+{
+ offsetT count;
+ int flen;
+ char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ count = get_absolute_expression ();
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
{
- as_warn ("Repeat < 0, .space ignored");
+ as_bad (_("missing value"));
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
ignore_rest_of_line ();
return;
}
- if (!need_pass_2)
+
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+
+ /* Skip any 0{letter} that may be present. Don't even check if the
+ * letter is legal. */
+ if (input_line_pointer[0] == '0'
+ && isalpha ((unsigned char) input_line_pointer[1]))
+ input_line_pointer += 2;
+
+ /* Accept :xxxx, where the x's are hex digits, for a floating point
+ with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
+ {
+ flen = hex_float (float_type, temp);
+ if (flen < 0)
+ {
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ {
+ char *err;
+
+ err = md_atof (float_type, temp, &flen);
+ know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (flen > 0);
+ if (err)
+ {
+ as_bad (_("Bad floating literal: %s"), err);
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+
+ while (--count >= 0)
{
- p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
- temp_repeat, (char *) 0);
- *p = temp_fill;
+ char *p;
+
+ p = frag_more (flen);
+ memcpy (p, temp, (unsigned int) flen);
}
+
+ 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;
+{
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+ abs_section_offset = get_absolute_expression ();
+ subseg_set (absolute_section, 0);
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
-} /* s_space() */
+}
void
s_text (ignore)
{
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'.",
+ if (isprint ((unsigned char) *input_line_pointer))
+ as_bad (_("Rest of line ignored. First ignored character is `%c'."),
*input_line_pointer);
else
- as_bad ("Rest of line ignored. First ignored character valued 0x%x.",
+ as_bad (_("Rest of line ignored. First ignored character valued 0x%x."),
*input_line_pointer);
while (input_line_pointer < buffer_limit
&& !is_end_of_line[(unsigned char) *input_line_pointer])
(void) expression (&exp);
if (exp.X_op == O_illegal)
- as_bad ("illegal expression; zero assumed");
+ as_bad (_("illegal expression; zero assumed"));
else if (exp.X_op == O_absent)
- as_bad ("missing expression; zero assumed");
+ as_bad (_("missing expression; zero assumed"));
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; zero assumed"));
+ else
+ as_bad (_("floating point number invalid; zero assumed"));
+ }
else if (exp.X_op == O_subtract
&& (S_GET_SEGMENT (exp.X_add_symbol)
== S_GET_SEGMENT (exp.X_op_symbol))
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)
+ symbolP->sy_frag = &zero_address_frag;
break;
case O_register:
are defined, which is the normal case, then only simple expressions
are permitted. */
+static void
+parse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+
#ifndef TC_PARSE_CONS_EXPRESSION
#ifdef BITFIELD_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
static void
parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
#endif
-#ifdef MRI
-#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_mri_cons (EXP)
-static void
-parse_mri_cons PARAMS ((expressionS *exp));
-#endif
#ifdef REPEAT_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
static void
/* worker to do .byte etc statements */
/* clobbers input_line_pointer, checks */
/* end-of-line. */
-void
-cons (nbytes)
+static void
+cons_worker (nbytes, rva)
register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+ int rva;
{
+ int c;
expressionS exp;
+ char *stop = NULL;
+ char stopc;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
if (is_it_end_of_statement ())
{
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
return;
}
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
+ c = 0;
do
{
- TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
+ if (flag_m68k_mri)
+ parse_mri_cons (&exp, (unsigned int) nbytes);
+ else
+ TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
+
+ if (rva)
+ {
+ if (exp.X_op == O_symbol)
+ exp.X_op = O_symbol_rva;
+ else
+ as_fatal (_("rva without symbol"));
+ }
emit_expr (&exp, (unsigned int) nbytes);
+ ++c;
}
while (*input_line_pointer++ == ',');
+ /* 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 && nbytes == 1 && (c & 1) != 0)
+ mri_pending_align = 1;
+
input_line_pointer--; /* Put terminator back into stream. */
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
demand_empty_rest_of_line ();
}
+
+void
+cons (size)
+ int size;
+{
+ cons_worker (size, 0);
+}
+
+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. */
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"));
+ abs_section_offset += nbytes;
+ return;
+ }
+
/* Handle a negative bignum. */
if (op == O_uminus
&& exp->X_add_number == 0
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; zero assumed"));
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;
}
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 */
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. */
get = exp->X_add_number;
use = get & unmask;
- if ((get & mask) != 0 && (get & mask) != mask)
+ 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.", get, use);
+ as_warn (_("Value 0x%lx truncated to 0x%lx."),
+ (unsigned long) get, (unsigned long) use);
}
/* 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);
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;
}
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
- fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
- /* @@ Should look at CPU word size. */
- nbytes == 2 ? BFD_RELOC_16
- : nbytes == 8 ? BFD_RELOC_64
- : BFD_RELOC_32);
+ {
+ bfd_reloc_code_real_type r;
+
+ switch (nbytes)
+ {
+ case 1:
+ r = BFD_RELOC_8;
+ break;
+ case 2:
+ r = BFD_RELOC_16;
+ break;
+ case 4:
+ r = BFD_RELOC_32;
+ break;
+ case 8:
+ r = BFD_RELOC_64;
+ break;
+ default:
+ as_bad (_("unsupported BFD relocation size %u"), nbytes);
+ r = BFD_RELOC_32;
+ break;
+ }
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
+ 0, r);
+ }
#endif
#else
#ifdef TC_CONS_FIX_NEW
widths, positions, and masks which most
of our current object formats don't
support.
-
+
In the specific case where a symbol
*is* defined in this assembly, we
*could* build fixups and track it, but
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 */
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;
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 */
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;
#endif /* BITFIELD_CONS_EXPRESSIONS */
\f
-#ifdef MRI
+/* Handle an MRI style string expression. */
static void
parse_mri_cons (exp, nbytes)
expressionS *exp;
unsigned int nbytes;
{
- if (*input_line_pointer == '\'')
+ if (*input_line_pointer != '\''
+ && (input_line_pointer[1] != '\''
+ || (*input_line_pointer != 'A'
+ && *input_line_pointer != 'E')))
+ TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+ else
{
- /* An MRI style string, cut into as many bytes as will fit into
- a nbyte chunk, left justify if necessary, and separate with
- commas so we can try again later */
- int scan = 0;
+ unsigned int scan;
unsigned int result = 0;
+
+ /* An MRI style string. Cut into as many bytes as will fit into
+ a nbyte chunk, left justify if necessary, and separate with
+ commas so we can try again later. */
+ if (*input_line_pointer == 'A')
+ ++input_line_pointer;
+ else if (*input_line_pointer == 'E')
+ {
+ as_bad (_("EBCDIC constants are not supported"));
+ ++input_line_pointer;
+ }
+
input_line_pointer++;
for (scan = 0; scan < nbytes; scan++)
{
else
input_line_pointer++;
}
- else
- expression (&exp);
}
-
-#endif /* MRI */
\f
#ifdef REPEAT_CONS_EXPRESSIONS
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;
}
#endif /* REPEAT_CONS_EXPRESSIONS */
\f
+/* Parse a floating point number represented as a hex constant. This
+ permits users to specify the exact bits they want in the floating
+ point number. */
+
+static int
+hex_float (float_type, bytes)
+ int float_type;
+ char *bytes;
+{
+ int length;
+ int i;
+
+ switch (float_type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ length = 4;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ length = 8;
+ break;
+
+ case 'x':
+ case 'X':
+ length = 12;
+ break;
+
+ case 'p':
+ case 'P':
+ length = 12;
+ break;
+
+ default:
+ as_bad (_("Unknown floating type type '%c'"), float_type);
+ return -1;
+ }
+
+ /* It would be nice if we could go through expression to parse the
+ hex constant, but if we get a bignum it's a pain to sort it into
+ the buffer correctly. */
+ i = 0;
+ while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
+ {
+ int d;
+
+ /* The MRI assembler accepts arbitrary underscores strewn about
+ through the hex constant, so we ignore them as well. */
+ if (*input_line_pointer == '_')
+ {
+ ++input_line_pointer;
+ continue;
+ }
+
+ if (i >= length)
+ {
+ as_warn (_("Floating point constant too large"));
+ return -1;
+ }
+ d = hex_value (*input_line_pointer) << 4;
+ ++input_line_pointer;
+ while (*input_line_pointer == '_')
+ ++input_line_pointer;
+ if (hex_p (*input_line_pointer))
+ {
+ d += hex_value (*input_line_pointer);
+ ++input_line_pointer;
+ }
+ if (target_big_endian)
+ bytes[i] = d;
+ else
+ bytes[length - i - 1] = d;
+ ++i;
+ }
+
+ if (i < length)
+ {
+ if (target_big_endian)
+ memset (bytes + i, 0, length - i);
+ else
+ memset (bytes, 0, length - i);
+ }
+
+ return length;
+}
+
/*
* float_cons()
*
return;
}
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
do
{
/* input_line_pointer->1st char of a flonum (we hope!). */
* 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]))
+ if (input_line_pointer[0] == '0'
+ && isalpha ((unsigned char) input_line_pointer[1]))
input_line_pointer += 2;
- err = md_atof (float_type, temp, &length);
- know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (length > 0);
- if (err)
+ /* Accept :xxxx, where the x's are hex digits, for a floating
+ point with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
{
- as_bad ("Bad floating literal: %s", err);
- ignore_rest_of_line ();
- return;
+ ++input_line_pointer;
+ length = hex_float (float_type, temp);
+ if (length < 0)
+ {
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ {
+ err = md_atof (float_type, temp, &length);
+ know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (length > 0);
+ if (err)
+ {
+ as_bad (_("Bad floating literal: %s"), err);
+ ignore_rest_of_line ();
+ return;
+ }
}
if (!need_pass_2)
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;
demand_empty_rest_of_line ();
} /* float_cons() */
\f
+/* 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;
+}
+
+inline 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 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 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 inline 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;
+
+ 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; zero assumed"));
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_register)
+ {
+ as_warn (_("register value used as expression"));
+ op = O_constant;
+ }
+
+ 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 ();
+}
+\f
/*
* stringer()
*
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,
{
case '\"':
++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);
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++;
FRAG_APPEND_1_CHAR (c);
if (*input_line_pointer != '>')
{
- as_bad ("Expected <nn>");
+ as_bad (_("Expected <nn>"));
}
input_line_pointer++;
break;
c = NOT_A_CHAR;
break;
+ case '\n':
+ as_warn (_("Unterminated string: Newline inserted."));
+ bump_line_counters ();
+ break;
+
#ifndef NO_STRING_ESCAPES
case '\\':
switch (c = *input_line_pointer++)
c = '\t';
break;
-#ifdef BACKSLASH_V
case 'v':
c = '\013';
break;
-#endif
case '\\':
case '"':
case '\n':
/* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
- as_warn ("Unterminated string: Newline inserted.");
+ as_warn (_("Unterminated string: Newline inserted."));
c = '\n';
+ bump_line_counters ();
break;
default:
#ifdef ONLY_STANDARD_ESCAPES
- as_bad ("Bad escaped character in string, '?' assumed");
+ as_bad (_("Bad escaped character in string, '?' assumed"));
c = '?';
#endif /* ONLY_STANDARD_ESCAPES */
|| expP->X_op == O_absent
|| expP->X_op == O_big)
{
- as_bad ("expected address expression; zero assumed");
+ as_bad (_("expected address expression; zero assumed"));
expP->X_op = O_constant;
expP->X_add_number = 0;
retval = absolute_section;
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;
if (exp.X_op != O_constant)
{
if (exp.X_op != O_absent)
- as_bad ("bad absolute expression; zero assumed");
+ as_bad (_("bad or irreducible absolute expression; zero assumed"));
exp.X_add_number = 0;
}
return exp.X_add_number;
{
register int len;
- for (len = *len_pointer;
- len > 0;
- len--)
+ for (len = *len_pointer; len > 0; len--)
{
if (*s == 0)
{
s = 0;
len = 1;
*len_pointer = 0;
- as_bad ("This string may not contain \'\\0\'");
+ as_bad (_("This string may not contain \'\\0\'"));
}
}
}
- return (s);
+ return s;
}
\f
/*
obstack_1grow (¬es, c);
len++;
}
- /* JF this next line is so demand_copy_C_string will return a null
- termanated string. */
+ /* JF this next line is so demand_copy_C_string will return a
+ 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 ();
}
} /* is_it_end_of_statement() */
void
-equals (sym_name)
+equals (sym_name, reassign)
char *sym_name;
+ int reassign;
{
register symbolS *symbolP; /* symbol we are working with */
+ char *stop = NULL;
+ char stopc;
input_line_pointer++;
if (*input_line_pointer == '=')
while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
input_line_pointer++;
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
if (sym_name[0] == '.' && sym_name[1] == '\0')
{
/* Turn '. = mumble' into a .org mumble */
register segT segment;
expressionS exp;
- register char *p;
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
- {
- if (segment != now_seg && segment != absolute_section)
- as_warn ("Illegal segment \"%s\". Segment \"%s\" assumed.",
- segment_name (segment),
- segment_name (now_seg));
- p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
- exp.X_add_number, (char *) 0);
- *p = 0;
- } /* if (ok to make frag) */
+ do_org (segment, &exp, 0);
}
else
{
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' already defined"), S_GET_NAME (symbolP));
pseudo_set (symbolP);
}
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
} /* equals() */
/* .include -- include a file at this point. */
FILE *try;
char *path;
- 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]
+ && *input_line_pointer != ' '
+ && *input_line_pointer != '\t')
+ {
+ obstack_1grow (¬es, *input_line_pointer);
+ ++input_line_pointer;
+ ++i;
+ }
+ obstack_1grow (¬es, '\0');
+ filename = obstack_finish (¬es);
+ 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, FOPEN_RT)))
+ if (0 != (try = fopen (path, "r")))
{
fclose (try);
goto gotit;
path = filename;
gotit:
/* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
+ register_dependency (path);
newbuf = input_scrub_include_file (path, input_line_pointer);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
} /* s_include() */
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. */
+
+static void
+generate_lineno_debug ()
+{
+ if (debug_type == DEBUG_STABS)
+ stabs_generate_asm_lineno ();
+
+#ifdef OBJ_GENERATE_ASM_LINENO
+#ifdef ECOFF_DEBUGGING
+ /* ECOFF assemblers automatically generate
+ debugging information. FIXME: This should
+ probably be handled elsewhere. */
+ if (debug_type == DEBUG_NONE)
+ {
+ if (ecoff_no_current_file ())
+ debug_type = DEBUG_ECOFF;
+ }
+
+ if (debug_type == DEBUG_ECOFF)
+ {
+ unsigned int lineno;
+ char *s;
+
+ as_where (&s, &lineno);
+ OBJ_GENERATE_ASM_LINENO (s, lineno);
+ }
+#endif
+#endif
+}
+
void
s_ignore (arg)
int arg;
}
+void
+read_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "pseudo-op table", po_hash);
+}
+
/* end of read.c */