gnulib: define the path to gnulib's parent dir
[binutils-gdb.git] / gas / read.c
index a65e56d16f99854ee6e49e96889ab36caaed0e0f..2f93e1bfd9625ff85b4eedb94f6283eae1222eec 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986-2020 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -64,7 +64,7 @@
 #endif
 
 char *input_line_pointer;      /*->next char of source file to parse.  */
-bfd_boolean input_from_string = FALSE;
+bool input_from_string = false;
 
 #if BITS_PER_CHAR != 8
 /*  The following table is indexed by[(char)] and will break if
@@ -364,9 +364,7 @@ static const pseudo_typeS potable[] = {
   {"common.s", s_mri_common, 1},
   {"data", s_data, 0},
   {"dc", cons, 2},
-#ifdef TC_ADDRESS_BYTES
   {"dc.a", cons, 0},
-#endif
   {"dc.b", cons, 1},
   {"dc.d", float_cons, 'd'},
   {"dc.l", cons, 4},
@@ -465,6 +463,7 @@ static const pseudo_typeS potable[] = {
   {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off.  */
   {"nopage", listing_nopage, 0},
+  {"nop", s_nop, 0},
   {"nops", s_nops, 0},
   {"octa", cons, 16},
   {"offset", s_struct, 0},
@@ -529,6 +528,9 @@ static const pseudo_typeS potable[] = {
   {"weakref", s_weakref, 0},
   {"word", cons, 2},
   {"zero", s_space, 0},
+  {"2byte", cons, 2},
+  {"4byte", cons, 4},
+  {"8byte", cons, 8},
   {NULL, NULL, 0}                      /* End sentinel.  */
 };
 
@@ -563,11 +565,14 @@ pop_insert (const pseudo_typeS *table)
   const pseudo_typeS *pop;
   for (pop = table; pop->poc_name; pop++)
     {
-      int exists = po_entry_find (po_hash, pop->poc_name) != NULL;
-      if (!pop_override_ok && exists)
-       as_fatal (_("error constructing %s pseudo-op table"), pop_table_name);
-      else if (!exists)
-       htab_insert (po_hash, po_entry_alloc (pop->poc_name, pop));
+      po_entry_t *elt = po_entry_alloc (pop->poc_name, pop);
+      if (htab_insert (po_hash, elt, 0) != NULL)
+       {
+         free (elt);
+         if (!pop_override_ok)
+           as_fatal (_("error constructing %s pseudo-op table"),
+                     pop_table_name);
+       }
     }
 }
 
@@ -788,7 +793,7 @@ assemble_one (char *line)
 
 #endif  /* HANDLE_BUNDLE */
 
-static bfd_boolean
+static bool
 in_bss (void)
 {
   flagword flags = bfd_section_flags (now_seg);
@@ -894,7 +899,7 @@ read_a_source_file (const char *name)
 #endif
       while (input_line_pointer < buffer_limit)
        {
-         bfd_boolean was_new_line;
+         bool was_new_line;
          /* We have more of this buffer to parse.  */
 
          /* We now have input_line_pointer->1st char of next line.
@@ -1002,8 +1007,7 @@ read_a_source_file (const char *name)
                      else
                        line_label = symbol_create (line_start,
                                                    absolute_section,
-                                                   (valueT) 0,
-                                                   &zero_address_frag);
+                                                   &zero_address_frag, 0);
 
                      next_char = restore_line_pointer (nul_char);
                      if (next_char == ':')
@@ -1316,7 +1320,7 @@ read_a_source_file (const char *name)
              char *tmp_buf = 0;
 
              s = input_line_pointer;
-             if (strncmp (s, "APP\n", 4))
+             if (!startswith (s, "APP\n"))
                {
                  /* We ignore it.  */
                  ignore_rest_of_line ();
@@ -1545,7 +1549,7 @@ static void
 s_align (signed int arg, int bytes_p)
 {
   unsigned int align_limit = TC_ALIGN_LIMIT;
-  unsigned int align;
+  addressT align;
   char *stop = NULL;
   char stopc = 0;
   offsetT fill = 0;
@@ -1592,7 +1596,7 @@ s_align (signed int arg, int bytes_p)
   if (align > align_limit)
     {
       align = align_limit;
-      as_warn (_("alignment too large: %u assumed"), align);
+      as_warn (_("alignment too large: %u assumed"), align_limit);
     }
 
   if (*input_line_pointer != ',')
@@ -2544,7 +2548,7 @@ bss_alloc (symbolS *symbolP, addressT size, unsigned int align)
     symbol_get_frag (symbolP)->fr_symbol = NULL;
 
   symbol_set_frag (symbolP, frag_now);
-  pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
+  pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size * OCTETS_PER_BYTE, NULL);
   *pfrag = 0;
 
 #ifdef S_SET_SIZE
@@ -3500,6 +3504,61 @@ s_space (int mult)
     mri_comment_end (stop, stopc);
 }
 
+void
+s_nop (int ignore ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+  fragS *start;
+  addressT start_off;
+  offsetT frag_off;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+  md_cons_align (1);
+#endif
+
+  SKIP_WHITESPACE ();
+  expression (&exp);
+  demand_empty_rest_of_line ();
+
+  start = frag_now;
+  start_off = frag_now_fix ();
+  do
+    {
+#ifdef md_emit_single_noop
+      md_emit_single_noop;
+#else
+      char *nop;
+
+#ifndef md_single_noop_insn
+#define md_single_noop_insn "nop"
+#endif
+      /* md_assemble might modify its argument, so
+        we must pass it a string that is writable.  */
+      if (asprintf (&nop, "%s", md_single_noop_insn) < 0)
+       as_fatal ("%s", xstrerror (errno));
+
+      /* Some targets assume that they can update input_line_pointer
+        inside md_assemble, and, worse, that they can leave it
+        assigned to the string pointer that was provided as an
+        argument.  So preserve ilp here.  */
+      char *saved_ilp = input_line_pointer;
+      md_assemble (nop);
+      input_line_pointer = saved_ilp;
+      free (nop);
+#endif
+#ifdef md_flush_pending_output
+      md_flush_pending_output ();
+#endif
+    } while (exp.X_op == O_constant
+            && exp.X_add_number > 0
+            && frag_offset_ignore_align_p (start, frag_now, &frag_off)
+            && frag_off + frag_now_fix () < start_off + exp.X_add_number);
+}
+
 void
 s_nops (int ignore ATTRIBUTE_UNUSED)
 {
@@ -3514,8 +3573,12 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
   md_cons_align (1);
 #endif
 
+  SKIP_WHITESPACE ();
   expression (&exp);
+  /* Note - this expression is tested for an absolute value in
+     write.c:relax_segment().  */
 
+  SKIP_WHITESPACE ();
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
@@ -3527,29 +3590,30 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
       val.X_add_number = 0;
     }
 
-  if (val.X_op == O_constant)
+  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;
-       }
+      as_bad (_("unsupported variable nop control in .nops directive"));
+      val.X_op = O_constant;
+      val.X_add_number = 0;
+    }
+  else if (val.X_add_number < 0)
+    {
+      as_warn (_("negative nop control byte, ignored"));
+      val.X_add_number = 0;
     }
-  else
-    as_bad (_("unsupported variable nop control in .nops directive"));
 
   demand_empty_rest_of_line ();
+
+  if (need_pass_2)
+    /* Ignore this directive if we are going to perform a second pass.  */
+    return;
+
+  /* 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;
 }
 
 /* This is like s_space, but the value is a floating point number with
@@ -4029,10 +4093,8 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long.  */
       return;
     }
 
-#ifdef TC_ADDRESS_BYTES
   if (nbytes == 0)
     nbytes = TC_ADDRESS_BYTES ();
-#endif
 
 #ifdef md_cons_align
   md_cons_align (nbytes);
@@ -4144,6 +4206,9 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
       goto err_out;
     case O_constant:
       exp.X_add_symbol = section_symbol (now_seg);
+      /* Mark the section symbol used in relocation so that it will be
+        included in the symbol table.  */
+      symbol_mark_used_in_reloc (exp.X_add_symbol);
       exp.X_op = O_symbol;
       /* Fallthru */
     case O_symbol:
@@ -4474,18 +4539,8 @@ emit_expr_with_reloc (expressionS *exp,
              || (get & hibit) == 0))
        {
          /* 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"),
-                  (unsigned long long) get, (unsigned long long) use);
-#else
-         as_warn (_("value 0x%I64x truncated to 0x%I64x"),
-                  (unsigned long long) get, (unsigned long long) use);
-#endif
-#else
-         as_warn (_("value 0x%lx truncated to 0x%lx"),
-                  (unsigned long) get, (unsigned long) use);
-#endif
+         as_warn (_("value 0x%" BFD_VMA_FMT "x truncated to 0x%" BFD_VMA_FMT "x"),
+                  get, use);
        }
       /* Put bytes in right order.  */
       md_number_to_chars (p, use, (int) nbytes);
@@ -5423,6 +5478,11 @@ stringer (int bits_appendzero)
          while (is_a_char (c = next_char_of_string ()))
            stringer_append_char (c, bitsize);
 
+         /* Treat "a" "b" as "ab".  Even if we are appending zeros.  */
+         SKIP_ALL_WHITESPACE ();
+         if (*input_line_pointer == '"')
+           break;
+
          if (append_zero)
            stringer_append_char (0, bitsize);
 
@@ -5669,12 +5729,12 @@ demand_copy_C_string (int *len_pointer)
 
       for (len = *len_pointer; len > 0; len--)
        {
-         if (*s == 0)
+         if (s[len - 1] == 0)
            {
              s = 0;
-             len = 1;
              *len_pointer = 0;
              as_bad (_("this string may not contain \'\\0\'"));
+             break;
            }
        }
     }
@@ -5835,7 +5895,16 @@ s_incbin (int x ATTRIBUTE_UNUSED)
   if (binfile)
     {
       long   file_len;
+      struct stat filestat;
 
+      if (fstat (fileno (binfile), &filestat) != 0
+         || ! S_ISREG (filestat.st_mode)
+         || S_ISDIR (filestat.st_mode))
+       {
+         as_bad (_("unable to include `%s'"), path);
+         goto done;
+       }
+      
       register_dependency (path);
 
       /* Compute the length of the file.  */
@@ -6291,7 +6360,7 @@ temp_ilp (char *buf)
 
   input_line_pointer = buf;
   buffer_limit = buf + strlen (buf);
-  input_from_string = TRUE;
+  input_from_string = true;
 }
 
 /* Restore a saved input line pointer.  */
@@ -6303,7 +6372,7 @@ restore_ilp (void)
 
   input_line_pointer = saved_ilp;
   buffer_limit = saved_limit;
-  input_from_string = FALSE;
+  input_from_string = false;
 
   saved_ilp = NULL;
 }