/* symbols.c -symbol table-
- Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#define DEBUG
+/* #define DEBUG_SYMS / * to debug symbol list maintenance */
#include <ctype.h>
#include "obstack.h" /* For "symbols.h" */
#include "subsegs.h"
+/* This is non-zero if symbols are case sensitive, which is the
+ default. */
+int symbols_case_sensitive = 1;
+
#ifndef WORKING_DOT_WORD
extern int new_broken_words;
#endif
symbolS *symbol_lastP;
symbolS abs_symbol;
-symbolS *dot_text_symbol;
-symbolS *dot_data_symbol;
-symbolS *dot_bss_symbol;
+#ifdef DEBUG_SYMS
+#define debug_verify_symchain verify_symbol_chain
+#else
+#define debug_verify_symchain(root, last) ((void) 0)
+#endif
struct obstack notes;
static void fb_label_init PARAMS ((void));
-void
-symbol_begin ()
+/* symbol_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
+ output file, you can call symbol_create. */
+
+symbolS *
+symbol_new (name, segment, valu, frag)
+ const char *name;
+ segT segment;
+ valueT valu;
+ fragS *frag;
{
- symbol_lastP = NULL;
- symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
- sy_hash = hash_new ();
- memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
+ symbolS *symbolP = symbol_create (name, segment, valu, frag);
+
+ /*
+ * Link to end of symbol chain.
+ */
#ifdef BFD_ASSEMBLER
- abs_symbol.bsym = bfd_abs_section.symbol;
-#else
- /* Can't initialise a union. Sigh. */
- S_SET_SEGMENT (&abs_symbol, absolute_section);
+ {
+ extern int symbol_table_frozen;
+ if (symbol_table_frozen)
+ abort ();
+ }
#endif
-#ifdef LOCAL_LABELS_FB
- fb_label_init ();
-#endif /* LOCAL_LABELS_FB */
-}
+ symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
+ debug_verify_symchain (symbol_rootP, symbol_lastP);
-/*
- * symbol_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.
- *
- *
- * Please always call this to create a new symbol.
- *
- * Changes since 1985: Symbol names may not contain '\0'. Sigh.
- * 2nd argument is now a SEG rather than a TYPE. The mapping between
- * segments and types is mostly encapsulated herein (actually, we inherit it
- * from macros in struc-symbol.h).
- */
+ return symbolP;
+}
symbolS *
-symbol_new (name, segment, value, frag)
- CONST char *name; /* It is copied, the caller can destroy/modify */
+symbol_create (name, segment, valu, frag)
+ const char *name; /* It is copied, the caller can destroy/modify */
segT segment; /* Segment identifier (SEG_<something>) */
- valueT value; /* Symbol value */
+ valueT valu; /* Symbol value */
fragS *frag; /* Associated fragment */
{
unsigned int name_length;
if (preserved_copy_of_name[0] == '_')
preserved_copy_of_name++;
#endif
+
+#ifdef tc_canonicalize_symbol_name
+ preserved_copy_of_name =
+ tc_canonicalize_symbol_name (preserved_copy_of_name);
+#endif
+
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *s;
+
+ for (s = (unsigned char *) preserved_copy_of_name; *s != '\0'; s++)
+ if (islower (*s))
+ *s = toupper (*s);
+ }
+
symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS));
/* symbol must be born in some fixed state. This seems as good as any. */
memset (symbolP, 0, sizeof (symbolS));
-
#ifdef BFD_ASSEMBLER
symbolP->bsym = bfd_make_empty_symbol (stdoutput);
- assert (symbolP->bsym != 0);
- symbolP->bsym->udata = (PTR) symbolP;
+ if (symbolP->bsym == NULL)
+ as_perror ("%s", "bfd_make_empty_symbol");
+ symbolP->bsym->udata.p = (PTR) symbolP;
#endif
S_SET_NAME (symbolP, preserved_copy_of_name);
S_SET_SEGMENT (symbolP, segment);
- S_SET_VALUE (symbolP, value);
- symbol_clear_list_pointers(symbolP);
+ S_SET_VALUE (symbolP, valu);
+ symbol_clear_list_pointers (symbolP);
symbolP->sy_frag = frag;
#ifndef BFD_ASSEMBLER
symbolP->sy_number = ~0;
- symbolP->sy_name_offset = ~0;
+ symbolP->sy_name_offset = (unsigned int) ~0;
#endif
- /*
- * Link to end of symbol chain.
- */
- symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
-
obj_symbol_new_hook (symbolP);
-#ifdef DEBUG
- verify_symbol_chain(symbol_rootP, symbol_lastP);
-#endif /* DEBUG */
+#ifdef tc_symbol_new_hook
+ tc_symbol_new_hook (symbolP);
+#endif
return symbolP;
}
* Gripes if we are redefining a symbol incompatibly (and ignores it).
*
*/
-void
+symbolS *
colon (sym_name) /* just seen "x:" - rattle symbols & frags */
- register char *sym_name; /* symbol name, as a cannonical string */
+ 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 */
-#ifdef LOCAL_LABELS_DOLLAR
/* Sun local labels go out of scope whenever a non-local symbol is
defined. */
-
- if (*sym_name != 'L')
+ if (LOCAL_LABELS_DOLLAR && ! LOCAL_LABEL (sym_name))
dollar_label_clear ();
-#endif /* LOCAL_LABELS_DOLLAR */
#ifndef WORKING_DOT_WORD
if (new_broken_words)
{
#ifdef RESOLVE_SYMBOL_REDEFINITION
if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
- return;
+ return symbolP;
#endif
/*
* Now check for undefined symbols
{
symbolP->sy_frag = frag_now;
#ifdef OBJ_VMS
- S_GET_OTHER(symbolP) = const_flag;
+ S_SET_OTHER(symbolP, const_flag);
#endif
- S_SET_VALUE (symbolP, (valueT) ((char*)obstack_next_free (&frags) - frag_now->fr_literal));
+ S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
S_SET_SEGMENT (symbolP, now_seg);
#ifdef N_UNDF
know (N_UNDF == 0);
data. */
symbolP->sy_frag = frag_now;
#ifdef OBJ_VMS
- S_GET_OTHER(symbolP) = const_flag;
-#endif /* OBJ_VMS */
+ 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_GET_OTHER (symbolP), S_GET_DESC (symbolP),
(long) S_GET_VALUE (symbolP));
#else
- as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.",
+ as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%ld.",
sym_name,
segment_name (S_GET_SEGMENT (symbolP)),
- S_GET_VALUE (symbolP));
+ (long) S_GET_VALUE (symbolP));
#endif
}
} /* if the undefined symbol has no value */
{
/* Don't blow up if the definition is the same */
if (!(frag_now == symbolP->sy_frag
- && S_GET_VALUE (symbolP) == (char*)obstack_next_free (&frags) - frag_now->fr_literal
+ && 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 */
}
else
{
- symbolP = symbol_new (sym_name,
- now_seg,
- (valueT) ((char*)obstack_next_free (&frags) - frag_now->fr_literal),
+ symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
frag_now);
#ifdef OBJ_VMS
S_SET_OTHER (symbolP, const_flag);
symbol_table_insert (symbolP);
} /* if we have seen this symbol before */
+ if (mri_common_symbol != NULL)
+ {
+ /* This symbol is actually being defined within an MRI common
+ section. This requires special handling. */
+ 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);
+ symbolP->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (symbolP, expr_section);
+ symbolP->sy_mri_common = 1;
+ }
+
#ifdef tc_frob_label
tc_frob_label (symbolP);
#endif
- return;
-} /* colon() */
+ return symbolP;
+}
\f
/*
symbol_table_insert (symbolP)
symbolS *symbolP;
{
- register char *error_string;
+ register const char *error_string;
know (symbolP);
know (S_GET_NAME (symbolP));
- if (*(error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (char *) symbolP)))
+ if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
{
as_fatal ("Inserting \"%s\" into symbol table failed: %s",
S_GET_NAME (symbolP), error_string);
*/
symbolS *
symbol_find_or_make (name)
- char *name;
+ const char *name;
{
register symbolS *symbolP;
{
if (strip_underscore && *name == '_')
name++;
+
+#ifdef tc_canonicalize_symbol_name
+ {
+ char *copy;
+
+ copy = (char *) alloca (strlen (name) + 1);
+ strcpy (copy, name);
+ name = tc_canonicalize_symbol_name (copy);
+ }
+#endif
+
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *copy;
+
+ copy = (unsigned char *) alloca (strlen (name) + 1);
+ name = (const char *) copy;
+ for (; *copy != '\0'; copy++)
+ if (islower (*copy))
+ *copy = toupper (*copy);
+ }
+
return ((symbolS *) hash_find (sy_hash, name));
}
#endif /* SYMBOLS_NEED_BACKPOINTERS */
}
+/* Set the chain pointers of SYMBOL to null. */
+void
+symbol_clear_list_pointers (symbolP)
+ symbolS *symbolP;
+{
+ symbolP->sy_next = NULL;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ symbolP->sy_previous = NULL;
+#endif
+}
+
#ifdef SYMBOLS_NEED_BACKPOINTERS
/* Remove SYMBOLP from the list. */
void
symbolP->sy_previous->sy_next = symbolP->sy_next;
} /* if not first */
-#ifdef DEBUG
- verify_symbol_chain (*rootPP, *lastPP);
-#endif /* DEBUG */
-}
-
-/* Set the chain pointers of SYMBOL to null. */
-void
-symbol_clear_list_pointers (symbolP)
- symbolS *symbolP;
-{
- symbolP->sy_next = NULL;
- symbolP->sy_previous = NULL;
+ debug_verify_symchain (*rootPP, *lastPP);
}
/* Link symbol ADDME before symbol TARGET in the chain. */
target->sy_previous = addme;
addme->sy_next = target;
-#ifdef DEBUG
- verify_symbol_chain (*rootPP, *lastPP);
-#endif /* DEBUG */
+ debug_verify_symchain (*rootPP, *lastPP);
}
#endif /* SYMBOLS_NEED_BACKPOINTERS */
know (symbolP->sy_next->sy_previous == symbolP);
#else
/* Walk the list anyways, to make sure pointers are still good. */
- *symbolP;
+ ;
#endif /* SYMBOLS_NEED_BACKPOINTERS */
}
resolve_symbol_value (symp)
symbolS *symp;
{
+ int resolved;
+
if (symp->sy_resolved)
return;
+ resolved = 0;
+
if (symp->sy_resolving)
{
as_bad ("Symbol definition loop encountered at %s",
S_GET_NAME (symp));
S_SET_VALUE (symp, (valueT) 0);
+ resolved = 1;
}
else
{
symp->sy_resolving = 1;
+ /* Simplify addition or subtraction of a constant by folding the
+ constant into X_add_number. */
+ if (symp->sy_value.X_op == O_add
+ || symp->sy_value.X_op == O_subtract)
+ {
+ resolve_symbol_value (symp->sy_value.X_add_symbol);
+ resolve_symbol_value (symp->sy_value.X_op_symbol);
+ if (S_GET_SEGMENT (symp->sy_value.X_op_symbol) == absolute_section)
+ {
+ right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+ if (symp->sy_value.X_op == O_add)
+ symp->sy_value.X_add_number += right;
+ else
+ symp->sy_value.X_add_number -= right;
+ symp->sy_value.X_op = O_symbol;
+ symp->sy_value.X_op_symbol = NULL;
+ }
+ else if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+ == absolute_section)
+ && symp->sy_value.X_op == O_add)
+ {
+ left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+ symp->sy_value.X_add_symbol = symp->sy_value.X_op_symbol;
+ symp->sy_value.X_add_number += left;
+ symp->sy_value.X_op = O_symbol;
+ symp->sy_value.X_op_symbol = NULL;
+ }
+ }
+
switch (symp->sy_value.X_op)
{
case O_absent:
S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
if (S_GET_SEGMENT (symp) == expr_section)
S_SET_SEGMENT (symp, absolute_section);
+ resolved = 1;
break;
case O_symbol:
resolve_symbol_value (symp->sy_value.X_add_symbol);
-#ifdef obj_frob_forward_symbol
- /* Some object formats need to forward the segment. */
- obj_frob_forward_symbol (symp);
-#endif
+ 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. */
+ S_SET_VALUE (symp, symp->sy_value.X_add_number);
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
+ break;
+ }
- S_SET_VALUE (symp,
- (symp->sy_value.X_add_number
- + symp->sy_frag->fr_address
- + S_GET_VALUE (symp->sy_value.X_add_symbol)));
- if (S_GET_SEGMENT (symp) == expr_section
- || S_GET_SEGMENT (symp) == undefined_section)
- S_SET_SEGMENT (symp,
- S_GET_SEGMENT (symp->sy_value.X_add_symbol));
+ if (symp->sy_value.X_add_number == 0)
+ copy_symbol_attributes (symp, symp->sy_value.X_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 (! S_IS_DEFINED (symp->sy_value.X_add_symbol)
+ || S_IS_COMMON (symp->sy_value.X_add_symbol))
+ symp->sy_value.X_op = O_symbol;
+ else
+ {
+ S_SET_VALUE (symp,
+ (symp->sy_value.X_add_number
+ + symp->sy_frag->fr_address
+ + S_GET_VALUE (symp->sy_value.X_add_symbol)));
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp,
+ S_GET_SEGMENT (symp->sy_value.X_add_symbol));
+ }
+
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
break;
case O_uminus:
case O_bit_not:
+ case O_logical_not:
resolve_symbol_value (symp->sy_value.X_add_symbol);
if (symp->sy_value.X_op == O_uminus)
val = - S_GET_VALUE (symp->sy_value.X_add_symbol);
+ else if (symp->sy_value.X_op == O_logical_not)
+ val = ! S_GET_VALUE (symp->sy_value.X_add_symbol);
else
val = ~ S_GET_VALUE (symp->sy_value.X_add_symbol);
S_SET_VALUE (symp,
if (S_GET_SEGMENT (symp) == expr_section
|| S_GET_SEGMENT (symp) == undefined_section)
S_SET_SEGMENT (symp, absolute_section);
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
break;
case O_multiply:
case O_bit_and:
case O_add:
case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
+ case O_logical_and:
+ case O_logical_or:
resolve_symbol_value (symp->sy_value.X_add_symbol);
resolve_symbol_value (symp->sy_value.X_op_symbol);
seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
- if (seg_left != seg_right
- && seg_left != undefined_section
- && seg_right != undefined_section)
- as_bad ("%s is operation on symbols in different sections",
- S_GET_NAME (symp));
- if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
- != absolute_section)
- && symp->sy_value.X_op != O_subtract)
- as_bad ("%s is illegal operation on non-absolute symbols",
- S_GET_NAME (symp));
left = S_GET_VALUE (symp->sy_value.X_add_symbol);
right = S_GET_VALUE (symp->sy_value.X_op_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. */
+ if ((seg_left != absolute_section
+ || seg_right != absolute_section)
+ && (symp->sy_value.X_op != O_subtract
+ || seg_left != seg_right))
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ {
+ if (seg_left == undefined_section
+ || seg_right == undefined_section)
+ as_bad_where (file, line,
+ "undefined symbol %s in operation",
+ (seg_left == undefined_section
+ ? S_GET_NAME (symp->sy_value.X_add_symbol)
+ : S_GET_NAME (symp->sy_value.X_op_symbol)));
+ else
+ as_bad_where (file, line, "invalid section for operation");
+ }
+ else
+ {
+ if (seg_left == undefined_section
+ || seg_right == undefined_section)
+ as_bad ("undefined symbol %s in operation setting %s",
+ (seg_left == undefined_section
+ ? S_GET_NAME (symp->sy_value.X_add_symbol)
+ : S_GET_NAME (symp->sy_value.X_op_symbol)),
+ S_GET_NAME (symp));
+ else
+ as_bad ("invalid section for operation setting %s",
+ S_GET_NAME (symp));
+ }
+ }
+
switch (symp->sy_value.X_op)
{
case O_multiply: val = left * right; break;
case O_bit_and: val = left & right; break;
case O_add: val = left + right; break;
case O_subtract: val = left - right; break;
+ case O_eq: val = left == right ? ~ (offsetT) 0 : 0;
+ case O_ne: val = left != right ? ~ (offsetT) 0 : 0;
+ case O_lt: val = left < right ? ~ (offsetT) 0 : 0;
+ case O_le: val = left <= right ? ~ (offsetT) 0 : 0;
+ case O_ge: val = left >= right ? ~ (offsetT) 0 : 0;
+ case O_gt: val = left > right ? ~ (offsetT) 0 : 0;
+ case O_logical_and: val = left && right; break;
+ case O_logical_or: val = left || right; break;
default: abort ();
}
S_SET_VALUE (symp,
if (S_GET_SEGMENT (symp) == expr_section
|| S_GET_SEGMENT (symp) == undefined_section)
S_SET_SEGMENT (symp, absolute_section);
+ resolved = (symp->sy_value.X_add_symbol->sy_resolved
+ && symp->sy_value.X_op_symbol->sy_resolved);
break;
case O_register:
case O_big:
case O_illegal:
- as_bad ("bad value for symbol \"%s\"", S_GET_NAME (symp));
+ /* Give an error (below) if not in expr_section. We don't
+ want to worry about expr_section symbols, because they
+ are fictional (they are created as part of expression
+ resolution), and any problems may not actually mean
+ anything. */
break;
}
}
- symp->sy_resolved = 1;
+ /* Don't worry if we can't resolve an expr_section symbol. */
+ 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));
+ symp->sy_resolved = 1;
+ }
}
-#ifdef LOCAL_LABELS_DOLLAR
-
/* 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
static long *dollar_label_instances;
static char *dollar_label_defines;
static long dollar_label_count;
-static long dollar_label_max;
+static unsigned long dollar_label_max;
int
dollar_label_defined (label)
void
dollar_label_clear ()
{
- memset (dollar_label_defines, '\0', dollar_label_count);
+ memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
}
#define DOLLAR_LABEL_BUMP_BY 10
return symbol_name_build;
}
-#endif /* LOCAL_LABELS_DOLLAR */
-
-#ifdef LOCAL_LABELS_FB
-
/*
* Sombody else's idea of local labels. They are made by "n:" where n
* is any decimal digit. Refer to them with
static long fb_low_counter[FB_LABEL_SPECIAL];
static long *fb_labels;
static long *fb_label_instances;
-static long fb_label_count = 0;
-static long fb_label_max = 0;
+static long fb_label_count;
+static long fb_label_max;
/* this must be more than FB_LABEL_SPECIAL */
#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
fb_labels[fb_label_count] = label;
fb_label_instances[fb_label_count] = 1;
++fb_label_count;
- return;
-} /* fb_label_instance_inc() */
+}
static long
fb_label_instance (label)
return (symbol_name_build);
} /* fb_label_name() */
-#endif /* LOCAL_LABELS_FB */
-
-
/*
* 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.
const char *message_format = "\"%d\" (instance number %d of a %s label)";
if (s[0] != 'L')
- return (s);
+ return s;
for (label_number = 0, p = s + 1; isdigit (*p); ++p)
- {
- label_number = (10 * label_number) + *p - '0';
- }
+ label_number = (10 * label_number) + *p - '0';
if (*p == 1)
- {
- type = "dollar";
- }
+ type = "dollar";
else if (*p == 2)
- {
- type = "fb";
- }
+ type = "fb";
else
- {
- return (s);
- }
+ return s;
- for (instance_number = 0, p = s + 1; isdigit (*p); ++p)
- {
- instance_number = (10 * instance_number) + *p - '0';
- }
+ for (instance_number = 0, p++; isdigit (*p); ++p)
+ instance_number = (10 * instance_number) + *p - '0';
symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30);
- (void) sprintf (symbol_decode, message_format, label_number,
- instance_number, type);
+ sprintf (symbol_decode, message_format, label_number, instance_number, type);
- return (symbol_decode);
-} /* decode_local_label_name() */
+ return symbol_decode;
+}
/* Get the value of a symbol. */
S_GET_VALUE (s)
symbolS *s;
{
+ if (!s->sy_resolved && !s->sy_resolving && s->sy_value.X_op != O_constant)
+ resolve_symbol_value (s);
if (s->sy_value.X_op != O_constant)
- as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
+ {
+ static symbolS *recur;
+
+ /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
+ may call S_GET_VALUE. We use a static symbol to avoid the
+ immediate recursion. */
+ if (recur == s)
+ return (valueT) s->sy_value.X_add_number;
+ recur = 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",
+ S_GET_NAME (s));
+ recur = NULL;
+ }
return (valueT) s->sy_value.X_add_number;
}
{
s->sy_value.X_op = O_constant;
s->sy_value.X_add_number = (offsetT) val;
+ s->sy_value.X_unsigned = 0;
+}
+
+void
+copy_symbol_attributes (dest, src)
+ symbolS *dest, *src;
+{
+#ifdef BFD_ASSEMBLER
+ /* In an expression, transfer the settings of these flags.
+ The user can override later, of course. */
+#define COPIED_SYMFLAGS (BSF_FUNCTION)
+ dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
+#endif
+
+#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
+ OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
+#endif
}
#ifdef BFD_ASSEMBLER
flagword flags = s->bsym->flags;
/* sanity check */
- if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
+ if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
abort ();
- return (flags & (BSF_EXPORT | BSF_GLOBAL)) != 0;
+ return (flags & BSF_GLOBAL) != 0;
+}
+
+int
+S_IS_WEAK (s)
+ symbolS *s;
+{
+ return (s->bsym->flags & BSF_WEAK) != 0;
}
int
S_IS_COMMON (s)
symbolS *s;
{
- return s->bsym->section == &bfd_com_section;
+ return bfd_is_com_section (s->bsym->section);
}
int
symbolS *s;
{
flagword flags = s->bsym->flags;
+ const char *name;
/* sanity check */
- if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
+ if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
abort ();
- return (S_GET_NAME (s)
+ if (bfd_get_section (s->bsym) == reg_section)
+ return 1;
+
+ name = S_GET_NAME (s);
+ return (name != NULL
&& ! S_IS_DEBUG (s)
- && (strchr (S_GET_NAME (s), '\001')
- || strchr (S_GET_NAME (s), '\002')
- || (S_LOCAL_NAME (s)
- && !flagseen['L'])));
+ && (strchr (name, '\001')
+ || strchr (name, '\002')
+ || (! flag_keep_locals
+ && (LOCAL_LABEL (name)
+ || (flag_mri
+ && name[0] == '?'
+ && name[1] == '?')))));
}
int
S_SET_EXTERNAL (s)
symbolS *s;
{
- s->bsym->flags |= BSF_EXPORT | BSF_GLOBAL;
- s->bsym->flags &= ~BSF_LOCAL;
+ if ((s->bsym->flags & BSF_WEAK) != 0)
+ {
+ /* Let .weak override .global. */
+ return;
+ }
+ s->bsym->flags |= BSF_GLOBAL;
+ s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
}
void
S_CLEAR_EXTERNAL (s)
symbolS *s;
{
+ if ((s->bsym->flags & BSF_WEAK) != 0)
+ {
+ /* Let .weak override. */
+ return;
+ }
s->bsym->flags |= BSF_LOCAL;
- s->bsym->flags &= ~(BSF_EXPORT | BSF_GLOBAL);
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
+}
+
+void
+S_SET_WEAK (s)
+ symbolS *s;
+{
+ s->bsym->flags |= BSF_WEAK;
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
}
void
}
#endif /* BFD_ASSEMBLER */
+void
+symbol_begin ()
+{
+ symbol_lastP = NULL;
+ symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
+ sy_hash = hash_new ();
+
+ memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
+#ifdef BFD_ASSEMBLER
+#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
+ abs_symbol.bsym = bfd_abs_section.symbol;
+#endif
+#else
+ /* Can't initialise a union. Sigh. */
+ S_SET_SEGMENT (&abs_symbol, absolute_section);
+#endif
+ abs_symbol.sy_value.X_op = O_constant;
+ abs_symbol.sy_frag = &zero_address_frag;
+
+ if (LOCAL_LABELS_FB)
+ fb_label_init ();
+}
+
+\f
+int indent_level;
+
+#if 0
+
+static void
+indent ()
+{
+ printf ("%*s", indent_level * 4, "");
+}
+
+#endif
+
+void print_expr_1 PARAMS ((FILE *, expressionS *));
+void print_symbol_value_1 PARAMS ((FILE *, symbolS *));
+
+void
+print_symbol_value_1 (file, sym)
+ FILE *file;
+ symbolS *sym;
+{
+ const char *name = S_GET_NAME (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");
+ fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
+ if (sym->sy_resolved)
+ {
+ segT s = S_GET_SEGMENT (sym);
+
+ if (s != undefined_section
+ && s != expr_section)
+ fprintf (file, " %lx", (long) S_GET_VALUE (sym));
+ }
+ else if (indent_level < 8 && S_GET_SEGMENT (sym) != undefined_section)
+ {
+ indent_level++;
+ fprintf (file, "\n%*s<", indent_level * 4, "");
+ print_expr_1 (file, &sym->sy_value);
+ fprintf (file, ">");
+ indent_level--;
+ }
+ fflush (file);
+}
+
+void
+print_symbol_value (sym)
+ symbolS *sym;
+{
+ indent_level = 0;
+ print_symbol_value_1 (stderr, sym);
+ fprintf (stderr, "\n");
+}
+
+void
+print_expr_1 (file, exp)
+ FILE *file;
+ expressionS *exp;
+{
+ fprintf (file, "expr %lx ", (long) exp);
+ switch (exp->X_op)
+ {
+ case O_illegal:
+ fprintf (file, "illegal");
+ break;
+ case O_absent:
+ fprintf (file, "absent");
+ break;
+ case O_constant:
+ fprintf (file, "constant %lx", (long) exp->X_add_number);
+ break;
+ case O_symbol:
+ indent_level++;
+ fprintf (file, "symbol\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">");
+ maybe_print_addnum:
+ if (exp->X_add_number)
+ fprintf (file, "\n%*s%lx", indent_level * 4, "",
+ (long) exp->X_add_number);
+ indent_level--;
+ break;
+ case O_register:
+ fprintf (file, "register #%d", (int) exp->X_add_number);
+ break;
+ case O_big:
+ fprintf (file, "big");
+ break;
+ case O_uminus:
+ fprintf (file, "uminus -<");
+ indent_level++;
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ case O_bit_not:
+ fprintf (file, "bit_not");
+ break;
+ case O_multiply:
+ fprintf (file, "multiply");
+ break;
+ case O_divide:
+ fprintf (file, "divide");
+ break;
+ case O_modulus:
+ fprintf (file, "modulus");
+ break;
+ case O_left_shift:
+ fprintf (file, "lshift");
+ break;
+ case O_right_shift:
+ fprintf (file, "rshift");
+ break;
+ case O_bit_inclusive_or:
+ fprintf (file, "bit_ior");
+ break;
+ case O_bit_exclusive_or:
+ fprintf (file, "bit_xor");
+ break;
+ case O_bit_and:
+ fprintf (file, "bit_and");
+ break;
+ case O_eq:
+ fprintf (file, "eq");
+ break;
+ case O_ne:
+ fprintf (file, "ne");
+ break;
+ case O_lt:
+ fprintf (file, "lt");
+ break;
+ case O_le:
+ fprintf (file, "le");
+ break;
+ case O_ge:
+ fprintf (file, "ge");
+ break;
+ case O_gt:
+ fprintf (file, "gt");
+ break;
+ case O_logical_and:
+ fprintf (file, "logical_and");
+ break;
+ case O_logical_or:
+ fprintf (file, "logical_or");
+ break;
+ case O_add:
+ indent_level++;
+ fprintf (file, "add\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_op_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ case O_subtract:
+ indent_level++;
+ fprintf (file, "subtract\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_op_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ default:
+ fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
+ break;
+ }
+ fflush (stdout);
+}
+
+void
+print_expr (exp)
+ expressionS *exp;
+{
+ print_expr_1 (stderr, exp);
+ fprintf (stderr, "\n");
+}
+
+void
+symbol_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "symbol table", sy_hash);
+}
+
/* end of symbols.c */