or1k: add support for l.swa/l.lwa atomic instructions
[deliverable/binutils-gdb.git] / gas / read.c
index b47c74a0884b3b528dc40e2b02f433106caad3fe..8e1b06edf6bdad5e0f412bc1b22de8f57ef4ac1c 100644 (file)
@@ -1,7 +1,5 @@
 /* read.c - read a source file -
-   Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012  Free Software Foundation, Inc.
+   Copyright (C) 1986-2014 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -40,6 +38,7 @@
 #include "obstack.h"
 #include "ecoff.h"
 #include "dw2gencfi.h"
+#include "wchar.h"
 
 #ifndef TC_START_LABEL
 #define TC_START_LABEL(x,y,z) (x == ':')
@@ -232,6 +231,10 @@ static unsigned int bundle_align_p2;
    we are expecting to see .bundle_unlock.  */
 static fragS *bundle_lock_frag;
 static frchainS *bundle_lock_frchain;
+
+/* This is incremented by .bundle_lock and decremented by .bundle_unlock,
+   to allow nesting.  */
+static unsigned int bundle_lock_depth;
 #endif
 
 static void do_s_func (int end_p, const char *default_prefix);
@@ -239,14 +242,11 @@ 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);
-#ifdef OBJ_ELF
-static void s_gnu_attribute (int);
-#endif
 static void s_reloc (int);
 static int hex_float (int, char *);
 static segT get_known_segmented_expression (expressionS * expP);
 static void pobegin (void);
-static int get_non_macro_line_sb (sb *);
+static size_t get_non_macro_line_sb (sb *);
 static void generate_file_debug (void);
 static char *_find_end_of_line (char *, int, int, int);
 \f
@@ -263,8 +263,11 @@ read_begin (void)
   obstack_begin (&notes, chunksize);
   obstack_begin (&cond_obstack, chunksize);
 
+#ifndef tc_line_separator_chars
+#define tc_line_separator_chars line_separator_chars
+#endif
   /* Use machine dependent syntax.  */
-  for (p = line_separator_chars; *p; p++)
+  for (p = tc_line_separator_chars; *p; p++)
     is_end_of_line[(unsigned char) *p] = 2;
   /* Use more.  FIXME-SOMEDAY.  */
 
@@ -373,9 +376,6 @@ static const pseudo_typeS potable[] = {
   {"func", s_func, 0},
   {"global", s_globl, 0},
   {"globl", s_globl, 0},
-#ifdef OBJ_ELF
-  {"gnu_attribute", s_gnu_attribute, 0},
-#endif
   {"hword", cons, 2},
   {"if", s_if, (int) O_ne},
   {"ifb", s_ifb, 1},
@@ -574,10 +574,10 @@ pobegin (void)
 static char *scrub_string;
 static char *scrub_string_end;
 
-static int
-scrub_from_string (char *buf, int buflen)
+static size_t
+scrub_from_string (char *buf, size_t buflen)
 {
-  int copy;
+  size_t copy;
 
   copy = scrub_string_end - scrub_string;
   if (copy > buflen)
@@ -692,7 +692,7 @@ finish_bundle (fragS *frag, unsigned int size)
 static void
 assemble_one (char *line)
 {
-  fragS *insn_start_frag;
+  fragS *insn_start_frag = NULL;
 
   if (bundle_lock_frchain != NULL && bundle_lock_frchain != frchain_now)
     {
@@ -1176,7 +1176,6 @@ read_a_source_file (char *name)
              bump_line_counters ();
              s += 4;
 
-             sb_new (&sbuf);
              ends = strstr (s, "#NO_APP\n");
 
              if (!ends)
@@ -1230,8 +1229,8 @@ read_a_source_file (char *name)
              new_tmp = new_buf;
              for (;;)
                {
-                 int space;
-                 int size;
+                 size_t space;
+                 size_t size;
 
                  space = (new_buf + new_length) - new_tmp;
                  size = do_scrub_chars (scrub_from_string, new_tmp, space);
@@ -1257,7 +1256,9 @@ read_a_source_file (char *name)
                 actual macro expansion (possibly nested) and other
                 input expansion work.  Beware that in messages, line
                 numbers and possibly file names will be incorrect.  */
-             sb_add_string (&sbuf, new_buf);
+             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);
              sb_kill (&sbuf);
              buffer_limit = input_scrub_next_buffer (&input_line_pointer);
@@ -1287,6 +1288,7 @@ read_a_source_file (char *name)
                    _(".bundle_lock with no matching .bundle_unlock"));
       bundle_lock_frag = NULL;
       bundle_lock_frchain = NULL;
+      bundle_lock_depth = 0;
     }
 #endif
 
@@ -1305,10 +1307,10 @@ read_a_source_file (char *name)
 }
 
 /* Convert O_constant expression EXP into the equivalent O_big representation.
-   Take the sign of the number from X_unsigned rather than X_add_number.  */
+   Take the sign of the number from SIGN rather than X_add_number.  */
 
 static void
-convert_to_bignum (expressionS *exp)
+convert_to_bignum (expressionS *exp, int sign)
 {
   valueT value;
   unsigned int i;
@@ -1321,8 +1323,8 @@ convert_to_bignum (expressionS *exp)
     }
   /* Add a sequence of sign bits if the top bit of X_add_number is not
      the sign of the original value.  */
-  if ((exp->X_add_number < 0) != !exp->X_unsigned)
-    generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK;
+  if ((exp->X_add_number < 0) == !sign)
+    generic_bignum[i++] = sign ? LITTLENUM_MASK : 0;
   exp->X_op = O_big;
   exp->X_add_number = i;
 }
@@ -1583,13 +1585,106 @@ s_altmacro (int on)
   macro_set_alternate (on);
 }
 
+/* Read a symbol name from input_line_pointer.
+
+   Stores the symbol name in a buffer and returns a pointer to this buffer.
+   The buffer is xalloc'ed.  It is the caller's responsibility to free
+   this buffer.
+
+   The name is not left in the i_l_p buffer as it may need processing
+   to handle escape characters.
+
+   Advances i_l_p to the next non-whitespace character.
+
+   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 *
+read_symbol_name (void)
+{
+  char * name;
+  char * start;
+  char c;
+
+  c = *input_line_pointer++;
+
+  if (c == '"')
+    {
+#define SYM_NAME_CHUNK_LEN 128
+      ptrdiff_t len = SYM_NAME_CHUNK_LEN;
+      char * name_end;
+      unsigned int C;
+
+      start = name = xmalloc (len + 1);
+
+      name_end = name + SYM_NAME_CHUNK_LEN;
+
+      while (is_a_char (C = next_char_of_string ()))
+       {
+         if (name >= name_end)
+           {
+             ptrdiff_t sofar;
+
+             sofar = name - start;
+             len += SYM_NAME_CHUNK_LEN;
+             start = xrealloc (start, len + 1);
+             name_end = start + len;
+             name = start + sofar;
+           }
+
+         *name++ = (char) C;
+       }
+      *name = 0;
+
+      /* Since quoted symbol names can contain non-ASCII characters,
+        check the string and warn if it cannot be recognised by the
+        current character set.  */
+      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')
+    {
+      ptrdiff_t len;
+
+      name = input_line_pointer - 1;
+
+      /* We accept \001 in a name in case this is
+        being called with a constructed string.  */
+      while (is_part_of_name (c = *input_line_pointer++)
+            || c == '\001')
+       ;
+
+      len = (input_line_pointer - name) - 1;
+      start = xmalloc (len + 1);
+
+      memcpy (start, name, len);
+      start[len] = 0;
+
+      /* Skip a name ender char if one is present.  */
+      if (! is_name_ender (c))
+       --input_line_pointer;
+    }
+  else
+    name = start = NULL;
+
+  if (name == start)
+    {
+      as_bad (_("expected symbol name"));
+      ignore_rest_of_line ();
+      return NULL;
+    }
+
+  SKIP_WHITESPACE ();
+
+  return start;
+}
+
+
 symbolS *
 s_comm_internal (int param,
                 symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
 {
   char *name;
-  char c;
-  char *p;
   offsetT temp, size;
   symbolS *symbolP = NULL;
   char *stop = NULL;
@@ -1599,20 +1694,8 @@ s_comm_internal (int param,
   if (flag_mri)
     stop = mri_comment_field (&stopc);
 
-  name = input_line_pointer;
-  c = get_symbol_end ();
-  /* Just after name is now '\0'.  */
-  p = input_line_pointer;
-  *p = c;
-
-  if (name == p)
-    {
-      as_bad (_("expected symbol name"));
-      ignore_rest_of_line ();
-      goto out;
-    }
-
-  SKIP_WHITESPACE ();
+  if ((name = read_symbol_name ()) == NULL)
+    goto out;
 
   /* Accept an optional comma after the name.  The comma used to be
      required, but Irix 5 cc does not generate it for .lcomm.  */
@@ -1635,7 +1718,6 @@ s_comm_internal (int param,
       goto out;
     }
 
-  *p = 0;
   symbolP = symbol_find_or_make (name);
   if ((S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
       && !S_IS_COMMON (symbolP))
@@ -1644,7 +1726,6 @@ s_comm_internal (int param,
        {
          symbolP = NULL;
          as_bad (_("symbol `%s' is already defined"), name);
-         *p = c;
          ignore_rest_of_line ();
          goto out;
        }
@@ -1662,7 +1743,6 @@ s_comm_internal (int param,
     as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
             name, (long) size, (long) temp);
 
-  *p = c;
   if (comm_parse_extra != NULL)
     symbolP = (*comm_parse_extra) (param, symbolP, size);
   else
@@ -1676,6 +1756,8 @@ s_comm_internal (int param,
  out:
   if (flag_mri)
     mri_comment_end (stop, stopc);
+  if (name != NULL)
+    free (name);
   return symbolP;
 }
 
@@ -2179,12 +2261,12 @@ s_globl (int ignore ATTRIBUTE_UNUSED)
 
   do
     {
-      name = input_line_pointer;
-      c = get_symbol_end ();
+      if ((name = read_symbol_name ()) == NULL)
+       return;
+
       symbolP = symbol_find_or_make (name);
       S_SET_EXTERNAL (symbolP);
 
-      *input_line_pointer = c;
       SKIP_WHITESPACE ();
       c = *input_line_pointer;
       if (c == ',')
@@ -2194,6 +2276,8 @@ s_globl (int ignore ATTRIBUTE_UNUSED)
          if (is_end_of_line[(unsigned char) *input_line_pointer])
            c = '\n';
        }
+
+      free (name);
     }
   while (c == ',');
 
@@ -2203,139 +2287,6 @@ s_globl (int ignore ATTRIBUTE_UNUSED)
     mri_comment_end (stop, stopc);
 }
 
-#ifdef OBJ_ELF
-#define skip_whitespace(str)  do { if (*(str) == ' ') ++(str); } while (0)
-
-static inline int
-skip_past_char (char ** str, char c)
-{
-  if (**str == c)
-    {
-      (*str)++;
-      return 0;
-    }
-  else
-    return -1;
-}
-#define skip_past_comma(str) skip_past_char (str, ',')
-
-/* Parse an attribute directive for VENDOR.
-   Returns the attribute number read, or zero on error.  */
-int
-s_vendor_attribute (int vendor)
-{
-  expressionS exp;
-  int type;
-  int tag;
-  unsigned int i = 0;
-  char *s = NULL;
-
-  /* Read the first number or name.  */
-  skip_whitespace (input_line_pointer);
-  s = input_line_pointer;
-  if (ISDIGIT (*input_line_pointer))
-    {
-      expression (& exp);
-      if (exp.X_op != O_constant)
-       goto bad;
-      tag = exp.X_add_number;
-    }
-  else
-    {
-      char *name;
-
-      /* A name may contain '_', but no other punctuation.  */
-      for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_';
-          ++input_line_pointer)
-       i++;
-      if (i == 0)
-       goto bad;
-
-      name = (char *) alloca (i + 1);
-      memcpy (name, s, i);
-      name[i] = '\0';
-
-#ifndef CONVERT_SYMBOLIC_ATTRIBUTE
-#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1
-#endif
-
-      tag = CONVERT_SYMBOLIC_ATTRIBUTE (name);
-      if (tag == -1)
-       {
-         as_bad (_("Attribute name not recognised: %s"), name);
-         ignore_rest_of_line ();
-         return 0;
-       }
-    }
-
-  type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
-
-  if (skip_past_comma (&input_line_pointer) == -1)
-    goto bad;
-  if (type & 1)
-    {
-      expression (& exp);
-      if (exp.X_op != O_constant)
-       {
-         as_bad (_("expected numeric constant"));
-         ignore_rest_of_line ();
-         return 0;
-       }
-      i = exp.X_add_number;
-    }
-  if ((type & 3) == 3
-      && skip_past_comma (&input_line_pointer) == -1)
-    {
-      as_bad (_("expected comma"));
-      ignore_rest_of_line ();
-      return 0;
-    }
-  if (type & 2)
-    {
-      int len;
-
-      skip_whitespace (input_line_pointer);
-      if (*input_line_pointer != '"')
-       goto bad_string;
-      s = demand_copy_C_string (&len);
-    }
-
-  switch (type & 3)
-    {
-    case 3:
-      bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s);
-      break;
-    case 2:
-      bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
-      break;
-    case 1:
-      bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
-      break;
-    default:
-      abort ();
-    }
-
-  demand_empty_rest_of_line ();
-  return tag;
-bad_string:
-  as_bad (_("bad string constant"));
-  ignore_rest_of_line ();
-  return 0;
-bad:
-  as_bad (_("expected <tag> , <value>"));
-  ignore_rest_of_line ();
-  return 0;
-}
-
-/* Parse a .gnu_attribute directive.  */
-
-static void
-s_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
-{
-  s_vendor_attribute (OBJ_ATTR_GNU);
-}
-#endif /* OBJ_ELF */
-
 /* Handle the MRI IRP and IRPC pseudo-ops.  */
 
 void
@@ -2349,8 +2300,8 @@ s_irp (int irpc)
 
   as_where (&file, &line);
 
-  sb_new (&s);
   eol = find_end_of_line (input_line_pointer, 0);
+  sb_build (&s, eol - input_line_pointer);
   sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer);
   input_line_pointer = eol;
 
@@ -2580,33 +2531,17 @@ void
 s_lsym (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
-  char c;
-  char *p;
   expressionS exp;
   symbolS *symbolP;
 
   /* We permit ANY defined expression: BSD4.2 demands constants.  */
-  name = input_line_pointer;
-  c = get_symbol_end ();
-  p = input_line_pointer;
-  *p = c;
-
-  if (name == p)
-    {
-      as_bad (_("expected symbol name"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  SKIP_WHITESPACE ();
+  if ((name = read_symbol_name ()) == NULL)
+    return;
 
   if (*input_line_pointer != ',')
     {
-      *p = 0;
       as_bad (_("expected comma after \"%s\""), name);
-      *p = c;
-      ignore_rest_of_line ();
-      return;
+      goto err_out;
     }
 
   input_line_pointer++;
@@ -2616,11 +2551,9 @@ s_lsym (int ignore ATTRIBUTE_UNUSED)
       && exp.X_op != O_register)
     {
       as_bad (_("bad expression"));
-      ignore_rest_of_line ();
-      return;
+      goto err_out;
     }
 
-  *p = 0;
   symbolP = symbol_find_or_make (name);
 
   if (S_GET_SEGMENT (symbolP) == undefined_section)
@@ -2638,8 +2571,14 @@ s_lsym (int ignore ATTRIBUTE_UNUSED)
       as_bad (_("symbol `%s' is already defined"), name);
     }
 
-  *p = c;
   demand_empty_rest_of_line ();
+  free (name);
+  return;
+
+ err_out:
+  ignore_rest_of_line ();
+  free (name);
+  return;
 }
 
 /* Read a line into an sb.  Returns the character that ended the line
@@ -2672,13 +2611,13 @@ get_line_sb (sb *line, int in_macro)
   return *input_line_pointer++;
 }
 
-static int
+static size_t
 get_non_macro_line_sb (sb *line)
 {
   return get_line_sb (line, 0);
 }
 
-static int
+static size_t
 get_macro_line_sb (sb *line)
 {
   return get_line_sb (line, 1);
@@ -2697,17 +2636,20 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
 
   as_where (&file, &line);
 
-  sb_new (&s);
   eol = find_end_of_line (input_line_pointer, 0);
+  sb_build (&s, eol - input_line_pointer);
   sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer);
   input_line_pointer = eol;
 
   if (line_label != NULL)
     {
       sb label;
+      size_t len;
 
-      sb_new (&label);
-      sb_add_string (&label, S_GET_NAME (line_label));
+      name = S_GET_NAME (line_label);
+      len = strlen (name);
+      sb_build (&label, len);
+      sb_add_buffer (&label, name, len);
       err = define_macro (0, &s, &label, get_macro_line_sb, file, line, &name);
       sb_kill (&label);
     }
@@ -3131,7 +3073,7 @@ do_repeat (int count, const char *start, const char *end)
       return;
     }
 
-  sb_new (&many);
+  sb_build (&many, count * one.len);
   while (count-- > 0)
     sb_add_sb (&many, &one);
 
@@ -3171,7 +3113,7 @@ do_repeat_with_expander (int count,
          char * sub;
          sb processed;
 
-         sb_new (& processed);
+         sb_build (& processed, one.len);
          sb_add_sb (& processed, & one);
          sub = strstr (processed.ptr, expander);
          len = sprintf (sub, "%d", count);
@@ -3283,42 +3225,25 @@ void
 s_set (int equiv)
 {
   char *name;
-  char delim;
-  char *end_name;
 
   /* Especial apologies for the random logic:
      this just grew, and could be parsed much more simply!
      Dean in haste.  */
-  name = input_line_pointer;
-  delim = get_symbol_end ();
-  end_name = input_line_pointer;
-  *end_name = delim;
-
-  if (name == end_name)
-    {
-      as_bad (_("expected symbol name"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  SKIP_WHITESPACE ();
+  if ((name = read_symbol_name ()) == NULL)
+    return;
 
   if (*input_line_pointer != ',')
     {
-      *end_name = 0;
       as_bad (_("expected comma after \"%s\""), name);
-      *end_name = delim;
       ignore_rest_of_line ();
+      free (name);
       return;
     }
 
   input_line_pointer++;
-  *end_name = 0;
-
   assign_symbol (name, equiv);
-  *end_name = delim;
-
   demand_empty_rest_of_line ();
+  free (name);
 }
 
 void
@@ -3622,23 +3547,12 @@ void
 s_weakref (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
-  char delim;
-  char *end_name;
   symbolS *symbolP;
   symbolS *symbolP2;
   expressionS exp;
 
-  name = input_line_pointer;
-  delim = get_symbol_end ();
-  end_name = input_line_pointer;
-
-  if (name == end_name)
-    {
-      as_bad (_("expected symbol name"));
-      *end_name = delim;
-      ignore_rest_of_line ();
-      return;
-    }
+  if ((name = read_symbol_name ()) == NULL)
+    return;
 
   symbolP = symbol_find_or_make (name);
 
@@ -3647,41 +3561,27 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
       if (!S_IS_VOLATILE (symbolP))
        {
          as_bad (_("symbol `%s' is already defined"), name);
-         *end_name = delim;
-         ignore_rest_of_line ();
-         return;
+         goto err_out;
        }
       symbolP = symbol_clone (symbolP, 1);
       S_CLEAR_VOLATILE (symbolP);
     }
 
-  *end_name = delim;
-
   SKIP_WHITESPACE ();
 
   if (*input_line_pointer != ',')
     {
-      *end_name = 0;
       as_bad (_("expected comma after \"%s\""), name);
-      *end_name = delim;
-      ignore_rest_of_line ();
-      return;
+      goto err_out;
     }
 
   input_line_pointer++;
 
   SKIP_WHITESPACE ();
+  free (name);
 
-  name = input_line_pointer;
-  delim = get_symbol_end ();
-  end_name = input_line_pointer;
-
-  if (name == end_name)
-    {
-      as_bad (_("expected symbol name"));
-      ignore_rest_of_line ();
-      return;
-    }
+  if ((name = read_symbol_name ()) == NULL)
+    return;
 
   if ((symbolP2 = symbol_find_noref (name, 1)) == NULL
       && (symbolP2 = md_undefined_symbol (name)) == NULL)
@@ -3712,6 +3612,7 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
          while (symp != symbolP)
            {
              char *old_loop = loop;
+
              symp = symbol_get_value_expression (symp)->X_add_symbol;
              loop = concat (loop, " => ", S_GET_NAME (symp),
                             (const char *) NULL);
@@ -3722,8 +3623,7 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
                  S_GET_NAME (symbolP), loop);
 
          free (loop);
-
-         *end_name = delim;
+         free (name);
          ignore_rest_of_line ();
          return;
        }
@@ -3734,8 +3634,6 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
       /* symbolP2 = symp; */
     }
 
-  *end_name = delim;
-
   memset (&exp, 0, sizeof (exp));
   exp.X_op = O_symbol;
   exp.X_add_symbol = symbolP2;
@@ -3746,6 +3644,13 @@ s_weakref (int ignore ATTRIBUTE_UNUSED)
   S_SET_WEAKREFR (symbolP);
 
   demand_empty_rest_of_line ();
+  free (name);
+  return;
+
+ err_out:
+  ignore_rest_of_line ();
+  free (name);
+  return;
 }
 \f
 
@@ -3946,19 +3851,22 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes);
 
 #ifndef TC_PARSE_CONS_EXPRESSION
 #ifdef BITFIELD_CONS_EXPRESSIONS
-#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
+#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)
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
+  (parse_repeat_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE)
 static void
 parse_repeat_cons (expressionS *exp, unsigned int nbytes);
 #endif
 
 /* If we haven't gotten one yet, just call expression.  */
 #ifndef TC_PARSE_CONS_EXPRESSION
-#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
+  (expression (EXP), TC_PARSE_CONS_RETURN_NONE)
 #endif
 #endif
 
@@ -3966,7 +3874,7 @@ void
 do_parse_cons_expression (expressionS *exp,
                          int nbytes ATTRIBUTE_UNUSED)
 {
-  TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+  (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes);
 }
 
 
@@ -4009,6 +3917,14 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long.  */
   c = 0;
   do
     {
+      TC_PARSE_CONS_RETURN_TYPE ret = TC_PARSE_CONS_RETURN_NONE;
+#ifdef TC_CONS_FIX_CHECK
+      fixS **cur_fix = &frchain_now->fix_tail;
+
+      if (*cur_fix != NULL)
+       cur_fix = &(*cur_fix)->fx_next;
+#endif
+
 #ifdef TC_M68K
       if (flag_m68k_mri)
        parse_mri_cons (&exp, (unsigned int) nbytes);
@@ -4021,7 +3937,7 @@ cons_worker (int nbytes,  /* 1=.byte, 2=.word, 4=.long.  */
              ignore_rest_of_line ();
              return;
            }
-         TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
+         ret = TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
        }
 
       if (rva)
@@ -4031,7 +3947,10 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long.  */
          else
            as_fatal (_("rva without symbol"));
        }
-      emit_expr (&exp, (unsigned int) nbytes);
+      emit_expr_with_reloc (&exp, (unsigned int) nbytes, ret);
+#ifdef TC_CONS_FIX_CHECK
+      TC_CONS_FIX_CHECK (&exp, nbytes, *cur_fix);
+#endif
       ++c;
     }
   while (*input_line_pointer++ == ',');
@@ -4174,6 +4093,14 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
 
 void
 emit_expr (expressionS *exp, unsigned int nbytes)
+{
+  emit_expr_with_reloc (exp, nbytes, TC_PARSE_CONS_RETURN_NONE);
+}
+
+void
+emit_expr_with_reloc (expressionS *exp,
+                     unsigned int nbytes,
+                     TC_PARSE_CONS_RETURN_TYPE reloc)
 {
   operatorT op;
   char *p;
@@ -4183,10 +4110,9 @@ emit_expr (expressionS *exp, unsigned int nbytes)
   if (need_pass_2)
     return;
 
-  /* Grow the current frag now so that dot_value does not get invalidated
-     if the frag were to fill up in the frag_more() call below.  */
   frag_grow (nbytes);
   dot_value = frag_now_fix ();
+  dot_frag = frag_now;
 
 #ifndef NO_LISTING
 #ifdef OBJ_ELF
@@ -4317,6 +4243,12 @@ emit_expr (expressionS *exp, unsigned int nbytes)
 
   p = frag_more ((int) nbytes);
 
+  if (reloc != TC_PARSE_CONS_RETURN_NONE)
+    {
+      emit_expr_fix (exp, nbytes, frag_now, p, reloc);
+      return;
+    }
+
 #ifndef WORKING_DOT_WORD
   /* If we have the difference of two symbols in a word, save it on
      the broken_words list.  See the code in write.c.  */
@@ -4347,7 +4279,7 @@ emit_expr (expressionS *exp, unsigned int nbytes)
   if (op == O_constant && nbytes > sizeof (valueT))
     {
       extra_digit = exp->X_unsigned ? 0 : -1;
-      convert_to_bignum (exp);
+      convert_to_bignum (exp, !exp->X_unsigned);
       op = O_big;
     }
 
@@ -4475,23 +4407,41 @@ emit_expr (expressionS *exp, unsigned int nbytes)
        }
     }
   else
-    emit_expr_fix (exp, nbytes, frag_now, p);
+    emit_expr_fix (exp, nbytes, frag_now, p, TC_PARSE_CONS_RETURN_NONE);
 }
 
 void
-emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p)
+emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p,
+              TC_PARSE_CONS_RETURN_TYPE r ATTRIBUTE_UNUSED)
 {
-  memset (p, 0, nbytes);
+  int offset = 0;
+  unsigned int size = nbytes;
+
+  memset (p, 0, size);
 
   /* Generate a fixS to record the symbol value.  */
 
 #ifdef TC_CONS_FIX_NEW
-  TC_CONS_FIX_NEW (frag, p - frag->fr_literal, nbytes, exp);
+  TC_CONS_FIX_NEW (frag, p - frag->fr_literal + offset, size, exp, r);
 #else
-  {
-    bfd_reloc_code_real_type r;
+  if (r != TC_PARSE_CONS_RETURN_NONE)
+    {
+      reloc_howto_type *reloc_howto;
 
-    switch (nbytes)
+      reloc_howto = bfd_reloc_type_lookup (stdoutput, r);
+      size = bfd_get_reloc_size (reloc_howto);
+
+      if (size > nbytes)
+       {
+         as_bad (_("%s relocations do not fit in %u bytes\n"),
+                 reloc_howto->name, nbytes);
+         return;
+       }
+      else if (target_big_endian)
+       offset = nbytes - size;
+    }
+  else
+    switch (size)
       {
       case 1:
        r = BFD_RELOC_8;
@@ -4509,13 +4459,11 @@ emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p)
        r = BFD_RELOC_64;
        break;
       default:
-       as_bad (_("unsupported BFD relocation size %u"), nbytes);
-       r = BFD_RELOC_32;
-       break;
+       as_bad (_("unsupported BFD relocation size %u"), size);
+       return;
       }
-    fix_new_exp (frag, p - frag->fr_literal, (int) nbytes, exp,
-                0, r);
-  }
+  fix_new_exp (frag, p - frag->fr_literal + offset, size,
+              exp, 0, r);
 #endif
 }
 \f
@@ -4641,6 +4589,7 @@ parse_bitfield_cons (exp, nbytes)
       exp->X_add_number = value;
       exp->X_op = O_constant;
       exp->X_unsigned = 1;
+      exp->X_extrabit = 0;
     }
 }
 
@@ -4650,9 +4599,7 @@ parse_bitfield_cons (exp, nbytes)
 
 #ifdef TC_M68K
 static void
-parse_mri_cons (exp, nbytes)
-     expressionS *exp;
-     unsigned int nbytes;
+parse_mri_cons (expressionS *exp, unsigned int nbytes)
 {
   if (*input_line_pointer != '\''
       && (input_line_pointer[1] != '\''
@@ -5200,12 +5147,12 @@ emit_leb128_expr (expressionS *exp, int sign)
     }
   else if (op == O_constant
           && sign
-          && (exp->X_add_number < 0) != !exp->X_unsigned)
+          && (exp->X_add_number < 0) == !exp->X_extrabit)
     {
       /* We're outputting a signed leb128 and the sign of X_add_number
         doesn't reflect the sign of the original value.  Convert EXP
         to a correctly-extended bignum instead.  */
-      convert_to_bignum (exp);
+      convert_to_bignum (exp, exp->X_extrabit);
       op = O_big;
     }
 
@@ -5890,8 +5837,8 @@ add_include_dir (char *path)
     {
       include_dir_count++;
       include_dirs =
-       (char **) realloc (include_dirs,
-                          include_dir_count * sizeof (*include_dirs));
+       (char **) xrealloc (include_dirs,
+                           include_dir_count * sizeof (*include_dirs));
     }
 
   include_dirs[include_dir_count - 1] = path;  /* New one.  */
@@ -6062,14 +6009,12 @@ s_bundle_lock (int arg ATTRIBUTE_UNUSED)
       return;
     }
 
-  if (bundle_lock_frag != NULL)
+  if (bundle_lock_depth == 0)
     {
-      as_bad (_("second .bundle_lock without .bundle_unlock"));
-      return;
+      bundle_lock_frchain = frchain_now;
+      bundle_lock_frag = start_bundle ();
     }
-
-  bundle_lock_frchain = frchain_now;
-  bundle_lock_frag = start_bundle ();
+  ++bundle_lock_depth;
 }
 
 void
@@ -6087,6 +6032,10 @@ s_bundle_unlock (int arg ATTRIBUTE_UNUSED)
 
   gas_assert (bundle_align_p2 > 0);
 
+  gas_assert (bundle_lock_depth > 0);
+  if (--bundle_lock_depth > 0)
+    return;
+
   size = pending_bundle_size (bundle_lock_frag);
 
   if (size > (1U << bundle_align_p2))
@@ -6126,8 +6075,9 @@ void
 input_scrub_insert_line (const char *line)
 {
   sb newline;
-  sb_new (&newline);
-  sb_add_string (&newline, 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);
   sb_kill (&newline);
   buffer_limit = input_scrub_next_buffer (&input_line_pointer);
This page took 0.034451 seconds and 4 git commands to generate.