symbols.c revision 130561
133965Sjdp/* symbols.c -symbol table-
278828Sobrien   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3130561Sobrien   1999, 2000, 2001, 2002, 2003
433965Sjdp   Free Software Foundation, Inc.
533965Sjdp
633965Sjdp   This file is part of GAS, the GNU Assembler.
733965Sjdp
833965Sjdp   GAS is free software; you can redistribute it and/or modify
933965Sjdp   it under the terms of the GNU General Public License as published by
1033965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1133965Sjdp   any later version.
1233965Sjdp
1333965Sjdp   GAS is distributed in the hope that it will be useful,
1433965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1533965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965Sjdp   GNU General Public License for more details.
1733965Sjdp
1833965Sjdp   You should have received a copy of the GNU General Public License
1933965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
2033965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2133965Sjdp   02111-1307, USA.  */
2233965Sjdp
2377298Sobrien/* #define DEBUG_SYMS / * to debug symbol list maintenance.  */
2433965Sjdp
2533965Sjdp#include "as.h"
2633965Sjdp
2789857Sobrien#include "safe-ctype.h"
2833965Sjdp#include "obstack.h"		/* For "symbols.h" */
2933965Sjdp#include "subsegs.h"
3033965Sjdp
3160484Sobrien#include "struc-symbol.h"
3260484Sobrien
3333965Sjdp/* This is non-zero if symbols are case sensitive, which is the
3433965Sjdp   default.  */
3533965Sjdpint symbols_case_sensitive = 1;
3633965Sjdp
3733965Sjdp#ifndef WORKING_DOT_WORD
3833965Sjdpextern int new_broken_words;
3933965Sjdp#endif
4033965Sjdp
4133965Sjdp/* symbol-name => struct symbol pointer */
4233965Sjdpstatic struct hash_control *sy_hash;
4333965Sjdp
4460484Sobrien/* Table of local symbols.  */
4560484Sobrienstatic struct hash_control *local_hash;
4660484Sobrien
4777298Sobrien/* Below are commented in "symbols.h".  */
4833965SjdpsymbolS *symbol_rootP;
4933965SjdpsymbolS *symbol_lastP;
5033965SjdpsymbolS abs_symbol;
5133965Sjdp
5233965Sjdp#ifdef DEBUG_SYMS
5333965Sjdp#define debug_verify_symchain verify_symbol_chain
5433965Sjdp#else
5533965Sjdp#define debug_verify_symchain(root, last) ((void) 0)
5633965Sjdp#endif
5733965Sjdp
5877298Sobrien#define DOLLAR_LABEL_CHAR	'\001'
5977298Sobrien#define LOCAL_LABEL_CHAR	'\002'
6077298Sobrien
6133965Sjdpstruct obstack notes;
6233965Sjdp
63130561Sobrienstatic char *save_symbol_name (const char *);
64130561Sobrienstatic void fb_label_init (void);
65130561Sobrienstatic long dollar_label_instance (long);
66130561Sobrienstatic long fb_label_instance (long);
6733965Sjdp
68130561Sobrienstatic void print_binary (FILE *, const char *, expressionS *);
69130561Sobrienstatic void report_op_error (symbolS *, symbolS *, symbolS *);
7060484Sobrien
7177298Sobrien/* Return a pointer to a new symbol.  Die if we can't make a new
7233965Sjdp   symbol.  Fill in the symbol's values.  Add symbol to end of symbol
7333965Sjdp   chain.
7477298Sobrien
7533965Sjdp   This function should be called in the general case of creating a
7633965Sjdp   symbol.  However, if the output file symbol table has already been
7733965Sjdp   set, and you are certain that this symbol won't be wanted in the
7833965Sjdp   output file, you can call symbol_create.  */
7933965Sjdp
8033965SjdpsymbolS *
81130561Sobriensymbol_new (const char *name, segT segment, valueT valu, fragS *frag)
8233965Sjdp{
8333965Sjdp  symbolS *symbolP = symbol_create (name, segment, valu, frag);
8433965Sjdp
8577298Sobrien  /* Link to end of symbol chain.  */
8633965Sjdp#ifdef BFD_ASSEMBLER
8733965Sjdp  {
8833965Sjdp    extern int symbol_table_frozen;
8933965Sjdp    if (symbol_table_frozen)
9033965Sjdp      abort ();
9133965Sjdp  }
9233965Sjdp#endif
9333965Sjdp  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
9433965Sjdp
9533965Sjdp  return symbolP;
9633965Sjdp}
9733965Sjdp
9860484Sobrien/* Save a symbol name on a permanent obstack, and convert it according
9960484Sobrien   to the object file format.  */
10060484Sobrien
10160484Sobrienstatic char *
102130561Sobriensave_symbol_name (const char *name)
10333965Sjdp{
10433965Sjdp  unsigned int name_length;
10560484Sobrien  char *ret;
10633965Sjdp
10777298Sobrien  name_length = strlen (name) + 1;	/* +1 for \0.  */
10833965Sjdp  obstack_grow (&notes, name, name_length);
10960484Sobrien  ret = obstack_finish (&notes);
11060484Sobrien
11133965Sjdp#ifdef STRIP_UNDERSCORE
11260484Sobrien  if (ret[0] == '_')
11360484Sobrien    ++ret;
11433965Sjdp#endif
11533965Sjdp
11633965Sjdp#ifdef tc_canonicalize_symbol_name
11760484Sobrien  ret = tc_canonicalize_symbol_name (ret);
11833965Sjdp#endif
11933965Sjdp
12033965Sjdp  if (! symbols_case_sensitive)
12133965Sjdp    {
12289857Sobrien      char *s;
12333965Sjdp
12489857Sobrien      for (s = ret; *s != '\0'; s++)
12589857Sobrien	*s = TOUPPER (*s);
12633965Sjdp    }
12733965Sjdp
12860484Sobrien  return ret;
12960484Sobrien}
13060484Sobrien
13160484SobriensymbolS *
132130561Sobriensymbol_create (const char *name, /* It is copied, the caller can destroy/modify.  */
133130561Sobrien	       segT segment,	/* Segment identifier (SEG_<something>).  */
134130561Sobrien	       valueT valu,	/* Symbol value.  */
135130561Sobrien	       fragS *frag	/* Associated fragment.  */)
13660484Sobrien{
13760484Sobrien  char *preserved_copy_of_name;
13860484Sobrien  symbolS *symbolP;
13960484Sobrien
14060484Sobrien  preserved_copy_of_name = save_symbol_name (name);
14160484Sobrien
14233965Sjdp  symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
14333965Sjdp
14477298Sobrien  /* symbol must be born in some fixed state.  This seems as good as any.  */
14533965Sjdp  memset (symbolP, 0, sizeof (symbolS));
14633965Sjdp
14733965Sjdp#ifdef BFD_ASSEMBLER
14833965Sjdp  symbolP->bsym = bfd_make_empty_symbol (stdoutput);
14933965Sjdp  if (symbolP->bsym == NULL)
15033965Sjdp    as_perror ("%s", "bfd_make_empty_symbol");
15133965Sjdp  symbolP->bsym->udata.p = (PTR) symbolP;
15233965Sjdp#endif
15333965Sjdp  S_SET_NAME (symbolP, preserved_copy_of_name);
15433965Sjdp
15533965Sjdp  S_SET_SEGMENT (symbolP, segment);
15633965Sjdp  S_SET_VALUE (symbolP, valu);
15733965Sjdp  symbol_clear_list_pointers (symbolP);
15833965Sjdp
15933965Sjdp  symbolP->sy_frag = frag;
16033965Sjdp#ifndef BFD_ASSEMBLER
16133965Sjdp  symbolP->sy_number = ~0;
16233965Sjdp  symbolP->sy_name_offset = (unsigned int) ~0;
16333965Sjdp#endif
16433965Sjdp
16533965Sjdp  obj_symbol_new_hook (symbolP);
16633965Sjdp
16733965Sjdp#ifdef tc_symbol_new_hook
16833965Sjdp  tc_symbol_new_hook (symbolP);
16933965Sjdp#endif
17033965Sjdp
17133965Sjdp  return symbolP;
17233965Sjdp}
17333965Sjdp
17460484Sobrien#ifdef BFD_ASSEMBLER
17533965Sjdp
17660484Sobrien/* Local symbol support.  If we can get away with it, we keep only a
17760484Sobrien   small amount of information for local symbols.  */
17860484Sobrien
179130561Sobrienstatic symbolS *local_symbol_convert (struct local_symbol *);
18060484Sobrien
18160484Sobrien/* Used for statistics.  */
18260484Sobrien
18360484Sobrienstatic unsigned long local_symbol_count;
18460484Sobrienstatic unsigned long local_symbol_conversion_count;
18560484Sobrien
18660484Sobrien/* This macro is called with a symbol argument passed by reference.
18760484Sobrien   It returns whether this is a local symbol.  If necessary, it
18860484Sobrien   changes its argument to the real symbol.  */
18960484Sobrien
19060484Sobrien#define LOCAL_SYMBOL_CHECK(s)						\
19160484Sobrien  (s->bsym == NULL							\
19260484Sobrien   ? (local_symbol_converted_p ((struct local_symbol *) s)		\
19360484Sobrien      ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s),	\
19460484Sobrien	 0)								\
19560484Sobrien      : 1)								\
19660484Sobrien   : 0)
19760484Sobrien
19860484Sobrien/* Create a local symbol and insert it into the local hash table.  */
19960484Sobrien
200130561Sobrienstruct local_symbol *
201130561Sobrienlocal_symbol_make (const char *name, segT section, valueT value, fragS *frag)
20260484Sobrien{
20360484Sobrien  char *name_copy;
20460484Sobrien  struct local_symbol *ret;
20560484Sobrien
20660484Sobrien  ++local_symbol_count;
20760484Sobrien
20860484Sobrien  name_copy = save_symbol_name (name);
20960484Sobrien
21060484Sobrien  ret = (struct local_symbol *) obstack_alloc (&notes, sizeof *ret);
21160484Sobrien  ret->lsy_marker = NULL;
21260484Sobrien  ret->lsy_name = name_copy;
21360484Sobrien  ret->lsy_section = section;
21460484Sobrien  local_symbol_set_frag (ret, frag);
21589857Sobrien  ret->lsy_value = value;
21660484Sobrien
21760484Sobrien  hash_jam (local_hash, name_copy, (PTR) ret);
21860484Sobrien
21960484Sobrien  return ret;
22060484Sobrien}
22160484Sobrien
22260484Sobrien/* Convert a local symbol into a real symbol.  Note that we do not
22360484Sobrien   reclaim the space used by the local symbol.  */
22460484Sobrien
22560484Sobrienstatic symbolS *
226130561Sobrienlocal_symbol_convert (struct local_symbol *locsym)
22760484Sobrien{
22860484Sobrien  symbolS *ret;
22960484Sobrien
23060484Sobrien  assert (locsym->lsy_marker == NULL);
23160484Sobrien  if (local_symbol_converted_p (locsym))
23260484Sobrien    return local_symbol_get_real_symbol (locsym);
23360484Sobrien
23460484Sobrien  ++local_symbol_conversion_count;
23560484Sobrien
23689857Sobrien  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value,
23760484Sobrien		    local_symbol_get_frag (locsym));
23860484Sobrien
23960484Sobrien  if (local_symbol_resolved_p (locsym))
24060484Sobrien    ret->sy_resolved = 1;
24160484Sobrien
24260484Sobrien  /* Local symbols are always either defined or used.  */
24360484Sobrien  ret->sy_used = 1;
24460484Sobrien
24589857Sobrien#ifdef TC_LOCAL_SYMFIELD_CONVERT
24689857Sobrien  TC_LOCAL_SYMFIELD_CONVERT (locsym, ret);
24789857Sobrien#endif
24889857Sobrien
24960484Sobrien  symbol_table_insert (ret);
25060484Sobrien
25160484Sobrien  local_symbol_mark_converted (locsym);
25260484Sobrien  local_symbol_set_real_symbol (locsym, ret);
25360484Sobrien
25460484Sobrien  hash_jam (local_hash, locsym->lsy_name, NULL);
25560484Sobrien
25660484Sobrien  return ret;
25760484Sobrien}
25860484Sobrien
25960484Sobrien#else /* ! BFD_ASSEMBLER */
26060484Sobrien
26160484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0
26260484Sobrien#define local_symbol_convert(s) ((symbolS *) s)
26360484Sobrien
26460484Sobrien#endif /* ! BFD_ASSEMBLER */
26560484Sobrien
26677298Sobrien/* We have just seen "<name>:".
26777298Sobrien   Creates a struct symbol unless it already exists.
26860484Sobrien
26977298Sobrien   Gripes if we are redefining a symbol incompatibly (and ignores it).  */
27077298Sobrien
27133965SjdpsymbolS *
272130561Sobriencolon (/* Just seen "x:" - rattle symbols & frags.  */
273130561Sobrien       const char *sym_name	/* Symbol name, as a cannonical string.  */
274130561Sobrien       /* We copy this string: OK to alter later.  */)
27533965Sjdp{
27677298Sobrien  register symbolS *symbolP;	/* Symbol we are working with.  */
27733965Sjdp
27833965Sjdp  /* Sun local labels go out of scope whenever a non-local symbol is
27933965Sjdp     defined.  */
28033965Sjdp  if (LOCAL_LABELS_DOLLAR)
28133965Sjdp    {
28233965Sjdp      int local;
28333965Sjdp
28433965Sjdp#ifdef BFD_ASSEMBLER
28533965Sjdp      local = bfd_is_local_label_name (stdoutput, sym_name);
28633965Sjdp#else
28733965Sjdp      local = LOCAL_LABEL (sym_name);
28833965Sjdp#endif
28933965Sjdp
29033965Sjdp      if (! local)
29133965Sjdp	dollar_label_clear ();
29233965Sjdp    }
29333965Sjdp
29433965Sjdp#ifndef WORKING_DOT_WORD
29533965Sjdp  if (new_broken_words)
29633965Sjdp    {
29733965Sjdp      struct broken_word *a;
29833965Sjdp      int possible_bytes;
29933965Sjdp      fragS *frag_tmp;
30033965Sjdp      char *frag_opcode;
30133965Sjdp
30233965Sjdp      extern const int md_short_jump_size;
30333965Sjdp      extern const int md_long_jump_size;
304130561Sobrien
305130561Sobrien      if (now_seg == absolute_section)
306130561Sobrien	{
307130561Sobrien	  as_bad (_("cannot define symbol `%s' in absolute section"), sym_name);
308130561Sobrien	  return NULL;
309130561Sobrien	}
310130561Sobrien
31133965Sjdp      possible_bytes = (md_short_jump_size
31233965Sjdp			+ new_broken_words * md_long_jump_size);
31333965Sjdp
31433965Sjdp      frag_tmp = frag_now;
31533965Sjdp      frag_opcode = frag_var (rs_broken_word,
31633965Sjdp			      possible_bytes,
31733965Sjdp			      possible_bytes,
31833965Sjdp			      (relax_substateT) 0,
31933965Sjdp			      (symbolS *) broken_words,
32033965Sjdp			      (offsetT) 0,
32133965Sjdp			      NULL);
32233965Sjdp
32377298Sobrien      /* We want to store the pointer to where to insert the jump
32477298Sobrien	 table in the fr_opcode of the rs_broken_word frag.  This
32577298Sobrien	 requires a little hackery.  */
32633965Sjdp      while (frag_tmp
32733965Sjdp	     && (frag_tmp->fr_type != rs_broken_word
32833965Sjdp		 || frag_tmp->fr_opcode))
32933965Sjdp	frag_tmp = frag_tmp->fr_next;
33033965Sjdp      know (frag_tmp);
33133965Sjdp      frag_tmp->fr_opcode = frag_opcode;
33233965Sjdp      new_broken_words = 0;
33333965Sjdp
33433965Sjdp      for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
33533965Sjdp	a->dispfrag = frag_tmp;
33633965Sjdp    }
33733965Sjdp#endif /* WORKING_DOT_WORD */
33833965Sjdp
33933965Sjdp  if ((symbolP = symbol_find (sym_name)) != 0)
34033965Sjdp    {
34133965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION
34233965Sjdp      if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
34333965Sjdp	return symbolP;
34433965Sjdp#endif
34577298Sobrien      /* Now check for undefined symbols.  */
34660484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
34733965Sjdp	{
34860484Sobrien#ifdef BFD_ASSEMBLER
34960484Sobrien	  struct local_symbol *locsym = (struct local_symbol *) symbolP;
35060484Sobrien
35160484Sobrien	  if (locsym->lsy_section != undefined_section
35260484Sobrien	      && (local_symbol_get_frag (locsym) != frag_now
35360484Sobrien		  || locsym->lsy_section != now_seg
35489857Sobrien		  || locsym->lsy_value != frag_now_fix ()))
35560484Sobrien	    {
35689857Sobrien	      as_bad (_("symbol `%s' is already defined"), sym_name);
35760484Sobrien	      return symbolP;
35860484Sobrien	    }
35960484Sobrien
36060484Sobrien	  locsym->lsy_section = now_seg;
36160484Sobrien	  local_symbol_set_frag (locsym, frag_now);
36289857Sobrien	  locsym->lsy_value = frag_now_fix ();
36360484Sobrien#endif
36460484Sobrien	}
36560484Sobrien      else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
36660484Sobrien	{
36733965Sjdp	  if (S_GET_VALUE (symbolP) == 0)
36833965Sjdp	    {
36933965Sjdp	      symbolP->sy_frag = frag_now;
37033965Sjdp#ifdef OBJ_VMS
37177298Sobrien	      S_SET_OTHER (symbolP, const_flag);
37233965Sjdp#endif
37333965Sjdp	      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
37433965Sjdp	      S_SET_SEGMENT (symbolP, now_seg);
37533965Sjdp#ifdef N_UNDF
37633965Sjdp	      know (N_UNDF == 0);
37777298Sobrien#endif /* if we have one, it better be zero.  */
37833965Sjdp
37933965Sjdp	    }
38033965Sjdp	  else
38133965Sjdp	    {
38277298Sobrien	      /* There are still several cases to check:
38333965Sjdp
38477298Sobrien		 A .comm/.lcomm symbol being redefined as initialized
38577298Sobrien		 data is OK
38677298Sobrien
38777298Sobrien		 A .comm/.lcomm symbol being redefined with a larger
38877298Sobrien		 size is also OK
38977298Sobrien
39077298Sobrien		 This only used to be allowed on VMS gas, but Sun cc
39177298Sobrien		 on the sparc also depends on it.  */
39277298Sobrien
39333965Sjdp	      if (((!S_IS_DEBUG (symbolP)
39433965Sjdp		    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
39533965Sjdp		    && S_IS_EXTERNAL (symbolP))
39633965Sjdp		   || S_GET_SEGMENT (symbolP) == bss_section)
39733965Sjdp		  && (now_seg == data_section
39833965Sjdp		      || now_seg == S_GET_SEGMENT (symbolP)))
39933965Sjdp		{
40077298Sobrien		  /* Select which of the 2 cases this is.  */
40133965Sjdp		  if (now_seg != data_section)
40233965Sjdp		    {
40377298Sobrien		      /* New .comm for prev .comm symbol.
40477298Sobrien
40577298Sobrien			 If the new size is larger we just change its
40677298Sobrien			 value.  If the new size is smaller, we ignore
40777298Sobrien			 this symbol.  */
40833965Sjdp		      if (S_GET_VALUE (symbolP)
40933965Sjdp			  < ((unsigned) frag_now_fix ()))
41033965Sjdp			{
41133965Sjdp			  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
41233965Sjdp			}
41333965Sjdp		    }
41433965Sjdp		  else
41533965Sjdp		    {
41633965Sjdp		      /* It is a .comm/.lcomm being converted to initialized
41733965Sjdp			 data.  */
41833965Sjdp		      symbolP->sy_frag = frag_now;
41933965Sjdp#ifdef OBJ_VMS
42077298Sobrien		      S_SET_OTHER (symbolP, const_flag);
42133965Sjdp#endif
42233965Sjdp		      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
42377298Sobrien		      S_SET_SEGMENT (symbolP, now_seg);	/* Keep N_EXT bit.  */
42433965Sjdp		    }
42533965Sjdp		}
42633965Sjdp	      else
42733965Sjdp		{
42860484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \
42960484Sobrien     && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT))
43060484Sobrien		  static const char *od_buf = "";
43133965Sjdp#else
43260484Sobrien		  char od_buf[100];
43360484Sobrien		  od_buf[0] = '\0';
43460484Sobrien#ifdef BFD_ASSEMBLER
43560484Sobrien		  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
43660484Sobrien#endif
437104834Sobrien		    sprintf (od_buf, "%d.%d.",
438104834Sobrien			     S_GET_OTHER (symbolP),
439104834Sobrien			     S_GET_DESC (symbolP));
44060484Sobrien#endif
44189857Sobrien		  as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"),
44233965Sjdp			    sym_name,
44333965Sjdp			    segment_name (S_GET_SEGMENT (symbolP)),
44460484Sobrien			    od_buf,
44533965Sjdp			    (long) S_GET_VALUE (symbolP));
44633965Sjdp		}
44777298Sobrien	    }			/* if the undefined symbol has no value  */
44833965Sjdp	}
44933965Sjdp      else
45033965Sjdp	{
45177298Sobrien	  /* Don't blow up if the definition is the same.  */
45233965Sjdp	  if (!(frag_now == symbolP->sy_frag
45333965Sjdp		&& S_GET_VALUE (symbolP) == frag_now_fix ()
45433965Sjdp		&& S_GET_SEGMENT (symbolP) == now_seg))
45589857Sobrien	    as_bad (_("symbol `%s' is already defined"), sym_name);
45677298Sobrien	}
45733965Sjdp
45833965Sjdp    }
45960484Sobrien#ifdef BFD_ASSEMBLER
46060484Sobrien  else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))
46160484Sobrien    {
46260484Sobrien      symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,
46360484Sobrien					       (valueT) frag_now_fix (),
46460484Sobrien					       frag_now);
46560484Sobrien    }
46660484Sobrien#endif /* BFD_ASSEMBLER */
46733965Sjdp  else
46833965Sjdp    {
46933965Sjdp      symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
47033965Sjdp			    frag_now);
47133965Sjdp#ifdef OBJ_VMS
47233965Sjdp      S_SET_OTHER (symbolP, const_flag);
47333965Sjdp#endif /* OBJ_VMS */
47433965Sjdp
47533965Sjdp      symbol_table_insert (symbolP);
47677298Sobrien    }
47733965Sjdp
47833965Sjdp  if (mri_common_symbol != NULL)
47933965Sjdp    {
48033965Sjdp      /* This symbol is actually being defined within an MRI common
481130561Sobrien	 section.  This requires special handling.  */
48260484Sobrien      if (LOCAL_SYMBOL_CHECK (symbolP))
48360484Sobrien	symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
48433965Sjdp      symbolP->sy_value.X_op = O_symbol;
48533965Sjdp      symbolP->sy_value.X_add_symbol = mri_common_symbol;
48633965Sjdp      symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
48733965Sjdp      symbolP->sy_frag = &zero_address_frag;
48833965Sjdp      S_SET_SEGMENT (symbolP, expr_section);
48933965Sjdp      symbolP->sy_mri_common = 1;
49033965Sjdp    }
49133965Sjdp
49233965Sjdp#ifdef tc_frob_label
49333965Sjdp  tc_frob_label (symbolP);
49433965Sjdp#endif
49533965Sjdp#ifdef obj_frob_label
49633965Sjdp  obj_frob_label (symbolP);
49733965Sjdp#endif
49833965Sjdp
49933965Sjdp  return symbolP;
50033965Sjdp}
50133965Sjdp
50277298Sobrien/* Die if we can't insert the symbol.  */
50333965Sjdp
50477298Sobrienvoid
505130561Sobriensymbol_table_insert (symbolS *symbolP)
50633965Sjdp{
50733965Sjdp  register const char *error_string;
50833965Sjdp
50933965Sjdp  know (symbolP);
51033965Sjdp  know (S_GET_NAME (symbolP));
51133965Sjdp
51260484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
51360484Sobrien    {
51460484Sobrien      error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
51560484Sobrien			       (PTR) symbolP);
51660484Sobrien      if (error_string != NULL)
51789857Sobrien	as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
51860484Sobrien		  S_GET_NAME (symbolP), error_string);
51960484Sobrien      return;
52060484Sobrien    }
52160484Sobrien
52233965Sjdp  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
52333965Sjdp    {
52489857Sobrien      as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
52533965Sjdp		S_GET_NAME (symbolP), error_string);
52677298Sobrien    }				/* on error  */
52777298Sobrien}
52833965Sjdp
52977298Sobrien/* If a symbol name does not exist, create it as undefined, and insert
53077298Sobrien   it into the symbol table.  Return a pointer to it.  */
53177298Sobrien
53233965SjdpsymbolS *
533130561Sobriensymbol_find_or_make (const char *name)
53433965Sjdp{
53533965Sjdp  register symbolS *symbolP;
53633965Sjdp
53733965Sjdp  symbolP = symbol_find (name);
53833965Sjdp
53933965Sjdp  if (symbolP == NULL)
54033965Sjdp    {
54160484Sobrien#ifdef BFD_ASSEMBLER
54260484Sobrien      if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))
54360484Sobrien	{
54460484Sobrien	  symbolP = md_undefined_symbol ((char *) name);
54560484Sobrien	  if (symbolP != NULL)
54660484Sobrien	    return symbolP;
54760484Sobrien
54860484Sobrien	  symbolP = (symbolS *) local_symbol_make (name, undefined_section,
54960484Sobrien						   (valueT) 0,
55060484Sobrien						   &zero_address_frag);
55160484Sobrien	  return symbolP;
55260484Sobrien	}
55360484Sobrien#endif
55460484Sobrien
55533965Sjdp      symbolP = symbol_make (name);
55633965Sjdp
55733965Sjdp      symbol_table_insert (symbolP);
55833965Sjdp    }				/* if symbol wasn't found */
55933965Sjdp
56033965Sjdp  return (symbolP);
56177298Sobrien}
56233965Sjdp
56333965SjdpsymbolS *
564130561Sobriensymbol_make (const char *name)
56533965Sjdp{
56633965Sjdp  symbolS *symbolP;
56733965Sjdp
56877298Sobrien  /* Let the machine description default it, e.g. for register names.  */
56933965Sjdp  symbolP = md_undefined_symbol ((char *) name);
57033965Sjdp
57133965Sjdp  if (!symbolP)
57233965Sjdp    symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
57333965Sjdp
57433965Sjdp  return (symbolP);
57577298Sobrien}
57633965Sjdp
577130561SobriensymbolS *
578130561Sobriensymbol_temp_new (segT seg, valueT ofs, fragS *frag)
579130561Sobrien{
580130561Sobrien  return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag);
581130561Sobrien}
582130561Sobrien
583130561SobriensymbolS *
584130561Sobriensymbol_temp_new_now (void)
585130561Sobrien{
586130561Sobrien  return symbol_temp_new (now_seg, frag_now_fix (), frag_now);
587130561Sobrien}
588130561Sobrien
589130561SobriensymbolS *
590130561Sobriensymbol_temp_make (void)
591130561Sobrien{
592130561Sobrien  return symbol_make (FAKE_LABEL_NAME);
593130561Sobrien}
594130561Sobrien
59577298Sobrien/* Implement symbol table lookup.
59677298Sobrien   In:	A symbol's name as a string: '\0' can't be part of a symbol name.
59777298Sobrien   Out:	NULL if the name was not in the symbol table, else the address
59877298Sobrien   of a struct symbol associated with that name.  */
59933965Sjdp
60033965SjdpsymbolS *
601130561Sobriensymbol_find (const char *name)
60233965Sjdp{
60333965Sjdp#ifdef STRIP_UNDERSCORE
60433965Sjdp  return (symbol_find_base (name, 1));
60533965Sjdp#else /* STRIP_UNDERSCORE */
60633965Sjdp  return (symbol_find_base (name, 0));
60733965Sjdp#endif /* STRIP_UNDERSCORE */
60877298Sobrien}
60933965Sjdp
61033965SjdpsymbolS *
611130561Sobriensymbol_find_exact (const char *name)
612104834Sobrien{
613104834Sobrien#ifdef BFD_ASSEMBLER
614104834Sobrien  {
615104834Sobrien    struct local_symbol *locsym;
616104834Sobrien
617104834Sobrien    locsym = (struct local_symbol *) hash_find (local_hash, name);
618104834Sobrien    if (locsym != NULL)
619104834Sobrien      return (symbolS *) locsym;
620104834Sobrien  }
621104834Sobrien#endif
622104834Sobrien
623104834Sobrien  return ((symbolS *) hash_find (sy_hash, name));
624104834Sobrien}
625104834Sobrien
626104834SobriensymbolS *
627130561Sobriensymbol_find_base (const char *name, int strip_underscore)
62833965Sjdp{
62933965Sjdp  if (strip_underscore && *name == '_')
63033965Sjdp    name++;
63133965Sjdp
63233965Sjdp#ifdef tc_canonicalize_symbol_name
63333965Sjdp  {
63433965Sjdp    char *copy;
63560484Sobrien    size_t len = strlen (name) + 1;
63633965Sjdp
63760484Sobrien    copy = (char *) alloca (len);
63860484Sobrien    memcpy (copy, name, len);
63933965Sjdp    name = tc_canonicalize_symbol_name (copy);
64033965Sjdp  }
64133965Sjdp#endif
64233965Sjdp
64333965Sjdp  if (! symbols_case_sensitive)
64433965Sjdp    {
64560484Sobrien      char *copy;
64660484Sobrien      const char *orig;
64760484Sobrien      unsigned char c;
64833965Sjdp
64960484Sobrien      orig = name;
65060484Sobrien      name = copy = (char *) alloca (strlen (name) + 1);
65160484Sobrien
65260484Sobrien      while ((c = *orig++) != '\0')
65360484Sobrien	{
65489857Sobrien	  *copy++ = TOUPPER (c);
65560484Sobrien	}
65660484Sobrien      *copy = '\0';
65733965Sjdp    }
65833965Sjdp
659104834Sobrien  return symbol_find_exact (name);
66033965Sjdp}
66133965Sjdp
66277298Sobrien/* Once upon a time, symbols were kept in a singly linked list.  At
66377298Sobrien   least coff needs to be able to rearrange them from time to time, for
66477298Sobrien   which a doubly linked list is much more convenient.  Loic did these
66577298Sobrien   as macros which seemed dangerous to me so they're now functions.
66677298Sobrien   xoxorich.  */
66733965Sjdp
66877298Sobrien/* Link symbol ADDME after symbol TARGET in the chain.  */
66977298Sobrien
67077298Sobrienvoid
671130561Sobriensymbol_append (symbolS *addme, symbolS *target,
672130561Sobrien	       symbolS **rootPP, symbolS **lastPP)
67333965Sjdp{
67460484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
67560484Sobrien    abort ();
67660484Sobrien  if (target != NULL && LOCAL_SYMBOL_CHECK (target))
67760484Sobrien    abort ();
67860484Sobrien
67933965Sjdp  if (target == NULL)
68033965Sjdp    {
68133965Sjdp      know (*rootPP == NULL);
68233965Sjdp      know (*lastPP == NULL);
68333965Sjdp      addme->sy_next = NULL;
68433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
68533965Sjdp      addme->sy_previous = NULL;
68633965Sjdp#endif
68733965Sjdp      *rootPP = addme;
68833965Sjdp      *lastPP = addme;
68933965Sjdp      return;
69077298Sobrien    }				/* if the list is empty  */
69133965Sjdp
69233965Sjdp  if (target->sy_next != NULL)
69333965Sjdp    {
69433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
69533965Sjdp      target->sy_next->sy_previous = addme;
69633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
69733965Sjdp    }
69833965Sjdp  else
69933965Sjdp    {
70033965Sjdp      know (*lastPP == target);
70133965Sjdp      *lastPP = addme;
70277298Sobrien    }				/* if we have a next  */
70333965Sjdp
70433965Sjdp  addme->sy_next = target->sy_next;
70533965Sjdp  target->sy_next = addme;
70633965Sjdp
70733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
70833965Sjdp  addme->sy_previous = target;
70933965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
71033965Sjdp
71133965Sjdp  debug_verify_symchain (symbol_rootP, symbol_lastP);
71233965Sjdp}
71333965Sjdp
71477298Sobrien/* Set the chain pointers of SYMBOL to null.  */
71577298Sobrien
71677298Sobrienvoid
717130561Sobriensymbol_clear_list_pointers (symbolS *symbolP)
71833965Sjdp{
71960484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
72060484Sobrien    abort ();
72133965Sjdp  symbolP->sy_next = NULL;
72233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
72333965Sjdp  symbolP->sy_previous = NULL;
72433965Sjdp#endif
72533965Sjdp}
72633965Sjdp
72733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
72877298Sobrien/* Remove SYMBOLP from the list.  */
72977298Sobrien
73077298Sobrienvoid
731130561Sobriensymbol_remove (symbolS *symbolP, symbolS **rootPP, symbolS **lastPP)
73233965Sjdp{
73360484Sobrien  if (LOCAL_SYMBOL_CHECK (symbolP))
73460484Sobrien    abort ();
73560484Sobrien
73633965Sjdp  if (symbolP == *rootPP)
73733965Sjdp    {
73833965Sjdp      *rootPP = symbolP->sy_next;
73977298Sobrien    }				/* if it was the root  */
74033965Sjdp
74133965Sjdp  if (symbolP == *lastPP)
74233965Sjdp    {
74333965Sjdp      *lastPP = symbolP->sy_previous;
74477298Sobrien    }				/* if it was the tail  */
74533965Sjdp
74633965Sjdp  if (symbolP->sy_next != NULL)
74733965Sjdp    {
74833965Sjdp      symbolP->sy_next->sy_previous = symbolP->sy_previous;
74977298Sobrien    }				/* if not last  */
75033965Sjdp
75133965Sjdp  if (symbolP->sy_previous != NULL)
75233965Sjdp    {
75333965Sjdp      symbolP->sy_previous->sy_next = symbolP->sy_next;
75477298Sobrien    }				/* if not first  */
75533965Sjdp
75633965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
75733965Sjdp}
75833965Sjdp
75977298Sobrien/* Link symbol ADDME before symbol TARGET in the chain.  */
76077298Sobrien
76177298Sobrienvoid
762130561Sobriensymbol_insert (symbolS *addme, symbolS *target,
763130561Sobrien	       symbolS **rootPP, symbolS **lastPP ATTRIBUTE_UNUSED)
76433965Sjdp{
76560484Sobrien  if (LOCAL_SYMBOL_CHECK (addme))
76660484Sobrien    abort ();
76760484Sobrien  if (LOCAL_SYMBOL_CHECK (target))
76860484Sobrien    abort ();
76960484Sobrien
77033965Sjdp  if (target->sy_previous != NULL)
77133965Sjdp    {
77233965Sjdp      target->sy_previous->sy_next = addme;
77333965Sjdp    }
77433965Sjdp  else
77533965Sjdp    {
77633965Sjdp      know (*rootPP == target);
77733965Sjdp      *rootPP = addme;
77877298Sobrien    }				/* if not first  */
77933965Sjdp
78033965Sjdp  addme->sy_previous = target->sy_previous;
78133965Sjdp  target->sy_previous = addme;
78233965Sjdp  addme->sy_next = target;
78333965Sjdp
78433965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
78533965Sjdp}
78633965Sjdp
78733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
78833965Sjdp
78977298Sobrienvoid
790130561Sobrienverify_symbol_chain (symbolS *rootP, symbolS *lastP)
79133965Sjdp{
79233965Sjdp  symbolS *symbolP = rootP;
79333965Sjdp
79433965Sjdp  if (symbolP == NULL)
79533965Sjdp    return;
79633965Sjdp
79733965Sjdp  for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
79833965Sjdp    {
79960484Sobrien#ifdef BFD_ASSEMBLER
80060484Sobrien      assert (symbolP->bsym != NULL);
80160484Sobrien#endif
80233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
80333965Sjdp      assert (symbolP->sy_next->sy_previous == symbolP);
80433965Sjdp#else
80533965Sjdp      /* Walk the list anyways, to make sure pointers are still good.  */
80633965Sjdp      ;
80733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
80833965Sjdp    }
80933965Sjdp
81033965Sjdp  assert (lastP == symbolP);
81133965Sjdp}
81233965Sjdp
81333965Sjdpvoid
814130561Sobrienverify_symbol_chain_2 (symbolS *sym)
81533965Sjdp{
81633965Sjdp  symbolS *p = sym, *n = sym;
81733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
81833965Sjdp  while (symbol_previous (p))
81933965Sjdp    p = symbol_previous (p);
82033965Sjdp#endif
82133965Sjdp  while (symbol_next (n))
82233965Sjdp    n = symbol_next (n);
82333965Sjdp  verify_symbol_chain (p, n);
82433965Sjdp}
82533965Sjdp
826130561Sobrienstatic void
827130561Sobrienreport_op_error (symbolS *symp, symbolS *left, symbolS *right)
828130561Sobrien{
829130561Sobrien  char *file;
830130561Sobrien  unsigned int line;
831130561Sobrien  segT seg_left = S_GET_SEGMENT (left);
832130561Sobrien  segT seg_right = right ? S_GET_SEGMENT (right) : 0;
833130561Sobrien
834130561Sobrien  if (expr_symbol_where (symp, &file, &line))
835130561Sobrien    {
836130561Sobrien      if (seg_left == undefined_section)
837130561Sobrien	as_bad_where (file, line,
838130561Sobrien		      _("undefined symbol `%s' in operation"),
839130561Sobrien		      S_GET_NAME (left));
840130561Sobrien      if (seg_right == undefined_section)
841130561Sobrien	as_bad_where (file, line,
842130561Sobrien		      _("undefined symbol `%s' in operation"),
843130561Sobrien		      S_GET_NAME (right));
844130561Sobrien      if (seg_left != undefined_section
845130561Sobrien	  && seg_right != undefined_section)
846130561Sobrien	{
847130561Sobrien	  if (right)
848130561Sobrien	    as_bad_where (file, line,
849130561Sobrien			  _("invalid sections for operation on `%s' and `%s'"),
850130561Sobrien			  S_GET_NAME (left), S_GET_NAME (right));
851130561Sobrien	  else
852130561Sobrien	    as_bad_where (file, line,
853130561Sobrien			  _("invalid section for operation on `%s'"),
854130561Sobrien			  S_GET_NAME (left));
855130561Sobrien	}
856130561Sobrien
857130561Sobrien    }
858130561Sobrien  else
859130561Sobrien    {
860130561Sobrien      if (seg_left == undefined_section)
861130561Sobrien	as_bad (_("undefined symbol `%s' in operation setting `%s'"),
862130561Sobrien		S_GET_NAME (left), S_GET_NAME (symp));
863130561Sobrien      if (seg_right == undefined_section)
864130561Sobrien	as_bad (_("undefined symbol `%s' in operation setting `%s'"),
865130561Sobrien		S_GET_NAME (right), S_GET_NAME (symp));
866130561Sobrien      if (seg_left != undefined_section
867130561Sobrien	  && seg_right != undefined_section)
868130561Sobrien	{
869130561Sobrien	  if (right)
870130561Sobrien	    as_bad_where (file, line,
871130561Sobrien			  _("invalid sections for operation on `%s' and `%s' setting `%s'"),
872130561Sobrien			  S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
873130561Sobrien	  else
874130561Sobrien	    as_bad_where (file, line,
875130561Sobrien			  _("invalid section for operation on `%s' setting `%s'"),
876130561Sobrien			  S_GET_NAME (left), S_GET_NAME (symp));
877130561Sobrien	}
878130561Sobrien    }
879130561Sobrien}
880130561Sobrien
88133965Sjdp/* Resolve the value of a symbol.  This is called during the final
88233965Sjdp   pass over the symbol table to resolve any symbols with complex
88333965Sjdp   values.  */
88433965Sjdp
88538889SjdpvalueT
886130561Sobrienresolve_symbol_value (symbolS *symp)
88733965Sjdp{
88833965Sjdp  int resolved;
889104834Sobrien  valueT final_val = 0;
89038889Sjdp  segT final_seg;
89133965Sjdp
89260484Sobrien#ifdef BFD_ASSEMBLER
89360484Sobrien  if (LOCAL_SYMBOL_CHECK (symp))
89460484Sobrien    {
89560484Sobrien      struct local_symbol *locsym = (struct local_symbol *) symp;
89660484Sobrien
89789857Sobrien      final_val = locsym->lsy_value;
89860484Sobrien      if (local_symbol_resolved_p (locsym))
89989857Sobrien	return final_val;
90060484Sobrien
90189857Sobrien      final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE;
90260484Sobrien
90389857Sobrien      if (finalize_syms)
90460484Sobrien	{
90589857Sobrien	  locsym->lsy_value = final_val;
90660484Sobrien	  local_symbol_mark_resolved (locsym);
90760484Sobrien	}
90860484Sobrien
90960484Sobrien      return final_val;
91060484Sobrien    }
91160484Sobrien#endif
91260484Sobrien
91333965Sjdp  if (symp->sy_resolved)
91438889Sjdp    {
91538889Sjdp      if (symp->sy_value.X_op == O_constant)
91638889Sjdp	return (valueT) symp->sy_value.X_add_number;
91738889Sjdp      else
91838889Sjdp	return 0;
91938889Sjdp    }
92033965Sjdp
92133965Sjdp  resolved = 0;
92238889Sjdp  final_seg = S_GET_SEGMENT (symp);
92333965Sjdp
92433965Sjdp  if (symp->sy_resolving)
92533965Sjdp    {
92689857Sobrien      if (finalize_syms)
92789857Sobrien	as_bad (_("symbol definition loop encountered at `%s'"),
92877298Sobrien		S_GET_NAME (symp));
92938889Sjdp      final_val = 0;
93033965Sjdp      resolved = 1;
93133965Sjdp    }
93233965Sjdp  else
93333965Sjdp    {
93438889Sjdp      symbolS *add_symbol, *op_symbol;
93538889Sjdp      offsetT left, right;
93633965Sjdp      segT seg_left, seg_right;
93738889Sjdp      operatorT op;
93833965Sjdp
93933965Sjdp      symp->sy_resolving = 1;
94033965Sjdp
94138889Sjdp      /* Help out with CSE.  */
94238889Sjdp      add_symbol = symp->sy_value.X_add_symbol;
94338889Sjdp      op_symbol = symp->sy_value.X_op_symbol;
94438889Sjdp      final_val = symp->sy_value.X_add_number;
94538889Sjdp      op = symp->sy_value.X_op;
94638889Sjdp
94738889Sjdp      switch (op)
94833965Sjdp	{
94938889Sjdp	default:
95038889Sjdp	  BAD_CASE (op);
95138889Sjdp	  break;
95233965Sjdp
95333965Sjdp	case O_absent:
95438889Sjdp	  final_val = 0;
95533965Sjdp	  /* Fall through.  */
95638889Sjdp
95733965Sjdp	case O_constant:
95860484Sobrien	  final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
95938889Sjdp	  if (final_seg == expr_section)
96038889Sjdp	    final_seg = absolute_section;
96133965Sjdp	  resolved = 1;
96233965Sjdp	  break;
96333965Sjdp
96433965Sjdp	case O_symbol:
96538889Sjdp	case O_symbol_rva:
96689857Sobrien	  left = resolve_symbol_value (add_symbol);
96789857Sobrien	  seg_left = S_GET_SEGMENT (add_symbol);
96889857Sobrien	  if (finalize_syms)
96989857Sobrien	    symp->sy_value.X_op_symbol = NULL;
97089857Sobrien
97138889Sjdp	do_symbol:
97233965Sjdp	  if (symp->sy_mri_common)
97333965Sjdp	    {
97433965Sjdp	      /* This is a symbol inside an MRI common section.  The
97589857Sobrien		 relocation routines are going to handle it specially.
97689857Sobrien		 Don't change the value.  */
97760484Sobrien	      resolved = symbol_resolved_p (add_symbol);
97833965Sjdp	      break;
97933965Sjdp	    }
98033965Sjdp
98189857Sobrien	  if (finalize_syms && final_val == 0)
98260484Sobrien	    {
98360484Sobrien	      if (LOCAL_SYMBOL_CHECK (add_symbol))
98460484Sobrien		add_symbol = local_symbol_convert ((struct local_symbol *)
98560484Sobrien						   add_symbol);
98660484Sobrien	      copy_symbol_attributes (symp, add_symbol);
98760484Sobrien	    }
98833965Sjdp
98989857Sobrien	  /* If we have equated this symbol to an undefined or common
99089857Sobrien	     symbol, keep X_op set to O_symbol, and don't change
99189857Sobrien	     X_add_number.  This permits the routine which writes out
99289857Sobrien	     relocation to detect this case, and convert the
99389857Sobrien	     relocation to be against the symbol to which this symbol
99489857Sobrien	     is equated.  */
99538889Sjdp	  if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
99633965Sjdp	    {
99789857Sobrien	      if (finalize_syms)
99838889Sjdp		{
99938889Sjdp		  symp->sy_value.X_op = O_symbol;
100060484Sobrien		  symp->sy_value.X_add_symbol = add_symbol;
100138889Sjdp		  symp->sy_value.X_add_number = final_val;
100289857Sobrien		  /* Use X_op_symbol as a flag.  */
100389857Sobrien		  symp->sy_value.X_op_symbol = add_symbol;
100489857Sobrien		  final_seg = seg_left;
100538889Sjdp		}
100638889Sjdp	      final_val = 0;
100760484Sobrien	      resolved = symbol_resolved_p (add_symbol);
100889857Sobrien	      symp->sy_resolving = 0;
100938889Sjdp	      goto exit_dont_set_value;
101033965Sjdp	    }
101189857Sobrien	  else if (finalize_syms && final_seg == expr_section
101289857Sobrien		   && seg_left != expr_section)
101389857Sobrien	    {
101489857Sobrien	      /* If the symbol is an expression symbol, do similarly
101589857Sobrien		 as for undefined and common syms above.  Handles
101689857Sobrien		 "sym +/- expr" where "expr" cannot be evaluated
101789857Sobrien		 immediately, and we want relocations to be against
101889857Sobrien		 "sym", eg. because it is weak.  */
101989857Sobrien	      symp->sy_value.X_op = O_symbol;
102089857Sobrien	      symp->sy_value.X_add_symbol = add_symbol;
102189857Sobrien	      symp->sy_value.X_add_number = final_val;
102289857Sobrien	      symp->sy_value.X_op_symbol = add_symbol;
102389857Sobrien	      final_seg = seg_left;
102489857Sobrien	      final_val += symp->sy_frag->fr_address + left;
102589857Sobrien	      resolved = symbol_resolved_p (add_symbol);
102689857Sobrien	      symp->sy_resolving = 0;
102789857Sobrien	      goto exit_dont_set_value;
102889857Sobrien	    }
102933965Sjdp	  else
103033965Sjdp	    {
103138889Sjdp	      final_val += symp->sy_frag->fr_address + left;
103238889Sjdp	      if (final_seg == expr_section || final_seg == undefined_section)
103389857Sobrien		final_seg = seg_left;
103433965Sjdp	    }
103533965Sjdp
103660484Sobrien	  resolved = symbol_resolved_p (add_symbol);
103733965Sjdp	  break;
103833965Sjdp
103933965Sjdp	case O_uminus:
104033965Sjdp	case O_bit_not:
104133965Sjdp	case O_logical_not:
104289857Sobrien	  left = resolve_symbol_value (add_symbol);
104399461Sobrien	  seg_left = S_GET_SEGMENT (add_symbol);
104438889Sjdp
1045130561Sobrien	  /* By reducing these to the relevant dyadic operator, we get
1046130561Sobrien	     	!S -> S == 0 	permitted on anything,
1047130561Sobrien		-S -> 0 - S 	only permitted on absolute
1048130561Sobrien		~S -> S ^ ~0 	only permitted on absolute  */
1049130561Sobrien	  if (op != O_logical_not && seg_left != absolute_section
1050130561Sobrien	      && finalize_syms)
1051130561Sobrien	    report_op_error (symp, add_symbol, NULL);
1052130561Sobrien
1053130561Sobrien	  if (final_seg == expr_section || final_seg == undefined_section)
1054130561Sobrien	    final_seg = absolute_section;
1055130561Sobrien
105638889Sjdp	  if (op == O_uminus)
105738889Sjdp	    left = -left;
105838889Sjdp	  else if (op == O_logical_not)
105938889Sjdp	    left = !left;
106033965Sjdp	  else
106138889Sjdp	    left = ~left;
106238889Sjdp
106338889Sjdp	  final_val += left + symp->sy_frag->fr_address;
106438889Sjdp
106560484Sobrien	  resolved = symbol_resolved_p (add_symbol);
106633965Sjdp	  break;
106733965Sjdp
106833965Sjdp	case O_multiply:
106933965Sjdp	case O_divide:
107033965Sjdp	case O_modulus:
107133965Sjdp	case O_left_shift:
107233965Sjdp	case O_right_shift:
107333965Sjdp	case O_bit_inclusive_or:
107433965Sjdp	case O_bit_or_not:
107533965Sjdp	case O_bit_exclusive_or:
107633965Sjdp	case O_bit_and:
107733965Sjdp	case O_add:
107833965Sjdp	case O_subtract:
107933965Sjdp	case O_eq:
108033965Sjdp	case O_ne:
108133965Sjdp	case O_lt:
108233965Sjdp	case O_le:
108333965Sjdp	case O_ge:
108433965Sjdp	case O_gt:
108533965Sjdp	case O_logical_and:
108633965Sjdp	case O_logical_or:
108789857Sobrien	  left = resolve_symbol_value (add_symbol);
108889857Sobrien	  right = resolve_symbol_value (op_symbol);
108938889Sjdp	  seg_left = S_GET_SEGMENT (add_symbol);
109038889Sjdp	  seg_right = S_GET_SEGMENT (op_symbol);
109133965Sjdp
109238889Sjdp	  /* Simplify addition or subtraction of a constant by folding the
109338889Sjdp	     constant into X_add_number.  */
109489857Sobrien	  if (op == O_add)
109538889Sjdp	    {
109638889Sjdp	      if (seg_right == absolute_section)
109738889Sjdp		{
109889857Sobrien		  final_val += right;
109938889Sjdp		  goto do_symbol;
110038889Sjdp		}
110189857Sobrien	      else if (seg_left == absolute_section)
110238889Sjdp		{
110338889Sjdp		  final_val += left;
110438889Sjdp		  add_symbol = op_symbol;
110538889Sjdp		  left = right;
110689857Sobrien		  seg_left = seg_right;
110738889Sjdp		  goto do_symbol;
110838889Sjdp		}
110938889Sjdp	    }
111089857Sobrien	  else if (op == O_subtract)
111189857Sobrien	    {
111289857Sobrien	      if (seg_right == absolute_section)
111389857Sobrien		{
111489857Sobrien		  final_val -= right;
111589857Sobrien		  goto do_symbol;
111689857Sobrien		}
111789857Sobrien	    }
111838889Sjdp
111989857Sobrien	  /* Equality and non-equality tests are permitted on anything.
112089857Sobrien	     Subtraction, and other comparison operators are permitted if
112189857Sobrien	     both operands are in the same section.  Otherwise, both
112289857Sobrien	     operands must be absolute.  We already handled the case of
112389857Sobrien	     addition or subtraction of a constant above.  This will
112489857Sobrien	     probably need to be changed for an object file format which
112589857Sobrien	     supports arbitrary expressions, such as IEEE-695.
112689857Sobrien
112789857Sobrien	     Don't emit messages unless we're finalizing the symbol value,
112838889Sjdp	     otherwise we may get the same message multiple times.  */
1129130561Sobrien	  if (finalize_syms
1130130561Sobrien	      && !(seg_left == absolute_section
1131130561Sobrien		   && seg_right == absolute_section)
1132130561Sobrien	      && !(op == O_eq || op == O_ne)
1133130561Sobrien	      && !((op == O_subtract
1134130561Sobrien		    || op == O_lt || op == O_le || op == O_ge || op == O_gt)
1135130561Sobrien		   && seg_left == seg_right
1136130561Sobrien		   && (seg_left != undefined_section
1137130561Sobrien		       || add_symbol == op_symbol)))
1138130561Sobrien	    report_op_error (symp, add_symbol, op_symbol);
113933965Sjdp
1140130561Sobrien	  if (final_seg == expr_section || final_seg == undefined_section)
1141130561Sobrien	    final_seg = absolute_section;
114233965Sjdp
114338889Sjdp	  /* Check for division by zero.  */
114438889Sjdp	  if ((op == O_divide || op == O_modulus) && right == 0)
114538889Sjdp	    {
114638889Sjdp	      /* If seg_right is not absolute_section, then we've
114789857Sobrien		 already issued a warning about using a bad symbol.  */
114889857Sobrien	      if (seg_right == absolute_section && finalize_syms)
114938889Sjdp		{
115038889Sjdp		  char *file;
115138889Sjdp		  unsigned int line;
115238889Sjdp
115338889Sjdp		  if (expr_symbol_where (symp, &file, &line))
115460484Sobrien		    as_bad_where (file, line, _("division by zero"));
115538889Sjdp		  else
115689857Sobrien		    as_bad (_("division by zero when setting `%s'"),
115738889Sjdp			    S_GET_NAME (symp));
115838889Sjdp		}
115938889Sjdp
116038889Sjdp	      right = 1;
116138889Sjdp	    }
116238889Sjdp
116333965Sjdp	  switch (symp->sy_value.X_op)
116433965Sjdp	    {
116538889Sjdp	    case O_multiply:		left *= right; break;
116638889Sjdp	    case O_divide:		left /= right; break;
116738889Sjdp	    case O_modulus:		left %= right; break;
116838889Sjdp	    case O_left_shift:		left <<= right; break;
116938889Sjdp	    case O_right_shift:		left >>= right; break;
117038889Sjdp	    case O_bit_inclusive_or:	left |= right; break;
117138889Sjdp	    case O_bit_or_not:		left |= ~right; break;
117238889Sjdp	    case O_bit_exclusive_or:	left ^= right; break;
117338889Sjdp	    case O_bit_and:		left &= right; break;
117438889Sjdp	    case O_add:			left += right; break;
117538889Sjdp	    case O_subtract:		left -= right; break;
117689857Sobrien	    case O_eq:
117789857Sobrien	    case O_ne:
117889857Sobrien	      left = (left == right && seg_left == seg_right
117989857Sobrien		      && (seg_left != undefined_section
118089857Sobrien			  || add_symbol == op_symbol)
118189857Sobrien		      ? ~ (offsetT) 0 : 0);
118289857Sobrien	      if (symp->sy_value.X_op == O_ne)
118389857Sobrien		left = ~left;
118489857Sobrien	      break;
118538889Sjdp	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;
118638889Sjdp	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;
118738889Sjdp	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;
118838889Sjdp	    case O_gt:	left = left >  right ? ~ (offsetT) 0 : 0; break;
118938889Sjdp	    case O_logical_and:	left = left && right; break;
119038889Sjdp	    case O_logical_or:	left = left || right; break;
119138889Sjdp	    default:		abort ();
119233965Sjdp	    }
119338889Sjdp
119438889Sjdp	  final_val += symp->sy_frag->fr_address + left;
119538889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
119699461Sobrien	    {
119799461Sobrien	      if (seg_left == undefined_section
119899461Sobrien		  || seg_right == undefined_section)
119999461Sobrien		final_seg = undefined_section;
120099461Sobrien	      else if (seg_left == absolute_section)
120199461Sobrien		final_seg = seg_right;
120299461Sobrien	      else
120399461Sobrien		final_seg = seg_left;
120499461Sobrien	    }
120560484Sobrien	  resolved = (symbol_resolved_p (add_symbol)
120660484Sobrien		      && symbol_resolved_p (op_symbol));
120777298Sobrien	  break;
120833965Sjdp
120933965Sjdp	case O_register:
121033965Sjdp	case O_big:
121133965Sjdp	case O_illegal:
121233965Sjdp	  /* Give an error (below) if not in expr_section.  We don't
121333965Sjdp	     want to worry about expr_section symbols, because they
121433965Sjdp	     are fictional (they are created as part of expression
121533965Sjdp	     resolution), and any problems may not actually mean
121633965Sjdp	     anything.  */
121733965Sjdp	  break;
121833965Sjdp	}
121938889Sjdp
122038889Sjdp      symp->sy_resolving = 0;
122133965Sjdp    }
122233965Sjdp
122389857Sobrien  if (finalize_syms)
122489857Sobrien    S_SET_VALUE (symp, final_val);
122538889Sjdp
122689857Sobrienexit_dont_set_value:
122789857Sobrien  /* Always set the segment, even if not finalizing the value.
122889857Sobrien     The segment is used to determine whether a symbol is defined.  */
122938889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
123089857Sobrien  /* The old a.out backend does not handle S_SET_SEGMENT correctly
123189857Sobrien     for a stab symbol, so we use this bad hack.  */
123289857Sobrien  if (final_seg != S_GET_SEGMENT (symp))
123338889Sjdp#endif
123489857Sobrien    S_SET_SEGMENT (symp, final_seg);
123538889Sjdp
123633965Sjdp  /* Don't worry if we can't resolve an expr_section symbol.  */
123789857Sobrien  if (finalize_syms)
123833965Sjdp    {
123938889Sjdp      if (resolved)
124038889Sjdp	symp->sy_resolved = 1;
124138889Sjdp      else if (S_GET_SEGMENT (symp) != expr_section)
124238889Sjdp	{
124389857Sobrien	  as_bad (_("can't resolve value for symbol `%s'"),
124477298Sobrien		  S_GET_NAME (symp));
124538889Sjdp	  symp->sy_resolved = 1;
124638889Sjdp	}
124733965Sjdp    }
124838889Sjdp
124938889Sjdp  return final_val;
125033965Sjdp}
125133965Sjdp
125260484Sobrien#ifdef BFD_ASSEMBLER
125360484Sobrien
1254130561Sobrienstatic void resolve_local_symbol (const char *, PTR);
125560484Sobrien
125660484Sobrien/* A static function passed to hash_traverse.  */
125760484Sobrien
125860484Sobrienstatic void
1259130561Sobrienresolve_local_symbol (const char *key ATTRIBUTE_UNUSED, PTR value)
126060484Sobrien{
126160484Sobrien  if (value != NULL)
126289857Sobrien    resolve_symbol_value (value);
126360484Sobrien}
126460484Sobrien
126560484Sobrien#endif
126660484Sobrien
126760484Sobrien/* Resolve all local symbols.  */
126860484Sobrien
126960484Sobrienvoid
1270130561Sobrienresolve_local_symbol_values (void)
127160484Sobrien{
127260484Sobrien#ifdef BFD_ASSEMBLER
127360484Sobrien  hash_traverse (local_hash, resolve_local_symbol);
127460484Sobrien#endif
127560484Sobrien}
127660484Sobrien
127733965Sjdp/* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
127833965Sjdp   They are *really* local.  That is, they go out of scope whenever we see a
127933965Sjdp   label that isn't local.  Also, like fb labels, there can be multiple
128033965Sjdp   instances of a dollar label.  Therefor, we name encode each instance with
128133965Sjdp   the instance number, keep a list of defined symbols separate from the real
128233965Sjdp   symbol table, and we treat these buggers as a sparse array.  */
128333965Sjdp
128433965Sjdpstatic long *dollar_labels;
128533965Sjdpstatic long *dollar_label_instances;
128633965Sjdpstatic char *dollar_label_defines;
128738889Sjdpstatic unsigned long dollar_label_count;
128833965Sjdpstatic unsigned long dollar_label_max;
128933965Sjdp
129077298Sobrienint
1291130561Sobriendollar_label_defined (long label)
129233965Sjdp{
129333965Sjdp  long *i;
129433965Sjdp
129533965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
129633965Sjdp
129733965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
129833965Sjdp    if (*i == label)
129933965Sjdp      return dollar_label_defines[i - dollar_labels];
130033965Sjdp
130177298Sobrien  /* If we get here, label isn't defined.  */
130233965Sjdp  return 0;
130377298Sobrien}
130433965Sjdp
130533965Sjdpstatic long
1306130561Sobriendollar_label_instance (long label)
130733965Sjdp{
130833965Sjdp  long *i;
130933965Sjdp
131033965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
131133965Sjdp
131233965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
131333965Sjdp    if (*i == label)
131433965Sjdp      return (dollar_label_instances[i - dollar_labels]);
131533965Sjdp
131677298Sobrien  /* If we get here, we haven't seen the label before.
131777298Sobrien     Therefore its instance count is zero.  */
131833965Sjdp  return 0;
131933965Sjdp}
132033965Sjdp
132177298Sobrienvoid
1322130561Sobriendollar_label_clear (void)
132333965Sjdp{
132433965Sjdp  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
132533965Sjdp}
132633965Sjdp
132733965Sjdp#define DOLLAR_LABEL_BUMP_BY 10
132833965Sjdp
132977298Sobrienvoid
1330130561Sobriendefine_dollar_label (long label)
133133965Sjdp{
133233965Sjdp  long *i;
133333965Sjdp
133433965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
133533965Sjdp    if (*i == label)
133633965Sjdp      {
133733965Sjdp	++dollar_label_instances[i - dollar_labels];
133833965Sjdp	dollar_label_defines[i - dollar_labels] = 1;
133933965Sjdp	return;
134033965Sjdp      }
134133965Sjdp
134277298Sobrien  /* If we get to here, we don't have label listed yet.  */
134333965Sjdp
134433965Sjdp  if (dollar_labels == NULL)
134533965Sjdp    {
134633965Sjdp      dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
134733965Sjdp      dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
134833965Sjdp      dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
134933965Sjdp      dollar_label_max = DOLLAR_LABEL_BUMP_BY;
135033965Sjdp      dollar_label_count = 0;
135133965Sjdp    }
135233965Sjdp  else if (dollar_label_count == dollar_label_max)
135333965Sjdp    {
135433965Sjdp      dollar_label_max += DOLLAR_LABEL_BUMP_BY;
135533965Sjdp      dollar_labels = (long *) xrealloc ((char *) dollar_labels,
135633965Sjdp					 dollar_label_max * sizeof (long));
135733965Sjdp      dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
135833965Sjdp					  dollar_label_max * sizeof (long));
135933965Sjdp      dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
136077298Sobrien    }				/* if we needed to grow  */
136133965Sjdp
136233965Sjdp  dollar_labels[dollar_label_count] = label;
136333965Sjdp  dollar_label_instances[dollar_label_count] = 1;
136433965Sjdp  dollar_label_defines[dollar_label_count] = 1;
136533965Sjdp  ++dollar_label_count;
136633965Sjdp}
136733965Sjdp
136877298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
136933965Sjdp
137077298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Am"
137177298Sobrien   where n is the label number and m is the instance number. "L" makes
137277298Sobrien   it a label discarded unless debugging and "^A"('\1') ensures no
137377298Sobrien   ordinary symbol SHOULD get the same name as a local label
137477298Sobrien   symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
137577298Sobrien
137677298Sobrien   fb labels get the same treatment, except that ^B is used in place
137777298Sobrien   of ^A.  */
137877298Sobrien
137977298Sobrienchar *				/* Return local label name.  */
1380130561Sobriendollar_label_name (register long n,	/* we just saw "n$:" : n a number.  */
1381130561Sobrien		   register int augend	/* 0 for current instance, 1 for new instance.  */)
138233965Sjdp{
138333965Sjdp  long i;
138477298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
138533965Sjdp  static char symbol_name_build[24];
138633965Sjdp  register char *p;
138733965Sjdp  register char *q;
138877298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
138933965Sjdp
139033965Sjdp  know (n >= 0);
139133965Sjdp  know (augend == 0 || augend == 1);
139233965Sjdp  p = symbol_name_build;
139360484Sobrien#ifdef LOCAL_LABEL_PREFIX
139460484Sobrien  *p++ = LOCAL_LABEL_PREFIX;
139560484Sobrien#endif
139633965Sjdp  *p++ = 'L';
139733965Sjdp
139877298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
139977298Sobrien  /* Label number.  */
140033965Sjdp  q = symbol_name_temporary;
140133965Sjdp  for (*q++ = 0, i = n; i; ++q)
140233965Sjdp    {
140333965Sjdp      *q = i % 10 + '0';
140433965Sjdp      i /= 10;
140533965Sjdp    }
140633965Sjdp  while ((*p = *--q) != '\0')
140733965Sjdp    ++p;
140833965Sjdp
140977298Sobrien  *p++ = DOLLAR_LABEL_CHAR;		/* ^A  */
141033965Sjdp
141177298Sobrien  /* Instance number.  */
141233965Sjdp  q = symbol_name_temporary;
141333965Sjdp  for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
141433965Sjdp    {
141533965Sjdp      *q = i % 10 + '0';
141633965Sjdp      i /= 10;
141733965Sjdp    }
141833965Sjdp  while ((*p++ = *--q) != '\0');;
141933965Sjdp
142077298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
142133965Sjdp  return symbol_name_build;
142233965Sjdp}
142333965Sjdp
1424130561Sobrien/* Somebody else's idea of local labels. They are made by "n:" where n
142577298Sobrien   is any decimal digit. Refer to them with
142677298Sobrien    "nb" for previous (backward) n:
142777298Sobrien   or "nf" for next (forward) n:.
142833965Sjdp
142977298Sobrien   We do a little better and let n be any number, not just a single digit, but
143077298Sobrien   since the other guy's assembler only does ten, we treat the first ten
143177298Sobrien   specially.
143277298Sobrien
143377298Sobrien   Like someone else's assembler, we have one set of local label counters for
143477298Sobrien   entire assembly, not one set per (sub)segment like in most assemblers. This
143577298Sobrien   implies that one can refer to a label in another segment, and indeed some
143677298Sobrien   crufty compilers have done just that.
143777298Sobrien
143877298Sobrien   Since there could be a LOT of these things, treat them as a sparse
143977298Sobrien   array.  */
144077298Sobrien
144133965Sjdp#define FB_LABEL_SPECIAL (10)
144233965Sjdp
144333965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL];
144433965Sjdpstatic long *fb_labels;
144533965Sjdpstatic long *fb_label_instances;
144633965Sjdpstatic long fb_label_count;
144733965Sjdpstatic long fb_label_max;
144833965Sjdp
144977298Sobrien/* This must be more than FB_LABEL_SPECIAL.  */
145033965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
145133965Sjdp
145277298Sobrienstatic void
1453130561Sobrienfb_label_init (void)
145433965Sjdp{
145533965Sjdp  memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
145677298Sobrien}
145733965Sjdp
145877298Sobrien/* Add one to the instance number of this fb label.  */
145977298Sobrien
146077298Sobrienvoid
1461130561Sobrienfb_label_instance_inc (long label)
146233965Sjdp{
146333965Sjdp  long *i;
146433965Sjdp
146533965Sjdp  if (label < FB_LABEL_SPECIAL)
146633965Sjdp    {
146733965Sjdp      ++fb_low_counter[label];
146833965Sjdp      return;
146933965Sjdp    }
147033965Sjdp
147133965Sjdp  if (fb_labels != NULL)
147233965Sjdp    {
147333965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
147433965Sjdp	   i < fb_labels + fb_label_count; ++i)
147533965Sjdp	{
147633965Sjdp	  if (*i == label)
147733965Sjdp	    {
147833965Sjdp	      ++fb_label_instances[i - fb_labels];
147933965Sjdp	      return;
148077298Sobrien	    }			/* if we find it  */
148177298Sobrien	}			/* for each existing label  */
148233965Sjdp    }
148333965Sjdp
148477298Sobrien  /* If we get to here, we don't have label listed yet.  */
148533965Sjdp
148633965Sjdp  if (fb_labels == NULL)
148733965Sjdp    {
148833965Sjdp      fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
148933965Sjdp      fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
149033965Sjdp      fb_label_max = FB_LABEL_BUMP_BY;
149133965Sjdp      fb_label_count = FB_LABEL_SPECIAL;
149233965Sjdp
149333965Sjdp    }
149433965Sjdp  else if (fb_label_count == fb_label_max)
149533965Sjdp    {
149633965Sjdp      fb_label_max += FB_LABEL_BUMP_BY;
149733965Sjdp      fb_labels = (long *) xrealloc ((char *) fb_labels,
149833965Sjdp				     fb_label_max * sizeof (long));
149933965Sjdp      fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
150033965Sjdp					      fb_label_max * sizeof (long));
150177298Sobrien    }				/* if we needed to grow  */
150233965Sjdp
150333965Sjdp  fb_labels[fb_label_count] = label;
150433965Sjdp  fb_label_instances[fb_label_count] = 1;
150533965Sjdp  ++fb_label_count;
150633965Sjdp}
150733965Sjdp
150877298Sobrienstatic long
1509130561Sobrienfb_label_instance (long label)
151033965Sjdp{
151133965Sjdp  long *i;
151233965Sjdp
151333965Sjdp  if (label < FB_LABEL_SPECIAL)
151433965Sjdp    {
151533965Sjdp      return (fb_low_counter[label]);
151633965Sjdp    }
151733965Sjdp
151833965Sjdp  if (fb_labels != NULL)
151933965Sjdp    {
152033965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
152133965Sjdp	   i < fb_labels + fb_label_count; ++i)
152233965Sjdp	{
152333965Sjdp	  if (*i == label)
152433965Sjdp	    {
152533965Sjdp	      return (fb_label_instances[i - fb_labels]);
152677298Sobrien	    }			/* if we find it  */
152777298Sobrien	}			/* for each existing label  */
152833965Sjdp    }
152933965Sjdp
153033965Sjdp  /* We didn't find the label, so this must be a reference to the
153133965Sjdp     first instance.  */
153233965Sjdp  return 0;
153333965Sjdp}
153433965Sjdp
153577298Sobrien/* Caller must copy returned name: we re-use the area for the next name.
153633965Sjdp
153777298Sobrien   The mth occurence of label n: is turned into the symbol "Ln^Bm"
153877298Sobrien   where n is the label number and m is the instance number. "L" makes
153977298Sobrien   it a label discarded unless debugging and "^B"('\2') ensures no
154077298Sobrien   ordinary symbol SHOULD get the same name as a local label
154177298Sobrien   symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
154277298Sobrien
154377298Sobrien   dollar labels get the same treatment, except that ^A is used in
154477298Sobrien   place of ^B.  */
154577298Sobrien
154677298Sobrienchar *				/* Return local label name.  */
1547130561Sobrienfb_label_name (long n,	/* We just saw "n:", "nf" or "nb" : n a number.  */
1548130561Sobrien	       long augend	/* 0 for nb, 1 for n:, nf.  */)
154933965Sjdp{
155033965Sjdp  long i;
155177298Sobrien  /* Returned to caller, then copied.  Used for created names ("4f").  */
155233965Sjdp  static char symbol_name_build[24];
155333965Sjdp  register char *p;
155433965Sjdp  register char *q;
155577298Sobrien  char symbol_name_temporary[20];	/* Build up a number, BACKWARDS.  */
155633965Sjdp
155733965Sjdp  know (n >= 0);
155833965Sjdp  know (augend == 0 || augend == 1);
155933965Sjdp  p = symbol_name_build;
156077298Sobrien#ifdef LOCAL_LABEL_PREFIX
156177298Sobrien  *p++ = LOCAL_LABEL_PREFIX;
156277298Sobrien#endif
156333965Sjdp  *p++ = 'L';
156433965Sjdp
156577298Sobrien  /* Next code just does sprintf( {}, "%d", n);  */
156677298Sobrien  /* Label number.  */
156733965Sjdp  q = symbol_name_temporary;
156833965Sjdp  for (*q++ = 0, i = n; i; ++q)
156933965Sjdp    {
157033965Sjdp      *q = i % 10 + '0';
157133965Sjdp      i /= 10;
157233965Sjdp    }
157333965Sjdp  while ((*p = *--q) != '\0')
157433965Sjdp    ++p;
157533965Sjdp
157677298Sobrien  *p++ = LOCAL_LABEL_CHAR;		/* ^B  */
157733965Sjdp
157877298Sobrien  /* Instance number.  */
157933965Sjdp  q = symbol_name_temporary;
158033965Sjdp  for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
158133965Sjdp    {
158233965Sjdp      *q = i % 10 + '0';
158333965Sjdp      i /= 10;
158433965Sjdp    }
158533965Sjdp  while ((*p++ = *--q) != '\0');;
158633965Sjdp
158777298Sobrien  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
158833965Sjdp  return (symbol_name_build);
158977298Sobrien}
159033965Sjdp
159177298Sobrien/* Decode name that may have been generated by foo_label_name() above.
159277298Sobrien   If the name wasn't generated by foo_label_name(), then return it
159377298Sobrien   unaltered.  This is used for error messages.  */
159433965Sjdp
159533965Sjdpchar *
1596130561Sobriendecode_local_label_name (char *s)
159733965Sjdp{
159833965Sjdp  char *p;
159933965Sjdp  char *symbol_decode;
160033965Sjdp  int label_number;
160133965Sjdp  int instance_number;
160233965Sjdp  char *type;
160378828Sobrien  const char *message_format;
160477298Sobrien  int index = 0;
160533965Sjdp
160677298Sobrien#ifdef LOCAL_LABEL_PREFIX
160777298Sobrien  if (s[index] == LOCAL_LABEL_PREFIX)
160877298Sobrien    ++index;
160977298Sobrien#endif
161077298Sobrien
161177298Sobrien  if (s[index] != 'L')
161233965Sjdp    return s;
161333965Sjdp
161489857Sobrien  for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p)
161533965Sjdp    label_number = (10 * label_number) + *p - '0';
161633965Sjdp
161777298Sobrien  if (*p == DOLLAR_LABEL_CHAR)
161833965Sjdp    type = "dollar";
161977298Sobrien  else if (*p == LOCAL_LABEL_CHAR)
162033965Sjdp    type = "fb";
162133965Sjdp  else
162233965Sjdp    return s;
162333965Sjdp
162489857Sobrien  for (instance_number = 0, p++; ISDIGIT (*p); ++p)
162533965Sjdp    instance_number = (10 * instance_number) + *p - '0';
162633965Sjdp
162778828Sobrien  message_format = _("\"%d\" (instance number %d of a %s label)");
162833965Sjdp  symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
162933965Sjdp  sprintf (symbol_decode, message_format, label_number, instance_number, type);
163033965Sjdp
163133965Sjdp  return symbol_decode;
163233965Sjdp}
163333965Sjdp
163433965Sjdp/* Get the value of a symbol.  */
163533965Sjdp
163633965SjdpvalueT
1637130561SobrienS_GET_VALUE (symbolS *s)
163833965Sjdp{
163960484Sobrien#ifdef BFD_ASSEMBLER
164060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
164189857Sobrien    return resolve_symbol_value (s);
164260484Sobrien#endif
164360484Sobrien
164489857Sobrien  if (!s->sy_resolved)
164589857Sobrien    {
164689857Sobrien      valueT val = resolve_symbol_value (s);
164789857Sobrien      if (!finalize_syms)
164889857Sobrien	return val;
164989857Sobrien    }
165033965Sjdp  if (s->sy_value.X_op != O_constant)
165133965Sjdp    {
165233965Sjdp      static symbolS *recur;
165333965Sjdp
165433965Sjdp      /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
1655130561Sobrien	 may call S_GET_VALUE.  We use a static symbol to avoid the
1656130561Sobrien	 immediate recursion.  */
165733965Sjdp      if (recur == s)
165833965Sjdp	return (valueT) s->sy_value.X_add_number;
165933965Sjdp      recur = s;
166033965Sjdp      if (! s->sy_resolved
166133965Sjdp	  || s->sy_value.X_op != O_symbol
166233965Sjdp	  || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
166389857Sobrien	as_bad (_("attempt to get value of unresolved symbol `%s'"),
166433965Sjdp		S_GET_NAME (s));
166533965Sjdp      recur = NULL;
166633965Sjdp    }
166733965Sjdp  return (valueT) s->sy_value.X_add_number;
166833965Sjdp}
166933965Sjdp
167033965Sjdp/* Set the value of a symbol.  */
167133965Sjdp
167233965Sjdpvoid
1673130561SobrienS_SET_VALUE (symbolS *s, valueT val)
167433965Sjdp{
167560484Sobrien#ifdef BFD_ASSEMBLER
167660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
167760484Sobrien    {
167889857Sobrien      ((struct local_symbol *) s)->lsy_value = val;
167960484Sobrien      return;
168060484Sobrien    }
168160484Sobrien#endif
168260484Sobrien
168333965Sjdp  s->sy_value.X_op = O_constant;
168433965Sjdp  s->sy_value.X_add_number = (offsetT) val;
168533965Sjdp  s->sy_value.X_unsigned = 0;
168633965Sjdp}
168733965Sjdp
168833965Sjdpvoid
1689130561Sobriencopy_symbol_attributes (symbolS *dest, symbolS *src)
169033965Sjdp{
169160484Sobrien  if (LOCAL_SYMBOL_CHECK (dest))
169260484Sobrien    dest = local_symbol_convert ((struct local_symbol *) dest);
169360484Sobrien  if (LOCAL_SYMBOL_CHECK (src))
169460484Sobrien    src = local_symbol_convert ((struct local_symbol *) src);
169560484Sobrien
169633965Sjdp#ifdef BFD_ASSEMBLER
169733965Sjdp  /* In an expression, transfer the settings of these flags.
169833965Sjdp     The user can override later, of course.  */
169938889Sjdp#define COPIED_SYMFLAGS	(BSF_FUNCTION | BSF_OBJECT)
170033965Sjdp  dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
170133965Sjdp#endif
170233965Sjdp
170333965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
170433965Sjdp  OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
170533965Sjdp#endif
170633965Sjdp}
170733965Sjdp
170833965Sjdp#ifdef BFD_ASSEMBLER
170933965Sjdp
171033965Sjdpint
1711130561SobrienS_IS_FUNCTION (symbolS *s)
171260484Sobrien{
171360484Sobrien  flagword flags;
171460484Sobrien
171560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
171660484Sobrien    return 0;
171760484Sobrien
171860484Sobrien  flags = s->bsym->flags;
171960484Sobrien
172060484Sobrien  return (flags & BSF_FUNCTION) != 0;
172160484Sobrien}
172260484Sobrien
172360484Sobrienint
1724130561SobrienS_IS_EXTERNAL (symbolS *s)
172533965Sjdp{
172660484Sobrien  flagword flags;
172733965Sjdp
172860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
172960484Sobrien    return 0;
173060484Sobrien
173160484Sobrien  flags = s->bsym->flags;
173260484Sobrien
173377298Sobrien  /* Sanity check.  */
173438889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
173533965Sjdp    abort ();
173633965Sjdp
173733965Sjdp  return (flags & BSF_GLOBAL) != 0;
173833965Sjdp}
173933965Sjdp
174033965Sjdpint
1741130561SobrienS_IS_WEAK (symbolS *s)
174233965Sjdp{
174360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
174460484Sobrien    return 0;
174533965Sjdp  return (s->bsym->flags & BSF_WEAK) != 0;
174633965Sjdp}
174733965Sjdp
174833965Sjdpint
1749130561SobrienS_IS_COMMON (symbolS *s)
175033965Sjdp{
175160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
175260484Sobrien    return 0;
175333965Sjdp  return bfd_is_com_section (s->bsym->section);
175433965Sjdp}
175533965Sjdp
175633965Sjdpint
1757130561SobrienS_IS_DEFINED (symbolS *s)
175833965Sjdp{
175960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
176060484Sobrien    return ((struct local_symbol *) s)->lsy_section != undefined_section;
176133965Sjdp  return s->bsym->section != undefined_section;
176233965Sjdp}
176333965Sjdp
1764130561Sobrien
1765130561Sobrien#ifndef EXTERN_FORCE_RELOC
1766130561Sobrien#define EXTERN_FORCE_RELOC IS_ELF
1767130561Sobrien#endif
1768130561Sobrien
1769130561Sobrien/* Return true for symbols that should not be reduced to section
1770130561Sobrien   symbols or eliminated from expressions, because they may be
1771130561Sobrien   overridden by the linker.  */
177233965Sjdpint
1773130561SobrienS_FORCE_RELOC (symbolS *s, int strict)
177433965Sjdp{
177560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
1776130561Sobrien    return ((struct local_symbol *) s)->lsy_section == undefined_section;
1777130561Sobrien
1778130561Sobrien  return ((strict
1779130561Sobrien	   && ((s->bsym->flags & BSF_WEAK) != 0
1780130561Sobrien	       || (EXTERN_FORCE_RELOC
1781130561Sobrien		   && (s->bsym->flags & BSF_GLOBAL) != 0)))
1782130561Sobrien	  || s->bsym->section == undefined_section
1783130561Sobrien	  || bfd_is_com_section (s->bsym->section));
1784130561Sobrien}
1785130561Sobrien
1786130561Sobrienint
1787130561SobrienS_IS_DEBUG (symbolS *s)
1788130561Sobrien{
1789130561Sobrien  if (LOCAL_SYMBOL_CHECK (s))
179060484Sobrien    return 0;
179133965Sjdp  if (s->bsym->flags & BSF_DEBUGGING)
179233965Sjdp    return 1;
179333965Sjdp  return 0;
179433965Sjdp}
179533965Sjdp
179633965Sjdpint
1797130561SobrienS_IS_LOCAL (symbolS *s)
179833965Sjdp{
179960484Sobrien  flagword flags;
180033965Sjdp  const char *name;
180133965Sjdp
180260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
180360484Sobrien    return 1;
180460484Sobrien
180560484Sobrien  flags = s->bsym->flags;
180660484Sobrien
180777298Sobrien  /* Sanity check.  */
180838889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
180933965Sjdp    abort ();
181033965Sjdp
181133965Sjdp  if (bfd_get_section (s->bsym) == reg_section)
181233965Sjdp    return 1;
181333965Sjdp
181438889Sjdp  if (flag_strip_local_absolute
181538889Sjdp      && (flags & BSF_GLOBAL) == 0
181638889Sjdp      && bfd_get_section (s->bsym) == absolute_section)
181738889Sjdp    return 1;
181838889Sjdp
181933965Sjdp  name = S_GET_NAME (s);
182033965Sjdp  return (name != NULL
182133965Sjdp	  && ! S_IS_DEBUG (s)
182277298Sobrien	  && (strchr (name, DOLLAR_LABEL_CHAR)
182377298Sobrien	      || strchr (name, LOCAL_LABEL_CHAR)
182433965Sjdp	      || (! flag_keep_locals
182533965Sjdp		  && (bfd_is_local_label (stdoutput, s->bsym)
182633965Sjdp		      || (flag_mri
182733965Sjdp			  && name[0] == '?'
182833965Sjdp			  && name[1] == '?')))));
182933965Sjdp}
183033965Sjdp
183133965Sjdpint
1832130561SobrienS_IS_EXTERN (symbolS *s)
183333965Sjdp{
183433965Sjdp  return S_IS_EXTERNAL (s);
183533965Sjdp}
183633965Sjdp
183733965Sjdpint
1838130561SobrienS_IS_STABD (symbolS *s)
183933965Sjdp{
184033965Sjdp  return S_GET_NAME (s) == 0;
184133965Sjdp}
184233965Sjdp
1843104834Sobrienconst char *
1844130561SobrienS_GET_NAME (symbolS *s)
184533965Sjdp{
184660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
184760484Sobrien    return ((struct local_symbol *) s)->lsy_name;
184833965Sjdp  return s->bsym->name;
184933965Sjdp}
185033965Sjdp
185133965SjdpsegT
1852130561SobrienS_GET_SEGMENT (symbolS *s)
185333965Sjdp{
185460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
185560484Sobrien    return ((struct local_symbol *) s)->lsy_section;
185633965Sjdp  return s->bsym->section;
185733965Sjdp}
185833965Sjdp
185933965Sjdpvoid
1860130561SobrienS_SET_SEGMENT (symbolS *s, segT seg)
186133965Sjdp{
186238889Sjdp  /* Don't reassign section symbols.  The direct reason is to prevent seg
186338889Sjdp     faults assigning back to const global symbols such as *ABS*, but it
186438889Sjdp     shouldn't happen anyway.  */
186538889Sjdp
186660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
186760484Sobrien    {
186860484Sobrien      if (seg == reg_section)
186960484Sobrien	s = local_symbol_convert ((struct local_symbol *) s);
187060484Sobrien      else
187160484Sobrien	{
187260484Sobrien	  ((struct local_symbol *) s)->lsy_section = seg;
187360484Sobrien	  return;
187460484Sobrien	}
187560484Sobrien    }
187660484Sobrien
187738889Sjdp  if (s->bsym->flags & BSF_SECTION_SYM)
187838889Sjdp    {
187938889Sjdp      if (s->bsym->section != seg)
188077298Sobrien	abort ();
188138889Sjdp    }
188238889Sjdp  else
188338889Sjdp    s->bsym->section = seg;
188433965Sjdp}
188533965Sjdp
188633965Sjdpvoid
1887130561SobrienS_SET_EXTERNAL (symbolS *s)
188833965Sjdp{
188960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
189060484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
189133965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
189233965Sjdp    {
189333965Sjdp      /* Let .weak override .global.  */
189433965Sjdp      return;
189533965Sjdp    }
189678828Sobrien  if (s->bsym->flags & BSF_SECTION_SYM)
189778828Sobrien    {
189878828Sobrien      char * file;
189978828Sobrien      unsigned int line;
1900104834Sobrien
190178828Sobrien      /* Do not reassign section symbols.  */
190278828Sobrien      as_where (& file, & line);
190378828Sobrien      as_warn_where (file, line,
190489857Sobrien		     _("section symbols are already global"));
190578828Sobrien      return;
190678828Sobrien    }
190733965Sjdp  s->bsym->flags |= BSF_GLOBAL;
190877298Sobrien  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
190933965Sjdp}
191033965Sjdp
191133965Sjdpvoid
1912130561SobrienS_CLEAR_EXTERNAL (symbolS *s)
191333965Sjdp{
191460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
191560484Sobrien    return;
191633965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
191733965Sjdp    {
191833965Sjdp      /* Let .weak override.  */
191933965Sjdp      return;
192033965Sjdp    }
192133965Sjdp  s->bsym->flags |= BSF_LOCAL;
192277298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
192333965Sjdp}
192433965Sjdp
192533965Sjdpvoid
1926130561SobrienS_SET_WEAK (symbolS *s)
192733965Sjdp{
192860484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
192960484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
193033965Sjdp  s->bsym->flags |= BSF_WEAK;
193177298Sobrien  s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
193233965Sjdp}
193333965Sjdp
193433965Sjdpvoid
1935130561SobrienS_SET_THREAD_LOCAL (symbolS *s)
193633965Sjdp{
193760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
1938130561Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
1939130561Sobrien  if (bfd_is_com_section (s->bsym->section)
1940130561Sobrien      && (s->bsym->flags & BSF_THREAD_LOCAL) != 0)
1941130561Sobrien    return;
1942130561Sobrien  s->bsym->flags |= BSF_THREAD_LOCAL;
1943130561Sobrien  if ((s->bsym->flags & BSF_FUNCTION) != 0)
1944130561Sobrien    as_bad (_("Accessing function `%s' as thread-local object"),
1945130561Sobrien	    S_GET_NAME (s));
1946130561Sobrien  else if (! bfd_is_und_section (s->bsym->section)
1947130561Sobrien	   && (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0)
1948130561Sobrien    as_bad (_("Accessing `%s' as thread-local object"),
1949130561Sobrien	    S_GET_NAME (s));
1950130561Sobrien}
1951130561Sobrien
1952130561Sobrienvoid
1953130561SobrienS_SET_NAME (symbolS *s, char *name)
1954130561Sobrien{
1955130561Sobrien  if (LOCAL_SYMBOL_CHECK (s))
195660484Sobrien    {
195760484Sobrien      ((struct local_symbol *) s)->lsy_name = name;
195860484Sobrien      return;
195960484Sobrien    }
196033965Sjdp  s->bsym->name = name;
196133965Sjdp}
196233965Sjdp#endif /* BFD_ASSEMBLER */
196333965Sjdp
196460484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS
196560484Sobrien
196660484Sobrien/* Return the previous symbol in a chain.  */
196760484Sobrien
196860484SobriensymbolS *
1969130561Sobriensymbol_previous (symbolS *s)
197060484Sobrien{
197160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
197260484Sobrien    abort ();
197360484Sobrien  return s->sy_previous;
197460484Sobrien}
197560484Sobrien
197660484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */
197760484Sobrien
197860484Sobrien/* Return the next symbol in a chain.  */
197960484Sobrien
198060484SobriensymbolS *
1981130561Sobriensymbol_next (symbolS *s)
198260484Sobrien{
198360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
198460484Sobrien    abort ();
198560484Sobrien  return s->sy_next;
198660484Sobrien}
198760484Sobrien
198860484Sobrien/* Return a pointer to the value of a symbol as an expression.  */
198960484Sobrien
199060484SobrienexpressionS *
1991130561Sobriensymbol_get_value_expression (symbolS *s)
199260484Sobrien{
199360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
199460484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
199560484Sobrien  return &s->sy_value;
199660484Sobrien}
199760484Sobrien
199860484Sobrien/* Set the value of a symbol to an expression.  */
199960484Sobrien
200033965Sjdpvoid
2001130561Sobriensymbol_set_value_expression (symbolS *s, const expressionS *exp)
200260484Sobrien{
200360484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
200460484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
200560484Sobrien  s->sy_value = *exp;
200660484Sobrien}
200760484Sobrien
2008130561Sobrien/* Set the value of SYM to the current position in the current segment.  */
2009130561Sobrien
2010130561Sobrienvoid
2011130561Sobriensymbol_set_value_now (symbolS *sym)
2012130561Sobrien{
2013130561Sobrien  S_SET_SEGMENT (sym, now_seg);
2014130561Sobrien  S_SET_VALUE (sym, frag_now_fix ());
2015130561Sobrien  symbol_set_frag (sym, frag_now);
2016130561Sobrien}
2017130561Sobrien
201860484Sobrien/* Set the frag of a symbol.  */
201960484Sobrien
202060484Sobrienvoid
2021130561Sobriensymbol_set_frag (symbolS *s, fragS *f)
202260484Sobrien{
202360484Sobrien#ifdef BFD_ASSEMBLER
202460484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
202560484Sobrien    {
202660484Sobrien      local_symbol_set_frag ((struct local_symbol *) s, f);
202760484Sobrien      return;
202860484Sobrien    }
202960484Sobrien#endif
203060484Sobrien  s->sy_frag = f;
203160484Sobrien}
203260484Sobrien
203360484Sobrien/* Return the frag of a symbol.  */
203460484Sobrien
203560484SobrienfragS *
2036130561Sobriensymbol_get_frag (symbolS *s)
203760484Sobrien{
203860484Sobrien#ifdef BFD_ASSEMBLER
203960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
204060484Sobrien    return local_symbol_get_frag ((struct local_symbol *) s);
204160484Sobrien#endif
204260484Sobrien  return s->sy_frag;
204360484Sobrien}
204460484Sobrien
204560484Sobrien/* Mark a symbol as having been used.  */
204660484Sobrien
204760484Sobrienvoid
2048130561Sobriensymbol_mark_used (symbolS *s)
204960484Sobrien{
205060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
205160484Sobrien    return;
205260484Sobrien  s->sy_used = 1;
205360484Sobrien}
205460484Sobrien
205560484Sobrien/* Clear the mark of whether a symbol has been used.  */
205660484Sobrien
205760484Sobrienvoid
2058130561Sobriensymbol_clear_used (symbolS *s)
205960484Sobrien{
206060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
206160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
206260484Sobrien  s->sy_used = 0;
206360484Sobrien}
206460484Sobrien
206560484Sobrien/* Return whether a symbol has been used.  */
206660484Sobrien
206760484Sobrienint
2068130561Sobriensymbol_used_p (symbolS *s)
206960484Sobrien{
207060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
207160484Sobrien    return 1;
207260484Sobrien  return s->sy_used;
207360484Sobrien}
207460484Sobrien
207560484Sobrien/* Mark a symbol as having been used in a reloc.  */
207660484Sobrien
207760484Sobrienvoid
2078130561Sobriensymbol_mark_used_in_reloc (symbolS *s)
207960484Sobrien{
208060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
208160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
208260484Sobrien  s->sy_used_in_reloc = 1;
208360484Sobrien}
208460484Sobrien
208560484Sobrien/* Clear the mark of whether a symbol has been used in a reloc.  */
208660484Sobrien
208760484Sobrienvoid
2088130561Sobriensymbol_clear_used_in_reloc (symbolS *s)
208960484Sobrien{
209060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
209160484Sobrien    return;
209260484Sobrien  s->sy_used_in_reloc = 0;
209360484Sobrien}
209460484Sobrien
209560484Sobrien/* Return whether a symbol has been used in a reloc.  */
209660484Sobrien
209760484Sobrienint
2098130561Sobriensymbol_used_in_reloc_p (symbolS *s)
209960484Sobrien{
210060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
210160484Sobrien    return 0;
210260484Sobrien  return s->sy_used_in_reloc;
210360484Sobrien}
210460484Sobrien
210560484Sobrien/* Mark a symbol as an MRI common symbol.  */
210660484Sobrien
210760484Sobrienvoid
2108130561Sobriensymbol_mark_mri_common (symbolS *s)
210960484Sobrien{
211060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
211160484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
211260484Sobrien  s->sy_mri_common = 1;
211360484Sobrien}
211460484Sobrien
211560484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol.  */
211660484Sobrien
211760484Sobrienvoid
2118130561Sobriensymbol_clear_mri_common (symbolS *s)
211960484Sobrien{
212060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
212160484Sobrien    return;
212260484Sobrien  s->sy_mri_common = 0;
212360484Sobrien}
212460484Sobrien
212560484Sobrien/* Return whether a symbol is an MRI common symbol.  */
212660484Sobrien
212760484Sobrienint
2128130561Sobriensymbol_mri_common_p (symbolS *s)
212960484Sobrien{
213060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
213160484Sobrien    return 0;
213260484Sobrien  return s->sy_mri_common;
213360484Sobrien}
213460484Sobrien
213560484Sobrien/* Mark a symbol as having been written.  */
213660484Sobrien
213760484Sobrienvoid
2138130561Sobriensymbol_mark_written (symbolS *s)
213960484Sobrien{
214060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
214160484Sobrien    return;
214260484Sobrien  s->written = 1;
214360484Sobrien}
214460484Sobrien
214560484Sobrien/* Clear the mark of whether a symbol has been written.  */
214660484Sobrien
214760484Sobrienvoid
2148130561Sobriensymbol_clear_written (symbolS *s)
214960484Sobrien{
215060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
215160484Sobrien    return;
215260484Sobrien  s->written = 0;
215360484Sobrien}
215460484Sobrien
215560484Sobrien/* Return whether a symbol has been written.  */
215660484Sobrien
215760484Sobrienint
2158130561Sobriensymbol_written_p (symbolS *s)
215960484Sobrien{
216060484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
216160484Sobrien    return 0;
216260484Sobrien  return s->written;
216360484Sobrien}
216460484Sobrien
216560484Sobrien/* Mark a symbol has having been resolved.  */
216660484Sobrien
216760484Sobrienvoid
2168130561Sobriensymbol_mark_resolved (symbolS *s)
216960484Sobrien{
217060484Sobrien#ifdef BFD_ASSEMBLER
217160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
217260484Sobrien    {
217360484Sobrien      local_symbol_mark_resolved ((struct local_symbol *) s);
217460484Sobrien      return;
217560484Sobrien    }
217660484Sobrien#endif
217760484Sobrien  s->sy_resolved = 1;
217860484Sobrien}
217960484Sobrien
218060484Sobrien/* Return whether a symbol has been resolved.  */
218160484Sobrien
218260484Sobrienint
2183130561Sobriensymbol_resolved_p (symbolS *s)
218460484Sobrien{
218560484Sobrien#ifdef BFD_ASSEMBLER
218660484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
218760484Sobrien    return local_symbol_resolved_p ((struct local_symbol *) s);
218860484Sobrien#endif
218960484Sobrien  return s->sy_resolved;
219060484Sobrien}
219160484Sobrien
219260484Sobrien/* Return whether a symbol is a section symbol.  */
219360484Sobrien
219460484Sobrienint
2195130561Sobriensymbol_section_p (symbolS *s ATTRIBUTE_UNUSED)
219660484Sobrien{
219760484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
219860484Sobrien    return 0;
219960484Sobrien#ifdef BFD_ASSEMBLER
220060484Sobrien  return (s->bsym->flags & BSF_SECTION_SYM) != 0;
220160484Sobrien#else
220277298Sobrien  /* FIXME.  */
220360484Sobrien  return 0;
220460484Sobrien#endif
220560484Sobrien}
220660484Sobrien
220760484Sobrien/* Return whether a symbol is equated to another symbol.  */
220860484Sobrien
220960484Sobrienint
2210130561Sobriensymbol_equated_p (symbolS *s)
221160484Sobrien{
221260484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
221360484Sobrien    return 0;
221460484Sobrien  return s->sy_value.X_op == O_symbol;
221560484Sobrien}
221660484Sobrien
221789857Sobrien/* Return whether a symbol is equated to another symbol, and should be
221889857Sobrien   treated specially when writing out relocs.  */
221989857Sobrien
222089857Sobrienint
2221130561Sobriensymbol_equated_reloc_p (symbolS *s)
222289857Sobrien{
222389857Sobrien  if (LOCAL_SYMBOL_CHECK (s))
222489857Sobrien    return 0;
222589857Sobrien  /* X_op_symbol, normally not used for O_symbol, is set by
222689857Sobrien     resolve_symbol_value to flag expression syms that have been
222789857Sobrien     equated.  */
222889857Sobrien  return (s->sy_value.X_op == O_symbol
222989857Sobrien	  && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
223089857Sobrien	      || ! S_IS_DEFINED (s)
223189857Sobrien	      || S_IS_COMMON (s)));
223289857Sobrien}
223389857Sobrien
223460484Sobrien/* Return whether a symbol has a constant value.  */
223560484Sobrien
223660484Sobrienint
2237130561Sobriensymbol_constant_p (symbolS *s)
223860484Sobrien{
223960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
224060484Sobrien    return 1;
224160484Sobrien  return s->sy_value.X_op == O_constant;
224260484Sobrien}
224360484Sobrien
224460484Sobrien#ifdef BFD_ASSEMBLER
224560484Sobrien
224660484Sobrien/* Return the BFD symbol for a symbol.  */
224760484Sobrien
224860484Sobrienasymbol *
2249130561Sobriensymbol_get_bfdsym (symbolS *s)
225060484Sobrien{
225160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
225260484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
225360484Sobrien  return s->bsym;
225460484Sobrien}
225560484Sobrien
225660484Sobrien/* Set the BFD symbol for a symbol.  */
225760484Sobrien
225860484Sobrienvoid
2259130561Sobriensymbol_set_bfdsym (symbolS *s, asymbol *bsym)
226060484Sobrien{
226160484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
226260484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
226360484Sobrien  s->bsym = bsym;
226460484Sobrien}
226560484Sobrien
226660484Sobrien#endif /* BFD_ASSEMBLER */
226760484Sobrien
226860484Sobrien#ifdef OBJ_SYMFIELD_TYPE
226960484Sobrien
227060484Sobrien/* Get a pointer to the object format information for a symbol.  */
227160484Sobrien
227260484SobrienOBJ_SYMFIELD_TYPE *
2273130561Sobriensymbol_get_obj (symbolS *s)
227460484Sobrien{
227560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
227660484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
227760484Sobrien  return &s->sy_obj;
227860484Sobrien}
227960484Sobrien
228060484Sobrien/* Set the object format information for a symbol.  */
228160484Sobrien
228260484Sobrienvoid
2283130561Sobriensymbol_set_obj (symbolS *s, OBJ_SYMFIELD_TYPE *o)
228460484Sobrien{
228560484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
228660484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
228760484Sobrien  s->sy_obj = *o;
228860484Sobrien}
228960484Sobrien
229060484Sobrien#endif /* OBJ_SYMFIELD_TYPE */
229160484Sobrien
229260484Sobrien#ifdef TC_SYMFIELD_TYPE
229360484Sobrien
229460484Sobrien/* Get a pointer to the processor information for a symbol.  */
229560484Sobrien
229660484SobrienTC_SYMFIELD_TYPE *
2297130561Sobriensymbol_get_tc (symbolS *s)
229860484Sobrien{
229960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
230060484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
230160484Sobrien  return &s->sy_tc;
230260484Sobrien}
230360484Sobrien
230460484Sobrien/* Set the processor information for a symbol.  */
230560484Sobrien
230660484Sobrienvoid
2307130561Sobriensymbol_set_tc (symbolS *s, TC_SYMFIELD_TYPE *o)
230860484Sobrien{
230960484Sobrien  if (LOCAL_SYMBOL_CHECK (s))
231060484Sobrien    s = local_symbol_convert ((struct local_symbol *) s);
231160484Sobrien  s->sy_tc = *o;
231260484Sobrien}
231360484Sobrien
231460484Sobrien#endif /* TC_SYMFIELD_TYPE */
231560484Sobrien
231660484Sobrienvoid
2317130561Sobriensymbol_begin (void)
231833965Sjdp{
231933965Sjdp  symbol_lastP = NULL;
232077298Sobrien  symbol_rootP = NULL;		/* In case we have 0 symbols (!!)  */
232133965Sjdp  sy_hash = hash_new ();
232260484Sobrien#ifdef BFD_ASSEMBLER
232360484Sobrien  local_hash = hash_new ();
232460484Sobrien#endif
232533965Sjdp
232633965Sjdp  memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
232733965Sjdp#ifdef BFD_ASSEMBLER
232833965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
232933965Sjdp  abs_symbol.bsym = bfd_abs_section.symbol;
233033965Sjdp#endif
233133965Sjdp#else
233277298Sobrien  /* Can't initialise a union. Sigh.  */
233333965Sjdp  S_SET_SEGMENT (&abs_symbol, absolute_section);
233433965Sjdp#endif
233533965Sjdp  abs_symbol.sy_value.X_op = O_constant;
233633965Sjdp  abs_symbol.sy_frag = &zero_address_frag;
233733965Sjdp
233833965Sjdp  if (LOCAL_LABELS_FB)
233933965Sjdp    fb_label_init ();
234033965Sjdp}
234133965Sjdp
234233965Sjdpint indent_level;
234333965Sjdp
234460484Sobrien/* Maximum indent level.
234560484Sobrien   Available for modification inside a gdb session.  */
234660484Sobrienint max_indent_level = 8;
234760484Sobrien
234833965Sjdp#if 0
234933965Sjdp
235033965Sjdpstatic void
2351130561Sobrienindent (void)
235233965Sjdp{
235333965Sjdp  printf ("%*s", indent_level * 4, "");
235433965Sjdp}
235533965Sjdp
235633965Sjdp#endif
235733965Sjdp
235833965Sjdpvoid
2359130561Sobrienprint_symbol_value_1 (FILE *file, symbolS *sym)
236033965Sjdp{
236133965Sjdp  const char *name = S_GET_NAME (sym);
236233965Sjdp  if (!name || !name[0])
236333965Sjdp    name = "(unnamed)";
236433965Sjdp  fprintf (file, "sym %lx %s", (unsigned long) sym, name);
236560484Sobrien
236660484Sobrien  if (LOCAL_SYMBOL_CHECK (sym))
236760484Sobrien    {
236860484Sobrien#ifdef BFD_ASSEMBLER
236960484Sobrien      struct local_symbol *locsym = (struct local_symbol *) sym;
237060484Sobrien      if (local_symbol_get_frag (locsym) != &zero_address_frag
237160484Sobrien	  && local_symbol_get_frag (locsym) != NULL)
237260484Sobrien	fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym));
237360484Sobrien      if (local_symbol_resolved_p (locsym))
237460484Sobrien	fprintf (file, " resolved");
237560484Sobrien      fprintf (file, " local");
237660484Sobrien#endif
237760484Sobrien    }
237860484Sobrien  else
237960484Sobrien    {
238060484Sobrien      if (sym->sy_frag != &zero_address_frag)
238160484Sobrien	fprintf (file, " frag %lx", (long) sym->sy_frag);
238260484Sobrien      if (sym->written)
238360484Sobrien	fprintf (file, " written");
238460484Sobrien      if (sym->sy_resolved)
238560484Sobrien	fprintf (file, " resolved");
238660484Sobrien      else if (sym->sy_resolving)
238760484Sobrien	fprintf (file, " resolving");
238860484Sobrien      if (sym->sy_used_in_reloc)
238960484Sobrien	fprintf (file, " used-in-reloc");
239060484Sobrien      if (sym->sy_used)
239160484Sobrien	fprintf (file, " used");
239260484Sobrien      if (S_IS_LOCAL (sym))
239360484Sobrien	fprintf (file, " local");
239460484Sobrien      if (S_IS_EXTERN (sym))
239560484Sobrien	fprintf (file, " extern");
239660484Sobrien      if (S_IS_DEBUG (sym))
239760484Sobrien	fprintf (file, " debug");
239860484Sobrien      if (S_IS_DEFINED (sym))
239960484Sobrien	fprintf (file, " defined");
240060484Sobrien    }
240133965Sjdp  fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
240260484Sobrien  if (symbol_resolved_p (sym))
240333965Sjdp    {
240433965Sjdp      segT s = S_GET_SEGMENT (sym);
240533965Sjdp
240633965Sjdp      if (s != undefined_section
2407104834Sobrien	  && s != expr_section)
240833965Sjdp	fprintf (file, " %lx", (long) S_GET_VALUE (sym));
240933965Sjdp    }
241060484Sobrien  else if (indent_level < max_indent_level
241160484Sobrien	   && S_GET_SEGMENT (sym) != undefined_section)
241233965Sjdp    {
241333965Sjdp      indent_level++;
241433965Sjdp      fprintf (file, "\n%*s<", indent_level * 4, "");
241560484Sobrien#ifdef BFD_ASSEMBLER
241660484Sobrien      if (LOCAL_SYMBOL_CHECK (sym))
241760484Sobrien	fprintf (file, "constant %lx",
241889857Sobrien		 (long) ((struct local_symbol *) sym)->lsy_value);
241960484Sobrien      else
242060484Sobrien#endif
242160484Sobrien	print_expr_1 (file, &sym->sy_value);
242233965Sjdp      fprintf (file, ">");
242333965Sjdp      indent_level--;
242433965Sjdp    }
242533965Sjdp  fflush (file);
242633965Sjdp}
242733965Sjdp
242833965Sjdpvoid
2429130561Sobrienprint_symbol_value (symbolS *sym)
243033965Sjdp{
243133965Sjdp  indent_level = 0;
243233965Sjdp  print_symbol_value_1 (stderr, sym);
243333965Sjdp  fprintf (stderr, "\n");
243433965Sjdp}
243533965Sjdp
243660484Sobrienstatic void
2437130561Sobrienprint_binary (FILE *file, const char *name, expressionS *exp)
243860484Sobrien{
243960484Sobrien  indent_level++;
244060484Sobrien  fprintf (file, "%s\n%*s<", name, indent_level * 4, "");
244160484Sobrien  print_symbol_value_1 (file, exp->X_add_symbol);
244260484Sobrien  fprintf (file, ">\n%*s<", indent_level * 4, "");
244360484Sobrien  print_symbol_value_1 (file, exp->X_op_symbol);
244460484Sobrien  fprintf (file, ">");
244560484Sobrien  indent_level--;
244660484Sobrien}
244760484Sobrien
244833965Sjdpvoid
2449130561Sobrienprint_expr_1 (FILE *file, expressionS *exp)
245033965Sjdp{
245133965Sjdp  fprintf (file, "expr %lx ", (long) exp);
245233965Sjdp  switch (exp->X_op)
245333965Sjdp    {
245433965Sjdp    case O_illegal:
245533965Sjdp      fprintf (file, "illegal");
245633965Sjdp      break;
245733965Sjdp    case O_absent:
245833965Sjdp      fprintf (file, "absent");
245933965Sjdp      break;
246033965Sjdp    case O_constant:
246133965Sjdp      fprintf (file, "constant %lx", (long) exp->X_add_number);
246233965Sjdp      break;
246333965Sjdp    case O_symbol:
246433965Sjdp      indent_level++;
246533965Sjdp      fprintf (file, "symbol\n%*s<", indent_level * 4, "");
246633965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
246733965Sjdp      fprintf (file, ">");
246833965Sjdp    maybe_print_addnum:
246933965Sjdp      if (exp->X_add_number)
247033965Sjdp	fprintf (file, "\n%*s%lx", indent_level * 4, "",
247133965Sjdp		 (long) exp->X_add_number);
247233965Sjdp      indent_level--;
247333965Sjdp      break;
247433965Sjdp    case O_register:
247533965Sjdp      fprintf (file, "register #%d", (int) exp->X_add_number);
247633965Sjdp      break;
247733965Sjdp    case O_big:
247833965Sjdp      fprintf (file, "big");
247933965Sjdp      break;
248033965Sjdp    case O_uminus:
248133965Sjdp      fprintf (file, "uminus -<");
248233965Sjdp      indent_level++;
248333965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
248433965Sjdp      fprintf (file, ">");
248533965Sjdp      goto maybe_print_addnum;
248633965Sjdp    case O_bit_not:
248733965Sjdp      fprintf (file, "bit_not");
248833965Sjdp      break;
248933965Sjdp    case O_multiply:
249060484Sobrien      print_binary (file, "multiply", exp);
249133965Sjdp      break;
249233965Sjdp    case O_divide:
249360484Sobrien      print_binary (file, "divide", exp);
249433965Sjdp      break;
249533965Sjdp    case O_modulus:
249660484Sobrien      print_binary (file, "modulus", exp);
249733965Sjdp      break;
249833965Sjdp    case O_left_shift:
249960484Sobrien      print_binary (file, "lshift", exp);
250033965Sjdp      break;
250133965Sjdp    case O_right_shift:
250260484Sobrien      print_binary (file, "rshift", exp);
250333965Sjdp      break;
250433965Sjdp    case O_bit_inclusive_or:
250560484Sobrien      print_binary (file, "bit_ior", exp);
250633965Sjdp      break;
250733965Sjdp    case O_bit_exclusive_or:
250860484Sobrien      print_binary (file, "bit_xor", exp);
250933965Sjdp      break;
251033965Sjdp    case O_bit_and:
251160484Sobrien      print_binary (file, "bit_and", exp);
251233965Sjdp      break;
251333965Sjdp    case O_eq:
251460484Sobrien      print_binary (file, "eq", exp);
251533965Sjdp      break;
251633965Sjdp    case O_ne:
251760484Sobrien      print_binary (file, "ne", exp);
251833965Sjdp      break;
251933965Sjdp    case O_lt:
252060484Sobrien      print_binary (file, "lt", exp);
252133965Sjdp      break;
252233965Sjdp    case O_le:
252360484Sobrien      print_binary (file, "le", exp);
252433965Sjdp      break;
252533965Sjdp    case O_ge:
252660484Sobrien      print_binary (file, "ge", exp);
252733965Sjdp      break;
252833965Sjdp    case O_gt:
252960484Sobrien      print_binary (file, "gt", exp);
253033965Sjdp      break;
253133965Sjdp    case O_logical_and:
253260484Sobrien      print_binary (file, "logical_and", exp);
253333965Sjdp      break;
253433965Sjdp    case O_logical_or:
253560484Sobrien      print_binary (file, "logical_or", exp);
253633965Sjdp      break;
253733965Sjdp    case O_add:
253833965Sjdp      indent_level++;
253933965Sjdp      fprintf (file, "add\n%*s<", indent_level * 4, "");
254033965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
254133965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
254233965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
254333965Sjdp      fprintf (file, ">");
254433965Sjdp      goto maybe_print_addnum;
254533965Sjdp    case O_subtract:
254633965Sjdp      indent_level++;
254733965Sjdp      fprintf (file, "subtract\n%*s<", indent_level * 4, "");
254833965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
254933965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
255033965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
255133965Sjdp      fprintf (file, ">");
255233965Sjdp      goto maybe_print_addnum;
255333965Sjdp    default:
255433965Sjdp      fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
255533965Sjdp      break;
255633965Sjdp    }
255733965Sjdp  fflush (stdout);
255833965Sjdp}
255933965Sjdp
256033965Sjdpvoid
2561130561Sobrienprint_expr (expressionS *exp)
256233965Sjdp{
256333965Sjdp  print_expr_1 (stderr, exp);
256433965Sjdp  fprintf (stderr, "\n");
256533965Sjdp}
256633965Sjdp
256733965Sjdpvoid
2568130561Sobriensymbol_print_statistics (FILE *file)
256933965Sjdp{
257033965Sjdp  hash_print_statistics (file, "symbol table", sy_hash);
257160484Sobrien#ifdef BFD_ASSEMBLER
257260484Sobrien  hash_print_statistics (file, "mini local symbol table", local_hash);
257360484Sobrien  fprintf (file, "%lu mini local symbols created, %lu converted\n",
257460484Sobrien	   local_symbol_count, local_symbol_conversion_count);
257560484Sobrien#endif
257633965Sjdp}
2577