daily update
[deliverable/binutils-gdb.git] / gas / symbols.c
index 68c50bbbaa04063cf1dec912f587863df53caa85..63b4d47a2a459924874c983601250b53a0ed5170 100644 (file)
@@ -1,5 +1,6 @@
 /* symbols.c -symbol table-
-   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
 
-/* #define DEBUG_SYMS / * to debug symbol list maintenance */
-
-#include <ctype.h>
+/* #define DEBUG_SYMS / * to debug symbol list maintenance.  */
 
 #include "as.h"
 
+#include "safe-ctype.h"
 #include "obstack.h"           /* For "symbols.h" */
 #include "subsegs.h"
 
@@ -44,7 +44,7 @@ static struct hash_control *sy_hash;
 /* Table of local symbols.  */
 static struct hash_control *local_hash;
 
-/* Below are commented in "symbols.h". */
+/* Below are commented in "symbols.h".  */
 symbolS *symbol_rootP;
 symbolS *symbol_lastP;
 symbolS abs_symbol;
@@ -55,20 +55,22 @@ symbolS abs_symbol;
 #define debug_verify_symchain(root, last) ((void) 0)
 #endif
 
+#define DOLLAR_LABEL_CHAR      '\001'
+#define LOCAL_LABEL_CHAR       '\002'
+
 struct obstack notes;
 
+static char *save_symbol_name PARAMS ((const char *));
 static void fb_label_init PARAMS ((void));
 static long dollar_label_instance PARAMS ((long));
 static long fb_label_instance PARAMS ((long));
 
 static void print_binary PARAMS ((FILE *, const char *, expressionS *));
 
-/* symbol_new()
-  
-   Return a pointer to a new symbol.  Die if we can't make a new
+/* Return a pointer to a new symbol.  Die if we can't make a new
    symbol.  Fill in the symbol's values.  Add symbol to end of symbol
    chain.
+
    This function should be called in the general case of creating a
    symbol.  However, if the output file symbol table has already been
    set, and you are certain that this symbol won't be wanted in the
@@ -83,9 +85,7 @@ symbol_new (name, segment, valu, frag)
 {
   symbolS *symbolP = symbol_create (name, segment, valu, frag);
 
-  /*
-   * Link to end of symbol chain.
-   */
+  /* Link to end of symbol chain.  */
 #ifdef BFD_ASSEMBLER
   {
     extern int symbol_table_frozen;
@@ -108,7 +108,7 @@ save_symbol_name (name)
   unsigned int name_length;
   char *ret;
 
-  name_length = strlen (name) + 1;     /* +1 for \0 */
+  name_length = strlen (name) + 1;     /* +1 for \0 */
   obstack_grow (&notes, name, name_length);
   ret = obstack_finish (&notes);
 
@@ -123,11 +123,10 @@ save_symbol_name (name)
 
   if (! symbols_case_sensitive)
     {
-      unsigned char *s;
+      char *s;
 
-      for (s = (unsigned char *) ret; *s != '\0'; s++)
-       if (islower (*s))
-         *s = toupper (*s);
+      for (s = ret; *s != '\0'; s++)
+       *s = TOUPPER (*s);
     }
 
   return ret;
@@ -135,10 +134,10 @@ save_symbol_name (name)
 
 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 */
+     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;
@@ -147,7 +146,7 @@ symbol_create (name, segment, valu, frag)
 
   symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
 
-  /* symbol must be born in some fixed state.  This seems as good as any. */
+  /* symbol must be born in some fixed state.  This seems as good as any.  */
   memset (symbolP, 0, sizeof (symbolS));
 
 #ifdef BFD_ASSEMBLER
@@ -206,10 +205,10 @@ static unsigned long local_symbol_conversion_count;
 /* Create a local symbol and insert it into the local hash table.  */
 
 static struct local_symbol *
-local_symbol_make (name, section, offset, frag)
+local_symbol_make (name, section, value, frag)
      const char *name;
      segT section;
-     valueT offset;
+     valueT value;
      fragS *frag;
 {
   char *name_copy;
@@ -224,7 +223,7 @@ local_symbol_make (name, section, offset, frag)
   ret->lsy_name = name_copy;
   ret->lsy_section = section;
   local_symbol_set_frag (ret, frag);
-  ret->lsy_offset = offset;
+  ret->lsy_value = value;
 
   hash_jam (local_hash, name_copy, (PTR) ret);
 
@@ -246,7 +245,7 @@ local_symbol_convert (locsym)
 
   ++local_symbol_conversion_count;
 
-  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset,
+  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value,
                    local_symbol_get_frag (locsym));
 
   if (local_symbol_resolved_p (locsym))
@@ -255,6 +254,10 @@ local_symbol_convert (locsym)
   /* Local symbols are always either defined or used.  */
   ret->sy_used = 1;
 
+#ifdef TC_LOCAL_SYMFIELD_CONVERT
+  TC_LOCAL_SYMFIELD_CONVERT (locsym, ret);
+#endif
+
   symbol_table_insert (ret);
 
   local_symbol_mark_converted (locsym);
@@ -272,22 +275,17 @@ local_symbol_convert (locsym)
 
 #endif /* ! BFD_ASSEMBLER */
 \f
+/* We have just seen "<name>:".
+   Creates a struct symbol unless it already exists.
+
+   Gripes if we are redefining a symbol incompatibly (and ignores it).  */
 
-/*
- *                     colon()
- *
- * We have just seen "<name>:".
- * Creates a struct symbol unless it already exists.
- *
- * Gripes if we are redefining a symbol incompatibly (and ignores it).
- *
- */
 symbolS *
-colon (sym_name)               /* just seen "x:" - rattle symbols & frags */
-     const char *sym_name;     /* symbol name, as a cannonical string */
-     /* We copy this string: OK to alter later. */
+colon (sym_name)               /* Just seen "x:" - rattle symbols & frags.  */
+     const char *sym_name;     /* Symbol name, as a cannonical string.  */
+     /* We copy this string: OK to alter later.  */
 {
-  register symbolS *symbolP;   /* symbol we are working with */
+  register symbolS *symbolP;   /* Symbol we are working with.  */
 
   /* Sun local labels go out of scope whenever a non-local symbol is
      defined.  */
@@ -327,9 +325,9 @@ colon (sym_name)            /* just seen "x:" - rattle symbols & frags */
                              (offsetT) 0,
                              NULL);
 
-      /* We want to store the pointer to where to insert the jump table in the
-        fr_opcode of the rs_broken_word frag.  This requires a little
-        hackery.  */
+      /* We want to store the pointer to where to insert the jump
+        table in the fr_opcode of the rs_broken_word frag.  This
+        requires a little hackery.  */
       while (frag_tmp
             && (frag_tmp->fr_type != rs_broken_word
                 || frag_tmp->fr_opcode))
@@ -349,9 +347,7 @@ colon (sym_name)            /* just seen "x:" - rattle symbols & frags */
       if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
        return symbolP;
 #endif
-      /*
-       *       Now check for undefined symbols
-       */
+      /* Now check for undefined symbols.  */
       if (LOCAL_SYMBOL_CHECK (symbolP))
        {
 #ifdef BFD_ASSEMBLER
@@ -360,15 +356,15 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
          if (locsym->lsy_section != undefined_section
              && (local_symbol_get_frag (locsym) != frag_now
                  || locsym->lsy_section != now_seg
-                 || locsym->lsy_offset != frag_now_fix ()))
+                 || locsym->lsy_value != frag_now_fix ()))
            {
-             as_bad (_("Symbol %s already defined."), sym_name);
+             as_bad (_("symbol `%s' is already defined"), sym_name);
              return symbolP;
            }
 
          locsym->lsy_section = now_seg;
          local_symbol_set_frag (locsym, frag_now);
-         locsym->lsy_offset = frag_now_fix ();
+         locsym->lsy_value = frag_now_fix ();
 #endif
        }
       else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
@@ -377,27 +373,27 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
            {
              symbolP->sy_frag = frag_now;
 #ifdef OBJ_VMS
-             S_SET_OTHER(symbolP, const_flag);
+             S_SET_OTHER (symbolP, const_flag);
 #endif
              S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
              S_SET_SEGMENT (symbolP, now_seg);
 #ifdef N_UNDF
              know (N_UNDF == 0);
-#endif /* if we have one, it better be zero. */
+#endif /* if we have one, it better be zero.  */
 
            }
          else
            {
-             /*
-              *        There are still several cases to check:
-              *                A .comm/.lcomm symbol being redefined as
-              *                        initialized data is OK
-              *                A .comm/.lcomm symbol being redefined with
-              *                        a larger size is also OK
-              *
-              * This only used to be allowed on VMS gas, but Sun cc
-              * on the sparc also depends on it.
-              */
+             /* There are still several cases to check:
+
+                A .comm/.lcomm symbol being redefined as initialized
+                data is OK
+
+                A .comm/.lcomm symbol being redefined with a larger
+                size is also OK
+
+                This only used to be allowed on VMS gas, but Sun cc
+                on the sparc also depends on it.  */
 
              if (((!S_IS_DEBUG (symbolP)
                    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
@@ -406,17 +402,14 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
                  && (now_seg == data_section
                      || now_seg == S_GET_SEGMENT (symbolP)))
                {
-                 /*
-                  *    Select which of the 2 cases this is
-                  */
+                 /* Select which of the 2 cases this is.  */
                  if (now_seg != data_section)
                    {
-                     /*
-                      *   New .comm for prev .comm symbol.
-                      *        If the new size is larger we just
-                      *        change its value.  If the new size
-                      *        is smaller, we ignore this symbol
-                      */
+                     /* New .comm for prev .comm symbol.
+
+                        If the new size is larger we just change its
+                        value.  If the new size is smaller, we ignore
+                        this symbol.  */
                      if (S_GET_VALUE (symbolP)
                          < ((unsigned) frag_now_fix ()))
                        {
@@ -429,10 +422,10 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
                         data.  */
                      symbolP->sy_frag = frag_now;
 #ifdef OBJ_VMS
-                     S_SET_OTHER(symbolP, const_flag);
+                     S_SET_OTHER (symbolP, const_flag);
 #endif
                      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
-                     S_SET_SEGMENT (symbolP, now_seg); /* keep N_EXT bit */
+                     S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit.  */
                    }
                }
              else
@@ -446,26 +439,26 @@ colon (sym_name)          /* just seen "x:" - rattle symbols & frags */
 #ifdef BFD_ASSEMBLER
                  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
 #endif
-                   sprintf(od_buf, "%d.%d.",
-                           S_GET_OTHER (symbolP),
-                           S_GET_DESC (symbolP));
+                   sprintf (od_buf, "%d.%d.",
+                            S_GET_OTHER (symbolP),
+                            S_GET_DESC (symbolP));
 #endif
-                 as_fatal (_("Symbol \"%s\" is already defined as \"%s\"/%s%ld."),
+                 as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"),
                            sym_name,
                            segment_name (S_GET_SEGMENT (symbolP)),
                            od_buf,
                            (long) S_GET_VALUE (symbolP));
                }
-           }                   /* if the undefined symbol has no value */
+           }                   /* if the undefined symbol has no value  */
        }
       else
        {
-         /* Don't blow up if the definition is the same */
+         /* Don't blow up if the definition is the same */
          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);
-       }                       /* if this symbol is not yet defined */
+           as_bad (_("symbol `%s' is already defined"), sym_name);
+       }
 
     }
 #ifdef BFD_ASSEMBLER
@@ -485,7 +478,7 @@ colon (sym_name)            /* just seen "x:" - rattle symbols & frags */
 #endif /* OBJ_VMS */
 
       symbol_table_insert (symbolP);
-    }                          /* if we have seen this symbol before */
+    }
 
   if (mri_common_symbol != NULL)
     {
@@ -511,15 +504,9 @@ colon (sym_name)           /* just seen "x:" - rattle symbols & frags */
   return symbolP;
 }
 \f
+/* Die if we can't insert the symbol.  */
 
-/*
- *                     symbol_table_insert()
- *
- * Die if we can't insert the symbol.
- *
- */
-
-void 
+void
 symbol_table_insert (symbolP)
      symbolS *symbolP;
 {
@@ -533,24 +520,21 @@ symbol_table_insert (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"),
+       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() */
+    }                          /* on error  */
+}
 \f
-/*
- *                     symbol_find_or_make()
- *
- * If a symbol name does not exist, create it as undefined, and insert
- * it into the symbol table. Return a pointer to it.
- */
+/* If a symbol name does not exist, create it as undefined, and insert
+   it into the symbol table.  Return a pointer to it.  */
+
 symbolS *
 symbol_find_or_make (name)
      const char *name;
@@ -581,46 +565,59 @@ symbol_find_or_make (name)
     }                          /* if symbol wasn't found */
 
   return (symbolP);
-}                              /* symbol_find_or_make() */
+}
 
 symbolS *
 symbol_make (name)
-     CONST char *name;
+     const char *name;
 {
   symbolS *symbolP;
 
-  /* Let the machine description default it, e.g. for register names. */
+  /* Let the machine description default it, e.g. for register names.  */
   symbolP = md_undefined_symbol ((char *) name);
 
   if (!symbolP)
     symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
 
   return (symbolP);
-}                              /* symbol_make() */
+}
 
-/*
- *                     symbol_find()
- *
- * Implement symbol table lookup.
- * In: A symbol's name as a string: '\0' can't be part of a symbol name.
- * Out:        NULL if the name was not in the symbol table, else the address
- *     of a struct symbol associated with that name.
- */
+/* Implement symbol table lookup.
+   In: A symbol's name as a string: '\0' can't be part of a symbol name.
+   Out:        NULL if the name was not in the symbol table, else the address
+   of a struct symbol associated with that name.  */
 
 symbolS *
 symbol_find (name)
-     CONST char *name;
+     const char *name;
 {
 #ifdef STRIP_UNDERSCORE
   return (symbol_find_base (name, 1));
 #else /* STRIP_UNDERSCORE */
   return (symbol_find_base (name, 0));
 #endif /* STRIP_UNDERSCORE */
-}                              /* symbol_find() */
+}
+
+symbolS *
+symbol_find_exact (name)
+     const char *name;
+{
+#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));
+}
 
 symbolS *
 symbol_find_base (name, strip_underscore)
-     CONST char *name;
+     const char *name;
      int strip_underscore;
 {
   if (strip_underscore && *name == '_')
@@ -648,36 +645,23 @@ symbol_find_base (name, strip_underscore)
 
       while ((c = *orig++) != '\0')
        {
-         if (islower (c))
-           c = toupper (c);
-         *copy++ = c;
+         *copy++ = TOUPPER (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));
+  return symbol_find_exact (name);
 }
 
-/*
- * Once upon a time, symbols were kept in a singly linked list.  At
- * least coff needs to be able to rearrange them from time to time, for
- * which a doubly linked list is much more convenient.  Loic did these
- * as macros which seemed dangerous to me so they're now functions.
- * xoxorich.
- */
+/* Once upon a time, symbols were kept in a singly linked list.  At
+   least coff needs to be able to rearrange them from time to time, for
+   which a doubly linked list is much more convenient.  Loic did these
+   as macros which seemed dangerous to me so they're now functions.
+   xoxorich.  */
 
-/* Link symbol ADDME after symbol TARGET in the chain. */
-void 
+/* Link symbol ADDME after symbol TARGET in the chain.  */
+
+void
 symbol_append (addme, target, rootPP, lastPP)
      symbolS *addme;
      symbolS *target;
@@ -700,7 +684,7 @@ symbol_append (addme, target, rootPP, lastPP)
       *rootPP = addme;
       *lastPP = addme;
       return;
-    }                          /* if the list is empty */
+    }                          /* if the list is empty  */
 
   if (target->sy_next != NULL)
     {
@@ -712,7 +696,7 @@ symbol_append (addme, target, rootPP, lastPP)
     {
       know (*lastPP == target);
       *lastPP = addme;
-    }                          /* if we have a next */
+    }                          /* if we have a next  */
 
   addme->sy_next = target->sy_next;
   target->sy_next = addme;
@@ -724,8 +708,9 @@ symbol_append (addme, target, rootPP, lastPP)
   debug_verify_symchain (symbol_rootP, symbol_lastP);
 }
 
-/* Set the chain pointers of SYMBOL to null. */
-void 
+/* Set the chain pointers of SYMBOL to null.  */
+
+void
 symbol_clear_list_pointers (symbolP)
      symbolS *symbolP;
 {
@@ -738,8 +723,9 @@ symbol_clear_list_pointers (symbolP)
 }
 
 #ifdef SYMBOLS_NEED_BACKPOINTERS
-/* Remove SYMBOLP from the list. */
-void 
+/* Remove SYMBOLP from the list.  */
+
+void
 symbol_remove (symbolP, rootPP, lastPP)
      symbolS *symbolP;
      symbolS **rootPP;
@@ -751,28 +737,29 @@ symbol_remove (symbolP, rootPP, lastPP)
   if (symbolP == *rootPP)
     {
       *rootPP = symbolP->sy_next;
-    }                          /* if it was the root */
+    }                          /* if it was the root  */
 
   if (symbolP == *lastPP)
     {
       *lastPP = symbolP->sy_previous;
-    }                          /* if it was the tail */
+    }                          /* if it was the tail  */
 
   if (symbolP->sy_next != NULL)
     {
       symbolP->sy_next->sy_previous = symbolP->sy_previous;
-    }                          /* if not last */
+    }                          /* if not last  */
 
   if (symbolP->sy_previous != NULL)
     {
       symbolP->sy_previous->sy_next = symbolP->sy_next;
-    }                          /* if not first */
+    }                          /* if not first  */
 
   debug_verify_symchain (*rootPP, *lastPP);
 }
 
-/* Link symbol ADDME before symbol TARGET in the chain. */
-void 
+/* Link symbol ADDME before symbol TARGET in the chain.  */
+
+void
 symbol_insert (addme, target, rootPP, lastPP)
      symbolS *addme;
      symbolS *target;
@@ -792,7 +779,7 @@ symbol_insert (addme, target, rootPP, lastPP)
     {
       know (*rootPP == target);
       *rootPP = addme;
-    }                          /* if not first */
+    }                          /* if not first  */
 
   addme->sy_previous = target->sy_previous;
   target->sy_previous = addme;
@@ -803,7 +790,7 @@ symbol_insert (addme, target, rootPP, lastPP)
 
 #endif /* SYMBOLS_NEED_BACKPOINTERS */
 
-void 
+void
 verify_symbol_chain (rootP, lastP)
      symbolS *rootP;
      symbolS *lastP;
@@ -848,12 +835,11 @@ verify_symbol_chain_2 (sym)
    values.  */
 
 valueT
-resolve_symbol_value (symp, finalize)
+resolve_symbol_value (symp)
      symbolS *symp;
-     int finalize;
 {
   int resolved;
-  valueT final_val;
+  valueT final_val = 0;
   segT final_seg;
 
 #ifdef BFD_ASSEMBLER
@@ -861,15 +847,15 @@ resolve_symbol_value (symp, finalize)
     {
       struct local_symbol *locsym = (struct local_symbol *) symp;
 
+      final_val = locsym->lsy_value;
       if (local_symbol_resolved_p (locsym))
-       return locsym->lsy_offset / bfd_octets_per_byte (stdoutput);
+       return final_val;
 
-      final_val = (local_symbol_get_frag (locsym)->fr_address
-                  + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput);
+      final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE;
 
-      if (finalize)
+      if (finalize_syms)
        {
-         locsym->lsy_offset = final_val;
+         locsym->lsy_value = final_val;
          local_symbol_mark_resolved (locsym);
        }
 
@@ -890,8 +876,9 @@ resolve_symbol_value (symp, finalize)
 
   if (symp->sy_resolving)
     {
-      if (finalize)
-       as_bad (_("Symbol definition loop encountered at %s"), S_GET_NAME (symp));
+      if (finalize_syms)
+       as_bad (_("symbol definition loop encountered at `%s'"),
+               S_GET_NAME (symp));
       final_val = 0;
       resolved = 1;
     }
@@ -929,19 +916,22 @@ resolve_symbol_value (symp, finalize)
 
        case O_symbol:
        case O_symbol_rva:
-         left = resolve_symbol_value (add_symbol, finalize);
-       do_symbol:
+         left = resolve_symbol_value (add_symbol);
+         seg_left = S_GET_SEGMENT (add_symbol);
+         if (finalize_syms)
+           symp->sy_value.X_op_symbol = NULL;
 
+       do_symbol:
          if (symp->sy_mri_common)
            {
              /* This is a symbol inside an MRI common section.  The
-                 relocation routines are going to handle it specially.
-                 Don't change the value.  */
+                relocation routines are going to handle it specially.
+                Don't change the value.  */
              resolved = symbol_resolved_p (add_symbol);
              break;
            }
 
-         if (finalize && final_val == 0)
+         if (finalize_syms && final_val == 0)
            {
              if (LOCAL_SYMBOL_CHECK (add_symbol))
                add_symbol = local_symbol_convert ((struct local_symbol *)
@@ -949,30 +939,51 @@ resolve_symbol_value (symp, finalize)
              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
-             X_add_number.  This permits the routine which writes out
-             relocation to detect this case, and convert the
-             relocation to be against the symbol to which this symbol
-             is equated.  */
+         /* If we have equated this symbol to an undefined or common
+            symbol, keep X_op set to O_symbol, and don't change
+            X_add_number.  This permits the routine which writes out
+            relocation to detect this case, and convert the
+            relocation to be against the symbol to which this symbol
+            is equated.  */
          if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
            {
-             if (finalize)
+             if (finalize_syms)
                {
-                 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;
+                 /* Use X_op_symbol as a flag.  */
+                 symp->sy_value.X_op_symbol = add_symbol;
+                 final_seg = seg_left;
                }
              final_val = 0;
              resolved = symbol_resolved_p (add_symbol);
+             symp->sy_resolving = 0;
+             goto exit_dont_set_value;
+           }
+         else if (finalize_syms && final_seg == expr_section
+                  && seg_left != expr_section)
+           {
+             /* If the symbol is an expression symbol, do similarly
+                as for undefined and common syms above.  Handles
+                "sym +/- expr" where "expr" cannot be evaluated
+                immediately, and we want relocations to be against
+                "sym", eg. because it is weak.  */
+             symp->sy_value.X_op = O_symbol;
+             symp->sy_value.X_add_symbol = add_symbol;
+             symp->sy_value.X_add_number = final_val;
+             symp->sy_value.X_op_symbol = add_symbol;
+             final_seg = seg_left;
+             final_val += symp->sy_frag->fr_address + left;
+             resolved = symbol_resolved_p (add_symbol);
+             symp->sy_resolving = 0;
              goto exit_dont_set_value;
            }
          else
            {
              final_val += symp->sy_frag->fr_address + left;
              if (final_seg == expr_section || final_seg == undefined_section)
-               final_seg = S_GET_SEGMENT (add_symbol);
+               final_seg = seg_left;
            }
 
          resolved = symbol_resolved_p (add_symbol);
@@ -981,7 +992,8 @@ resolve_symbol_value (symp, finalize)
        case O_uminus:
        case O_bit_not:
        case O_logical_not:
-         left = resolve_symbol_value (add_symbol, finalize);
+         left = resolve_symbol_value (add_symbol);
+         seg_left = S_GET_SEGMENT (add_symbol);
 
          if (op == O_uminus)
            left = -left;
@@ -992,7 +1004,7 @@ resolve_symbol_value (symp, finalize)
 
          final_val += left + symp->sy_frag->fr_address;
          if (final_seg == expr_section || final_seg == undefined_section)
-           final_seg = absolute_section;
+           final_seg = seg_left;
 
          resolved = symbol_resolved_p (add_symbol);
          break;
@@ -1016,50 +1028,61 @@ resolve_symbol_value (symp, finalize)
        case O_gt:
        case O_logical_and:
        case O_logical_or:
-         left = resolve_symbol_value (add_symbol, finalize);
-         right = resolve_symbol_value (op_symbol, finalize);
+         left = resolve_symbol_value (add_symbol);
+         right = resolve_symbol_value (op_symbol);
          seg_left = S_GET_SEGMENT (add_symbol);
          seg_right = S_GET_SEGMENT (op_symbol);
 
          /* Simplify addition or subtraction of a constant by folding the
             constant into X_add_number.  */
-         if (op == O_add || op == O_subtract)
+         if (op == O_add)
            {
              if (seg_right == absolute_section)
                {
-                 if (op == O_add)
-                   final_val += right;
-                 else
-                   final_val -= right;
-                 op = O_symbol;
-                 op_symbol = NULL;
+                 final_val += right;
                  goto do_symbol;
                }
-             else if (seg_left == absolute_section && op == O_add)
+             else if (seg_left == absolute_section)
                {
-                 op = O_symbol;
                  final_val += left;
                  add_symbol = op_symbol;
                  left = right;
-                 op_symbol = NULL;
+                 seg_left = seg_right;
+                 goto do_symbol;
+               }
+           }
+         else if (op == O_subtract)
+           {
+             if (seg_right == absolute_section)
+               {
+                 final_val -= right;
                  goto do_symbol;
                }
            }
 
-         /* Subtraction is permitted if both operands are in the same
-            section.  Otherwise, both operands must be absolute.  We
-            already handled the case of addition or subtraction of a
-            constant above.  This will probably need to be changed
-            for an object file format which supports arbitrary
-            expressions, such as IEEE-695.  */
-         /* Don't emit messages unless we're finalizing the symbol value,
+         /* Equality and non-equality tests are permitted on anything.
+            Subtraction, and other comparison operators are permitted if
+            both operands are in the same section.  Otherwise, both
+            operands must be absolute.  We already handled the case of
+            addition or subtraction of a constant above.  This will
+            probably need to be changed for an object file format which
+            supports arbitrary 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
-                 || seg_left == undefined_section)
-             && finalize)
+         if ((op == O_eq || op == O_ne)
+             || ((op == O_subtract
+                  || op == O_lt || op == O_le || op == O_ge || op == O_gt)
+                 && seg_left == seg_right
+                 && (seg_left != undefined_section
+                     || add_symbol == op_symbol))
+             || (seg_left == absolute_section
+                 && seg_right == absolute_section))
+           {
+             if (final_seg == expr_section || final_seg == undefined_section)
+               final_seg = absolute_section;
+           }
+         else if (finalize_syms)
            {
              char *file;
              unsigned int line;
@@ -1068,39 +1091,43 @@ 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));
                }
+             /* Prevent the error propagating.  */
+             if (final_seg == expr_section || final_seg == undefined_section)
+               final_seg = absolute_section;
            }
 
          /* Check for division by zero.  */
          if ((op == O_divide || op == O_modulus) && right == 0)
            {
              /* If seg_right is not absolute_section, then we've
-                 already issued a warning about using a bad symbol.  */
-             if (seg_right == absolute_section && finalize)
+                already issued a warning about using a bad symbol.  */
+             if (seg_right == absolute_section && finalize_syms)
                {
                  char *file;
                  unsigned int line;
@@ -1108,7 +1135,7 @@ resolve_symbol_value (symp, finalize)
                  if (expr_symbol_where (symp, &file, &line))
                    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));
                }
 
@@ -1128,8 +1155,15 @@ resolve_symbol_value (symp, finalize)
            case O_bit_and:             left &= right; break;
            case O_add:                 left += right; break;
            case O_subtract:            left -= right; break;
-           case O_eq:  left = left == right ? ~ (offsetT) 0 : 0; break;
-           case O_ne:  left = left != right ? ~ (offsetT) 0 : 0; break;
+           case O_eq:
+           case O_ne:
+             left = (left == right && seg_left == seg_right
+                     && (seg_left != undefined_section
+                         || add_symbol == op_symbol)
+                     ? ~ (offsetT) 0 : 0);
+             if (symp->sy_value.X_op == O_ne)
+               left = ~left;
+             break;
            case O_lt:  left = left <  right ? ~ (offsetT) 0 : 0; break;
            case O_le:  left = left <= right ? ~ (offsetT) 0 : 0; break;
            case O_ge:  left = left >= right ? ~ (offsetT) 0 : 0; break;
@@ -1141,10 +1175,18 @@ 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;
+           {
+             if (seg_left == undefined_section
+                 || seg_right == undefined_section)
+               final_seg = undefined_section;
+             else if (seg_left == absolute_section)
+               final_seg = seg_right;
+             else
+               final_seg = seg_left;
+           }
          resolved = (symbol_resolved_p (add_symbol)
                      && symbol_resolved_p (op_symbol));
-         break;
+         break;
 
        case O_register:
        case O_big:
@@ -1160,27 +1202,28 @@ resolve_symbol_value (symp, finalize)
       symp->sy_resolving = 0;
     }
 
-  if (finalize)
-    {
-      S_SET_VALUE (symp, final_val);
+  if (finalize_syms)
+    S_SET_VALUE (symp, final_val);
 
+exit_dont_set_value:
+  /* Always set the segment, even if not finalizing the value.
+     The segment is used to determine whether a symbol is defined.  */
 #if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
-      /* The old a.out backend does not handle S_SET_SEGMENT correctly
-         for a stab symbol, so we use this bad hack.  */
-      if (final_seg != S_GET_SEGMENT (symp))
+  /* The old a.out backend does not handle S_SET_SEGMENT correctly
+     for a stab symbol, so we use this bad hack.  */
+  if (final_seg != S_GET_SEGMENT (symp))
 #endif
-       S_SET_SEGMENT (symp, final_seg);
-    }
+    S_SET_SEGMENT (symp, final_seg);
 
-exit_dont_set_value:
   /* Don't worry if we can't resolve an expr_section symbol.  */
-  if (finalize)
+  if (finalize_syms)
     {
       if (resolved)
        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;
        }
     }
@@ -1200,7 +1243,7 @@ resolve_local_symbol (key, value)
      PTR value;
 {
   if (value != NULL)
-    resolve_symbol_value (value, 1);
+    resolve_symbol_value (value);
 }
 
 #endif
@@ -1228,7 +1271,7 @@ static char *dollar_label_defines;
 static unsigned long dollar_label_count;
 static unsigned long dollar_label_max;
 
-int 
+int
 dollar_label_defined (label)
      long label;
 {
@@ -1240,9 +1283,9 @@ dollar_label_defined (label)
     if (*i == label)
       return dollar_label_defines[i - dollar_labels];
 
-  /* if we get here, label isn't defined */
+  /* If we get here, label isn't defined.  */
   return 0;
-}                              /* dollar_label_defined() */
+}
 
 static long
 dollar_label_instance (label)
@@ -1256,12 +1299,12 @@ dollar_label_instance (label)
     if (*i == label)
       return (dollar_label_instances[i - dollar_labels]);
 
-  /* If we get here, we haven't seen the label before, therefore its instance
-     count is zero.  */
+  /* If we get here, we haven't seen the label before.
+     Therefore its instance count is zero.  */
   return 0;
 }
 
-void 
+void
 dollar_label_clear ()
 {
   memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
@@ -1269,7 +1312,7 @@ dollar_label_clear ()
 
 #define DOLLAR_LABEL_BUMP_BY 10
 
-void 
+void
 define_dollar_label (label)
      long label;
 {
@@ -1283,7 +1326,7 @@ define_dollar_label (label)
        return;
       }
 
-  /* if we get to here, we don't have label listed yet. */
+  /* If we get to here, we don't have label listed yet.  */
 
   if (dollar_labels == NULL)
     {
@@ -1301,7 +1344,7 @@ define_dollar_label (label)
       dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
                                          dollar_label_max * sizeof (long));
       dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
-    }                          /* if we needed to grow */
+    }                          /* if we needed to grow  */
 
   dollar_labels[dollar_label_count] = label;
   dollar_label_instances[dollar_label_count] = 1;
@@ -1309,31 +1352,28 @@ define_dollar_label (label)
   ++dollar_label_count;
 }
 
-/*
- *                     dollar_label_name()
- *
- * Caller must copy returned name: we re-use the area for the next name.
- *
- * The mth occurence of label n: is turned into the symbol "Ln^Am"
- * where n is the label number and m is the instance number. "L" makes
- * it a label discarded unless debugging and "^A"('\1') ensures no
- * ordinary symbol SHOULD get the same name as a local label
- * symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
- *
- * fb labels get the same treatment, except that ^B is used in place of ^A.
- */
-
-char *                         /* Return local label name. */
+/* Caller must copy returned name: we re-use the area for the next name.
+
+   The mth occurence of label n: is turned into the symbol "Ln^Am"
+   where n is the label number and m is the instance number. "L" makes
+   it a label discarded unless debugging and "^A"('\1') ensures no
+   ordinary symbol SHOULD get the same name as a local label
+   symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
+
+   fb labels get the same treatment, except that ^B is used in place
+   of ^A.  */
+
+char *                         /* Return local label name.  */
 dollar_label_name (n, augend)
-     register long n;          /* we just saw "n$:" : n a number */
-     register int augend;      /* 0 for current instance, 1 for new instance */
+     register long n;          /* we just saw "n$:" : n a number */
+     register int augend;      /* 0 for current instance, 1 for new instance */
 {
   long i;
-  /* Returned to caller, then copied.  used for created names ("4f") */
+  /* Returned to caller, then copied.  Used for created names ("4f").  */
   static char symbol_name_build[24];
   register char *p;
   register char *q;
-  char symbol_name_temporary[20];      /* build up a number, BACKWARDS */
+  char symbol_name_temporary[20];      /* Build up a number, BACKWARDS.  */
 
   know (n >= 0);
   know (augend == 0 || augend == 1);
@@ -1343,8 +1383,8 @@ dollar_label_name (n, augend)
 #endif
   *p++ = 'L';
 
-  /* Next code just does sprintf( {}, "%d", n); */
-  /* label number */
+  /* Next code just does sprintf( {}, "%d", n);  */
+  /* Label number.  */
   q = symbol_name_temporary;
   for (*q++ = 0, i = n; i; ++q)
     {
@@ -1354,9 +1394,9 @@ dollar_label_name (n, augend)
   while ((*p = *--q) != '\0')
     ++p;
 
-  *p++ = 1;                    /* ^A */
+  *p++ = DOLLAR_LABEL_CHAR;            /* ^A  */
 
-  /* instance number */
+  /* Instance number.  */
   q = symbol_name_temporary;
   for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
     {
@@ -1365,27 +1405,26 @@ dollar_label_name (n, augend)
     }
   while ((*p++ = *--q) != '\0');;
 
-  /* The label, as a '\0' ended string, starts at symbol_name_build. */
+  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
   return symbol_name_build;
 }
 
-/*
- * Sombody else's idea of local labels. They are made by "n:" where n
- * is any decimal digit. Refer to them with
- *  "nb" for previous (backward) n:
- *  or "nf" for next (forward) n:.
- *
- * We do a little better and let n be any number, not just a single digit, but
- * since the other guy's assembler only does ten, we treat the first ten
- * specially.
- *
- * Like someone else's assembler, we have one set of local label counters for
- * entire assembly, not one set per (sub)segment like in most assemblers. This
- * implies that one can refer to a label in another segment, and indeed some
- * crufty compilers have done just that.
- *
- * Since there could be a LOT of these things, treat them as a sparse array.
- */
+/* Sombody else's idea of local labels. They are made by "n:" where n
+   is any decimal digit. Refer to them with
+    "nb" for previous (backward) n:
+   or "nf" for next (forward) n:.
+
+   We do a little better and let n be any number, not just a single digit, but
+   since the other guy's assembler only does ten, we treat the first ten
+   specially.
+
+   Like someone else's assembler, we have one set of local label counters for
+   entire assembly, not one set per (sub)segment like in most assemblers. This
+   implies that one can refer to a label in another segment, and indeed some
+   crufty compilers have done just that.
+
+   Since there could be a LOT of these things, treat them as a sparse
+   array.  */
 
 #define FB_LABEL_SPECIAL (10)
 
@@ -1395,17 +1434,18 @@ static long *fb_label_instances;
 static long fb_label_count;
 static long fb_label_max;
 
-/* this must be more than FB_LABEL_SPECIAL */
+/* This must be more than FB_LABEL_SPECIAL.  */
 #define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
 
-static void 
+static void
 fb_label_init ()
 {
   memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
-}                              /* fb_label_init() */
+}
+
+/* Add one to the instance number of this fb label.  */
 
-/* add one to the instance number of this fb label */
-void 
+void
 fb_label_instance_inc (label)
      long label;
 {
@@ -1426,11 +1466,11 @@ fb_label_instance_inc (label)
            {
              ++fb_label_instances[i - fb_labels];
              return;
-           }                   /* if we find it */
-       }                       /* for each existing label */
+           }                   /* if we find it  */
+       }                       /* for each existing label  */
     }
 
-  /* if we get to here, we don't have label listed yet. */
+  /* If we get to here, we don't have label listed yet.  */
 
   if (fb_labels == NULL)
     {
@@ -1447,14 +1487,14 @@ fb_label_instance_inc (label)
                                     fb_label_max * sizeof (long));
       fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
                                              fb_label_max * sizeof (long));
-    }                          /* if we needed to grow */
+    }                          /* if we needed to grow  */
 
   fb_labels[fb_label_count] = label;
   fb_label_instances[fb_label_count] = 1;
   ++fb_label_count;
 }
 
-static long 
+static long
 fb_label_instance (label)
      long label;
 {
@@ -1473,8 +1513,8 @@ fb_label_instance (label)
          if (*i == label)
            {
              return (fb_label_instances[i - fb_labels]);
-           }                   /* if we find it */
-       }                       /* for each existing label */
+           }                   /* if we find it  */
+       }                       /* for each existing label  */
     }
 
   /* We didn't find the label, so this must be a reference to the
@@ -1482,38 +1522,39 @@ fb_label_instance (label)
   return 0;
 }
 
-/*
- *                     fb_label_name()
- *
- * Caller must copy returned name: we re-use the area for the next name.
- *
- * The mth occurence of label n: is turned into the symbol "Ln^Bm"
- * where n is the label number and m is the instance number. "L" makes
- * it a label discarded unless debugging and "^B"('\2') ensures no
- * ordinary symbol SHOULD get the same name as a local label
- * symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
- *
- * dollar labels get the same treatment, except that ^A is used in place of ^B. */
-
-char *                         /* Return local label name. */
+/* Caller must copy returned name: we re-use the area for the next name.
+
+   The mth occurence of label n: is turned into the symbol "Ln^Bm"
+   where n is the label number and m is the instance number. "L" makes
+   it a label discarded unless debugging and "^B"('\2') ensures no
+   ordinary symbol SHOULD get the same name as a local label
+   symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
+
+   dollar labels get the same treatment, except that ^A is used in
+   place of ^B.  */
+
+char *                         /* Return local label name.  */
 fb_label_name (n, augend)
-     long n;                   /* we just saw "n:", "nf" or "nb" : n a number */
-     long augend;              /* 0 for nb, 1 for n:, nf */
+     long n;                   /* We just saw "n:", "nf" or "nb" : n a number.  */
+     long augend;              /* 0 for nb, 1 for n:, nf */
 {
   long i;
-  /* Returned to caller, then copied.  used for created names ("4f") */
+  /* Returned to caller, then copied.  Used for created names ("4f").  */
   static char symbol_name_build[24];
   register char *p;
   register char *q;
-  char symbol_name_temporary[20];      /* build up a number, BACKWARDS */
+  char symbol_name_temporary[20];      /* Build up a number, BACKWARDS.  */
 
   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); */
-  /* label number */
+  /* Next code just does sprintf( {}, "%d", n);  */
+  /* Label number.  */
   q = symbol_name_temporary;
   for (*q++ = 0, i = n; i; ++q)
     {
@@ -1523,9 +1564,9 @@ fb_label_name (n, augend)
   while ((*p = *--q) != '\0')
     ++p;
 
-  *p++ = 2;                    /* ^B */
+  *p++ = LOCAL_LABEL_CHAR;             /* ^B  */
 
-  /* instance number */
+  /* Instance number.  */
   q = symbol_name_temporary;
   for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
     {
@@ -1534,15 +1575,13 @@ fb_label_name (n, augend)
     }
   while ((*p++ = *--q) != '\0');;
 
-  /* The label, as a '\0' ended string, starts at symbol_name_build. */
+  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
   return (symbol_name_build);
-}                              /* fb_label_name() */
+}
 
-/*
- * decode name that may have been generated by foo_label_name() above.  If
- * the name wasn't generated by foo_label_name(), then return it unaltered.
- * This is used for error messages.
- */
+/* Decode name that may have been generated by foo_label_name() above.
+   If the name wasn't generated by foo_label_name(), then return it
+   unaltered.  This is used for error messages.  */
 
 char *
 decode_local_label_name (s)
@@ -1553,24 +1592,31 @@ 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;
+  int index = 0;
+
+#ifdef LOCAL_LABEL_PREFIX
+  if (s[index] == LOCAL_LABEL_PREFIX)
+    ++index;
+#endif
 
-  if (s[0] != 'L')
+  if (s[index] != 'L')
     return s;
 
-  for (label_number = 0, p = s + 1; isdigit ((unsigned char) *p); ++p)
+  for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p)
     label_number = (10 * label_number) + *p - '0';
 
-  if (*p == 1)
+  if (*p == DOLLAR_LABEL_CHAR)
     type = "dollar";
-  else if (*p == 2)
+  else if (*p == LOCAL_LABEL_CHAR)
     type = "fb";
   else
     return s;
 
-  for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
+  for (instance_number = 0, p++; ISDIGIT (*p); ++p)
     instance_number = (10 * instance_number) + *p - '0';
 
+  message_format = _("\"%d\" (instance number %d of a %s label)");
   symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
   sprintf (symbol_decode, message_format, label_number, instance_number, type);
 
@@ -1585,11 +1631,15 @@ S_GET_VALUE (s)
 {
 #ifdef BFD_ASSEMBLER
   if (LOCAL_SYMBOL_CHECK (s))
-    return ((struct local_symbol *) s)->lsy_offset;
+    return resolve_symbol_value (s);
 #endif
 
-  if (!s->sy_resolved && s->sy_value.X_op != O_constant)
-    resolve_symbol_value (s, 1);
+  if (!s->sy_resolved)
+    {
+      valueT val = resolve_symbol_value (s);
+      if (!finalize_syms)
+       return val;
+    }
   if (s->sy_value.X_op != O_constant)
     {
       static symbolS *recur;
@@ -1603,7 +1653,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;
     }
@@ -1620,7 +1670,7 @@ S_SET_VALUE (s, val)
 #ifdef BFD_ASSEMBLER
   if (LOCAL_SYMBOL_CHECK (s))
     {
-      ((struct local_symbol *) s)->lsy_offset = val;
+      ((struct local_symbol *) s)->lsy_value = val;
       return;
     }
 #endif
@@ -1678,7 +1728,7 @@ S_IS_EXTERNAL (s)
 
   flags = s->bsym->flags;
 
-  /* sanity check */
+  /* Sanity check.  */
   if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
     abort ();
 
@@ -1735,7 +1785,7 @@ S_IS_LOCAL (s)
 
   flags = s->bsym->flags;
 
-  /* sanity check */
+  /* Sanity check.  */
   if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
     abort ();
 
@@ -1750,8 +1800,8 @@ S_IS_LOCAL (s)
   name = S_GET_NAME (s);
   return (name != NULL
          && ! S_IS_DEBUG (s)
-         && (strchr (name, '\001')
-             || strchr (name, '\002')
+         && (strchr (name, DOLLAR_LABEL_CHAR)
+             || strchr (name, LOCAL_LABEL_CHAR)
              || (! flag_keep_locals
                  && (bfd_is_local_label (stdoutput, s->bsym)
                      || (flag_mri
@@ -1773,7 +1823,7 @@ S_IS_STABD (s)
   return S_GET_NAME (s) == 0;
 }
 
-CONST char *
+const char *
 S_GET_NAME (s)
      symbolS *s;
 {
@@ -1814,7 +1864,7 @@ S_SET_SEGMENT (s, seg)
   if (s->bsym->flags & BSF_SECTION_SYM)
     {
       if (s->bsym->section != seg)
-       abort();
+       abort ();
     }
   else
     s->bsym->section = seg;
@@ -1831,8 +1881,19 @@ S_SET_EXTERNAL (s)
       /* Let .weak override .global.  */
       return;
     }
+  if (s->bsym->flags & BSF_SECTION_SYM)
+    {
+      char * file;
+      unsigned int line;
+
+      /* Do not reassign section symbols.  */
+      as_where (& file, & line);
+      as_warn_where (file, line,
+                    _("section symbols are already global"));
+      return;
+    }
   s->bsym->flags |= BSF_GLOBAL;
-  s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
+  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
 }
 
 void
@@ -1847,7 +1908,7 @@ S_CLEAR_EXTERNAL (s)
       return;
     }
   s->bsym->flags |= BSF_LOCAL;
-  s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
+  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
 }
 
 void
@@ -1857,7 +1918,7 @@ S_SET_WEAK (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);
+  s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
 }
 
 void
@@ -2125,7 +2186,7 @@ symbol_section_p (s)
 #ifdef BFD_ASSEMBLER
   return (s->bsym->flags & BSF_SECTION_SYM) != 0;
 #else
-  /* FIXME */
+  /* FIXME */
   return 0;
 #endif
 }
@@ -2141,6 +2202,24 @@ symbol_equated_p (s)
   return s->sy_value.X_op == O_symbol;
 }
 
+/* Return whether a symbol is equated to another symbol, and should be
+   treated specially when writing out relocs.  */
+
+int
+symbol_equated_reloc_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  /* X_op_symbol, normally not used for O_symbol, is set by
+     resolve_symbol_value to flag expression syms that have been
+     equated.  */
+  return (s->sy_value.X_op == O_symbol
+         && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
+             || ! S_IS_DEFINED (s)
+             || S_IS_COMMON (s)));
+}
+
 /* Return whether a symbol has a constant value.  */
 
 int
@@ -2237,7 +2316,7 @@ void
 symbol_begin ()
 {
   symbol_lastP = NULL;
-  symbol_rootP = NULL;         /* In case we have 0 symbols (!!) */
+  symbol_rootP = NULL;         /* In case we have 0 symbols (!!)  */
   sy_hash = hash_new ();
 #ifdef BFD_ASSEMBLER
   local_hash = hash_new ();
@@ -2249,7 +2328,7 @@ symbol_begin ()
   abs_symbol.bsym = bfd_abs_section.symbol;
 #endif
 #else
-  /* Can't initialise a union. Sigh. */
+  /* Can't initialise a union. Sigh.  */
   S_SET_SEGMENT (&abs_symbol, absolute_section);
 #endif
   abs_symbol.sy_value.X_op = O_constant;
@@ -2258,8 +2337,6 @@ symbol_begin ()
   if (LOCAL_LABELS_FB)
     fb_label_init ();
 }
-
-
 \f
 int indent_level;
 
@@ -2328,7 +2405,7 @@ print_symbol_value_1 (file, sym)
       segT s = S_GET_SEGMENT (sym);
 
       if (s != undefined_section
-          && s != expr_section)
+         && s != expr_section)
        fprintf (file, " %lx", (long) S_GET_VALUE (sym));
     }
   else if (indent_level < max_indent_level
@@ -2339,7 +2416,7 @@ print_symbol_value_1 (file, sym)
 #ifdef BFD_ASSEMBLER
       if (LOCAL_SYMBOL_CHECK (sym))
        fprintf (file, "constant %lx",
-                (long) ((struct local_symbol *) sym)->lsy_offset);
+                (long) ((struct local_symbol *) sym)->lsy_value);
       else
 #endif
        print_expr_1 (file, &sym->sy_value);
@@ -2361,7 +2438,7 @@ print_symbol_value (sym)
 static void
 print_binary (file, name, exp)
      FILE *file;
-     const char * name;
+     const char *name;
      expressionS *exp;
 {
   indent_level++;
@@ -2506,5 +2583,3 @@ symbol_print_statistics (file)
           local_symbol_count, local_symbol_conversion_count);
 #endif
 }
-
-/* end of symbols.c */
This page took 0.096095 seconds and 4 git commands to generate.