gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gas / read.c
index e992534bce7ab7c854a26f5da951ee98d3bc7966..8f93c2ba2b461a22440889e67875fb40a34275f4 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986-2016 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -19,7 +19,7 @@
    02110-1301, USA.  */
 
 /* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF).
-   But then, GNU isn't spozed to run on your machine anyway.
+   But then, GNU isn't supposed to run on your machine anyway.
    (RMS is so shortsighted sometimes.)  */
 #define MASK_CHAR ((int)(unsigned char) -1)
 
@@ -62,6 +62,7 @@
 #endif
 
 char *input_line_pointer;      /*->next char of source file to parse.  */
+bfd_boolean input_from_string = FALSE;
 
 #if BITS_PER_CHAR != 8
 /*  The following table is indexed by[(char)] and will break if
@@ -166,7 +167,7 @@ int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
 /* Variables for handling include file directory table.  */
 
 /* Table of pointers to directories to search for .include's.  */
-char **include_dirs;
+const char **include_dirs;
 
 /* How many are in the table.  */
 int include_dir_count;
@@ -416,6 +417,7 @@ static const pseudo_typeS potable[] = {
   {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off.  */
   {"nopage", listing_nopage, 0},
+  {"nops", s_nops, 0},
   {"octa", cons, 16},
   {"offset", s_struct, 0},
   {"org", s_org, 0},
@@ -713,19 +715,19 @@ assemble_one (char *line)
       /* Make sure this hasn't pushed the locked sequence
         past the bundle size.  */
       unsigned int bundle_size = pending_bundle_size (bundle_lock_frag);
-      if (bundle_size > (1U << bundle_align_p2))
-       as_bad (_("\
-.bundle_lock sequence at %u bytes but .bundle_align_mode limit is %u bytes"),
+      if (bundle_size > 1U << bundle_align_p2)
+       as_bad (_ (".bundle_lock sequence at %u bytes, "
+                  "but .bundle_align_mode limit is %u bytes"),
                bundle_size, 1U << bundle_align_p2);
     }
   else if (bundle_align_p2 > 0)
     {
       unsigned int insn_size = pending_bundle_size (insn_start_frag);
 
-      if (insn_size > (1U << bundle_align_p2))
-       as_bad (_("\
-single instruction is %u bytes long but .bundle_align_mode limit is %u"),
-               (unsigned int) insn_size, 1U << bundle_align_p2);
+      if (insn_size > 1U << bundle_align_p2)
+       as_bad (_("single instruction is %u bytes long, "
+                 "but .bundle_align_mode limit is %u bytes"),
+               insn_size, 1U << bundle_align_p2);
 
       finish_bundle (insn_start_frag, insn_size);
     }
@@ -740,7 +742,7 @@ single instruction is %u bytes long but .bundle_align_mode limit is %u"),
 static bfd_boolean
 in_bss (void)
 {
-  flagword flags = bfd_get_section_flags (stdoutput, now_seg);
+  flagword flags = bfd_section_flags (now_seg);
 
   return (flags & SEC_ALLOC) && !(flags & (SEC_LOAD | SEC_HAS_CONTENTS));
 }
@@ -754,7 +756,7 @@ in_bss (void)
    MAX is the maximum number of characters to skip when doing the alignment,
     or 0 if there is no maximum.  */
 
-static void
+void
 do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
 {
   if (now_seg == absolute_section || in_bss ())
@@ -809,7 +811,7 @@ do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
 /* We read the file, putting things into a web that represents what we
    have been reading.  */
 void
-read_a_source_file (char *name)
+read_a_source_file (const char *name)
 {
   char nul_char;
   char next_char;
@@ -879,7 +881,7 @@ read_a_source_file (char *name)
                      /* Copy it for safe keeping.  Also give an indication of
                         how much macro nesting is involved at this point.  */
                      len = s - input_line_pointer;
-                     copy = (char *) xmalloc (len + macro_nest + 2);
+                     copy = XNEWVEC (char, len + macro_nest + 2);
                      memset (copy, '>', macro_nest);
                      copy[macro_nest] = ' ';
                      memcpy (copy + macro_nest + 1, input_line_pointer, len);
@@ -1050,7 +1052,8 @@ read_a_source_file (char *name)
                  {
                    char *s2 = s;
 
-                   strncpy (original_case_string, s2, sizeof (original_case_string));
+                   strncpy (original_case_string, s2,
+                            sizeof (original_case_string) - 1);
                    original_case_string[sizeof (original_case_string) - 1] = 0;
 
                    while (*s2)
@@ -1271,7 +1274,7 @@ read_a_source_file (char *name)
                     that goes with this #APP  There is one.  The specs
                     guarantee it...  */
                  tmp_len = buffer_limit - s;
-                 tmp_buf = (char *) xmalloc (tmp_len + 1);
+                 tmp_buf = XNEWVEC (char, tmp_len + 1);
                  memcpy (tmp_buf, s, tmp_len);
                  do
                    {
@@ -1287,7 +1290,7 @@ read_a_source_file (char *name)
                      else
                        num = buffer_limit - buffer;
 
-                     tmp_buf = (char *) xrealloc (tmp_buf, tmp_len + num);
+                     tmp_buf = XRESIZEVEC (char, tmp_buf, tmp_len + num);
                      memcpy (tmp_buf + tmp_len, buffer, num);
                      tmp_len += num;
                    }
@@ -1308,7 +1311,7 @@ read_a_source_file (char *name)
              scrub_string_end = ends;
 
              new_length = ends - s;
-             new_buf = (char *) xmalloc (new_length);
+             new_buf = XNEWVEC (char, new_length);
              new_tmp = new_buf;
              for (;;)
                {
@@ -1324,13 +1327,12 @@ read_a_source_file (char *name)
                      break;
                    }
 
-                 new_buf = (char *) xrealloc (new_buf, new_length + 100);
+                 new_buf = XRESIZEVEC (char, new_buf, new_length + 100);
                  new_tmp = new_buf + new_length;
                  new_length += 100;
                }
 
-             if (tmp_buf)
-               free (tmp_buf);
+             free (tmp_buf);
 
              /* We've "scrubbed" input to the preferred format.  In the
                 process we may have consumed the whole of the remaining
@@ -1657,7 +1659,7 @@ read_symbol_name (void)
       char * name_end;
       unsigned int C;
 
-      start = name = xmalloc (len + 1);
+      start = name = XNEWVEC (char, len + 1);
 
       name_end = name + SYM_NAME_CHUNK_LEN;
 
@@ -1669,7 +1671,7 @@ read_symbol_name (void)
 
              sofar = name - start;
              len += SYM_NAME_CHUNK_LEN;
-             start = xrealloc (start, len + 1);
+             start = XRESIZEVEC (char, start, len + 1);
              name_end = start + len;
              name = start + sofar;
            }
@@ -1684,20 +1686,20 @@ read_symbol_name (void)
       if (mbstowcs (NULL, name, len) == (size_t) -1)
        as_warn (_("symbol name not recognised in the current locale"));
     }
-  else if (is_name_beginner (c) || c == '\001')
+  else if (is_name_beginner (c) || (input_from_string && c == FAKE_LABEL_CHAR))
     {
       ptrdiff_t len;
 
       name = input_line_pointer - 1;
 
-      /* We accept \001 in a name in case this is
+      /* We accept FAKE_LABEL_CHAR in a name in case this is
         being called with a constructed string.  */
       while (is_part_of_name (c = *input_line_pointer++)
-            || c == '\001')
+            || (input_from_string && c == FAKE_LABEL_CHAR))
        ;
 
       len = (input_line_pointer - name) - 1;
-      start = xmalloc (len + 1);
+      start = XNEWVEC (char, len + 1);
 
       memcpy (start, name, len);
       start[len] = 0;
@@ -1798,8 +1800,7 @@ s_comm_internal (int param,
  out:
   if (flag_mri)
     mri_comment_end (stop, stopc);
-  if (name != NULL)
-    free (name);
+  free (name);
   return symbolP;
 }
 
@@ -1850,9 +1851,8 @@ s_mri_common (int small ATTRIBUTE_UNUSED)
 
       if (line_label != NULL)
        {
-         alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
-                                 + (input_line_pointer - name)
-                                 + 1);
+         alc = XNEWVEC (char, strlen (S_GET_NAME (line_label))
+                        + (input_line_pointer - name) + 1);
          sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
          name = alc;
        }
@@ -1860,8 +1860,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED)
 
   sym = symbol_find_or_make (name);
   c = restore_line_pointer (c);
-  if (alc != NULL)
-    free (alc);
+  free (alc);
 
   if (*input_line_pointer != ',')
     align = 0;
@@ -2137,7 +2136,7 @@ s_errwarn (int err)
      self-contained message, one that can be passed like the
      demand_copy_C_string return value, and with no assumption on the
      location of the name of the directive within the message.  */
-  char *msg
+  const char *msg
     = (err ? _(".error directive invoked in source file")
        : _(".warning directive invoked in source file"));
 
@@ -2203,7 +2202,7 @@ s_fill (int ignore ATTRIBUTE_UNUSED)
   md_cons_align (1);
 #endif
 
-  get_known_segmented_expression (&rep_exp);
+  expression (&rep_exp);
   if (*input_line_pointer == ',')
     {
       input_line_pointer++;
@@ -2418,7 +2417,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
     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 = bfd_section_flags (now_seg);
     flags |= SEC_LINK_ONCE;
     switch (type)
       {
@@ -2437,7 +2436,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
        flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
        break;
       }
-    if (!bfd_set_section_flags (stdoutput, now_seg, flags))
+    if (!bfd_set_section_flags (now_seg, flags))
       as_bad (_("bfd_set_section_flags: %s"),
              bfd_errmsg (bfd_get_error ()));
   }
@@ -2463,7 +2462,7 @@ bss_alloc (symbolS *symbolP, addressT size, unsigned int align)
        {
          bss_seg = subseg_new (".sbss", 1);
          seg_info (bss_seg)->bss = 1;
-         if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
+         if (!bfd_set_section_flags (bss_seg, SEC_ALLOC | SEC_SMALL_DATA))
            as_warn (_("error setting flags for \".sbss\": %s"),
                     bfd_errmsg (bfd_get_error ()));
        }
@@ -2956,9 +2955,9 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
          flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
        if (flags != SEC_NO_FLAGS)
          {
-           if (!bfd_set_section_flags (stdoutput, seg, flags))
+           if (!bfd_set_section_flags (seg, flags))
              as_warn (_("error setting flags for \"%s\": %s"),
-                      bfd_section_name (stdoutput, seg),
+                      bfd_section_name (seg),
                       bfd_errmsg (bfd_get_error ()));
          }
       }
@@ -2971,81 +2970,10 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 
 #else /* ! TC_M68K */
-#ifdef TC_I960
-
-  char *name;
-  char c;
-  segT seg;
-
-  SKIP_WHITESPACE ();
-
-  c = get_symbol_name (& name);
-
-  name = xstrdup (name);
-
-  c = restore_line_pointer (c);
-
-  seg = subseg_new (name, 0);
-
-  if (c != ',')
-    *type = 'C';
-  else
-    {
-      char *sectype;
-
-      ++input_line_pointer;
-      SKIP_WHITESPACE ();
-      c = get_symbol_name (& sectype);
-      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);
-      (void) restore_line_pointer (c);
-    }
-
-  if (*input_line_pointer == ',')
-    {
-      char *seccmd;
-
-      ++input_line_pointer;
-      SKIP_WHITESPACE ();
-      c = get_symbol_name (& seccmd);
-      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)
-       {
-         unsigned int align;
-
-         (void) restore_line_pointer (c);
-         align = get_absolute_expression ();
-         record_alignment (seg, align);
-       }
-      else
-       {
-         as_warn (_("unrecognized section command `%s'"), seccmd);
-         (void) restore_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 */
 }
 
@@ -3107,9 +3035,9 @@ s_bad_end (int endr)
 void
 s_rept (int ignore ATTRIBUTE_UNUSED)
 {
-  int count;
+  size_t count;
 
-  count = get_absolute_expression ();
+  count = (size_t) get_absolute_expression ();
 
   do_repeat (count, "REPT", "ENDR");
 }
@@ -3118,11 +3046,17 @@ s_rept (int ignore ATTRIBUTE_UNUSED)
    different directives to be used as the start/end keys.  */
 
 void
-do_repeat (int count, const char *start, const char *end)
+do_repeat (size_t count, const char *start, const char *end)
 {
   sb one;
   sb many;
 
+  if (((ssize_t) count) < 0)
+    {
+      as_bad (_("negative count for %s - ignored"), start);
+      count = 0;
+    }
+
   sb_new (&one);
   if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
     {
@@ -3142,10 +3076,10 @@ do_repeat (int count, const char *start, const char *end)
 }
 
 /* Like do_repeat except that any text matching EXPANDER in the
-   block is replaced by the itteration count.  */
+   block is replaced by the iteration count.  */
 
 void
-do_repeat_with_expander (int count,
+do_repeat_with_expander (size_t count,
                         const char * start,
                         const char * end,
                         const char * expander)
@@ -3153,6 +3087,12 @@ do_repeat_with_expander (int count,
   sb one;
   sb many;
 
+  if (((ssize_t) count) < 0)
+    {
+      as_bad (_("negative count for %s - ignored"), start);
+      count = 0;
+    }
+
   sb_new (&one);
   if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
     {
@@ -3173,9 +3113,10 @@ do_repeat_with_expander (int count,
          sb_build (& processed, one.len);
          sb_add_sb (& processed, & one);
          sub = strstr (processed.ptr, expander);
-         len = sprintf (sub, "%d", count);
+         len = sprintf (sub, "%lu", (unsigned long) count);
          gas_assert (len < 8);
-         strcpy (sub + len, sub + 8);
+         memmove (sub + len, sub + 8,
+                  processed.ptr + processed.len - (sub + 8));
          processed.len -= (8 - len);
          sb_add_sb (& many, & processed);
          sb_kill (& processed);
@@ -3238,7 +3179,7 @@ assign_symbol (char *name, int mode)
       if (listing & LISTING_SYMBOLS)
        {
          extern struct list_info_struct *listing_tail;
-         fragS *dummy_frag = (fragS *) xcalloc (1, sizeof (fragS));
+         fragS *dummy_frag = XCNEW (fragS);
          dummy_frag->line = listing_tail;
          dummy_frag->fr_symbol = symbolP;
          symbol_set_frag (symbolP, dummy_frag);
@@ -3256,7 +3197,9 @@ assign_symbol (char *name, int mode)
          && !S_CAN_BE_REDEFINED (symbolP))
        {
          as_bad (_("symbol `%s' is already defined"), name);
-         symbolP = symbol_clone (symbolP, 0);
+         ignore_rest_of_line ();
+         input_line_pointer--;
+         return;
        }
       /* If the symbol is volatile, copy the symbol and replace the
         original with the copy, so that previous uses of the symbol will
@@ -3393,11 +3336,20 @@ s_space (int mult)
        {
          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);
+         /* PR 20901: Check for excessive values.
+            FIXME: 1<<10 is an arbitrary limit.  Maybe use maxpagesize instead ?  */
+         if (exp.X_add_number < 0 || exp.X_add_number > (1 << 10))
+           as_bad (_("size value for space directive too large: %lx"),
+                   (long) exp.X_add_number);
+         else
+           {
+             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
@@ -3485,6 +3437,58 @@ s_space (int mult)
     mri_comment_end (stop, stopc);
 }
 
+void
+s_nops (int ignore ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+  expressionS val;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+  md_cons_align (1);
+#endif
+
+  expression (&exp);
+
+  if (*input_line_pointer == ',')
+    {
+      ++input_line_pointer;
+      expression (&val);
+    }
+  else
+    {
+      val.X_op = O_constant;
+      val.X_add_number = 0;
+    }
+
+  if (val.X_op == O_constant)
+    {
+      if (val.X_add_number < 0)
+       {
+         as_warn (_("negative nop control byte, ignored"));
+         val.X_add_number = 0;
+       }
+
+      if (!need_pass_2)
+       {
+         /* Store the no-op instruction control byte in the first byte
+            of frag.  */
+         char *p;
+         symbolS *sym = make_expr_symbol (&exp);
+         p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
+                       sym, (offsetT) 0, (char *) 0);
+         *p = val.X_add_number;
+       }
+    }
+  else
+    as_bad (_("unsupported variable nop control in .nops directive"));
+
+  demand_empty_rest_of_line ();
+}
+
 /* This is like s_space, but the value is a floating point number with
    the given precision.  This is for the MRI dcb.s pseudo-op and
    friends.  */
@@ -3542,7 +3546,7 @@ s_float_space (int float_type)
     }
   else
     {
-      char *err;
+      const char *err;
 
       err = md_atof (float_type, temp, &flen);
       know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
@@ -3754,7 +3758,8 @@ ignore_rest_of_line (void)
   input_line_pointer++;
 
   /* Return pointing just after end-of-line.  */
-  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
+  if (input_line_pointer <= buffer_limit)
+    know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
 /* Sets frag for given symbol to zero_address_frag, except when the
@@ -3860,7 +3865,7 @@ pseudo_set (symbolS *symbolP)
          symbolS *s = exp.X_add_symbol;
 
          if (S_IS_COMMON (s))
-           as_bad (_("`%s' can't be equated to common symbol '%s'"),
+           as_bad (_("`%s' can't be equated to common symbol `%s'"),
                    S_GET_NAME (symbolP), S_GET_NAME (s));
 
          S_SET_SEGMENT (symbolP, seg);
@@ -3902,7 +3907,6 @@ pseudo_set (symbolS *symbolP)
 /* Some targets need to parse the expression in various fancy ways.
    You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
    (for example, the HPPA does this).  Otherwise, you can define
-   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
    REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
    are defined, which is the normal case, then only simple expressions
    are permitted.  */
@@ -3913,12 +3917,6 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes);
 #endif
 
 #ifndef TC_PARSE_CONS_EXPRESSION
-#ifdef BITFIELD_CONS_EXPRESSIONS
-#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
-  (parse_bitfield_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE)
-static void
-parse_bitfield_cons (expressionS *exp, unsigned int nbytes);
-#endif
 #ifdef REPEAT_CONS_EXPRESSIONS
 #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
   (parse_repeat_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE)
@@ -4067,7 +4065,7 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
     { "64", BFD_RELOC_64 }
   };
 
-  reloc = (struct reloc_list *) xmalloc (sizeof (*reloc));
+  reloc = XNEW (struct reloc_list);
 
   if (flag_mri)
     stop = mri_comment_field (&stopc);
@@ -4084,14 +4082,14 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
     case O_constant:
       exp.X_add_symbol = section_symbol (now_seg);
       exp.X_op = O_symbol;
-      /* Fall thru */
+      /* Fallthru */
     case O_symbol:
       if (exp.X_add_number == 0)
        {
          reloc->u.a.offset_sym = exp.X_add_symbol;
          break;
        }
-      /* Fall thru */
+      /* Fallthru */
     default:
       reloc->u.a.offset_sym = make_expr_symbol (&exp);
       break;
@@ -4347,7 +4345,7 @@ emit_expr_with_reloc (expressionS *exp,
     {
       struct broken_word *x;
 
-      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
+      x = XNEW (struct broken_word);
       x->next_broken_word = broken_words;
       broken_words = x;
       x->seg = now_seg;
@@ -4411,7 +4409,8 @@ emit_expr_with_reloc (expressionS *exp,
       if ((get & mask) != 0
          && ((get & mask) != mask
              || (get & hibit) == 0))
-       {               /* Leading bits contain both 0s & 1s.  */
+       {
+         /* Leading bits contain both 0s & 1s.  */
 #if defined (BFD64) && BFD_HOST_64BIT_LONG_LONG
 #ifndef __MSVCRT__
          as_warn (_("value 0x%llx truncated to 0x%llx"),
@@ -4437,18 +4436,39 @@ emit_expr_with_reloc (expressionS *exp,
       if (nbytes < size)
        {
          int i = nbytes / CHARS_PER_LITTLENUM;
+
          if (i != 0)
            {
              LITTLENUM_TYPE sign = 0;
              if ((generic_bignum[--i]
                   & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) != 0)
                sign = ~(LITTLENUM_TYPE) 0;
+
              while (++i < exp->X_add_number)
                if (generic_bignum[i] != sign)
                  break;
            }
+         else if (nbytes == 1)
+           {
+             /* We have nbytes == 1 and CHARS_PER_LITTLENUM == 2 (probably).
+                Check that bits 8.. of generic_bignum[0] match bit 7
+                and that they match all of generic_bignum[1..exp->X_add_number].  */
+             LITTLENUM_TYPE sign = (generic_bignum[0] & (1 << 7)) ? -1 : 0;
+             LITTLENUM_TYPE himask = LITTLENUM_MASK & ~ 0xFF;
+
+             if ((generic_bignum[0] & himask) == (sign & himask))
+               {
+                 while (++i < exp->X_add_number)
+                   if (generic_bignum[i] != sign)
+                     break;
+               }
+           }
+
          if (i < exp->X_add_number)
-           as_warn (_("bignum truncated to %d bytes"), nbytes);
+           as_warn (ngettext ("bignum truncated to %d byte",
+                              "bignum truncated to %d bytes",
+                              nbytes),
+                    nbytes);
          size = nbytes;
        }
 
@@ -4524,7 +4544,9 @@ emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p,
 
       if (size > nbytes)
        {
-         as_bad (_("%s relocations do not fit in %u bytes\n"),
+         as_bad (ngettext ("%s relocations do not fit in %u byte",
+                           "%s relocations do not fit in %u bytes",
+                           nbytes),
                  reloc_howto->name, nbytes);
          return;
        }
@@ -4558,134 +4580,6 @@ emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p,
 #endif
 }
 \f
-#ifdef BITFIELD_CONS_EXPRESSIONS
-
-/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
-   w:x,y:z, where w and y are bitwidths and x and y are values.  They
-   then pack them all together. We do a little better in that we allow
-   them in words, longs, etc. and we'll pack them in target byte order
-   for you.
-
-   The rules are: pack least significant bit first, if a field doesn't
-   entirely fit, put it in the next unit.  Overflowing the bitfield is
-   explicitly *not* even a warning.  The bitwidth should be considered
-   a "mask".
-
-   To use this function the tc-XXX.h file should define
-   BITFIELD_CONS_EXPRESSIONS.  */
-
-static void
-parse_bitfield_cons (exp, nbytes)
-     expressionS *exp;
-     unsigned int nbytes;
-{
-  unsigned int bits_available = BITS_PER_CHAR * nbytes;
-  char *hold = input_line_pointer;
-
-  (void) expression (exp);
-
-  if (*input_line_pointer == ':')
-    {
-      /* Bitfields.  */
-      long value = 0;
-
-      for (;;)
-       {
-         unsigned long width;
-
-         if (*input_line_pointer != ':')
-           {
-             input_line_pointer = hold;
-             break;
-           }                   /* Next piece is not a bitfield.  */
-
-         /* In the general case, we can't allow
-            full expressions with symbol
-            differences and such.  The relocation
-            entries for symbols not defined in this
-            assembly would require arbitrary field
-            widths, positions, and masks which most
-            of our current object formats don't
-            support.
-
-            In the specific case where a symbol
-            *is* defined in this assembly, we
-            *could* build fixups and track it, but
-            this could lead to confusion for the
-            backends.  I'm lazy. I'll take any
-            SEG_ABSOLUTE. I think that means that
-            you can use a previous .set or
-            .equ type symbol.  xoxorich.  */
-
-         if (exp->X_op == O_absent)
-           {
-             as_warn (_("using a bit field width of zero"));
-             exp->X_add_number = 0;
-             exp->X_op = O_constant;
-           }                   /* Implied zero width bitfield.  */
-
-         if (exp->X_op != O_constant)
-           {
-             *input_line_pointer = '\0';
-             as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
-             *input_line_pointer = ':';
-             demand_empty_rest_of_line ();
-             return;
-           }                   /* Too complex.  */
-
-         if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
-           {
-             as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
-                      width, nbytes, (BITS_PER_CHAR * nbytes));
-             width = BITS_PER_CHAR * nbytes;
-           }                   /* Too big.  */
-
-         if (width > bits_available)
-           {
-             /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
-             input_line_pointer = hold;
-             exp->X_add_number = value;
-             break;
-           }                   /* Won't fit.  */
-
-         /* Skip ':'.  */
-         hold = ++input_line_pointer;
-
-         (void) expression (exp);
-         if (exp->X_op != O_constant)
-           {
-             char cache = *input_line_pointer;
-
-             *input_line_pointer = '\0';
-             as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
-             *input_line_pointer = cache;
-             demand_empty_rest_of_line ();
-             return;
-           }                   /* Too complex.  */
-
-         value |= ((~(-(1 << width)) & exp->X_add_number)
-                   << ((BITS_PER_CHAR * nbytes) - bits_available));
-
-         if ((bits_available -= width) == 0
-             || is_it_end_of_statement ()
-             || *input_line_pointer != ',')
-           {
-             break;
-           }                   /* All the bitfields we're gonna get.  */
-
-         hold = ++input_line_pointer;
-         (void) expression (exp);
-       }
-
-      exp->X_add_number = value;
-      exp->X_op = O_constant;
-      exp->X_unsigned = 1;
-      exp->X_extrabit = 0;
-    }
-}
-
-#endif /* BITFIELD_CONS_EXPRESSIONS */
-\f
 /* Handle an MRI style string expression.  */
 
 #ifdef TC_M68K
@@ -4762,9 +4656,7 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes)
    To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
 
 static void
-parse_repeat_cons (exp, nbytes)
-     expressionS *exp;
-     unsigned int nbytes;
+parse_repeat_cons (expressionS *exp, unsigned int nbytes)
 {
   expressionS count;
   int i;
@@ -4906,7 +4798,7 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
 {
   char *p;
   int length;                  /* Number of chars in an object.  */
-  char *err;           /* Error from scanning floating literal.  */
+  const char *err;             /* Error from scanning floating literal.  */
   char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
 
   if (is_it_end_of_statement ())
@@ -5319,13 +5211,21 @@ emit_leb128_expr (expressionS *exp, int sign)
   else if (op == O_big)
     {
       /* O_big is a different sort of constant.  */
-
+      int nbr_digits = exp->X_add_number;
       unsigned int size;
       char *p;
 
-      size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
+      /* If the leading littenum is 0xffff, prepend a 0 to avoid confusion with
+        a signed number.  Unary operators like - or ~ always extend the
+        bignum to its largest size.  */
+      if (exp->X_unsigned
+         && nbr_digits < SIZE_OF_LARGE_NUMBER
+         && generic_bignum[nbr_digits - 1] == LITTLENUM_MASK)
+       generic_bignum[nbr_digits++] = 0;
+
+      size = output_big_leb128 (NULL, generic_bignum, nbr_digits, sign);
       p = frag_more (size);
-      if (output_big_leb128 (p, generic_bignum, exp->X_add_number, sign) > size)
+      if (output_big_leb128 (p, generic_bignum, nbr_digits, sign) > size)
        abort ();
     }
   else
@@ -5463,8 +5363,6 @@ stringer (int bits_appendzero)
          if (append_zero)
            stringer_append_char (0, bitsize);
 
-         know (input_line_pointer[-1] == '\"');
-
 #if !defined(NO_LISTING) && defined (OBJ_ELF)
          /* In ELF, when gcc is emitting DWARF 1 debugging output, it
             will emit .string with a filename in the .debug section
@@ -5489,8 +5387,11 @@ stringer (int bits_appendzero)
          c = get_single_number ();
          stringer_append_char (c, bitsize);
          if (*input_line_pointer != '>')
-           as_bad (_("expected <nn>"));
-
+           {
+             as_bad (_("expected <nn>"));
+             ignore_rest_of_line ();
+             return;
+           }
          input_line_pointer++;
          break;
        case ',':
@@ -5517,6 +5418,12 @@ next_char_of_string (void)
   c = *input_line_pointer++ & CHAR_MASK;
   switch (c)
     {
+    case 0:
+      /* PR 20902: Do not advance past the end of the buffer.  */
+      -- input_line_pointer;
+      c = NOT_A_CHAR;
+      break;
+
     case '\"':
       c = NOT_A_CHAR;
       break;
@@ -5526,8 +5433,9 @@ next_char_of_string (void)
       bump_line_counters ();
       break;
 
-#ifndef NO_STRING_ESCAPES
     case '\\':
+      if (!TC_STRING_ESCAPES)
+       break;
       switch (c = *input_line_pointer++ & CHAR_MASK)
        {
        case 'b':
@@ -5613,6 +5521,12 @@ next_char_of_string (void)
          bump_line_counters ();
          break;
 
+       case 0:
+         /* Do not advance past the end of the buffer.  */
+         -- input_line_pointer;
+         c = NOT_A_CHAR;
+         break;
+
        default:
 
 #ifdef ONLY_STANDARD_ESCAPES
@@ -5623,7 +5537,6 @@ next_char_of_string (void)
          break;
        }
       break;
-#endif /* ! defined (NO_STRING_ESCAPES) */
 
     default:
       break;
@@ -5839,7 +5752,7 @@ s_incbin (int x ATTRIBUTE_UNUSED)
     {
       int i;
 
-      path = (char *) xmalloc ((unsigned long) len + include_dir_maxlen + 5);
+      path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
 
       for (i = 0; i < include_dir_count; i++)
        {
@@ -5895,11 +5808,10 @@ s_incbin (int x ATTRIBUTE_UNUSED)
        as_warn (_("truncated file `%s', %ld of %ld bytes read"),
                 path, bytes, count);
     }
-done:
+ done:
   if (binfile != NULL)
     fclose (binfile);
-  if (path)
-    free (path);
+  free (path);
 }
 
 /* .include -- include a file at this point.  */
@@ -5942,8 +5854,8 @@ s_include (int arg ATTRIBUTE_UNUSED)
     }
 
   demand_empty_rest_of_line ();
-  path = (char *) xmalloc ((unsigned long) i
-                          + include_dir_maxlen + 5 /* slop */ );
+  path = XNEWVEC (char, (unsigned long) i
+                 + include_dir_maxlen + 5 /* slop */ );
 
   for (i = 0; i < include_dir_count; i++)
     {
@@ -5959,7 +5871,7 @@ s_include (int arg ATTRIBUTE_UNUSED)
 
   free (path);
   path = filename;
-gotit:
+ gotit:
   /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY.  */
   register_dependency (path);
   input_scrub_insert_file (path);
@@ -5972,16 +5884,15 @@ add_include_dir (char *path)
 
   if (include_dir_count == 0)
     {
-      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
+      include_dirs = XNEWVEC (const char *, 2);
       include_dirs[0] = ".";   /* Current dir.  */
       include_dir_count = 2;
     }
   else
     {
       include_dir_count++;
-      include_dirs =
-       (char **) xrealloc (include_dirs,
-                           include_dir_count * sizeof (*include_dirs));
+      include_dirs = XRESIZEVEC (const char *, include_dirs,
+                                include_dir_count);
     }
 
   include_dirs[include_dir_count - 1] = path;  /* New one.  */
@@ -6179,9 +6090,10 @@ s_bundle_unlock (int arg ATTRIBUTE_UNUSED)
 
   size = pending_bundle_size (bundle_lock_frag);
 
-  if (size > (1U << bundle_align_p2))
-    as_bad (_(".bundle_lock sequence is %u bytes, but bundle size only %u"),
-           size, 1 << bundle_align_p2);
+  if (size > 1U << bundle_align_p2)
+    as_bad (_(".bundle_lock sequence is %u bytes, "
+             "but bundle size is only %u bytes"),
+           size, 1u << bundle_align_p2);
   else
     finish_bundle (bundle_lock_frag, size);
 
@@ -6289,3 +6201,46 @@ find_end_of_line (char *s, int mri_string)
 {
   return _find_end_of_line (s, mri_string, 0, 0);
 }
+
+static char *saved_ilp = NULL;
+static char *saved_limit;
+
+/* Use BUF as a temporary input pointer for calling other functions in this
+   file.  BUF must be a C string, so that its end can be found by strlen.
+   Also sets the buffer_limit variable (local to this file) so that buffer
+   overruns should not occur.  Saves the current input line pointer so that
+   it can be restored by calling restore_ilp().
+
+   Does not support recursion.  */
+
+void
+temp_ilp (char *buf)
+{
+  gas_assert (saved_ilp == NULL);
+  gas_assert (buf != NULL);
+
+  saved_ilp = input_line_pointer;
+  saved_limit = buffer_limit;
+  /* Prevent the assert in restore_ilp from triggering if
+     the input_line_pointer has not yet been initialised.  */
+  if (saved_ilp == NULL)
+    saved_limit = saved_ilp = (char *) "";
+
+  input_line_pointer = buf;
+  buffer_limit = buf + strlen (buf);
+  input_from_string = TRUE;
+}
+
+/* Restore a saved input line pointer.  */
+
+void
+restore_ilp (void)
+{
+  gas_assert (saved_ilp != NULL);
+
+  input_line_pointer = saved_ilp;
+  buffer_limit = saved_limit;
+  input_from_string = FALSE;
+
+  saved_ilp = NULL;
+}
This page took 0.037062 seconds and 4 git commands to generate.