/* symbols.c -symbol table-
- Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+ 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_SYMS / * to debug symbol list maintenance */
#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
#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;
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. */
#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);
* 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 */
/* Sun local labels go out of scope whenever a non-local symbol is
defined. */
- if (LOCAL_LABELS_DOLLAR && *sym_name != 'L')
+ if (LOCAL_LABELS_DOLLAR && ! LOCAL_LABEL (sym_name))
dollar_label_clear ();
#ifndef WORKING_DOT_WORD
{
#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) frag_now_fix ());
S_SET_SEGMENT (symbolP, now_seg);
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 */
}
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 symbolP;
}
\f
*/
symbolS *
symbol_find_or_make (name)
- char *name;
+ const char *name;
{
register symbolS *symbolP;
}
#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));
}
case O_symbol:
resolve_symbol_value (symp->sy_value.X_add_symbol);
-#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 (symp->sy_mri_common)
{
- 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));
+ /* 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;
}
+
+ 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));
+
+ /* If we have equated this symbol to an undefined symbol, we
+ keep X_op set to O_symbol. 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) || S_IS_COMMON (symp))
+ symp->sy_value.X_op = O_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,
case O_bit_exclusive_or:
case O_bit_and:
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);
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));
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ as_bad_where
+ (file, line,
+ "illegal operation on symbols in different sections");
+ else
+ as_bad
+ ("%s set to illegal 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));
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ as_bad_where (file, line,
+ "illegal operation on non-absolute symbols");
+ else
+ as_bad ("%s set to 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);
switch (symp->sy_value.X_op)
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->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;
}
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;
symbolS *s;
{
flagword flags = s->bsym->flags;
+ const char *name;
/* sanity check */
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)
- && !flag_keep_locals)));
+ && (strchr (name, '\001')
+ || strchr (name, '\002')
+ || (! flag_keep_locals
+ && (LOCAL_LABEL (name)
+ || (flag_mri
+ && name[0] == '?'
+ && name[1] == '?')))));
}
int
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);
}
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 ();
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, "");
fprintf (stderr, "\n");
}
+void
+symbol_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "symbol table", sy_hash);
+}
+
/* end of symbols.c */