replace some raw xmalloc / xrealloc with the XNEW* macros
[deliverable/binutils-gdb.git] / gas / read.c
index 7dfc20a737116c5968d1bf457c0c6e6a569055dc..a22c7505efebe4bb108e43118be9c7d1e616c541 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -41,7 +41,7 @@
 #include "wchar.h"
 
 #ifndef TC_START_LABEL
-#define TC_START_LABEL(x,y,z) (x == ':')
+#define TC_START_LABEL(STR, NUL_CHAR, NEXT_CHAR) (NEXT_CHAR == ':')
 #endif
 
 /* Set by the object-format or the target.  */
@@ -166,7 +166,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;
@@ -238,7 +238,6 @@ static unsigned int bundle_lock_depth;
 #endif
 
 static void do_s_func (int end_p, const char *default_prefix);
-static void do_align (int, char *, int, int);
 static void s_align (int, int);
 static void s_altmacro (int);
 static void s_bad_end (int);
@@ -487,6 +486,7 @@ static offsetT
 get_absolute_expr (expressionS *exp)
 {
   expression_and_evaluate (exp);
+
   if (exp->X_op != O_constant)
     {
       if (exp->X_op != O_absent)
@@ -685,7 +685,8 @@ finish_bundle (fragS *frag, unsigned int size)
   /* We do this every time rather than just in s_bundle_align_mode
      so that we catch any affected section without needing hooks all
      over for all paths that do section changes.  It's cheap enough.  */
-  record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
+  if (bundle_align_p2 > OCTETS_PER_BYTE_POWER)
+    record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
 }
 
 /* Assemble one instruction.  This takes care of the bundle features
@@ -736,12 +737,82 @@ single instruction is %u bytes long but .bundle_align_mode limit is %u"),
 
 #endif  /* HANDLE_BUNDLE */
 
+static bfd_boolean
+in_bss (void)
+{
+  flagword flags = bfd_get_section_flags (stdoutput, now_seg);
+
+  return (flags & SEC_ALLOC) && !(flags & (SEC_LOAD | SEC_HAS_CONTENTS));
+}
+
+/* Guts of .align directive:
+   N is the power of two to which to align.  A value of zero is accepted but
+    ignored: the default alignment of the section will be at least this.
+   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.  If LEN is zero
+    but FILL is not NULL then LEN is treated as if it were one.
+   MAX is the maximum number of characters to skip when doing the alignment,
+    or 0 if there is no maximum.  */
+
+void
+do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
+{
+  if (now_seg == absolute_section || in_bss ())
+    {
+      if (fill != NULL)
+       while (len-- > 0)
+         if (*fill++ != '\0')
+           {
+             if (now_seg == absolute_section)
+               as_warn (_("ignoring fill value in absolute section"));
+             else
+               as_warn (_("ignoring fill value in section `%s'"),
+                        segment_name (now_seg));
+             break;
+           }
+      fill = NULL;
+      len = 0;
+    }
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+#ifdef md_do_align
+  md_do_align (n, fill, len, max, just_record_alignment);
+#endif
+
+  /* Only make a frag if we HAVE to...  */
+  if ((n > OCTETS_PER_BYTE_POWER) && !need_pass_2)
+    {
+      if (fill == NULL)
+       {
+         if (subseg_text_p (now_seg))
+           frag_align_code (n, max);
+         else
+           frag_align (n, 0, max);
+       }
+      else if (len <= 1)
+       frag_align (n, *fill, max);
+      else
+       frag_align_pattern (n, fill, len, max);
+    }
+
+#ifdef md_do_align
+ just_record_alignment: ATTRIBUTE_UNUSED_LABEL
+#endif
+
+  if (n > OCTETS_PER_BYTE_POWER)
+    record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
+}
+
 /* 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 c;
+  char nul_char;
+  char next_char;
   char *s;             /* String of symbol, '\0' appended.  */
   int temp;
   pseudo_typeS *pop;
@@ -808,7 +879,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);
@@ -828,16 +899,18 @@ read_a_source_file (char *name)
 
              if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
                {
+                 next_char = * input_line_pointer;
                  /* Text at the start of a line must be a label, we
                     run down and stick a colon in.  */
-                 if (is_name_beginner (*input_line_pointer))
+                 if (is_name_beginner (next_char) || next_char == '"')
                    {
-                     char *line_start = input_line_pointer;
+                     char *line_start;
                      int mri_line_macro;
 
                      HANDLE_CONDITIONAL_ASSEMBLY (0);
 
-                     c = get_symbol_end ();
+                     nul_char = get_symbol_name (& line_start);
+                     next_char = (nul_char == '"' ? input_line_pointer[1] : nul_char);
 
                      /* In MRI mode, the EQU and MACRO pseudoops must
                         be handled specially.  */
@@ -871,8 +944,7 @@ read_a_source_file (char *name)
                         symbol in the symbol table.  */
                      if (!mri_line_macro
 #ifdef TC_START_LABEL_WITHOUT_COLON
-                         && TC_START_LABEL_WITHOUT_COLON(c,
-                                                         input_line_pointer)
+                         && TC_START_LABEL_WITHOUT_COLON (nul_char, next_char)
 #endif
                          )
                        line_label = colon (line_start);
@@ -882,8 +954,8 @@ read_a_source_file (char *name)
                                                    (valueT) 0,
                                                    &zero_address_frag);
 
-                     *input_line_pointer = c;
-                     if (c == ':')
+                     next_char = restore_line_pointer (nul_char);
+                     if (next_char == ':')
                        input_line_pointer++;
                    }
                }
@@ -898,30 +970,32 @@ read_a_source_file (char *name)
             Each test is independent of all other tests at the (top)
             level.  */
          do
-           c = *input_line_pointer++;
-         while (c == '\t' || c == ' ' || c == '\f');
+           nul_char = next_char = *input_line_pointer++;
+         while (next_char == '\t' || next_char == ' ' || next_char == '\f');
 
          /* C is the 1st significant character.
             Input_line_pointer points after that character.  */
-         if (is_name_beginner (c))
+         if (is_name_beginner (next_char) || next_char == '"')
            {
+             char *rest;
+
              /* Want user-defined label or pseudo/opcode.  */
              HANDLE_CONDITIONAL_ASSEMBLY (1);
 
-             s = --input_line_pointer;
-             c = get_symbol_end ();    /* name's delimiter.  */
+             --input_line_pointer;
+             nul_char = get_symbol_name (& s); /* name's delimiter.  */
+             next_char = (nul_char == '"' ? input_line_pointer[1] : nul_char);
+             rest = input_line_pointer + (nul_char == '"' ? 2 : 1);
 
-             /* C is character after symbol.
-                That character's place in the input line is now '\0'.
+             /* NEXT_CHAR is character after symbol.
+                The end of symbol in the input line is now '\0'.
                 S points to the beginning of the symbol.
                   [In case of pseudo-op, s->'.'.]
-                Input_line_pointer->'\0' where c was.  */
-             if (TC_START_LABEL (c, s, input_line_pointer))
+                Input_line_pointer->'\0' where NUL_CHAR was.  */
+             if (TC_START_LABEL (s, nul_char, next_char))
                {
                  if (flag_m68k_mri)
                    {
-                     char *rest = input_line_pointer + 1;
-
                      /* In MRI mode, \tsym: set 0 is permitted.  */
                      if (*rest == ':')
                        ++rest;
@@ -940,27 +1014,27 @@ read_a_source_file (char *name)
                    }
 
                  line_label = colon (s);       /* User-defined label.  */
-                 /* Put ':' back for error messages' sake.  */
-                 *input_line_pointer++ = ':';
+                 restore_line_pointer (nul_char);
+                 ++ input_line_pointer;
 #ifdef tc_check_label
                  tc_check_label (line_label);
 #endif
                  /* Input_line_pointer->after ':'.  */
                  SKIP_WHITESPACE ();
                }
-             else if ((c == '=' && input_line_pointer[1] == '=')
-                      || ((c == ' ' || c == '\t')
-                          && input_line_pointer[1] == '='
-                          && input_line_pointer[2] == '='))
+             else if ((next_char == '=' && *rest == '=')
+                      || ((next_char == ' ' || next_char == '\t')
+                          && rest[0] == '='
+                          && rest[1] == '='))
                {
                  equals (s, -1);
                  demand_empty_rest_of_line ();
                }
-             else if ((c == '='
-                      || ((c == ' ' || c == '\t')
-                           && input_line_pointer[1] == '='))
+             else if ((next_char == '='
+                      || ((next_char == ' ' || next_char == '\t')
+                           && *rest == '='))
 #ifdef TC_EQUAL_IN_INSN
-                          && !TC_EQUAL_IN_INSN (c, s)
+                          && !TC_EQUAL_IN_INSN (next_char, s)
 #endif
                           )
                {
@@ -1000,7 +1074,7 @@ read_a_source_file (char *name)
                    {
                      /* PSEUDO - OP.
 
-                        WARNING: c has next char, which may be end-of-line.
+                        WARNING: next_char may be end-of-line.
                         We lookup the pseudo-op table with s+1 because we
                         already know that the pseudo-op begins with a '.'.  */
 
@@ -1045,25 +1119,25 @@ read_a_source_file (char *name)
                        {
                          char *end = input_line_pointer;
 
-                         *input_line_pointer = c;
+                         (void) restore_line_pointer (nul_char);
                          s_ignore (0);
-                         c = *--input_line_pointer;
+                         nul_char = next_char = *--input_line_pointer;
                          *input_line_pointer = '\0';
-                         if (! macro_defined || ! try_macro (c, s))
+                         if (! macro_defined || ! try_macro (next_char, s))
                            {
                              *end = '\0';
                              as_bad (_("unknown pseudo-op: `%s'"), s);
-                             *input_line_pointer++ = c;
+                             *input_line_pointer++ = nul_char;
                            }
                          continue;
                        }
 
                      /* Put it back for error messages etc.  */
-                     *input_line_pointer = c;
+                     next_char = restore_line_pointer (nul_char);
                      /* The following skip of whitespace is compulsory.
                         A well shaped space is sometimes all that separates
                         keyword from operands.  */
-                     if (c == ' ' || c == '\t')
+                     if (next_char == ' ' || next_char == '\t')
                        input_line_pointer++;
 
                      /* Input_line is restored.
@@ -1077,16 +1151,16 @@ read_a_source_file (char *name)
                    }
                  else
                    {
-                     /* WARNING: c has char, which may be end-of-line.  */
-                     /* Also: input_line_pointer->`\0` where c was.  */
-                     *input_line_pointer = c;
+                     /* WARNING: next_char may be end-of-line.  */
+                     /* Also: input_line_pointer->`\0` where nul_char was.  */
+                     (void) restore_line_pointer (nul_char);
                      input_line_pointer = _find_end_of_line (input_line_pointer, flag_m68k_mri, 1, 0);
-                     c = *input_line_pointer;
+                     next_char = nul_char = *input_line_pointer;
                      *input_line_pointer = '\0';
 
                      generate_lineno_debug ();
 
-                     if (macro_defined && try_macro (c, s))
+                     if (macro_defined && try_macro (next_char, s))
                        continue;
 
                      if (mri_pending_align)
@@ -1102,7 +1176,12 @@ read_a_source_file (char *name)
 
                      assemble_one (s); /* Assemble 1 instruction.  */
 
-                     *input_line_pointer++ = c;
+                     /* PR 19630: The backend may have set ilp to NULL
+                        if it encountered a catastrophic failure.  */
+                     if (input_line_pointer == NULL)
+                       as_fatal (_("unable to continue with assembly."));
+                     *input_line_pointer++ = nul_char;
 
                      /* We resume loop AFTER the end-of-line from
                         this instruction.  */
@@ -1112,17 +1191,20 @@ read_a_source_file (char *name)
            }
 
          /* Empty statement?  */
-         if (is_end_of_line[(unsigned char) c])
+         if (is_end_of_line[(unsigned char) next_char])
            continue;
 
-         if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
+         if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (next_char))
            {
              /* local label  ("4:")  */
              char *backup = input_line_pointer;
 
              HANDLE_CONDITIONAL_ASSEMBLY (1);
 
-             temp = c - '0';
+             temp = next_char - '0';
+
+             if (nul_char == '"')
+               ++ input_line_pointer;
 
              /* Read the whole number.  */
              while (ISDIGIT (*input_line_pointer))
@@ -1156,9 +1238,9 @@ read_a_source_file (char *name)
                }
 
              input_line_pointer = backup;
-           }                   /* local label  ("4:") */
+           }
 
-         if (c && strchr (line_comment_chars, c))
+         if (next_char && strchr (line_comment_chars, next_char))
            {                   /* Its a comment.  Better say APP or NO_APP.  */
              sb sbuf;
              char *ends;
@@ -1189,7 +1271,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
                    {
@@ -1205,7 +1287,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;
                    }
@@ -1226,7 +1308,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 (;;)
                {
@@ -1242,7 +1324,7 @@ 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;
                }
@@ -1270,7 +1352,7 @@ read_a_source_file (char *name)
          HANDLE_CONDITIONAL_ASSEMBLY (1);
 
 #ifdef tc_unrecognized_line
-         if (tc_unrecognized_line (c))
+         if (tc_unrecognized_line (next_char))
            continue;
 #endif
          input_line_pointer--;
@@ -1386,58 +1468,6 @@ s_abort (int ignore ATTRIBUTE_UNUSED)
   as_fatal (_(".abort detected.  Abandoning ship."));
 }
 
-/* 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 (int n, char *fill, int len, int max)
-{
-  if (now_seg == absolute_section)
-    {
-      if (fill != NULL)
-       while (len-- > 0)
-         if (*fill++ != '\0')
-           {
-             as_warn (_("ignoring fill value in absolute section"));
-             break;
-           }
-      fill = NULL;
-      len = 0;
-    }
-
-#ifdef md_flush_pending_output
-  md_flush_pending_output ();
-#endif
-#ifdef md_do_align
-  md_do_align (n, fill, len, max, just_record_alignment);
-#endif
-
-  /* Only make a frag if we HAVE to...  */
-  if (n != 0 && !need_pass_2)
-    {
-      if (fill == NULL)
-       {
-         if (subseg_text_p (now_seg))
-           frag_align_code (n, max);
-         else
-           frag_align (n, 0, max);
-       }
-      else if (len <= 1)
-       frag_align (n, *fill, max);
-      else
-       frag_align_pattern (n, fill, len, max);
-    }
-
-#ifdef md_do_align
- just_record_alignment: ATTRIBUTE_UNUSED_LABEL
-#endif
-
-  record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
-}
-
 /* 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
@@ -1447,14 +1477,14 @@ do_align (int n, char *fill, int len, int max)
 #endif
 
 static void
-s_align (int arg, int bytes_p)
+s_align (signed int arg, int bytes_p)
 {
   unsigned int align_limit = TC_ALIGN_LIMIT;
   unsigned int align;
   char *stop = NULL;
   char stopc = 0;
   offsetT fill = 0;
-  int max;
+  unsigned int max;
   int fill_p;
 
   if (flag_mri)
@@ -1471,6 +1501,11 @@ s_align (int arg, int bytes_p)
     {
       align = get_absolute_expression ();
       SKIP_WHITESPACE ();
+
+#ifdef TC_ALIGN_ZERO_IS_DEFAULT
+      if (arg > 0 && align == 0)
+       align = arg;
+#endif
     }
 
   if (bytes_p)
@@ -1529,15 +1564,16 @@ s_align (int arg, int bytes_p)
     }
   else
     {
-      int fill_len;
+      unsigned int fill_len;
 
       if (arg >= 0)
        fill_len = 1;
       else
        fill_len = -arg;
+
       if (fill_len <= 1)
        {
-         char fill_char;
+         char fill_char = 0;
 
          fill_char = fill;
          do_align (align, &fill_char, fill_len, max);
@@ -1547,7 +1583,12 @@ s_align (int arg, int bytes_p)
          char ab[16];
 
          if ((size_t) fill_len > sizeof ab)
-           abort ();
+           {
+             as_warn (_("fill pattern too long, truncating to %u"),
+                      (unsigned) sizeof ab);
+             fill_len = sizeof ab;
+           }
+
          md_number_to_chars (ab, fill, fill_len);
          do_align (align, ab, fill_len, max);
        }
@@ -1600,7 +1641,7 @@ s_altmacro (int on)
    If a symbol name could not be read, the routine issues an error
    messages, skips to the end of the line and returns NULL.  */
 
-static char *
+char *
 read_symbol_name (void)
 {
   char * name;
@@ -1616,7 +1657,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;
 
@@ -1628,7 +1669,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;
            }
@@ -1656,7 +1697,7 @@ read_symbol_name (void)
        ;
 
       len = (input_line_pointer - name) - 1;
-      start = xmalloc (len + 1);
+      start = XNEWVEC (char, len + 1);
 
       memcpy (start, name, len);
       start[len] = 0;
@@ -1795,7 +1836,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED)
 
   name = input_line_pointer;
   if (!ISDIGIT (*name))
-    c = get_symbol_end ();
+    c = get_symbol_name (& name);
   else
     {
       do
@@ -1809,16 +1850,15 @@ 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;
        }
     }
 
   sym = symbol_find_or_make (name);
-  *input_line_pointer = c;
+  c = restore_line_pointer (c);
   if (alc != NULL)
     free (alc);
 
@@ -2195,6 +2235,20 @@ s_fill (int ignore ATTRIBUTE_UNUSED)
 
   if (size && !need_pass_2)
     {
+      if (now_seg == absolute_section)
+       {
+         if (rep_exp.X_op != O_constant)
+           as_bad (_("non-constant fill count for absolute section"));
+         else if (fill && rep_exp.X_add_number != 0)
+           as_bad (_("attempt to fill absolute section with non-zero value"));
+         abs_section_offset += rep_exp.X_add_number * size;
+       }
+      else if (fill
+              && (rep_exp.X_op != O_constant || rep_exp.X_add_number != 0)
+              && in_bss ())
+       as_bad (_("attempt to fill section `%s' with non-zero value"),
+               segment_name (now_seg));
+
       if (rep_exp.X_op == O_constant)
        {
          p = frag_var (rs_fill, (int) size, (int) size,
@@ -2293,13 +2347,14 @@ s_globl (int ignore ATTRIBUTE_UNUSED)
 void
 s_irp (int irpc)
 {
-  char *file, *eol;
+  char * eol;
+  const char * file;
   unsigned int line;
   sb s;
   const char *err;
   sb out;
 
-  as_where (&file, &line);
+  file = as_where (&line);
 
   eol = find_end_of_line (input_line_pointer, 0);
   sb_build (&s, eol - input_line_pointer);
@@ -2338,8 +2393,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
       char *s;
       char c;
 
-      s = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (& s);
       if (strcasecmp (s, "discard") == 0)
        type = LINKONCE_DISCARD;
       else if (strcasecmp (s, "one_only") == 0)
@@ -2351,7 +2405,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
       else
        as_warn (_("unrecognized .linkonce type `%s'"), s);
 
-      *input_line_pointer = c;
+      (void) restore_line_pointer (c);
     }
 
 #ifdef obj_handle_link_once
@@ -2392,7 +2446,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
 }
 
 void
-bss_alloc (symbolS *symbolP, addressT size, int align)
+bss_alloc (symbolS *symbolP, addressT size, unsigned int align)
 {
   char *pfrag;
   segT current_seg = now_seg;
@@ -2416,7 +2470,7 @@ bss_alloc (symbolS *symbolP, addressT size, int align)
 #endif
   subseg_set (bss_seg, 1);
 
-  if (align)
+  if (align > OCTETS_PER_BYTE_POWER)
     {
       record_alignment (bss_seg, align);
       frag_align (align, 0, 0);
@@ -2629,13 +2683,14 @@ get_macro_line_sb (sb *line)
 void
 s_macro (int ignore ATTRIBUTE_UNUSED)
 {
-  char *file, *eol;
+  char *eol;
+  const char * file;
   unsigned int line;
   sb s;
   const char *err;
   const char *name;
 
-  as_where (&file, &line);
+  file = as_where (&line);
 
   eol = find_end_of_line (input_line_pointer, 0);
   sb_build (&s, eol - input_line_pointer);
@@ -2766,6 +2821,10 @@ do_org (segT segment, expressionS *exp, int fill)
       symbolS *sym = exp->X_add_symbol;
       offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
 
+      if (fill && in_bss ())
+       as_warn (_("ignoring fill value in section `%s'"),
+                segment_name (now_seg));
+
       if (exp->X_op != O_constant && exp->X_op != O_symbol)
        {
          /* Handle complex expressions.  */
@@ -2845,7 +2904,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
 
   name = input_line_pointer;
   if (!ISDIGIT (*name))
-    c = get_symbol_end ();
+    c = get_symbol_name (& name);
   else
     {
       do
@@ -2860,13 +2919,13 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
 
   name = xstrdup (name);
 
-  *input_line_pointer = c;
+  c = restore_line_pointer (c);
 
   seg = subseg_new (name, 0);
 
-  if (*input_line_pointer == ',')
+  if (c == ',')
     {
-      int align;
+      unsigned int align;
 
       ++input_line_pointer;
       align = get_absolute_expression ();
@@ -2919,16 +2978,15 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
 
   SKIP_WHITESPACE ();
 
-  name = input_line_pointer;
-  c = get_symbol_end ();
+  c = get_symbol_name (& name);
 
   name = xstrdup (name);
 
-  *input_line_pointer = c;
+  c = restore_line_pointer (c);
 
   seg = subseg_new (name, 0);
 
-  if (*input_line_pointer != ',')
+  if (c != ',')
     *type = 'C';
   else
     {
@@ -2936,8 +2994,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
 
       ++input_line_pointer;
       SKIP_WHITESPACE ();
-      sectype = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (& sectype);
       if (*sectype == '\0')
        *type = 'C';
       else if (strcasecmp (sectype, "text") == 0)
@@ -2948,7 +3005,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
        *type = 'R';
       else
        as_warn (_("unrecognized section type `%s'"), sectype);
-      *input_line_pointer = c;
+      (void) restore_line_pointer (c);
     }
 
   if (*input_line_pointer == ',')
@@ -2957,8 +3014,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
 
       ++input_line_pointer;
       SKIP_WHITESPACE ();
-      seccmd = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (& seccmd);
       if (strcasecmp (seccmd, "absolute") == 0)
        {
          as_bad (_("absolute sections are not supported"));
@@ -2968,16 +3024,16 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED)
        }
       else if (strcasecmp (seccmd, "align") == 0)
        {
-         int align;
+         unsigned int align;
 
-         *input_line_pointer = c;
+         (void) restore_line_pointer (c);
          align = get_absolute_expression ();
          record_alignment (seg, align);
        }
       else
        {
          as_warn (_("unrecognized section command `%s'"), seccmd);
-         *input_line_pointer = c;
+         (void) restore_line_pointer (c);
        }
     }
 
@@ -3023,11 +3079,10 @@ s_purgem (int ignore ATTRIBUTE_UNUSED)
       char c;
 
       SKIP_WHITESPACE ();
-      name = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (& name);
       delete_macro (name);
       *input_line_pointer = c;
-      SKIP_WHITESPACE ();
+      SKIP_WHITESPACE_AFTER_NAME ();
     }
   while (*input_line_pointer++ == ',');
 
@@ -3182,7 +3237,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);
@@ -3324,10 +3379,11 @@ s_space (int mult)
       val.X_add_number = 0;
     }
 
-  if (val.X_op != O_constant
-      || val.X_add_number < - 0x80
-      || val.X_add_number > 0xff
-      || (mult != 0 && mult != 1 && val.X_add_number != 0))
+  if ((val.X_op != O_constant
+       || val.X_add_number < - 0x80
+       || val.X_add_number > 0xff
+       || (mult != 0 && mult != 1 && val.X_add_number != 0))
+      && (now_seg != absolute_section && !in_bss ()))
     {
       resolve_expression (&exp);
       if (exp.X_op != O_constant)
@@ -3368,6 +3424,8 @@ s_space (int mult)
          /* 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 != 0)
+               as_warn (_("ignoring fill value in absolute section"));
              abs_section_offset += repeat;
              goto getout;
            }
@@ -3405,7 +3463,10 @@ s_space (int mult)
                          make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
        }
 
-      if (p)
+      if ((val.X_op != O_constant || val.X_add_number != 0) && in_bss ())
+       as_warn (_("ignoring fill value in section `%s'"),
+                segment_name (now_seg));
+      else if (p)
        *p = val.X_add_number;
     }
 
@@ -3932,12 +3993,14 @@ cons_worker (int nbytes,        /* 1=.byte, 2=.word, 4=.long.  */
       else
 #endif
        {
+#if 0
          if (*input_line_pointer == '"')
            {
              as_bad (_("unexpected `\"' in expression"));
              ignore_rest_of_line ();
              return;
            }
+#endif
          ret = TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
        }
 
@@ -3993,8 +4056,17 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
   char *r_name;
   int c;
   struct reloc_list *reloc;
+  struct _bfd_rel { const char * name; bfd_reloc_code_real_type code; };
+  static struct _bfd_rel bfd_relocs[] =
+  {
+    { "NONE", BFD_RELOC_NONE },
+    { "8",  BFD_RELOC_8 },
+    { "16", BFD_RELOC_16 },
+    { "32", BFD_RELOC_32 },
+    { "64", BFD_RELOC_64 }
+  };
 
-  reloc = (struct reloc_list *) xmalloc (sizeof (*reloc));
+  reloc = XNEW (struct reloc_list);
 
   if (flag_mri)
     stop = mri_comment_field (&stopc);
@@ -4033,9 +4105,21 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
 
   ++input_line_pointer;
   SKIP_WHITESPACE ();
-  r_name = input_line_pointer;
-  c = get_symbol_end ();
-  reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name);
+  c = get_symbol_name (& r_name);
+  if (strncasecmp (r_name, "BFD_RELOC_", 10) == 0)
+    {
+      unsigned int i;
+
+      for (reloc->u.a.howto = NULL, i = 0; i < ARRAY_SIZE (bfd_relocs); i++)
+       if (strcasecmp (r_name + 10, bfd_relocs[i].name) == 0)
+         {
+           reloc->u.a.howto = bfd_reloc_type_lookup (stdoutput,
+                                                     bfd_relocs[i].code);
+           break;
+         }
+    }
+  else
+    reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name);
   *input_line_pointer = c;
   if (reloc->u.a.howto == NULL)
     {
@@ -4044,7 +4128,7 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
     }
 
   exp.X_op = O_absent;
-  SKIP_WHITESPACE ();
+  SKIP_WHITESPACE_AFTER_NAME ();
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
@@ -4080,7 +4164,7 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
       break;
     }
 
-  as_where (&reloc->file, &reloc->line);
+  reloc->file = as_where (&reloc->line);
   reloc->next = reloc_list;
   reloc_list = reloc;
 
@@ -4184,15 +4268,6 @@ emit_expr_with_reloc (expressionS *exp,
 
   op = exp->X_op;
 
-  /* Allow `.word 0' in the absolute section.  */
-  if (now_seg == absolute_section)
-    {
-      if (op != O_constant || exp->X_add_number != 0)
-       as_bad (_("attempt to store value in absolute section"));
-      abs_section_offset += nbytes;
-      return;
-    }
-
   /* Handle a negative bignum.  */
   if (op == O_uminus
       && exp->X_add_number == 0
@@ -4242,6 +4317,20 @@ emit_expr_with_reloc (expressionS *exp,
       op = O_constant;
     }
 
+  /* Allow `.word 0' in the absolute section.  */
+  if (now_seg == absolute_section)
+    {
+      if (op != O_constant || exp->X_add_number != 0)
+       as_bad (_("attempt to store value in absolute section"));
+      abs_section_offset += nbytes;
+      return;
+    }
+
+  /* Allow `.word 0' in BSS style sections.  */
+  if ((op != O_constant || exp->X_add_number != 0) && in_bss ())
+    as_bad (_("attempt to store non-zero value in section `%s'"),
+           segment_name (now_seg));
+
   p = frag_more ((int) nbytes);
 
   if (reloc != TC_PARSE_CONS_RETURN_NONE)
@@ -4257,7 +4346,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;
@@ -4321,7 +4410,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"),
@@ -4347,16 +4437,34 @@ 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);
          size = nbytes;
@@ -4573,7 +4681,7 @@ parse_bitfield_cons (exp, nbytes)
              return;
            }                   /* Too complex.  */
 
-         value |= ((~(-1 << width) & exp->X_add_number)
+         value |= ((~(-(1 << width)) & exp->X_add_number)
                    << ((BITS_PER_CHAR * nbytes) - bits_available));
 
          if ((bits_available -= width) == 0
@@ -4825,6 +4933,21 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
       return;
     }
 
+  if (now_seg == absolute_section)
+    {
+      as_bad (_("attempt to store float in absolute section"));
+      ignore_rest_of_line ();
+      return;
+    }
+
+  if (in_bss ())
+    {
+      as_bad (_("attempt to store float in section `%s'"),
+             segment_name (now_seg));
+      ignore_rest_of_line ();
+      return;
+    }
+
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
 #endif
@@ -4908,9 +5031,25 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
   demand_empty_rest_of_line ();
 }
 \f
-/* Return the size of a LEB128 value.  */
+/* LEB128 Encoding.
 
-static inline int
+   Note - we are using the DWARF standard's definition of LEB128 encoding
+   where each 7-bit value is a stored in a byte, *not* an octet.  This
+   means that on targets where a byte contains multiple octets there is
+   a *huge waste of space*.  (This also means that we do not have to
+   have special versions of these functions for when OCTETS_PER_BYTE_POWER
+   is non-zero).
+
+   If the 7-bit values were to be packed into N-bit bytes (where N > 8)
+   we would then have to consider whether multiple, successive LEB128
+   values should be packed into the bytes without padding (bad idea) or
+   whether each LEB128 number is padded out to a whole number of bytes.
+   Plus you have to decide on the endianness of packing octets into a
+   byte.  */
+
+/* Return the size of a LEB128 value in bytes.  */
+
+static inline unsigned int
 sizeof_sleb128 (offsetT value)
 {
   int size = 0;
@@ -4931,7 +5070,7 @@ sizeof_sleb128 (offsetT value)
   return size;
 }
 
-static inline int
+static inline unsigned int
 sizeof_uleb128 (valueT value)
 {
   int size = 0;
@@ -4946,7 +5085,7 @@ sizeof_uleb128 (valueT value)
   return size;
 }
 
-int
+unsigned int
 sizeof_leb128 (valueT value, int sign)
 {
   if (sign)
@@ -4955,9 +5094,9 @@ sizeof_leb128 (valueT value, int sign)
     return sizeof_uleb128 (value);
 }
 
-/* Output a LEB128 value.  */
+/* Output a LEB128 value.  Returns the number of bytes used.  */
 
-static inline int
+static inline unsigned int
 output_sleb128 (char *p, offsetT value)
 {
   char *orig = p;
@@ -4984,7 +5123,7 @@ output_sleb128 (char *p, offsetT value)
   return p - orig;
 }
 
-static inline int
+static inline unsigned int
 output_uleb128 (char *p, valueT value)
 {
   char *orig = p;
@@ -4992,6 +5131,7 @@ output_uleb128 (char *p, valueT value)
   do
     {
       unsigned byte = (value & 0x7f);
+
       value >>= 7;
       if (value != 0)
        /* More bytes to follow.  */
@@ -5004,7 +5144,7 @@ output_uleb128 (char *p, valueT value)
   return p - orig;
 }
 
-int
+unsigned int
 output_leb128 (char *p, valueT value, int sign)
 {
   if (sign)
@@ -5015,10 +5155,11 @@ output_leb128 (char *p, valueT value, int sign)
 
 /* Do the same for bignums.  We combine sizeof with output here in that
    we don't output for NULL values of P.  It isn't really as critical as
-   for "normal" values that this be streamlined.  */
+   for "normal" values that this be streamlined.  Returns the number of
+   bytes used.  */
 
-static inline int
-output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
+static inline unsigned int
+output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size)
 {
   char *orig = p;
   valueT val = 0;
@@ -5063,7 +5204,7 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
     {
       /* Sign-extend VAL.  */
       if (val & (1 << (loaded - 1)))
-       val |= ~0 << loaded;
+       val |= ~0U << loaded;
       if (orig)
        *p = val & 0x7f;
       p++;
@@ -5072,8 +5213,8 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
   return p - orig;
 }
 
-static inline int
-output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
+static inline unsigned int
+output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size)
 {
   char *orig = p;
   valueT val = 0;
@@ -5111,8 +5252,8 @@ output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
   return p - orig;
 }
 
-static int
-output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
+static unsigned int
+output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size, int sign)
 {
   if (sign)
     return output_big_sleb128 (p, bignum, size);
@@ -5121,7 +5262,7 @@ output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
 }
 
 /* Generate the appropriate fragments for a given expression to emit a
-   leb128 value.  */
+   leb128 value.  SIGN is 1 for sleb, 0 for uleb.  */
 
 static void
 emit_leb128_expr (expressionS *exp, int sign)
@@ -5157,6 +5298,18 @@ emit_leb128_expr (expressionS *exp, int sign)
       op = O_big;
     }
 
+  if (now_seg == absolute_section)
+    {
+      if (op != O_constant || exp->X_add_number != 0)
+       as_bad (_("attempt to store value in absolute section"));
+      abs_section_offset++;
+      return;
+    }
+
+  if ((op != O_constant || exp->X_add_number != 0) && in_bss ())
+    as_bad (_("attempt to store non-zero value in section `%s'"),
+           segment_name (now_seg));
+
   /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
      a signal that this is leb128 data.  It shouldn't optimize this away.  */
   nbytes = (unsigned int) -1;
@@ -5173,23 +5326,25 @@ emit_leb128_expr (expressionS *exp, int sign)
       /* If we've got a constant, emit the thing directly right now.  */
 
       valueT value = exp->X_add_number;
-      int size;
+      unsigned int size;
       char *p;
 
       size = sizeof_leb128 (value, sign);
       p = frag_more (size);
-      output_leb128 (p, value, sign);
+      if (output_leb128 (p, value, sign) > size)
+       abort ();
     }
   else if (op == O_big)
     {
       /* O_big is a different sort of constant.  */
 
-      int size;
+      unsigned int size;
       char *p;
 
       size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
       p = frag_more (size);
-      output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
+      if (output_big_leb128 (p, generic_bignum, exp->X_add_number, sign) > size)
+       abort ();
     }
   else
     {
@@ -5226,6 +5381,10 @@ s_leb128 (int sign)
 static void
 stringer_append_char (int c, int bitsize)
 {
+  if (c && in_bss ())
+    as_bad (_("attempt to store non-empty string in section `%s'"),
+           segment_name (now_seg));
+
   if (!target_big_endian)
     FRAG_APPEND_1_CHAR (c);
 
@@ -5281,6 +5440,15 @@ stringer (int bits_appendzero)
   md_cons_align (1);
 #endif
 
+  /* If we have been switched into the abs_section then we
+     will not have an obstack onto which we can hang strings.  */
+  if (now_seg == absolute_section)
+    {
+      as_bad (_("strings must be placed into a section"));
+      ignore_rest_of_line ();
+      return;
+    }
+
   /* The following awkward logic is to parse ZERO or more strings,
      comma separated. Recall a string expression includes spaces
      before the opening '\"' and spaces after the closing '\"'.
@@ -5295,14 +5463,6 @@ stringer (int bits_appendzero)
     {
       c = ',';                 /* Do loop.  */
     }
-  /* If we have been switched into the abs_section then we
-     will not have an obstack onto which we can hang strings.  */
-  if (now_seg == absolute_section)
-    {
-      as_bad (_("strings must be placed into a section"));
-      c = 0;
-      ignore_rest_of_line ();
-    }
 
   while (c == ',' || c == '<' || c == '"')
     {
@@ -5386,7 +5546,7 @@ next_char_of_string (void)
 
 #ifndef NO_STRING_ESCAPES
     case '\\':
-      switch (c = *input_line_pointer++)
+      switch (c = *input_line_pointer++ & CHAR_MASK)
        {
        case 'b':
          c = '\b';
@@ -5437,7 +5597,7 @@ next_char_of_string (void)
                number = number * 8 + c - '0';
              }
 
-           c = number & 0xff;
+           c = number & CHAR_MASK;
          }
          --input_line_pointer;
          break;
@@ -5459,7 +5619,7 @@ next_char_of_string (void)
                  number = number * 16 + c - 'a' + 10;
                c = *input_line_pointer++;
              }
-           c = number & 0xff;
+           c = number & CHAR_MASK;
            --input_line_pointer;
          }
          break;
@@ -5697,7 +5857,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++)
        {
@@ -5800,8 +5960,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++)
     {
@@ -5830,16 +5990,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.  */
@@ -5931,11 +6090,10 @@ do_s_func (int end_p, const char *default_prefix)
          return;
        }
 
-      name = input_line_pointer;
-      delim1 = get_symbol_end ();
+      delim1 = get_symbol_name (& name);
       name = xstrdup (name);
       *input_line_pointer = delim1;
-      SKIP_WHITESPACE ();
+      SKIP_WHITESPACE_AFTER_NAME ();
       if (*input_line_pointer != ',')
        {
          if (default_prefix)
@@ -5961,10 +6119,9 @@ do_s_func (int end_p, const char *default_prefix)
        {
          ++input_line_pointer;
          SKIP_WHITESPACE ();
-         label = input_line_pointer;
-         delim2 = get_symbol_end ();
+         delim2 = get_symbol_name (& label);
          label = xstrdup (label);
-         *input_line_pointer = delim2;
+         restore_line_pointer (delim2);
        }
 
       if (debug_type == DEBUG_STABS)
This page took 0.042917 seconds and 4 git commands to generate.