1999-09-11 Donn Terry <donn@interix.com>
[deliverable/binutils-gdb.git] / gas / symbols.c
index f64d0495da6c83fafd52ddf788c5288ade181576..60decd891510c0fbc02b5ea235d4f4cce1648f0d 100644 (file)
@@ -1,5 +1,5 @@
 /* symbols.c -symbol table-
-   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -28,6 +28,8 @@
 #include "obstack.h"           /* For "symbols.h" */
 #include "subsegs.h"
 
+#include "struc-symbol.h"
+
 /* This is non-zero if symbols are case sensitive, which is the
    default.  */
 int symbols_case_sensitive = 1;
@@ -39,6 +41,9 @@ extern int new_broken_words;
 /* symbol-name => struct symbol pointer */
 static struct hash_control *sy_hash;
 
+/* Table of local symbols.  */
+static struct hash_control *local_hash;
+
 /* Below are commented in "symbols.h". */
 symbolS *symbol_rootP;
 symbolS *symbol_lastP;
@@ -93,39 +98,53 @@ symbol_new (name, segment, valu, frag)
   return symbolP;
 }
 
-symbolS *
-symbol_create (name, segment, valu, frag)
-     const char *name;         /* It is copied, the caller can destroy/modify */
-     segT segment;             /* Segment identifier (SEG_<something>) */
-     valueT valu;              /* Symbol value */
-     fragS *frag;              /* Associated fragment */
+/* Save a symbol name on a permanent obstack, and convert it according
+   to the object file format.  */
+
+static char *
+save_symbol_name (name)
+     const char *name;
 {
   unsigned int name_length;
-  char *preserved_copy_of_name;
-  symbolS *symbolP;
+  char *ret;
 
   name_length = strlen (name) + 1;     /* +1 for \0 */
   obstack_grow (&notes, name, name_length);
-  preserved_copy_of_name = obstack_finish (&notes);
+  ret = obstack_finish (&notes);
+
 #ifdef STRIP_UNDERSCORE
-  if (preserved_copy_of_name[0] == '_')
-    preserved_copy_of_name++;
+  if (ret[0] == '_')
+    ++ret;
 #endif
 
 #ifdef tc_canonicalize_symbol_name
-  preserved_copy_of_name =
-    tc_canonicalize_symbol_name (preserved_copy_of_name);
+  ret = tc_canonicalize_symbol_name (ret);
 #endif
 
   if (! symbols_case_sensitive)
     {
       unsigned char *s;
 
-      for (s = (unsigned char *) preserved_copy_of_name; *s != '\0'; s++)
+      for (s = (unsigned char *) ret; *s != '\0'; s++)
        if (islower (*s))
          *s = toupper (*s);
     }
 
+  return ret;
+}
+
+symbolS *
+symbol_create (name, segment, valu, frag)
+     const char *name;         /* It is copied, the caller can destroy/modify */
+     segT segment;             /* Segment identifier (SEG_<something>) */
+     valueT valu;              /* Symbol value */
+     fragS *frag;              /* Associated fragment */
+{
+  char *preserved_copy_of_name;
+  symbolS *symbolP;
+
+  preserved_copy_of_name = save_symbol_name (name);
+
   symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
 
   /* symbol must be born in some fixed state.  This seems as good as any. */
@@ -158,6 +177,101 @@ symbol_create (name, segment, valu, frag)
   return symbolP;
 }
 \f
+#ifdef BFD_ASSEMBLER
+
+/* Local symbol support.  If we can get away with it, we keep only a
+   small amount of information for local symbols.  */
+
+static struct local_symbol *local_symbol_make PARAMS ((const char *, segT,
+                                                      valueT, fragS *));
+static symbolS *local_symbol_convert PARAMS ((struct local_symbol *));
+
+/* Used for statistics.  */
+
+static unsigned long local_symbol_count;
+static unsigned long local_symbol_conversion_count;
+
+/* This macro is called with a symbol argument passed by reference.
+   It returns whether this is a local symbol.  If necessary, it
+   changes its argument to the real symbol.  */
+
+#define LOCAL_SYMBOL_CHECK(s)                                          \
+  (s->bsym == NULL                                                     \
+   ? (local_symbol_converted_p ((struct local_symbol *) s)             \
+      ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s), \
+        0)                                                             \
+      : 1)                                                             \
+   : 0)
+
+/* Create a local symbol and insert it into the local hash table.  */
+
+static struct local_symbol *
+local_symbol_make (name, section, offset, frag)
+     const char *name;
+     segT section;
+     valueT offset;
+     fragS *frag;
+{
+  char *name_copy;
+  struct local_symbol *ret;
+
+  ++local_symbol_count;
+
+  name_copy = save_symbol_name (name);
+
+  ret = (struct local_symbol *) obstack_alloc (&notes, sizeof *ret);
+  ret->lsy_marker = NULL;
+  ret->lsy_name = name_copy;
+  ret->lsy_section = section;
+  local_symbol_set_frag (ret, frag);
+  ret->lsy_offset = offset;
+
+  hash_jam (local_hash, name_copy, (PTR) ret);
+
+  return ret;
+}
+
+/* Convert a local symbol into a real symbol.  Note that we do not
+   reclaim the space used by the local symbol.  */
+
+static symbolS *
+local_symbol_convert (locsym)
+     struct local_symbol *locsym;
+{
+  symbolS *ret;
+
+  assert (locsym->lsy_marker == NULL);
+  if (local_symbol_converted_p (locsym))
+    return local_symbol_get_real_symbol (locsym);
+
+  ++local_symbol_conversion_count;
+
+  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset,
+                   local_symbol_get_frag (locsym));
+
+  if (local_symbol_resolved_p (locsym))
+    ret->sy_resolved = 1;
+
+  /* Local symbols are always either defined or used.  */
+  ret->sy_used = 1;
+
+  symbol_table_insert (ret);
+
+  local_symbol_mark_converted (locsym);
+  local_symbol_set_real_symbol (locsym, ret);
+
+  hash_jam (local_hash, locsym->lsy_name, NULL);
+
+  return ret;
+}
+
+#else /* ! BFD_ASSEMBLER */
+
+#define LOCAL_SYMBOL_CHECK(s) 0
+#define local_symbol_convert(s) ((symbolS *) s)
+
+#endif /* ! BFD_ASSEMBLER */
+\f
 
 /*
  *                     colon()
@@ -238,7 +352,26 @@ colon (sym_name)           /* just seen "x:" - rattle symbols & frags */
       /*
        *       Now check for undefined symbols
        */
-      if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
+      if (LOCAL_SYMBOL_CHECK (symbolP))
+       {
+#ifdef BFD_ASSEMBLER
+         struct local_symbol *locsym = (struct local_symbol *) symbolP;
+
+         if (locsym->lsy_section != undefined_section
+             && (local_symbol_get_frag (locsym) != frag_now
+                 || locsym->lsy_section != now_seg
+                 || locsym->lsy_offset != frag_now_fix ()))
+           {
+             as_bad (_("Symbol %s already defined."), sym_name);
+             return symbolP;
+           }
+
+         locsym->lsy_section = now_seg;
+         local_symbol_set_frag (locsym, frag_now);
+         locsym->lsy_offset = frag_now_fix ();
+#endif
+       }
+      else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
        {
          if (S_GET_VALUE (symbolP) == 0)
            {
@@ -305,13 +438,13 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
              else
                {
 #if defined (S_GET_OTHER) && defined (S_GET_DESC)
-                 as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld.",
+                 as_fatal (_("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld."),
                            sym_name,
                            segment_name (S_GET_SEGMENT (symbolP)),
                            S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
                            (long) S_GET_VALUE (symbolP));
 #else
-                 as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%ld.",
+                 as_fatal (_("Symbol \"%s\" is already defined as \"%s\"/%ld."),
                            sym_name,
                            segment_name (S_GET_SEGMENT (symbolP)),
                            (long) S_GET_VALUE (symbolP));
@@ -325,10 +458,18 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
          if (!(frag_now == symbolP->sy_frag
                && S_GET_VALUE (symbolP) == frag_now_fix ()
                && S_GET_SEGMENT (symbolP) == now_seg))
-           as_fatal ("Symbol %s already defined.", sym_name);
+           as_fatal (_("Symbol %s already defined."), sym_name);
        }                       /* if this symbol is not yet defined */
 
     }
+#ifdef BFD_ASSEMBLER
+  else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))
+    {
+      symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,
+                                              (valueT) frag_now_fix (),
+                                              frag_now);
+    }
+#endif /* BFD_ASSEMBLER */
   else
     {
       symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
@@ -344,6 +485,8 @@ colon (sym_name)            /* just seen "x:" - rattle symbols & frags */
     {
       /* This symbol is actually being defined within an MRI common
          section.  This requires special handling.  */
+      if (LOCAL_SYMBOL_CHECK (symbolP))
+       symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
       symbolP->sy_value.X_op = O_symbol;
       symbolP->sy_value.X_add_symbol = mri_common_symbol;
       symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
@@ -379,9 +522,19 @@ symbol_table_insert (symbolP)
   know (symbolP);
   know (S_GET_NAME (symbolP));
 
+  if (LOCAL_SYMBOL_CHECK (symbolP))
+    {
+      error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
+                              (PTR) symbolP);
+      if (error_string != NULL)
+       as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
+                 S_GET_NAME (symbolP), error_string);
+      return;
+    }
+
   if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
     {
-      as_fatal ("Inserting \"%s\" into symbol table failed: %s",
+      as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
                S_GET_NAME (symbolP), error_string);
     }                          /* on error */
 }                              /* symbol_table_insert() */
@@ -402,6 +555,20 @@ symbol_find_or_make (name)
 
   if (symbolP == NULL)
     {
+#ifdef BFD_ASSEMBLER
+      if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))
+       {
+         symbolP = md_undefined_symbol ((char *) name);
+         if (symbolP != NULL)
+           return symbolP;
+
+         symbolP = (symbolS *) local_symbol_make (name, undefined_section,
+                                                  (valueT) 0,
+                                                  &zero_address_frag);
+         return symbolP;
+       }
+#endif
+
       symbolP = symbol_make (name);
 
       symbol_table_insert (symbolP);
@@ -456,24 +623,42 @@ symbol_find_base (name, strip_underscore)
 #ifdef tc_canonicalize_symbol_name
   {
     char *copy;
+    size_t len = strlen (name) + 1;
 
-    copy = (char *) alloca (strlen (name) + 1);
-    strcpy (copy, name);
+    copy = (char *) alloca (len);
+    memcpy (copy, name, len);
     name = tc_canonicalize_symbol_name (copy);
   }
 #endif
 
   if (! symbols_case_sensitive)
     {
-      unsigned char *copy;
+      char *copy;
+      const char *orig;
+      unsigned char c;
+
+      orig = name;
+      name = copy = (char *) alloca (strlen (name) + 1);
 
-      copy = (unsigned char *) alloca (strlen (name) + 1);
-      name = (const char *) copy;
-      for (; *copy != '\0'; copy++)
-       if (islower (*copy))
-         *copy = toupper (*copy);
+      while ((c = *orig++) != '\0')
+       {
+         if (islower (c))
+           c = toupper (c);
+         *copy++ = c;
+       }
+      *copy = '\0';
     }
 
+#ifdef BFD_ASSEMBLER
+  {
+    struct local_symbol *locsym;
+
+    locsym = (struct local_symbol *) hash_find (local_hash, name);
+    if (locsym != NULL)
+      return (symbolS *) locsym;
+  }
+#endif
+
   return ((symbolS *) hash_find (sy_hash, name));
 }
 
@@ -493,6 +678,11 @@ symbol_append (addme, target, rootPP, lastPP)
      symbolS **rootPP;
      symbolS **lastPP;
 {
+  if (LOCAL_SYMBOL_CHECK (addme))
+    abort ();
+  if (target != NULL && LOCAL_SYMBOL_CHECK (target))
+    abort ();
+
   if (target == NULL)
     {
       know (*rootPP == NULL);
@@ -533,6 +723,8 @@ void
 symbol_clear_list_pointers (symbolP)
      symbolS *symbolP;
 {
+  if (LOCAL_SYMBOL_CHECK (symbolP))
+    abort ();
   symbolP->sy_next = NULL;
 #ifdef SYMBOLS_NEED_BACKPOINTERS
   symbolP->sy_previous = NULL;
@@ -547,6 +739,9 @@ symbol_remove (symbolP, rootPP, lastPP)
      symbolS **rootPP;
      symbolS **lastPP;
 {
+  if (LOCAL_SYMBOL_CHECK (symbolP))
+    abort ();
+
   if (symbolP == *rootPP)
     {
       *rootPP = symbolP->sy_next;
@@ -576,8 +771,13 @@ symbol_insert (addme, target, rootPP, lastPP)
      symbolS *addme;
      symbolS *target;
      symbolS **rootPP;
-     symbolS **lastPP;
+     symbolS **lastPP ATTRIBUTE_UNUSED;
 {
+  if (LOCAL_SYMBOL_CHECK (addme))
+    abort ();
+  if (LOCAL_SYMBOL_CHECK (target))
+    abort ();
+
   if (target->sy_previous != NULL)
     {
       target->sy_previous->sy_next = addme;
@@ -609,6 +809,9 @@ verify_symbol_chain (rootP, lastP)
 
   for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
     {
+#ifdef BFD_ASSEMBLER
+      assert (symbolP->bsym != NULL);
+#endif
 #ifdef SYMBOLS_NEED_BACKPOINTERS
       assert (symbolP->sy_next->sy_previous == symbolP);
 #else
@@ -647,6 +850,27 @@ resolve_symbol_value (symp, finalize)
   valueT final_val;
   segT final_seg;
 
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (symp))
+    {
+      struct local_symbol *locsym = (struct local_symbol *) symp;
+
+      if (local_symbol_resolved_p (locsym))
+       return locsym->lsy_offset;
+
+      final_val = (local_symbol_get_frag (locsym)->fr_address
+                  + locsym->lsy_offset);
+
+      if (finalize)
+       {
+         locsym->lsy_offset = final_val;
+         local_symbol_mark_resolved (locsym);
+       }
+
+      return final_val;
+    }
+#endif
+
   if (symp->sy_resolved)
     {
       if (symp->sy_value.X_op == O_constant)
@@ -661,7 +885,7 @@ resolve_symbol_value (symp, finalize)
   if (symp->sy_resolving)
     {
       if (finalize)
-       as_bad ("Symbol definition loop encountered at %s", S_GET_NAME (symp));
+       as_bad (_("Symbol definition loop encountered at %s"), S_GET_NAME (symp));
       final_val = 0;
       resolved = 1;
     }
@@ -707,12 +931,17 @@ resolve_symbol_value (symp, finalize)
              /* This is a symbol inside an MRI common section.  The
                  relocation routines are going to handle it specially.
                  Don't change the value.  */
-             resolved = add_symbol->sy_resolved;
+             resolved = symbol_resolved_p (add_symbol);
              break;
            }
 
          if (finalize && final_val == 0)
-           copy_symbol_attributes (symp, add_symbol);
+           {
+             if (LOCAL_SYMBOL_CHECK (add_symbol))
+               add_symbol = local_symbol_convert ((struct local_symbol *)
+                                                  add_symbol);
+             copy_symbol_attributes (symp, add_symbol);
+           }
 
          /* If we have equated this symbol to an undefined symbol, we
              keep X_op set to O_symbol, and we don't change
@@ -724,12 +953,13 @@ resolve_symbol_value (symp, finalize)
            {
              if (finalize)
                {
-                 symp->sy_value.X_op = O_symbol;
                  S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
+                 symp->sy_value.X_op = O_symbol;
+                 symp->sy_value.X_add_symbol = add_symbol;
                  symp->sy_value.X_add_number = final_val;
                }
              final_val = 0;
-             resolved = add_symbol->sy_resolved;
+             resolved = symbol_resolved_p (add_symbol);
              goto exit_dont_set_value;
            }
          else
@@ -739,7 +969,7 @@ resolve_symbol_value (symp, finalize)
                final_seg = S_GET_SEGMENT (add_symbol);
            }
 
-         resolved = add_symbol->sy_resolved;
+         resolved = symbol_resolved_p (add_symbol);
          break;
 
        case O_uminus:
@@ -758,7 +988,7 @@ resolve_symbol_value (symp, finalize)
          if (final_seg == expr_section || final_seg == undefined_section)
            final_seg = absolute_section;
 
-         resolved = add_symbol->sy_resolved;
+         resolved = symbol_resolved_p (add_symbol);
          break;
 
        case O_multiply:
@@ -818,8 +1048,11 @@ resolve_symbol_value (symp, finalize)
             expressions, such as IEEE-695.  */
          /* Don't emit messages unless we're finalizing the symbol value,
             otherwise we may get the same message multiple times.  */
-         if ((seg_left != absolute_section || seg_right != absolute_section)
-             && (op != O_subtract || seg_left != seg_right)
+         if ((seg_left != absolute_section
+              || seg_right != absolute_section)
+             && (op != O_subtract
+                 || seg_left != seg_right
+                 || seg_left == undefined_section)
              && finalize)
            {
              char *file;
@@ -829,29 +1062,29 @@ resolve_symbol_value (symp, finalize)
                {
                  if (seg_left == undefined_section)
                    as_bad_where (file, line,
-                                 "undefined symbol %s in operation",
+                                 _("undefined symbol %s in operation"),
                                  S_GET_NAME (symp->sy_value.X_add_symbol));
                  if (seg_right == undefined_section)
                    as_bad_where (file, line,
-                                 "undefined symbol %s in operation",
+                                 _("undefined symbol %s in operation"),
                                  S_GET_NAME (symp->sy_value.X_op_symbol));
                  if (seg_left != undefined_section
                      && seg_right != undefined_section)
-                   as_bad_where (file, line, "invalid section for operation");
+                   as_bad_where (file, line, _("invalid section for operation"));
                }
              else
                {
                  if (seg_left == undefined_section)
-                   as_bad ("undefined symbol %s in operation setting %s",
+                   as_bad (_("undefined symbol %s in operation setting %s"),
                            S_GET_NAME (symp->sy_value.X_add_symbol),
                            S_GET_NAME (symp));
                  if (seg_right == undefined_section)
-                   as_bad ("undefined symbol %s in operation setting %s",
+                   as_bad (_("undefined symbol %s in operation setting %s"),
                            S_GET_NAME (symp->sy_value.X_op_symbol),
                            S_GET_NAME (symp));
                  if (seg_left != undefined_section
                      && seg_right != undefined_section)
-                   as_bad ("invalid section for operation setting %s",
+                   as_bad (_("invalid section for operation setting %s"),
                            S_GET_NAME (symp));
                }
            }
@@ -867,9 +1100,9 @@ resolve_symbol_value (symp, finalize)
                  unsigned int line;
 
                  if (expr_symbol_where (symp, &file, &line))
-                   as_bad_where (file, line, "division by zero");
+                   as_bad_where (file, line, _("division by zero"));
                  else
-                   as_bad ("division by zero when setting %s",
+                   as_bad (_("division by zero when setting %s"),
                            S_GET_NAME (symp));
                }
 
@@ -903,7 +1136,8 @@ resolve_symbol_value (symp, finalize)
          final_val += symp->sy_frag->fr_address + left;
          if (final_seg == expr_section || final_seg == undefined_section)
            final_seg = absolute_section;
-         resolved = (add_symbol->sy_resolved && op_symbol->sy_resolved);
+         resolved = (symbol_resolved_p (add_symbol)
+                     && symbol_resolved_p (op_symbol));
          break;
 
        case O_register:
@@ -940,7 +1174,7 @@ exit_dont_set_value:
        symp->sy_resolved = 1;
       else if (S_GET_SEGMENT (symp) != expr_section)
        {
-         as_bad ("can't resolve value for symbol \"%s\"", S_GET_NAME (symp));
+         as_bad (_("can't resolve value for symbol \"%s\""), S_GET_NAME (symp));
          symp->sy_resolved = 1;
        }
     }
@@ -948,6 +1182,33 @@ exit_dont_set_value:
   return final_val;
 }
 
+#ifdef BFD_ASSEMBLER
+
+static void resolve_local_symbol PARAMS ((const char *, PTR));
+
+/* A static function passed to hash_traverse.  */
+
+static void
+resolve_local_symbol (key, value)
+     const char *key ATTRIBUTE_UNUSED;
+     PTR value;
+{
+  if (value != NULL)
+    resolve_symbol_value (value, 1);
+}
+
+#endif
+
+/* Resolve all local symbols.  */
+
+void
+resolve_local_symbol_values ()
+{
+#ifdef BFD_ASSEMBLER
+  hash_traverse (local_hash, resolve_local_symbol);
+#endif
+}
+
 /* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
    They are *really* local.  That is, they go out of scope whenever we see a
    label that isn't local.  Also, like fb labels, there can be multiple
@@ -1071,6 +1332,9 @@ dollar_label_name (n, augend)
   know (n >= 0);
   know (augend == 0 || augend == 1);
   p = symbol_name_build;
+#ifdef LOCAL_LABEL_PREFIX
+  *p++ = LOCAL_LABEL_PREFIX;
+#endif
   *p++ = 'L';
 
   /* Next code just does sprintf( {}, "%d", n); */
@@ -1283,7 +1547,7 @@ decode_local_label_name (s)
   int label_number;
   int instance_number;
   char *type;
-  const char *message_format = "\"%d\" (instance number %d of a %s label)";
+  const char *message_format = _("\"%d\" (instance number %d of a %s label)");
 
   if (s[0] != 'L')
     return s;
@@ -1313,6 +1577,11 @@ valueT
 S_GET_VALUE (s)
      symbolS *s;
 {
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    return ((struct local_symbol *) s)->lsy_offset;
+#endif
+
   if (!s->sy_resolved && s->sy_value.X_op != O_constant)
     resolve_symbol_value (s, 1);
   if (s->sy_value.X_op != O_constant)
@@ -1328,7 +1597,7 @@ S_GET_VALUE (s)
       if (! s->sy_resolved
          || s->sy_value.X_op != O_symbol
          || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
-       as_bad ("Attempt to get value of unresolved symbol %s",
+       as_bad (_("Attempt to get value of unresolved symbol %s"),
                S_GET_NAME (s));
       recur = NULL;
     }
@@ -1342,6 +1611,14 @@ S_SET_VALUE (s, val)
      symbolS *s;
      valueT val;
 {
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    {
+      ((struct local_symbol *) s)->lsy_offset = val;
+      return;
+    }
+#endif
+
   s->sy_value.X_op = O_constant;
   s->sy_value.X_add_number = (offsetT) val;
   s->sy_value.X_unsigned = 0;
@@ -1351,6 +1628,11 @@ void
 copy_symbol_attributes (dest, src)
      symbolS *dest, *src;
 {
+  if (LOCAL_SYMBOL_CHECK (dest))
+    dest = local_symbol_convert ((struct local_symbol *) dest);
+  if (LOCAL_SYMBOL_CHECK (src))
+    src = local_symbol_convert ((struct local_symbol *) src);
+
 #ifdef BFD_ASSEMBLER
   /* In an expression, transfer the settings of these flags.
      The user can override later, of course.  */
@@ -1365,11 +1647,30 @@ copy_symbol_attributes (dest, src)
 
 #ifdef BFD_ASSEMBLER
 
+int
+S_IS_FUNCTION (s)
+     symbolS *s;
+{
+  flagword flags;
+
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+
+  flags = s->bsym->flags;
+
+  return (flags & BSF_FUNCTION) != 0;
+}
+
 int
 S_IS_EXTERNAL (s)
      symbolS *s;
 {
-  flagword flags = s->bsym->flags;
+  flagword flags;
+
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+
+  flags = s->bsym->flags;
 
   /* sanity check */
   if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
@@ -1382,6 +1683,8 @@ int
 S_IS_WEAK (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
   return (s->bsym->flags & BSF_WEAK) != 0;
 }
 
@@ -1389,6 +1692,8 @@ int
 S_IS_COMMON (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
   return bfd_is_com_section (s->bsym->section);
 }
 
@@ -1396,6 +1701,8 @@ int
 S_IS_DEFINED (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return ((struct local_symbol *) s)->lsy_section != undefined_section;
   return s->bsym->section != undefined_section;
 }
 
@@ -1403,6 +1710,8 @@ int
 S_IS_DEBUG (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
   if (s->bsym->flags & BSF_DEBUGGING)
     return 1;
   return 0;
@@ -1412,9 +1721,14 @@ int
 S_IS_LOCAL (s)
      symbolS *s;
 {
-  flagword flags = s->bsym->flags;
+  flagword flags;
   const char *name;
 
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 1;
+
+  flags = s->bsym->flags;
+
   /* sanity check */
   if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
     abort ();
@@ -1457,6 +1771,8 @@ CONST char *
 S_GET_NAME (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return ((struct local_symbol *) s)->lsy_name;
   return s->bsym->name;
 }
 
@@ -1464,6 +1780,8 @@ segT
 S_GET_SEGMENT (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return ((struct local_symbol *) s)->lsy_section;
   return s->bsym->section;
 }
 
@@ -1476,6 +1794,17 @@ S_SET_SEGMENT (s, seg)
      faults assigning back to const global symbols such as *ABS*, but it
      shouldn't happen anyway.  */
 
+  if (LOCAL_SYMBOL_CHECK (s))
+    {
+      if (seg == reg_section)
+       s = local_symbol_convert ((struct local_symbol *) s);
+      else
+       {
+         ((struct local_symbol *) s)->lsy_section = seg;
+         return;
+       }
+    }
+
   if (s->bsym->flags & BSF_SECTION_SYM)
     {
       if (s->bsym->section != seg)
@@ -1489,6 +1818,8 @@ void
 S_SET_EXTERNAL (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
   if ((s->bsym->flags & BSF_WEAK) != 0)
     {
       /* Let .weak override .global.  */
@@ -1502,6 +1833,8 @@ void
 S_CLEAR_EXTERNAL (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
   if ((s->bsym->flags & BSF_WEAK) != 0)
     {
       /* Let .weak override.  */
@@ -1515,6 +1848,8 @@ void
 S_SET_WEAK (s)
      symbolS *s;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
   s->bsym->flags |= BSF_WEAK;
   s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
 }
@@ -1524,16 +1859,383 @@ S_SET_NAME (s, name)
      symbolS *s;
      char *name;
 {
+  if (LOCAL_SYMBOL_CHECK (s))
+    {
+      ((struct local_symbol *) s)->lsy_name = name;
+      return;
+    }
   s->bsym->name = name;
 }
 #endif /* BFD_ASSEMBLER */
 
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+
+/* Return the previous symbol in a chain.  */
+
+symbolS *
+symbol_previous (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    abort ();
+  return s->sy_previous;
+}
+
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+/* Return the next symbol in a chain.  */
+
+symbolS *
+symbol_next (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    abort ();
+  return s->sy_next;
+}
+
+/* Return a pointer to the value of a symbol as an expression.  */
+
+expressionS *
+symbol_get_value_expression (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  return &s->sy_value;
+}
+
+/* Set the value of a symbol to an expression.  */
+
+void
+symbol_set_value_expression (s, exp)
+     symbolS *s;
+     const expressionS *exp;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_value = *exp;
+}
+
+/* Set the frag of a symbol.  */
+
+void
+symbol_set_frag (s, f)
+     symbolS *s;
+     fragS *f;
+{
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    {
+      local_symbol_set_frag ((struct local_symbol *) s, f);
+      return;
+    }
+#endif
+  s->sy_frag = f;
+}
+
+/* Return the frag of a symbol.  */
+
+fragS *
+symbol_get_frag (s)
+     symbolS *s;
+{
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    return local_symbol_get_frag ((struct local_symbol *) s);
+#endif
+  return s->sy_frag;
+}
+
+/* Mark a symbol as having been used.  */
+
+void
+symbol_mark_used (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
+  s->sy_used = 1;
+}
+
+/* Clear the mark of whether a symbol has been used.  */
+
+void
+symbol_clear_used (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_used = 0;
+}
+
+/* Return whether a symbol has been used.  */
+
+int
+symbol_used_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 1;
+  return s->sy_used;
+}
+
+/* Mark a symbol as having been used in a reloc.  */
+
+void
+symbol_mark_used_in_reloc (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_used_in_reloc = 1;
+}
+
+/* Clear the mark of whether a symbol has been used in a reloc.  */
+
+void
+symbol_clear_used_in_reloc (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
+  s->sy_used_in_reloc = 0;
+}
+
+/* Return whether a symbol has been used in a reloc.  */
+
+int
+symbol_used_in_reloc_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->sy_used_in_reloc;
+}
+
+/* Mark a symbol as an MRI common symbol.  */
+
+void
+symbol_mark_mri_common (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_mri_common = 1;
+}
+
+/* Clear the mark of whether a symbol is an MRI common symbol.  */
+
+void
+symbol_clear_mri_common (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
+  s->sy_mri_common = 0;
+}
+
+/* Return whether a symbol is an MRI common symbol.  */
+
+int
+symbol_mri_common_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->sy_mri_common;
+}
+
+/* Mark a symbol as having been written.  */
+
+void
+symbol_mark_written (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
+  s->written = 1;
+}
+
+/* Clear the mark of whether a symbol has been written.  */
+
+void
+symbol_clear_written (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return;
+  s->written = 0;
+}
+
+/* Return whether a symbol has been written.  */
+
+int
+symbol_written_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->written;
+}
+
+/* Mark a symbol has having been resolved.  */
+
+void
+symbol_mark_resolved (s)
+     symbolS *s;
+{
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    {
+      local_symbol_mark_resolved ((struct local_symbol *) s);
+      return;
+    }
+#endif
+  s->sy_resolved = 1;
+}
+
+/* Return whether a symbol has been resolved.  */
+
+int
+symbol_resolved_p (s)
+     symbolS *s;
+{
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    return local_symbol_resolved_p ((struct local_symbol *) s);
+#endif
+  return s->sy_resolved;
+}
+
+/* Return whether a symbol is a section symbol.  */
+
+int
+symbol_section_p (s)
+     symbolS *s ATTRIBUTE_UNUSED;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+#ifdef BFD_ASSEMBLER
+  return (s->bsym->flags & BSF_SECTION_SYM) != 0;
+#else
+  /* FIXME */
+  return 0;
+#endif
+}
+
+/* Return whether a symbol is equated to another symbol.  */
+
+int
+symbol_equated_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->sy_value.X_op == O_symbol;
+}
+
+/* Return whether a symbol has a constant value.  */
+
+int
+symbol_constant_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 1;
+  return s->sy_value.X_op == O_constant;
+}
+
+#ifdef BFD_ASSEMBLER
+
+/* Return the BFD symbol for a symbol.  */
+
+asymbol *
+symbol_get_bfdsym (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  return s->bsym;
+}
+
+/* Set the BFD symbol for a symbol.  */
+
+void
+symbol_set_bfdsym (s, bsym)
+     symbolS *s;
+     asymbol *bsym;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->bsym = bsym;
+}
+
+#endif /* BFD_ASSEMBLER */
+
+#ifdef OBJ_SYMFIELD_TYPE
+
+/* Get a pointer to the object format information for a symbol.  */
+
+OBJ_SYMFIELD_TYPE *
+symbol_get_obj (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  return &s->sy_obj;
+}
+
+/* Set the object format information for a symbol.  */
+
+void
+symbol_set_obj (s, o)
+     symbolS *s;
+     OBJ_SYMFIELD_TYPE *o;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_obj = *o;
+}
+
+#endif /* OBJ_SYMFIELD_TYPE */
+
+#ifdef TC_SYMFIELD_TYPE
+
+/* Get a pointer to the processor information for a symbol.  */
+
+TC_SYMFIELD_TYPE *
+symbol_get_tc (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  return &s->sy_tc;
+}
+
+/* Set the processor information for a symbol.  */
+
+void
+symbol_set_tc (s, o)
+     symbolS *s;
+     TC_SYMFIELD_TYPE *o;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->sy_tc = *o;
+}
+
+#endif /* TC_SYMFIELD_TYPE */
+
 void
 symbol_begin ()
 {
   symbol_lastP = NULL;
   symbol_rootP = NULL;         /* In case we have 0 symbols (!!) */
   sy_hash = hash_new ();
+#ifdef BFD_ASSEMBLER
+  local_hash = hash_new ();
+#endif
 
   memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
 #ifdef BFD_ASSEMBLER
@@ -1551,9 +2253,14 @@ symbol_begin ()
     fb_label_init ();
 }
 
+
 \f
 int indent_level;
 
+/* Maximum indent level.
+   Available for modification inside a gdb session.  */
+int max_indent_level = 8;
+
 #if 0
 
 static void
@@ -1573,28 +2280,44 @@ print_symbol_value_1 (file, sym)
   if (!name || !name[0])
     name = "(unnamed)";
   fprintf (file, "sym %lx %s", (unsigned long) sym, name);
-  if (sym->sy_frag != &zero_address_frag)
-    fprintf (file, " frag %lx", (long) sym->sy_frag);
-  if (sym->written)
-    fprintf (file, " written");
-  if (sym->sy_resolved)
-    fprintf (file, " resolved");
-  else if (sym->sy_resolving)
-    fprintf (file, " resolving");
-  if (sym->sy_used_in_reloc)
-    fprintf (file, " used-in-reloc");
-  if (sym->sy_used)
-    fprintf (file, " used");
-  if (S_IS_LOCAL (sym))
-    fprintf (file, " local");
-  if (S_IS_EXTERN (sym))
-    fprintf (file, " extern");
-  if (S_IS_DEBUG (sym))
-    fprintf (file, " debug");
-  if (S_IS_DEFINED (sym))
-    fprintf (file, " defined");
+
+  if (LOCAL_SYMBOL_CHECK (sym))
+    {
+#ifdef BFD_ASSEMBLER
+      struct local_symbol *locsym = (struct local_symbol *) sym;
+      if (local_symbol_get_frag (locsym) != &zero_address_frag
+         && local_symbol_get_frag (locsym) != NULL)
+       fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym));
+      if (local_symbol_resolved_p (locsym))
+       fprintf (file, " resolved");
+      fprintf (file, " local");
+#endif
+    }
+  else
+    {
+      if (sym->sy_frag != &zero_address_frag)
+       fprintf (file, " frag %lx", (long) sym->sy_frag);
+      if (sym->written)
+       fprintf (file, " written");
+      if (sym->sy_resolved)
+       fprintf (file, " resolved");
+      else if (sym->sy_resolving)
+       fprintf (file, " resolving");
+      if (sym->sy_used_in_reloc)
+       fprintf (file, " used-in-reloc");
+      if (sym->sy_used)
+       fprintf (file, " used");
+      if (S_IS_LOCAL (sym))
+       fprintf (file, " local");
+      if (S_IS_EXTERN (sym))
+       fprintf (file, " extern");
+      if (S_IS_DEBUG (sym))
+       fprintf (file, " debug");
+      if (S_IS_DEFINED (sym))
+       fprintf (file, " defined");
+    }
   fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
-  if (sym->sy_resolved)
+  if (symbol_resolved_p (sym))
     {
       segT s = S_GET_SEGMENT (sym);
 
@@ -1602,11 +2325,18 @@ print_symbol_value_1 (file, sym)
           && s != expr_section)
        fprintf (file, " %lx", (long) S_GET_VALUE (sym));
     }
-  else if (indent_level < 8 && S_GET_SEGMENT (sym) != undefined_section)
+  else if (indent_level < max_indent_level
+          && S_GET_SEGMENT (sym) != undefined_section)
     {
       indent_level++;
       fprintf (file, "\n%*s<", indent_level * 4, "");
-      print_expr_1 (file, &sym->sy_value);
+#ifdef BFD_ASSEMBLER
+      if (LOCAL_SYMBOL_CHECK (sym))
+       fprintf (file, "constant %lx",
+                (long) ((struct local_symbol *) sym)->lsy_offset);
+      else
+#endif
+       print_expr_1 (file, &sym->sy_value);
       fprintf (file, ">");
       indent_level--;
     }
@@ -1764,6 +2494,11 @@ symbol_print_statistics (file)
      FILE *file;
 {
   hash_print_statistics (file, "symbol table", sy_hash);
+#ifdef BFD_ASSEMBLER
+  hash_print_statistics (file, "mini local symbol table", local_hash);
+  fprintf (file, "%lu mini local symbols created, %lu converted\n",
+          local_symbol_count, local_symbol_conversion_count);
+#endif
 }
 
 /* end of symbols.c */
This page took 0.037069 seconds and 4 git commands to generate.