]> Git Repo - binutils.git/blobdiff - gas/read.c
Sun Mar 23 18:03:31 1997 Martin M. Hunt <[email protected]>
[binutils.git] / gas / read.c
index c8ea2eb7c1d9e23f51400569e13df7d4fe6b4181..450046b83fc3381febabf90a9918ba18d681fee3 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
+   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 1997
    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
-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
@@ -44,9 +45,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 #include "subsegs.h"
 #include "sb.h"
 #include "macro.h"
-#include "libiberty.h"
 #include "obstack.h"
 #include "listing.h"
+#include "ecoff.h"
 
 #ifndef TC_START_LABEL
 #define TC_START_LABEL(x,y) (x==':')
@@ -95,6 +96,11 @@ die horribly;
 #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] =
 {
@@ -105,7 +111,7 @@ char lex_type[256] =
   LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,      /* `abcdefghijklmno */
-  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 0, /* pqrstuvwxyz{|}~. */
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -153,17 +159,9 @@ char is_end_of_line[256] =
 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;
-#else
-int target_big_endian /* = 0 */;
-#endif
 
 static char *old_buffer;       /* JF a hack */
 static char *old_input;
@@ -201,12 +199,13 @@ symbolS *mri_common_symbol;
    may be needed.  */
 static int mri_pending_align;
 
+static void cons_worker PARAMS ((int, int));
 static int scrub_from_string PARAMS ((char **));
-static void do_align PARAMS ((int, char *, int));
+static void do_align PARAMS ((int, char *, int, int));
+static void s_align PARAMS ((int, int));
 static int hex_float PARAMS ((int, char *));
 static void do_org PARAMS ((segT, expressionS *, int));
 char *demand_copy_string PARAMS ((int *lenP));
-int is_it_end_of_statement PARAMS ((void));
 static segT get_segmented_expression PARAMS ((expressionS *expP));
 static segT get_known_segmented_expression PARAMS ((expressionS * expP));
 static void pobegin PARAMS ((void));
@@ -327,6 +326,7 @@ static const pseudo_typeS potable[] =
   {"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},
@@ -362,6 +362,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'},
@@ -525,13 +526,16 @@ read_a_source_file (name)
                    {
                      char *line_start = input_line_pointer;
                      char c;
+                     int mri_line_macro;
 
+                     LISTING_NEWLINE ();
                      HANDLE_CONDITIONAL_ASSEMBLY ();
 
                      c = get_symbol_end ();
 
-                     /* In MRI mode, the EQU pseudoop must be
-                        handled specially.  */
+                     /* In MRI mode, the EQU and MACRO pseudoops must
+                        be handled specially.  */
+                     mri_line_macro = 0;
                      if (flag_m68k_mri)
                        {
                          char *rest = input_line_pointer + 1;
@@ -545,12 +549,27 @@ read_a_source_file (name)
                              && (rest[3] == ' ' || rest[3] == '\t'))
                            {
                              input_line_pointer = rest + 3;
-                             equals (line_start);
+                             equals (line_start,
+                                     strncasecmp (rest, "SET", 3) == 0);
                              continue;
                            }
+                         if (strncasecmp (rest, "MACRO", 5) == 0
+                             && (rest[5] == ' '
+                                 || rest[5] == '\t'
+                                 || is_end_of_line[(unsigned char) rest[5]]))
+                           mri_line_macro = 1;
                        }
 
-                     line_label = colon (line_start);
+                     /* In MRI mode, we need to handle the MACRO
+                         pseudo-op specially: we don't want to put the
+                         symbol in the symbol table.  */
+                     if (! mri_line_macro)
+                       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 == ':')
@@ -617,7 +636,7 @@ read_a_source_file (name)
                          && (rest[3] == ' ' || rest[3] == '\t'))
                        {
                          input_line_pointer = rest + 3;
-                         equals (s);
+                         equals (s, 1);
                          continue;
                        }
                    }
@@ -630,13 +649,14 @@ read_a_source_file (name)
 
                }
              else if (c == '='
-                      || (input_line_pointer[1] == '='
+                      || ((c == ' ' || c == '\t')
+                          && input_line_pointer[1] == '='
 #ifdef TC_EQUAL_IN_INSN
                           && ! TC_EQUAL_IN_INSN (c, input_line_pointer)
 #endif
                           ))
                {
-                 equals (s);
+                 equals (s, 1);
                  demand_empty_rest_of_line ();
                }
              else
@@ -691,10 +711,26 @@ read_a_source_file (name)
                              || ! ((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, 0);
+                         do_align (1, (char *) NULL, 0, 0);
                          mri_pending_align = 0;
+                         if (line_label != NULL)
+                           {
+                             line_label->sy_frag = frag_now;
+                             S_SET_VALUE (line_label, frag_now_fix ());
+                           }
                        }
 
                      /* Print the error msg now, while we still can */
@@ -725,15 +761,9 @@ read_a_source_file (name)
                        goto quit;
                    }
                  else
-                   {           /* machine instruction */
+                   {
                      int inquote = 0;
 
-                     if (mri_pending_align)
-                       {
-                         do_align (1, (char *) NULL, 0);
-                         mri_pending_align = 0;
-                       }
-
                      /* WARNING: c has char, which may be end-of-line. */
                      /* Also: input_line_pointer->`\0` where c was. */
                      *input_line_pointer = c;
@@ -787,6 +817,17 @@ read_a_source_file (name)
                            }
                        }
 
+                     if (mri_pending_align)
+                       {
+                         do_align (1, (char *) NULL, 0, 0);
+                         mri_pending_align = 0;
+                         if (line_label != NULL)
+                           {
+                             line_label->sy_frag = frag_now;
+                             S_SET_VALUE (line_label, frag_now_fix ());
+                           }
+                       }
+
                      md_assemble (s);  /* Assemble 1 instruction. */
 
                      *input_line_pointer++ = c;
@@ -973,6 +1014,10 @@ read_a_source_file (name)
     }                          /* while (more buffers to scan) */
 
  quit:
+
+#ifdef md_cleanup
+  md_cleanup();
+#endif
   input_scrub_close ();                /* Close the input file */
 }
 
@@ -1043,40 +1088,43 @@ s_abort (ignore)
   as_fatal (".abort detected.  Abandoning ship.");
 }
 
-/* Guts of .align directive.  */
+/* Guts of .align directive.  N is the power of two to which to align.
+   FILL may be NULL, or it may point to the bytes of the fill pattern.
+   LEN is the length of whatever FILL points to, if anything.  MAX is
+   the maximum number of characters to skip when doing the alignment,
+   or 0 if there is no maximum.  */
+
 static void 
-do_align (n, fill, len)
+do_align (n, fill, len, max)
      int n;
      char *fill;
      int len;
+     int max;
 {
+  char default_fill;
+
 #ifdef md_do_align
-  md_do_align (n, fill, len, just_record_alignment);
+  md_do_align (n, fill, len, max, just_record_alignment);
 #endif
-  if (!fill)
-    {
-      /* @@ Fix this right for BFD!  */
-      static char zero;
-      static char nop_opcode = NOP_OPCODE;
 
+  if (fill == NULL)
+    {
+      /* FIXME: Fix this right for BFD!  */
       if (now_seg != data_section && now_seg != bss_section)
-       {
-         fill = &nop_opcode;
-       }
+       default_fill = NOP_OPCODE;
       else
-       {
-         fill = &zero;
-       }
+       default_fill = 0;
+      fill = &default_fill;
       len = 1;
     }
 
   /* Only make a frag if we HAVE to. . . */
-  if (n && !need_pass_2)
+  if (n != 0 && !need_pass_2)
     {
       if (len <= 1)
-       frag_align (n, *fill);
+       frag_align (n, *fill, max);
       else
-       frag_align_pattern (n, fill, len);
+       frag_align_pattern (n, fill, len, max);
     }
 
 #ifdef md_do_align
@@ -1086,17 +1134,22 @@ do_align (n, fill, len)
   record_alignment (now_seg, n);
 }
 
-/* For machines where ".align 4" means align to a 4 byte boundary. */
-void 
-s_align_bytes (arg)
+/* Handle the .align pseudo-op.  A positive ARG is a default alignment
+   (in bytes).  A negative ARG is the negative of the length of the
+   fill pattern.  BYTES_P is non-zero if the alignment value should be
+   interpreted as the byte boundary, rather than the power of 2.  */
+
+static void
+s_align (arg, bytes_p)
      int arg;
+     int bytes_p;
 {
-  register unsigned int temp;
-  char temp_fill;
-  unsigned int i = 0;
-  unsigned long max_alignment = 1 << 15;
+  register unsigned int align;
   char *stop = NULL;
   char stopc;
+  offsetT fill = 0;
+  int max;
+  int fill_p;
 
   if (flag_mri)
     stop = mri_comment_field (&stopc);
@@ -1104,122 +1157,94 @@ s_align_bytes (arg)
   if (is_end_of_line[(unsigned char) *input_line_pointer])
     {
       if (arg < 0)
-       temp = 0;
+       align = 0;
       else
-       temp = arg;     /* Default value from pseudo-op table */
+       align = arg;    /* Default value from pseudo-op table */
     }
   else
-    temp = get_absolute_expression ();
-
-  if (temp > max_alignment)
     {
-      as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
+      align = get_absolute_expression ();
+      SKIP_WHITESPACE ();
     }
 
-  /* For the sparc, `.align (1<<n)' actually means `.align n' so we
-     have to convert it.  */
-  if (temp != 0)
+  if (bytes_p)
     {
-      for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
-       ;
+      /* Convert to a power of 2.  */
+      if (align != 0)
+       {
+         unsigned int i;
+
+         for (i = 0; (align & 1) == 0; align >>= 1, ++i)
+           ;
+         if (align != 1)
+           as_bad ("Alignment not a power of 2");
+         align = i;
+       }
     }
-  if (temp != 1)
-    as_bad ("Alignment not a power of 2");
 
-  temp = i;
-  if (*input_line_pointer == ',')
+  if (align > 15)
     {
-      offsetT fillval;
-      int len;
+      align = 15;
+      as_bad ("Alignment too large: %u assumed", align);
+    }
 
-      input_line_pointer++;
-      fillval = get_absolute_expression ();
-      if (arg >= 0)
-       len = 1;
+  if (*input_line_pointer != ',')
+    {
+      fill_p = 0;
+      max = 0;
+    }
+  else
+    {
+      ++input_line_pointer;
+      if (*input_line_pointer == ',')
+       fill_p = 0;
       else
-       len = - arg;
-      if (len <= 1)
        {
-         temp_fill = fillval;
-         do_align (temp, &temp_fill, len);
+         fill = get_absolute_expression ();
+         SKIP_WHITESPACE ();
+         fill_p = 1;
        }
+
+      if (*input_line_pointer != ',')
+       max = 0;
       else
        {
-         char ab[16];
-
-         if (len > sizeof ab)
-           abort ();
-         md_number_to_chars (ab, fillval, len);
-         do_align (temp, ab, len);
+         ++input_line_pointer;
+         max = get_absolute_expression ();
        }
     }
-  else
+
+  if (! fill_p)
     {
       if (arg < 0)
        as_warn ("expected fill pattern missing");
-      do_align (temp, (char *) NULL, 0);
-    }
-
-  if (flag_mri)
-    mri_comment_end (stop, stopc);
-
-  demand_empty_rest_of_line ();
-}
-
-/* For machines where ".align 4" means align to 2**4 boundary. */
-void 
-s_align_ptwo (arg)
-     int arg;
-{
-  register int temp;
-  char temp_fill;
-  long max_alignment = 15;
-  char *stop = NULL;
-  char stopc;
-
-  if (flag_mri)
-    stop = mri_comment_field (&stopc);
-
-  temp = get_absolute_expression ();
-  if (temp > max_alignment)
-    as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
-  else if (temp < 0)
-    {
-      as_bad ("Alignment negative. 0 assumed.");
-      temp = 0;
+      do_align (align, (char *) NULL, 0, max);
     }
-  if (*input_line_pointer == ',')
+  else
     {
-      offsetT fillval;
-      int len;
+      int fill_len;
 
-      input_line_pointer++;
-      fillval = get_absolute_expression ();
       if (arg >= 0)
-       len = 1;
+       fill_len = 1;
       else
-       len = - arg;
-      if (len <= 1)
+       fill_len = - arg;
+      if (fill_len <= 1)
        {
-         temp_fill = fillval;
-         do_align (temp, &temp_fill, len);
+         char fill_char;
+
+         fill_char = fill;
+         do_align (align, &fill_char, fill_len, max);
        }
       else
        {
          char ab[16];
 
-         if (len > sizeof ab)
+         if (fill_len > sizeof ab)
            abort ();
-         md_number_to_chars (ab, fillval, len);
-         do_align (temp, ab, len);
+         md_number_to_chars (ab, fill, fill_len);
+         do_align (align, ab, fill_len, max);
        }
     }
-  else
-    {
-      if (arg < 0)
-       as_warn ("expected fill pattern missing");
-      do_align (temp, (char *) NULL, 0);
-    }
 
   if (flag_mri)
     mri_comment_end (stop, stopc);
@@ -1227,6 +1252,26 @@ s_align_ptwo (arg)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .align pseudo-op on machines where ".align 4" means
+   align to a 4 byte boundary.  */
+
+void 
+s_align_bytes (arg)
+     int arg;
+{
+  s_align (arg, 1);
+}
+
+/* Handle the .align pseud-op on machines where ".align 4" means align
+   to a 2**4 boundary.  */
+
+void 
+s_align_ptwo (arg)
+     int arg;
+{
+  s_align (arg, 0);
+}
+
 void 
 s_comm (ignore)
      int ignore;
@@ -1595,7 +1640,8 @@ s_fill (ignore)
     }
   else if (temp_repeat <= 0)
     {
-      as_warn ("Repeat < 0, .fill ignored");
+      if (temp_repeat < 0)
+       as_warn ("Repeat < 0, .fill ignored");
       temp_size = 0;
     }
 
@@ -1689,6 +1735,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
@@ -1742,6 +1865,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
@@ -1757,6 +1885,11 @@ s_lcomm (needs_align)
        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);
      }
 
@@ -1793,7 +1926,7 @@ s_lcomm (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;
@@ -1820,7 +1953,7 @@ s_lcomm (needs_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)
        symbolP->sy_frag->fr_symbol = NULL;
@@ -1923,6 +2056,11 @@ 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);
@@ -1930,16 +2068,39 @@ get_line_sb (line)
        return 0;
     }
 
-  while (! is_end_of_line[(unsigned char) *input_line_pointer])
-    sb_add_char (line, *input_line_pointer++);
-  while (input_line_pointer < buffer_limit
-        && is_end_of_line[(unsigned char) *input_line_pointer])
+  /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
+     code needs to be changed.  */
+  if (! flag_m68k_mri)
+    quote1 = '"';
+  else
+    quote1 = '\0';
+
+  quote2 = '\0';
+  if (flag_m68k_mri)
+    quote2 = '\'';
+#ifdef LEX_IS_STRINGQUOTE
+  quote2 = '\'';
+#endif
+
+  inquote = '\0';
+  while (! is_end_of_line[(unsigned char) *input_line_pointer]
+        || (inquote != '\0' && *input_line_pointer != '\n'))
     {
-      if (*input_line_pointer == '\n')
+      if (inquote == *input_line_pointer)
+       inquote = '\0';
+      else if (inquote == '\0')
        {
-         bump_line_counters ();
-         LISTING_NEWLINE ();
+         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 && *input_line_pointer == '\n')
+    {
+      if (input_line_pointer[-1] == '\n')
+       bump_line_counters ();
       ++input_line_pointer;
     }
   return 1;
@@ -1957,6 +2118,7 @@ s_macro (ignore)
   sb s;
   sb label;
   const char *err;
+  const char *name;
 
   as_where (&file, &line);
 
@@ -1968,9 +2130,7 @@ 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);
+  err = define_macro (0, &s, &label, get_line_sb, &name);
   if (err != NULL)
     as_bad_where (file, line, "%s", err);
   else
@@ -1981,6 +2141,18 @@ s_macro (ignore)
          S_SET_VALUE (line_label, 0);
          line_label->sy_frag = &zero_address_frag;
        }
+
+      if (((flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+           || 1
+#endif
+           )
+          && hash_find (po_hash, name) != NULL)
+         || (! flag_m68k_mri
+             && *name == '.'
+             && hash_find (po_hash, name + 1) != NULL))
+       as_warn ("attempt to redefine pseudo-op `%s' ignored",
+                name);
     }
 
   sb_kill (&s);
@@ -2417,10 +2589,11 @@ s_space (mult)
      int mult;
 {
   expressionS exp;
-  long temp_fill;
+  expressionS val;
   char *p = 0;
   char *stop = NULL;
   char stopc;
+  int bytes;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
@@ -2429,75 +2602,145 @@ s_space (mult)
   if (flag_mri)
     stop = mri_comment_field (&stopc);
 
-  /* Just like .fill, but temp_size = 1 */
-  expression (&exp);
-  if (exp.X_op == O_constant)
+  /* In m68k MRI mode, we need to align to a word boundary, unless
+     this is ds.b.  */
+  if (flag_m68k_mri && mult > 1)
     {
-      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;
+         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);
-         goto getout;
-       }
+         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)
+               {
+                 know (line_label->sy_value.X_op == O_symbol);
+                 know (line_label->sy_value.X_add_symbol == mri_common_symbol);
+                 line_label->sy_value.X_add_number += 1;
+               }
+           }
        }
-      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)
+           {
+             line_label->sy_frag = 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 == ',')
     {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
+      ++input_line_pointer;
+      expression (&val);
     }
   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 || 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);
+       }
+      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), 0L, (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;
+
   if (flag_mri)
     mri_comment_end (stop, stopc);
 
@@ -2828,6 +3071,10 @@ cons_worker (nbytes, rva)
       return;
     }
 
+#ifdef md_cons_align
+  md_cons_align (nbytes);
+#endif
+
   c = 0;
   do
     {
@@ -3005,14 +3252,25 @@ emit_expr (exp, nbytes)
       register valueT get;
       register valueT use;
       register valueT mask;
+      valueT hibit;
       register valueT unmask;
 
       /* JF << of >= number of bits in the object is undefined.  In
         particular SPARC (Sun 4) has problems */
       if (nbytes >= sizeof (valueT))
-       mask = 0;
+       {
+         mask = 0;
+         if (nbytes > sizeof (valueT))
+           hibit = 0;
+         else
+           hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+       }
       else
-       mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
+       {
+         /* Don't store these bits. */
+         mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
+         hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+       }
 
       unmask = ~mask;          /* Do store these bits. */
 
@@ -3023,9 +3281,12 @@ emit_expr (exp, nbytes)
 
       get = exp->X_add_number;
       use = get & unmask;
-      if ((get & mask) != 0 && (get & mask) != mask)
+      if ((get & mask) != 0
+         && ((get & mask) != mask
+             || (get & hibit) == 0))
        {               /* Leading bits contain both 0s & 1s. */
-         as_warn ("Value 0x%lx truncated to 0x%lx.", get, use);
+         as_warn ("Value 0x%lx truncated to 0x%lx.",
+                  (unsigned long) get, (unsigned long) use);
        }
       /* put bytes in right order. */
       md_number_to_chars (p, use, (int) nbytes);
@@ -3099,11 +3360,31 @@ emit_expr (exp, nbytes)
 #ifdef TC_CONS_FIX_NEW
       TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
 #else
-      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
-                  /* @@ Should look at CPU word size.  */
-                  nbytes == 2 ? BFD_RELOC_16
-                     : nbytes == 8 ? BFD_RELOC_64
-                     : BFD_RELOC_32);
+      {
+       bfd_reloc_code_real_type r;
+
+       switch (nbytes)
+         {
+         case 1:
+           r = BFD_RELOC_8;
+           break;
+         case 2:
+           r = BFD_RELOC_16;
+           break;
+         case 4:
+           r = BFD_RELOC_32;
+           break;
+         case 8:
+           r = BFD_RELOC_64;
+           break;
+         default:
+           as_bad ("unsupported BFD relocation size %u", nbytes);
+           r = BFD_RELOC_32;
+           break;
+         }
+       fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
+                    0, r);
+      }
 #endif
 #else
 #ifdef TC_CONS_FIX_NEW
@@ -3484,6 +3765,10 @@ float_cons (float_type)
       return;
     }
 
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
   do
     {
       /* input_line_pointer->1st char of a flonum (we hope!). */
@@ -3651,6 +3936,11 @@ next_char_of_string ()
       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++)
@@ -3732,6 +4022,7 @@ next_char_of_string ()
          /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
          as_warn ("Unterminated string: Newline inserted.");
          c = '\n';
+         bump_line_counters ();
          break;
 
        default:
@@ -3906,8 +4197,9 @@ is_it_end_of_statement ()
 }                              /* is_it_end_of_statement() */
 
 void 
-equals (sym_name)
+equals (sym_name, reassign)
      char *sym_name;
+     int reassign;
 {
   register symbolS *symbolP;   /* symbol we are working with */
   char *stop;
@@ -3936,6 +4228,11 @@ equals (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);
     }
 
This page took 0.061254 seconds and 4 git commands to generate.