symbols.c revision 89857
133965Sjdp/* symbols.c -symbol table-
278828Sobrien   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
378828Sobrien   1999, 2000, 2001
433965Sjdp   Free Software Foundation, Inc.
533965Sjdp
633965Sjdp   This file is part of GAS, the GNU Assembler.
733965Sjdp
833965Sjdp   GAS is free software; you can redistribute it and/or modify
933965Sjdp   it under the terms of the GNU General Public License as published by
1033965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1133965Sjdp   any later version.
1233965Sjdp
1333965Sjdp   GAS is distributed in the hope that it will be useful,
1433965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1533965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965Sjdp   GNU General Public License for more details.
1733965Sjdp
1833965Sjdp   You should have received a copy of the GNU General Public License
1933965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
2033965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2133965Sjdp   02111-1307, USA.  */
2233965Sjdp
2377298Sobrien/* #define DEBUG_SYMS / * to debug symbol list maintenance.  */
2433965Sjdp
2533965Sjdp#include "as.h"
2633965Sjdp
2789857Sobrien#include "safe-ctype.h"
2833965Sjdp#include "obstack.h"		/* For "symbols.h" */
2933965Sjdp#include "subsegs.h"
3033965Sjdp
3160484Sobrien#include "struc-symbol.h"
3260484Sobrien
3333965Sjdp/* This is non-zero if symbols are case sensitive, which is the
3433965Sjdp   default.  */
3533965Sjdpint symbols_case_sensitive = 1;
3633965Sjdp
3733965Sjdp#ifndef WORKING_DOT_WORD
3833965Sjdpextern int new_broken_words;
3933965Sjdp#endif
4033965Sjdp
4133965Sjdp/* symbol-name => struct symbol pointer */
4233965Sjdpstatic struct hash_control *sy_hash;
4333965Sjdp
4460484Sobrien/* Table of local symbols.  */
4560484Sobrienstatic struct hash_control *local_hash;
4660484Sobrien
4777298Sobrien/* Below are commented in "symbols.h".  */
4833965SjdpsymbolS *symbol_rootP;
4933965SjdpsymbolS *symbol_lastP;
5033965SjdpsymbolS abs_symbol;
5133965Sjdp
5233965Sjdp#ifdef DEBUG_SYMS
5333965Sjdp#define debug_verify_symchain verify_symbol_chain
5433965Sjdp#else
5533965Sjdp#define debug_verify_symchain(root, last) ((void) 0)
5633965Sjdp#endif
5733965Sjdp
5877298Sobrien#define DOLLAR_LABEL_CHAR	'\001'
5977298Sobrien#define LOCAL_LABEL_CHAR	'\002'
6077298Sobrien
6133965Sjdpstruct obstack notes;
6233965Sjdp
6389857Sobrienstatic char *save_symbol_name PARAMS ((const char *));
6433965Sjdpstatic void fb_label_init PARAMS ((void));
6533965Sjdpstatic long dollar_label_instance PARAMS ((long));
6633965Sjdpstatic long fb_label_instance PARAMS ((long));
6733965Sjdp
6860484Sobrienstatic void print_binary PARAMS ((FILE *, const char *, expressionS *));
6960484Sobrien
7077298Sobrien/* Return a pointer to a new symbol.  Die if we can't make a new
7133965Sjdp   symbol.  Fill in the symbol's values.  Add symbol to end of symbol
7233965Sjdp   chain.
7377298Sobrien
7433965Sjdp   This function should be called in the general case of creating a
7533965Sjdp   symbol.  However, if the output file symbol table has already been
7633965Sjdp   set, and you are certain that this symbol won't be wanted in the
7733965Sjdp   output file, you can call symbol_create.  */
7833965Sjdp
7933965SjdpsymbolS *
8033965Sjdpsymbol_new (name, segment, valu, frag)
8133965Sjdp     const char *name;
8233965Sjdp     segT segment;
8333965Sjdp     valueT valu;
8433965Sjdp     fragS *frag;
8533965Sjdp{
8633965Sjdp  symbolS *symbolP = symbol_create (name, segment, valu, frag);
8733965Sjdp
8877298Sobrien  /* Link to end of symbol chain.  */
8933965Sjdp#ifdef BFD_ASSEMBLER
9033965Sjdp  {
9133965Sjdp    extern int symbol_table_frozen;
9233965Sjdp    if (symbol_table_frozen)
9333965Sjdp      abort ();
9433965Sjdp  }
9533965Sjdp#endif
9633965Sjdp  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
9733965Sjdp
9833965Sjdp  return symbolP;
9933965Sjdp}
10033965Sjdp
10160484Sobrien/* Save a symbol name on a permanent obstack, and convert it according
10260484Sobrien   to the object file format.  */
10360484Sobrien
10460484Sobrienstatic char *
10560484Sobriensave_symbol_name (name)
10660484Sobrien     const char *name;
10733965Sjdp{
10833965Sjdp  unsigned int name_length;
10960484Sobrien  char *ret;
11033965Sjdp
11177298Sobrien  name_length = strlen (name) + 1;	/* +1 for \0.  */
11233965Sjdp  obstack_grow (&notes, name, name_length);
11360484Sobrien  ret = obstack_finish (&notes);
11460484Sobrien
11533965Sjdp#ifdef STRIP_UNDERSCORE
11660484Sobrien  if (ret[0] == '_')
11760484Sobrien    ++ret;
11833965Sjdp#endif
11933965Sjdp
12033965Sjdp#ifdef tc_canonicalize_symbol_name
12160484Sobrien  ret = tc_canonicalize_symbol_name (ret);
12233965Sjdp#endif
12333965Sjdp
12433965Sjdp  if (! symbols_case_sensitive)
12533965Sjdp    {
12689857Sobrien      char *s;
12733965Sjdp
12889857Sobrien      for (s = ret; *s != '\0'; s++)
12989857Sobrien	*s = TOUPPER (*s);
13033965Sjdp    }
13133965Sjdp
13260484Sobrien  return ret;
13360484Sobrien}
13460484Sobrien
13560484SobriensymbolS *
13660484Sobriensymbol_create (name, segment, valu, frag)
13777298Sobrien     const char *name;		/* It is copied, the caller can destroy/modify.  */
13877298Sobrien     segT segment;		/* Segment identifier (SEG_<something>).  */
13977298Sobrien     valueT valu;		/* Symbol value.  */
14077298Sobrien     fragS *frag;		/* Associated fragment.  */
14160484Sobrien{
14260484Sobrien  char *preserved_copy_of_name;
14360484Sobrien  symbolS *symbolP;
14460484Sobrien
14560484Sobrien  preserved_copy_of_name = save_symbol_name (name);
14660484Sobrien
14733965Sjdp  symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
14833965Sjdp
14977298Sobrien  /* symbol must be born in some fixed state.  This seems as good as any.  */
15033965Sjdp  memset (symbolP, 0, sizeof (symbolS));
15133965Sjdp
15233965Sjdp#ifdef BFD_ASSEMBLER
15333965Sjdp  symbolP->bsym = bfd_make_empty_symbol (stdoutput);
15433965Sjdp  if (symbolP->bsym == NULL)
15533965Sjdp    as_perror ("%s", "bfd_make_empty_symbol");
15633965Sjdp  symbolP->bsym->udata.p = (PTR) symbolP;
15733965Sjdp#endif
15833965Sjdp  S_SET_NAME (symbolP, preserved_copy_of_name);
15933965Sjdp
16033965Sjdp  S_SET_SEGMENT (symbolP, segment);
16133965Sjdp  S_SET_VALUE (symbolP, valu);
16233965Sjdp  symbol_clear_list_pointers (symbolP);
16333965Sjdp
16433965Sjdp  symbolP->sy_frag = frag;
16533965Sjdp#ifndef BFD_ASSEMBLER
16633965Sjdp  symbolP->sy_number = ~0;
16733965Sjdp  symbolP->sy_name_offset = (unsigned int) ~0;
16833965Sjdp#endif
16933965Sjdp
17033965Sjdp  obj_symbol_new_hook (symbolP);
17133965Sjdp
17233965Sjdp#ifdef tc_symbol_new_hook
17333965Sjdp  tc_symbol_new_hook (symbolP);
17433965Sjdp#endif
17533965Sjdp
17633965Sjdp  return symbolP;
17733965Sjdp}
17833965Sjdp
17960484Sobrien#ifdef BFD_ASSEMBLER
18033965Sjdp
18160484Sobrien/* Local symbol support.  If we can get away with it, we keep only a
18260484Sobrien   small amount of information for local symbols.  */
18360484Sobrien
18460484Sobrienstatic struct local_symbol *local_symbol_make PARAMS ((const char *, segT,
18560484Sobrien						       valueT, fragS *));
18660484Sobrienstatic symbolS *local_symbol_convert PARAMS ((struct local_symbol *));
18760484Sobrien
18860484Sobrien/* Used for statistics.  */
18960484Sobrien
19060484Sobrienstatic unsigned long local_symbol_count;
19160484Sobrienstatic unsigned long local_symbol_conversion_count;
19260484Sobrien
19360484Sobrien/* This macro is called with a symbol argument passed by reference.
19460484Sobrien   It returns whether this is a local symbol.  If necessary, it
19560484Sobrien   changes its argument to the real symbol.  */
19660484Sobrien
19760484Sobrien#define LOCAL_SYMBOL_CHECK(s)						\
19860484Sobrien  (s->bsym == NULL							\
19960484Sobrien   ? (local_symbol_converted_p ((struct local_symbol *) s)		\
20060484Sobrien      ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s),	\
20160484Sobrien	 0)								\
20260484Sobrien      : 1)								\
20360484Sobrien   : 0)
20460484Sobrien
20560484Sobrien/* Create a local symbol and insert it into the local hash table.  */
20660484Sobrien
20760484Sobrienstatic struct local_symbol *
20889857Sobrienlocal_symbol_make (name, section, value, frag)
20960484Sobrien     const char *name;
21060484Sobrien     segT section;
21189857Sobrien     valueT value;
21260484Sobrien     fragS *frag;
21360484Sobrien{
21460484Sobrien  char *name_copy;
21560484Sobrien  struct local_symbol *ret;
21660484Sobrien
21760484Sobrien  ++local_symbol_count;
21860484Sobrien
21960484Sobrien  name_copy = save_symbol_name (name);
22060484Sobrien
22160484Sobrien  ret = (struct local_symbol *) obstack_alloc (&notes, sizeof *ret);
22260484Sobrien  ret->lsy_marker = NULL;
22360484Sobrien  ret->lsy_name = name_copy;
22460484Sobrien  ret->lsy_section = section;
22560484Sobrien  local_symbol_set_frag (ret, frag);
22689857Sobrien  ret->lsy_value = value;
22760484Sobrien
22860484Sobrien  hash_jam (local_hash, name_copy, (PTR) ret);
22960484Sobrien
23060484Sobrien  return ret;
23160484Sobrien}
23260484Sobrien
23360484Sobrien/* Convert a local symbol into a real symbol.  Note that we do not
23460484Sobrien   reclaim the space used by the local symbol.  */
23560484Sobrien
23660484Sobrienstatic symbolS *
23760484Sobrienlocal_symbol_convert (locsym)
23860484Sobrien     struct local_symbol *locsym;
23960484Sobrien{
24060484Sobrien  symbolS *ret;
24160484Sobrien
24260484Sobrien  assert (locsym->lsy_marker == NULL);
24360484Sobrien  if (local_symbol_converted_p (locsym))
24460484Sobrien    return local_symbol_get_real_symbol (locsym);
24560484Sobrien
24660484Sobrien  ++local_symbol_conversion_count;
24760484Sobrien
24889857Sobrien  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value,
24960484Sobrien		    local_symbol_get_frag (locsym));
25060484Sobrien
25160484Sobrien  if (local_symbol_resolved_p (locsym))
25260484Sobrien    ret->sy_resolved = 1;
25360484Sobrien
25460484Sobrien  /* Local symbols are always either defined or used.  */
25560484Sobrien  ret->sy_used = 1;
25660484Sobrien
25789857Sobrien#ifdef TC_LOCAL_SYMFIELD_CONVERT
25889857Sobrien  TC_LOCAL_SYMFIELD_CONVERT (locsym, ret);
25989857Sobrien#endif
26089857Sobrien
26160484Sobrien  symbol_table_insert (ret);
26260484Sobrien
26360484Sobrien  local_symbol_mark_converted (locsym);
26460484Sobrien  local_symbol_set_real_symbol (locsym, ret);
26560484Sobrien
26660484Sobrien  hash_jam (local_hash, locsym->lsy_name, NULL);
26760484Sobrien
26860484Sobrien  return ret;
26960484Sobrien}
27060484Sobrien
27160484Sobrien#else /* ! BFD_ASSEMBLER */
27260484Sobrien
27360484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0
27460484Sobrien#define local_symbol_convert(s) ((symbolS *) s)
27560484Sobrien
27660484Sobrien#endif /* ! BFD_ASSEMBLER */
27760484Sobrien
27877298Sobrien/* We have just seen "<name>:".
27977298Sobrien   Creates a struct symbol unless it already exists.
28060484Sobrien
28177298Sobrien   Gripes if we are redefining a symbol incompatibly (and ignores it).  */
28277298Sobrien
28333965SjdpsymbolS *
28477298Sobriencolon (sym_name)		/* Just seen "x:" - rattle symbols & frags.  */
28577298Sobrien     const char *sym_name;	/* Symbol name, as a cannonical string.  */
28677298Sobrien     /* We copy this string: OK to alter later.  */
28733965Sjdp{
28877298Sobrien  register symbolS *symbolP;	/* Symbol we are working with.  */
28933965Sjdp
29033965Sjdp  /* Sun local labels go out of scope whenever a non-local symbol is
29133965Sjdp     defined.  */
29233965Sjdp  if (LOCAL_LABELS_DOLLAR)
29333965Sjdp    {
29433965Sjdp      int local;
29533965Sjdp
29633965Sjdp#ifdef BFD_ASSEMBLER
29733965Sjdp      local = bfd_is_local_label_name (stdoutput, sym_name);
29833965Sjdp#else
29933965Sjdp      local = LOCAL_LABEL (sym_name);
30033965Sjdp#endif
30133965Sjdp
30233965Sjdp      if (! local)
30333965Sjdp	dollar_label_clear ();
30433965Sjdp    }
30533965Sjdp
30633965Sjdp#ifndef WORKING_DOT_WORD
30733965Sjdp  if (new_broken_words)
30833965Sjdp    {
30933965Sjdp      struct broken_word *a;
31033965Sjdp      int possible_bytes;
31133965Sjdp      fragS *frag_tmp;
31233965Sjdp      char *frag_opcode;
31333965Sjdp
31433965Sjdp      extern const int md_short_jump_size;
31533965Sjdp      extern const int md_long_jump_size;
31633965Sjdp      possible_bytes = (md_short_jump_size
31733965Sjdp			+ new_broken_words * md_long_jump_size);
31833965Sjdp
31933965Sjdp      frag_tmp = frag_now;
32033965Sjdp      frag_opcode = frag_var (rs_broken_word,
32133965Sjdp			      possible_bytes,
32233965Sjdp			      possible_bytes,
32333965Sjdp			      (relax_substateT) 0,
32433965Sjdp			      (symbolS *) broken_words,
32533965Sjdp			      (offsetT) 0,
32633965Sjdp			      NULL);
32733965Sjdp
32877298Sobrien      /* We want to store the pointer to where to insert the jump
32977298Sobrien	 table in the fr_opcode of the rs_broken_word frag.  This
33077298Sobrien	 requires a little hackery.  */
33133965Sjdp      while (frag_tmp
33233965Sjdp	     && (frag_tmp->fr_type != rs_broken_word
33333965Sjdp		 || frag_tmp->fr_opcode))
33433965Sjdp	frag_tmp = frag_tmp->fr_next;
33533965Sjdp      know (frag_tmp);
33633965Sjdp      frag_tmp->fr_opcode = frag_opcode;
33733965Sjdp      new_broken_words = 0;
33833965Sjdp
33933965Sjdp      for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
34033965Sjdp	a->dispfrag = frag_tmp;
34133965Sjdp    }
34233965Sjdp#endif /* WORKING_DOT_WORD */
34333965Sjdp
34433965Sjdp  if ((symbolP = symbol_find (sym_name)) != 0)
34533965Sjdp    {
34633965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION
34733965Sjdp      if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
34833965Sjdp	return symbolP;
34933965Sjdp#endif
35077298Sobrien      /* Now check for undefined symbols.  */
35160484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
35233965Sjdp	{
35360484Sobrien#ifdef BFD_ASSEMBLER
35460484Sobrien	  struct local_symbol *locsym = (struct local_symbol *) symbolP;
35560484Sobrien
35660484Sobrien	  if (locsym->lsy_section != undefined_section
35760484Sobrien	      && (local_symbol_get_frag (locsym) != frag_now
35860484Sobrien		  || locsym->lsy_section != now_seg
35989857Sobrien		  || locsym->lsy_value != frag_now_fix ()))
36060484Sobrien	    {
36189857Sobrien	      as_bad (_("symbol `%s' is already defined"), sym_name);
36260484Sobrien	      return symbolP;
36360484Sobrien	    }
36460484Sobrien
36560484Sobrien	  locsym->lsy_section = now_seg;
36660484Sobrien	  local_symbol_set_frag (locsym, frag_now);
36789857Sobrien	  locsym->lsy_value = frag_now_fix ();
36860484Sobrien#endif
36960484Sobrien	}
37060484Sobrien      else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
37160484Sobrien	{
37233965Sjdp	  if (S_GET_VALUE (symbolP) == 0)
37333965Sjdp	    {
37433965Sjdp	      symbolP->sy_frag = frag_now;
37533965Sjdp#ifdef OBJ_VMS
37677298Sobrien	      S_SET_OTHER (symbolP, const_flag);
37733965Sjdp#endif
37833965Sjdp	      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
37933965Sjdp	      S_SET_SEGMENT (symbolP, now_seg);
38033965Sjdp#ifdef N_UNDF
38133965Sjdp	      know (N_UNDF == 0);
38277298Sobrien#endif /* if we have one, it better be zero.  */
38333965Sjdp
38433965Sjdp	    }
38533965Sjdp	  else
38633965Sjdp	    {
38777298Sobrien	      /* There are still several cases to check:
38833965Sjdp
38977298Sobrien		 A .comm/.lcomm symbol being redefined as initialized
39077298Sobrien		 data is OK
39177298Sobrien
39277298Sobrien		 A .comm/.lcomm symbol being redefined with a larger
39377298Sobrien		 size is also OK
39477298Sobrien
39577298Sobrien		 This only used to be allowed on VMS gas, but Sun cc
39677298Sobrien		 on the sparc also depends on it.  */
39777298Sobrien
39833965Sjdp	      if (((!S_IS_DEBUG (symbolP)
39933965Sjdp		    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
40033965Sjdp		    && S_IS_EXTERNAL (symbolP))
40133965Sjdp		   || S_GET_SEGMENT (symbolP) == bss_section)
40233965Sjdp		  && (now_seg == data_section
40333965Sjdp		      || now_seg == S_GET_SEGMENT (symbolP)))
40433965Sjdp		{
40577298Sobrien		  /* Select which of the 2 cases this is.  */
40633965Sjdp		  if (now_seg != data_section)
40733965Sjdp		    {
40877298Sobrien		      /* New .comm for prev .comm symbol.
40977298Sobrien
41077298Sobrien			 If the new size is larger we just change its
41177298Sobrien			 value.  If the new size is smaller, we ignore
41277298Sobrien			 this symbol.  */
41333965Sjdp		      if (S_GET_VALUE (symbolP)
41433965Sjdp			  < ((unsigned) frag_now_fix ()))
41533965Sjdp			{
41633965Sjdp			  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
41733965Sjdp			}
41833965Sjdp		    }
41933965Sjdp		  else
42033965Sjdp		    {
42133965Sjdp		      /* It is a .comm/.lcomm being converted to initialized
42233965Sjdp			 data.  */
42333965Sjdp		      symbolP->sy_frag = frag_now;
42433965Sjdp#ifdef OBJ_VMS
42577298Sobrien		      S_SET_OTHER (symbolP, const_flag);
42633965Sjdp#endif
42733965Sjdp		      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
42877298Sobrien		      S_SET_SEGMENT (symbolP, now_seg);	/* Keep N_EXT bit.  */
42933965Sjdp		    }
43033965Sjdp		}
43133965Sjdp	      else
43233965Sjdp		{
43360484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \
43460484Sobrien     && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT))
43560484Sobrien		  static const char *od_buf = "";
43633965Sjdp#else
43760484Sobrien		  char od_buf[100];
43860484Sobrien		  od_buf[0] = '\0';
43960484Sobrien#ifdef BFD_ASSEMBLER
44060484Sobrien		  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
44160484Sobrien#endif
44260484Sobrien		    sprintf(od_buf, "%d.%d.",
44360484Sobrien			    S_GET_OTHER (symbolP),
44460484Sobrien			    S_GET_DESC (symbolP));
44560484Sobrien#endif
44689857Sobrien		  as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"),
44733965Sjdp			    sym_name,
44833965Sjdp			    segment_name (S_GET_SEGMENT (symbolP)),
44960484Sobrien			    od_buf,
45033965Sjdp			    (long) S_GET_VALUE (symbolP));
45133965Sjdp		}
45277298Sobrien	    }			/* if the undefined symbol has no value  */
45333965Sjdp	}
45433965Sjdp      else
45533965Sjdp	{
45677298Sobrien	  /* Don't blow up if the definition is the same.  */
45733965Sjdp	  if (!(frag_now == symbolP->sy_frag
45833965Sjdp		&& S_GET_VALUE (symbolP) == frag_now_fix ()
45933965Sjdp		&& S_GET_SEGMENT (symbolP) == now_seg))
46089857Sobrien	    as_bad (_("symbol `%s' is already defined"), sym_name);
46177298Sobrien	}
46233965Sjdp
46333965Sjdp    }
46460484Sobrien#ifdef BFD_ASSEMBLER
46560484Sobrien  else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))
46660484Sobrien    {
46760484Sobrien      symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,
46860484Sobrien					       (valueT) frag_now_fix (),
46960484Sobrien					       frag_now);
47060484Sobrien    }
47160484Sobrien#endif /* BFD_ASSEMBLER */
47233965Sjdp  else
47333965Sjdp    {
47433965Sjdp      symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
47533965Sjdp			    frag_now);
47633965Sjdp#ifdef OBJ_VMS
47733965Sjdp      S_SET_OTHER (symbolP, const_flag);
47833965Sjdp#endif /* OBJ_VMS */
47933965Sjdp
48033965Sjdp      symbol_table_insert (symbolP);
48177298Sobrien    }
48233965Sjdp
48333965Sjdp  if (mri_common_symbol != NULL)
48433965Sjdp    {
48533965Sjdp      /* This symbol is actually being defined within an MRI common
48633965Sjdp         section.  This requires special handling.  */
48760484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
48860484Sobrien	symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
48933965Sjdp      symbolP->sy_value.X_op = O_symbol;
49033965Sjdp      symbolP->sy_value.X_add_symbol = mri_common_symbol;
49133965Sjdp      symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
49233965Sjdp      symbolP->sy_frag = &zero_address_frag;
49333965Sjdp      S_SET_SEGMENT (symbolP, expr_section);
49433965Sjdp      symbolP->sy_mri_common = 1;
49533965Sjdp    }
49633965Sjdp
49733965Sjdp#ifdef tc_frob_label
49833965Sjdp  tc_frob_label (symbolP);
49933965Sjdp#endif
50033965Sjdp#ifdef obj_frob_label
50133965Sjdp  obj_frob_label (symbolP);
50233965Sjdp#endif
50333965Sjdp
50433965Sjdp  return symbolP;
50533965Sjdp}
50633965Sjdp
50777298Sobrien/* Die if we can't insert the symbol.  */
50833965Sjdp
50977298Sobrienvoid
51033965Sjdpsymbol_table_insert (symbolP)
51133965Sjdp     symbolS *symbolP;
51233965Sjdp{
51333965Sjdp  register const char *error_string;
51433965Sjdp
51533965Sjdp  know (symbolP);
51633965Sjdp  know (S_GET_NAME (symbolP));
51733965Sjdp
51860484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
51960484Sobrien    {
52060484Sobrien      error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
52160484Sobrien			       (PTR) symbolP);
52260484Sobrien      if (error_string != NULL)
52389857Sobrien	as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
52460484Sobrien		  S_GET_NAME (symbolP), error_string);
52560484Sobrien      return;
52660484Sobrien    }
52760484Sobrien
52833965Sjdp  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
52933965Sjdp    {
53089857Sobrien      as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
53133965Sjdp		S_GET_NAME (symbolP), error_string);
53277298Sobrien    }				/* on error  */
53377298Sobrien}
53433965Sjdp
53577298Sobrien/* If a symbol name does not exist, create it as undefined, and insert
53677298Sobrien   it into the symbol table.  Return a pointer to it.  */
53777298Sobrien
53833965SjdpsymbolS *
53933965Sjdpsymbol_find_or_make (name)
54033965Sjdp     const char *name;
54133965Sjdp{
54233965Sjdp  register symbolS *symbolP;
54333965Sjdp
54433965Sjdp  symbolP = symbol_find (name);
54533965Sjdp
54633965Sjdp  if (symbolP == NULL)
54733965Sjdp    {
54860484Sobrien#ifdef BFD_ASSEMBLER
54960484Sobrien      if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))
55060484Sobrien	{
55160484Sobrien	  symbolP = md_undefined_symbol ((char *) name);
55260484Sobrien	  if (symbolP != NULL)
55360484Sobrien	    return symbolP;
55460484Sobrien
55560484Sobrien	  symbolP = (symbolS *) local_symbol_make (name, undefined_section,
55660484Sobrien						   (valueT) 0,
55760484Sobrien						   &zero_address_frag);
55860484Sobrien	  return symbolP;
55960484Sobrien	}
56060484Sobrien#endif
56160484Sobrien
56233965Sjdp      symbolP = symbol_make (name);
56333965Sjdp
56433965Sjdp      symbol_table_insert (symbolP);
56533965Sjdp    }				/* if symbol wasn't found */
56633965Sjdp
56733965Sjdp  return (symbolP);
56877298Sobrien}
56933965Sjdp
57033965SjdpsymbolS *
57133965Sjdpsymbol_make (name)
57233965Sjdp     CONST char *name;
57333965Sjdp{
57433965Sjdp  symbolS *symbolP;
57533965Sjdp
57677298Sobrien  /* Let the machine description default it, e.g. for register names.  */
57733965Sjdp  symbolP = md_undefined_symbol ((char *) name);
57833965Sjdp
57933965Sjdp  if (!symbolP)
58033965Sjdp    symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
58133965Sjdp
58233965Sjdp  return (symbolP);
58377298Sobrien}
58433965Sjdp
58577298Sobrien/* Implement symbol table lookup.
58677298Sobrien   In:	A symbol's name as a string: '\0' can't be part of a symbol name.
58777298Sobrien   Out:	NULL if the name was not in the symbol table, else the address
58877298Sobrien   of a struct symbol associated with that name.  */
58933965Sjdp
59033965SjdpsymbolS *
59133965Sjdpsymbol_find (name)
59233965Sjdp     CONST char *name;
59333965Sjdp{
59433965Sjdp#ifdef STRIP_UNDERSCORE
59533965Sjdp  return (symbol_find_base (name, 1));
59633965Sjdp#else /* STRIP_UNDERSCORE */
59733965Sjdp  return (symbol_find_base (name, 0));
59833965Sjdp#endif /* STRIP_UNDERSCORE */
59977298Sobrien}
60033965Sjdp
60133965SjdpsymbolS *
60233965Sjdpsymbol_find_base (name, strip_underscore)
60333965Sjdp     CONST char *name;
60433965Sjdp     int strip_underscore;
60533965Sjdp{
60633965Sjdp  if (strip_underscore && *name == '_')
60733965Sjdp    name++;
60833965Sjdp
60933965Sjdp#ifdef tc_canonicalize_symbol_name
61033965Sjdp  {
61133965Sjdp    char *copy;
61260484Sobrien    size_t len = strlen (name) + 1;
61333965Sjdp
61460484Sobrien    copy = (char *) alloca (len);
61560484Sobrien    memcpy (copy, name, len);
61633965Sjdp    name = tc_canonicalize_symbol_name (copy);
61733965Sjdp  }
61833965Sjdp#endif
61933965Sjdp
62033965Sjdp  if (! symbols_case_sensitive)
62133965Sjdp    {
62260484Sobrien      char *copy;
62360484Sobrien      const char *orig;
62460484Sobrien      unsigned char c;
62533965Sjdp
62660484Sobrien      orig = name;
62760484Sobrien      name = copy = (char *) alloca (strlen (name) + 1);
62860484Sobrien
62960484Sobrien      while ((c = *orig++) != '\0')
63060484Sobrien	{
63189857Sobrien	  *copy++ = TOUPPER (c);
63260484Sobrien	}
63360484Sobrien      *copy = '\0';
63433965Sjdp    }
63533965Sjdp
63660484Sobrien#ifdef BFD_ASSEMBLER
63760484Sobrien  {
63860484Sobrien    struct local_symbol *locsym;
63960484Sobrien
64060484Sobrien    locsym = (struct local_symbol *) hash_find (local_hash, name);
64160484Sobrien    if (locsym != NULL)
64260484Sobrien      return (symbolS *) locsym;
64360484Sobrien  }
64460484Sobrien#endif
64560484Sobrien
64633965Sjdp  return ((symbolS *) hash_find (sy_hash, name));
64733965Sjdp}
64833965Sjdp
64977298Sobrien/* Once upon a time, symbols were kept in a singly linked list.  At
65077298Sobrien   least coff needs to be able to rearrange them from time to time, for
65177298Sobrien   which a doubly linked list is much more convenient.  Loic did these
65277298Sobrien   as macros which seemed dangerous to me so they're now functions.
65377298Sobrien   xoxorich.  */
65433965Sjdp
65577298Sobrien/* Link symbol ADDME after symbol TARGET in the chain.  */
65677298Sobrien
65777298Sobrienvoid
65833965Sjdpsymbol_append (addme, target, rootPP, lastPP)
65933965Sjdp     symbolS *addme;
66033965Sjdp     symbolS *target;
66133965Sjdp     symbolS **rootPP;
66233965Sjdp     symbolS **lastPP;
66333965Sjdp{
66460484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
66560484Sobrien    abort ();
66660484Sobrien  if (target != NULL && LOCAL_SYMBOL_CHECK (target))
66760484Sobrien    abort ();
66860484Sobrien
66933965Sjdp  if (target == NULL)
67033965Sjdp    {
67133965Sjdp      know (*rootPP == NULL);
67233965Sjdp      know (*lastPP == NULL);
67333965Sjdp      addme->sy_next = NULL;
67433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
67533965Sjdp      addme->sy_previous = NULL;
67633965Sjdp#endif
67733965Sjdp      *rootPP = addme;
67833965Sjdp      *lastPP = addme;
67933965Sjdp      return;
68077298Sobrien    }				/* if the list is empty  */
68133965Sjdp
68233965Sjdp  if (target->sy_next != NULL)
68333965Sjdp    {
68433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
68533965Sjdp      target->sy_next->sy_previous = addme;
68633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
68733965Sjdp    }
68833965Sjdp  else
68933965Sjdp    {
69033965Sjdp      know (*lastPP == target);
69133965Sjdp      *lastPP = addme;
69277298Sobrien    }				/* if we have a next  */
69333965Sjdp
69433965Sjdp  addme->sy_next = target->sy_next;
69533965Sjdp  target->sy_next = addme;
69633965Sjdp
69733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
69833965Sjdp  addme->sy_previous = target;
69933965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
70033965Sjdp
70133965Sjdp  debug_verify_symchain (symbol_rootP, symbol_lastP);
70233965Sjdp}
70333965Sjdp
70477298Sobrien/* Set the chain pointers of SYMBOL to null.  */
70577298Sobrien
70677298Sobrienvoid
70733965Sjdpsymbol_clear_list_pointers (symbolP)
70833965Sjdp     symbolS *symbolP;
70933965Sjdp{
71060484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
71160484Sobrien    abort ();
71233965Sjdp  symbolP->sy_next = NULL;
71333965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
71433965Sjdp  symbolP->sy_previous = NULL;
71533965Sjdp#endif
71633965Sjdp}
71733965Sjdp
71833965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
71977298Sobrien/* Remove SYMBOLP from the list.  */
72077298Sobrien
72177298Sobrienvoid
72233965Sjdpsymbol_remove (symbolP, rootPP, lastPP)
72333965Sjdp     symbolS *symbolP;
72433965Sjdp     symbolS **rootPP;
72533965Sjdp     symbolS **lastPP;
72633965Sjdp{
72760484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
72860484Sobrien    abort ();
72960484Sobrien
73033965Sjdp  if (symbolP == *rootPP)
73133965Sjdp    {
73233965Sjdp      *rootPP = symbolP->sy_next;
73377298Sobrien    }				/* if it was the root  */
73433965Sjdp
73533965Sjdp  if (symbolP == *lastPP)
73633965Sjdp    {
73733965Sjdp      *lastPP = symbolP->sy_previous;
73877298Sobrien    }				/* if it was the tail  */
73933965Sjdp
74033965Sjdp  if (symbolP->sy_next != NULL)
74133965Sjdp    {
74233965Sjdp      symbolP->sy_next->sy_previous = symbolP->sy_previous;
74377298Sobrien    }				/* if not last  */
74433965Sjdp
74533965Sjdp  if (symbolP->sy_previous != NULL)
74633965Sjdp    {
74733965Sjdp      symbolP->sy_previous->sy_next = symbolP->sy_next;
74877298Sobrien    }				/* if not first  */
74933965Sjdp
75033965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
75133965Sjdp}
75233965Sjdp
75377298Sobrien/* Link symbol ADDME before symbol TARGET in the chain.  */
75477298Sobrien
75577298Sobrienvoid
75633965Sjdpsymbol_insert (addme, target, rootPP, lastPP)
75733965Sjdp     symbolS *addme;
75833965Sjdp     symbolS *target;
75933965Sjdp     symbolS **rootPP;
76060484Sobrien     symbolS **lastPP ATTRIBUTE_UNUSED;
76133965Sjdp{
76260484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
76360484Sobrien    abort ();
76460484Sobrien  if (LOCAL_SYMBOL_CHECK (target))
76560484Sobrien    abort ();
76660484Sobrien
76733965Sjdp  if (target->sy_previous != NULL)
76833965Sjdp    {
76933965Sjdp      target->sy_previous->sy_next = addme;
77033965Sjdp    }
77133965Sjdp  else
77233965Sjdp    {
77333965Sjdp      know (*rootPP == target);
77433965Sjdp      *rootPP = addme;
77577298Sobrien    }				/* if not first  */
77633965Sjdp
77733965Sjdp  addme->sy_previous = target->sy_previous;
77833965Sjdp  target->sy_previous = addme;
77933965Sjdp  addme->sy_next = target;
78033965Sjdp
78133965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
78233965Sjdp}
78333965Sjdp
78433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
78533965Sjdp
78677298Sobrienvoid
78733965Sjdpverify_symbol_chain (rootP, lastP)
78833965Sjdp     symbolS *rootP;
78933965Sjdp     symbolS *lastP;
79033965Sjdp{
79133965Sjdp  symbolS *symbolP = rootP;
79233965Sjdp
79333965Sjdp  if (symbolP == NULL)
79433965Sjdp    return;
79533965Sjdp
79633965Sjdp  for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
79733965Sjdp    {
79860484Sobrien#ifdef BFD_ASSEMBLER
79960484Sobrien      assert (symbolP->bsym != NULL);
80060484Sobrien#endif
80133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
80233965Sjdp      assert (symbolP->sy_next->sy_previous == symbolP);
80333965Sjdp#else
80433965Sjdp      /* Walk the list anyways, to make sure pointers are still good.  */
80533965Sjdp      ;
80633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
80733965Sjdp    }
80833965Sjdp
80933965Sjdp  assert (lastP == symbolP);
81033965Sjdp}
81133965Sjdp
81233965Sjdpvoid
81333965Sjdpverify_symbol_chain_2 (sym)
81433965Sjdp     symbolS *sym;
81533965Sjdp{
81633965Sjdp  symbolS *p = sym, *n = sym;
81733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
81833965Sjdp  while (symbol_previous (p))
81933965Sjdp    p = symbol_previous (p);
82033965Sjdp#endif
82133965Sjdp  while (symbol_next (n))
82233965Sjdp    n = symbol_next (n);
82333965Sjdp  verify_symbol_chain (p, n);
82433965Sjdp}
82533965Sjdp
82633965Sjdp/* Resolve the value of a symbol.  This is called during the final
82733965Sjdp   pass over the symbol table to resolve any symbols with complex
82833965Sjdp   values.  */
82933965Sjdp
83038889SjdpvalueT
83189857Sobrienresolve_symbol_value (symp)
83233965Sjdp     symbolS *symp;
83333965Sjdp{
83433965Sjdp  int resolved;
83538889Sjdp  valueT final_val;
83638889Sjdp  segT final_seg;
83733965Sjdp
83860484Sobrien#ifdef BFD_ASSEMBLER
83960484Sobrien  if (LOCAL_SYMBOL_CHECK (symp))
84060484Sobrien    {
84160484Sobrien      struct local_symbol *locsym = (struct local_symbol *) symp;
84260484Sobrien
84389857Sobrien      final_val = locsym->lsy_value;
84460484Sobrien      if (local_symbol_resolved_p (locsym))
84589857Sobrien	return final_val;
84660484Sobrien
84789857Sobrien      final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE;
84860484Sobrien
84989857Sobrien      if (finalize_syms)
85060484Sobrien	{
85189857Sobrien	  locsym->lsy_value = final_val;
85260484Sobrien	  local_symbol_mark_resolved (locsym);
85360484Sobrien	}
85460484Sobrien
85560484Sobrien      return final_val;
85660484Sobrien    }
85760484Sobrien#endif
85860484Sobrien
85933965Sjdp  if (symp->sy_resolved)
86038889Sjdp    {
86138889Sjdp      if (symp->sy_value.X_op == O_constant)
86238889Sjdp	return (valueT) symp->sy_value.X_add_number;
86338889Sjdp      else
86438889Sjdp	return 0;
86538889Sjdp    }
86633965Sjdp
86733965Sjdp  resolved = 0;
86838889Sjdp  final_seg = S_GET_SEGMENT (symp);
86933965Sjdp
87033965Sjdp  if (symp->sy_resolving)
87133965Sjdp    {
87289857Sobrien      if (finalize_syms)
87389857Sobrien	as_bad (_("symbol definition loop encountered at `%s'"),
87477298Sobrien		S_GET_NAME (symp));
87538889Sjdp      final_val = 0;
87633965Sjdp      resolved = 1;
87733965Sjdp    }
87833965Sjdp  else
87933965Sjdp    {
88038889Sjdp      symbolS *add_symbol, *op_symbol;
88138889Sjdp      offsetT left, right;
88233965Sjdp      segT seg_left, seg_right;
88338889Sjdp      operatorT op;
88433965Sjdp
88533965Sjdp      symp->sy_resolving = 1;
88633965Sjdp
88738889Sjdp      /* Help out with CSE.  */
88838889Sjdp      add_symbol = symp->sy_value.X_add_symbol;
88938889Sjdp      op_symbol = symp->sy_value.X_op_symbol;
89038889Sjdp      final_val = symp->sy_value.X_add_number;
89138889Sjdp      op = symp->sy_value.X_op;
89238889Sjdp
89338889Sjdp      switch (op)
89433965Sjdp	{
89538889Sjdp	default:
89638889Sjdp	  BAD_CASE (op);
89738889Sjdp	  break;
89833965Sjdp
89933965Sjdp	case O_absent:
90038889Sjdp	  final_val = 0;
90133965Sjdp	  /* Fall through.  */
90238889Sjdp
90333965Sjdp	case O_constant:
90460484Sobrien	  final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
90538889Sjdp	  if (final_seg == expr_section)
90638889Sjdp	    final_seg = absolute_section;
90733965Sjdp	  resolved = 1;
90833965Sjdp	  break;
90933965Sjdp
91033965Sjdp	case O_symbol:
91138889Sjdp	case O_symbol_rva:
91289857Sobrien	  left = resolve_symbol_value (add_symbol);
91389857Sobrien	  seg_left = S_GET_SEGMENT (add_symbol);
91489857Sobrien	  if (finalize_syms)
91589857Sobrien	    symp->sy_value.X_op_symbol = NULL;
91689857Sobrien
91738889Sjdp	do_symbol:
91833965Sjdp	  if (symp->sy_mri_common)
91933965Sjdp	    {
92033965Sjdp	      /* This is a symbol inside an MRI common section.  The
92189857Sobrien		 relocation routines are going to handle it specially.
92289857Sobrien		 Don't change the value.  */
92360484Sobrien	      resolved = symbol_resolved_p (add_symbol);
92433965Sjdp	      break;
92533965Sjdp	    }
92633965Sjdp
92789857Sobrien	  if (finalize_syms && final_val == 0)
92860484Sobrien	    {
92960484Sobrien	      if (LOCAL_SYMBOL_CHECK (add_symbol))
93060484Sobrien		add_symbol = local_symbol_convert ((struct local_symbol *)
93160484Sobrien						   add_symbol);
93260484Sobrien	      copy_symbol_attributes (symp, add_symbol);
93360484Sobrien	    }
93433965Sjdp
93589857Sobrien	  /* If we have equated this symbol to an undefined or common
93689857Sobrien	     symbol, keep X_op set to O_symbol, and don't change
93789857Sobrien	     X_add_number.  This permits the routine which writes out
93889857Sobrien	     relocation to detect this case, and convert the
93989857Sobrien	     relocation to be against the symbol to which this symbol
94089857Sobrien	     is equated.  */
94138889Sjdp	  if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
94233965Sjdp	    {
94389857Sobrien	      if (finalize_syms)
94438889Sjdp		{
94538889Sjdp		  symp->sy_value.X_op = O_symbol;
94660484Sobrien		  symp->sy_value.X_add_symbol = add_symbol;
94738889Sjdp		  symp->sy_value.X_add_number = final_val;
94889857Sobrien		  /* Use X_op_symbol as a flag.  */
94989857Sobrien		  symp->sy_value.X_op_symbol = add_symbol;
95089857Sobrien		  final_seg = seg_left;
95138889Sjdp		}
95238889Sjdp	      final_val = 0;
95360484Sobrien	      resolved = symbol_resolved_p (add_symbol);
95489857Sobrien	      symp->sy_resolving = 0;
95538889Sjdp	      goto exit_dont_set_value;
95633965Sjdp	    }
95789857Sobrien	  else if (finalize_syms && final_seg == expr_section
95889857Sobrien		   && seg_left != expr_section)
95989857Sobrien	    {
96089857Sobrien	      /* If the symbol is an expression symbol, do similarly
96189857Sobrien		 as for undefined and common syms above.  Handles
96289857Sobrien		 "sym +/- expr" where "expr" cannot be evaluated
96389857Sobrien		 immediately, and we want relocations to be against
96489857Sobrien		 "sym", eg. because it is weak.  */
96589857Sobrien	      symp->sy_value.X_op = O_symbol;
96689857Sobrien	      symp->sy_value.X_add_symbol = add_symbol;
96789857Sobrien	      symp->sy_value.X_add_number = final_val;
96889857Sobrien	      symp->sy_value.X_op_symbol = add_symbol;
96989857Sobrien	      final_seg = seg_left;
97089857Sobrien	      final_val += symp->sy_frag->fr_address + left;
97189857Sobrien	      resolved = symbol_resolved_p (add_symbol);
97289857Sobrien	      symp->sy_resolving = 0;
97389857Sobrien	      goto exit_dont_set_value;
97489857Sobrien	    }
97533965Sjdp	  else
97633965Sjdp	    {
97738889Sjdp	      final_val += symp->sy_frag->fr_address + left;
97838889Sjdp	      if (final_seg == expr_section || final_seg == undefined_section)
97989857Sobrien		final_seg = seg_left;
98033965Sjdp	    }
98133965Sjdp
98260484Sobrien	  resolved = symbol_resolved_p (add_symbol);
98333965Sjdp	  break;
98433965Sjdp
98533965Sjdp	case O_uminus:
98633965Sjdp	case O_bit_not:
98733965Sjdp	case O_logical_not:
98889857Sobrien	  left = resolve_symbol_value (add_symbol);
98938889Sjdp
99038889Sjdp	  if (op == O_uminus)
99138889Sjdp	    left = -left;
99238889Sjdp	  else if (op == O_logical_not)
99338889Sjdp	    left = !left;
99433965Sjdp	  else
99538889Sjdp	    left = ~left;
99638889Sjdp
99738889Sjdp	  final_val += left + symp->sy_frag->fr_address;
99838889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
99938889Sjdp	    final_seg = absolute_section;
100038889Sjdp
100160484Sobrien	  resolved = symbol_resolved_p (add_symbol);
100233965Sjdp	  break;
100333965Sjdp
100433965Sjdp	case O_multiply:
100533965Sjdp	case O_divide:
100633965Sjdp	case O_modulus:
100733965Sjdp	case O_left_shift:
100833965Sjdp	case O_right_shift:
100933965Sjdp	case O_bit_inclusive_or:
101033965Sjdp	case O_bit_or_not:
101133965Sjdp	case O_bit_exclusive_or:
101233965Sjdp	case O_bit_and:
101333965Sjdp	case O_add:
101433965Sjdp	case O_subtract:
101533965Sjdp	case O_eq:
101633965Sjdp	case O_ne:
101733965Sjdp	case O_lt:
101833965Sjdp	case O_le:
101933965Sjdp	case O_ge:
102033965Sjdp	case O_gt:
102133965Sjdp	case O_logical_and:
102233965Sjdp	case O_logical_or:
102389857Sobrien	  left = resolve_symbol_value (add_symbol);
102489857Sobrien	  right = resolve_symbol_value (op_symbol);
102538889Sjdp	  seg_left = S_GET_SEGMENT (add_symbol);
102638889Sjdp	  seg_right = S_GET_SEGMENT (op_symbol);
102733965Sjdp
102838889Sjdp	  /* Simplify addition or subtraction of a constant by folding the
102938889Sjdp	     constant into X_add_number.  */
103089857Sobrien	  if (op == O_add)
103138889Sjdp	    {
103238889Sjdp	      if (seg_right == absolute_section)
103338889Sjdp		{
103489857Sobrien		  final_val += right;
103538889Sjdp		  goto do_symbol;
103638889Sjdp		}
103789857Sobrien	      else if (seg_left == absolute_section)
103838889Sjdp		{
103938889Sjdp		  final_val += left;
104038889Sjdp		  add_symbol = op_symbol;
104138889Sjdp		  left = right;
104289857Sobrien		  seg_left = seg_right;
104338889Sjdp		  goto do_symbol;
104438889Sjdp		}
104538889Sjdp	    }
104689857Sobrien	  else if (op == O_subtract)
104789857Sobrien	    {
104889857Sobrien	      if (seg_right == absolute_section)
104989857Sobrien		{
105089857Sobrien		  final_val -= right;
105189857Sobrien		  goto do_symbol;
105289857Sobrien		}
105389857Sobrien	    }
105438889Sjdp
105589857Sobrien	  /* Equality and non-equality tests are permitted on anything.
105689857Sobrien	     Subtraction, and other comparison operators are permitted if
105789857Sobrien	     both operands are in the same section.  Otherwise, both
105889857Sobrien	     operands must be absolute.  We already handled the case of
105989857Sobrien	     addition or subtraction of a constant above.  This will
106089857Sobrien	     probably need to be changed for an object file format which
106189857Sobrien	     supports arbitrary expressions, such as IEEE-695.
106289857Sobrien
106389857Sobrien	     Don't emit messages unless we're finalizing the symbol value,
106438889Sjdp	     otherwise we may get the same message multiple times.  */
106589857Sobrien	  if (op != O_eq && op != O_ne
106689857Sobrien	      && (seg_left != absolute_section
106789857Sobrien		  || seg_right != absolute_section)
106889857Sobrien	      && ((op != O_subtract
106989857Sobrien		   && op != O_lt && op != O_le && op != O_ge && op != O_gt)
107060484Sobrien		  || seg_left != seg_right
107189857Sobrien		  || (seg_left == undefined_section
107289857Sobrien		      && add_symbol != op_symbol))
107389857Sobrien	      && finalize_syms)
107433965Sjdp	    {
107533965Sjdp	      char *file;
107633965Sjdp	      unsigned int line;
107733965Sjdp
107833965Sjdp	      if (expr_symbol_where (symp, &file, &line))
107933965Sjdp		{
108033965Sjdp		  if (seg_left == undefined_section)
108133965Sjdp		    as_bad_where (file, line,
108289857Sobrien				  _("undefined symbol `%s' in operation"),
108333965Sjdp				  S_GET_NAME (symp->sy_value.X_add_symbol));
108433965Sjdp		  if (seg_right == undefined_section)
108533965Sjdp		    as_bad_where (file, line,
108689857Sobrien				  _("undefined symbol `%s' in operation"),
108733965Sjdp				  S_GET_NAME (symp->sy_value.X_op_symbol));
108833965Sjdp		  if (seg_left != undefined_section
108933965Sjdp		      && seg_right != undefined_section)
109077298Sobrien		    as_bad_where (file, line,
109177298Sobrien				  _("invalid section for operation"));
109233965Sjdp		}
109333965Sjdp	      else
109433965Sjdp		{
109533965Sjdp		  if (seg_left == undefined_section)
109689857Sobrien		    as_bad (_("undefined symbol `%s' in operation setting `%s'"),
109733965Sjdp			    S_GET_NAME (symp->sy_value.X_add_symbol),
109833965Sjdp			    S_GET_NAME (symp));
109933965Sjdp		  if (seg_right == undefined_section)
110089857Sobrien		    as_bad (_("undefined symbol `%s' in operation setting `%s'"),
110133965Sjdp			    S_GET_NAME (symp->sy_value.X_op_symbol),
110233965Sjdp			    S_GET_NAME (symp));
110333965Sjdp		  if (seg_left != undefined_section
110433965Sjdp		      && seg_right != undefined_section)
110589857Sobrien		    as_bad (_("invalid section for operation setting `%s'"),
110633965Sjdp			    S_GET_NAME (symp));
110733965Sjdp		}
110833965Sjdp	    }
110933965Sjdp
111038889Sjdp	  /* Check for division by zero.  */
111138889Sjdp	  if ((op == O_divide || op == O_modulus) && right == 0)
111238889Sjdp	    {
111338889Sjdp	      /* If seg_right is not absolute_section, then we've
111489857Sobrien		 already issued a warning about using a bad symbol.  */
111589857Sobrien	      if (seg_right == absolute_section && finalize_syms)
111638889Sjdp		{
111738889Sjdp		  char *file;
111838889Sjdp		  unsigned int line;
111938889Sjdp
112038889Sjdp		  if (expr_symbol_where (symp, &file, &line))
112160484Sobrien		    as_bad_where (file, line, _("division by zero"));
112238889Sjdp		  else
112389857Sobrien		    as_bad (_("division by zero when setting `%s'"),
112438889Sjdp			    S_GET_NAME (symp));
112538889Sjdp		}
112638889Sjdp
112738889Sjdp	      right = 1;
112838889Sjdp	    }
112938889Sjdp
113033965Sjdp	  switch (symp->sy_value.X_op)
113133965Sjdp	    {
113238889Sjdp	    case O_multiply:		left *= right; break;
113338889Sjdp	    case O_divide:		left /= right; break;
113438889Sjdp	    case O_modulus:		left %= right; break;
113538889Sjdp	    case O_left_shift:		left <<= right; break;
113638889Sjdp	    case O_right_shift:		left >>= right; break;
113738889Sjdp	    case O_bit_inclusive_or:	left |= right; break;
113838889Sjdp	    case O_bit_or_not:		left |= ~right; break;
113938889Sjdp	    case O_bit_exclusive_or:	left ^= right; break;
114038889Sjdp	    case O_bit_and:		left &= right; break;
114138889Sjdp	    case O_add:			left += right; break;
114238889Sjdp	    case O_subtract:		left -= right; break;
114389857Sobrien	    case O_eq:
114489857Sobrien	    case O_ne:
114589857Sobrien	      left = (left == right && seg_left == seg_right
114689857Sobrien		      && (seg_left != undefined_section
114789857Sobrien			  || add_symbol == op_symbol)
114889857Sobrien		      ? ~ (offsetT) 0 : 0);
114989857Sobrien	      if (symp->sy_value.X_op == O_ne)
115089857Sobrien		left = ~left;
115189857Sobrien	      break;
115238889Sjdp	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;
115338889Sjdp	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;
115438889Sjdp	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;
115538889Sjdp	    case O_gt:	left = left >  right ? ~ (offsetT) 0 : 0; break;
115638889Sjdp	    case O_logical_and:	left = left && right; break;
115738889Sjdp	    case O_logical_or:	left = left || right; break;
115838889Sjdp	    default:		abort ();
115933965Sjdp	    }
116038889Sjdp
116138889Sjdp	  final_val += symp->sy_frag->fr_address + left;
116238889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
116338889Sjdp	    final_seg = absolute_section;
116460484Sobrien	  resolved = (symbol_resolved_p (add_symbol)
116560484Sobrien		      && symbol_resolved_p (op_symbol));
116677298Sobrien	  break;
116733965Sjdp
116833965Sjdp	case O_register:
116933965Sjdp	case O_big:
117033965Sjdp	case O_illegal:
117133965Sjdp	  /* Give an error (below) if not in expr_section.  We don't
117233965Sjdp	     want to worry about expr_section symbols, because they
117333965Sjdp	     are fictional (they are created as part of expression
117433965Sjdp	     resolution), and any problems may not actually mean
117533965Sjdp	     anything.  */
117633965Sjdp	  break;
117733965Sjdp	}
117838889Sjdp
117938889Sjdp      symp->sy_resolving = 0;
118033965Sjdp    }
118133965Sjdp
118289857Sobrien  if (finalize_syms)
118389857Sobrien    S_SET_VALUE (symp, final_val);
118438889Sjdp
118589857Sobrienexit_dont_set_value:
118689857Sobrien  /* Always set the segment, even if not finalizing the value.
118789857Sobrien     The segment is used to determine whether a symbol is defined.  */
118838889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
118989857Sobrien  /* The old a.out backend does not handle S_SET_SEGMENT correctly
119089857Sobrien     for a stab symbol, so we use this bad hack.  */
119189857Sobrien  if (final_seg != S_GET_SEGMENT (symp))
119238889Sjdp#endif
119389857Sobrien    S_SET_SEGMENT (symp, final_seg);
119438889Sjdp
119533965Sjdp  /* Don't worry if we can't resolve an expr_section symbol.  */
119689857Sobrien  if (finalize_syms)
119733965Sjdp    {
119838889Sjdp      if (resolved)
119938889Sjdp	symp->sy_resolved = 1;
120038889Sjdp      else if (S_GET_SEGMENT (symp) != expr_section)
120138889Sjdp	{
120289857Sobrien	  as_bad (_("can't resolve value for symbol `%s'"),
120377298Sobrien		  S_GET_NAME (symp));
120438889Sjdp	  symp->sy_resolved = 1;
120538889Sjdp	}
120633965Sjdp    }
120738889Sjdp
120838889Sjdp  return final_val;
120933965Sjdp}
121033965Sjdp
121160484Sobrien#ifdef BFD_ASSEMBLER
121260484Sobrien
121360484Sobrienstatic void resolve_local_symbol PARAMS ((const char *, PTR));
121460484Sobrien
121560484Sobrien/* A static function passed to hash_traverse.  */
121660484Sobrien
121760484Sobrienstatic void
121860484Sobrienresolve_local_symbol (key, value)
121960484Sobrien     const char *key ATTRIBUTE_UNUSED;
122060484Sobrien     PTR value;
122160484Sobrien{
122260484Sobrien  if (value != NULL)
122389857Sobrien    resolve_symbol_value (value);
122460484Sobrien}
122560484Sobrien
122660484Sobrien#endif
122760484Sobrien
122860484Sobrien/* Resolve all local symbols.  */
122960484Sobrien
123060484Sobrienvoid
123160484Sobrienresolve_local_symbol_values ()
123260484Sobrien{
123360484Sobrien#ifdef BFD_ASSEMBLER
123460484Sobrien  hash_traverse (local_hash, resolve_local_symbol);
123560484Sobrien#endif
123660484Sobrien}
123760484Sobrien
123833965Sjdp/* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
123933965Sjdp   They are *really* local.  That is, they go out of scope whenever we see a
124033965Sjdp   label that isn't local.  Also, like fb labels, there can be multiple
124133965Sjdp   instances of a dollar label.  Therefor, we name encode each instance with
124233965Sjdp   the instance number, keep a list of defined symbols separate from the real
124333965Sjdp   symbol table, and we treat these buggers as a sparse array.  */
124433965Sjdp
124533965Sjdpstatic long *dollar_labels;
124633965Sjdpstatic long *dollar_label_instances;
124733965Sjdpstatic char *dollar_label_defines;
124838889Sjdpstatic unsigned long dollar_label_count;
124933965Sjdpstatic unsigned long dollar_label_max;
125033965Sjdp
125177298Sobrienint
125233965Sjdpdollar_label_defined (label)
125333965Sjdp     long label;
125433965Sjdp{
125533965Sjdp  long *i;
125633965Sjdp
125733965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
125833965Sjdp
125933965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
126033965Sjdp    if (*i == label)
126133965Sjdp      return dollar_label_defines[i - dollar_labels];
126233965Sjdp
126377298Sobrien  /* If we get here, label isn't defined.  */
126433965Sjdp  return 0;
126577298Sobrien}
126633965Sjdp
126733965Sjdpstatic long
126833965Sjdpdollar_label_instance (label)
126933965Sjdp     long label;
127033965Sjdp{
127133965Sjdp  long *i;
127233965Sjdp
127333965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
127433965Sjdp
127533965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
127633965Sjdp    if (*i == label)
127733965Sjdp      return (dollar_label_instances[i - dollar_labels]);
127833965Sjdp
127977298Sobrien  /* If we get here, we haven't seen the label before.
128077298Sobrien     Therefore its instance count is zero.  */
128133965Sjdp  return 0;
128233965Sjdp}
128333965Sjdp
128477298Sobrienvoid
128533965Sjdpdollar_label_clear ()
128633965Sjdp{
128733965Sjdp  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
128833965Sjdp}
128933965Sjdp
129033965Sjdp#define DOLLAR_LABEL_BUMP_BY 10
129133965Sjdp
129277298Sobrienvoid
129333965Sjdpdefine_dollar_label (label)
129433965Sjdp     long label;
129533965Sjdp{
129633965Sjdp  long *i;
129733965Sjdp
129833965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
129933965Sjdp    if (*i == label)
130033965Sjdp      {
130133965Sjdp	++dollar_label_instances[i - dollar_labels];
130233965Sjdp	dollar_label_defines[i - dollar_labels] = 1;
130333965Sjdp	return;
130433965Sjdp      }
130533965Sjdp
130677298Sobrien  /* If we get to here, we don't have label listed yet.  */
130733965Sjdp
130833965Sjdp  if (dollar_labels == NULL)
130933965Sjdp    {
131033965Sjdp      dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
131133965Sjdp      dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
131233965Sjdp      dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
131333965Sjdp      dollar_label_max = DOLLAR_LABEL_BUMP_BY;
131433965Sjdp      dollar_label_count = 0;
131533965Sjdp    }
131633965Sjdp  else if (dollar_label_count == dollar_label_max)
131733965Sjdp    {
131833965Sjdp      dollar_label_max += DOLLAR_LABEL_BUMP_BY;
131933965Sjdp      dollar_labels = (long *) xrealloc ((char *) dollar_labels,
132033965Sjdp					 dollar_label_max * sizeof (long));
132133965Sjdp      dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
132233965Sjdp					  dollar_label_max * sizeof (long));
132333965Sjdp      dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
132477298Sobrien    }				/* if we needed to grow  */
132533965Sjdp
132633965Sjdp  dollar_labels[dollar_label_count] = label;
132733965Sjdp  dollar_label_instances[dollar_label_count] = 1;
132833965Sjdp  dollar_label_defines[dollar_label_count] = 1;
132933965Sjdp  ++dollar_label_count;
133033965Sjdp}
133133965Sjdp
133277298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
133333965Sjdp
133477298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Am"
133577298Sobrien   where n is the label number and m is the instance number. "L" makes
133677298Sobrien   it a label discarded unless debugging and "^A"('\1') ensures no
133777298Sobrien   ordinary symbol SHOULD get the same name as a local label
133877298Sobrien   symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
133977298Sobrien
134077298Sobrien   fb labels get the same treatment, except that ^B is used in place
134177298Sobrien   of ^A.  */
134277298Sobrien
134377298Sobrienchar *				/* Return local label name.  */
134433965Sjdpdollar_label_name (n, augend)
134577298Sobrien     register long n;		/* we just saw "n$:" : n a number.  */
134677298Sobrien     register int augend;	/* 0 for current instance, 1 for new instance.  */
134733965Sjdp{
134833965Sjdp  long i;
134977298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
135033965Sjdp  static char symbol_name_build[24];
135133965Sjdp  register char *p;
135233965Sjdp  register char *q;
135377298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
135433965Sjdp
135533965Sjdp  know (n >= 0);
135633965Sjdp  know (augend == 0 || augend == 1);
135733965Sjdp  p = symbol_name_build;
135860484Sobrien#ifdef LOCAL_LABEL_PREFIX
135960484Sobrien  *p++ = LOCAL_LABEL_PREFIX;
136060484Sobrien#endif
136133965Sjdp  *p++ = 'L';
136233965Sjdp
136377298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
136477298Sobrien  /* Label number.  */
136533965Sjdp  q = symbol_name_temporary;
136633965Sjdp  for (*q++ = 0, i = n; i; ++q)
136733965Sjdp    {
136833965Sjdp      *q = i % 10 + '0';
136933965Sjdp      i /= 10;
137033965Sjdp    }
137133965Sjdp  while ((*p = *--q) != '\0')
137233965Sjdp    ++p;
137333965Sjdp
137477298Sobrien  *p++ = DOLLAR_LABEL_CHAR;		/* ^A  */
137533965Sjdp
137677298Sobrien  /* Instance number.  */
137733965Sjdp  q = symbol_name_temporary;
137833965Sjdp  for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
137933965Sjdp    {
138033965Sjdp      *q = i % 10 + '0';
138133965Sjdp      i /= 10;
138233965Sjdp    }
138333965Sjdp  while ((*p++ = *--q) != '\0');;
138433965Sjdp
138577298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
138633965Sjdp  return symbol_name_build;
138733965Sjdp}
138833965Sjdp
138977298Sobrien/* Sombody else's idea of local labels. They are made by "n:" where n
139077298Sobrien   is any decimal digit. Refer to them with
139177298Sobrien    "nb" for previous (backward) n:
139277298Sobrien   or "nf" for next (forward) n:.
139333965Sjdp
139477298Sobrien   We do a little better and let n be any number, not just a single digit, but
139577298Sobrien   since the other guy's assembler only does ten, we treat the first ten
139677298Sobrien   specially.
139777298Sobrien
139877298Sobrien   Like someone else's assembler, we have one set of local label counters for
139977298Sobrien   entire assembly, not one set per (sub)segment like in most assemblers. This
140077298Sobrien   implies that one can refer to a label in another segment, and indeed some
140177298Sobrien   crufty compilers have done just that.
140277298Sobrien
140377298Sobrien   Since there could be a LOT of these things, treat them as a sparse
140477298Sobrien   array.  */
140577298Sobrien
140633965Sjdp#define FB_LABEL_SPECIAL (10)
140733965Sjdp
140833965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL];
140933965Sjdpstatic long *fb_labels;
141033965Sjdpstatic long *fb_label_instances;
141133965Sjdpstatic long fb_label_count;
141233965Sjdpstatic long fb_label_max;
141333965Sjdp
141477298Sobrien/* This must be more than FB_LABEL_SPECIAL.  */
141533965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
141633965Sjdp
141777298Sobrienstatic void
141833965Sjdpfb_label_init ()
141933965Sjdp{
142033965Sjdp  memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
142177298Sobrien}
142233965Sjdp
142377298Sobrien/* Add one to the instance number of this fb label.  */
142477298Sobrien
142577298Sobrienvoid
142633965Sjdpfb_label_instance_inc (label)
142733965Sjdp     long label;
142833965Sjdp{
142933965Sjdp  long *i;
143033965Sjdp
143133965Sjdp  if (label < FB_LABEL_SPECIAL)
143233965Sjdp    {
143333965Sjdp      ++fb_low_counter[label];
143433965Sjdp      return;
143533965Sjdp    }
143633965Sjdp
143733965Sjdp  if (fb_labels != NULL)
143833965Sjdp    {
143933965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
144033965Sjdp	   i < fb_labels + fb_label_count; ++i)
144133965Sjdp	{
144233965Sjdp	  if (*i == label)
144333965Sjdp	    {
144433965Sjdp	      ++fb_label_instances[i - fb_labels];
144533965Sjdp	      return;
144677298Sobrien	    }			/* if we find it  */
144777298Sobrien	}			/* for each existing label  */
144833965Sjdp    }
144933965Sjdp
145077298Sobrien  /* If we get to here, we don't have label listed yet.  */
145133965Sjdp
145233965Sjdp  if (fb_labels == NULL)
145333965Sjdp    {
145433965Sjdp      fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
145533965Sjdp      fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
145633965Sjdp      fb_label_max = FB_LABEL_BUMP_BY;
145733965Sjdp      fb_label_count = FB_LABEL_SPECIAL;
145833965Sjdp
145933965Sjdp    }
146033965Sjdp  else if (fb_label_count == fb_label_max)
146133965Sjdp    {
146233965Sjdp      fb_label_max += FB_LABEL_BUMP_BY;
146333965Sjdp      fb_labels = (long *) xrealloc ((char *) fb_labels,
146433965Sjdp				     fb_label_max * sizeof (long));
146533965Sjdp      fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
146633965Sjdp					      fb_label_max * sizeof (long));
146777298Sobrien    }				/* if we needed to grow  */
146833965Sjdp
146933965Sjdp  fb_labels[fb_label_count] = label;
147033965Sjdp  fb_label_instances[fb_label_count] = 1;
147133965Sjdp  ++fb_label_count;
147233965Sjdp}
147333965Sjdp
147477298Sobrienstatic long
147533965Sjdpfb_label_instance (label)
147633965Sjdp     long label;
147733965Sjdp{
147833965Sjdp  long *i;
147933965Sjdp
148033965Sjdp  if (label < FB_LABEL_SPECIAL)
148133965Sjdp    {
148233965Sjdp      return (fb_low_counter[label]);
148333965Sjdp    }
148433965Sjdp
148533965Sjdp  if (fb_labels != NULL)
148633965Sjdp    {
148733965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
148833965Sjdp	   i < fb_labels + fb_label_count; ++i)
148933965Sjdp	{
149033965Sjdp	  if (*i == label)
149133965Sjdp	    {
149233965Sjdp	      return (fb_label_instances[i - fb_labels]);
149377298Sobrien	    }			/* if we find it  */
149477298Sobrien	}			/* for each existing label  */
149533965Sjdp    }
149633965Sjdp
149733965Sjdp  /* We didn't find the label, so this must be a reference to the
149833965Sjdp     first instance.  */
149933965Sjdp  return 0;
150033965Sjdp}
150133965Sjdp
150277298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
150333965Sjdp
150477298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Bm"
150577298Sobrien   where n is the label number and m is the instance number. "L" makes
150677298Sobrien   it a label discarded unless debugging and "^B"('\2') ensures no
150777298Sobrien   ordinary symbol SHOULD get the same name as a local label
150877298Sobrien   symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
150977298Sobrien
151077298Sobrien   dollar labels get the same treatment, except that ^A is used in
151177298Sobrien   place of ^B.  */
151277298Sobrien
151377298Sobrienchar *				/* Return local label name.  */
151433965Sjdpfb_label_name (n, augend)
151577298Sobrien     long n;			/* We just saw "n:", "nf" or "nb" : n a number.  */
151677298Sobrien     long augend;		/* 0 for nb, 1 for n:, nf.  */
151733965Sjdp{
151833965Sjdp  long i;
151977298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
152033965Sjdp  static char symbol_name_build[24];
152133965Sjdp  register char *p;
152233965Sjdp  register char *q;
152377298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
152433965Sjdp
152533965Sjdp  know (n >= 0);
152633965Sjdp  know (augend == 0 || augend == 1);
152733965Sjdp  p = symbol_name_build;
152877298Sobrien#ifdef LOCAL_LABEL_PREFIX
152977298Sobrien  *p++ = LOCAL_LABEL_PREFIX;
153077298Sobrien#endif
153133965Sjdp  *p++ = 'L';
153233965Sjdp
153377298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
153477298Sobrien  /* Label number.  */
153533965Sjdp  q = symbol_name_temporary;
153633965Sjdp  for (*q++ = 0, i = n; i; ++q)
153733965Sjdp    {
153833965Sjdp      *q = i % 10 + '0';
153933965Sjdp      i /= 10;
154033965Sjdp    }
154133965Sjdp  while ((*p = *--q) != '\0')
154233965Sjdp    ++p;
154333965Sjdp
154477298Sobrien  *p++ = LOCAL_LABEL_CHAR;		/* ^B  */
154533965Sjdp
154677298Sobrien  /* Instance number.  */
154733965Sjdp  q = symbol_name_temporary;
154833965Sjdp  for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
154933965Sjdp    {
155033965Sjdp      *q = i % 10 + '0';
155133965Sjdp      i /= 10;
155233965Sjdp    }
155333965Sjdp  while ((*p++ = *--q) != '\0');;
155433965Sjdp
155577298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
155633965Sjdp  return (symbol_name_build);
155777298Sobrien}
155833965Sjdp
155977298Sobrien/* Decode name that may have been generated by foo_label_name() above.
156077298Sobrien   If the name wasn't generated by foo_label_name(), then return it
156177298Sobrien   unaltered.  This is used for error messages.  */
156233965Sjdp
156333965Sjdpchar *
156433965Sjdpdecode_local_label_name (s)
156533965Sjdp     char *s;
156633965Sjdp{
156733965Sjdp  char *p;
156833965Sjdp  char *symbol_decode;
156933965Sjdp  int label_number;
157033965Sjdp  int instance_number;
157133965Sjdp  char *type;
157278828Sobrien  const char *message_format;
157377298Sobrien  int index = 0;
157433965Sjdp
157577298Sobrien#ifdef LOCAL_LABEL_PREFIX
157677298Sobrien  if (s[index] == LOCAL_LABEL_PREFIX)
157777298Sobrien    ++index;
157877298Sobrien#endif
157977298Sobrien
158077298Sobrien  if (s[index] != 'L')
158133965Sjdp    return s;
158233965Sjdp
158389857Sobrien  for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p)
158433965Sjdp    label_number = (10 * label_number) + *p - '0';
158533965Sjdp
158677298Sobrien  if (*p == DOLLAR_LABEL_CHAR)
158733965Sjdp    type = "dollar";
158877298Sobrien  else if (*p == LOCAL_LABEL_CHAR)
158933965Sjdp    type = "fb";
159033965Sjdp  else
159133965Sjdp    return s;
159233965Sjdp
159389857Sobrien  for (instance_number = 0, p++; ISDIGIT (*p); ++p)
159433965Sjdp    instance_number = (10 * instance_number) + *p - '0';
159533965Sjdp
159678828Sobrien  message_format = _("\"%d\" (instance number %d of a %s label)");
159733965Sjdp  symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
159833965Sjdp  sprintf (symbol_decode, message_format, label_number, instance_number, type);
159933965Sjdp
160033965Sjdp  return symbol_decode;
160133965Sjdp}
160233965Sjdp
160333965Sjdp/* Get the value of a symbol.  */
160433965Sjdp
160533965SjdpvalueT
160633965SjdpS_GET_VALUE (s)
160733965Sjdp     symbolS *s;
160833965Sjdp{
160960484Sobrien#ifdef BFD_ASSEMBLER
161060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
161189857Sobrien    return resolve_symbol_value (s);
161260484Sobrien#endif
161360484Sobrien
161489857Sobrien  if (!s->sy_resolved)
161589857Sobrien    {
161689857Sobrien      valueT val = resolve_symbol_value (s);
161789857Sobrien      if (!finalize_syms)
161889857Sobrien	return val;
161989857Sobrien    }
162033965Sjdp  if (s->sy_value.X_op != O_constant)
162133965Sjdp    {
162233965Sjdp      static symbolS *recur;
162333965Sjdp
162433965Sjdp      /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
162533965Sjdp         may call S_GET_VALUE.  We use a static symbol to avoid the
162633965Sjdp         immediate recursion.  */
162733965Sjdp      if (recur == s)
162833965Sjdp	return (valueT) s->sy_value.X_add_number;
162933965Sjdp      recur = s;
163033965Sjdp      if (! s->sy_resolved
163133965Sjdp	  || s->sy_value.X_op != O_symbol
163233965Sjdp	  || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
163389857Sobrien	as_bad (_("attempt to get value of unresolved symbol `%s'"),
163433965Sjdp		S_GET_NAME (s));
163533965Sjdp      recur = NULL;
163633965Sjdp    }
163733965Sjdp  return (valueT) s->sy_value.X_add_number;
163833965Sjdp}
163933965Sjdp
164033965Sjdp/* Set the value of a symbol.  */
164133965Sjdp
164233965Sjdpvoid
164333965SjdpS_SET_VALUE (s, val)
164433965Sjdp     symbolS *s;
164533965Sjdp     valueT val;
164633965Sjdp{
164760484Sobrien#ifdef BFD_ASSEMBLER
164860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
164960484Sobrien    {
165089857Sobrien      ((struct local_symbol *) s)->lsy_value = val;
165160484Sobrien      return;
165260484Sobrien    }
165360484Sobrien#endif
165460484Sobrien
165533965Sjdp  s->sy_value.X_op = O_constant;
165633965Sjdp  s->sy_value.X_add_number = (offsetT) val;
165733965Sjdp  s->sy_value.X_unsigned = 0;
165833965Sjdp}
165933965Sjdp
166033965Sjdpvoid
166133965Sjdpcopy_symbol_attributes (dest, src)
166233965Sjdp     symbolS *dest, *src;
166333965Sjdp{
166460484Sobrien  if (LOCAL_SYMBOL_CHECK (dest))
166560484Sobrien    dest = local_symbol_convert ((struct local_symbol *) dest);
166660484Sobrien  if (LOCAL_SYMBOL_CHECK (src))
166760484Sobrien    src = local_symbol_convert ((struct local_symbol *) src);
166860484Sobrien
166933965Sjdp#ifdef BFD_ASSEMBLER
167033965Sjdp  /* In an expression, transfer the settings of these flags.
167133965Sjdp     The user can override later, of course.  */
167238889Sjdp#define COPIED_SYMFLAGS	(BSF_FUNCTION | BSF_OBJECT)
167333965Sjdp  dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
167433965Sjdp#endif
167533965Sjdp
167633965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
167733965Sjdp  OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
167833965Sjdp#endif
167933965Sjdp}
168033965Sjdp
168133965Sjdp#ifdef BFD_ASSEMBLER
168233965Sjdp
168333965Sjdpint
168460484SobrienS_IS_FUNCTION (s)
168560484Sobrien     symbolS *s;
168660484Sobrien{
168760484Sobrien  flagword flags;
168860484Sobrien
168960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
169060484Sobrien    return 0;
169160484Sobrien
169260484Sobrien  flags = s->bsym->flags;
169360484Sobrien
169460484Sobrien  return (flags & BSF_FUNCTION) != 0;
169560484Sobrien}
169660484Sobrien
169760484Sobrienint
169833965SjdpS_IS_EXTERNAL (s)
169933965Sjdp     symbolS *s;
170033965Sjdp{
170160484Sobrien  flagword flags;
170233965Sjdp
170360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
170460484Sobrien    return 0;
170560484Sobrien
170660484Sobrien  flags = s->bsym->flags;
170760484Sobrien
170877298Sobrien  /* Sanity check.  */
170938889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
171033965Sjdp    abort ();
171133965Sjdp
171233965Sjdp  return (flags & BSF_GLOBAL) != 0;
171333965Sjdp}
171433965Sjdp
171533965Sjdpint
171633965SjdpS_IS_WEAK (s)
171733965Sjdp     symbolS *s;
171833965Sjdp{
171960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
172060484Sobrien    return 0;
172133965Sjdp  return (s->bsym->flags & BSF_WEAK) != 0;
172233965Sjdp}
172333965Sjdp
172433965Sjdpint
172533965SjdpS_IS_COMMON (s)
172633965Sjdp     symbolS *s;
172733965Sjdp{
172860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
172960484Sobrien    return 0;
173033965Sjdp  return bfd_is_com_section (s->bsym->section);
173133965Sjdp}
173233965Sjdp
173333965Sjdpint
173433965SjdpS_IS_DEFINED (s)
173533965Sjdp     symbolS *s;
173633965Sjdp{
173760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
173860484Sobrien    return ((struct local_symbol *) s)->lsy_section != undefined_section;
173933965Sjdp  return s->bsym->section != undefined_section;
174033965Sjdp}
174133965Sjdp
174233965Sjdpint
174333965SjdpS_IS_DEBUG (s)
174433965Sjdp     symbolS *s;
174533965Sjdp{
174660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
174760484Sobrien    return 0;
174833965Sjdp  if (s->bsym->flags & BSF_DEBUGGING)
174933965Sjdp    return 1;
175033965Sjdp  return 0;
175133965Sjdp}
175233965Sjdp
175333965Sjdpint
175433965SjdpS_IS_LOCAL (s)
175533965Sjdp     symbolS *s;
175633965Sjdp{
175760484Sobrien  flagword flags;
175833965Sjdp  const char *name;
175933965Sjdp
176060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
176160484Sobrien    return 1;
176260484Sobrien
176360484Sobrien  flags = s->bsym->flags;
176460484Sobrien
176577298Sobrien  /* Sanity check.  */
176638889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
176733965Sjdp    abort ();
176833965Sjdp
176933965Sjdp  if (bfd_get_section (s->bsym) == reg_section)
177033965Sjdp    return 1;
177133965Sjdp
177238889Sjdp  if (flag_strip_local_absolute
177338889Sjdp      && (flags & BSF_GLOBAL) == 0
177438889Sjdp      && bfd_get_section (s->bsym) == absolute_section)
177538889Sjdp    return 1;
177638889Sjdp
177733965Sjdp  name = S_GET_NAME (s);
177833965Sjdp  return (name != NULL
177933965Sjdp	  && ! S_IS_DEBUG (s)
178077298Sobrien	  && (strchr (name, DOLLAR_LABEL_CHAR)
178177298Sobrien	      || strchr (name, LOCAL_LABEL_CHAR)
178233965Sjdp	      || (! flag_keep_locals
178333965Sjdp		  && (bfd_is_local_label (stdoutput, s->bsym)
178433965Sjdp		      || (flag_mri
178533965Sjdp			  && name[0] == '?'
178633965Sjdp			  && name[1] == '?')))));
178733965Sjdp}
178833965Sjdp
178933965Sjdpint
179033965SjdpS_IS_EXTERN (s)
179133965Sjdp     symbolS *s;
179233965Sjdp{
179333965Sjdp  return S_IS_EXTERNAL (s);
179433965Sjdp}
179533965Sjdp
179633965Sjdpint
179733965SjdpS_IS_STABD (s)
179833965Sjdp     symbolS *s;
179933965Sjdp{
180033965Sjdp  return S_GET_NAME (s) == 0;
180133965Sjdp}
180233965Sjdp
180333965SjdpCONST char *
180433965SjdpS_GET_NAME (s)
180533965Sjdp     symbolS *s;
180633965Sjdp{
180760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
180860484Sobrien    return ((struct local_symbol *) s)->lsy_name;
180933965Sjdp  return s->bsym->name;
181033965Sjdp}
181133965Sjdp
181233965SjdpsegT
181333965SjdpS_GET_SEGMENT (s)
181433965Sjdp     symbolS *s;
181533965Sjdp{
181660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
181760484Sobrien    return ((struct local_symbol *) s)->lsy_section;
181833965Sjdp  return s->bsym->section;
181933965Sjdp}
182033965Sjdp
182133965Sjdpvoid
182233965SjdpS_SET_SEGMENT (s, seg)
182333965Sjdp     symbolS *s;
182433965Sjdp     segT seg;
182533965Sjdp{
182638889Sjdp  /* Don't reassign section symbols.  The direct reason is to prevent seg
182738889Sjdp     faults assigning back to const global symbols such as *ABS*, but it
182838889Sjdp     shouldn't happen anyway.  */
182938889Sjdp
183060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
183160484Sobrien    {
183260484Sobrien      if (seg == reg_section)
183360484Sobrien	s = local_symbol_convert ((struct local_symbol *) s);
183460484Sobrien      else
183560484Sobrien	{
183660484Sobrien	  ((struct local_symbol *) s)->lsy_section = seg;
183760484Sobrien	  return;
183860484Sobrien	}
183960484Sobrien    }
184060484Sobrien
184138889Sjdp  if (s->bsym->flags & BSF_SECTION_SYM)
184238889Sjdp    {
184338889Sjdp      if (s->bsym->section != seg)
184477298Sobrien	abort ();
184538889Sjdp    }
184638889Sjdp  else
184738889Sjdp    s->bsym->section = seg;
184833965Sjdp}
184933965Sjdp
185033965Sjdpvoid
185133965SjdpS_SET_EXTERNAL (s)
185233965Sjdp     symbolS *s;
185333965Sjdp{
185460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
185560484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
185633965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
185733965Sjdp    {
185833965Sjdp      /* Let .weak override .global.  */
185933965Sjdp      return;
186033965Sjdp    }
186178828Sobrien  if (s->bsym->flags & BSF_SECTION_SYM)
186278828Sobrien    {
186378828Sobrien      char * file;
186478828Sobrien      unsigned int line;
186578828Sobrien
186678828Sobrien      /* Do not reassign section symbols.  */
186778828Sobrien      as_where (& file, & line);
186878828Sobrien      as_warn_where (file, line,
186989857Sobrien		     _("section symbols are already global"));
187078828Sobrien      return;
187178828Sobrien    }
187233965Sjdp  s->bsym->flags |= BSF_GLOBAL;
187377298Sobrien  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
187433965Sjdp}
187533965Sjdp
187633965Sjdpvoid
187733965SjdpS_CLEAR_EXTERNAL (s)
187833965Sjdp     symbolS *s;
187933965Sjdp{
188060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
188160484Sobrien    return;
188233965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
188333965Sjdp    {
188433965Sjdp      /* Let .weak override.  */
188533965Sjdp      return;
188633965Sjdp    }
188733965Sjdp  s->bsym->flags |= BSF_LOCAL;
188877298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
188933965Sjdp}
189033965Sjdp
189133965Sjdpvoid
189233965SjdpS_SET_WEAK (s)
189333965Sjdp     symbolS *s;
189433965Sjdp{
189560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
189660484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
189733965Sjdp  s->bsym->flags |= BSF_WEAK;
189877298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
189933965Sjdp}
190033965Sjdp
190133965Sjdpvoid
190233965SjdpS_SET_NAME (s, name)
190333965Sjdp     symbolS *s;
190433965Sjdp     char *name;
190533965Sjdp{
190660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
190760484Sobrien    {
190860484Sobrien      ((struct local_symbol *) s)->lsy_name = name;
190960484Sobrien      return;
191060484Sobrien    }
191133965Sjdp  s->bsym->name = name;
191233965Sjdp}
191333965Sjdp#endif /* BFD_ASSEMBLER */
191433965Sjdp
191560484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS
191660484Sobrien
191760484Sobrien/* Return the previous symbol in a chain.  */
191860484Sobrien
191960484SobriensymbolS *
192060484Sobriensymbol_previous (s)
192160484Sobrien     symbolS *s;
192260484Sobrien{
192360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
192460484Sobrien    abort ();
192560484Sobrien  return s->sy_previous;
192660484Sobrien}
192760484Sobrien
192860484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */
192960484Sobrien
193060484Sobrien/* Return the next symbol in a chain.  */
193160484Sobrien
193260484SobriensymbolS *
193360484Sobriensymbol_next (s)
193460484Sobrien     symbolS *s;
193560484Sobrien{
193660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
193760484Sobrien    abort ();
193860484Sobrien  return s->sy_next;
193960484Sobrien}
194060484Sobrien
194160484Sobrien/* Return a pointer to the value of a symbol as an expression.  */
194260484Sobrien
194360484SobrienexpressionS *
194460484Sobriensymbol_get_value_expression (s)
194560484Sobrien     symbolS *s;
194660484Sobrien{
194760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
194860484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
194960484Sobrien  return &s->sy_value;
195060484Sobrien}
195160484Sobrien
195260484Sobrien/* Set the value of a symbol to an expression.  */
195360484Sobrien
195433965Sjdpvoid
195560484Sobriensymbol_set_value_expression (s, exp)
195660484Sobrien     symbolS *s;
195760484Sobrien     const expressionS *exp;
195860484Sobrien{
195960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
196060484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
196160484Sobrien  s->sy_value = *exp;
196260484Sobrien}
196360484Sobrien
196460484Sobrien/* Set the frag of a symbol.  */
196560484Sobrien
196660484Sobrienvoid
196760484Sobriensymbol_set_frag (s, f)
196860484Sobrien     symbolS *s;
196960484Sobrien     fragS *f;
197060484Sobrien{
197160484Sobrien#ifdef BFD_ASSEMBLER
197260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
197360484Sobrien    {
197460484Sobrien      local_symbol_set_frag ((struct local_symbol *) s, f);
197560484Sobrien      return;
197660484Sobrien    }
197760484Sobrien#endif
197860484Sobrien  s->sy_frag = f;
197960484Sobrien}
198060484Sobrien
198160484Sobrien/* Return the frag of a symbol.  */
198260484Sobrien
198360484SobrienfragS *
198460484Sobriensymbol_get_frag (s)
198560484Sobrien     symbolS *s;
198660484Sobrien{
198760484Sobrien#ifdef BFD_ASSEMBLER
198860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
198960484Sobrien    return local_symbol_get_frag ((struct local_symbol *) s);
199060484Sobrien#endif
199160484Sobrien  return s->sy_frag;
199260484Sobrien}
199360484Sobrien
199460484Sobrien/* Mark a symbol as having been used.  */
199560484Sobrien
199660484Sobrienvoid
199760484Sobriensymbol_mark_used (s)
199860484Sobrien     symbolS *s;
199960484Sobrien{
200060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
200160484Sobrien    return;
200260484Sobrien  s->sy_used = 1;
200360484Sobrien}
200460484Sobrien
200560484Sobrien/* Clear the mark of whether a symbol has been used.  */
200660484Sobrien
200760484Sobrienvoid
200860484Sobriensymbol_clear_used (s)
200960484Sobrien     symbolS *s;
201060484Sobrien{
201160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
201260484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
201360484Sobrien  s->sy_used = 0;
201460484Sobrien}
201560484Sobrien
201660484Sobrien/* Return whether a symbol has been used.  */
201760484Sobrien
201860484Sobrienint
201960484Sobriensymbol_used_p (s)
202060484Sobrien     symbolS *s;
202160484Sobrien{
202260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
202360484Sobrien    return 1;
202460484Sobrien  return s->sy_used;
202560484Sobrien}
202660484Sobrien
202760484Sobrien/* Mark a symbol as having been used in a reloc.  */
202860484Sobrien
202960484Sobrienvoid
203060484Sobriensymbol_mark_used_in_reloc (s)
203160484Sobrien     symbolS *s;
203260484Sobrien{
203360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
203460484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
203560484Sobrien  s->sy_used_in_reloc = 1;
203660484Sobrien}
203760484Sobrien
203860484Sobrien/* Clear the mark of whether a symbol has been used in a reloc.  */
203960484Sobrien
204060484Sobrienvoid
204160484Sobriensymbol_clear_used_in_reloc (s)
204260484Sobrien     symbolS *s;
204360484Sobrien{
204460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
204560484Sobrien    return;
204660484Sobrien  s->sy_used_in_reloc = 0;
204760484Sobrien}
204860484Sobrien
204960484Sobrien/* Return whether a symbol has been used in a reloc.  */
205060484Sobrien
205160484Sobrienint
205260484Sobriensymbol_used_in_reloc_p (s)
205360484Sobrien     symbolS *s;
205460484Sobrien{
205560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
205660484Sobrien    return 0;
205760484Sobrien  return s->sy_used_in_reloc;
205860484Sobrien}
205960484Sobrien
206060484Sobrien/* Mark a symbol as an MRI common symbol.  */
206160484Sobrien
206260484Sobrienvoid
206360484Sobriensymbol_mark_mri_common (s)
206460484Sobrien     symbolS *s;
206560484Sobrien{
206660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
206760484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
206860484Sobrien  s->sy_mri_common = 1;
206960484Sobrien}
207060484Sobrien
207160484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol.  */
207260484Sobrien
207360484Sobrienvoid
207460484Sobriensymbol_clear_mri_common (s)
207560484Sobrien     symbolS *s;
207660484Sobrien{
207760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
207860484Sobrien    return;
207960484Sobrien  s->sy_mri_common = 0;
208060484Sobrien}
208160484Sobrien
208260484Sobrien/* Return whether a symbol is an MRI common symbol.  */
208360484Sobrien
208460484Sobrienint
208560484Sobriensymbol_mri_common_p (s)
208660484Sobrien     symbolS *s;
208760484Sobrien{
208860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
208960484Sobrien    return 0;
209060484Sobrien  return s->sy_mri_common;
209160484Sobrien}
209260484Sobrien
209360484Sobrien/* Mark a symbol as having been written.  */
209460484Sobrien
209560484Sobrienvoid
209660484Sobriensymbol_mark_written (s)
209760484Sobrien     symbolS *s;
209860484Sobrien{
209960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
210060484Sobrien    return;
210160484Sobrien  s->written = 1;
210260484Sobrien}
210360484Sobrien
210460484Sobrien/* Clear the mark of whether a symbol has been written.  */
210560484Sobrien
210660484Sobrienvoid
210760484Sobriensymbol_clear_written (s)
210860484Sobrien     symbolS *s;
210960484Sobrien{
211060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
211160484Sobrien    return;
211260484Sobrien  s->written = 0;
211360484Sobrien}
211460484Sobrien
211560484Sobrien/* Return whether a symbol has been written.  */
211660484Sobrien
211760484Sobrienint
211860484Sobriensymbol_written_p (s)
211960484Sobrien     symbolS *s;
212060484Sobrien{
212160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
212260484Sobrien    return 0;
212360484Sobrien  return s->written;
212460484Sobrien}
212560484Sobrien
212660484Sobrien/* Mark a symbol has having been resolved.  */
212760484Sobrien
212860484Sobrienvoid
212960484Sobriensymbol_mark_resolved (s)
213060484Sobrien     symbolS *s;
213160484Sobrien{
213260484Sobrien#ifdef BFD_ASSEMBLER
213360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
213460484Sobrien    {
213560484Sobrien      local_symbol_mark_resolved ((struct local_symbol *) s);
213660484Sobrien      return;
213760484Sobrien    }
213860484Sobrien#endif
213960484Sobrien  s->sy_resolved = 1;
214060484Sobrien}
214160484Sobrien
214260484Sobrien/* Return whether a symbol has been resolved.  */
214360484Sobrien
214460484Sobrienint
214560484Sobriensymbol_resolved_p (s)
214660484Sobrien     symbolS *s;
214760484Sobrien{
214860484Sobrien#ifdef BFD_ASSEMBLER
214960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
215060484Sobrien    return local_symbol_resolved_p ((struct local_symbol *) s);
215160484Sobrien#endif
215260484Sobrien  return s->sy_resolved;
215360484Sobrien}
215460484Sobrien
215560484Sobrien/* Return whether a symbol is a section symbol.  */
215660484Sobrien
215760484Sobrienint
215860484Sobriensymbol_section_p (s)
215960484Sobrien     symbolS *s ATTRIBUTE_UNUSED;
216060484Sobrien{
216160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
216260484Sobrien    return 0;
216360484Sobrien#ifdef BFD_ASSEMBLER
216460484Sobrien  return (s->bsym->flags & BSF_SECTION_SYM) != 0;
216560484Sobrien#else
216677298Sobrien  /* FIXME.  */
216760484Sobrien  return 0;
216860484Sobrien#endif
216960484Sobrien}
217060484Sobrien
217160484Sobrien/* Return whether a symbol is equated to another symbol.  */
217260484Sobrien
217360484Sobrienint
217460484Sobriensymbol_equated_p (s)
217560484Sobrien     symbolS *s;
217660484Sobrien{
217760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
217860484Sobrien    return 0;
217960484Sobrien  return s->sy_value.X_op == O_symbol;
218060484Sobrien}
218160484Sobrien
218289857Sobrien/* Return whether a symbol is equated to another symbol, and should be
218389857Sobrien   treated specially when writing out relocs.  */
218489857Sobrien
218589857Sobrienint
218689857Sobriensymbol_equated_reloc_p (s)
218789857Sobrien     symbolS *s;
218889857Sobrien{
218989857Sobrien  if (LOCAL_SYMBOL_CHECK (s))
219089857Sobrien    return 0;
219189857Sobrien  /* X_op_symbol, normally not used for O_symbol, is set by
219289857Sobrien     resolve_symbol_value to flag expression syms that have been
219389857Sobrien     equated.  */
219489857Sobrien  return (s->sy_value.X_op == O_symbol
219589857Sobrien	  && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
219689857Sobrien	      || ! S_IS_DEFINED (s)
219789857Sobrien	      || S_IS_COMMON (s)));
219889857Sobrien}
219989857Sobrien
220060484Sobrien/* Return whether a symbol has a constant value.  */
220160484Sobrien
220260484Sobrienint
220360484Sobriensymbol_constant_p (s)
220460484Sobrien     symbolS *s;
220560484Sobrien{
220660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
220760484Sobrien    return 1;
220860484Sobrien  return s->sy_value.X_op == O_constant;
220960484Sobrien}
221060484Sobrien
221160484Sobrien#ifdef BFD_ASSEMBLER
221260484Sobrien
221360484Sobrien/* Return the BFD symbol for a symbol.  */
221460484Sobrien
221560484Sobrienasymbol *
221660484Sobriensymbol_get_bfdsym (s)
221760484Sobrien     symbolS *s;
221860484Sobrien{
221960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
222060484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
222160484Sobrien  return s->bsym;
222260484Sobrien}
222360484Sobrien
222460484Sobrien/* Set the BFD symbol for a symbol.  */
222560484Sobrien
222660484Sobrienvoid
222760484Sobriensymbol_set_bfdsym (s, bsym)
222860484Sobrien     symbolS *s;
222960484Sobrien     asymbol *bsym;
223060484Sobrien{
223160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
223260484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
223360484Sobrien  s->bsym = bsym;
223460484Sobrien}
223560484Sobrien
223660484Sobrien#endif /* BFD_ASSEMBLER */
223760484Sobrien
223860484Sobrien#ifdef OBJ_SYMFIELD_TYPE
223960484Sobrien
224060484Sobrien/* Get a pointer to the object format information for a symbol.  */
224160484Sobrien
224260484SobrienOBJ_SYMFIELD_TYPE *
224360484Sobriensymbol_get_obj (s)
224460484Sobrien     symbolS *s;
224560484Sobrien{
224660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
224760484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
224860484Sobrien  return &s->sy_obj;
224960484Sobrien}
225060484Sobrien
225160484Sobrien/* Set the object format information for a symbol.  */
225260484Sobrien
225360484Sobrienvoid
225460484Sobriensymbol_set_obj (s, o)
225560484Sobrien     symbolS *s;
225660484Sobrien     OBJ_SYMFIELD_TYPE *o;
225760484Sobrien{
225860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
225960484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
226060484Sobrien  s->sy_obj = *o;
226160484Sobrien}
226260484Sobrien
226360484Sobrien#endif /* OBJ_SYMFIELD_TYPE */
226460484Sobrien
226560484Sobrien#ifdef TC_SYMFIELD_TYPE
226660484Sobrien
226760484Sobrien/* Get a pointer to the processor information for a symbol.  */
226860484Sobrien
226960484SobrienTC_SYMFIELD_TYPE *
227060484Sobriensymbol_get_tc (s)
227160484Sobrien     symbolS *s;
227260484Sobrien{
227360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
227460484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
227560484Sobrien  return &s->sy_tc;
227660484Sobrien}
227760484Sobrien
227860484Sobrien/* Set the processor information for a symbol.  */
227960484Sobrien
228060484Sobrienvoid
228160484Sobriensymbol_set_tc (s, o)
228260484Sobrien     symbolS *s;
228360484Sobrien     TC_SYMFIELD_TYPE *o;
228460484Sobrien{
228560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
228660484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
228760484Sobrien  s->sy_tc = *o;
228860484Sobrien}
228960484Sobrien
229060484Sobrien#endif /* TC_SYMFIELD_TYPE */
229160484Sobrien
229260484Sobrienvoid
229333965Sjdpsymbol_begin ()
229433965Sjdp{
229533965Sjdp  symbol_lastP = NULL;
229677298Sobrien  symbol_rootP = NULL;		/* In case we have 0 symbols (!!)  */
229733965Sjdp  sy_hash = hash_new ();
229860484Sobrien#ifdef BFD_ASSEMBLER
229960484Sobrien  local_hash = hash_new ();
230060484Sobrien#endif
230133965Sjdp
230233965Sjdp  memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
230333965Sjdp#ifdef BFD_ASSEMBLER
230433965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
230533965Sjdp  abs_symbol.bsym = bfd_abs_section.symbol;
230633965Sjdp#endif
230733965Sjdp#else
230877298Sobrien  /* Can't initialise a union. Sigh.  */
230933965Sjdp  S_SET_SEGMENT (&abs_symbol, absolute_section);
231033965Sjdp#endif
231133965Sjdp  abs_symbol.sy_value.X_op = O_constant;
231233965Sjdp  abs_symbol.sy_frag = &zero_address_frag;
231333965Sjdp
231433965Sjdp  if (LOCAL_LABELS_FB)
231533965Sjdp    fb_label_init ();
231633965Sjdp}
231733965Sjdp
231833965Sjdpint indent_level;
231933965Sjdp
232060484Sobrien/* Maximum indent level.
232160484Sobrien   Available for modification inside a gdb session.  */
232260484Sobrienint max_indent_level = 8;
232360484Sobrien
232433965Sjdp#if 0
232533965Sjdp
232633965Sjdpstatic void
232733965Sjdpindent ()
232833965Sjdp{
232933965Sjdp  printf ("%*s", indent_level * 4, "");
233033965Sjdp}
233133965Sjdp
233233965Sjdp#endif
233333965Sjdp
233433965Sjdpvoid
233533965Sjdpprint_symbol_value_1 (file, sym)
233633965Sjdp     FILE *file;
233733965Sjdp     symbolS *sym;
233833965Sjdp{
233933965Sjdp  const char *name = S_GET_NAME (sym);
234033965Sjdp  if (!name || !name[0])
234133965Sjdp    name = "(unnamed)";
234233965Sjdp  fprintf (file, "sym %lx %s", (unsigned long) sym, name);
234360484Sobrien
234460484Sobrien  if (LOCAL_SYMBOL_CHECK (sym))
234560484Sobrien    {
234660484Sobrien#ifdef BFD_ASSEMBLER
234760484Sobrien      struct local_symbol *locsym = (struct local_symbol *) sym;
234860484Sobrien      if (local_symbol_get_frag (locsym) != &zero_address_frag
234960484Sobrien	  && local_symbol_get_frag (locsym) != NULL)
235060484Sobrien	fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym));
235160484Sobrien      if (local_symbol_resolved_p (locsym))
235260484Sobrien	fprintf (file, " resolved");
235360484Sobrien      fprintf (file, " local");
235460484Sobrien#endif
235560484Sobrien    }
235660484Sobrien  else
235760484Sobrien    {
235860484Sobrien      if (sym->sy_frag != &zero_address_frag)
235960484Sobrien	fprintf (file, " frag %lx", (long) sym->sy_frag);
236060484Sobrien      if (sym->written)
236160484Sobrien	fprintf (file, " written");
236260484Sobrien      if (sym->sy_resolved)
236360484Sobrien	fprintf (file, " resolved");
236460484Sobrien      else if (sym->sy_resolving)
236560484Sobrien	fprintf (file, " resolving");
236660484Sobrien      if (sym->sy_used_in_reloc)
236760484Sobrien	fprintf (file, " used-in-reloc");
236860484Sobrien      if (sym->sy_used)
236960484Sobrien	fprintf (file, " used");
237060484Sobrien      if (S_IS_LOCAL (sym))
237160484Sobrien	fprintf (file, " local");
237260484Sobrien      if (S_IS_EXTERN (sym))
237360484Sobrien	fprintf (file, " extern");
237460484Sobrien      if (S_IS_DEBUG (sym))
237560484Sobrien	fprintf (file, " debug");
237660484Sobrien      if (S_IS_DEFINED (sym))
237760484Sobrien	fprintf (file, " defined");
237860484Sobrien    }
237933965Sjdp  fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
238060484Sobrien  if (symbol_resolved_p (sym))
238133965Sjdp    {
238233965Sjdp      segT s = S_GET_SEGMENT (sym);
238333965Sjdp
238433965Sjdp      if (s != undefined_section
238533965Sjdp          && s != expr_section)
238633965Sjdp	fprintf (file, " %lx", (long) S_GET_VALUE (sym));
238733965Sjdp    }
238860484Sobrien  else if (indent_level < max_indent_level
238960484Sobrien	   && S_GET_SEGMENT (sym) != undefined_section)
239033965Sjdp    {
239133965Sjdp      indent_level++;
239233965Sjdp      fprintf (file, "\n%*s<", indent_level * 4, "");
239360484Sobrien#ifdef BFD_ASSEMBLER
239460484Sobrien      if (LOCAL_SYMBOL_CHECK (sym))
239560484Sobrien	fprintf (file, "constant %lx",
239689857Sobrien		 (long) ((struct local_symbol *) sym)->lsy_value);
239760484Sobrien      else
239860484Sobrien#endif
239960484Sobrien	print_expr_1 (file, &sym->sy_value);
240033965Sjdp      fprintf (file, ">");
240133965Sjdp      indent_level--;
240233965Sjdp    }
240333965Sjdp  fflush (file);
240433965Sjdp}
240533965Sjdp
240633965Sjdpvoid
240733965Sjdpprint_symbol_value (sym)
240833965Sjdp     symbolS *sym;
240933965Sjdp{
241033965Sjdp  indent_level = 0;
241133965Sjdp  print_symbol_value_1 (stderr, sym);
241233965Sjdp  fprintf (stderr, "\n");
241333965Sjdp}
241433965Sjdp
241560484Sobrienstatic void
241660484Sobrienprint_binary (file, name, exp)
241760484Sobrien     FILE *file;
241877298Sobrien     const char *name;
241960484Sobrien     expressionS *exp;
242060484Sobrien{
242160484Sobrien  indent_level++;
242260484Sobrien  fprintf (file, "%s\n%*s<", name, indent_level * 4, "");
242360484Sobrien  print_symbol_value_1 (file, exp->X_add_symbol);
242460484Sobrien  fprintf (file, ">\n%*s<", indent_level * 4, "");
242560484Sobrien  print_symbol_value_1 (file, exp->X_op_symbol);
242660484Sobrien  fprintf (file, ">");
242760484Sobrien  indent_level--;
242860484Sobrien}
242960484Sobrien
243033965Sjdpvoid
243133965Sjdpprint_expr_1 (file, exp)
243233965Sjdp     FILE *file;
243333965Sjdp     expressionS *exp;
243433965Sjdp{
243533965Sjdp  fprintf (file, "expr %lx ", (long) exp);
243633965Sjdp  switch (exp->X_op)
243733965Sjdp    {
243833965Sjdp    case O_illegal:
243933965Sjdp      fprintf (file, "illegal");
244033965Sjdp      break;
244133965Sjdp    case O_absent:
244233965Sjdp      fprintf (file, "absent");
244333965Sjdp      break;
244433965Sjdp    case O_constant:
244533965Sjdp      fprintf (file, "constant %lx", (long) exp->X_add_number);
244633965Sjdp      break;
244733965Sjdp    case O_symbol:
244833965Sjdp      indent_level++;
244933965Sjdp      fprintf (file, "symbol\n%*s<", indent_level * 4, "");
245033965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
245133965Sjdp      fprintf (file, ">");
245233965Sjdp    maybe_print_addnum:
245333965Sjdp      if (exp->X_add_number)
245433965Sjdp	fprintf (file, "\n%*s%lx", indent_level * 4, "",
245533965Sjdp		 (long) exp->X_add_number);
245633965Sjdp      indent_level--;
245733965Sjdp      break;
245833965Sjdp    case O_register:
245933965Sjdp      fprintf (file, "register #%d", (int) exp->X_add_number);
246033965Sjdp      break;
246133965Sjdp    case O_big:
246233965Sjdp      fprintf (file, "big");
246333965Sjdp      break;
246433965Sjdp    case O_uminus:
246533965Sjdp      fprintf (file, "uminus -<");
246633965Sjdp      indent_level++;
246733965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
246833965Sjdp      fprintf (file, ">");
246933965Sjdp      goto maybe_print_addnum;
247033965Sjdp    case O_bit_not:
247133965Sjdp      fprintf (file, "bit_not");
247233965Sjdp      break;
247333965Sjdp    case O_multiply:
247460484Sobrien      print_binary (file, "multiply", exp);
247533965Sjdp      break;
247633965Sjdp    case O_divide:
247760484Sobrien      print_binary (file, "divide", exp);
247833965Sjdp      break;
247933965Sjdp    case O_modulus:
248060484Sobrien      print_binary (file, "modulus", exp);
248133965Sjdp      break;
248233965Sjdp    case O_left_shift:
248360484Sobrien      print_binary (file, "lshift", exp);
248433965Sjdp      break;
248533965Sjdp    case O_right_shift:
248660484Sobrien      print_binary (file, "rshift", exp);
248733965Sjdp      break;
248833965Sjdp    case O_bit_inclusive_or:
248960484Sobrien      print_binary (file, "bit_ior", exp);
249033965Sjdp      break;
249133965Sjdp    case O_bit_exclusive_or:
249260484Sobrien      print_binary (file, "bit_xor", exp);
249333965Sjdp      break;
249433965Sjdp    case O_bit_and:
249560484Sobrien      print_binary (file, "bit_and", exp);
249633965Sjdp      break;
249733965Sjdp    case O_eq:
249860484Sobrien      print_binary (file, "eq", exp);
249933965Sjdp      break;
250033965Sjdp    case O_ne:
250160484Sobrien      print_binary (file, "ne", exp);
250233965Sjdp      break;
250333965Sjdp    case O_lt:
250460484Sobrien      print_binary (file, "lt", exp);
250533965Sjdp      break;
250633965Sjdp    case O_le:
250760484Sobrien      print_binary (file, "le", exp);
250833965Sjdp      break;
250933965Sjdp    case O_ge:
251060484Sobrien      print_binary (file, "ge", exp);
251133965Sjdp      break;
251233965Sjdp    case O_gt:
251360484Sobrien      print_binary (file, "gt", exp);
251433965Sjdp      break;
251533965Sjdp    case O_logical_and:
251660484Sobrien      print_binary (file, "logical_and", exp);
251733965Sjdp      break;
251833965Sjdp    case O_logical_or:
251960484Sobrien      print_binary (file, "logical_or", exp);
252033965Sjdp      break;
252133965Sjdp    case O_add:
252233965Sjdp      indent_level++;
252333965Sjdp      fprintf (file, "add\n%*s<", indent_level * 4, "");
252433965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
252533965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
252633965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
252733965Sjdp      fprintf (file, ">");
252833965Sjdp      goto maybe_print_addnum;
252933965Sjdp    case O_subtract:
253033965Sjdp      indent_level++;
253133965Sjdp      fprintf (file, "subtract\n%*s<", indent_level * 4, "");
253233965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
253333965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
253433965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
253533965Sjdp      fprintf (file, ">");
253633965Sjdp      goto maybe_print_addnum;
253733965Sjdp    default:
253833965Sjdp      fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
253933965Sjdp      break;
254033965Sjdp    }
254133965Sjdp  fflush (stdout);
254233965Sjdp}
254333965Sjdp
254433965Sjdpvoid
254533965Sjdpprint_expr (exp)
254633965Sjdp     expressionS *exp;
254733965Sjdp{
254833965Sjdp  print_expr_1 (stderr, exp);
254933965Sjdp  fprintf (stderr, "\n");
255033965Sjdp}
255133965Sjdp
255233965Sjdpvoid
255333965Sjdpsymbol_print_statistics (file)
255433965Sjdp     FILE *file;
255533965Sjdp{
255633965Sjdp  hash_print_statistics (file, "symbol table", sy_hash);
255760484Sobrien#ifdef BFD_ASSEMBLER
255860484Sobrien  hash_print_statistics (file, "mini local symbol table", local_hash);
255960484Sobrien  fprintf (file, "%lu mini local symbols created, %lu converted\n",
256060484Sobrien	   local_symbol_count, local_symbol_conversion_count);
256160484Sobrien#endif
256233965Sjdp}
2563