* m10300-opc.c, m10300-dis.c: Add am33 support.
[deliverable/binutils-gdb.git] / gas / read.c
index e1f1a077a0c0f846712f0674035446df65bf9666..b64203b5959a037fa919640e15799ba61ad07ead 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
 /* 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, 98, 1999
    Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
    Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
@@ -15,8 +15,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GAS; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+along with GAS; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
 
 #if 0
 #define MASK_CHAR (0xFF)       /* If your chars aren't 8 bits, you will
 
 #if 0
 #define MASK_CHAR (0xFF)       /* If your chars aren't 8 bits, you will
@@ -42,9 +43,11 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 
 #include "as.h"
 #include "subsegs.h"
 
 #include "as.h"
 #include "subsegs.h"
-#include "libiberty.h"
+#include "sb.h"
+#include "macro.h"
 #include "obstack.h"
 #include "listing.h"
 #include "obstack.h"
 #include "listing.h"
+#include "ecoff.h"
 
 #ifndef TC_START_LABEL
 #define TC_START_LABEL(x,y) (x==':')
 
 #ifndef TC_START_LABEL
 #define TC_START_LABEL(x,y) (x==':')
@@ -60,8 +63,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 
 char *input_line_pointer;      /*->next char of source file to parse. */
 
 
 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!)!  */
 #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!)!  */
@@ -83,24 +84,44 @@ die horribly;
 #define LEX_PCT 0
 #endif
 
 #define LEX_PCT 0
 #endif
 
+#ifndef LEX_QM
+/* The PowerPC Windows NT assemblers permits ? inside label names.  */
+#define LEX_QM 0
+#endif
+
+#ifndef LEX_HASH
+#define LEX_HASH 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[] */
 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[\]^_ */
 /* used by is_... macros. our ctype[] */
 char lex_type[256] =
 {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* @ABCDEFGHIJKLMNO */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* PQRSTUVWXYZ[\]^_ */
-  0, 0, 0, 0, 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, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */
   LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,      /* `abcdefghijklmno */
   LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,      /* `abcdefghijklmno */
-  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 0, /* pqrstuvwxyz{|}~. */
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
 };
 
 
 };
 
 
@@ -108,61 +129,53 @@ char lex_type[256] =
  * In: a character.
  * Out: 1 if this character ends a line.
  */
  * 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
 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
 #else
-  _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _,     /* @abcdefghijklmno */
+  99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, Z_,      /* @abcdefghijklmno */
 #endif
 #endif
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,      /* */
+  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,      /* */
 #ifdef TC_HPPA
 #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
 #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. */
 
 
 /* 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. */
 
-#ifdef TARGET_BYTES_BIG_ENDIAN
-/* Hack to deal with tc-*.h defining TARGET_BYTES_BIG_ENDIAN to empty
-   instead of to 0 or 1.  */
-#if 5 - TARGET_BYTES_BIG_ENDIAN - 5 == 10
-#undef  TARGET_BYTES_BIG_ENDIAN
-#define TARGET_BYTES_BIG_ENDIAN 1
-#endif
+/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
+   tc-<CPU>.h file.  See the "Porting GAS" section of the internals manual. */
 int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
 int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
-#else
-int target_big_endian /* = 0 */;
-#endif
 
 static char *old_buffer;       /* JF a hack */
 static char *old_input;
 static char *old_limit;
 
 
 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 */
                           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;
 
 #ifndef WORKING_DOT_WORD
 struct broken_word *broken_words;
@@ -176,7 +189,7 @@ 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.  */
 
 /* 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 *mri_line_label;
+symbolS *line_label;
 
 /* This global variable is used to support MRI common sections.  We
    translate such sections into a common symbol.  This variable is
 
 /* This global variable is used to support MRI common sections.  We
    translate such sections into a common symbol.  This variable is
@@ -189,14 +202,35 @@ symbolS *mri_common_symbol;
    may be needed.  */
 static int mri_pending_align;
 
    may be needed.  */
 static int mri_pending_align;
 
-static void do_align PARAMS ((int, char *));
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+/* This variable is set to be non-zero if the next string we see might
+   be the name of the source file in DWARF debugging information.  See
+   the comment in emit_expr for the format we look for.  */
+static int dwarf_file_string;
+#endif
+#endif
+
+static void cons_worker PARAMS ((int, int));
+static int scrub_from_string PARAMS ((char *, int));
+static void do_align PARAMS ((int, char *, int, int));
+static void s_align PARAMS ((int, int));
+static void s_lcomm_internal PARAMS ((int, int));
 static int hex_float PARAMS ((int, char *));
 static int hex_float PARAMS ((int, char *));
+static inline int sizeof_sleb128 PARAMS ((offsetT));
+static inline int sizeof_uleb128 PARAMS ((valueT));
+static inline int output_sleb128 PARAMS ((char *, offsetT));
+static inline int output_uleb128 PARAMS ((char *, valueT));
+static inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
+static inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
+static int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int));
 static void do_org PARAMS ((segT, expressionS *, int));
 char *demand_copy_string PARAMS ((int *lenP));
 static 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 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));
 \f
 
 void
 \f
 
 void
@@ -209,8 +243,8 @@ read_begin ()
 
   /* Something close -- but not too close -- to a multiple of 1024.
      The debugging malloc I'm using has 24 bytes of overhead.  */
 
   /* Something close -- but not too close -- to a multiple of 1024.
      The debugging malloc I'm using has 24 bytes of overhead.  */
-  obstack_begin (&notes, 5090);
-  obstack_begin (&cond_obstack, 990);
+  obstack_begin (&notes, chunksize);
+  obstack_begin (&cond_obstack, chunksize);
 
   /* Use machine dependent syntax */
   for (p = line_separator_chars; *p; p++)
 
   /* Use machine dependent syntax */
   for (p = line_separator_chars; *p; p++)
@@ -232,6 +266,8 @@ static const pseudo_typeS potable[] =
   {"ascii", stringer, 0},
   {"asciz", stringer, 1},
   {"balign", s_align_bytes, 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},
 /* block */
   {"byte", cons, 1},
   {"comm", s_comm, 0},
@@ -260,6 +296,7 @@ static const pseudo_typeS potable[] =
   {"ds.s", s_space, 4},
   {"ds.w", s_space, 2},
   {"ds.x", 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
 #ifdef S_SET_DESC
   {"desc", s_desc, 0},
 #endif
@@ -271,10 +308,13 @@ static const pseudo_typeS potable[] =
   {"elsec", s_else, 0},
   {"end", s_end, 0},
   {"endc", s_endif, 0},
   {"elsec", s_else, 0},
   {"end", s_end, 0},
   {"endc", s_endif, 0},
+  {"endfunc", s_func, 1},
   {"endif", s_endif, 0},
 /* endef */
   {"equ", s_set, 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},
 /* extend */
   {"extern", s_ignore, 0},     /* We treat all undef as ext */
   {"appfile", s_app_file, 1},
@@ -284,10 +324,12 @@ static const pseudo_typeS potable[] =
   {"fill", s_fill, 0},
   {"float", float_cons, 'f'},
   {"format", s_ignore, 0},
   {"fill", s_fill, 0},
   {"float", float_cons, 'f'},
   {"format", s_ignore, 0},
+  {"func", s_func, 0},
   {"global", s_globl, 0},
   {"globl", s_globl, 0},
   {"hword", cons, 2},
   {"if", s_if, (int) O_ne},
   {"global", s_globl, 0},
   {"globl", s_globl, 0},
   {"hword", cons, 2},
   {"if", s_if, (int) O_ne},
+  {"ifc", s_ifc, 0},
   {"ifdef", s_ifdef, 0},
   {"ifeq", s_if, (int) O_eq},
   {"ifeqs", s_ifeqs, 0},
   {"ifdef", s_ifdef, 0},
   {"ifeq", s_if, (int) O_eq},
   {"ifeqs", s_ifeqs, 0},
@@ -295,18 +337,29 @@ static const pseudo_typeS potable[] =
   {"ifgt", s_if, (int) O_gt},
   {"ifle", s_if, (int) O_le},
   {"iflt", s_if, (int) O_lt},
   {"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},
   {"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 */
   {"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},
   {"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},
   {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off */
   {"nopage", listing_nopage, 0},
@@ -314,11 +367,17 @@ static const pseudo_typeS potable[] =
   {"offset", s_struct, 0},
   {"org", s_org, 0},
   {"p2align", s_align_ptwo, 0},
   {"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},
   {"page", listing_eject, 0},
   {"plen", listing_psize, 0},
+  {"print", s_print, 0},
   {"psize", listing_psize, 0}, /* set paper size */
   {"psize", listing_psize, 0}, /* set paper size */
-/* print */
+  {"purgem", s_purgem, 0},
   {"quad", cons, 8},
   {"quad", cons, 8},
+  {"rep", s_rept, 0},
+  {"rept", s_rept, 0},
+  {"rva", s_rva, 4},
   {"sbttl", listing_title, 1}, /* Subtitle of listing */
 /* scl */
 /* sect */
   {"sbttl", listing_title, 1}, /* Subtitle of listing */
 /* scl */
 /* sect */
@@ -327,6 +386,9 @@ static const pseudo_typeS potable[] =
   {"single", float_cons, 'f'},
 /* size */
   {"space", s_space, 0},
   {"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'},
   {"stabd", s_stab, 'd'},
   {"stabn", s_stab, 'n'},
   {"stabs", s_stab, 's'},
@@ -346,14 +408,18 @@ static const pseudo_typeS potable[] =
   {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
 
   {"title", listing_title, 0}, /* Listing title */
   {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
 
   {"title", listing_title, 0}, /* Listing title */
+  {"ttl", listing_title, 0},
 /* type */
 /* type */
+  {"uleb128", s_leb128, 0},
 /* use */
 /* val */
 /* use */
 /* val */
+  {"xcom", s_comm, 0},
   {"xdef", s_globl, 0},
   {"xdef", s_globl, 0},
+  {"xref", s_ignore, 0},
   {"xstabs", s_xstab, 's'},
   {"word", cons, 2},
   {"zero", s_space, 0},
   {"xstabs", s_xstab, 's'},
   {"word", cons, 2},
   {"zero", s_space, 0},
-  {NULL                      /* end sentinel */
+  {NULL, NULL, 0}                      /* end sentinel */
 };
 
 static int pop_override_ok = 0;
 };
 
 static int pop_override_ok = 0;
@@ -369,7 +435,8 @@ pop_insert (table)
     {
       errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
       if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
     {
       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", pop_table_name);
+       as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
+                 errtxt);
     }
 }
 
     }
 }
 
@@ -410,6 +477,27 @@ pobegin ()
     }
 
 
     }
 
 
+/* 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 (buf, buflen)
+     char *buf;
+     int buflen;
+{
+  int copy;
+
+  copy = scrub_string_end - scrub_string;
+  if (copy > buflen)
+    copy = buflen;
+  memcpy (buf, scrub_string, copy);
+  scrub_string += copy;
+  return copy;
+}
+
 /*     read_a_source_file()
  *
  * We read the file, putting things into a web that
 /*     read_a_source_file()
  *
  * We read the file, putting things into a web that
@@ -427,7 +515,13 @@ read_a_source_file (name)
   buffer = input_scrub_new_file (name);
 
   listing_file (name);
   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. */
 
   while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
     {                          /* We have another line to parse. */
@@ -453,43 +547,65 @@ read_a_source_file (name)
              if (input_line_pointer[-1] == '\n')
                bump_line_counters ();
 
              if (input_line_pointer[-1] == '\n')
                bump_line_counters ();
 
-             if (flag_mri
+             line_label = NULL;
+
+             if (flag_m68k_mri
 #ifdef LABELS_WITHOUT_COLONS
                  || 1
 #endif
                  )
                {
 #ifdef LABELS_WITHOUT_COLONS
                  || 1
 #endif
                  )
                {
-                 mri_line_label = NULL;
-
                  /* 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;
                  /* Text at the start of a line must be a label, we
                     run down and stick a colon in.  */
                  if (is_name_beginner (*input_line_pointer))
                    {
                      char *line_start = input_line_pointer;
-                     char c = get_symbol_end ();
+                     char c;
+                     int mri_line_macro;
+
+                     LISTING_NEWLINE ();
+                     HANDLE_CONDITIONAL_ASSEMBLY ();
 
 
-                     if (! ignore_input ())
+                     c = get_symbol_end ();
+
+                     /* In MRI mode, the EQU and MACRO pseudoops must
+                        be handled specially.  */
+                     mri_line_macro = 0;
+                     if (flag_m68k_mri)
                        {
                        {
-                         /* In MRI mode, the EQU pseudoop must be
-                            handled specially.  */
-                         if (flag_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'))
                            {
                            {
-                             if (((strncasecmp (input_line_pointer + 1,
-                                                "EQU", 3) == 0)
-                                  || (strncasecmp (input_line_pointer + 1,
-                                                   "SET", 3) == 0))
-                                 && (input_line_pointer[4] == ' '
-                                     || input_line_pointer[4] == '\t'))
-                               {
-                                 input_line_pointer += 4;
-                                 equals (line_start);
-                                 continue;
-                               }
+                             input_line_pointer = rest + 3;
+                             equals (line_start,
+                                     strncasecmp (rest, "SET", 3) == 0);
+                             continue;
                            }
                            }
-
-                         mri_line_label = colon (line_start);
+                         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++;
                      *input_line_pointer = c;
                      if (c == ':')
                        input_line_pointer++;
@@ -519,7 +635,39 @@ read_a_source_file (name)
              c = *input_line_pointer++;
            }
          know (c != ' ');      /* No further leading whitespace. */
              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.
          /*
           * C is the 1st significant character.
           * Input_line_pointer points after that character.
@@ -540,7 +688,27 @@ read_a_source_file (name)
               */
              if (TC_START_LABEL(c, input_line_pointer))
                {
               */
              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 ();
                  *input_line_pointer++ = ':';  /* Put ':' back for error messages' sake. */
                  /* Input_line_pointer->after ':'. */
                  SKIP_WHITESPACE ();
@@ -548,13 +716,14 @@ read_a_source_file (name)
 
                }
              else if (c == '='
 
                }
              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
                           ))
                {
 #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
                  demand_empty_rest_of_line ();
                }
              else
@@ -567,14 +736,14 @@ read_a_source_file (name)
                    char *s2 = s;
                    while (*s2)
                      {
                    char *s2 = s;
                    while (*s2)
                      {
-                       if (isupper (*s2))
+                       if (isupper ((unsigned char) *s2))
                          *s2 = tolower (*s2);
                        s2++;
                      }
                  }
 #endif
 
                          *s2 = tolower (*s2);
                        s2++;
                      }
                  }
 #endif
 
-                 if (flag_mri
+                 if (flag_m68k_mri
 #ifdef NO_PSEUDO_DOT
                      || 1
 #endif
 #ifdef NO_PSEUDO_DOT
                      || 1
 #endif
@@ -587,7 +756,8 @@ read_a_source_file (name)
                        pop = NULL;
                    }
 
                        pop = NULL;
                    }
 
-                 if (pop != NULL || *s == '.')
+                 if (pop != NULL
+                     || (! flag_m68k_mri && *s == '.'))
                    {
                      /*
                       * PSEUDO - OP.
                    {
                      /*
                       * PSEUDO - OP.
@@ -608,16 +778,32 @@ read_a_source_file (name)
                              || ! ((pop->poc_handler == cons
                                     && pop->poc_val == 1)
                                    || (pop->poc_handler == s_space
                              || ! ((pop->poc_handler == cons
                                     && pop->poc_val == 1)
                                    || (pop->poc_handler == s_space
-                                       && pop->poc_val == 1))))
+                                       && 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);
+                         do_align (1, (char *) NULL, 0, 0);
                          mri_pending_align = 0;
                          mri_pending_align = 0;
+                         if (line_label != NULL)
+                           {
+                             symbol_set_frag (line_label, frag_now);
+                             S_SET_VALUE (line_label, frag_now_fix ());
+                           }
                        }
 
                      /* Print the error msg now, while we still can */
                      if (pop == NULL)
                        {
                        }
 
                      /* 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;
                          *input_line_pointer = c;
                          s_ignore (0);
                          continue;
@@ -642,43 +828,69 @@ read_a_source_file (name)
                        goto quit;
                    }
                  else
                        goto quit;
                    }
                  else
-                   {           /* machine instruction */
-                     if (mri_pending_align)
-                       {
-                         do_align (1, (char *) NULL);
-                         mri_pending_align = 0;
-                       }
+                   {
+                     int inquote = 0;
+#ifdef QUOTES_IN_INSN
+                     int inescape = 0;
+#endif
 
                      /* WARNING: c has char, which may be end-of-line. */
                      /* Also: input_line_pointer->`\0` where c was. */
                      *input_line_pointer = c;
                      while (!is_end_of_line[(unsigned char) *input_line_pointer]
 
                      /* 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
                             )
                        {
 #ifdef TC_EOL_IN_INSN
                             || TC_EOL_IN_INSN (input_line_pointer)
 #endif
                             )
                        {
+                         if (flag_m68k_mri && *input_line_pointer == '\'')
+                           inquote = ! inquote;
+#ifdef QUOTES_IN_INSN
+                         if (inescape)
+                           inescape = 0;
+                         else if (*input_line_pointer == '"')
+                           inquote = ! inquote;
+                         else if (*input_line_pointer == '\\')
+                           inescape = 1;
+#endif
                          input_line_pointer++;
                        }
 
                      c = *input_line_pointer;
                      *input_line_pointer = '\0';
 
                          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;
+                           }
                        }
                        }
-                     if (generate_asm_lineno == 1)
-                       {
-                         unsigned int lineno;
-                         char *s;
 
 
-                         as_where (&s, &lineno);
-                         OBJ_GENERATE_ASM_LINENO (s, lineno);
-                       }
-#endif
+                     if (mri_pending_align)
+                       {
+                         do_align (1, (char *) NULL, 0, 0);
+                         mri_pending_align = 0;
+                         if (line_label != NULL)
+                           {
+                             symbol_set_frag (line_label, frag_now);
+                             S_SET_VALUE (line_label, frag_now_fix ());
+                           }
+                       }
 
                      md_assemble (s);  /* Assemble 1 instruction. */
 
 
                      md_assemble (s);  /* Assemble 1 instruction. */
 
@@ -697,7 +909,7 @@ read_a_source_file (name)
            continue;
 
          if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
            continue;
 
          if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
-             && isdigit (c))
+             && isdigit ((unsigned char) c))
            {
              /* local label  ("4:") */
              char *backup = input_line_pointer;
            {
              /* local label  ("4:") */
              char *backup = input_line_pointer;
@@ -706,7 +918,7 @@ read_a_source_file (name)
 
              temp = c - '0';
 
 
              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;
                {
                  temp = (temp * 10) + *input_line_pointer - '0';
                  ++input_line_pointer;
@@ -720,7 +932,7 @@ read_a_source_file (name)
 
                  if (dollar_label_defined (temp))
                    {
 
                  if (dollar_label_defined (temp))
                    {
-                     as_fatal ("label \"%d$\" redefined", temp);
+                     as_fatal (_("label \"%d$\" redefined"), temp);
                    }
 
                  define_dollar_label (temp);
                    }
 
                  define_dollar_label (temp);
@@ -746,7 +958,6 @@ read_a_source_file (name)
              char *new_tmp;
              unsigned int new_length;
              char *tmp_buf = 0;
              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;
 
              bump_line_counters ();
              s = input_line_pointer;
@@ -798,26 +1009,30 @@ read_a_source_file (name)
                {
                  input_line_pointer = ends + 8;
                }
                {
                  input_line_pointer = ends + 8;
                }
-             new_buf = xmalloc (100);
-             new_length = 100;
-             new_tmp = new_buf;
 
              scrub_string = s;
 
              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 (;;)
                {
              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)
                }
 
              if (tmp_buf)
@@ -833,6 +1048,11 @@ read_a_source_file (name)
 
          HANDLE_CONDITIONAL_ASSEMBLY ();
 
 
          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 ();
          /* as_warn("Junk character %d.",c);  Now done by ignore_rest */
          input_line_pointer--; /* Report unknown char as ignored. */
          ignore_rest_of_line ();
@@ -844,6 +1064,7 @@ read_a_source_file (name)
 
       if (old_buffer)
        {
 
       if (old_buffer)
        {
+         free (buffer);
          bump_line_counters ();
          if (old_input != 0)
            {
          bump_line_counters ();
          if (old_input != 0)
            {
@@ -857,43 +1078,117 @@ read_a_source_file (name)
     }                          /* while (more buffers to scan) */
 
  quit:
     }                          /* while (more buffers to scan) */
 
  quit:
+
+#ifdef md_cleanup
+  md_cleanup();
+#endif
   input_scrub_close ();                /* Close the input file */
 }
 
   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)
 void 
 s_abort (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 {
-  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 
 static void 
-do_align (n, fill)
+do_align (n, fill, len, max)
      int n;
      char *fill;
      int n;
      char *fill;
+     int len;
+     int max;
 {
 {
+  char default_fill;
+
 #ifdef md_do_align
 #ifdef md_do_align
-  md_do_align (n, fill, just_record_alignment);
+  md_do_align (n, fill, len, max, just_record_alignment);
 #endif
 #endif
-  if (!fill)
-    {
-      /* @@ Fix this right for BFD!  */
-      static char zero;
-      static char nop_opcode = NOP_OPCODE;
 
 
-      if (now_seg != data_section && now_seg != bss_section)
-       {
-         fill = &nop_opcode;
-       }
+  if (fill == NULL)
+    {
+      if (subseg_text_p (now_seg))
+       default_fill = NOP_OPCODE;
       else
       else
-       {
-         fill = &zero;
-       }
+       default_fill = 0;
+      fill = &default_fill;
+      len = 1;
     }
     }
+
   /* Only make a frag if we HAVE to. . . */
   /* 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:
 
 #ifdef md_do_align
  just_record_alignment:
@@ -902,87 +1197,158 @@ do_align (n, fill)
   record_alignment (now_seg, n);
 }
 
   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 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])
 
   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
   else
-    temp = get_absolute_expression ();
+    {
+      align = get_absolute_expression ();
+      SKIP_WHITESPACE ();
+    }
+
+  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 (temp > max_alignment)
+  if (align > 15)
     {
     {
-      as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
+      align = 15;
+      as_bad (_("Alignment too large: %u assumed"), align);
     }
 
     }
 
-  /* For the sparc, `.align (1<<n)' actually means `.align n' so we
-     have to convert it.  */
-  if (temp != 0)
+  if (*input_line_pointer != ',')
     {
     {
-      for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
-       ;
+      fill_p = 0;
+      max = 0;
     }
     }
-  if (temp != 1)
-    as_bad ("Alignment not a power of 2");
+  else
+    {
+      ++input_line_pointer;
+      if (*input_line_pointer == ',')
+       fill_p = 0;
+      else
+       {
+         fill = get_absolute_expression ();
+         SKIP_WHITESPACE ();
+         fill_p = 1;
+       }
 
 
-  temp = i;
-  if (*input_line_pointer == ',')
+      if (*input_line_pointer != ',')
+       max = 0;
+      else
+       {
+         ++input_line_pointer;
+         max = get_absolute_expression ();
+       }
+    }
+
+  if (! fill_p)
     {
     {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-      do_align (temp, &temp_fill);
+      if (arg < 0)
+       as_warn (_("expected fill pattern missing"));
+      do_align (align, (char *) NULL, 0, max);
     }
   else
     }
   else
-    do_align (temp, (char *) 0);
+    {
+      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);
+       }
+    }
 
   demand_empty_rest_of_line ();
 
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 }
 
-/* For machines where ".align 4" means align to 2**4 boundary. */
+/* Handle the .align pseudo-op on machines where ".align 4" means
+   align to a 4 byte boundary.  */
+
 void 
 void 
-s_align_ptwo (ignore)
-     int ignore;
+s_align_bytes (arg)
+     int arg;
 {
 {
-  register int temp;
-  char temp_fill;
-  long max_alignment = 15;
+  s_align (arg, 1);
+}
 
 
-  temp = get_absolute_expression ();
-  if (temp > max_alignment)
-    as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
-  else if (temp < 0)
-    {
-      as_bad ("Alignment negative. 0 assumed.");
-      temp = 0;
-    }
-  if (*input_line_pointer == ',')
-    {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-      do_align (temp, &temp_fill);
-    }
-  else
-    do_align (temp, (char *) 0);
+/* Handle the .align pseudo-op on machines where ".align 4" means align
+   to a 2**4 boundary.  */
 
 
-  demand_empty_rest_of_line ();
+void 
+s_align_ptwo (arg)
+     int arg;
+{
+  s_align (arg, 0);
 }
 
 void 
 s_comm (ignore)
 }
 
 void 
 s_comm (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register char *name;
   register char c;
   register char *p;
   offsetT temp;
   register symbolS *symbolP;
 {
   register char *name;
   register char c;
   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 ();
 
   name = input_line_pointer;
   c = get_symbol_end ();
@@ -992,31 +1358,37 @@ s_comm (ignore)
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
   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."));
       ignore_rest_of_line ();
       ignore_rest_of_line ();
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       return;
     }
   input_line_pointer++;                /* skip ',' */
   if ((temp = get_absolute_expression ()) < 0)
     {
       return;
     }
   input_line_pointer++;                /* skip ',' */
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
+      as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
       ignore_rest_of_line ();
       ignore_rest_of_line ();
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       return;
     }
   *p = 0;
   symbolP = symbol_find_or_make (name);
   *p = c;
       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));
       ignore_rest_of_line ();
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       return;
     }
   if (S_GET_VALUE (symbolP))
     {
       if (S_GET_VALUE (symbolP) != (valueT) temp)
       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);
                S_GET_NAME (symbolP),
                (long) S_GET_VALUE (symbolP),
                (long) temp);
@@ -1034,7 +1406,11 @@ s_comm (ignore)
   }
 #endif /* not OBJ_VMS */
   know (symbolP->sy_frag == &zero_address_frag);
   }
 #endif /* not OBJ_VMS */
   know (symbolP->sy_frag == &zero_address_frag);
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }                              /* s_comm() */
 
 /* The MRI COMMON pseudo-op.  We handle this by creating a common
 }                              /* s_comm() */
 
 /* The MRI COMMON pseudo-op.  We handle this by creating a common
@@ -1043,13 +1419,15 @@ s_comm (ignore)
 
 void
 s_mri_common (small)
 
 void
 s_mri_common (small)
-     int small;
+     int small ATTRIBUTE_UNUSED;
 {
   char *name;
   char c;
   char *alc = NULL;
   symbolS *sym;
   offsetT align;
 {
   char *name;
   char c;
   char *alc = NULL;
   symbolS *sym;
   offsetT align;
+  char *stop = NULL;
+  char stopc;
 
   if (! flag_mri)
     {
 
   if (! flag_mri)
     {
@@ -1057,6 +1435,8 @@ s_mri_common (small)
       return;
     }
 
       return;
     }
 
+  stop = mri_comment_field (&stopc);
+
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
@@ -1072,12 +1452,12 @@ s_mri_common (small)
       c = *input_line_pointer;
       *input_line_pointer = '\0';
 
       c = *input_line_pointer;
       *input_line_pointer = '\0';
 
-      if (mri_line_label != NULL)
+      if (line_label != NULL)
        {
        {
-         alc = (char *) xmalloc (strlen (S_GET_NAME (mri_line_label))
+         alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
                                  + (input_line_pointer - name)
                                  + 1);
                                  + (input_line_pointer - name)
                                  + 1);
-         sprintf (alc, "%s%s", name, S_GET_NAME (mri_line_label));
+         sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
          name = alc;
        }
     }
          name = alc;
        }
     }
@@ -1095,16 +1475,12 @@ s_mri_common (small)
       align = get_absolute_expression ();
     }
 
       align = get_absolute_expression ();
     }
 
-  if (S_IS_DEFINED (sym))
+  if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
     {
     {
-#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER)
-      if (! S_IS_COMMON (sym))
-#endif
-       {
-         as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
-         ignore_rest_of_line ();
-         return;
-       }
+      as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym));
+      ignore_rest_of_line ();
+      mri_comment_end (stop, stopc);
+      return;
     }
 
   S_SET_EXTERNAL (sym);
     }
 
   S_SET_EXTERNAL (sym);
@@ -1115,13 +1491,15 @@ s_mri_common (small)
     S_SET_ALIGN (sym, align);
 #endif
 
     S_SET_ALIGN (sym, align);
 #endif
 
-  if (mri_line_label != NULL)
+  if (line_label != NULL)
     {
     {
-      mri_line_label->sy_value.X_op = O_symbol;
-      mri_line_label->sy_value.X_add_symbol = sym;
-      mri_line_label->sy_value.X_add_number = S_GET_VALUE (sym);
-      mri_line_label->sy_frag = &zero_address_frag;
-      S_SET_SEGMENT (mri_line_label, expr_section);
+      expressionS exp;
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = sym;
+      exp.X_add_number = 0;
+      symbol_set_value_expression (line_label, &exp);
+      symbol_set_frag (line_label, &zero_address_frag);
+      S_SET_SEGMENT (line_label, expr_section);
     }
 
   /* FIXME: We just ignore the small argument, which distinguishes
     }
 
   /* FIXME: We just ignore the small argument, which distinguishes
@@ -1132,12 +1510,15 @@ s_mri_common (small)
     input_line_pointer += 2;
   if (*input_line_pointer == ',')
     input_line_pointer += 2;
     input_line_pointer += 2;
   if (*input_line_pointer == ',')
     input_line_pointer += 2;
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  mri_comment_end (stop, stopc);
 }
 
 void
 s_data (ignore)
 }
 
 void
 s_data (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   segT section;
   register int temp;
 {
   segT section;
   register int temp;
@@ -1160,11 +1541,11 @@ s_data (ignore)
 }
 
 /* Handle the .appfile pseudo-op.  This is automatically generated by
 }
 
 /* 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)
 
 void 
 s_app_file (appfile)
@@ -1179,26 +1560,39 @@ 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.  */
       /* 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 ();
       demand_empty_rest_of_line ();
+      if (! may_omit)
+       {
 #ifdef LISTING
 #ifdef LISTING
-      if (listing)
-       listing_source_file (s);
+         if (listing)
+           listing_source_file (s);
 #endif
 #endif
-    }
+         register_dependency (s);
 #ifdef obj_app_file
 #ifdef obj_app_file
-  obj_app_file (s);
+         obj_app_file (s);
 #endif
 #endif
+       }
+    }
 }
 
 /* Handle the .appline pseudo-op.  This is automatically generated by
 }
 
 /* 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)
 
 void
 s_app_line (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   int l;
 
 {
   int l;
 
@@ -1207,7 +1601,7 @@ s_app_line (ignore)
   if (l < 0)
     /* Some of the back ends can't deal with non-positive line numbers.
        Besides, it's silly.  */
   if (l < 0)
     /* Some of the back ends can't deal with non-positive line numbers.
        Besides, it's silly.  */
-    as_warn ("Line numbers must be positive; line number %d rejected.", l+1);
+    as_warn (_("Line numbers must be positive; line number %d rejected."), l+1);
   else
     {
       new_logical_line ((char *) NULL, l);
   else
     {
       new_logical_line ((char *) NULL, l);
@@ -1224,87 +1618,144 @@ s_app_line (ignore)
 
 void
 s_end (ignore)
 
 void
 s_end (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (flag_mri)
     {
       /* The MRI assembler permits the start symbol to follow .end,
          but we don't support that.  */
       SKIP_WHITESPACE ();
 {
   if (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])
-       as_warn ("start address not supported");
+      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 ATTRIBUTE_UNUSED;
+{
+  as_bad (_(".err encountered"));
+  demand_empty_rest_of_line ();
+}
+
 /* Handle the MRI fail pseudo-op.  */
 
 void
 s_fail (ignore)
 /* Handle the MRI fail pseudo-op.  */
 
 void
 s_fail (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   offsetT temp;
 {
   offsetT temp;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   temp = get_absolute_expression ();
   if (temp >= 500)
 
   temp = get_absolute_expression ();
   if (temp >= 500)
-    as_warn (".fail %ld encountered", (long) temp);
+    as_warn (_(".fail %ld encountered"), (long) temp);
   else
   else
-    as_bad (".fail %ld encountered", (long) temp);
+    as_bad (_(".fail %ld encountered"), (long) temp);
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 void 
 s_fill (ignore)
 }
 
 void 
 s_fill (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 {
-  long temp_repeat = 0;
-  long temp_size = 1;
-  register long temp_fill = 0;
+  expressionS rep_exp;
+  long size = 1;
+  register long fill = 0;
   char *p;
 
   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++;
   if (*input_line_pointer == ',')
     {
       input_line_pointer++;
-      temp_size = get_absolute_expression ();
+      size = get_absolute_expression ();
       if (*input_line_pointer == ',')
        {
          input_line_pointer++;
       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)
   /* 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)
       /* 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
                           ? 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.
       /* 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.
@@ -1315,20 +1766,27 @@ s_fill (ignore)
 
 void 
 s_globl (ignore)
 
 void 
 s_globl (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   int c;
   symbolS *symbolP;
 {
   char *name;
   int c;
   symbolS *symbolP;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   do
     {
       name = input_line_pointer;
       c = get_symbol_end ();
       symbolP = symbol_find_or_make (name);
 
   do
     {
       name = input_line_pointer;
       c = get_symbol_end ();
       symbolP = symbol_find_or_make (name);
+      S_SET_EXTERNAL (symbolP);
+
       *input_line_pointer = c;
       SKIP_WHITESPACE ();
       *input_line_pointer = c;
       SKIP_WHITESPACE ();
-      S_SET_EXTERNAL (symbolP);
+      c = *input_line_pointer;
       if (c == ',')
        {
          input_line_pointer++;
       if (c == ',')
        {
          input_line_pointer++;
@@ -1338,22 +1796,137 @@ s_globl (ignore)
        }
     }
   while (c == ',');
        }
     }
   while (c == ',');
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 }
 
-void 
-s_lcomm (needs_align)
-     /* 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;
+/* Handle the MRI IRP and IRPC pseudo-ops.  */
+
+void
+s_irp (irpc)
+     int irpc;
 {
 {
-  register char *name;
-  register char c;
-  register char *p;
-  register int temp;
-  register symbolS *symbolP;
-  segT current_seg = now_seg;
-  subsegT current_subseg = now_subseg;
+  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 ATTRIBUTE_UNUSED;
+{
+  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;
+  register char *p;
+  register int temp;
+  register symbolS *symbolP;
+  segT current_seg = now_seg;
+  subsegT current_subseg = now_subseg;
   const int max_alignment = 15;
   int align = 0;
   segT bss_seg = bss_section;
   const int max_alignment = 15;
   int align = 0;
   segT bss_seg = bss_section;
@@ -1374,13 +1947,13 @@ s_lcomm (needs_align)
 
   if (*input_line_pointer == '\n')
     {
 
   if (*input_line_pointer == '\n')
     {
-      as_bad ("Missing size expression");
+      as_bad (_("Missing size expression"));
       return;
     }
 
   if ((temp = get_absolute_expression ()) < 0)
     {
       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;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -1394,6 +1967,11 @@ s_lcomm (needs_align)
        {
          bss_seg = subseg_new (".sbss", 1);
          seg_info (bss_seg)->bss = 1;
        {
          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
        }
     }
 #endif
@@ -1409,6 +1987,11 @@ s_lcomm (needs_align)
        else
         align = 0;
 
        else
         align = 0;
 
+#ifdef OBJ_EVAX
+       /* FIXME: This needs to be done in a more general fashion.  */
+       align = 3;
+#endif
+
        record_alignment(bss_seg, align);
      }
 
        record_alignment(bss_seg, align);
      }
 
@@ -1418,7 +2001,7 @@ s_lcomm (needs_align)
       SKIP_WHITESPACE ();
       if (*input_line_pointer != ',')
        {
       SKIP_WHITESPACE ();
       if (*input_line_pointer != ',')
        {
-         as_bad ("Expected comma after size");
+         as_bad (_("Expected comma after size"));
          ignore_rest_of_line ();
          return;
        }
          ignore_rest_of_line ();
          return;
        }
@@ -1426,26 +2009,40 @@ s_lcomm (needs_align)
       SKIP_WHITESPACE ();
       if (*input_line_pointer == '\n')
        {
       SKIP_WHITESPACE ();
       if (*input_line_pointer == '\n')
        {
-         as_bad ("Missing alignment");
+         as_bad (_("Missing alignment"));
          return;
        }
       align = get_absolute_expression ();
          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;
       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;
        }
       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.  */
        }
       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;
       if (temp > 1)
        {
          align = ffs (temp) - 1;
@@ -1472,14 +2069,14 @@ s_lcomm (needs_align)
       subseg_set (bss_seg, 1);
 
       if (align)
       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)
                                        /* detach from old frag */
       if (S_GET_SEGMENT (symbolP) == bss_seg)
-       symbolP->sy_frag->fr_symbol = NULL;
+       symbol_get_frag (symbolP)->fr_symbol = NULL;
 
 
-      symbolP->sy_frag = frag_now;
+      symbol_set_frag (symbolP, frag_now);
       pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
       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);
       *pfrag = 0;
 
       S_SET_SEGMENT (symbolP, bss_seg);
@@ -1493,19 +2090,36 @@ s_lcomm (needs_align)
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
        }
 #endif /* OBJ_COFF */
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
        }
 #endif /* OBJ_COFF */
+
+#ifdef S_SET_SIZE
+      S_SET_SIZE (symbolP, temp);
+#endif
     }
   else
     }
   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_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)
 
 void 
 s_lsym (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register char *name;
   register char c;
 {
   register char *name;
   register char c;
@@ -1522,7 +2136,7 @@ s_lsym (ignore)
   if (*input_line_pointer != ',')
     {
       *p = 0;
   if (*input_line_pointer != ',')
     {
       *p = 0;
-      as_bad ("Expected comma after name \"%s\"", name);
+      as_bad (_("Expected comma after name \"%s\""), name);
       *p = c;
       ignore_rest_of_line ();
       return;
       *p = c;
       ignore_rest_of_line ();
       return;
@@ -1532,7 +2146,7 @@ s_lsym (ignore)
   if (exp.X_op != O_constant
       && exp.X_op != O_register)
     {
   if (exp.X_op != O_constant
       && exp.X_op != O_register)
     {
-      as_bad ("bad expression");
+      as_bad (_("bad expression"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -1559,12 +2173,169 @@ s_lsym (ignore)
     }
   else
     {
     }
   else
     {
-      as_bad ("Symbol %s already defined", name);
+      as_bad (_("Symbol %s already defined"), name);
     }
   *p = c;
   demand_empty_rest_of_line ();
 }                              /* s_lsym() */
 
     }
   *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 ATTRIBUTE_UNUSED;
+{
+  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);
+         symbol_set_frag (line_label, &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 ATTRIBUTE_UNUSED;
+{
+  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 ATTRIBUTE_UNUSED;
+{
+  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
+      macro_mri_mode (1);
+    }
+  else
+    {
+      flag_mri = 0;
+      flag_m68k_mri = 0;
+      macro_mri_mode (0);
+    }
+
+  /* Operator precedence changes in m68k MRI mode, so we need to
+     update the operator rankings.  */
+  expr_set_precedence ();
+
+#ifdef MRI_MODE_CHANGE
+  if (on != old_flag)
+    MRI_MODE_CHANGE (on);
+#endif
+
+  demand_empty_rest_of_line ();
+}
+
 /* Handle changing the location counter.  */
 
 static void
 /* Handle changing the location counter.  */
 
 static void
@@ -1574,16 +2345,16 @@ do_org (segment, exp, fill)
      int fill;
 {
   if (segment != now_seg && segment != absolute_section)
      int fill;
 {
   if (segment != now_seg && segment != absolute_section)
-    as_bad ("invalid segment \"%s\"; segment \"%s\" assumed",
+    as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"),
            segment_name (segment), segment_name (now_seg));
 
   if (now_seg == absolute_section)
     {
       if (fill != 0)
            segment_name (segment), segment_name (now_seg));
 
   if (now_seg == absolute_section)
     {
       if (fill != 0)
-       as_warn ("ignoring fill value in absolute section");
+       as_warn (_("ignoring fill value in absolute section"));
       if (exp->X_op != O_constant)
        {
       if (exp->X_op != O_constant)
        {
-         as_bad ("only constant offsets supported in absolute section");
+         as_bad (_("only constant offsets supported in absolute section"));
          exp->X_add_number = 0;
        }
       abs_section_offset = exp->X_add_number;
          exp->X_add_number = 0;
        }
       abs_section_offset = exp->X_add_number;
@@ -1600,18 +2371,22 @@ do_org (segment, exp, fill)
 
 void 
 s_org (ignore)
 
 void 
 s_org (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register segT segment;
   expressionS exp;
   register long temp_fill;
 
 {
   register segT segment;
   expressionS exp;
   register long temp_fill;
 
-  /* The 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_mri)
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  /* The m68k MRI assembler has a different meaning for .org.  It
+     means to create an absolute section at a given address.  We can't
+     support that--use a linker script instead.  */
+  if (flag_m68k_mri)
     {
     {
-      as_bad ("MRI style ORG pseudo-op not supported");
+      as_bad (_("MRI style ORG pseudo-op not supported"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -1643,9 +2418,256 @@ s_org (ignore)
   demand_empty_rest_of_line ();
 }                              /* s_org() */
 
   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 ATTRIBUTE_UNUSED;
+{
+#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 ATTRIBUTE_UNUSED;
+{
+  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 ATTRIBUTE_UNUSED;
+{
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+  do
+    {
+      char *name;
+      char c;
+
+      SKIP_WHITESPACE ();
+      name = input_line_pointer;
+      c = get_symbol_end ();
+      delete_macro (name);
+      *input_line_pointer = c;
+      SKIP_WHITESPACE ();
+    }
+  while (*input_line_pointer++ == ',');
+
+  --input_line_pointer;
+  demand_empty_rest_of_line ();
+}
+
+/* Handle the .rept pseudo-op.  */
+
+void
+s_rept (ignore)
+     int ignore ATTRIBUTE_UNUSED;
+{
+  int count;
+  sb one;
+  sb many;
+
+  count = get_absolute_expression ();
+
+  sb_new (&one);
+  if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb))
+    {
+      as_bad (_("rept without endr"));
+      return;
+    }
+
+  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 
 void 
-s_set (ignore)
-     int ignore;
+s_set (equiv)
+     int equiv;
 {
   register char *name;
   register char delim;
 {
   register char *name;
   register char delim;
@@ -1666,7 +2688,7 @@ s_set (ignore)
   if (*input_line_pointer != ',')
     {
       *end_name = 0;
   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;
       *end_name = delim;
       ignore_rest_of_line ();
       return;
@@ -1693,7 +2715,24 @@ s_set (ignore)
   if ((symbolP = symbol_find (name)) == NULL
       && (symbolP = md_undefined_symbol (name)) == NULL)
     {
   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);
 #ifdef OBJ_COFF
       /* "set" symbols are local unless otherwise specified. */
       SF_SET_LOCAL (symbolP);
@@ -1704,6 +2743,12 @@ s_set (ignore)
   symbol_table_insert (symbolP);
 
   *end_name = delim;
   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() */
   pseudo_set (symbolP);
   demand_empty_rest_of_line ();
 }                              /* s_set() */
@@ -1713,83 +2758,166 @@ s_space (mult)
      int mult;
 {
   expressionS exp;
      int mult;
 {
   expressionS exp;
-  long temp_fill;
+  expressionS val;
   char *p = 0;
   char *p = 0;
+  char *stop = NULL;
+  char stopc;
+  int bytes;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
-  /* Just like .fill, but temp_size = 1 */
-  expression (&exp);
-  if (exp.X_op == O_constant)
-    {
-      long repeat;
-
-      repeat = exp.X_add_number;
-      if (mult)
-       repeat *= mult;
-      if (repeat <= 0)
-       {
-         as_warn (".space repeat count is %s, ignored",
-                  repeat ? "negative" : "zero");
-         ignore_rest_of_line ();
-         return;
-       }
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
 
-      /* If we are in the absolute section, just bump the offset.  */
+  /* In m68k MRI mode, we need to align to a word boundary, unless
+     this is ds.b.  */
+  if (flag_m68k_mri && mult > 1)
+    {
       if (now_seg == absolute_section)
        {
       if (now_seg == absolute_section)
        {
-         abs_section_offset += repeat;
-         demand_empty_rest_of_line ();
-         return;
+         abs_section_offset += abs_section_offset & 1;
+         if (line_label != NULL)
+           S_SET_VALUE (line_label, abs_section_offset);
        }
        }
-
-      /* 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)
+      else if (mri_common_symbol != NULL)
        {
        {
-         S_SET_VALUE (mri_common_symbol,
-                      S_GET_VALUE (mri_common_symbol) + repeat);
-         demand_empty_rest_of_line ();
-         return;
-       }
+         valueT val;
 
 
-      if (!need_pass_2)
-       p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
-                     repeat, (char *) 0);
-    }
-  else
-    {
-      if (now_seg == absolute_section)
-       {
-         as_bad ("space allocation too complex in absolute section");
-         subseg_set (text_section, 0);
+         val = S_GET_VALUE (mri_common_symbol);
+         if ((val & 1) != 0)
+           {
+             S_SET_VALUE (mri_common_symbol, val + 1);
+             if (line_label != NULL)
+               {
+                 expressionS *symexp;
+
+                 symexp = symbol_get_value_expression (line_label);
+                 know (symexp->X_op == O_symbol);
+                 know (symexp->X_add_symbol == mri_common_symbol);
+                 symexp->X_add_number += 1;
+               }
+           }
        }
        }
-      if (mri_common_symbol != NULL)
+      else
        {
        {
-         as_bad ("space allocation too complex in common section");
-         mri_common_symbol = NULL;
+         do_align (1, (char *) NULL, 0, 0);
+         if (line_label != NULL)
+           {
+             symbol_set_frag (line_label, frag_now);
+             S_SET_VALUE (line_label, frag_now_fix ());
+           }
        }
        }
-      if (!need_pass_2)
-       p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
-                     make_expr_symbol (&exp), 0L, (char *) 0);
     }
     }
+
+  bytes = mult;
+
+  expression (&exp);
+
   SKIP_WHITESPACE ();
   if (*input_line_pointer == ',')
     {
   SKIP_WHITESPACE ();
   if (*input_line_pointer == ',')
     {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
+      ++input_line_pointer;
+      expression (&val);
     }
   else
     {
     }
   else
     {
-      temp_fill = 0;
+      val.X_op = O_constant;
+      val.X_add_number = 0;
     }
     }
-  if (p)
+
+  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))
     {
     {
-      *p = temp_fill;
+      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);
+       }
     }
     }
+  else
+    {
+      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;
+    }
+
+ 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;
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 /* This is like s_space, but the value is a floating point number with
 }
 
 /* This is like s_space, but the value is a floating point number with
@@ -1803,14 +2931,21 @@ s_float_space (float_type)
   offsetT count;
   int flen;
   char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
   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 != ',')
     {
 
   count = get_absolute_expression ();
 
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing value");
+      as_bad (_("missing value"));
       ignore_rest_of_line ();
       ignore_rest_of_line ();
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       return;
     }
 
       return;
     }
 
@@ -1820,7 +2955,8 @@ s_float_space (float_type)
 
   /* Skip any 0{letter} that may be present.  Don't even check if the
    * letter is legal.  */
 
   /* Skip any 0{letter} that may be present.  Don't even check if the
    * letter is legal.  */
-  if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
+  if (input_line_pointer[0] == '0'
+      && isalpha ((unsigned char) input_line_pointer[1]))
     input_line_pointer += 2;
 
   /* Accept :xxxx, where the x's are hex digits, for a floating point
     input_line_pointer += 2;
 
   /* Accept :xxxx, where the x's are hex digits, for a floating point
@@ -1831,6 +2967,8 @@ s_float_space (float_type)
       if (flen < 0)
        {
          ignore_rest_of_line ();
       if (flen < 0)
        {
          ignore_rest_of_line ();
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          return;
        }
     }
          return;
        }
     }
@@ -1843,8 +2981,10 @@ s_float_space (float_type)
       know (flen > 0);
       if (err)
        {
       know (flen > 0);
       if (err)
        {
-         as_bad ("Bad floating literal: %s", err);
+         as_bad (_("Bad floating literal: %s"), err);
          ignore_rest_of_line ();
          ignore_rest_of_line ();
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          return;
        }
     }
          return;
        }
     }
@@ -1858,22 +2998,32 @@ s_float_space (float_type)
     }
 
   demand_empty_rest_of_line ();
     }
 
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 /* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
 
 void
 s_struct (ignore)
 }
 
 /* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
 
 void
 s_struct (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 {
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
   abs_section_offset = get_absolute_expression ();
   subseg_set (absolute_section, 0);
   demand_empty_rest_of_line ();
   abs_section_offset = get_absolute_expression ();
   subseg_set (absolute_section, 0);
   demand_empty_rest_of_line ();
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }
 
 void
 s_text (ignore)
 }
 
 void
 s_text (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register int temp;
 
 {
   register int temp;
 
@@ -1906,11 +3056,11 @@ ignore_rest_of_line ()          /* For suspect lines: gives warning. */
 {
   if (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
 {
   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
                *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])
                *input_line_pointer);
       while (input_line_pointer < buffer_limit
             && !is_end_of_line[(unsigned char) *input_line_pointer])
@@ -1922,6 +3072,18 @@ ignore_rest_of_line ()           /* For suspect lines: gives warning. */
   know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
   know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
+void
+discard_rest_of_line ()
+{
+  while (input_line_pointer < buffer_limit
+         && !is_end_of_line[(unsigned char) *input_line_pointer])
+    {
+      input_line_pointer++;
+    }
+  input_line_pointer++;         /* Return pointing just after end-of-line. */
+  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
+}
+
 /*
  *                     pseudo_set()
  *
 /*
  *                     pseudo_set()
  *
@@ -1949,17 +3111,22 @@ pseudo_set (symbolP)
   (void) expression (&exp);
 
   if (exp.X_op == O_illegal)
   (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)
   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)
   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))
           && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
   else if (exp.X_op == O_subtract
           && (S_GET_SEGMENT (exp.X_add_symbol)
               == S_GET_SEGMENT (exp.X_op_symbol))
           && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
-          && exp.X_add_symbol->sy_frag == exp.X_op_symbol->sy_frag)
+          && (symbol_get_frag (exp.X_add_symbol)
+              == symbol_get_frag (exp.X_op_symbol)))
     {
       exp.X_op = O_constant;
       exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
     {
       exp.X_op = O_constant;
       exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
@@ -1982,19 +3149,22 @@ pseudo_set (symbolP)
        S_CLEAR_EXTERNAL (symbolP);
 #endif /* OBJ_AOUT or OBJ_BOUT */
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
        S_CLEAR_EXTERNAL (symbolP);
 #endif /* OBJ_AOUT or OBJ_BOUT */
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
-      symbolP->sy_frag = &zero_address_frag;
+      if (exp.X_op != O_constant)
+        symbol_set_frag (symbolP, &zero_address_frag);
       break;
 
     case O_register:
       S_SET_SEGMENT (symbolP, reg_section);
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
       break;
 
     case O_register:
       S_SET_SEGMENT (symbolP, reg_section);
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
-      symbolP->sy_frag = &zero_address_frag;
+      symbol_set_frag (symbolP, &zero_address_frag);
       break;
 
     case O_symbol:
       if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
          || exp.X_add_number != 0)
       break;
 
     case O_symbol:
       if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
          || exp.X_add_number != 0)
-       symbolP->sy_value = exp;
+       symbol_set_value_expression (symbolP, &exp);
+      else if (symbol_section_p (symbolP))
+       as_bad ("invalid attempt to set value of section symbol");
       else
        {
          symbolS *s = exp.X_add_symbol;
       else
        {
          symbolS *s = exp.X_add_symbol;
@@ -2008,7 +3178,7 @@ pseudo_set (symbolP)
 #endif /* OBJ_AOUT or OBJ_BOUT */
          S_SET_VALUE (symbolP,
                       exp.X_add_number + S_GET_VALUE (s));
 #endif /* OBJ_AOUT or OBJ_BOUT */
          S_SET_VALUE (symbolP,
                       exp.X_add_number + S_GET_VALUE (s));
-         symbolP->sy_frag = s->sy_frag;
+         symbol_set_frag (symbolP, symbol_get_frag (s));
          copy_symbol_attributes (symbolP, s);
        }
       break;
          copy_symbol_attributes (symbolP, s);
        }
       break;
@@ -2016,7 +3186,7 @@ pseudo_set (symbolP)
     default:
       /* The value is some complex expression.
         FIXME: Should we set the segment to anything?  */
     default:
       /* The value is some complex expression.
         FIXME: Should we set the segment to anything?  */
-      symbolP->sy_value = exp;
+      symbol_set_value_expression (symbolP, &exp);
       break;
     }
 }
       break;
     }
 }
@@ -2070,30 +3240,50 @@ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
 /* worker to do .byte etc statements */
 /* clobbers input_line_pointer, checks */
 /* end-of-line. */
 /* worker to do .byte etc statements */
 /* clobbers input_line_pointer, checks */
 /* end-of-line. */
-void 
-cons (nbytes)
+static void 
+cons_worker (nbytes, rva)
      register int nbytes;      /* 1=.byte, 2=.word, 4=.long */
      register int nbytes;      /* 1=.byte, 2=.word, 4=.long */
+     int rva;
 {
   int c;
   expressionS exp;
 {
   int c;
   expressionS exp;
+  char *stop = NULL;
+  char stopc;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
+
   if (is_it_end_of_statement ())
     {
       demand_empty_rest_of_line ();
   if (is_it_end_of_statement ())
     {
       demand_empty_rest_of_line ();
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       return;
     }
 
       return;
     }
 
+#ifdef md_cons_align
+  md_cons_align (nbytes);
+#endif
+
   c = 0;
   do
     {
   c = 0;
   do
     {
-      if (flag_mri)
+      if (flag_m68k_mri)
        parse_mri_cons (&exp, (unsigned int) nbytes);
       else
        TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
        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;
     }
       emit_expr (&exp, (unsigned int) nbytes);
       ++c;
     }
@@ -2106,7 +3296,26 @@ cons (nbytes)
     mri_pending_align = 1;
 
   input_line_pointer--;                /* Put terminator back into stream. */
     mri_pending_align = 1;
 
   input_line_pointer--;                /* Put terminator back into stream. */
+
   demand_empty_rest_of_line ();
   demand_empty_rest_of_line ();
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+}
+
+
+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
 }
 
 /* Put the contents of expression EXP into the object file using
@@ -2121,8 +3330,75 @@ emit_expr (exp, nbytes)
   register char *p;
   valueT extra_digit = 0;
 
   register char *p;
   valueT extra_digit = 0;
 
-  /* Don't do anything if we are going to make another pass.  */
-  if (need_pass_2)
+  /* Don't do anything if we are going to make another pass.  */
+  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;
     return;
 
   op = exp->X_op;
@@ -2131,7 +3407,7 @@ emit_expr (exp, nbytes)
   if (now_seg == absolute_section)
     {
       if (op != O_constant || exp->X_add_number != 0)
   if (now_seg == absolute_section)
     {
       if (op != O_constant || exp->X_add_number != 0)
-       as_bad ("attempt to store value in absolute section");
+       as_bad (_("attempt to store value in absolute section"));
       abs_section_offset += nbytes;
       return;
     }
       abs_section_offset += nbytes;
       return;
     }
@@ -2139,13 +3415,13 @@ emit_expr (exp, nbytes)
   /* Handle a negative bignum.  */
   if (op == O_uminus
       && exp->X_add_number == 0
   /* Handle a negative bignum.  */
   if (op == O_uminus
       && exp->X_add_number == 0
-      && exp->X_add_symbol->sy_value.X_op == O_big
-      && exp->X_add_symbol->sy_value.X_add_number > 0)
+      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
+      && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
     {
       int i;
       unsigned long carry;
 
     {
       int i;
       unsigned long carry;
 
-      exp = &exp->X_add_symbol->sy_value;
+      exp = symbol_get_value_expression (exp->X_add_symbol);
 
       /* Negate the bignum: one's complement each digit and add 1.  */
       carry = 1;
 
       /* Negate the bignum: one's complement each digit and add 1.  */
       carry = 1;
@@ -2169,19 +3445,19 @@ emit_expr (exp, nbytes)
 
   if (op == O_absent || op == O_illegal)
     {
 
   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)
     {
       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)
     {
       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;
     }
 
       op = O_constant;
     }
 
@@ -2197,6 +3473,8 @@ emit_expr (exp, nbytes)
       x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
       x->next_broken_word = broken_words;
       broken_words = x;
       x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
       x->next_broken_word = broken_words;
       broken_words = x;
+      x->seg = now_seg;
+      x->subseg = now_subseg;
       x->frag = frag_now;
       x->word_goes_here = p;
       x->dispfrag = 0;
       x->frag = frag_now;
       x->word_goes_here = p;
       x->dispfrag = 0;
@@ -2236,14 +3514,25 @@ emit_expr (exp, nbytes)
       register valueT get;
       register valueT use;
       register valueT mask;
       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))
       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
       else
-       mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
+       {
+         /* Don't store these bits. */
+         mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
+         hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+       }
 
       unmask = ~mask;          /* Do store these bits. */
 
 
       unmask = ~mask;          /* Do store these bits. */
 
@@ -2254,16 +3543,19 @@ emit_expr (exp, nbytes)
 
       get = exp->X_add_number;
       use = get & unmask;
 
       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. */
        {               /* 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)
     {
        }
       /* 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);
       LITTLENUM_TYPE *nums;
 
       know (nbytes % CHARS_PER_LITTLENUM == 0);
@@ -2271,7 +3563,7 @@ emit_expr (exp, nbytes)
       size = exp->X_add_number * CHARS_PER_LITTLENUM;
       if (nbytes < size)
        {
       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;
        }
 
          size = nbytes;
        }
 
@@ -2330,11 +3622,31 @@ emit_expr (exp, nbytes)
 #ifdef TC_CONS_FIX_NEW
       TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
 #else
 #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
 #endif
 #else
 #ifdef TC_CONS_FIX_NEW
@@ -2417,7 +3729,7 @@ parse_bitfield_cons (exp, nbytes)
 
          if (exp->X_op == O_absent)
            {
 
          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 */
              exp->X_add_number = 0;
              exp->X_op = O_constant;
            }                   /* implied zero width bitfield */
@@ -2425,7 +3737,7 @@ parse_bitfield_cons (exp, nbytes)
          if (exp->X_op != O_constant)
            {
              *input_line_pointer = '\0';
          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;
              *input_line_pointer = ':';
              demand_empty_rest_of_line ();
              return;
@@ -2433,7 +3745,7 @@ parse_bitfield_cons (exp, nbytes)
 
          if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
            {
 
          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 */
                       width, nbytes, (BITS_PER_CHAR * nbytes));
              width = BITS_PER_CHAR * nbytes;
            }                   /* too big */
@@ -2454,7 +3766,7 @@ parse_bitfield_cons (exp, nbytes)
              char cache = *input_line_pointer;
 
              *input_line_pointer = '\0';
              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;
              *input_line_pointer = cache;
              demand_empty_rest_of_line ();
              return;
@@ -2496,7 +3808,7 @@ parse_mri_cons (exp, nbytes)
     TC_PARSE_CONS_EXPRESSION (exp, nbytes);
   else
     {
     TC_PARSE_CONS_EXPRESSION (exp, nbytes);
   else
     {
-      int scan = 0;
+      unsigned int scan;
       unsigned int result = 0;
 
       /* An MRI style string.  Cut into as many bytes as will fit into
       unsigned int result = 0;
 
       /* An MRI style string.  Cut into as many bytes as will fit into
@@ -2506,7 +3818,7 @@ parse_mri_cons (exp, nbytes)
        ++input_line_pointer;
       else if (*input_line_pointer == 'E')
        {
        ++input_line_pointer;
       else if (*input_line_pointer == 'E')
        {
-         as_bad ("EBCDIC constants are not supported");
+         as_bad (_("EBCDIC constants are not supported"));
          ++input_line_pointer;
        }
 
          ++input_line_pointer;
        }
 
@@ -2576,7 +3888,7 @@ parse_repeat_cons (exp, nbytes)
   if (count.X_op != O_constant
       || count.X_add_number <= 0)
     {
   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;
     }
 
       return;
     }
 
@@ -2627,7 +3939,7 @@ hex_float (float_type, bytes)
       break;
 
     default:
       break;
 
     default:
-      as_bad ("Unknown floating type type '%c'", float_type);
+      as_bad (_("Unknown floating type type '%c'"), float_type);
       return -1;
     }
 
       return -1;
     }
 
@@ -2649,7 +3961,7 @@ hex_float (float_type, bytes)
 
       if (i >= length)
        {
 
       if (i >= length)
        {
-         as_warn ("Floating point constant too large");
+         as_warn (_("Floating point constant too large"));
          return -1;
        }
       d = hex_value (*input_line_pointer) << 4;
          return -1;
        }
       d = hex_value (*input_line_pointer) << 4;
@@ -2715,6 +4027,10 @@ float_cons (float_type)
       return;
     }
 
       return;
     }
 
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
   do
     {
       /* input_line_pointer->1st char of a flonum (we hope!). */
   do
     {
       /* input_line_pointer->1st char of a flonum (we hope!). */
@@ -2725,7 +4041,8 @@ float_cons (float_type)
        * has no use for such information. Lusers beware: you get
        * diagnostics if your input is ill-conditioned.
        */
        * 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;
 
       /* Accept :xxxx, where the x's are hex digits, for a floating
        input_line_pointer += 2;
 
       /* Accept :xxxx, where the x's are hex digits, for a floating
@@ -2747,7 +4064,7 @@ float_cons (float_type)
          know (length > 0);
          if (err)
            {
          know (length > 0);
          if (err)
            {
-             as_bad ("Bad floating literal: %s", err);
+             as_bad (_("Bad floating literal: %s"), err);
              ignore_rest_of_line ();
              return;
            }
              ignore_rest_of_line ();
              return;
            }
@@ -2769,7 +4086,7 @@ float_cons (float_type)
              if (count_exp.X_op != O_constant
                  || count_exp.X_add_number <= 0)
                {
              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;
                }
              else
                count = count_exp.X_add_number;
@@ -2790,10 +4107,310 @@ float_cons (float_type)
   demand_empty_rest_of_line ();
 }                              /* float_cons() */
 \f
   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;
+}
+
+int
+output_leb128 (p, value, sign)
+     char *p;
+     valueT value;
+     int sign;
+{
+  if (sign)
+    return output_sleb128 (p, (offsetT) value);
+  else
+    return output_uleb128 (p, value);
+}
+
+/* Do the same for bignums.  We combine sizeof with output here in that
+   we don't output for NULL values of P.  It isn't really as critical as
+   for "normal" values that this be streamlined.  */
+
+static inline int
+output_big_sleb128 (p, bignum, size)
+     char *p;
+     LITTLENUM_TYPE *bignum;
+     int size;
+{
+  char *orig = p;
+  valueT val = 0;
+  int loaded = 0;
+  unsigned byte;
+
+  /* Strip leading sign extensions off the bignum.  */
+  while (size > 0 && bignum[size-1] == (LITTLENUM_TYPE)-1)
+    size--;
+
+  do
+    {
+      if (loaded < 7 && size > 0)
+       {
+         val |= (*bignum << loaded);
+         loaded += 8 * CHARS_PER_LITTLENUM;
+         size--;
+         bignum++;
+       }
+
+      byte = val & 0x7f;
+      loaded -= 7;
+      val >>= 7;
+
+      if (size == 0)
+       {
+         if ((val == 0 && (byte & 0x40) == 0)
+             || (~(val | ~(((valueT)1 << loaded) - 1)) == 0
+                 && (byte & 0x40) != 0))
+           byte |= 0x80;
+       }
+
+      if (orig)
+       *p = byte;
+      p++;
+    }
+  while (byte & 0x80);
+
+  return p - orig;
+}
+
+static inline int
+output_big_uleb128 (p, bignum, size)
+     char *p;
+     LITTLENUM_TYPE *bignum;
+     int size;
+{
+  char *orig = p;
+  valueT val = 0;
+  int loaded = 0;
+  unsigned byte;
+
+  /* Strip leading zeros off the bignum.  */
+  /* XXX: Is this needed?  */
+  while (size > 0 && bignum[size-1] == 0)
+    size--;
+
+  do
+    {
+      if (loaded < 7 && size > 0)
+       {
+         val |= (*bignum << loaded);
+         loaded += 8 * CHARS_PER_LITTLENUM;
+         size--;
+         bignum++;
+       }
+
+      byte = val & 0x7f;
+      loaded -= 7;
+      val >>= 7;
+
+      if (size > 0 || val)
+       byte |= 0x80;
+
+      if (orig)
+       *p = byte;
+      p++;
+    }
+  while (byte & 0x80);
+
+  return p - orig;
+}
+
+static int
+output_big_leb128 (p, bignum, size, sign)
+     char *p;
+     LITTLENUM_TYPE *bignum;
+     int size, sign;
+{
+  if (sign)
+    return output_big_sleb128 (p, bignum, size);
+  else
+    return output_big_uleb128 (p, bignum, size);
+}
+
+/* Generate the appropriate fragments for a given expression to emit a
+   leb128 value.  */
+
+void
+emit_leb128_expr(exp, sign)
+     expressionS *exp;
+     int sign;
+{
+  operatorT op = exp->X_op;
+
+  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()
  *
 /*
  *                     stringer()
  *
- * We read 0 or more ',' seperated, double-quoted strings.
+ * We read 0 or more ',' separated, double-quoted strings.
  *
  * Caller should have checked need_pass_2 is FALSE because we don't check it.
  */
  *
  * Caller should have checked need_pass_2 is FALSE because we don't check it.
  */
@@ -2805,6 +4422,7 @@ stringer (append_zero)            /* Worker to do .ascii etc statements. */
      register int append_zero; /* 0: don't append '\0', else 1 */
 {
   register unsigned int c;
      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 ();
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
@@ -2812,7 +4430,7 @@ stringer (append_zero)            /* Worker to do .ascii etc statements. */
 
   /*
    * The following awkward logic is to parse ZERO or more strings,
 
   /*
    * The following awkward logic is to parse ZERO or more strings,
-   * comma seperated. Recall a string expression includes spaces
+   * comma separated. Recall a string expression includes spaces
    * before the opening '\"' and spaces after the closing '\"'.
    * We fake a leading ',' if there is (supposed to be)
    * a 1st, expression. We keep demanding expressions for each
    * before the opening '\"' and spaces after the closing '\"'.
    * We fake a leading ',' if there is (supposed to be)
    * a 1st, expression. We keep demanding expressions for each
@@ -2834,6 +4452,7 @@ stringer (append_zero)            /* Worker to do .ascii etc statements. */
        {
        case '\"':
          ++input_line_pointer; /*->1st char of string. */
        {
        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);
          while (is_a_char (c = next_char_of_string ()))
            {
              FRAG_APPEND_1_CHAR (c);
@@ -2843,6 +4462,27 @@ stringer (append_zero)           /* Worker to do .ascii etc statements. */
              FRAG_APPEND_1_CHAR (0);
            }
          know (input_line_pointer[-1] == '\"');
              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++;
          break;
        case '<':
          input_line_pointer++;
@@ -2850,7 +4490,7 @@ stringer (append_zero)            /* Worker to do .ascii etc statements. */
          FRAG_APPEND_1_CHAR (c);
          if (*input_line_pointer != '>')
            {
          FRAG_APPEND_1_CHAR (c);
          if (*input_line_pointer != '>')
            {
-             as_bad ("Expected <nn>");
+             as_bad (_("Expected <nn>"));
            }
          input_line_pointer++;
          break;
            }
          input_line_pointer++;
          break;
@@ -2882,6 +4522,11 @@ next_char_of_string ()
       c = NOT_A_CHAR;
       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++)
 #ifndef NO_STRING_ESCAPES
     case '\\':
       switch (c = *input_line_pointer++)
@@ -2961,14 +4606,15 @@ next_char_of_string ()
 
        case '\n':
          /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
 
        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';
          c = '\n';
+         bump_line_counters ();
          break;
 
        default:
 
 #ifdef ONLY_STANDARD_ESCAPES
          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 */
 
          c = '?';
 #endif /* ONLY_STANDARD_ESCAPES */
 
@@ -2994,7 +4640,7 @@ get_segmented_expression (expP)
       || expP->X_op == O_absent
       || expP->X_op == O_big)
     {
       || 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;
       expP->X_op = O_constant;
       expP->X_add_number = 0;
       retval = absolute_section;
@@ -3014,10 +4660,10 @@ get_known_segmented_expression (expP)
         expression.  */
       if (expP->X_add_symbol != NULL
          && S_GET_SEGMENT (expP->X_add_symbol) != expr_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
                 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;
       retval = absolute_section;
       expP->X_op = O_constant;
       expP->X_add_number = 0;
@@ -3035,7 +4681,7 @@ get_absolute_expression ()
   if (exp.X_op != O_constant)
     {
       if (exp.X_op != O_absent)
   if (exp.X_op != O_constant)
     {
       if (exp.X_op != O_absent)
-       as_bad ("bad or irreducible absolute expression; zero assumed");
+       as_bad (_("bad or irreducible absolute expression; zero assumed"));
       exp.X_add_number = 0;
     }
   return exp.X_add_number;
       exp.X_add_number = 0;
     }
   return exp.X_add_number;
@@ -3066,20 +4712,18 @@ demand_copy_C_string (len_pointer)
     {
       register int len;
 
     {
       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;
        {
          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
 /*
 }
 \f
 /*
@@ -3107,14 +4751,14 @@ demand_copy_string (lenP)
          obstack_1grow (&notes, c);
          len++;
        }
          obstack_1grow (&notes, 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 (&notes, '\0');
       retval = obstack_finish (&notes);
     }
   else
     {
       obstack_1grow (&notes, '\0');
       retval = obstack_finish (&notes);
     }
   else
     {
-      as_warn ("Missing string");
+      as_warn (_("Missing string"));
       retval = NULL;
       ignore_rest_of_line ();
     }
       retval = NULL;
       ignore_rest_of_line ();
     }
@@ -3139,10 +4783,13 @@ is_it_end_of_statement ()
 }                              /* is_it_end_of_statement() */
 
 void 
 }                              /* is_it_end_of_statement() */
 
 void 
-equals (sym_name)
+equals (sym_name, reassign)
      char *sym_name;
      char *sym_name;
+     int reassign;
 {
   register symbolS *symbolP;   /* symbol we are working with */
 {
   register symbolS *symbolP;   /* symbol we are working with */
+  char *stop = NULL;
+  char stopc;
 
   input_line_pointer++;
   if (*input_line_pointer == '=')
 
   input_line_pointer++;
   if (*input_line_pointer == '=')
@@ -3151,6 +4798,9 @@ equals (sym_name)
   while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
     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 */
   if (sym_name[0] == '.' && sym_name[1] == '\0')
     {
       /* Turn '. = mumble' into a .org mumble */
@@ -3164,8 +4814,19 @@ equals (sym_name)
   else
     {
       symbolP = symbol_find_or_make (sym_name);
   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);
     }
       pseudo_set (symbolP);
     }
+
+  if (flag_mri)
+     {
+       ignore_rest_of_line (); /* check garbage after the expression */
+       mri_comment_end (stop, stopc);
+     }
 }                              /* equals() */
 
 /* .include -- include a file at this point. */
 }                              /* equals() */
 
 /* .include -- include a file at this point. */
@@ -3173,7 +4834,7 @@ equals (sym_name)
 /* ARGSUSED */
 void 
 s_include (arg)
 /* ARGSUSED */
 void 
 s_include (arg)
-     int arg;
+     int arg ATTRIBUTE_UNUSED;
 {
   char *newbuf;
   char *filename;
 {
   char *newbuf;
   char *filename;
@@ -3181,7 +4842,33 @@ s_include (arg)
   FILE *try;
   char *path;
 
   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 (&notes, *input_line_pointer);
+         ++input_line_pointer;
+         ++i;
+       }
+      obstack_1grow (&notes, '\0');
+      filename = obstack_finish (&notes);
+      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++)
   demand_empty_rest_of_line ();
   path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
   for (i = 0; i < include_dir_count; i++)
@@ -3199,6 +4886,7 @@ s_include (arg)
   path = filename;
 gotit:
   /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY. */
   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() */
   newbuf = input_scrub_include_file (path, input_line_pointer);
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }                              /* s_include() */
@@ -3228,10 +4916,147 @@ add_include_dir (path)
   if (i > include_dir_maxlen)
     include_dir_maxlen = i;
 }                              /* add_include_dir() */
   if (i > include_dir_maxlen)
     include_dir_maxlen = i;
 }                              /* add_include_dir() */
+\f
+/* Output debugging information to denote the source file.  */
+
+static void
+generate_file_debug ()
+{
+  if (debug_type == DEBUG_STABS)
+    stabs_generate_asm_file ();
+}
+
+/* Output line number debugging information for the current source line.  */
+
+void
+generate_lineno_debug ()
+{
+#ifdef ECOFF_DEBUGGING
+  /* ECOFF assemblers automatically generate debugging information. 
+     FIXME: This should probably be handled elsewhere.  */
+  if (debug_type == DEBUG_UNSPECIFIED)
+    {
+      if (ECOFF_DEBUGGING && ecoff_no_current_file ())
+        debug_type = DEBUG_ECOFF;
+      else
+       debug_type = DEBUG_NONE;
+    }
+#endif
+
+  switch (debug_type)
+    {
+    case DEBUG_UNSPECIFIED:
+    case DEBUG_NONE:
+      break;
+    case DEBUG_STABS:
+      stabs_generate_asm_lineno ();
+      break;
+    case DEBUG_ECOFF:
+      ecoff_generate_asm_lineno ();
+      break;
+    case DEBUG_DWARF:
+    case DEBUG_DWARF2:
+      /* FIXME.  */
+      break;
+    }
+}
+
+/* Output debugging information to mark a function entry point or end point.
+   END_P is zero for .func, and non-zero for .endfunc.  */
+
+void
+s_func (end_p)
+     int end_p;
+{
+  do_s_func (end_p, NULL);
+}
+
+/* Subroutine of s_func so targets can choose a different default prefix.
+   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
+
+void
+do_s_func (end_p, default_prefix)
+     int end_p;
+     const char *default_prefix;
+{
+  /* Record the current function so that we can issue an error message for
+     misplaced .func,.endfunc, and also so that .endfunc needs no
+     arguments.  */
+  static char *current_name;
+  static char *current_label;
+
+  if (end_p)
+    {
+      if (current_name == NULL)
+       {
+         as_bad (_("missing .func"));
+         ignore_rest_of_line ();
+         return;
+       }
+
+      if (debug_type == DEBUG_STABS)
+       stabs_generate_asm_endfunc (current_name, current_label);
+
+      current_name = current_label = NULL;
+    }
+  else /* ! end_p */
+    {
+      char *name,*label;
+      char delim1,delim2;
+
+      if (current_name != NULL)
+       {
+         as_bad (_(".endfunc missing for previous .func"));
+         ignore_rest_of_line ();
+         return;
+       }
+
+      name = input_line_pointer;
+      delim1 = get_symbol_end ();
+      name = xstrdup (name);
+      *input_line_pointer = delim1;
+      SKIP_WHITESPACE ();
+      if (*input_line_pointer != ',')
+       {
+         if (default_prefix)
+           asprintf (&label, "%s%s", default_prefix, name);
+         else
+           {
+             char leading_char = 0;
+#ifdef BFD_ASSEMBLER
+             leading_char = bfd_get_symbol_leading_char (stdoutput);
+#endif
+             /* Missing entry point, use function's name with the leading
+                char prepended.  */
+             if (leading_char)
+               asprintf (&label, "%c%s", leading_char, name);
+             else
+               label = name;
+           }
+       }
+      else
+       {
+         ++input_line_pointer;
+         SKIP_WHITESPACE ();
+         label = input_line_pointer;
+         delim2 = get_symbol_end ();
+         label = xstrdup (label);
+         *input_line_pointer = delim2;
+       }
+
+      if (debug_type == DEBUG_STABS)
+       stabs_generate_asm_func (name, label);
+
+      current_name = name;
+      current_label = label;
+    }
 
 
+  demand_empty_rest_of_line ();
+}
+\f
 void 
 s_ignore (arg)
 void 
 s_ignore (arg)
-     int arg;
+     int arg ATTRIBUTE_UNUSED;
 {
   while (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
 {
   while (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
@@ -3241,4 +5066,11 @@ s_ignore (arg)
 }
 
 
 }
 
 
+void
+read_print_statistics (file)
+     FILE *file;
+{
+  hash_print_statistics (file, "pseudo-op table", po_hash);
+}
+
 /* end of read.c */
 /* end of read.c */
This page took 0.071512 seconds and 4 git commands to generate.