start writing functions for extracting and inserting unusual operands
[deliverable/binutils-gdb.git] / gas / read.c
index 7efdaad626fd655a3fe45264b22a2d48ffbefbbb..2bf064d5b428048eb5d193d06f9d05e5fbe0d18c 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986, 1987, 1990, 1991, 1993, 1994
+   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
    Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
@@ -85,13 +85,23 @@ die horribly;
 #define LEX_PCT 0
 #endif
 
+#ifndef LEX_QM
+/* The PowerPC Windows NT assemblers permits ? inside label names.  */
+#define LEX_QM 0
+#endif
+
+#ifndef LEX_DOLLAR
+/* The a29k assembler does not permits labels to start with $.  */
+#define LEX_DOLLAR 3
+#endif
+
 /* 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, 0, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */
   LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,      /* `abcdefghijklmno */
@@ -191,7 +201,8 @@ symbolS *mri_common_symbol;
    may be needed.  */
 static int mri_pending_align;
 
-static void do_align PARAMS ((int, char *));
+static int scrub_from_string PARAMS ((char **));
+static void do_align PARAMS ((int, char *, int));
 static int hex_float PARAMS ((int, char *));
 static void do_org PARAMS ((segT, expressionS *, int));
 char *demand_copy_string PARAMS ((int *lenP));
@@ -212,8 +223,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.  */
-  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++)
@@ -235,6 +246,8 @@ static const pseudo_typeS potable[] =
   {"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},
@@ -263,6 +276,7 @@ static const pseudo_typeS potable[] =
   {"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
@@ -277,7 +291,7 @@ static const pseudo_typeS potable[] =
   {"endif", s_endif, 0},
 /* endef */
   {"equ", s_set, 0},
-/* err */
+  {"err", s_err, 0},
   {"exitm", s_mexit, 0},
 /* extend */
   {"extern", s_ignore, 0},     /* We treat all undef as ext */
@@ -308,15 +322,21 @@ static const pseudo_typeS potable[] =
   {"include", s_include, 0},
   {"int", cons, 4},
   {"irp", s_irp, 0},
+  {"irep", s_irp, 0},
   {"irpc", s_irp, 1},
+  {"irepc", s_irp, 1},
   {"lcomm", s_lcomm, 0},
   {"lflags", listing_flags, 0},        /* Listing flags */
+  {"linkonce", s_linkonce, 0},
   {"list", listing_list, 1},   /* Turn listing on */
   {"llen", listing_psize, 1},
   {"long", cons, 4},
   {"lsym", s_lsym, 0},
   {"macro", s_macro, 0},
   {"mexit", s_mexit, 0},
+  {"mri", s_mri, 0},
+  {".mri", s_mri, 0},  /* Special case so .mri works in MRI mode.  */
+  {"name", s_ignore, 0},
   {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off */
   {"nopage", listing_nopage, 0},
@@ -324,12 +344,17 @@ static const pseudo_typeS potable[] =
   {"offset", s_struct, 0},
   {"org", s_org, 0},
   {"p2align", s_align_ptwo, 0},
+  {"p2alignw", s_align_ptwo, -2},
+  {"p2alignl", s_align_ptwo, -4},
   {"page", listing_eject, 0},
   {"plen", listing_psize, 0},
+  {"print", s_print, 0},
   {"psize", listing_psize, 0}, /* set paper size */
-/* print */
+  {"purgem", s_purgem, 0},
   {"quad", cons, 8},
+  {"rep", s_rept, 0},
   {"rept", s_rept, 0},
+  {"rva", s_rva, 4},
   {"sbttl", listing_title, 1}, /* Subtitle of listing */
 /* scl */
 /* sect */
@@ -338,6 +363,7 @@ static const pseudo_typeS potable[] =
   {"single", float_cons, 'f'},
 /* size */
   {"space", s_space, 0},
+  {"skip", s_space, 0},
   {"spc", s_ignore, 0},
   {"stabd", s_stab, 'd'},
   {"stabn", s_stab, 'n'},
@@ -384,7 +410,8 @@ pop_insert (table)
     {
       errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
       if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
-       as_fatal ("error constructing %s pseudo-op table", pop_table_name);
+       as_fatal ("error constructing %s pseudo-op table: %s", pop_table_name,
+                 errtxt);
     }
 }
 
@@ -425,6 +452,24 @@ 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 (from)
+     char **from;
+{
+  int size;
+
+  *from = scrub_string;
+  size = scrub_string_end - scrub_string;
+  scrub_string = scrub_string_end;
+  return size;
+}
+
 /*     read_a_source_file()
  *
  * We read the file, putting things into a web that
@@ -470,7 +515,7 @@ read_a_source_file (name)
 
              line_label = NULL;
 
-             if (flag_mri
+             if (flag_m68k_mri
 #ifdef LABELS_WITHOUT_COLONS
                  || 1
 #endif
@@ -489,7 +534,7 @@ read_a_source_file (name)
 
                      /* In MRI mode, the EQU pseudoop must be
                         handled specially.  */
-                     if (flag_mri)
+                     if (flag_m68k_mri)
                        {
                          char *rest = input_line_pointer + 1;
 
@@ -559,7 +604,7 @@ read_a_source_file (name)
               */
              if (TC_START_LABEL(c, input_line_pointer))
                {
-                 if (flag_mri)
+                 if (flag_m68k_mri)
                    {
                      char *rest = input_line_pointer + 1;
 
@@ -613,7 +658,7 @@ read_a_source_file (name)
                  }
 #endif
 
-                 if (flag_mri
+                 if (flag_m68k_mri
 #ifdef NO_PSEUDO_DOT
                      || 1
 #endif
@@ -627,7 +672,7 @@ read_a_source_file (name)
                    }
 
                  if (pop != NULL
-                     || (! flag_mri && *s == '.'))
+                     || (! flag_m68k_mri && *s == '.'))
                    {
                      /*
                       * PSEUDO - OP.
@@ -650,7 +695,7 @@ read_a_source_file (name)
                                    || (pop->poc_handler == s_space
                                        && pop->poc_val == 1))))
                        {
-                         do_align (1, (char *) NULL);
+                         do_align (1, (char *) NULL, 0);
                          mri_pending_align = 0;
                        }
 
@@ -687,7 +732,7 @@ read_a_source_file (name)
 
                      if (mri_pending_align)
                        {
-                         do_align (1, (char *) NULL);
+                         do_align (1, (char *) NULL, 0);
                          mri_pending_align = 0;
                        }
 
@@ -701,7 +746,7 @@ read_a_source_file (name)
 #endif
                             )
                        {
-                         if (flag_mri && *input_line_pointer == '\'')
+                         if (flag_m68k_mri && *input_line_pointer == '\'')
                            inquote = ! inquote;
                          input_line_pointer++;
                        }
@@ -810,7 +855,6 @@ read_a_source_file (name)
              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;
@@ -862,26 +906,30 @@ read_a_source_file (name)
                {
                  input_line_pointer = ends + 8;
                }
-             new_buf = xmalloc (100);
-             new_length = 100;
-             new_tmp = new_buf;
 
              scrub_string = s;
-             scrub_last_string = ends;
+             scrub_string_end = ends;
+
+             new_length = ends - s;
+             new_buf = (char *) xmalloc (new_length);
+             new_tmp = new_buf;
              for (;;)
                {
-                 int ch;
+                 int space;
+                 int size;
 
-                 ch = do_scrub_next_char (scrub_from_string, scrub_to_string);
-                 if (ch == EOF)
-                   break;
-                 *new_tmp++ = ch;
-                 if (new_tmp == new_buf + new_length)
+                 space = (new_buf + new_length) - new_tmp;
+                 size = do_scrub_chars (scrub_from_string, new_tmp, space);
+
+                 if (size < space)
                    {
-                     new_buf = xrealloc (new_buf, new_length + 100);
-                     new_tmp = new_buf + new_length;
-                     new_length += 100;
+                     new_tmp += size;
+                     break;
                    }
+
+                 new_buf = xrealloc (new_buf, new_length + 100);
+                 new_tmp = new_buf + new_length;
+                 new_length += 100;
                }
 
              if (tmp_buf)
@@ -897,6 +945,11 @@ read_a_source_file (name)
 
          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 ();
@@ -908,6 +961,7 @@ read_a_source_file (name)
 
       if (old_buffer)
        {
+         free (buffer);
          bump_line_counters ();
          if (old_input != 0)
            {
@@ -924,6 +978,66 @@ read_a_source_file (name)
   input_scrub_close ();                /* Close the input file */
 }
 
+/* For most MRI pseudo-ops, the line actually ends at the first
+   nonquoted space.  This function looks for that point, stuffs a null
+   in, and sets *STOPCP to the character that used to be there, and
+   returns the location.
+
+   Until I hear otherwise, I am going to assume that this is only true
+   for the m68k MRI assembler.  */
+
+char *
+mri_comment_field (stopcp)
+     char *stopcp;
+{
+#ifdef TC_M68K
+
+  char *s;
+  int inquote = 0;
+
+  know (flag_m68k_mri);
+
+  for (s = input_line_pointer;
+       ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
+       || inquote);
+       s++)
+    {
+      if (*s == '\'')
+       inquote = ! inquote;
+    }
+  *stopcp = *s;
+  *s = '\0';
+  return s;
+
+#else
+
+  char *s;
+
+  for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
+    ;
+  *stopcp = *s;
+  *s = '\0';
+  return s;
+
+#endif
+
+}
+
+/* Skip to the end of an MRI comment field.  */
+
+void
+mri_comment_end (stop, stopc)
+     char *stop;
+     int stopc;
+{
+  know (flag_mri);
+
+  input_line_pointer = stop;
+  *stop = stopc;
+  while (! is_end_of_line[(unsigned char) *input_line_pointer])
+    ++input_line_pointer;
+}
+
 void 
 s_abort (ignore)
      int ignore;
@@ -933,12 +1047,13 @@ s_abort (ignore)
 
 /* Guts of .align directive.  */
 static void 
-do_align (n, fill)
+do_align (n, fill, len)
      int n;
      char *fill;
+     int len;
 {
 #ifdef md_do_align
-  md_do_align (n, fill, just_record_alignment);
+  md_do_align (n, fill, len, just_record_alignment);
 #endif
   if (!fill)
     {
@@ -954,10 +1069,17 @@ do_align (n, fill)
        {
          fill = &zero;
        }
+      len = 1;
     }
+
   /* Only make a frag if we HAVE to. . . */
   if (n && !need_pass_2)
-    frag_align (n, *fill);
+    {
+      if (len <= 1)
+       frag_align (n, *fill);
+      else
+       frag_align_pattern (n, fill, len);
+    }
 
 #ifdef md_do_align
  just_record_alignment:
@@ -975,9 +1097,19 @@ s_align_bytes (arg)
   char temp_fill;
   unsigned int i = 0;
   unsigned long max_alignment = 1 << 15;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   if (is_end_of_line[(unsigned char) *input_line_pointer])
-    temp = arg;                        /* Default value from pseudo-op table */
+    {
+      if (arg < 0)
+       temp = 0;
+      else
+       temp = arg;     /* Default value from pseudo-op table */
+    }
   else
     temp = get_absolute_expression ();
 
@@ -999,24 +1131,56 @@ s_align_bytes (arg)
   temp = i;
   if (*input_line_pointer == ',')
     {
+      offsetT fillval;
+      int len;
+
       input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-      do_align (temp, &temp_fill);
+      fillval = get_absolute_expression ();
+      if (arg >= 0)
+       len = 1;
+      else
+       len = - arg;
+      if (len <= 1)
+       {
+         temp_fill = fillval;
+         do_align (temp, &temp_fill, len);
+       }
+      else
+       {
+         char ab[16];
+
+         if (len > sizeof ab)
+           abort ();
+         md_number_to_chars (ab, fillval, len);
+         do_align (temp, ab, len);
+       }
     }
   else
-    do_align (temp, (char *) 0);
+    {
+      if (arg < 0)
+       as_warn ("expected fill pattern missing");
+      do_align (temp, (char *) NULL, 0);
+    }
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 
   demand_empty_rest_of_line ();
 }
 
 /* For machines where ".align 4" means align to 2**4 boundary. */
 void 
-s_align_ptwo (ignore)
-     int ignore;
+s_align_ptwo (arg)
+     int arg;
 {
   register int temp;
   char temp_fill;
   long max_alignment = 15;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   temp = get_absolute_expression ();
   if (temp > max_alignment)
@@ -1028,12 +1192,39 @@ s_align_ptwo (ignore)
     }
   if (*input_line_pointer == ',')
     {
+      offsetT fillval;
+      int len;
+
       input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-      do_align (temp, &temp_fill);
+      fillval = get_absolute_expression ();
+      if (arg >= 0)
+       len = 1;
+      else
+       len = - arg;
+      if (len <= 1)
+       {
+         temp_fill = fillval;
+         do_align (temp, &temp_fill, len);
+       }
+      else
+       {
+         char ab[16];
+
+         if (len > sizeof ab)
+           abort ();
+         md_number_to_chars (ab, fillval, len);
+         do_align (temp, ab, len);
+       }
     }
   else
-    do_align (temp, (char *) 0);
+    {
+      if (arg < 0)
+       as_warn ("expected fill pattern missing");
+      do_align (temp, (char *) NULL, 0);
+    }
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 
   demand_empty_rest_of_line ();
 }
@@ -1047,6 +1238,11 @@ s_comm (ignore)
   register char *p;
   offsetT temp;
   register symbolS *symbolP;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   name = input_line_pointer;
   c = get_symbol_end ();
@@ -1057,6 +1253,8 @@ s_comm (ignore)
   if (*input_line_pointer != ',')
     {
       as_bad ("Expected comma after symbol-name: rest of line ignored.");
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1064,6 +1262,8 @@ s_comm (ignore)
   if ((temp = get_absolute_expression ()) < 0)
     {
       as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1074,6 +1274,8 @@ s_comm (ignore)
     {
       as_bad ("Ignoring attempt to re-define symbol `%s'.",
              S_GET_NAME (symbolP));
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1098,6 +1300,10 @@ s_comm (ignore)
   }
 #endif /* not OBJ_VMS */
   know (symbolP->sy_frag == &zero_address_frag);
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }                              /* s_comm() */
 
@@ -1114,6 +1320,8 @@ s_mri_common (small)
   char *alc = NULL;
   symbolS *sym;
   offsetT align;
+  char *stop = NULL;
+  char stopc;
 
   if (! flag_mri)
     {
@@ -1121,6 +1329,8 @@ s_mri_common (small)
       return;
     }
 
+  stop = mri_comment_field (&stopc);
+
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
@@ -1166,6 +1376,7 @@ s_mri_common (small)
 #endif
        {
          as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
+         mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -1196,6 +1407,9 @@ s_mri_common (small)
     input_line_pointer += 2;
   if (*input_line_pointer == ',')
     input_line_pointer += 2;
+
+  mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1224,11 +1438,11 @@ s_data (ignore)
 }
 
 /* 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)
@@ -1244,6 +1458,14 @@ s_app_file (appfile)
         the buffer.  Passing -2 to new_logical_line tells it to
         account for it.  */
       new_logical_line (s, appfile ? -2 : -1);
+
+      /* 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 ();
 #ifdef LISTING
       if (listing)
@@ -1256,9 +1478,9 @@ s_app_file (appfile)
 }
 
 /* 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)
@@ -1295,11 +1517,23 @@ s_end (ignore)
       /* The MRI assembler permits the start symbol to follow .end,
          but we don't support that.  */
       SKIP_WHITESPACE ();
-      if (! is_end_of_line[(unsigned char) *input_line_pointer])
+      if (! is_end_of_line[(unsigned char) *input_line_pointer]
+         && *input_line_pointer != '*'
+         && *input_line_pointer != '!')
        as_warn ("start address not supported");
     }
 }
 
+/* Handle the .err pseudo-op.  */
+
+void
+s_err (ignore)
+     int ignore;
+{
+  as_bad (".err encountered");
+  demand_empty_rest_of_line ();
+}
+
 /* Handle the MRI fail pseudo-op.  */
 
 void
@@ -1307,12 +1541,21 @@ s_fail (ignore)
      int ignore;
 {
   offsetT temp;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   temp = get_absolute_expression ();
   if (temp >= 500)
     as_warn (".fail %ld encountered", (long) temp);
   else
     as_bad (".fail %ld encountered", (long) temp);
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1325,6 +1568,9 @@ s_fill (ignore)
   register long temp_fill = 0;
   char *p;
 
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
 
   temp_repeat = get_absolute_expression ();
   if (*input_line_pointer == ',')
@@ -1384,6 +1630,11 @@ s_globl (ignore)
   char *name;
   int c;
   symbolS *symbolP;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   do
     {
@@ -1402,6 +1653,10 @@ s_globl (ignore)
        }
     }
   while (c == ',');
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1436,6 +1691,83 @@ s_irp (irpc)
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }
 
+/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
+   the section to only be linked once.  However, this is not supported
+   by most object file formats.  This takes an optional argument,
+   which is what to do about duplicates.  */
+
+void
+s_linkonce (ignore)
+     int ignore;
+{
+  enum linkonce_type type;
+
+  SKIP_WHITESPACE ();
+
+  type = LINKONCE_DISCARD;
+
+  if (! is_end_of_line[(unsigned char) *input_line_pointer])
+    {
+      char *s;
+      char c;
+
+      s = input_line_pointer;
+      c = get_symbol_end ();
+      if (strcasecmp (s, "discard") == 0)
+       type = LINKONCE_DISCARD;
+      else if (strcasecmp (s, "one_only") == 0)
+       type = LINKONCE_ONE_ONLY;
+      else if (strcasecmp (s, "same_size") == 0)
+       type = LINKONCE_SAME_SIZE;
+      else if (strcasecmp (s, "same_contents") == 0)
+       type = LINKONCE_SAME_CONTENTS;
+      else
+       as_warn ("unrecognized .linkonce type `%s'", s);
+
+      *input_line_pointer = c;
+    }
+
+#ifdef obj_handle_link_once
+  obj_handle_link_once (type);
+#else /* ! defined (obj_handle_link_once) */
+#ifdef BFD_ASSEMBLER
+  {
+    flagword flags;
+
+    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
+      as_warn (".linkonce is not supported for this object file format");
+
+    flags = bfd_get_section_flags (stdoutput, now_seg);
+    flags |= SEC_LINK_ONCE;
+    switch (type)
+      {
+      default:
+       abort ();
+      case LINKONCE_DISCARD:
+       flags |= SEC_LINK_DUPLICATES_DISCARD;
+       break;
+      case LINKONCE_ONE_ONLY:
+       flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+       break;
+      case LINKONCE_SAME_SIZE:
+       flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
+       break;
+      case LINKONCE_SAME_CONTENTS:
+       flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
+       break;
+      }
+    if (! bfd_set_section_flags (stdoutput, now_seg, flags))
+      as_bad ("bfd_set_section_flags: %s",
+             bfd_errmsg (bfd_get_error ()));
+  }
+#else /* ! defined (BFD_ASSEMBLER) */
+  as_warn (".linkonce is not supported for this object file format");
+#endif /* ! defined (BFD_ASSEMBLER) */
+#endif /* ! defined (obj_handle_link_once) */
+
+  demand_empty_rest_of_line ();
+}
+
 void 
 s_lcomm (needs_align)
      /* 1 if this was a ".bss" directive, which may require a 3rd argument
@@ -1489,6 +1821,11 @@ s_lcomm (needs_align)
        {
          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
@@ -1588,6 +1925,10 @@ s_lcomm (needs_align)
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
        }
 #endif /* OBJ_COFF */
+
+#ifdef S_SET_SIZE
+      S_SET_SIZE (symbolP, temp);
+#endif
     }
   else
     as_bad ("Ignoring attempt to re-define symbol `%s'.",
@@ -1666,6 +2007,9 @@ static int
 get_line_sb (line)
      sb *line;
 {
+  if (input_line_pointer[-1] == '\n')
+    bump_line_counters ();
+
   if (input_line_pointer >= buffer_limit)
     {
       buffer_limit = input_scrub_next_buffer (&input_line_pointer);
@@ -1675,13 +2019,11 @@ get_line_sb (line)
 
   while (! is_end_of_line[(unsigned char) *input_line_pointer])
     sb_add_char (line, *input_line_pointer++);
-  while (is_end_of_line[(unsigned char) *input_line_pointer])
+  while (input_line_pointer < buffer_limit
+        && is_end_of_line[(unsigned char) *input_line_pointer])
     {
-      if (*input_line_pointer == '\n')
-       {
-         bump_line_counters ();
-         LISTING_NEWLINE ();
-       }
+      if (input_line_pointer[-1] == '\n')
+       bump_line_counters ();
       ++input_line_pointer;
     }
   return 1;
@@ -1710,8 +2052,6 @@ s_macro (ignore)
   if (line_label != NULL)
     sb_add_string (&label, S_GET_NAME (line_label));
 
-  demand_empty_rest_of_line ();
-
   err = define_macro (0, &s, &label, get_line_sb);
   if (err != NULL)
     as_bad_where (file, line, "%s", err);
@@ -1738,6 +2078,37 @@ s_mexit (ignore)
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }
 
+/* Switch in and out of MRI mode.  */
+
+void
+s_mri (ignore)
+     int ignore;
+{
+  int on, old_flag;
+
+  on = get_absolute_expression ();
+  old_flag = flag_mri;
+  if (on != 0)
+    {
+      flag_mri = 1;
+#ifdef TC_M68K
+      flag_m68k_mri = 1;
+#endif
+    }
+  else
+    {
+      flag_mri = 0;
+      flag_m68k_mri = 0;
+    }
+
+#ifdef MRI_MODE_CHANGE
+  if (on != old_flag)
+    MRI_MODE_CHANGE (on);
+#endif
+
+  demand_empty_rest_of_line ();
+}
+
 /* Handle changing the location counter.  */
 
 static void
@@ -1779,10 +2150,10 @@ s_org (ignore)
   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)
+  /* The m68k MRI assembler has a different meaning for .org.  It
+     means to create an absolute section at a given address.  We can't
+     support that--use a linker script instead.  */
+  if (flag_m68k_mri)
     {
       as_bad ("MRI style ORG pseudo-op not supported");
       ignore_rest_of_line ();
@@ -1819,14 +2190,16 @@ s_org (ignore)
 /* 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 '\0' (unspecified), 'C'
-   (code), 'D' (data), 'M' (mixed), or 'R' (romable).  If
-   BFD_ASSEMBLER is defined, the flags will be set in the section.  */
+   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
+   'M' (mixed), or 'R' (romable).  If BFD_ASSEMBLER is defined, the
+   flags will be set in the section.  */
 
 void
 s_mri_sect (type)
      char *type;
 {
+#ifdef TC_M68K
+
   char *name;
   char c;
   segT seg;
@@ -1847,9 +2220,7 @@ s_mri_sect (type)
       *input_line_pointer = '\0';
     }
 
-  name = strdup (name);
-  if (name == NULL)
-    as_fatal ("virtual memory exhausted");
+  name = xstrdup (name);
 
   *input_line_pointer = c;
 
@@ -1864,7 +2235,7 @@ s_mri_sect (type)
       record_alignment (seg, align);
     }
 
-  *type = '\0';
+  *type = 'C';
   if (*input_line_pointer == ',')
     {
       c = *++input_line_pointer;
@@ -1881,11 +2252,11 @@ s_mri_sect (type)
 
        flags = SEC_NO_FLAGS;
        if (*type == 'C')
-         flags = SEC_CODE;
-       else if (*type == 'D')
-         flags = SEC_DATA;
+         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_ROM;
+         flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
        if (flags != SEC_NO_FLAGS)
          {
            if (! bfd_set_section_flags (stdoutput, seg, flags))
@@ -1902,6 +2273,130 @@ s_mri_sect (type)
     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.  */
+  abort ();
+#endif /* ! TC_I960 */
+#endif /* ! TC_M68K */
+}
+
+/* Handle the .print pseudo-op.  */
+
+void
+s_print (ignore)
+     int ignore;
+{
+  char *s;
+  int len;
+
+  s = demand_copy_C_string (&len);
+  printf ("%s\n", s);
+  demand_empty_rest_of_line ();
+}
+
+/* Handle the .purgem pseudo-op.  */
+
+void
+s_purgem (ignore)
+     int ignore;
+{
+  if (is_it_end_of_statement ())
+    {
+      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.  */
@@ -2004,83 +2499,112 @@ s_space (mult)
      int mult;
 {
   expressionS exp;
-  long temp_fill;
+  expressionS val;
   char *p = 0;
+  char *stop = NULL;
+  char stopc;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
-  /* Just like .fill, but temp_size = 1 */
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
+
   expression (&exp);
-  if (exp.X_op == O_constant)
-    {
-      long repeat;
 
-      repeat = exp.X_add_number;
-      if (mult)
-       repeat *= mult;
-      if (repeat <= 0)
-       {
-         if (! flag_mri || repeat < 0)
-           as_warn (".space repeat count is %s, ignored",
-                    repeat ? "negative" : "zero");
-         ignore_rest_of_line ();
-         return;
-       }
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer == ',')
+    {
+      ++input_line_pointer;
+      expression (&val);
+    }
+  else
+    {
+      val.X_op = O_constant;
+      val.X_add_number = 0;
+    }
 
-      /* If we are in the absolute section, just bump the offset.  */
-      if (now_seg == absolute_section)
+  if (val.X_op != O_constant
+      || val.X_add_number < - 0x80
+      || val.X_add_number > 0xff
+      || (mult != 0 && mult != 1 && val.X_add_number != 0))
+    {
+      if (exp.X_op != O_constant)
+       as_bad ("Unsupported variable size or fill value");
+      else
        {
-         abs_section_offset += repeat;
-         demand_empty_rest_of_line ();
-         return;
-       }
+         offsetT i;
 
-      /* 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);
-         demand_empty_rest_of_line ();
-         return;
+         if (mult == 0)
+           mult = 1;
+         for (i = 0; i < exp.X_add_number; i++)
+           emit_expr (&val, mult);
        }
-
-      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)
+      if (exp.X_op == O_constant)
        {
-         as_bad ("space allocation too complex in absolute section");
-         subseg_set (text_section, 0);
+         long repeat;
+
+         repeat = exp.X_add_number;
+         if (mult)
+           repeat *= mult;
+         if (repeat <= 0)
+           {
+             if (! flag_mri || repeat < 0)
+               as_warn (".space repeat count is %s, ignored",
+                        repeat ? "negative" : "zero");
+             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,
+                         repeat, (char *) 0);
        }
-      if (mri_common_symbol != NULL)
+      else
        {
-         as_bad ("space allocation too complex in common section");
-         mri_common_symbol = NULL;
+         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), 0L, (char *) 0);
        }
-      if (!need_pass_2)
-       p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
-                     make_expr_symbol (&exp), 0L, (char *) 0);
-    }
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer == ',')
-    {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-    }
-  else
-    {
-      temp_fill = 0;
-    }
-  if (p)
-    {
-      *p = temp_fill;
+
+      if (p)
+       *p = val.X_add_number;
     }
+
+ getout:
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -2095,6 +2619,11 @@ s_float_space (float_type)
   offsetT count;
   int flen;
   char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   count = get_absolute_expression ();
 
@@ -2102,6 +2631,8 @@ s_float_space (float_type)
   if (*input_line_pointer != ',')
     {
       as_bad ("missing value");
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -2122,6 +2653,8 @@ s_float_space (float_type)
       flen = hex_float (float_type, temp);
       if (flen < 0)
        {
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -2136,6 +2669,8 @@ s_float_space (float_type)
       if (err)
        {
          as_bad ("Bad floating literal: %s", err);
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -2149,6 +2684,9 @@ s_float_space (float_type)
       memcpy (p, temp, (unsigned int) flen);
     }
 
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -2158,8 +2696,15 @@ void
 s_struct (ignore)
      int ignore;
 {
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
   abs_section_offset = get_absolute_expression ();
   subseg_set (absolute_section, 0);
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
   demand_empty_rest_of_line ();
 }
 
@@ -2362,19 +2907,27 @@ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
 /* worker to do .byte etc statements */
 /* clobbers input_line_pointer, checks */
 /* end-of-line. */
-void 
-cons (nbytes)
+static void 
+cons_worker (nbytes, rva)
      register int nbytes;      /* 1=.byte, 2=.word, 4=.long */
+     int rva;
 {
   int c;
   expressionS exp;
+  char *stop = NULL;
+  char stopc;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
 
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
+
   if (is_it_end_of_statement ())
     {
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       demand_empty_rest_of_line ();
       return;
     }
@@ -2382,10 +2935,18 @@ cons (nbytes)
   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);
+
+      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;
     }
@@ -2398,9 +2959,29 @@ cons (nbytes)
     mri_pending_align = 1;
 
   input_line_pointer--;                /* Put terminator back into stream. */
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
+
+void
+cons (size)
+     int size;
+{
+  cons_worker (size, 0);
+}
+
+void 
+s_rva (size)
+     int size;
+{
+  cons_worker (size, 1);
+}
+
+
 /* Put the contents of expression EXP into the object file using
    NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
 
@@ -2625,8 +3206,8 @@ emit_expr (exp, nbytes)
       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);
+                     : nbytes == 8 ? BFD_RELOC_64
+                     : BFD_RELOC_32);
 #endif
 #else
 #ifdef TC_CONS_FIX_NEW
@@ -3358,9 +3939,7 @@ demand_copy_C_string (len_pointer)
     {
       register int len;
 
-      for (len = *len_pointer;
-          len > 0;
-          len--)
+      for (len = *len_pointer; len > 0; len--)
        {
          if (*s == 0)
            {
@@ -3371,7 +3950,7 @@ demand_copy_C_string (len_pointer)
            }
        }
     }
-  return (s);
+  return s;
 }
 \f
 /*
@@ -3399,8 +3978,8 @@ demand_copy_string (lenP)
          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);
     }
@@ -3435,6 +4014,8 @@ equals (sym_name)
      char *sym_name;
 {
   register symbolS *symbolP;   /* symbol we are working with */
+  char *stop;
+  char stopc;
 
   input_line_pointer++;
   if (*input_line_pointer == '=')
@@ -3443,6 +4024,9 @@ equals (sym_name)
   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 */
@@ -3458,6 +4042,9 @@ equals (sym_name)
       symbolP = symbol_find_or_make (sym_name);
       pseudo_set (symbolP);
     }
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
 }                              /* equals() */
 
 /* .include -- include a file at this point. */
@@ -3473,7 +4060,7 @@ s_include (arg)
   FILE *try;
   char *path;
 
-  if (! flag_mri)
+  if (! flag_m68k_mri)
     filename = demand_copy_string (&i);
   else
     {
@@ -3489,6 +4076,8 @@ s_include (arg)
        }
       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 */ );
@@ -3549,4 +4138,11 @@ s_ignore (arg)
 }
 
 
+void
+read_print_statistics (file)
+     FILE *file;
+{
+  hash_print_statistics (file, "pseudo-op table", po_hash);
+}
+
 /* end of read.c */
This page took 0.0479349999999999 seconds and 4 git commands to generate.