/* symbols.c -symbol table-
- Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GNU General Public License for more details.
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* #define DEBUG_SYMS / * to debug symbol list maintenance */
#ifdef DEBUG_SYMS
#define debug_verify_symchain verify_symbol_chain
#else
-#define debug_verify_symchain (void)
+#define debug_verify_symchain(root, last) ((void) 0)
#endif
struct obstack notes;
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()
}
#endif
symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
- debug_verify_symchain (symbol_rootP, symbol_lastP);
return symbolP;
}
#ifdef BFD_ASSEMBLER
symbolP->bsym = bfd_make_empty_symbol (stdoutput);
- assert (symbolP->bsym != 0);
+ 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);
/* Sun local labels go out of scope whenever a non-local symbol is
defined. */
- if (LOCAL_LABELS_DOLLAR && *sym_name != 'L')
- dollar_label_clear ();
+ if (LOCAL_LABELS_DOLLAR)
+ {
+ int local;
+
+#ifdef BFD_ASSEMBLER
+ local = bfd_is_local_label_name (stdoutput, sym_name);
+#else
+ local = LOCAL_LABEL (sym_name);
+#endif
+
+ if (! local)
+ dollar_label_clear ();
+ }
#ifndef WORKING_DOT_WORD
if (new_broken_words)
possible_bytes,
(relax_substateT) 0,
(symbolS *) broken_words,
- 0L,
+ (offsetT) 0,
NULL);
/* We want to store the pointer to where to insert the jump table in the
/*
* Now check for undefined symbols
*/
- if (!S_IS_DEFINED (symbolP))
+ if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
{
if (S_GET_VALUE (symbolP) == 0)
{
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) frag_now_fix ());
S_SET_SEGMENT (symbolP, now_seg);
*/
if (((!S_IS_DEBUG (symbolP)
- && !S_IS_DEFINED (symbolP)
+ && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
&& S_IS_EXTERNAL (symbolP))
|| S_GET_SEGMENT (symbolP) == bss_section)
&& (now_seg == data_section
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 */
}
#ifdef tc_frob_label
tc_frob_label (symbolP);
#endif
+#ifdef obj_frob_label
+ obj_frob_label (symbolP);
+#endif
return symbolP;
}
*/
symbolS *
symbol_find_or_make (name)
- char *name;
+ const char *name;
{
register symbolS *symbolP;
{
know (*rootPP == NULL);
know (*lastPP == NULL);
+ addme->sy_next = NULL;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ addme->sy_previous = NULL;
+#endif
*rootPP = addme;
*lastPP = addme;
return;
#ifdef SYMBOLS_NEED_BACKPOINTERS
addme->sy_previous = target;
#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+ debug_verify_symchain (symbol_rootP, symbol_lastP);
}
/* Set the chain pointers of SYMBOL to null. */
for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
{
#ifdef SYMBOLS_NEED_BACKPOINTERS
- know (symbolP->sy_next->sy_previous == symbolP);
+ assert (symbolP->sy_next->sy_previous == symbolP);
#else
/* Walk the list anyways, to make sure pointers are still good. */
;
pass over the symbol table to resolve any symbols with complex
values. */
-void
-resolve_symbol_value (symp)
+valueT
+resolve_symbol_value (symp, finalize)
symbolS *symp;
+ int finalize;
{
int resolved;
+ valueT final_val;
+ segT final_seg;
if (symp->sy_resolved)
- return;
+ {
+ if (symp->sy_value.X_op == O_constant)
+ return (valueT) symp->sy_value.X_add_number;
+ else
+ return 0;
+ }
resolved = 0;
+ final_seg = S_GET_SEGMENT (symp);
if (symp->sy_resolving)
{
- as_bad ("Symbol definition loop encountered at %s",
- S_GET_NAME (symp));
- S_SET_VALUE (symp, (valueT) 0);
+ if (finalize)
+ as_bad ("Symbol definition loop encountered at %s", S_GET_NAME (symp));
+ final_val = 0;
resolved = 1;
}
else
{
- offsetT left, right, val;
+ symbolS *add_symbol, *op_symbol;
+ offsetT left, right;
segT seg_left, seg_right;
+ operatorT op;
symp->sy_resolving = 1;
- reduce:
- switch (symp->sy_value.X_op)
+ /* Help out with CSE. */
+ add_symbol = symp->sy_value.X_add_symbol;
+ op_symbol = symp->sy_value.X_op_symbol;
+ final_val = symp->sy_value.X_add_number;
+ op = symp->sy_value.X_op;
+
+ switch (op)
{
+ default:
+ BAD_CASE (op);
+ break;
+
case O_absent:
- S_SET_VALUE (symp, 0);
+ final_val = 0;
/* Fall through. */
+
case O_constant:
- 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);
+ final_val += symp->sy_frag->fr_address;
+ if (final_seg == expr_section)
+ final_seg = absolute_section;
resolved = 1;
break;
case O_symbol:
- resolve_symbol_value (symp->sy_value.X_add_symbol);
+ case O_symbol_rva:
+ left = resolve_symbol_value (add_symbol, finalize);
+ 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. */
- S_SET_VALUE (symp, symp->sy_value.X_add_number);
- resolved = symp->sy_value.X_add_symbol->sy_resolved;
+ resolved = add_symbol->sy_resolved;
break;
}
-#if 0 /* I thought this was needed for some of the i386-svr4 PIC
- support, but it appears I was wrong, and it breaks rs6000
- support. */
- if (S_GET_SEGMENT (symp->sy_value.X_add_symbol) != undefined_section
- && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section)
-#endif
+ if (finalize && final_val == 0)
+ 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 (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
+ {
+ if (finalize)
+ {
+ symp->sy_value.X_op = O_symbol;
+ S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
+ symp->sy_value.X_add_number = final_val;
+ }
+ final_val = 0;
+ resolved = add_symbol->sy_resolved;
+ goto exit_dont_set_value;
+ }
+ else
{
- if (symp->sy_value.X_add_number == 0)
- copy_symbol_attributes (symp, symp->sy_value.X_add_symbol);
-
- 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));
+ final_val += symp->sy_frag->fr_address + left;
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = S_GET_SEGMENT (add_symbol);
}
- resolved = symp->sy_value.X_add_symbol->sy_resolved;
+
+ resolved = add_symbol->sy_resolved;
break;
case O_uminus:
case O_bit_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);
+ case O_logical_not:
+ left = resolve_symbol_value (add_symbol, finalize);
+
+ if (op == O_uminus)
+ left = -left;
+ else if (op == O_logical_not)
+ left = !left;
else
- val = ~ S_GET_VALUE (symp->sy_value.X_add_symbol);
- S_SET_VALUE (symp,
- (val
- + symp->sy_value.X_add_number
- + symp->sy_frag->fr_address));
- 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;
+ left = ~left;
- case O_add:
- 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);
- /* This case comes up with PIC support. */
- {
- symbolS *s_left = symp->sy_value.X_add_symbol;
- symbolS *s_right = symp->sy_value.X_op_symbol;
-
- if (seg_left == absolute_section)
- {
- symbolS *t;
- segT ts;
- t = s_left;
- s_left = s_right;
- s_right = t;
- ts = seg_left;
- seg_left = seg_right;
- seg_right = ts;
- }
- if (seg_right == absolute_section
- && s_right->sy_resolved)
- {
- symp->sy_value.X_add_number += S_GET_VALUE (s_right);
- symp->sy_value.X_op_symbol = 0;
- symp->sy_value.X_add_symbol = s_left;
- symp->sy_value.X_op = O_symbol;
- goto reduce;
- }
- }
- /* fall through */
+ final_val += left + symp->sy_frag->fr_address;
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
+
+ resolved = add_symbol->sy_resolved;
+ break;
case O_multiply:
case O_divide:
case O_bit_or_not:
case O_bit_exclusive_or:
case O_bit_and:
+ case O_add:
case O_subtract:
case O_eq:
case O_ne:
case O_le:
case O_ge:
case O_gt:
- 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);
+ case O_logical_and:
+ case O_logical_or:
+ left = resolve_symbol_value (add_symbol, finalize);
+ right = resolve_symbol_value (op_symbol, finalize);
+ 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 (seg_right == absolute_section)
+ {
+ if (op == O_add)
+ final_val += right;
+ else
+ final_val -= right;
+ op = O_symbol;
+ op_symbol = NULL;
+ goto do_symbol;
+ }
+ else if (seg_left == absolute_section && op == O_add)
+ {
+ op = O_symbol;
+ final_val += left;
+ add_symbol = op_symbol;
+ left = right;
+ op_symbol = NULL;
+ 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,
+ 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)
+ && finalize)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ {
+ if (seg_left == undefined_section)
+ as_bad_where (file, line,
+ "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",
+ 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");
+ }
+ else
+ {
+ if (seg_left == undefined_section)
+ 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",
+ 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",
+ S_GET_NAME (symp));
+ }
+ }
+
+ /* 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)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ as_bad_where (file, line, "division by zero");
+ else
+ as_bad ("division by zero when setting %s",
+ S_GET_NAME (symp));
+ }
+
+ right = 1;
+ }
+
switch (symp->sy_value.X_op)
{
- case O_multiply: val = left * right; break;
- case O_divide: val = left / right; break;
- case O_modulus: val = left % right; break;
- case O_left_shift: val = left << right; break;
- case O_right_shift: val = left >> right; break;
- case O_bit_inclusive_or: val = left | right; break;
- case O_bit_or_not: val = left |~ right; break;
- case O_bit_exclusive_or: 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;
- default: abort ();
+ case O_multiply: left *= right; break;
+ case O_divide: left /= right; break;
+ case O_modulus: left %= right; break;
+ case O_left_shift: left <<= right; break;
+ case O_right_shift: left >>= right; break;
+ case O_bit_inclusive_or: left |= right; break;
+ case O_bit_or_not: left |= ~right; break;
+ case O_bit_exclusive_or: left ^= right; break;
+ 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_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;
+ case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break;
+ case O_logical_and: left = left && right; break;
+ case O_logical_or: left = left || right; break;
+ default: abort ();
}
- S_SET_VALUE (symp,
- (symp->sy_value.X_add_number
- + symp->sy_frag->fr_address
- + val));
- 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);
+
+ 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);
break;
case O_register:
anything. */
break;
}
+
+ symp->sy_resolving = 0;
+ }
+
+ if (finalize)
+ {
+ S_SET_VALUE (symp, final_val);
+
+#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))
+#endif
+ S_SET_SEGMENT (symp, final_seg);
}
+exit_dont_set_value:
/* 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)
+ if (finalize)
{
- as_bad ("can't resolve value for symbol \"%s\"", S_GET_NAME (symp));
- symp->sy_resolved = 1;
+ 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;
+ }
}
+
+ return final_val;
}
/* Dollar labels look like a number followed by a dollar sign. Eg, "42$".
static long *dollar_labels;
static long *dollar_label_instances;
static char *dollar_label_defines;
-static long dollar_label_count;
+static unsigned long dollar_label_count;
static unsigned long dollar_label_max;
int
return 0;
} /* dollar_label_defined() */
-static int
+static long
dollar_label_instance (label)
long label;
{
if (s[0] != 'L')
return s;
- for (label_number = 0, p = s + 1; isdigit (*p); ++p)
+ for (label_number = 0, p = s + 1; isdigit ((unsigned char) *p); ++p)
label_number = (10 * label_number) + *p - '0';
if (*p == 1)
else
return s;
- for (instance_number = 0, p++; isdigit (*p); ++p)
+ for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
instance_number = (10 * instance_number) + *p - '0';
symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30);
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_resolved && s->sy_value.X_op != O_constant)
+ resolve_symbol_value (s, 1);
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;
}
#ifdef BFD_ASSEMBLER
/* In an expression, transfer the settings of these flags.
The user can override later, of course. */
-#define COPIED_SYMFLAGS (BSF_FUNCTION)
+#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT)
dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
#endif
flagword flags = s->bsym->flags;
/* sanity check */
- if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
+ if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
abort ();
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;
const char *name;
/* sanity check */
- if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
+ if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
abort ();
if (bfd_get_section (s->bsym) == reg_section)
return 1;
+ if (flag_strip_local_absolute
+ && (flags & BSF_GLOBAL) == 0
+ && bfd_get_section (s->bsym) == absolute_section)
+ return 1;
+
name = S_GET_NAME (s);
return (name != NULL
&& ! S_IS_DEBUG (s)
&& (strchr (name, '\001')
|| strchr (name, '\002')
|| (! flag_keep_locals
- && (LOCAL_LABEL (name)
+ && (bfd_is_local_label (stdoutput, s->bsym)
|| (flag_mri
&& name[0] == '?'
&& name[1] == '?')))));
symbolS *s;
segT seg;
{
- s->bsym->section = seg;
+ /* Don't reassign section symbols. The direct reason is to prevent seg
+ faults assigning back to const global symbols such as *ABS*, but it
+ shouldn't happen anyway. */
+
+ if (s->bsym->flags & BSF_SECTION_SYM)
+ {
+ if (s->bsym->section != seg)
+ abort();
+ }
+ else
+ s->bsym->section = seg;
}
void
symbolS *s;
{
if ((s->bsym->flags & BSF_WEAK) != 0)
- as_warn ("%s already declared as weak", S_GET_NAME (s));
+ {
+ /* Let .weak override .global. */
+ return;
+ }
s->bsym->flags |= BSF_GLOBAL;
s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
}
symbolS *s;
{
if ((s->bsym->flags & BSF_WEAK) != 0)
- as_warn ("%s already declared as weak", S_GET_NAME (s));
+ {
+ /* Let .weak override. */
+ return;
+ }
s->bsym->flags |= BSF_LOCAL;
s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
}
S_SET_WEAK (s)
symbolS *s;
{
- if ((s->bsym->flags & BSF_GLOBAL) != 0)
- as_warn ("%s already declared as global", S_GET_NAME (s));
s->bsym->flags |= BSF_WEAK;
s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
}
\f
int indent_level;
+/* Maximum indent level.
+ Available for modification inside a gdb session. */
+int max_indent_level = 8;
+
#if 0
static void
#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;
&& 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, "");
fprintf (stderr, "\n");
}
+static void
+print_binary (file, name, exp)
+ FILE *file;
+ const char * name;
+ expressionS *exp;
+{
+ indent_level++;
+ fprintf (file, "%s\n%*s<", name, 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, ">");
+ indent_level--;
+}
+
void
print_expr_1 (file, exp)
FILE *file;
fprintf (file, "bit_not");
break;
case O_multiply:
- fprintf (file, "multiply");
+ print_binary (file, "multiply", exp);
break;
case O_divide:
- fprintf (file, "divide");
+ print_binary (file, "divide", exp);
break;
case O_modulus:
- fprintf (file, "modulus");
+ print_binary (file, "modulus", exp);
break;
case O_left_shift:
- fprintf (file, "lshift");
+ print_binary (file, "lshift", exp);
break;
case O_right_shift:
- fprintf (file, "rshift");
+ print_binary (file, "rshift", exp);
break;
case O_bit_inclusive_or:
- fprintf (file, "bit_ior");
+ print_binary (file, "bit_ior", exp);
break;
case O_bit_exclusive_or:
- fprintf (file, "bit_xor");
+ print_binary (file, "bit_xor", exp);
break;
case O_bit_and:
- fprintf (file, "bit_and");
+ print_binary (file, "bit_and", exp);
break;
case O_eq:
- fprintf (file, "eq");
+ print_binary (file, "eq", exp);
break;
case O_ne:
- fprintf (file, "ne");
+ print_binary (file, "ne", exp);
break;
case O_lt:
- fprintf (file, "lt");
+ print_binary (file, "lt", exp);
break;
case O_le:
- fprintf (file, "le");
+ print_binary (file, "le", exp);
break;
case O_ge:
- fprintf (file, "ge");
+ print_binary (file, "ge", exp);
break;
case O_gt:
- fprintf (file, "gt");
+ print_binary (file, "gt", exp);
+ break;
+ case O_logical_and:
+ print_binary (file, "logical_and", exp);
+ break;
+ case O_logical_or:
+ print_binary (file, "logical_or", exp);
break;
case O_add:
indent_level++;
fprintf (stderr, "\n");
}
+void
+symbol_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "symbol table", sy_hash);
+}
+
/* end of symbols.c */