read.c s_include: use notes obstack for path
[binutils-gdb.git] / gas / read.c
index 6bba696cebca1ba38f61ae627e7bd5d76034f585..71bb30e4e70f5a928d6d8ff52b86c39be99a30d3 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -295,53 +295,7 @@ address_bytes (void)
 
 /* Set up pseudo-op tables.  */
 
-struct po_entry
-{
-  const char *poc_name;
-
-  const pseudo_typeS *pop;
-};
-
-typedef struct po_entry po_entry_t;
-
-/* Hash function for a po_entry.  */
-
-static hashval_t
-hash_po_entry (const void *e)
-{
-  const po_entry_t *entry = (const po_entry_t *) e;
-  return htab_hash_string (entry->poc_name);
-}
-
-/* Equality function for a po_entry.  */
-
-static int
-eq_po_entry (const void *a, const void *b)
-{
-  const po_entry_t *ea = (const po_entry_t *) a;
-  const po_entry_t *eb = (const po_entry_t *) b;
-
-  return strcmp (ea->poc_name, eb->poc_name) == 0;
-}
-
-static po_entry_t *
-po_entry_alloc (const char *poc_name, const pseudo_typeS *pop)
-{
-  po_entry_t *entry = XNEW (po_entry_t);
-  entry->poc_name = poc_name;
-  entry->pop = pop;
-  return entry;
-}
-
-static const pseudo_typeS *
-po_entry_find (htab_t table, const char *poc_name)
-{
-  po_entry_t needle = { poc_name, NULL };
-  po_entry_t *entry = htab_find (table, &needle);
-  return entry != NULL ? entry->pop : NULL;
-}
-
-static struct htab *po_hash;
+static htab_t po_hash;
 
 static const pseudo_typeS potable[] = {
   {"abort", s_abort, 0},
@@ -412,10 +366,8 @@ static const pseudo_typeS potable[] = {
   {"exitm", s_mexit, 0},
 /* extend  */
   {"extern", s_ignore, 0},     /* We treat all undef as ext.  */
-  {"appfile", s_app_file, 1},
-  {"appline", s_app_line, 1},
   {"fail", s_fail, 0},
-  {"file", s_app_file, 0},
+  {"file", s_file, 0},
   {"fill", s_fill, 0},
   {"float", float_cons, 'f'},
   {"format", s_ignore, 0},
@@ -448,7 +400,7 @@ static const pseudo_typeS potable[] = {
   {"irepc", s_irp, 1},
   {"lcomm", s_lcomm, 0},
   {"lflags", s_ignore, 0},     /* Listing flags.  */
-  {"linefile", s_app_line, 0},
+  {"linefile", s_linefile, 0},
   {"linkonce", s_linkonce, 0},
   {"list", listing_list, 1},   /* Turn listing on.  */
   {"llen", listing_psize, 1},
@@ -565,10 +517,8 @@ pop_insert (const pseudo_typeS *table)
   const pseudo_typeS *pop;
   for (pop = table; pop->poc_name; pop++)
     {
-      po_entry_t *elt = po_entry_alloc (pop->poc_name, pop);
-      if (htab_insert (po_hash, elt, 0) != NULL)
+      if (str_hash_insert (po_hash, pop->poc_name, pop, 0) != NULL)
        {
-         free (elt);
          if (!pop_override_ok)
            as_fatal (_("error constructing %s pseudo-op table"),
                      pop_table_name);
@@ -591,8 +541,7 @@ pop_insert (const pseudo_typeS *table)
 static void
 pobegin (void)
 {
-  po_hash = htab_create_alloc (16, hash_po_entry, eq_po_entry, NULL,
-                              xcalloc, xfree);
+  po_hash = str_htab_create ();
 
   /* Do the target-specific pseudo ops.  */
   pop_table_name = "md";
@@ -625,25 +574,6 @@ pobegin (void)
       continue;                                                                \
     }
 
-/* This function is used when scrubbing the characters between #APP
-   and #NO_APP.  */
-
-static char *scrub_string;
-static char *scrub_string_end;
-
-static size_t
-scrub_from_string (char *buf, size_t buflen)
-{
-  size_t copy;
-
-  copy = scrub_string_end - scrub_string;
-  if (copy > buflen)
-    copy = buflen;
-  memcpy (buf, scrub_string, copy);
-  scrub_string += copy;
-  return copy;
-}
-
 /* Helper function of read_a_source_file, which tries to expand a macro.  */
 static int
 try_macro (char term, const char *line)
@@ -658,7 +588,7 @@ try_macro (char term, const char *line)
        as_bad ("%s", err);
       *input_line_pointer++ = term;
       input_scrub_include_sb (&out,
-                             input_line_pointer, 1);
+                             input_line_pointer, expanding_macro);
       sb_kill (&out);
       buffer_limit =
        input_scrub_next_buffer (&input_line_pointer);
@@ -929,7 +859,7 @@ read_a_source_file (const char *name)
                  if (s != last_eol)
                    {
                      char *copy;
-                     int len;
+                     size_t len;
 
                      last_eol = s;
                      /* Copy it for safe keeping.  Also give an indication of
@@ -1120,7 +1050,7 @@ read_a_source_file (const char *name)
                    {
                      /* The MRI assembler uses pseudo-ops without
                         a period.  */
-                     pop = po_entry_find (po_hash, s);
+                     pop = str_hash_find (po_hash, s);
                      if (pop != NULL && pop->poc_handler == NULL)
                        pop = NULL;
                    }
@@ -1135,7 +1065,7 @@ read_a_source_file (const char *name)
                         already know that the pseudo-op begins with a '.'.  */
 
                      if (pop == NULL)
-                       pop = po_entry_find (po_hash, s + 1);
+                       pop = str_hash_find (po_hash, s + 1);
                      if (pop && !pop->poc_handler)
                        pop = NULL;
 
@@ -1266,7 +1196,7 @@ read_a_source_file (const char *name)
              while (ISDIGIT (*input_line_pointer))
                {
                  const long digit = *input_line_pointer - '0';
-                 if (temp > (LONG_MAX - digit) / 10)
+                 if (temp > (INT_MAX - digit) / 10)
                    {
                      as_bad (_("local label too large near %s"), backup);
                      temp = -1;
@@ -1314,10 +1244,7 @@ read_a_source_file (const char *name)
            {                   /* Its a comment.  Better say APP or NO_APP.  */
              sb sbuf;
              char *ends;
-             char *new_buf;
-             char *new_tmp;
-             unsigned int new_length;
-             char *tmp_buf = 0;
+             size_t len;
 
              s = input_line_pointer;
              if (!startswith (s, "APP\n"))
@@ -1330,91 +1257,32 @@ read_a_source_file (const char *name)
              s += 4;
 
              ends = strstr (s, "#NO_APP\n");
+             len = ends ? ends - s : buffer_limit - s;
 
+             sb_build (&sbuf, len + 100);
+             sb_add_buffer (&sbuf, s, len);
              if (!ends)
                {
-                 unsigned int tmp_len;
-                 unsigned int num;
-
                  /* The end of the #APP wasn't in this buffer.  We
                     keep reading in buffers until we find the #NO_APP
                     that goes with this #APP  There is one.  The specs
                     guarantee it...  */
-                 tmp_len = buffer_limit - s;
-                 tmp_buf = XNEWVEC (char, tmp_len + 1);
-                 memcpy (tmp_buf, s, tmp_len);
                  do
                    {
-                     new_tmp = input_scrub_next_buffer (&buffer);
-                     if (!new_tmp)
+                     buffer_limit = input_scrub_next_buffer (&buffer);
+                     if (!buffer_limit)
                        break;
-                     else
-                       buffer_limit = new_tmp;
-                     input_line_pointer = buffer;
                      ends = strstr (buffer, "#NO_APP\n");
-                     if (ends)
-                       num = ends - buffer;
-                     else
-                       num = buffer_limit - buffer;
-
-                     tmp_buf = XRESIZEVEC (char, tmp_buf, tmp_len + num);
-                     memcpy (tmp_buf + tmp_len, buffer, num);
-                     tmp_len += num;
+                     len = ends ? ends - buffer : buffer_limit - buffer;
+                     sb_add_buffer (&sbuf, buffer, len);
                    }
                  while (!ends);
-
-                 input_line_pointer = ends ? ends + 8 : NULL;
-
-                 s = tmp_buf;
-                 ends = s + tmp_len;
-
-               }
-             else
-               {
-                 input_line_pointer = ends + 8;
                }
 
-             scrub_string = s;
-             scrub_string_end = ends;
-
-             new_length = ends - s;
-             new_buf = XNEWVEC (char, new_length);
-             new_tmp = new_buf;
-             for (;;)
-               {
-                 size_t space;
-                 size_t size;
-
-                 space = (new_buf + new_length) - new_tmp;
-                 size = do_scrub_chars (scrub_from_string, new_tmp, space);
-
-                 if (size < space)
-                   {
-                     new_tmp[size] = 0;
-                     break;
-                   }
-
-                 new_buf = XRESIZEVEC (char, new_buf, new_length + 100);
-                 new_tmp = new_buf + new_length;
-                 new_length += 100;
-               }
-
-             free (tmp_buf);
-
-             /* We've "scrubbed" input to the preferred format.  In the
-                process we may have consumed the whole of the remaining
-                file (and included files).  We handle this formatted
-                input similar to that of macro expansion, letting
-                actual macro expansion (possibly nested) and other
-                input expansion work.  Beware that in messages, line
-                numbers and possibly file names will be incorrect.  */
-             new_length = strlen (new_buf);
-             sb_build (&sbuf, new_length);
-             sb_add_buffer (&sbuf, new_buf, new_length);
-             input_scrub_include_sb (&sbuf, input_line_pointer, 0);
+             input_line_pointer = ends ? ends + 8 : NULL;
+             input_scrub_include_sb (&sbuf, input_line_pointer, expanding_none);
              sb_kill (&sbuf);
              buffer_limit = input_scrub_next_buffer (&input_line_pointer);
-             free (new_buf);
              continue;
            }
 
@@ -1782,6 +1650,7 @@ read_symbol_name (void)
     {
       as_bad (_("expected symbol name"));
       ignore_rest_of_line ();
+      free (start);
       return NULL;
     }
 
@@ -1940,7 +1809,6 @@ s_mri_common (int small ATTRIBUTE_UNUSED)
   if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
     {
       as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
-      ignore_rest_of_line ();
       mri_comment_end (stop, stopc);
       return;
     }
@@ -2001,15 +1869,11 @@ s_data (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-/* Handle the .appfile pseudo-op.  This is automatically generated by
-   do_scrub_chars when a preprocessor # line comment is seen with a
-   file name.  This default definition may be overridden by the object
-   or CPU specific pseudo-ops.  This function is also the default
-   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
-   .file.  */
+/* Handle the .file pseudo-op.  This default definition may be overridden by
+   the object or CPU specific pseudo-ops.  */
 
 void
-s_app_file_string (char *file, int appfile ATTRIBUTE_UNUSED)
+s_file_string (char *file)
 {
 #ifdef LISTING
   if (listing)
@@ -2017,12 +1881,12 @@ s_app_file_string (char *file, int appfile ATTRIBUTE_UNUSED)
 #endif
   register_dependency (file);
 #ifdef obj_app_file
-  obj_app_file (file, appfile);
+  obj_app_file (file);
 #endif
 }
 
 void
-s_app_file (int appfile)
+s_file (int ignore ATTRIBUTE_UNUSED)
 {
   char *s;
   int length;
@@ -2030,8 +1894,7 @@ s_app_file (int appfile)
   /* Some assemblers tolerate immediately following '"'.  */
   if ((s = demand_copy_string (&length)) != 0)
     {
-      int may_omit
-       = (!new_logical_line_flags (s, -1, 1) && appfile);
+      new_logical_line_flags (s, -1, 1);
 
       /* In MRI mode, the preprocessor may have inserted an extraneous
         backquote.  */
@@ -2041,47 +1904,61 @@ s_app_file (int appfile)
        ++input_line_pointer;
 
       demand_empty_rest_of_line ();
-      if (!may_omit)
-       s_app_file_string (s, appfile);
+      s_file_string (s);
     }
 }
 
-static int
+static bool
 get_linefile_number (int *flag)
 {
+  expressionS exp;
+
   SKIP_WHITESPACE ();
 
   if (*input_line_pointer < '0' || *input_line_pointer > '9')
-    return 0;
+    return false;
 
-  *flag = get_absolute_expression ();
+  /* Don't mistakenly interpret octal numbers as line numbers.  */
+  if (*input_line_pointer == '0')
+    {
+      *flag = 0;
+      ++input_line_pointer;
+      return true;
+    }
 
-  return 1;
+  expression_and_evaluate (&exp);
+  if (exp.X_op != O_constant)
+    return false;
+
+#if defined (BFD64) || LONG_MAX > INT_MAX
+  if (exp.X_add_number < INT_MIN || exp.X_add_number > INT_MAX)
+    return false;
+#endif
+
+  *flag = exp.X_add_number;
+
+  return true;
 }
 
-/* Handle the .appline pseudo-op.  This is automatically generated by
+/* Handle the .linefile pseudo-op.  This is automatically generated by
    do_scrub_chars when a preprocessor # line comment is seen.  This
    default definition may be overridden by the object or CPU specific
    pseudo-ops.  */
 
 void
-s_app_line (int appline)
+s_linefile (int ignore ATTRIBUTE_UNUSED)
 {
   char *file = NULL;
-  int l;
+  int linenum, flags = 0;
 
   /* The given number is that of the next line.  */
-  if (appline)
-    l = get_absolute_expression ();
-  else if (!get_linefile_number (&l))
+  if (!get_linefile_number (&linenum))
     {
       ignore_rest_of_line ();
       return;
     }
 
-  l--;
-
-  if (l < -1)
+  if (linenum < 0)
     /* Some of the back ends can't deal with non-positive line numbers.
        Besides, it's silly.  GCC however will generate a line number of
        zero when it is pre-processing builtins for assembler-with-cpp files:
@@ -2092,74 +1969,75 @@ s_app_line (int appline)
        in the GCC and GDB testsuites.  So we check for negative line numbers
        rather than non-positive line numbers.  */
     as_warn (_("line numbers must be positive; line number %d rejected"),
-            l + 1);
+            linenum);
   else
     {
-      int flags = 0;
       int length = 0;
 
-      if (!appline)
+      SKIP_WHITESPACE ();
+
+      if (*input_line_pointer == '"')
+       file = demand_copy_string (&length);
+      else if (*input_line_pointer == '.')
        {
-         SKIP_WHITESPACE ();
+         /* buffer_and_nest() may insert this form.  */
+         ++input_line_pointer;
+         flags = 1 << 3;
+       }
 
-         if (*input_line_pointer == '"')
-           file = demand_copy_string (&length);
+      if (file)
+       {
+         int this_flag;
 
-         if (file)
-           {
-             int this_flag;
+         while (get_linefile_number (&this_flag))
+           switch (this_flag)
+             {
+               /* From GCC's cpp documentation:
+                  1: start of a new file.
+                  2: returning to a file after having included another file.
+                  3: following text comes from a system header file.
+                  4: following text should be treated as extern "C".
+
+                  4 is nonsensical for the assembler; 3, we don't care about,
+                  so we ignore it just in case a system header file is
+                  included while preprocessing assembly.  So 1 and 2 are all
+                  we care about, and they are mutually incompatible.
+                  new_logical_line_flags() demands this.  */
+             case 1:
+             case 2:
+               if (flags && flags != (1 << this_flag))
+                 as_warn (_("incompatible flag %i in line directive"),
+                          this_flag);
+               else
+                 flags |= 1 << this_flag;
+               break;
 
-             while (get_linefile_number (&this_flag))
-               switch (this_flag)
-                 {
-                   /* From GCC's cpp documentation:
-                      1: start of a new file.
-                      2: returning to a file after having included
-                         another file.
-                      3: following text comes from a system header file.
-                      4: following text should be treated as extern "C".
-
-                      4 is nonsensical for the assembler; 3, we don't
-                      care about, so we ignore it just in case a
-                      system header file is included while
-                      preprocessing assembly.  So 1 and 2 are all we
-                      care about, and they are mutually incompatible.
-                      new_logical_line_flags() demands this.  */
-                 case 1:
-                 case 2:
-                   if (flags && flags != (1 << this_flag))
-                     as_warn (_("incompatible flag %i in line directive"),
-                              this_flag);
-                   else
-                     flags |= 1 << this_flag;
-                   break;
-
-                 case 3:
-                 case 4:
-                   /* We ignore these.  */
-                   break;
-
-                 default:
-                   as_warn (_("unsupported flag %i in line directive"),
-                            this_flag);
-                   break;
-                 }
+             case 3:
+             case 4:
+               /* We ignore these.  */
+               break;
 
-             if (!is_end_of_line[(unsigned char)*input_line_pointer])
-               file = 0;
-           }
-       }
+             default:
+               as_warn (_("unsupported flag %i in line directive"),
+                        this_flag);
+               break;
+             }
+
+         if (!is_end_of_line[(unsigned char)*input_line_pointer])
+           file = NULL;
+        }
 
-      if (appline || file)
+      if (file || flags)
        {
-         new_logical_line_flags (file, l, flags);
+         linenum--;
+         new_logical_line_flags (file, linenum, flags);
 #ifdef LISTING
          if (listing)
-           listing_source_line (l);
+           listing_source_line (linenum);
 #endif
        }
     }
-  if (appline || file)
+  if (file || flags)
     demand_empty_rest_of_line ();
   else
     ignore_rest_of_line ();
@@ -2436,7 +2314,7 @@ s_irp (int irpc)
 
   sb_kill (&s);
 
-  input_scrub_include_sb (&out, input_line_pointer, 1);
+  input_scrub_include_sb (&out, input_line_pointer, expanding_repeat);
   sb_kill (&out);
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }
@@ -2790,10 +2668,10 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
        }
 
       if (((NO_PSEUDO_DOT || flag_m68k_mri)
-          && po_entry_find (po_hash, name) != NULL)
+          && str_hash_find (po_hash, name) != NULL)
          || (!flag_m68k_mri
              && *name == '.'
-             && po_entry_find (po_hash, name + 1) != NULL))
+             && str_hash_find (po_hash, name + 1) != NULL))
        as_warn_where (file,
                 line,
                 _("attempt to redefine pseudo-op `%s' ignored"),
@@ -3106,14 +2984,17 @@ s_rept (int ignore ATTRIBUTE_UNUSED)
 
   count = (size_t) get_absolute_expression ();
 
-  do_repeat (count, "REPT", "ENDR");
+  do_repeat (count, "REPT", "ENDR", NULL);
 }
 
 /* This function provides a generic repeat block implementation.   It allows
-   different directives to be used as the start/end keys.  */
+   different directives to be used as the start/end keys.  Any text matching
+   the optional EXPANDER in the block is replaced by the remaining iteration
+   count.  */
 
 void
-do_repeat (size_t count, const char *start, const char *end)
+do_repeat (size_t count, const char *start, const char *end,
+          const char *expander)
 {
   sb one;
   sb many;
@@ -3131,46 +3012,16 @@ do_repeat (size_t count, const char *start, const char *end)
       return;
     }
 
-  sb_build (&many, count * one.len);
-  while (count-- > 0)
-    sb_add_sb (&many, &one);
-
-  sb_kill (&one);
-
-  input_scrub_include_sb (&many, input_line_pointer, 1);
-  sb_kill (&many);
-  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
-}
-
-/* Like do_repeat except that any text matching EXPANDER in the
-   block is replaced by the iteration count.  */
-
-void
-do_repeat_with_expander (size_t count,
-                        const char * start,
-                        const char * end,
-                        const char * expander)
-{
-  sb one;
-  sb many;
-
-  if (((ssize_t) count) < 0)
+  if (expander == NULL || strstr (one.ptr, expander) == NULL)
     {
-      as_bad (_("negative count for %s - ignored"), start);
-      count = 0;
+      sb_build (&many, count * one.len);
+      while (count-- > 0)
+       sb_add_sb (&many, &one);
     }
-
-  sb_new (&one);
-  if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
+  else
     {
-      as_bad (_("%s without %s"), start, end);
-      return;
-    }
-
-  sb_new (&many);
+      sb_new (&many);
 
-  if (expander != NULL && strstr (one.ptr, expander) != NULL)
-    {
       while (count -- > 0)
        {
          int len;
@@ -3189,13 +3040,10 @@ do_repeat_with_expander (size_t count,
          sb_kill (& processed);
        }
     }
-  else
-    while (count-- > 0)
-      sb_add_sb (&many, &one);
 
   sb_kill (&one);
 
-  input_scrub_include_sb (&many, input_line_pointer, 1);
+  input_scrub_include_sb (&many, input_line_pointer, expanding_repeat);
   sb_kill (&many);
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }
@@ -3639,6 +3487,68 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
   *p = val.X_add_number;
 }
 
+/* Obtain the size of a floating point number, given a type.  */
+
+static int
+float_length (int float_type, int *pad_p)
+{
+  int length, pad = 0;
+
+  switch (float_type)
+    {
+    case 'b':
+    case 'B':
+    case 'h':
+    case 'H':
+      length = 2;
+      break;
+
+    case 'f':
+    case 'F':
+    case 's':
+    case 'S':
+      length = 4;
+      break;
+
+    case 'd':
+    case 'D':
+    case 'r':
+    case 'R':
+      length = 8;
+      break;
+
+    case 'x':
+    case 'X':
+#ifdef X_PRECISION
+      length = X_PRECISION * sizeof (LITTLENUM_TYPE);
+      pad = X_PRECISION_PAD * sizeof (LITTLENUM_TYPE);
+      if (!length)
+#endif
+       length = 12;
+      break;
+
+    case 'p':
+    case 'P':
+#ifdef P_PRECISION
+      length = P_PRECISION * sizeof (LITTLENUM_TYPE);
+      pad = P_PRECISION_PAD * sizeof (LITTLENUM_TYPE);
+      if (!length)
+#endif
+       length = 12;
+      break;
+
+    default:
+      as_bad (_("unknown floating type '%c'"), float_type);
+      length = -1;
+      break;
+    }
+
+  if (pad_p)
+    *pad_p = pad;
+
+  return length;
+}
+
 static int
 parse_one_float (int float_type, char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT])
 {
@@ -3709,16 +3619,19 @@ s_float_space (int float_type)
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad (_("missing value"));
-      ignore_rest_of_line ();
-      if (flag_mri)
-       mri_comment_end (stop, stopc);
-      return;
+      int pad;
+
+      flen = float_length (float_type, &pad);
+      if (flen >= 0)
+       memset (temp, 0, flen += pad);
     }
+  else
+    {
+      ++input_line_pointer;
 
-  ++input_line_pointer;
+      flen = parse_one_float (float_type, temp);
+    }
 
-  flen = parse_one_float (float_type, temp);
   if (flen < 0)
     {
       if (flag_mri)
@@ -3887,12 +3800,19 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
 \f
 
 /* Verify that we are at the end of a line.  If not, issue an error and
-   skip to EOL.  */
+   skip to EOL.  This function may leave input_line_pointer one past
+   buffer_limit, so should not be called from places that may
+   dereference input_line_pointer unconditionally.  Note that when the
+   gas parser is switched to handling a string (where buffer_limit
+   should be the size of the string excluding the NUL terminator) this
+   will be one past the NUL; is_end_of_line(0) returns true.  */
 
 void
 demand_empty_rest_of_line (void)
 {
   SKIP_WHITESPACE ();
+  if (input_line_pointer > buffer_limit)
+    return;
   if (is_end_of_line[(unsigned char) *input_line_pointer])
     input_line_pointer++;
   else
@@ -3905,26 +3825,22 @@ demand_empty_rest_of_line (void)
                 *input_line_pointer);
       ignore_rest_of_line ();
     }
-
   /* Return pointing just after end-of-line.  */
-  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
 /* Silently advance to the end of line.  Use this after already having
-   issued an error about something bad.  */
+   issued an error about something bad.  Like demand_empty_rest_of_line,
+   this function may leave input_line_pointer one after buffer_limit;
+   Don't call it from within expression parsing code in an attempt to
+   silence further errors.  */
 
 void
 ignore_rest_of_line (void)
 {
-  while (input_line_pointer < buffer_limit
-        && !is_end_of_line[(unsigned char) *input_line_pointer])
-    input_line_pointer++;
-
-  input_line_pointer++;
-
+  while (input_line_pointer <= buffer_limit)
+    if (is_end_of_line[(unsigned char) *input_line_pointer++])
+      break;
   /* Return pointing just after end-of-line.  */
-  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
@@ -4847,39 +4763,11 @@ parse_repeat_cons (expressionS *exp, unsigned int nbytes)
 static int
 hex_float (int float_type, char *bytes)
 {
-  int length;
+  int pad, length = float_length (float_type, &pad);
   int i;
 
-  switch (float_type)
-    {
-    case 'f':
-    case 'F':
-    case 's':
-    case 'S':
-      length = 4;
-      break;
-
-    case 'd':
-    case 'D':
-    case 'r':
-    case 'R':
-      length = 8;
-      break;
-
-    case 'x':
-    case 'X':
-      length = 12;
-      break;
-
-    case 'p':
-    case 'P':
-      length = 12;
-      break;
-
-    default:
-      as_bad (_("unknown floating type type '%c'"), float_type);
-      return -1;
-    }
+  if (length < 0)
+    return length;
 
   /* It would be nice if we could go through expression to parse the
      hex constant, but if we get a bignum it's a pain to sort it into
@@ -4926,7 +4814,9 @@ hex_float (int float_type, char *bytes)
        memset (bytes, 0, length - i);
     }
 
-  return length;
+  memset (bytes + length, 0, pad);
+
+  return length + pad;
 }
 
 /*                     float_cons()
@@ -5603,7 +5493,7 @@ next_char_of_string (void)
        case '8':
        case '9':
          {
-           long number;
+           unsigned number;
            int i;
 
            for (i = 0, number = 0;
@@ -5621,7 +5511,7 @@ next_char_of_string (void)
        case 'x':
        case 'X':
          {
-           long number;
+           unsigned number;
 
            number = 0;
            c = *input_line_pointer++;
@@ -5989,8 +5879,7 @@ s_include (int arg ATTRIBUTE_UNUSED)
     }
 
   demand_empty_rest_of_line ();
-  path = XNEWVEC (char, (unsigned long) i
-                 + include_dir_maxlen + 5 /* slop */ );
+  path = notes_alloc ((size_t) i + include_dir_maxlen + 5);
 
   for (i = 0; i < include_dir_count; i++)
     {
@@ -6004,10 +5893,9 @@ s_include (int arg ATTRIBUTE_UNUSED)
        }
     }
 
-  free (path);
+  notes_free (path);
   path = filename;
  gotit:
-  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY.  */
   register_dependency (path);
   input_scrub_insert_file (path);
 }
@@ -6266,7 +6154,7 @@ input_scrub_insert_line (const char *line)
   size_t len = strlen (line);
   sb_build (&newline, len);
   sb_add_buffer (&newline, line, len);
-  input_scrub_include_sb (&newline, input_line_pointer, 0);
+  input_scrub_include_sb (&newline, input_line_pointer, expanding_none);
   sb_kill (&newline);
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }