symbols.c revision 77298
133965Sjdp/* symbols.c -symbol table-
260484Sobrien   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
333965Sjdp   Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
1933965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2033965Sjdp   02111-1307, USA.  */
2133965Sjdp
2277298Sobrien/* #define DEBUG_SYMS / * to debug symbol list maintenance.  */
2333965Sjdp
2433965Sjdp#include <ctype.h>
2533965Sjdp
2633965Sjdp#include "as.h"
2733965Sjdp
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
6333965Sjdpstatic void fb_label_init PARAMS ((void));
6433965Sjdpstatic long dollar_label_instance PARAMS ((long));
6533965Sjdpstatic long fb_label_instance PARAMS ((long));
6633965Sjdp
6760484Sobrienstatic void print_binary PARAMS ((FILE *, const char *, expressionS *));
6860484Sobrien
6977298Sobrien/* Return a pointer to a new symbol.  Die if we can't make a new
7033965Sjdp   symbol.  Fill in the symbol's values.  Add symbol to end of symbol
7133965Sjdp   chain.
7277298Sobrien
7333965Sjdp   This function should be called in the general case of creating a
7433965Sjdp   symbol.  However, if the output file symbol table has already been
7533965Sjdp   set, and you are certain that this symbol won't be wanted in the
7633965Sjdp   output file, you can call symbol_create.  */
7733965Sjdp
7833965SjdpsymbolS *
7933965Sjdpsymbol_new (name, segment, valu, frag)
8033965Sjdp     const char *name;
8133965Sjdp     segT segment;
8233965Sjdp     valueT valu;
8333965Sjdp     fragS *frag;
8433965Sjdp{
8533965Sjdp  symbolS *symbolP = symbol_create (name, segment, valu, frag);
8633965Sjdp
8777298Sobrien  /* Link to end of symbol chain.  */
8833965Sjdp#ifdef BFD_ASSEMBLER
8933965Sjdp  {
9033965Sjdp    extern int symbol_table_frozen;
9133965Sjdp    if (symbol_table_frozen)
9233965Sjdp      abort ();
9333965Sjdp  }
9433965Sjdp#endif
9533965Sjdp  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
9633965Sjdp
9733965Sjdp  return symbolP;
9833965Sjdp}
9933965Sjdp
10060484Sobrien/* Save a symbol name on a permanent obstack, and convert it according
10160484Sobrien   to the object file format.  */
10260484Sobrien
10360484Sobrienstatic char *
10460484Sobriensave_symbol_name (name)
10560484Sobrien     const char *name;
10633965Sjdp{
10733965Sjdp  unsigned int name_length;
10860484Sobrien  char *ret;
10933965Sjdp
11077298Sobrien  name_length = strlen (name) + 1;	/* +1 for \0.  */
11133965Sjdp  obstack_grow (&notes, name, name_length);
11260484Sobrien  ret = obstack_finish (&notes);
11360484Sobrien
11433965Sjdp#ifdef STRIP_UNDERSCORE
11560484Sobrien  if (ret[0] == '_')
11660484Sobrien    ++ret;
11733965Sjdp#endif
11833965Sjdp
11933965Sjdp#ifdef tc_canonicalize_symbol_name
12060484Sobrien  ret = tc_canonicalize_symbol_name (ret);
12133965Sjdp#endif
12233965Sjdp
12333965Sjdp  if (! symbols_case_sensitive)
12433965Sjdp    {
12533965Sjdp      unsigned char *s;
12633965Sjdp
12760484Sobrien      for (s = (unsigned char *) ret; *s != '\0'; s++)
12833965Sjdp	if (islower (*s))
12933965Sjdp	  *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 *
20860484Sobrienlocal_symbol_make (name, section, offset, frag)
20960484Sobrien     const char *name;
21060484Sobrien     segT section;
21160484Sobrien     valueT offset;
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);
22660484Sobrien  ret->lsy_offset = offset;
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
24860484Sobrien  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset,
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
25760484Sobrien  symbol_table_insert (ret);
25860484Sobrien
25960484Sobrien  local_symbol_mark_converted (locsym);
26060484Sobrien  local_symbol_set_real_symbol (locsym, ret);
26160484Sobrien
26260484Sobrien  hash_jam (local_hash, locsym->lsy_name, NULL);
26360484Sobrien
26460484Sobrien  return ret;
26560484Sobrien}
26660484Sobrien
26760484Sobrien#else /* ! BFD_ASSEMBLER */
26860484Sobrien
26960484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0
27060484Sobrien#define local_symbol_convert(s) ((symbolS *) s)
27160484Sobrien
27260484Sobrien#endif /* ! BFD_ASSEMBLER */
27360484Sobrien
27477298Sobrien/* We have just seen "<name>:".
27577298Sobrien   Creates a struct symbol unless it already exists.
27660484Sobrien
27777298Sobrien   Gripes if we are redefining a symbol incompatibly (and ignores it).  */
27877298Sobrien
27933965SjdpsymbolS *
28077298Sobriencolon (sym_name)		/* Just seen "x:" - rattle symbols & frags.  */
28177298Sobrien     const char *sym_name;	/* Symbol name, as a cannonical string.  */
28277298Sobrien     /* We copy this string: OK to alter later.  */
28333965Sjdp{
28477298Sobrien  register symbolS *symbolP;	/* Symbol we are working with.  */
28533965Sjdp
28633965Sjdp  /* Sun local labels go out of scope whenever a non-local symbol is
28733965Sjdp     defined.  */
28833965Sjdp  if (LOCAL_LABELS_DOLLAR)
28933965Sjdp    {
29033965Sjdp      int local;
29133965Sjdp
29233965Sjdp#ifdef BFD_ASSEMBLER
29333965Sjdp      local = bfd_is_local_label_name (stdoutput, sym_name);
29433965Sjdp#else
29533965Sjdp      local = LOCAL_LABEL (sym_name);
29633965Sjdp#endif
29733965Sjdp
29833965Sjdp      if (! local)
29933965Sjdp	dollar_label_clear ();
30033965Sjdp    }
30133965Sjdp
30233965Sjdp#ifndef WORKING_DOT_WORD
30333965Sjdp  if (new_broken_words)
30433965Sjdp    {
30533965Sjdp      struct broken_word *a;
30633965Sjdp      int possible_bytes;
30733965Sjdp      fragS *frag_tmp;
30833965Sjdp      char *frag_opcode;
30933965Sjdp
31033965Sjdp      extern const int md_short_jump_size;
31133965Sjdp      extern const int md_long_jump_size;
31233965Sjdp      possible_bytes = (md_short_jump_size
31333965Sjdp			+ new_broken_words * md_long_jump_size);
31433965Sjdp
31533965Sjdp      frag_tmp = frag_now;
31633965Sjdp      frag_opcode = frag_var (rs_broken_word,
31733965Sjdp			      possible_bytes,
31833965Sjdp			      possible_bytes,
31933965Sjdp			      (relax_substateT) 0,
32033965Sjdp			      (symbolS *) broken_words,
32133965Sjdp			      (offsetT) 0,
32233965Sjdp			      NULL);
32333965Sjdp
32477298Sobrien      /* We want to store the pointer to where to insert the jump
32577298Sobrien	 table in the fr_opcode of the rs_broken_word frag.  This
32677298Sobrien	 requires a little hackery.  */
32733965Sjdp      while (frag_tmp
32833965Sjdp	     && (frag_tmp->fr_type != rs_broken_word
32933965Sjdp		 || frag_tmp->fr_opcode))
33033965Sjdp	frag_tmp = frag_tmp->fr_next;
33133965Sjdp      know (frag_tmp);
33233965Sjdp      frag_tmp->fr_opcode = frag_opcode;
33333965Sjdp      new_broken_words = 0;
33433965Sjdp
33533965Sjdp      for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
33633965Sjdp	a->dispfrag = frag_tmp;
33733965Sjdp    }
33833965Sjdp#endif /* WORKING_DOT_WORD */
33933965Sjdp
34033965Sjdp  if ((symbolP = symbol_find (sym_name)) != 0)
34133965Sjdp    {
34233965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION
34333965Sjdp      if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
34433965Sjdp	return symbolP;
34533965Sjdp#endif
34677298Sobrien      /* Now check for undefined symbols.  */
34760484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
34833965Sjdp	{
34960484Sobrien#ifdef BFD_ASSEMBLER
35060484Sobrien	  struct local_symbol *locsym = (struct local_symbol *) symbolP;
35160484Sobrien
35260484Sobrien	  if (locsym->lsy_section != undefined_section
35360484Sobrien	      && (local_symbol_get_frag (locsym) != frag_now
35460484Sobrien		  || locsym->lsy_section != now_seg
35560484Sobrien		  || locsym->lsy_offset != frag_now_fix ()))
35660484Sobrien	    {
35760484Sobrien	      as_bad (_("Symbol %s already defined."), sym_name);
35860484Sobrien	      return symbolP;
35960484Sobrien	    }
36060484Sobrien
36160484Sobrien	  locsym->lsy_section = now_seg;
36260484Sobrien	  local_symbol_set_frag (locsym, frag_now);
36360484Sobrien	  locsym->lsy_offset = frag_now_fix ();
36460484Sobrien#endif
36560484Sobrien	}
36660484Sobrien      else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
36760484Sobrien	{
36833965Sjdp	  if (S_GET_VALUE (symbolP) == 0)
36933965Sjdp	    {
37033965Sjdp	      symbolP->sy_frag = frag_now;
37133965Sjdp#ifdef OBJ_VMS
37277298Sobrien	      S_SET_OTHER (symbolP, const_flag);
37333965Sjdp#endif
37433965Sjdp	      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
37533965Sjdp	      S_SET_SEGMENT (symbolP, now_seg);
37633965Sjdp#ifdef N_UNDF
37733965Sjdp	      know (N_UNDF == 0);
37877298Sobrien#endif /* if we have one, it better be zero.  */
37933965Sjdp
38033965Sjdp	    }
38133965Sjdp	  else
38233965Sjdp	    {
38377298Sobrien	      /* There are still several cases to check:
38433965Sjdp
38577298Sobrien		 A .comm/.lcomm symbol being redefined as initialized
38677298Sobrien		 data is OK
38777298Sobrien
38877298Sobrien		 A .comm/.lcomm symbol being redefined with a larger
38977298Sobrien		 size is also OK
39077298Sobrien
39177298Sobrien		 This only used to be allowed on VMS gas, but Sun cc
39277298Sobrien		 on the sparc also depends on it.  */
39377298Sobrien
39433965Sjdp	      if (((!S_IS_DEBUG (symbolP)
39533965Sjdp		    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
39633965Sjdp		    && S_IS_EXTERNAL (symbolP))
39733965Sjdp		   || S_GET_SEGMENT (symbolP) == bss_section)
39833965Sjdp		  && (now_seg == data_section
39933965Sjdp		      || now_seg == S_GET_SEGMENT (symbolP)))
40033965Sjdp		{
40177298Sobrien		  /* Select which of the 2 cases this is.  */
40233965Sjdp		  if (now_seg != data_section)
40333965Sjdp		    {
40477298Sobrien		      /* New .comm for prev .comm symbol.
40577298Sobrien
40677298Sobrien			 If the new size is larger we just change its
40777298Sobrien			 value.  If the new size is smaller, we ignore
40877298Sobrien			 this symbol.  */
40933965Sjdp		      if (S_GET_VALUE (symbolP)
41033965Sjdp			  < ((unsigned) frag_now_fix ()))
41133965Sjdp			{
41233965Sjdp			  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
41333965Sjdp			}
41433965Sjdp		    }
41533965Sjdp		  else
41633965Sjdp		    {
41733965Sjdp		      /* It is a .comm/.lcomm being converted to initialized
41833965Sjdp			 data.  */
41933965Sjdp		      symbolP->sy_frag = frag_now;
42033965Sjdp#ifdef OBJ_VMS
42177298Sobrien		      S_SET_OTHER (symbolP, const_flag);
42233965Sjdp#endif
42333965Sjdp		      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
42477298Sobrien		      S_SET_SEGMENT (symbolP, now_seg);	/* Keep N_EXT bit.  */
42533965Sjdp		    }
42633965Sjdp		}
42733965Sjdp	      else
42833965Sjdp		{
42960484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \
43060484Sobrien     && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT))
43160484Sobrien		  static const char *od_buf = "";
43233965Sjdp#else
43360484Sobrien		  char od_buf[100];
43460484Sobrien		  od_buf[0] = '\0';
43560484Sobrien#ifdef BFD_ASSEMBLER
43660484Sobrien		  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
43760484Sobrien#endif
43860484Sobrien		    sprintf(od_buf, "%d.%d.",
43960484Sobrien			    S_GET_OTHER (symbolP),
44060484Sobrien			    S_GET_DESC (symbolP));
44160484Sobrien#endif
44277298Sobrien		  as_bad (_("Symbol \"%s\" is already defined as \"%s\"/%s%ld."),
44333965Sjdp			    sym_name,
44433965Sjdp			    segment_name (S_GET_SEGMENT (symbolP)),
44560484Sobrien			    od_buf,
44633965Sjdp			    (long) S_GET_VALUE (symbolP));
44733965Sjdp		}
44877298Sobrien	    }			/* if the undefined symbol has no value  */
44933965Sjdp	}
45033965Sjdp      else
45133965Sjdp	{
45277298Sobrien	  /* Don't blow up if the definition is the same.  */
45333965Sjdp	  if (!(frag_now == symbolP->sy_frag
45433965Sjdp		&& S_GET_VALUE (symbolP) == frag_now_fix ()
45533965Sjdp		&& S_GET_SEGMENT (symbolP) == now_seg))
45677298Sobrien	    as_bad (_("Symbol %s already defined."), sym_name);
45777298Sobrien	}
45833965Sjdp
45933965Sjdp    }
46060484Sobrien#ifdef BFD_ASSEMBLER
46160484Sobrien  else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))
46260484Sobrien    {
46360484Sobrien      symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,
46460484Sobrien					       (valueT) frag_now_fix (),
46560484Sobrien					       frag_now);
46660484Sobrien    }
46760484Sobrien#endif /* BFD_ASSEMBLER */
46833965Sjdp  else
46933965Sjdp    {
47033965Sjdp      symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
47133965Sjdp			    frag_now);
47233965Sjdp#ifdef OBJ_VMS
47333965Sjdp      S_SET_OTHER (symbolP, const_flag);
47433965Sjdp#endif /* OBJ_VMS */
47533965Sjdp
47633965Sjdp      symbol_table_insert (symbolP);
47777298Sobrien    }
47833965Sjdp
47933965Sjdp  if (mri_common_symbol != NULL)
48033965Sjdp    {
48133965Sjdp      /* This symbol is actually being defined within an MRI common
48233965Sjdp         section.  This requires special handling.  */
48360484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
48460484Sobrien	symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
48533965Sjdp      symbolP->sy_value.X_op = O_symbol;
48633965Sjdp      symbolP->sy_value.X_add_symbol = mri_common_symbol;
48733965Sjdp      symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
48833965Sjdp      symbolP->sy_frag = &zero_address_frag;
48933965Sjdp      S_SET_SEGMENT (symbolP, expr_section);
49033965Sjdp      symbolP->sy_mri_common = 1;
49133965Sjdp    }
49233965Sjdp
49333965Sjdp#ifdef tc_frob_label
49433965Sjdp  tc_frob_label (symbolP);
49533965Sjdp#endif
49633965Sjdp#ifdef obj_frob_label
49733965Sjdp  obj_frob_label (symbolP);
49833965Sjdp#endif
49933965Sjdp
50033965Sjdp  return symbolP;
50133965Sjdp}
50233965Sjdp
50377298Sobrien/* Die if we can't insert the symbol.  */
50433965Sjdp
50577298Sobrienvoid
50633965Sjdpsymbol_table_insert (symbolP)
50733965Sjdp     symbolS *symbolP;
50833965Sjdp{
50933965Sjdp  register const char *error_string;
51033965Sjdp
51133965Sjdp  know (symbolP);
51233965Sjdp  know (S_GET_NAME (symbolP));
51333965Sjdp
51460484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
51560484Sobrien    {
51660484Sobrien      error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
51760484Sobrien			       (PTR) symbolP);
51860484Sobrien      if (error_string != NULL)
51960484Sobrien	as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
52060484Sobrien		  S_GET_NAME (symbolP), error_string);
52160484Sobrien      return;
52260484Sobrien    }
52360484Sobrien
52433965Sjdp  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
52533965Sjdp    {
52660484Sobrien      as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
52733965Sjdp		S_GET_NAME (symbolP), error_string);
52877298Sobrien    }				/* on error  */
52977298Sobrien}
53033965Sjdp
53177298Sobrien/* If a symbol name does not exist, create it as undefined, and insert
53277298Sobrien   it into the symbol table.  Return a pointer to it.  */
53377298Sobrien
53433965SjdpsymbolS *
53533965Sjdpsymbol_find_or_make (name)
53633965Sjdp     const char *name;
53733965Sjdp{
53833965Sjdp  register symbolS *symbolP;
53933965Sjdp
54033965Sjdp  symbolP = symbol_find (name);
54133965Sjdp
54233965Sjdp  if (symbolP == NULL)
54333965Sjdp    {
54460484Sobrien#ifdef BFD_ASSEMBLER
54560484Sobrien      if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))
54660484Sobrien	{
54760484Sobrien	  symbolP = md_undefined_symbol ((char *) name);
54860484Sobrien	  if (symbolP != NULL)
54960484Sobrien	    return symbolP;
55060484Sobrien
55160484Sobrien	  symbolP = (symbolS *) local_symbol_make (name, undefined_section,
55260484Sobrien						   (valueT) 0,
55360484Sobrien						   &zero_address_frag);
55460484Sobrien	  return symbolP;
55560484Sobrien	}
55660484Sobrien#endif
55760484Sobrien
55833965Sjdp      symbolP = symbol_make (name);
55933965Sjdp
56033965Sjdp      symbol_table_insert (symbolP);
56133965Sjdp    }				/* if symbol wasn't found */
56233965Sjdp
56333965Sjdp  return (symbolP);
56477298Sobrien}
56533965Sjdp
56633965SjdpsymbolS *
56733965Sjdpsymbol_make (name)
56833965Sjdp     CONST char *name;
56933965Sjdp{
57033965Sjdp  symbolS *symbolP;
57133965Sjdp
57277298Sobrien  /* Let the machine description default it, e.g. for register names.  */
57333965Sjdp  symbolP = md_undefined_symbol ((char *) name);
57433965Sjdp
57533965Sjdp  if (!symbolP)
57633965Sjdp    symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
57733965Sjdp
57833965Sjdp  return (symbolP);
57977298Sobrien}
58033965Sjdp
58177298Sobrien/* Implement symbol table lookup.
58277298Sobrien   In:	A symbol's name as a string: '\0' can't be part of a symbol name.
58377298Sobrien   Out:	NULL if the name was not in the symbol table, else the address
58477298Sobrien   of a struct symbol associated with that name.  */
58533965Sjdp
58633965SjdpsymbolS *
58733965Sjdpsymbol_find (name)
58833965Sjdp     CONST char *name;
58933965Sjdp{
59033965Sjdp#ifdef STRIP_UNDERSCORE
59133965Sjdp  return (symbol_find_base (name, 1));
59233965Sjdp#else /* STRIP_UNDERSCORE */
59333965Sjdp  return (symbol_find_base (name, 0));
59433965Sjdp#endif /* STRIP_UNDERSCORE */
59577298Sobrien}
59633965Sjdp
59733965SjdpsymbolS *
59833965Sjdpsymbol_find_base (name, strip_underscore)
59933965Sjdp     CONST char *name;
60033965Sjdp     int strip_underscore;
60133965Sjdp{
60233965Sjdp  if (strip_underscore && *name == '_')
60333965Sjdp    name++;
60433965Sjdp
60533965Sjdp#ifdef tc_canonicalize_symbol_name
60633965Sjdp  {
60733965Sjdp    char *copy;
60860484Sobrien    size_t len = strlen (name) + 1;
60933965Sjdp
61060484Sobrien    copy = (char *) alloca (len);
61160484Sobrien    memcpy (copy, name, len);
61233965Sjdp    name = tc_canonicalize_symbol_name (copy);
61333965Sjdp  }
61433965Sjdp#endif
61533965Sjdp
61633965Sjdp  if (! symbols_case_sensitive)
61733965Sjdp    {
61860484Sobrien      char *copy;
61960484Sobrien      const char *orig;
62060484Sobrien      unsigned char c;
62133965Sjdp
62260484Sobrien      orig = name;
62360484Sobrien      name = copy = (char *) alloca (strlen (name) + 1);
62460484Sobrien
62560484Sobrien      while ((c = *orig++) != '\0')
62660484Sobrien	{
62760484Sobrien	  if (islower (c))
62860484Sobrien	    c = toupper (c);
62960484Sobrien	  *copy++ = c;
63060484Sobrien	}
63160484Sobrien      *copy = '\0';
63233965Sjdp    }
63333965Sjdp
63460484Sobrien#ifdef BFD_ASSEMBLER
63560484Sobrien  {
63660484Sobrien    struct local_symbol *locsym;
63760484Sobrien
63860484Sobrien    locsym = (struct local_symbol *) hash_find (local_hash, name);
63960484Sobrien    if (locsym != NULL)
64060484Sobrien      return (symbolS *) locsym;
64160484Sobrien  }
64260484Sobrien#endif
64360484Sobrien
64433965Sjdp  return ((symbolS *) hash_find (sy_hash, name));
64533965Sjdp}
64633965Sjdp
64777298Sobrien/* Once upon a time, symbols were kept in a singly linked list.  At
64877298Sobrien   least coff needs to be able to rearrange them from time to time, for
64977298Sobrien   which a doubly linked list is much more convenient.  Loic did these
65077298Sobrien   as macros which seemed dangerous to me so they're now functions.
65177298Sobrien   xoxorich.  */
65233965Sjdp
65377298Sobrien/* Link symbol ADDME after symbol TARGET in the chain.  */
65477298Sobrien
65577298Sobrienvoid
65633965Sjdpsymbol_append (addme, target, rootPP, lastPP)
65733965Sjdp     symbolS *addme;
65833965Sjdp     symbolS *target;
65933965Sjdp     symbolS **rootPP;
66033965Sjdp     symbolS **lastPP;
66133965Sjdp{
66260484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
66360484Sobrien    abort ();
66460484Sobrien  if (target != NULL && LOCAL_SYMBOL_CHECK (target))
66560484Sobrien    abort ();
66660484Sobrien
66733965Sjdp  if (target == NULL)
66833965Sjdp    {
66933965Sjdp      know (*rootPP == NULL);
67033965Sjdp      know (*lastPP == NULL);
67133965Sjdp      addme->sy_next = NULL;
67233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
67333965Sjdp      addme->sy_previous = NULL;
67433965Sjdp#endif
67533965Sjdp      *rootPP = addme;
67633965Sjdp      *lastPP = addme;
67733965Sjdp      return;
67877298Sobrien    }				/* if the list is empty  */
67933965Sjdp
68033965Sjdp  if (target->sy_next != NULL)
68133965Sjdp    {
68233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
68333965Sjdp      target->sy_next->sy_previous = addme;
68433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
68533965Sjdp    }
68633965Sjdp  else
68733965Sjdp    {
68833965Sjdp      know (*lastPP == target);
68933965Sjdp      *lastPP = addme;
69077298Sobrien    }				/* if we have a next  */
69133965Sjdp
69233965Sjdp  addme->sy_next = target->sy_next;
69333965Sjdp  target->sy_next = addme;
69433965Sjdp
69533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
69633965Sjdp  addme->sy_previous = target;
69733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
69833965Sjdp
69933965Sjdp  debug_verify_symchain (symbol_rootP, symbol_lastP);
70033965Sjdp}
70133965Sjdp
70277298Sobrien/* Set the chain pointers of SYMBOL to null.  */
70377298Sobrien
70477298Sobrienvoid
70533965Sjdpsymbol_clear_list_pointers (symbolP)
70633965Sjdp     symbolS *symbolP;
70733965Sjdp{
70860484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
70960484Sobrien    abort ();
71033965Sjdp  symbolP->sy_next = NULL;
71133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
71233965Sjdp  symbolP->sy_previous = NULL;
71333965Sjdp#endif
71433965Sjdp}
71533965Sjdp
71633965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
71777298Sobrien/* Remove SYMBOLP from the list.  */
71877298Sobrien
71977298Sobrienvoid
72033965Sjdpsymbol_remove (symbolP, rootPP, lastPP)
72133965Sjdp     symbolS *symbolP;
72233965Sjdp     symbolS **rootPP;
72333965Sjdp     symbolS **lastPP;
72433965Sjdp{
72560484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
72660484Sobrien    abort ();
72760484Sobrien
72833965Sjdp  if (symbolP == *rootPP)
72933965Sjdp    {
73033965Sjdp      *rootPP = symbolP->sy_next;
73177298Sobrien    }				/* if it was the root  */
73233965Sjdp
73333965Sjdp  if (symbolP == *lastPP)
73433965Sjdp    {
73533965Sjdp      *lastPP = symbolP->sy_previous;
73677298Sobrien    }				/* if it was the tail  */
73733965Sjdp
73833965Sjdp  if (symbolP->sy_next != NULL)
73933965Sjdp    {
74033965Sjdp      symbolP->sy_next->sy_previous = symbolP->sy_previous;
74177298Sobrien    }				/* if not last  */
74233965Sjdp
74333965Sjdp  if (symbolP->sy_previous != NULL)
74433965Sjdp    {
74533965Sjdp      symbolP->sy_previous->sy_next = symbolP->sy_next;
74677298Sobrien    }				/* if not first  */
74733965Sjdp
74833965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
74933965Sjdp}
75033965Sjdp
75177298Sobrien/* Link symbol ADDME before symbol TARGET in the chain.  */
75277298Sobrien
75377298Sobrienvoid
75433965Sjdpsymbol_insert (addme, target, rootPP, lastPP)
75533965Sjdp     symbolS *addme;
75633965Sjdp     symbolS *target;
75733965Sjdp     symbolS **rootPP;
75860484Sobrien     symbolS **lastPP ATTRIBUTE_UNUSED;
75933965Sjdp{
76060484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
76160484Sobrien    abort ();
76260484Sobrien  if (LOCAL_SYMBOL_CHECK (target))
76360484Sobrien    abort ();
76460484Sobrien
76533965Sjdp  if (target->sy_previous != NULL)
76633965Sjdp    {
76733965Sjdp      target->sy_previous->sy_next = addme;
76833965Sjdp    }
76933965Sjdp  else
77033965Sjdp    {
77133965Sjdp      know (*rootPP == target);
77233965Sjdp      *rootPP = addme;
77377298Sobrien    }				/* if not first  */
77433965Sjdp
77533965Sjdp  addme->sy_previous = target->sy_previous;
77633965Sjdp  target->sy_previous = addme;
77733965Sjdp  addme->sy_next = target;
77833965Sjdp
77933965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
78033965Sjdp}
78133965Sjdp
78233965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
78333965Sjdp
78477298Sobrienvoid
78533965Sjdpverify_symbol_chain (rootP, lastP)
78633965Sjdp     symbolS *rootP;
78733965Sjdp     symbolS *lastP;
78833965Sjdp{
78933965Sjdp  symbolS *symbolP = rootP;
79033965Sjdp
79133965Sjdp  if (symbolP == NULL)
79233965Sjdp    return;
79333965Sjdp
79433965Sjdp  for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
79533965Sjdp    {
79660484Sobrien#ifdef BFD_ASSEMBLER
79760484Sobrien      assert (symbolP->bsym != NULL);
79860484Sobrien#endif
79933965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
80033965Sjdp      assert (symbolP->sy_next->sy_previous == symbolP);
80133965Sjdp#else
80233965Sjdp      /* Walk the list anyways, to make sure pointers are still good.  */
80333965Sjdp      ;
80433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
80533965Sjdp    }
80633965Sjdp
80733965Sjdp  assert (lastP == symbolP);
80833965Sjdp}
80933965Sjdp
81033965Sjdpvoid
81133965Sjdpverify_symbol_chain_2 (sym)
81233965Sjdp     symbolS *sym;
81333965Sjdp{
81433965Sjdp  symbolS *p = sym, *n = sym;
81533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
81633965Sjdp  while (symbol_previous (p))
81733965Sjdp    p = symbol_previous (p);
81833965Sjdp#endif
81933965Sjdp  while (symbol_next (n))
82033965Sjdp    n = symbol_next (n);
82133965Sjdp  verify_symbol_chain (p, n);
82233965Sjdp}
82333965Sjdp
82433965Sjdp/* Resolve the value of a symbol.  This is called during the final
82533965Sjdp   pass over the symbol table to resolve any symbols with complex
82633965Sjdp   values.  */
82733965Sjdp
82838889SjdpvalueT
82938889Sjdpresolve_symbol_value (symp, finalize)
83033965Sjdp     symbolS *symp;
83138889Sjdp     int finalize;
83233965Sjdp{
83333965Sjdp  int resolved;
83438889Sjdp  valueT final_val;
83538889Sjdp  segT final_seg;
83633965Sjdp
83760484Sobrien#ifdef BFD_ASSEMBLER
83860484Sobrien  if (LOCAL_SYMBOL_CHECK (symp))
83960484Sobrien    {
84060484Sobrien      struct local_symbol *locsym = (struct local_symbol *) symp;
84160484Sobrien
84260484Sobrien      if (local_symbol_resolved_p (locsym))
84377298Sobrien	return locsym->lsy_offset / bfd_octets_per_byte (stdoutput);
84460484Sobrien
84560484Sobrien      final_val = (local_symbol_get_frag (locsym)->fr_address
84677298Sobrien		   + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput);
84760484Sobrien
84860484Sobrien      if (finalize)
84960484Sobrien	{
85060484Sobrien	  locsym->lsy_offset = final_val;
85160484Sobrien	  local_symbol_mark_resolved (locsym);
85260484Sobrien	}
85360484Sobrien
85460484Sobrien      return final_val;
85560484Sobrien    }
85660484Sobrien#endif
85760484Sobrien
85833965Sjdp  if (symp->sy_resolved)
85938889Sjdp    {
86038889Sjdp      if (symp->sy_value.X_op == O_constant)
86138889Sjdp	return (valueT) symp->sy_value.X_add_number;
86238889Sjdp      else
86338889Sjdp	return 0;
86438889Sjdp    }
86533965Sjdp
86633965Sjdp  resolved = 0;
86738889Sjdp  final_seg = S_GET_SEGMENT (symp);
86833965Sjdp
86933965Sjdp  if (symp->sy_resolving)
87033965Sjdp    {
87138889Sjdp      if (finalize)
87277298Sobrien	as_bad (_("Symbol definition loop encountered at %s"),
87377298Sobrien		S_GET_NAME (symp));
87438889Sjdp      final_val = 0;
87533965Sjdp      resolved = 1;
87633965Sjdp    }
87733965Sjdp  else
87833965Sjdp    {
87938889Sjdp      symbolS *add_symbol, *op_symbol;
88038889Sjdp      offsetT left, right;
88133965Sjdp      segT seg_left, seg_right;
88238889Sjdp      operatorT op;
88333965Sjdp
88433965Sjdp      symp->sy_resolving = 1;
88533965Sjdp
88638889Sjdp      /* Help out with CSE.  */
88738889Sjdp      add_symbol = symp->sy_value.X_add_symbol;
88838889Sjdp      op_symbol = symp->sy_value.X_op_symbol;
88938889Sjdp      final_val = symp->sy_value.X_add_number;
89038889Sjdp      op = symp->sy_value.X_op;
89138889Sjdp
89238889Sjdp      switch (op)
89333965Sjdp	{
89438889Sjdp	default:
89538889Sjdp	  BAD_CASE (op);
89638889Sjdp	  break;
89733965Sjdp
89833965Sjdp	case O_absent:
89938889Sjdp	  final_val = 0;
90033965Sjdp	  /* Fall through.  */
90138889Sjdp
90233965Sjdp	case O_constant:
90360484Sobrien	  final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
90438889Sjdp	  if (final_seg == expr_section)
90538889Sjdp	    final_seg = absolute_section;
90633965Sjdp	  resolved = 1;
90733965Sjdp	  break;
90833965Sjdp
90933965Sjdp	case O_symbol:
91038889Sjdp	case O_symbol_rva:
91138889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
91238889Sjdp	do_symbol:
91333965Sjdp
91433965Sjdp	  if (symp->sy_mri_common)
91533965Sjdp	    {
91633965Sjdp	      /* This is a symbol inside an MRI common section.  The
91733965Sjdp                 relocation routines are going to handle it specially.
91833965Sjdp                 Don't change the value.  */
91960484Sobrien	      resolved = symbol_resolved_p (add_symbol);
92033965Sjdp	      break;
92133965Sjdp	    }
92233965Sjdp
92338889Sjdp	  if (finalize && final_val == 0)
92460484Sobrien	    {
92560484Sobrien	      if (LOCAL_SYMBOL_CHECK (add_symbol))
92660484Sobrien		add_symbol = local_symbol_convert ((struct local_symbol *)
92760484Sobrien						   add_symbol);
92860484Sobrien	      copy_symbol_attributes (symp, add_symbol);
92960484Sobrien	    }
93033965Sjdp
93133965Sjdp	  /* If we have equated this symbol to an undefined symbol, we
93233965Sjdp             keep X_op set to O_symbol, and we don't change
93333965Sjdp             X_add_number.  This permits the routine which writes out
93433965Sjdp             relocation to detect this case, and convert the
93533965Sjdp             relocation to be against the symbol to which this symbol
93633965Sjdp             is equated.  */
93738889Sjdp	  if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
93833965Sjdp	    {
93938889Sjdp	      if (finalize)
94038889Sjdp		{
94160484Sobrien		  S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
94238889Sjdp		  symp->sy_value.X_op = O_symbol;
94360484Sobrien		  symp->sy_value.X_add_symbol = add_symbol;
94438889Sjdp		  symp->sy_value.X_add_number = final_val;
94538889Sjdp		}
94638889Sjdp	      final_val = 0;
94760484Sobrien	      resolved = symbol_resolved_p (add_symbol);
94838889Sjdp	      goto exit_dont_set_value;
94933965Sjdp	    }
95033965Sjdp	  else
95133965Sjdp	    {
95238889Sjdp	      final_val += symp->sy_frag->fr_address + left;
95338889Sjdp	      if (final_seg == expr_section || final_seg == undefined_section)
95438889Sjdp		final_seg = S_GET_SEGMENT (add_symbol);
95533965Sjdp	    }
95633965Sjdp
95760484Sobrien	  resolved = symbol_resolved_p (add_symbol);
95833965Sjdp	  break;
95933965Sjdp
96033965Sjdp	case O_uminus:
96133965Sjdp	case O_bit_not:
96233965Sjdp	case O_logical_not:
96338889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
96438889Sjdp
96538889Sjdp	  if (op == O_uminus)
96638889Sjdp	    left = -left;
96738889Sjdp	  else if (op == O_logical_not)
96838889Sjdp	    left = !left;
96933965Sjdp	  else
97038889Sjdp	    left = ~left;
97138889Sjdp
97238889Sjdp	  final_val += left + symp->sy_frag->fr_address;
97338889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
97438889Sjdp	    final_seg = absolute_section;
97538889Sjdp
97660484Sobrien	  resolved = symbol_resolved_p (add_symbol);
97733965Sjdp	  break;
97833965Sjdp
97933965Sjdp	case O_multiply:
98033965Sjdp	case O_divide:
98133965Sjdp	case O_modulus:
98233965Sjdp	case O_left_shift:
98333965Sjdp	case O_right_shift:
98433965Sjdp	case O_bit_inclusive_or:
98533965Sjdp	case O_bit_or_not:
98633965Sjdp	case O_bit_exclusive_or:
98733965Sjdp	case O_bit_and:
98833965Sjdp	case O_add:
98933965Sjdp	case O_subtract:
99033965Sjdp	case O_eq:
99133965Sjdp	case O_ne:
99233965Sjdp	case O_lt:
99333965Sjdp	case O_le:
99433965Sjdp	case O_ge:
99533965Sjdp	case O_gt:
99633965Sjdp	case O_logical_and:
99733965Sjdp	case O_logical_or:
99838889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
99938889Sjdp	  right = resolve_symbol_value (op_symbol, finalize);
100038889Sjdp	  seg_left = S_GET_SEGMENT (add_symbol);
100138889Sjdp	  seg_right = S_GET_SEGMENT (op_symbol);
100233965Sjdp
100338889Sjdp	  /* Simplify addition or subtraction of a constant by folding the
100438889Sjdp	     constant into X_add_number.  */
100538889Sjdp	  if (op == O_add || op == O_subtract)
100638889Sjdp	    {
100738889Sjdp	      if (seg_right == absolute_section)
100838889Sjdp		{
100938889Sjdp		  if (op == O_add)
101038889Sjdp		    final_val += right;
101138889Sjdp		  else
101238889Sjdp		    final_val -= right;
101338889Sjdp		  op = O_symbol;
101438889Sjdp		  op_symbol = NULL;
101538889Sjdp		  goto do_symbol;
101638889Sjdp		}
101738889Sjdp	      else if (seg_left == absolute_section && op == O_add)
101838889Sjdp		{
101938889Sjdp		  op = O_symbol;
102038889Sjdp		  final_val += left;
102138889Sjdp		  add_symbol = op_symbol;
102238889Sjdp		  left = right;
102338889Sjdp		  op_symbol = NULL;
102438889Sjdp		  goto do_symbol;
102538889Sjdp		}
102638889Sjdp	    }
102738889Sjdp
102833965Sjdp	  /* Subtraction is permitted if both operands are in the same
102933965Sjdp	     section.  Otherwise, both operands must be absolute.  We
103033965Sjdp	     already handled the case of addition or subtraction of a
103133965Sjdp	     constant above.  This will probably need to be changed
103233965Sjdp	     for an object file format which supports arbitrary
103333965Sjdp	     expressions, such as IEEE-695.  */
103438889Sjdp	  /* Don't emit messages unless we're finalizing the symbol value,
103538889Sjdp	     otherwise we may get the same message multiple times.  */
103660484Sobrien	  if ((seg_left != absolute_section
103760484Sobrien	       || seg_right != absolute_section)
103860484Sobrien	      && (op != O_subtract
103960484Sobrien		  || seg_left != seg_right
104060484Sobrien		  || seg_left == undefined_section)
104138889Sjdp	      && finalize)
104233965Sjdp	    {
104333965Sjdp	      char *file;
104433965Sjdp	      unsigned int line;
104533965Sjdp
104633965Sjdp	      if (expr_symbol_where (symp, &file, &line))
104733965Sjdp		{
104833965Sjdp		  if (seg_left == undefined_section)
104933965Sjdp		    as_bad_where (file, line,
105060484Sobrien				  _("undefined symbol %s in operation"),
105133965Sjdp				  S_GET_NAME (symp->sy_value.X_add_symbol));
105233965Sjdp		  if (seg_right == undefined_section)
105333965Sjdp		    as_bad_where (file, line,
105460484Sobrien				  _("undefined symbol %s in operation"),
105533965Sjdp				  S_GET_NAME (symp->sy_value.X_op_symbol));
105633965Sjdp		  if (seg_left != undefined_section
105733965Sjdp		      && seg_right != undefined_section)
105877298Sobrien		    as_bad_where (file, line,
105977298Sobrien				  _("invalid section for operation"));
106033965Sjdp		}
106133965Sjdp	      else
106233965Sjdp		{
106333965Sjdp		  if (seg_left == undefined_section)
106460484Sobrien		    as_bad (_("undefined symbol %s in operation setting %s"),
106533965Sjdp			    S_GET_NAME (symp->sy_value.X_add_symbol),
106633965Sjdp			    S_GET_NAME (symp));
106733965Sjdp		  if (seg_right == undefined_section)
106860484Sobrien		    as_bad (_("undefined symbol %s in operation setting %s"),
106933965Sjdp			    S_GET_NAME (symp->sy_value.X_op_symbol),
107033965Sjdp			    S_GET_NAME (symp));
107133965Sjdp		  if (seg_left != undefined_section
107233965Sjdp		      && seg_right != undefined_section)
107360484Sobrien		    as_bad (_("invalid section for operation setting %s"),
107433965Sjdp			    S_GET_NAME (symp));
107533965Sjdp		}
107633965Sjdp	    }
107733965Sjdp
107838889Sjdp	  /* Check for division by zero.  */
107938889Sjdp	  if ((op == O_divide || op == O_modulus) && right == 0)
108038889Sjdp	    {
108138889Sjdp	      /* If seg_right is not absolute_section, then we've
108238889Sjdp                 already issued a warning about using a bad symbol.  */
108338889Sjdp	      if (seg_right == absolute_section && finalize)
108438889Sjdp		{
108538889Sjdp		  char *file;
108638889Sjdp		  unsigned int line;
108738889Sjdp
108838889Sjdp		  if (expr_symbol_where (symp, &file, &line))
108960484Sobrien		    as_bad_where (file, line, _("division by zero"));
109038889Sjdp		  else
109160484Sobrien		    as_bad (_("division by zero when setting %s"),
109238889Sjdp			    S_GET_NAME (symp));
109338889Sjdp		}
109438889Sjdp
109538889Sjdp	      right = 1;
109638889Sjdp	    }
109738889Sjdp
109833965Sjdp	  switch (symp->sy_value.X_op)
109933965Sjdp	    {
110038889Sjdp	    case O_multiply:		left *= right; break;
110138889Sjdp	    case O_divide:		left /= right; break;
110238889Sjdp	    case O_modulus:		left %= right; break;
110338889Sjdp	    case O_left_shift:		left <<= right; break;
110438889Sjdp	    case O_right_shift:		left >>= right; break;
110538889Sjdp	    case O_bit_inclusive_or:	left |= right; break;
110638889Sjdp	    case O_bit_or_not:		left |= ~right; break;
110738889Sjdp	    case O_bit_exclusive_or:	left ^= right; break;
110838889Sjdp	    case O_bit_and:		left &= right; break;
110938889Sjdp	    case O_add:			left += right; break;
111038889Sjdp	    case O_subtract:		left -= right; break;
111138889Sjdp	    case O_eq:	left = left == right ? ~ (offsetT) 0 : 0; break;
111238889Sjdp	    case O_ne:	left = left != right ? ~ (offsetT) 0 : 0; break;
111338889Sjdp	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;
111438889Sjdp	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;
111538889Sjdp	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;
111638889Sjdp	    case O_gt:	left = left >  right ? ~ (offsetT) 0 : 0; break;
111738889Sjdp	    case O_logical_and:	left = left && right; break;
111838889Sjdp	    case O_logical_or:	left = left || right; break;
111938889Sjdp	    default:		abort ();
112033965Sjdp	    }
112138889Sjdp
112238889Sjdp	  final_val += symp->sy_frag->fr_address + left;
112338889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
112438889Sjdp	    final_seg = absolute_section;
112560484Sobrien	  resolved = (symbol_resolved_p (add_symbol)
112660484Sobrien		      && symbol_resolved_p (op_symbol));
112777298Sobrien	  break;
112833965Sjdp
112933965Sjdp	case O_register:
113033965Sjdp	case O_big:
113133965Sjdp	case O_illegal:
113233965Sjdp	  /* Give an error (below) if not in expr_section.  We don't
113333965Sjdp	     want to worry about expr_section symbols, because they
113433965Sjdp	     are fictional (they are created as part of expression
113533965Sjdp	     resolution), and any problems may not actually mean
113633965Sjdp	     anything.  */
113733965Sjdp	  break;
113833965Sjdp	}
113938889Sjdp
114038889Sjdp      symp->sy_resolving = 0;
114133965Sjdp    }
114233965Sjdp
114338889Sjdp  if (finalize)
114438889Sjdp    {
114538889Sjdp      S_SET_VALUE (symp, final_val);
114638889Sjdp
114738889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
114838889Sjdp      /* The old a.out backend does not handle S_SET_SEGMENT correctly
114938889Sjdp         for a stab symbol, so we use this bad hack.  */
115038889Sjdp      if (final_seg != S_GET_SEGMENT (symp))
115138889Sjdp#endif
115238889Sjdp	S_SET_SEGMENT (symp, final_seg);
115338889Sjdp    }
115438889Sjdp
115538889Sjdpexit_dont_set_value:
115633965Sjdp  /* Don't worry if we can't resolve an expr_section symbol.  */
115738889Sjdp  if (finalize)
115833965Sjdp    {
115938889Sjdp      if (resolved)
116038889Sjdp	symp->sy_resolved = 1;
116138889Sjdp      else if (S_GET_SEGMENT (symp) != expr_section)
116238889Sjdp	{
116377298Sobrien	  as_bad (_("can't resolve value for symbol \"%s\""),
116477298Sobrien		  S_GET_NAME (symp));
116538889Sjdp	  symp->sy_resolved = 1;
116638889Sjdp	}
116733965Sjdp    }
116838889Sjdp
116938889Sjdp  return final_val;
117033965Sjdp}
117133965Sjdp
117260484Sobrien#ifdef BFD_ASSEMBLER
117360484Sobrien
117460484Sobrienstatic void resolve_local_symbol PARAMS ((const char *, PTR));
117560484Sobrien
117660484Sobrien/* A static function passed to hash_traverse.  */
117760484Sobrien
117860484Sobrienstatic void
117960484Sobrienresolve_local_symbol (key, value)
118060484Sobrien     const char *key ATTRIBUTE_UNUSED;
118160484Sobrien     PTR value;
118260484Sobrien{
118360484Sobrien  if (value != NULL)
118460484Sobrien    resolve_symbol_value (value, 1);
118560484Sobrien}
118660484Sobrien
118760484Sobrien#endif
118860484Sobrien
118960484Sobrien/* Resolve all local symbols.  */
119060484Sobrien
119160484Sobrienvoid
119260484Sobrienresolve_local_symbol_values ()
119360484Sobrien{
119460484Sobrien#ifdef BFD_ASSEMBLER
119560484Sobrien  hash_traverse (local_hash, resolve_local_symbol);
119660484Sobrien#endif
119760484Sobrien}
119860484Sobrien
119933965Sjdp/* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
120033965Sjdp   They are *really* local.  That is, they go out of scope whenever we see a
120133965Sjdp   label that isn't local.  Also, like fb labels, there can be multiple
120233965Sjdp   instances of a dollar label.  Therefor, we name encode each instance with
120333965Sjdp   the instance number, keep a list of defined symbols separate from the real
120433965Sjdp   symbol table, and we treat these buggers as a sparse array.  */
120533965Sjdp
120633965Sjdpstatic long *dollar_labels;
120733965Sjdpstatic long *dollar_label_instances;
120833965Sjdpstatic char *dollar_label_defines;
120938889Sjdpstatic unsigned long dollar_label_count;
121033965Sjdpstatic unsigned long dollar_label_max;
121133965Sjdp
121277298Sobrienint
121333965Sjdpdollar_label_defined (label)
121433965Sjdp     long label;
121533965Sjdp{
121633965Sjdp  long *i;
121733965Sjdp
121833965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
121933965Sjdp
122033965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
122133965Sjdp    if (*i == label)
122233965Sjdp      return dollar_label_defines[i - dollar_labels];
122333965Sjdp
122477298Sobrien  /* If we get here, label isn't defined.  */
122533965Sjdp  return 0;
122677298Sobrien}
122733965Sjdp
122833965Sjdpstatic long
122933965Sjdpdollar_label_instance (label)
123033965Sjdp     long label;
123133965Sjdp{
123233965Sjdp  long *i;
123333965Sjdp
123433965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
123533965Sjdp
123633965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
123733965Sjdp    if (*i == label)
123833965Sjdp      return (dollar_label_instances[i - dollar_labels]);
123933965Sjdp
124077298Sobrien  /* If we get here, we haven't seen the label before.
124177298Sobrien     Therefore its instance count is zero.  */
124233965Sjdp  return 0;
124333965Sjdp}
124433965Sjdp
124577298Sobrienvoid
124633965Sjdpdollar_label_clear ()
124733965Sjdp{
124833965Sjdp  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
124933965Sjdp}
125033965Sjdp
125133965Sjdp#define DOLLAR_LABEL_BUMP_BY 10
125233965Sjdp
125377298Sobrienvoid
125433965Sjdpdefine_dollar_label (label)
125533965Sjdp     long label;
125633965Sjdp{
125733965Sjdp  long *i;
125833965Sjdp
125933965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
126033965Sjdp    if (*i == label)
126133965Sjdp      {
126233965Sjdp	++dollar_label_instances[i - dollar_labels];
126333965Sjdp	dollar_label_defines[i - dollar_labels] = 1;
126433965Sjdp	return;
126533965Sjdp      }
126633965Sjdp
126777298Sobrien  /* If we get to here, we don't have label listed yet.  */
126833965Sjdp
126933965Sjdp  if (dollar_labels == NULL)
127033965Sjdp    {
127133965Sjdp      dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
127233965Sjdp      dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
127333965Sjdp      dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
127433965Sjdp      dollar_label_max = DOLLAR_LABEL_BUMP_BY;
127533965Sjdp      dollar_label_count = 0;
127633965Sjdp    }
127733965Sjdp  else if (dollar_label_count == dollar_label_max)
127833965Sjdp    {
127933965Sjdp      dollar_label_max += DOLLAR_LABEL_BUMP_BY;
128033965Sjdp      dollar_labels = (long *) xrealloc ((char *) dollar_labels,
128133965Sjdp					 dollar_label_max * sizeof (long));
128233965Sjdp      dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
128333965Sjdp					  dollar_label_max * sizeof (long));
128433965Sjdp      dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
128577298Sobrien    }				/* if we needed to grow  */
128633965Sjdp
128733965Sjdp  dollar_labels[dollar_label_count] = label;
128833965Sjdp  dollar_label_instances[dollar_label_count] = 1;
128933965Sjdp  dollar_label_defines[dollar_label_count] = 1;
129033965Sjdp  ++dollar_label_count;
129133965Sjdp}
129233965Sjdp
129377298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
129433965Sjdp
129577298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Am"
129677298Sobrien   where n is the label number and m is the instance number. "L" makes
129777298Sobrien   it a label discarded unless debugging and "^A"('\1') ensures no
129877298Sobrien   ordinary symbol SHOULD get the same name as a local label
129977298Sobrien   symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
130077298Sobrien
130177298Sobrien   fb labels get the same treatment, except that ^B is used in place
130277298Sobrien   of ^A.  */
130377298Sobrien
130477298Sobrienchar *				/* Return local label name.  */
130533965Sjdpdollar_label_name (n, augend)
130677298Sobrien     register long n;		/* we just saw "n$:" : n a number.  */
130777298Sobrien     register int augend;	/* 0 for current instance, 1 for new instance.  */
130833965Sjdp{
130933965Sjdp  long i;
131077298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
131133965Sjdp  static char symbol_name_build[24];
131233965Sjdp  register char *p;
131333965Sjdp  register char *q;
131477298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
131533965Sjdp
131633965Sjdp  know (n >= 0);
131733965Sjdp  know (augend == 0 || augend == 1);
131833965Sjdp  p = symbol_name_build;
131960484Sobrien#ifdef LOCAL_LABEL_PREFIX
132060484Sobrien  *p++ = LOCAL_LABEL_PREFIX;
132160484Sobrien#endif
132233965Sjdp  *p++ = 'L';
132333965Sjdp
132477298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
132577298Sobrien  /* Label number.  */
132633965Sjdp  q = symbol_name_temporary;
132733965Sjdp  for (*q++ = 0, i = n; i; ++q)
132833965Sjdp    {
132933965Sjdp      *q = i % 10 + '0';
133033965Sjdp      i /= 10;
133133965Sjdp    }
133233965Sjdp  while ((*p = *--q) != '\0')
133333965Sjdp    ++p;
133433965Sjdp
133577298Sobrien  *p++ = DOLLAR_LABEL_CHAR;		/* ^A  */
133633965Sjdp
133777298Sobrien  /* Instance number.  */
133833965Sjdp  q = symbol_name_temporary;
133933965Sjdp  for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
134033965Sjdp    {
134133965Sjdp      *q = i % 10 + '0';
134233965Sjdp      i /= 10;
134333965Sjdp    }
134433965Sjdp  while ((*p++ = *--q) != '\0');;
134533965Sjdp
134677298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
134733965Sjdp  return symbol_name_build;
134833965Sjdp}
134933965Sjdp
135077298Sobrien/* Sombody else's idea of local labels. They are made by "n:" where n
135177298Sobrien   is any decimal digit. Refer to them with
135277298Sobrien    "nb" for previous (backward) n:
135377298Sobrien   or "nf" for next (forward) n:.
135433965Sjdp
135577298Sobrien   We do a little better and let n be any number, not just a single digit, but
135677298Sobrien   since the other guy's assembler only does ten, we treat the first ten
135777298Sobrien   specially.
135877298Sobrien
135977298Sobrien   Like someone else's assembler, we have one set of local label counters for
136077298Sobrien   entire assembly, not one set per (sub)segment like in most assemblers. This
136177298Sobrien   implies that one can refer to a label in another segment, and indeed some
136277298Sobrien   crufty compilers have done just that.
136377298Sobrien
136477298Sobrien   Since there could be a LOT of these things, treat them as a sparse
136577298Sobrien   array.  */
136677298Sobrien
136733965Sjdp#define FB_LABEL_SPECIAL (10)
136833965Sjdp
136933965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL];
137033965Sjdpstatic long *fb_labels;
137133965Sjdpstatic long *fb_label_instances;
137233965Sjdpstatic long fb_label_count;
137333965Sjdpstatic long fb_label_max;
137433965Sjdp
137577298Sobrien/* This must be more than FB_LABEL_SPECIAL.  */
137633965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
137733965Sjdp
137877298Sobrienstatic void
137933965Sjdpfb_label_init ()
138033965Sjdp{
138133965Sjdp  memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
138277298Sobrien}
138333965Sjdp
138477298Sobrien/* Add one to the instance number of this fb label.  */
138577298Sobrien
138677298Sobrienvoid
138733965Sjdpfb_label_instance_inc (label)
138833965Sjdp     long label;
138933965Sjdp{
139033965Sjdp  long *i;
139133965Sjdp
139233965Sjdp  if (label < FB_LABEL_SPECIAL)
139333965Sjdp    {
139433965Sjdp      ++fb_low_counter[label];
139533965Sjdp      return;
139633965Sjdp    }
139733965Sjdp
139833965Sjdp  if (fb_labels != NULL)
139933965Sjdp    {
140033965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
140133965Sjdp	   i < fb_labels + fb_label_count; ++i)
140233965Sjdp	{
140333965Sjdp	  if (*i == label)
140433965Sjdp	    {
140533965Sjdp	      ++fb_label_instances[i - fb_labels];
140633965Sjdp	      return;
140777298Sobrien	    }			/* if we find it  */
140877298Sobrien	}			/* for each existing label  */
140933965Sjdp    }
141033965Sjdp
141177298Sobrien  /* If we get to here, we don't have label listed yet.  */
141233965Sjdp
141333965Sjdp  if (fb_labels == NULL)
141433965Sjdp    {
141533965Sjdp      fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
141633965Sjdp      fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
141733965Sjdp      fb_label_max = FB_LABEL_BUMP_BY;
141833965Sjdp      fb_label_count = FB_LABEL_SPECIAL;
141933965Sjdp
142033965Sjdp    }
142133965Sjdp  else if (fb_label_count == fb_label_max)
142233965Sjdp    {
142333965Sjdp      fb_label_max += FB_LABEL_BUMP_BY;
142433965Sjdp      fb_labels = (long *) xrealloc ((char *) fb_labels,
142533965Sjdp				     fb_label_max * sizeof (long));
142633965Sjdp      fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
142733965Sjdp					      fb_label_max * sizeof (long));
142877298Sobrien    }				/* if we needed to grow  */
142933965Sjdp
143033965Sjdp  fb_labels[fb_label_count] = label;
143133965Sjdp  fb_label_instances[fb_label_count] = 1;
143233965Sjdp  ++fb_label_count;
143333965Sjdp}
143433965Sjdp
143577298Sobrienstatic long
143633965Sjdpfb_label_instance (label)
143733965Sjdp     long label;
143833965Sjdp{
143933965Sjdp  long *i;
144033965Sjdp
144133965Sjdp  if (label < FB_LABEL_SPECIAL)
144233965Sjdp    {
144333965Sjdp      return (fb_low_counter[label]);
144433965Sjdp    }
144533965Sjdp
144633965Sjdp  if (fb_labels != NULL)
144733965Sjdp    {
144833965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
144933965Sjdp	   i < fb_labels + fb_label_count; ++i)
145033965Sjdp	{
145133965Sjdp	  if (*i == label)
145233965Sjdp	    {
145333965Sjdp	      return (fb_label_instances[i - fb_labels]);
145477298Sobrien	    }			/* if we find it  */
145577298Sobrien	}			/* for each existing label  */
145633965Sjdp    }
145733965Sjdp
145833965Sjdp  /* We didn't find the label, so this must be a reference to the
145933965Sjdp     first instance.  */
146033965Sjdp  return 0;
146133965Sjdp}
146233965Sjdp
146377298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
146433965Sjdp
146577298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Bm"
146677298Sobrien   where n is the label number and m is the instance number. "L" makes
146777298Sobrien   it a label discarded unless debugging and "^B"('\2') ensures no
146877298Sobrien   ordinary symbol SHOULD get the same name as a local label
146977298Sobrien   symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
147077298Sobrien
147177298Sobrien   dollar labels get the same treatment, except that ^A is used in
147277298Sobrien   place of ^B.  */
147377298Sobrien
147477298Sobrienchar *				/* Return local label name.  */
147533965Sjdpfb_label_name (n, augend)
147677298Sobrien     long n;			/* We just saw "n:", "nf" or "nb" : n a number.  */
147777298Sobrien     long augend;		/* 0 for nb, 1 for n:, nf.  */
147833965Sjdp{
147933965Sjdp  long i;
148077298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
148133965Sjdp  static char symbol_name_build[24];
148233965Sjdp  register char *p;
148333965Sjdp  register char *q;
148477298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
148533965Sjdp
148633965Sjdp  know (n >= 0);
148733965Sjdp  know (augend == 0 || augend == 1);
148833965Sjdp  p = symbol_name_build;
148977298Sobrien#ifdef LOCAL_LABEL_PREFIX
149077298Sobrien  *p++ = LOCAL_LABEL_PREFIX;
149177298Sobrien#endif
149233965Sjdp  *p++ = 'L';
149333965Sjdp
149477298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
149577298Sobrien  /* Label number.  */
149633965Sjdp  q = symbol_name_temporary;
149733965Sjdp  for (*q++ = 0, i = n; i; ++q)
149833965Sjdp    {
149933965Sjdp      *q = i % 10 + '0';
150033965Sjdp      i /= 10;
150133965Sjdp    }
150233965Sjdp  while ((*p = *--q) != '\0')
150333965Sjdp    ++p;
150433965Sjdp
150577298Sobrien  *p++ = LOCAL_LABEL_CHAR;		/* ^B  */
150633965Sjdp
150777298Sobrien  /* Instance number.  */
150833965Sjdp  q = symbol_name_temporary;
150933965Sjdp  for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
151033965Sjdp    {
151133965Sjdp      *q = i % 10 + '0';
151233965Sjdp      i /= 10;
151333965Sjdp    }
151433965Sjdp  while ((*p++ = *--q) != '\0');;
151533965Sjdp
151677298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
151733965Sjdp  return (symbol_name_build);
151877298Sobrien}
151933965Sjdp
152077298Sobrien/* Decode name that may have been generated by foo_label_name() above.
152177298Sobrien   If the name wasn't generated by foo_label_name(), then return it
152277298Sobrien   unaltered.  This is used for error messages.  */
152333965Sjdp
152433965Sjdpchar *
152533965Sjdpdecode_local_label_name (s)
152633965Sjdp     char *s;
152733965Sjdp{
152833965Sjdp  char *p;
152933965Sjdp  char *symbol_decode;
153033965Sjdp  int label_number;
153133965Sjdp  int instance_number;
153233965Sjdp  char *type;
153360484Sobrien  const char *message_format = _("\"%d\" (instance number %d of a %s label)");
153477298Sobrien  int index = 0;
153533965Sjdp
153677298Sobrien#ifdef LOCAL_LABEL_PREFIX
153777298Sobrien  if (s[index] == LOCAL_LABEL_PREFIX)
153877298Sobrien    ++index;
153977298Sobrien#endif
154077298Sobrien
154177298Sobrien  if (s[index] != 'L')
154233965Sjdp    return s;
154333965Sjdp
154477298Sobrien  for (label_number = 0, p = s + index + 1; isdigit ((unsigned char) *p); ++p)
154533965Sjdp    label_number = (10 * label_number) + *p - '0';
154633965Sjdp
154777298Sobrien  if (*p == DOLLAR_LABEL_CHAR)
154833965Sjdp    type = "dollar";
154977298Sobrien  else if (*p == LOCAL_LABEL_CHAR)
155033965Sjdp    type = "fb";
155133965Sjdp  else
155233965Sjdp    return s;
155333965Sjdp
155438889Sjdp  for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
155533965Sjdp    instance_number = (10 * instance_number) + *p - '0';
155633965Sjdp
155733965Sjdp  symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
155833965Sjdp  sprintf (symbol_decode, message_format, label_number, instance_number, type);
155933965Sjdp
156033965Sjdp  return symbol_decode;
156133965Sjdp}
156233965Sjdp
156333965Sjdp/* Get the value of a symbol.  */
156433965Sjdp
156533965SjdpvalueT
156633965SjdpS_GET_VALUE (s)
156733965Sjdp     symbolS *s;
156833965Sjdp{
156960484Sobrien#ifdef BFD_ASSEMBLER
157060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
157160484Sobrien    return ((struct local_symbol *) s)->lsy_offset;
157260484Sobrien#endif
157360484Sobrien
157438889Sjdp  if (!s->sy_resolved && s->sy_value.X_op != O_constant)
157538889Sjdp    resolve_symbol_value (s, 1);
157633965Sjdp  if (s->sy_value.X_op != O_constant)
157733965Sjdp    {
157833965Sjdp      static symbolS *recur;
157933965Sjdp
158033965Sjdp      /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
158133965Sjdp         may call S_GET_VALUE.  We use a static symbol to avoid the
158233965Sjdp         immediate recursion.  */
158333965Sjdp      if (recur == s)
158433965Sjdp	return (valueT) s->sy_value.X_add_number;
158533965Sjdp      recur = s;
158633965Sjdp      if (! s->sy_resolved
158733965Sjdp	  || s->sy_value.X_op != O_symbol
158833965Sjdp	  || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
158960484Sobrien	as_bad (_("Attempt to get value of unresolved symbol %s"),
159033965Sjdp		S_GET_NAME (s));
159133965Sjdp      recur = NULL;
159233965Sjdp    }
159333965Sjdp  return (valueT) s->sy_value.X_add_number;
159433965Sjdp}
159533965Sjdp
159633965Sjdp/* Set the value of a symbol.  */
159733965Sjdp
159833965Sjdpvoid
159933965SjdpS_SET_VALUE (s, val)
160033965Sjdp     symbolS *s;
160133965Sjdp     valueT val;
160233965Sjdp{
160360484Sobrien#ifdef BFD_ASSEMBLER
160460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
160560484Sobrien    {
160660484Sobrien      ((struct local_symbol *) s)->lsy_offset = val;
160760484Sobrien      return;
160860484Sobrien    }
160960484Sobrien#endif
161060484Sobrien
161133965Sjdp  s->sy_value.X_op = O_constant;
161233965Sjdp  s->sy_value.X_add_number = (offsetT) val;
161333965Sjdp  s->sy_value.X_unsigned = 0;
161433965Sjdp}
161533965Sjdp
161633965Sjdpvoid
161733965Sjdpcopy_symbol_attributes (dest, src)
161833965Sjdp     symbolS *dest, *src;
161933965Sjdp{
162060484Sobrien  if (LOCAL_SYMBOL_CHECK (dest))
162160484Sobrien    dest = local_symbol_convert ((struct local_symbol *) dest);
162260484Sobrien  if (LOCAL_SYMBOL_CHECK (src))
162360484Sobrien    src = local_symbol_convert ((struct local_symbol *) src);
162460484Sobrien
162533965Sjdp#ifdef BFD_ASSEMBLER
162633965Sjdp  /* In an expression, transfer the settings of these flags.
162733965Sjdp     The user can override later, of course.  */
162838889Sjdp#define COPIED_SYMFLAGS	(BSF_FUNCTION | BSF_OBJECT)
162933965Sjdp  dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
163033965Sjdp#endif
163133965Sjdp
163233965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
163333965Sjdp  OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
163433965Sjdp#endif
163533965Sjdp}
163633965Sjdp
163733965Sjdp#ifdef BFD_ASSEMBLER
163833965Sjdp
163933965Sjdpint
164060484SobrienS_IS_FUNCTION (s)
164160484Sobrien     symbolS *s;
164260484Sobrien{
164360484Sobrien  flagword flags;
164460484Sobrien
164560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
164660484Sobrien    return 0;
164760484Sobrien
164860484Sobrien  flags = s->bsym->flags;
164960484Sobrien
165060484Sobrien  return (flags & BSF_FUNCTION) != 0;
165160484Sobrien}
165260484Sobrien
165360484Sobrienint
165433965SjdpS_IS_EXTERNAL (s)
165533965Sjdp     symbolS *s;
165633965Sjdp{
165760484Sobrien  flagword flags;
165833965Sjdp
165960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
166060484Sobrien    return 0;
166160484Sobrien
166260484Sobrien  flags = s->bsym->flags;
166360484Sobrien
166477298Sobrien  /* Sanity check.  */
166538889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
166633965Sjdp    abort ();
166733965Sjdp
166833965Sjdp  return (flags & BSF_GLOBAL) != 0;
166933965Sjdp}
167033965Sjdp
167133965Sjdpint
167233965SjdpS_IS_WEAK (s)
167333965Sjdp     symbolS *s;
167433965Sjdp{
167560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
167660484Sobrien    return 0;
167733965Sjdp  return (s->bsym->flags & BSF_WEAK) != 0;
167833965Sjdp}
167933965Sjdp
168033965Sjdpint
168133965SjdpS_IS_COMMON (s)
168233965Sjdp     symbolS *s;
168333965Sjdp{
168460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
168560484Sobrien    return 0;
168633965Sjdp  return bfd_is_com_section (s->bsym->section);
168733965Sjdp}
168833965Sjdp
168933965Sjdpint
169033965SjdpS_IS_DEFINED (s)
169133965Sjdp     symbolS *s;
169233965Sjdp{
169360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
169460484Sobrien    return ((struct local_symbol *) s)->lsy_section != undefined_section;
169533965Sjdp  return s->bsym->section != undefined_section;
169633965Sjdp}
169733965Sjdp
169833965Sjdpint
169933965SjdpS_IS_DEBUG (s)
170033965Sjdp     symbolS *s;
170133965Sjdp{
170260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
170360484Sobrien    return 0;
170433965Sjdp  if (s->bsym->flags & BSF_DEBUGGING)
170533965Sjdp    return 1;
170633965Sjdp  return 0;
170733965Sjdp}
170833965Sjdp
170933965Sjdpint
171033965SjdpS_IS_LOCAL (s)
171133965Sjdp     symbolS *s;
171233965Sjdp{
171360484Sobrien  flagword flags;
171433965Sjdp  const char *name;
171533965Sjdp
171660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
171760484Sobrien    return 1;
171860484Sobrien
171960484Sobrien  flags = s->bsym->flags;
172060484Sobrien
172177298Sobrien  /* Sanity check.  */
172238889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
172333965Sjdp    abort ();
172433965Sjdp
172533965Sjdp  if (bfd_get_section (s->bsym) == reg_section)
172633965Sjdp    return 1;
172733965Sjdp
172838889Sjdp  if (flag_strip_local_absolute
172938889Sjdp      && (flags & BSF_GLOBAL) == 0
173038889Sjdp      && bfd_get_section (s->bsym) == absolute_section)
173138889Sjdp    return 1;
173238889Sjdp
173333965Sjdp  name = S_GET_NAME (s);
173433965Sjdp  return (name != NULL
173533965Sjdp	  && ! S_IS_DEBUG (s)
173677298Sobrien	  && (strchr (name, DOLLAR_LABEL_CHAR)
173777298Sobrien	      || strchr (name, LOCAL_LABEL_CHAR)
173833965Sjdp	      || (! flag_keep_locals
173933965Sjdp		  && (bfd_is_local_label (stdoutput, s->bsym)
174033965Sjdp		      || (flag_mri
174133965Sjdp			  && name[0] == '?'
174233965Sjdp			  && name[1] == '?')))));
174333965Sjdp}
174433965Sjdp
174533965Sjdpint
174633965SjdpS_IS_EXTERN (s)
174733965Sjdp     symbolS *s;
174833965Sjdp{
174933965Sjdp  return S_IS_EXTERNAL (s);
175033965Sjdp}
175133965Sjdp
175233965Sjdpint
175333965SjdpS_IS_STABD (s)
175433965Sjdp     symbolS *s;
175533965Sjdp{
175633965Sjdp  return S_GET_NAME (s) == 0;
175733965Sjdp}
175833965Sjdp
175933965SjdpCONST char *
176033965SjdpS_GET_NAME (s)
176133965Sjdp     symbolS *s;
176233965Sjdp{
176360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
176460484Sobrien    return ((struct local_symbol *) s)->lsy_name;
176533965Sjdp  return s->bsym->name;
176633965Sjdp}
176733965Sjdp
176833965SjdpsegT
176933965SjdpS_GET_SEGMENT (s)
177033965Sjdp     symbolS *s;
177133965Sjdp{
177260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
177360484Sobrien    return ((struct local_symbol *) s)->lsy_section;
177433965Sjdp  return s->bsym->section;
177533965Sjdp}
177633965Sjdp
177733965Sjdpvoid
177833965SjdpS_SET_SEGMENT (s, seg)
177933965Sjdp     symbolS *s;
178033965Sjdp     segT seg;
178133965Sjdp{
178238889Sjdp  /* Don't reassign section symbols.  The direct reason is to prevent seg
178338889Sjdp     faults assigning back to const global symbols such as *ABS*, but it
178438889Sjdp     shouldn't happen anyway.  */
178538889Sjdp
178660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
178760484Sobrien    {
178860484Sobrien      if (seg == reg_section)
178960484Sobrien	s = local_symbol_convert ((struct local_symbol *) s);
179060484Sobrien      else
179160484Sobrien	{
179260484Sobrien	  ((struct local_symbol *) s)->lsy_section = seg;
179360484Sobrien	  return;
179460484Sobrien	}
179560484Sobrien    }
179660484Sobrien
179738889Sjdp  if (s->bsym->flags & BSF_SECTION_SYM)
179838889Sjdp    {
179938889Sjdp      if (s->bsym->section != seg)
180077298Sobrien	abort ();
180138889Sjdp    }
180238889Sjdp  else
180338889Sjdp    s->bsym->section = seg;
180433965Sjdp}
180533965Sjdp
180633965Sjdpvoid
180733965SjdpS_SET_EXTERNAL (s)
180833965Sjdp     symbolS *s;
180933965Sjdp{
181060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
181160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
181233965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
181333965Sjdp    {
181433965Sjdp      /* Let .weak override .global.  */
181533965Sjdp      return;
181633965Sjdp    }
181733965Sjdp  s->bsym->flags |= BSF_GLOBAL;
181877298Sobrien  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
181933965Sjdp}
182033965Sjdp
182133965Sjdpvoid
182233965SjdpS_CLEAR_EXTERNAL (s)
182333965Sjdp     symbolS *s;
182433965Sjdp{
182560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
182660484Sobrien    return;
182733965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
182833965Sjdp    {
182933965Sjdp      /* Let .weak override.  */
183033965Sjdp      return;
183133965Sjdp    }
183233965Sjdp  s->bsym->flags |= BSF_LOCAL;
183377298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
183433965Sjdp}
183533965Sjdp
183633965Sjdpvoid
183733965SjdpS_SET_WEAK (s)
183833965Sjdp     symbolS *s;
183933965Sjdp{
184060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
184160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
184233965Sjdp  s->bsym->flags |= BSF_WEAK;
184377298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
184433965Sjdp}
184533965Sjdp
184633965Sjdpvoid
184733965SjdpS_SET_NAME (s, name)
184833965Sjdp     symbolS *s;
184933965Sjdp     char *name;
185033965Sjdp{
185160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
185260484Sobrien    {
185360484Sobrien      ((struct local_symbol *) s)->lsy_name = name;
185460484Sobrien      return;
185560484Sobrien    }
185633965Sjdp  s->bsym->name = name;
185733965Sjdp}
185833965Sjdp#endif /* BFD_ASSEMBLER */
185933965Sjdp
186060484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS
186160484Sobrien
186260484Sobrien/* Return the previous symbol in a chain.  */
186360484Sobrien
186460484SobriensymbolS *
186560484Sobriensymbol_previous (s)
186660484Sobrien     symbolS *s;
186760484Sobrien{
186860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
186960484Sobrien    abort ();
187060484Sobrien  return s->sy_previous;
187160484Sobrien}
187260484Sobrien
187360484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */
187460484Sobrien
187560484Sobrien/* Return the next symbol in a chain.  */
187660484Sobrien
187760484SobriensymbolS *
187860484Sobriensymbol_next (s)
187960484Sobrien     symbolS *s;
188060484Sobrien{
188160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
188260484Sobrien    abort ();
188360484Sobrien  return s->sy_next;
188460484Sobrien}
188560484Sobrien
188660484Sobrien/* Return a pointer to the value of a symbol as an expression.  */
188760484Sobrien
188860484SobrienexpressionS *
188960484Sobriensymbol_get_value_expression (s)
189060484Sobrien     symbolS *s;
189160484Sobrien{
189260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
189360484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
189460484Sobrien  return &s->sy_value;
189560484Sobrien}
189660484Sobrien
189760484Sobrien/* Set the value of a symbol to an expression.  */
189860484Sobrien
189933965Sjdpvoid
190060484Sobriensymbol_set_value_expression (s, exp)
190160484Sobrien     symbolS *s;
190260484Sobrien     const expressionS *exp;
190360484Sobrien{
190460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
190560484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
190660484Sobrien  s->sy_value = *exp;
190760484Sobrien}
190860484Sobrien
190960484Sobrien/* Set the frag of a symbol.  */
191060484Sobrien
191160484Sobrienvoid
191260484Sobriensymbol_set_frag (s, f)
191360484Sobrien     symbolS *s;
191460484Sobrien     fragS *f;
191560484Sobrien{
191660484Sobrien#ifdef BFD_ASSEMBLER
191760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
191860484Sobrien    {
191960484Sobrien      local_symbol_set_frag ((struct local_symbol *) s, f);
192060484Sobrien      return;
192160484Sobrien    }
192260484Sobrien#endif
192360484Sobrien  s->sy_frag = f;
192460484Sobrien}
192560484Sobrien
192660484Sobrien/* Return the frag of a symbol.  */
192760484Sobrien
192860484SobrienfragS *
192960484Sobriensymbol_get_frag (s)
193060484Sobrien     symbolS *s;
193160484Sobrien{
193260484Sobrien#ifdef BFD_ASSEMBLER
193360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
193460484Sobrien    return local_symbol_get_frag ((struct local_symbol *) s);
193560484Sobrien#endif
193660484Sobrien  return s->sy_frag;
193760484Sobrien}
193860484Sobrien
193960484Sobrien/* Mark a symbol as having been used.  */
194060484Sobrien
194160484Sobrienvoid
194260484Sobriensymbol_mark_used (s)
194360484Sobrien     symbolS *s;
194460484Sobrien{
194560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
194660484Sobrien    return;
194760484Sobrien  s->sy_used = 1;
194860484Sobrien}
194960484Sobrien
195060484Sobrien/* Clear the mark of whether a symbol has been used.  */
195160484Sobrien
195260484Sobrienvoid
195360484Sobriensymbol_clear_used (s)
195460484Sobrien     symbolS *s;
195560484Sobrien{
195660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
195760484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
195860484Sobrien  s->sy_used = 0;
195960484Sobrien}
196060484Sobrien
196160484Sobrien/* Return whether a symbol has been used.  */
196260484Sobrien
196360484Sobrienint
196460484Sobriensymbol_used_p (s)
196560484Sobrien     symbolS *s;
196660484Sobrien{
196760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
196860484Sobrien    return 1;
196960484Sobrien  return s->sy_used;
197060484Sobrien}
197160484Sobrien
197260484Sobrien/* Mark a symbol as having been used in a reloc.  */
197360484Sobrien
197460484Sobrienvoid
197560484Sobriensymbol_mark_used_in_reloc (s)
197660484Sobrien     symbolS *s;
197760484Sobrien{
197860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
197960484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
198060484Sobrien  s->sy_used_in_reloc = 1;
198160484Sobrien}
198260484Sobrien
198360484Sobrien/* Clear the mark of whether a symbol has been used in a reloc.  */
198460484Sobrien
198560484Sobrienvoid
198660484Sobriensymbol_clear_used_in_reloc (s)
198760484Sobrien     symbolS *s;
198860484Sobrien{
198960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
199060484Sobrien    return;
199160484Sobrien  s->sy_used_in_reloc = 0;
199260484Sobrien}
199360484Sobrien
199460484Sobrien/* Return whether a symbol has been used in a reloc.  */
199560484Sobrien
199660484Sobrienint
199760484Sobriensymbol_used_in_reloc_p (s)
199860484Sobrien     symbolS *s;
199960484Sobrien{
200060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
200160484Sobrien    return 0;
200260484Sobrien  return s->sy_used_in_reloc;
200360484Sobrien}
200460484Sobrien
200560484Sobrien/* Mark a symbol as an MRI common symbol.  */
200660484Sobrien
200760484Sobrienvoid
200860484Sobriensymbol_mark_mri_common (s)
200960484Sobrien     symbolS *s;
201060484Sobrien{
201160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
201260484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
201360484Sobrien  s->sy_mri_common = 1;
201460484Sobrien}
201560484Sobrien
201660484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol.  */
201760484Sobrien
201860484Sobrienvoid
201960484Sobriensymbol_clear_mri_common (s)
202060484Sobrien     symbolS *s;
202160484Sobrien{
202260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
202360484Sobrien    return;
202460484Sobrien  s->sy_mri_common = 0;
202560484Sobrien}
202660484Sobrien
202760484Sobrien/* Return whether a symbol is an MRI common symbol.  */
202860484Sobrien
202960484Sobrienint
203060484Sobriensymbol_mri_common_p (s)
203160484Sobrien     symbolS *s;
203260484Sobrien{
203360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
203460484Sobrien    return 0;
203560484Sobrien  return s->sy_mri_common;
203660484Sobrien}
203760484Sobrien
203860484Sobrien/* Mark a symbol as having been written.  */
203960484Sobrien
204060484Sobrienvoid
204160484Sobriensymbol_mark_written (s)
204260484Sobrien     symbolS *s;
204360484Sobrien{
204460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
204560484Sobrien    return;
204660484Sobrien  s->written = 1;
204760484Sobrien}
204860484Sobrien
204960484Sobrien/* Clear the mark of whether a symbol has been written.  */
205060484Sobrien
205160484Sobrienvoid
205260484Sobriensymbol_clear_written (s)
205360484Sobrien     symbolS *s;
205460484Sobrien{
205560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
205660484Sobrien    return;
205760484Sobrien  s->written = 0;
205860484Sobrien}
205960484Sobrien
206060484Sobrien/* Return whether a symbol has been written.  */
206160484Sobrien
206260484Sobrienint
206360484Sobriensymbol_written_p (s)
206460484Sobrien     symbolS *s;
206560484Sobrien{
206660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
206760484Sobrien    return 0;
206860484Sobrien  return s->written;
206960484Sobrien}
207060484Sobrien
207160484Sobrien/* Mark a symbol has having been resolved.  */
207260484Sobrien
207360484Sobrienvoid
207460484Sobriensymbol_mark_resolved (s)
207560484Sobrien     symbolS *s;
207660484Sobrien{
207760484Sobrien#ifdef BFD_ASSEMBLER
207860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
207960484Sobrien    {
208060484Sobrien      local_symbol_mark_resolved ((struct local_symbol *) s);
208160484Sobrien      return;
208260484Sobrien    }
208360484Sobrien#endif
208460484Sobrien  s->sy_resolved = 1;
208560484Sobrien}
208660484Sobrien
208760484Sobrien/* Return whether a symbol has been resolved.  */
208860484Sobrien
208960484Sobrienint
209060484Sobriensymbol_resolved_p (s)
209160484Sobrien     symbolS *s;
209260484Sobrien{
209360484Sobrien#ifdef BFD_ASSEMBLER
209460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
209560484Sobrien    return local_symbol_resolved_p ((struct local_symbol *) s);
209660484Sobrien#endif
209760484Sobrien  return s->sy_resolved;
209860484Sobrien}
209960484Sobrien
210060484Sobrien/* Return whether a symbol is a section symbol.  */
210160484Sobrien
210260484Sobrienint
210360484Sobriensymbol_section_p (s)
210460484Sobrien     symbolS *s ATTRIBUTE_UNUSED;
210560484Sobrien{
210660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
210760484Sobrien    return 0;
210860484Sobrien#ifdef BFD_ASSEMBLER
210960484Sobrien  return (s->bsym->flags & BSF_SECTION_SYM) != 0;
211060484Sobrien#else
211177298Sobrien  /* FIXME.  */
211260484Sobrien  return 0;
211360484Sobrien#endif
211460484Sobrien}
211560484Sobrien
211660484Sobrien/* Return whether a symbol is equated to another symbol.  */
211760484Sobrien
211860484Sobrienint
211960484Sobriensymbol_equated_p (s)
212060484Sobrien     symbolS *s;
212160484Sobrien{
212260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
212360484Sobrien    return 0;
212460484Sobrien  return s->sy_value.X_op == O_symbol;
212560484Sobrien}
212660484Sobrien
212760484Sobrien/* Return whether a symbol has a constant value.  */
212860484Sobrien
212960484Sobrienint
213060484Sobriensymbol_constant_p (s)
213160484Sobrien     symbolS *s;
213260484Sobrien{
213360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
213460484Sobrien    return 1;
213560484Sobrien  return s->sy_value.X_op == O_constant;
213660484Sobrien}
213760484Sobrien
213860484Sobrien#ifdef BFD_ASSEMBLER
213960484Sobrien
214060484Sobrien/* Return the BFD symbol for a symbol.  */
214160484Sobrien
214260484Sobrienasymbol *
214360484Sobriensymbol_get_bfdsym (s)
214460484Sobrien     symbolS *s;
214560484Sobrien{
214660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
214760484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
214860484Sobrien  return s->bsym;
214960484Sobrien}
215060484Sobrien
215160484Sobrien/* Set the BFD symbol for a symbol.  */
215260484Sobrien
215360484Sobrienvoid
215460484Sobriensymbol_set_bfdsym (s, bsym)
215560484Sobrien     symbolS *s;
215660484Sobrien     asymbol *bsym;
215760484Sobrien{
215860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
215960484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
216060484Sobrien  s->bsym = bsym;
216160484Sobrien}
216260484Sobrien
216360484Sobrien#endif /* BFD_ASSEMBLER */
216460484Sobrien
216560484Sobrien#ifdef OBJ_SYMFIELD_TYPE
216660484Sobrien
216760484Sobrien/* Get a pointer to the object format information for a symbol.  */
216860484Sobrien
216960484SobrienOBJ_SYMFIELD_TYPE *
217060484Sobriensymbol_get_obj (s)
217160484Sobrien     symbolS *s;
217260484Sobrien{
217360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
217460484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
217560484Sobrien  return &s->sy_obj;
217660484Sobrien}
217760484Sobrien
217860484Sobrien/* Set the object format information for a symbol.  */
217960484Sobrien
218060484Sobrienvoid
218160484Sobriensymbol_set_obj (s, o)
218260484Sobrien     symbolS *s;
218360484Sobrien     OBJ_SYMFIELD_TYPE *o;
218460484Sobrien{
218560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
218660484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
218760484Sobrien  s->sy_obj = *o;
218860484Sobrien}
218960484Sobrien
219060484Sobrien#endif /* OBJ_SYMFIELD_TYPE */
219160484Sobrien
219260484Sobrien#ifdef TC_SYMFIELD_TYPE
219360484Sobrien
219460484Sobrien/* Get a pointer to the processor information for a symbol.  */
219560484Sobrien
219660484SobrienTC_SYMFIELD_TYPE *
219760484Sobriensymbol_get_tc (s)
219860484Sobrien     symbolS *s;
219960484Sobrien{
220060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
220160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
220260484Sobrien  return &s->sy_tc;
220360484Sobrien}
220460484Sobrien
220560484Sobrien/* Set the processor information for a symbol.  */
220660484Sobrien
220760484Sobrienvoid
220860484Sobriensymbol_set_tc (s, o)
220960484Sobrien     symbolS *s;
221060484Sobrien     TC_SYMFIELD_TYPE *o;
221160484Sobrien{
221260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
221360484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
221460484Sobrien  s->sy_tc = *o;
221560484Sobrien}
221660484Sobrien
221760484Sobrien#endif /* TC_SYMFIELD_TYPE */
221860484Sobrien
221960484Sobrienvoid
222033965Sjdpsymbol_begin ()
222133965Sjdp{
222233965Sjdp  symbol_lastP = NULL;
222377298Sobrien  symbol_rootP = NULL;		/* In case we have 0 symbols (!!)  */
222433965Sjdp  sy_hash = hash_new ();
222560484Sobrien#ifdef BFD_ASSEMBLER
222660484Sobrien  local_hash = hash_new ();
222760484Sobrien#endif
222833965Sjdp
222933965Sjdp  memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
223033965Sjdp#ifdef BFD_ASSEMBLER
223133965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
223233965Sjdp  abs_symbol.bsym = bfd_abs_section.symbol;
223333965Sjdp#endif
223433965Sjdp#else
223577298Sobrien  /* Can't initialise a union. Sigh.  */
223633965Sjdp  S_SET_SEGMENT (&abs_symbol, absolute_section);
223733965Sjdp#endif
223833965Sjdp  abs_symbol.sy_value.X_op = O_constant;
223933965Sjdp  abs_symbol.sy_frag = &zero_address_frag;
224033965Sjdp
224133965Sjdp  if (LOCAL_LABELS_FB)
224233965Sjdp    fb_label_init ();
224333965Sjdp}
224433965Sjdp
224533965Sjdpint indent_level;
224633965Sjdp
224760484Sobrien/* Maximum indent level.
224860484Sobrien   Available for modification inside a gdb session.  */
224960484Sobrienint max_indent_level = 8;
225060484Sobrien
225133965Sjdp#if 0
225233965Sjdp
225333965Sjdpstatic void
225433965Sjdpindent ()
225533965Sjdp{
225633965Sjdp  printf ("%*s", indent_level * 4, "");
225733965Sjdp}
225833965Sjdp
225933965Sjdp#endif
226033965Sjdp
226133965Sjdpvoid
226233965Sjdpprint_symbol_value_1 (file, sym)
226333965Sjdp     FILE *file;
226433965Sjdp     symbolS *sym;
226533965Sjdp{
226633965Sjdp  const char *name = S_GET_NAME (sym);
226733965Sjdp  if (!name || !name[0])
226833965Sjdp    name = "(unnamed)";
226933965Sjdp  fprintf (file, "sym %lx %s", (unsigned long) sym, name);
227060484Sobrien
227160484Sobrien  if (LOCAL_SYMBOL_CHECK (sym))
227260484Sobrien    {
227360484Sobrien#ifdef BFD_ASSEMBLER
227460484Sobrien      struct local_symbol *locsym = (struct local_symbol *) sym;
227560484Sobrien      if (local_symbol_get_frag (locsym) != &zero_address_frag
227660484Sobrien	  && local_symbol_get_frag (locsym) != NULL)
227760484Sobrien	fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym));
227860484Sobrien      if (local_symbol_resolved_p (locsym))
227960484Sobrien	fprintf (file, " resolved");
228060484Sobrien      fprintf (file, " local");
228160484Sobrien#endif
228260484Sobrien    }
228360484Sobrien  else
228460484Sobrien    {
228560484Sobrien      if (sym->sy_frag != &zero_address_frag)
228660484Sobrien	fprintf (file, " frag %lx", (long) sym->sy_frag);
228760484Sobrien      if (sym->written)
228860484Sobrien	fprintf (file, " written");
228960484Sobrien      if (sym->sy_resolved)
229060484Sobrien	fprintf (file, " resolved");
229160484Sobrien      else if (sym->sy_resolving)
229260484Sobrien	fprintf (file, " resolving");
229360484Sobrien      if (sym->sy_used_in_reloc)
229460484Sobrien	fprintf (file, " used-in-reloc");
229560484Sobrien      if (sym->sy_used)
229660484Sobrien	fprintf (file, " used");
229760484Sobrien      if (S_IS_LOCAL (sym))
229860484Sobrien	fprintf (file, " local");
229960484Sobrien      if (S_IS_EXTERN (sym))
230060484Sobrien	fprintf (file, " extern");
230160484Sobrien      if (S_IS_DEBUG (sym))
230260484Sobrien	fprintf (file, " debug");
230360484Sobrien      if (S_IS_DEFINED (sym))
230460484Sobrien	fprintf (file, " defined");
230560484Sobrien    }
230633965Sjdp  fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
230760484Sobrien  if (symbol_resolved_p (sym))
230833965Sjdp    {
230933965Sjdp      segT s = S_GET_SEGMENT (sym);
231033965Sjdp
231133965Sjdp      if (s != undefined_section
231233965Sjdp          && s != expr_section)
231333965Sjdp	fprintf (file, " %lx", (long) S_GET_VALUE (sym));
231433965Sjdp    }
231560484Sobrien  else if (indent_level < max_indent_level
231660484Sobrien	   && S_GET_SEGMENT (sym) != undefined_section)
231733965Sjdp    {
231833965Sjdp      indent_level++;
231933965Sjdp      fprintf (file, "\n%*s<", indent_level * 4, "");
232060484Sobrien#ifdef BFD_ASSEMBLER
232160484Sobrien      if (LOCAL_SYMBOL_CHECK (sym))
232260484Sobrien	fprintf (file, "constant %lx",
232360484Sobrien		 (long) ((struct local_symbol *) sym)->lsy_offset);
232460484Sobrien      else
232560484Sobrien#endif
232660484Sobrien	print_expr_1 (file, &sym->sy_value);
232733965Sjdp      fprintf (file, ">");
232833965Sjdp      indent_level--;
232933965Sjdp    }
233033965Sjdp  fflush (file);
233133965Sjdp}
233233965Sjdp
233333965Sjdpvoid
233433965Sjdpprint_symbol_value (sym)
233533965Sjdp     symbolS *sym;
233633965Sjdp{
233733965Sjdp  indent_level = 0;
233833965Sjdp  print_symbol_value_1 (stderr, sym);
233933965Sjdp  fprintf (stderr, "\n");
234033965Sjdp}
234133965Sjdp
234260484Sobrienstatic void
234360484Sobrienprint_binary (file, name, exp)
234460484Sobrien     FILE *file;
234577298Sobrien     const char *name;
234660484Sobrien     expressionS *exp;
234760484Sobrien{
234860484Sobrien  indent_level++;
234960484Sobrien  fprintf (file, "%s\n%*s<", name, indent_level * 4, "");
235060484Sobrien  print_symbol_value_1 (file, exp->X_add_symbol);
235160484Sobrien  fprintf (file, ">\n%*s<", indent_level * 4, "");
235260484Sobrien  print_symbol_value_1 (file, exp->X_op_symbol);
235360484Sobrien  fprintf (file, ">");
235460484Sobrien  indent_level--;
235560484Sobrien}
235660484Sobrien
235733965Sjdpvoid
235833965Sjdpprint_expr_1 (file, exp)
235933965Sjdp     FILE *file;
236033965Sjdp     expressionS *exp;
236133965Sjdp{
236233965Sjdp  fprintf (file, "expr %lx ", (long) exp);
236333965Sjdp  switch (exp->X_op)
236433965Sjdp    {
236533965Sjdp    case O_illegal:
236633965Sjdp      fprintf (file, "illegal");
236733965Sjdp      break;
236833965Sjdp    case O_absent:
236933965Sjdp      fprintf (file, "absent");
237033965Sjdp      break;
237133965Sjdp    case O_constant:
237233965Sjdp      fprintf (file, "constant %lx", (long) exp->X_add_number);
237333965Sjdp      break;
237433965Sjdp    case O_symbol:
237533965Sjdp      indent_level++;
237633965Sjdp      fprintf (file, "symbol\n%*s<", indent_level * 4, "");
237733965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
237833965Sjdp      fprintf (file, ">");
237933965Sjdp    maybe_print_addnum:
238033965Sjdp      if (exp->X_add_number)
238133965Sjdp	fprintf (file, "\n%*s%lx", indent_level * 4, "",
238233965Sjdp		 (long) exp->X_add_number);
238333965Sjdp      indent_level--;
238433965Sjdp      break;
238533965Sjdp    case O_register:
238633965Sjdp      fprintf (file, "register #%d", (int) exp->X_add_number);
238733965Sjdp      break;
238833965Sjdp    case O_big:
238933965Sjdp      fprintf (file, "big");
239033965Sjdp      break;
239133965Sjdp    case O_uminus:
239233965Sjdp      fprintf (file, "uminus -<");
239333965Sjdp      indent_level++;
239433965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
239533965Sjdp      fprintf (file, ">");
239633965Sjdp      goto maybe_print_addnum;
239733965Sjdp    case O_bit_not:
239833965Sjdp      fprintf (file, "bit_not");
239933965Sjdp      break;
240033965Sjdp    case O_multiply:
240160484Sobrien      print_binary (file, "multiply", exp);
240233965Sjdp      break;
240333965Sjdp    case O_divide:
240460484Sobrien      print_binary (file, "divide", exp);
240533965Sjdp      break;
240633965Sjdp    case O_modulus:
240760484Sobrien      print_binary (file, "modulus", exp);
240833965Sjdp      break;
240933965Sjdp    case O_left_shift:
241060484Sobrien      print_binary (file, "lshift", exp);
241133965Sjdp      break;
241233965Sjdp    case O_right_shift:
241360484Sobrien      print_binary (file, "rshift", exp);
241433965Sjdp      break;
241533965Sjdp    case O_bit_inclusive_or:
241660484Sobrien      print_binary (file, "bit_ior", exp);
241733965Sjdp      break;
241833965Sjdp    case O_bit_exclusive_or:
241960484Sobrien      print_binary (file, "bit_xor", exp);
242033965Sjdp      break;
242133965Sjdp    case O_bit_and:
242260484Sobrien      print_binary (file, "bit_and", exp);
242333965Sjdp      break;
242433965Sjdp    case O_eq:
242560484Sobrien      print_binary (file, "eq", exp);
242633965Sjdp      break;
242733965Sjdp    case O_ne:
242860484Sobrien      print_binary (file, "ne", exp);
242933965Sjdp      break;
243033965Sjdp    case O_lt:
243160484Sobrien      print_binary (file, "lt", exp);
243233965Sjdp      break;
243333965Sjdp    case O_le:
243460484Sobrien      print_binary (file, "le", exp);
243533965Sjdp      break;
243633965Sjdp    case O_ge:
243760484Sobrien      print_binary (file, "ge", exp);
243833965Sjdp      break;
243933965Sjdp    case O_gt:
244060484Sobrien      print_binary (file, "gt", exp);
244133965Sjdp      break;
244233965Sjdp    case O_logical_and:
244360484Sobrien      print_binary (file, "logical_and", exp);
244433965Sjdp      break;
244533965Sjdp    case O_logical_or:
244660484Sobrien      print_binary (file, "logical_or", exp);
244733965Sjdp      break;
244833965Sjdp    case O_add:
244933965Sjdp      indent_level++;
245033965Sjdp      fprintf (file, "add\n%*s<", indent_level * 4, "");
245133965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
245233965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
245333965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
245433965Sjdp      fprintf (file, ">");
245533965Sjdp      goto maybe_print_addnum;
245633965Sjdp    case O_subtract:
245733965Sjdp      indent_level++;
245833965Sjdp      fprintf (file, "subtract\n%*s<", indent_level * 4, "");
245933965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
246033965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
246133965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
246233965Sjdp      fprintf (file, ">");
246333965Sjdp      goto maybe_print_addnum;
246433965Sjdp    default:
246533965Sjdp      fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
246633965Sjdp      break;
246733965Sjdp    }
246833965Sjdp  fflush (stdout);
246933965Sjdp}
247033965Sjdp
247133965Sjdpvoid
247233965Sjdpprint_expr (exp)
247333965Sjdp     expressionS *exp;
247433965Sjdp{
247533965Sjdp  print_expr_1 (stderr, exp);
247633965Sjdp  fprintf (stderr, "\n");
247733965Sjdp}
247833965Sjdp
247933965Sjdpvoid
248033965Sjdpsymbol_print_statistics (file)
248133965Sjdp     FILE *file;
248233965Sjdp{
248333965Sjdp  hash_print_statistics (file, "symbol table", sy_hash);
248460484Sobrien#ifdef BFD_ASSEMBLER
248560484Sobrien  hash_print_statistics (file, "mini local symbol table", local_hash);
248660484Sobrien  fprintf (file, "%lu mini local symbols created, %lu converted\n",
248760484Sobrien	   local_symbol_count, local_symbol_conversion_count);
248860484Sobrien#endif
248933965Sjdp}
2490