symbols.c revision 38889
133965Sjdp/* symbols.c -symbol table-
238889Sjdp   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
333965Sjdp   Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
1933965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2033965Sjdp   02111-1307, USA.  */
2133965Sjdp
2233965Sjdp/* #define DEBUG_SYMS / * to debug symbol list maintenance */
2333965Sjdp
2433965Sjdp#include <ctype.h>
2533965Sjdp
2633965Sjdp#include "as.h"
2733965Sjdp
2833965Sjdp#include "obstack.h"		/* For "symbols.h" */
2933965Sjdp#include "subsegs.h"
3033965Sjdp
3133965Sjdp/* This is non-zero if symbols are case sensitive, which is the
3233965Sjdp   default.  */
3333965Sjdpint symbols_case_sensitive = 1;
3433965Sjdp
3533965Sjdp#ifndef WORKING_DOT_WORD
3633965Sjdpextern int new_broken_words;
3733965Sjdp#endif
3833965Sjdp
3933965Sjdp/* symbol-name => struct symbol pointer */
4033965Sjdpstatic struct hash_control *sy_hash;
4133965Sjdp
4233965Sjdp/* Below are commented in "symbols.h". */
4333965SjdpsymbolS *symbol_rootP;
4433965SjdpsymbolS *symbol_lastP;
4533965SjdpsymbolS abs_symbol;
4633965Sjdp
4733965Sjdp#ifdef DEBUG_SYMS
4833965Sjdp#define debug_verify_symchain verify_symbol_chain
4933965Sjdp#else
5033965Sjdp#define debug_verify_symchain(root, last) ((void) 0)
5133965Sjdp#endif
5233965Sjdp
5333965Sjdpstruct obstack notes;
5433965Sjdp
5533965Sjdpstatic void fb_label_init PARAMS ((void));
5633965Sjdpstatic long dollar_label_instance PARAMS ((long));
5733965Sjdpstatic long fb_label_instance PARAMS ((long));
5833965Sjdp
5933965Sjdp/* symbol_new()
6033965Sjdp
6133965Sjdp   Return a pointer to a new symbol.  Die if we can't make a new
6233965Sjdp   symbol.  Fill in the symbol's values.  Add symbol to end of symbol
6333965Sjdp   chain.
6433965Sjdp
6533965Sjdp   This function should be called in the general case of creating a
6633965Sjdp   symbol.  However, if the output file symbol table has already been
6733965Sjdp   set, and you are certain that this symbol won't be wanted in the
6833965Sjdp   output file, you can call symbol_create.  */
6933965Sjdp
7033965SjdpsymbolS *
7133965Sjdpsymbol_new (name, segment, valu, frag)
7233965Sjdp     const char *name;
7333965Sjdp     segT segment;
7433965Sjdp     valueT valu;
7533965Sjdp     fragS *frag;
7633965Sjdp{
7733965Sjdp  symbolS *symbolP = symbol_create (name, segment, valu, frag);
7833965Sjdp
7933965Sjdp  /*
8033965Sjdp   * Link to end of symbol chain.
8133965Sjdp   */
8233965Sjdp#ifdef BFD_ASSEMBLER
8333965Sjdp  {
8433965Sjdp    extern int symbol_table_frozen;
8533965Sjdp    if (symbol_table_frozen)
8633965Sjdp      abort ();
8733965Sjdp  }
8833965Sjdp#endif
8933965Sjdp  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
9033965Sjdp
9133965Sjdp  return symbolP;
9233965Sjdp}
9333965Sjdp
9433965SjdpsymbolS *
9533965Sjdpsymbol_create (name, segment, valu, frag)
9633965Sjdp     const char *name;		/* It is copied, the caller can destroy/modify */
9733965Sjdp     segT segment;		/* Segment identifier (SEG_<something>) */
9833965Sjdp     valueT valu;		/* Symbol value */
9933965Sjdp     fragS *frag;		/* Associated fragment */
10033965Sjdp{
10133965Sjdp  unsigned int name_length;
10233965Sjdp  char *preserved_copy_of_name;
10333965Sjdp  symbolS *symbolP;
10433965Sjdp
10533965Sjdp  name_length = strlen (name) + 1;	/* +1 for \0 */
10633965Sjdp  obstack_grow (&notes, name, name_length);
10733965Sjdp  preserved_copy_of_name = obstack_finish (&notes);
10833965Sjdp#ifdef STRIP_UNDERSCORE
10933965Sjdp  if (preserved_copy_of_name[0] == '_')
11033965Sjdp    preserved_copy_of_name++;
11133965Sjdp#endif
11233965Sjdp
11333965Sjdp#ifdef tc_canonicalize_symbol_name
11433965Sjdp  preserved_copy_of_name =
11533965Sjdp    tc_canonicalize_symbol_name (preserved_copy_of_name);
11633965Sjdp#endif
11733965Sjdp
11833965Sjdp  if (! symbols_case_sensitive)
11933965Sjdp    {
12033965Sjdp      unsigned char *s;
12133965Sjdp
12233965Sjdp      for (s = (unsigned char *) preserved_copy_of_name; *s != '\0'; s++)
12333965Sjdp	if (islower (*s))
12433965Sjdp	  *s = toupper (*s);
12533965Sjdp    }
12633965Sjdp
12733965Sjdp  symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
12833965Sjdp
12933965Sjdp  /* symbol must be born in some fixed state.  This seems as good as any. */
13033965Sjdp  memset (symbolP, 0, sizeof (symbolS));
13133965Sjdp
13233965Sjdp#ifdef BFD_ASSEMBLER
13333965Sjdp  symbolP->bsym = bfd_make_empty_symbol (stdoutput);
13433965Sjdp  if (symbolP->bsym == NULL)
13533965Sjdp    as_perror ("%s", "bfd_make_empty_symbol");
13633965Sjdp  symbolP->bsym->udata.p = (PTR) symbolP;
13733965Sjdp#endif
13833965Sjdp  S_SET_NAME (symbolP, preserved_copy_of_name);
13933965Sjdp
14033965Sjdp  S_SET_SEGMENT (symbolP, segment);
14133965Sjdp  S_SET_VALUE (symbolP, valu);
14233965Sjdp  symbol_clear_list_pointers (symbolP);
14333965Sjdp
14433965Sjdp  symbolP->sy_frag = frag;
14533965Sjdp#ifndef BFD_ASSEMBLER
14633965Sjdp  symbolP->sy_number = ~0;
14733965Sjdp  symbolP->sy_name_offset = (unsigned int) ~0;
14833965Sjdp#endif
14933965Sjdp
15033965Sjdp  obj_symbol_new_hook (symbolP);
15133965Sjdp
15233965Sjdp#ifdef tc_symbol_new_hook
15333965Sjdp  tc_symbol_new_hook (symbolP);
15433965Sjdp#endif
15533965Sjdp
15633965Sjdp  return symbolP;
15733965Sjdp}
15833965Sjdp
15933965Sjdp
16033965Sjdp/*
16133965Sjdp *			colon()
16233965Sjdp *
16333965Sjdp * We have just seen "<name>:".
16433965Sjdp * Creates a struct symbol unless it already exists.
16533965Sjdp *
16633965Sjdp * Gripes if we are redefining a symbol incompatibly (and ignores it).
16733965Sjdp *
16833965Sjdp */
16933965SjdpsymbolS *
17033965Sjdpcolon (sym_name)		/* just seen "x:" - rattle symbols & frags */
17133965Sjdp     const char *sym_name;	/* symbol name, as a cannonical string */
17233965Sjdp     /* We copy this string: OK to alter later. */
17333965Sjdp{
17433965Sjdp  register symbolS *symbolP;	/* symbol we are working with */
17533965Sjdp
17633965Sjdp  /* Sun local labels go out of scope whenever a non-local symbol is
17733965Sjdp     defined.  */
17833965Sjdp  if (LOCAL_LABELS_DOLLAR)
17933965Sjdp    {
18033965Sjdp      int local;
18133965Sjdp
18233965Sjdp#ifdef BFD_ASSEMBLER
18333965Sjdp      local = bfd_is_local_label_name (stdoutput, sym_name);
18433965Sjdp#else
18533965Sjdp      local = LOCAL_LABEL (sym_name);
18633965Sjdp#endif
18733965Sjdp
18833965Sjdp      if (! local)
18933965Sjdp	dollar_label_clear ();
19033965Sjdp    }
19133965Sjdp
19233965Sjdp#ifndef WORKING_DOT_WORD
19333965Sjdp  if (new_broken_words)
19433965Sjdp    {
19533965Sjdp      struct broken_word *a;
19633965Sjdp      int possible_bytes;
19733965Sjdp      fragS *frag_tmp;
19833965Sjdp      char *frag_opcode;
19933965Sjdp
20033965Sjdp      extern const int md_short_jump_size;
20133965Sjdp      extern const int md_long_jump_size;
20233965Sjdp      possible_bytes = (md_short_jump_size
20333965Sjdp			+ new_broken_words * md_long_jump_size);
20433965Sjdp
20533965Sjdp      frag_tmp = frag_now;
20633965Sjdp      frag_opcode = frag_var (rs_broken_word,
20733965Sjdp			      possible_bytes,
20833965Sjdp			      possible_bytes,
20933965Sjdp			      (relax_substateT) 0,
21033965Sjdp			      (symbolS *) broken_words,
21133965Sjdp			      (offsetT) 0,
21233965Sjdp			      NULL);
21333965Sjdp
21433965Sjdp      /* We want to store the pointer to where to insert the jump table in the
21533965Sjdp	 fr_opcode of the rs_broken_word frag.  This requires a little
21633965Sjdp	 hackery.  */
21733965Sjdp      while (frag_tmp
21833965Sjdp	     && (frag_tmp->fr_type != rs_broken_word
21933965Sjdp		 || frag_tmp->fr_opcode))
22033965Sjdp	frag_tmp = frag_tmp->fr_next;
22133965Sjdp      know (frag_tmp);
22233965Sjdp      frag_tmp->fr_opcode = frag_opcode;
22333965Sjdp      new_broken_words = 0;
22433965Sjdp
22533965Sjdp      for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
22633965Sjdp	a->dispfrag = frag_tmp;
22733965Sjdp    }
22833965Sjdp#endif /* WORKING_DOT_WORD */
22933965Sjdp
23033965Sjdp  if ((symbolP = symbol_find (sym_name)) != 0)
23133965Sjdp    {
23233965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION
23333965Sjdp      if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
23433965Sjdp	return symbolP;
23533965Sjdp#endif
23633965Sjdp      /*
23733965Sjdp       *	Now check for undefined symbols
23833965Sjdp       */
23933965Sjdp      if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
24033965Sjdp	{
24133965Sjdp	  if (S_GET_VALUE (symbolP) == 0)
24233965Sjdp	    {
24333965Sjdp	      symbolP->sy_frag = frag_now;
24433965Sjdp#ifdef OBJ_VMS
24533965Sjdp	      S_SET_OTHER(symbolP, const_flag);
24633965Sjdp#endif
24733965Sjdp	      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
24833965Sjdp	      S_SET_SEGMENT (symbolP, now_seg);
24933965Sjdp#ifdef N_UNDF
25033965Sjdp	      know (N_UNDF == 0);
25133965Sjdp#endif /* if we have one, it better be zero. */
25233965Sjdp
25333965Sjdp	    }
25433965Sjdp	  else
25533965Sjdp	    {
25633965Sjdp	      /*
25733965Sjdp	       *	There are still several cases to check:
25833965Sjdp	       *		A .comm/.lcomm symbol being redefined as
25933965Sjdp	       *			initialized data is OK
26033965Sjdp	       *		A .comm/.lcomm symbol being redefined with
26133965Sjdp	       *			a larger size is also OK
26233965Sjdp	       *
26333965Sjdp	       * This only used to be allowed on VMS gas, but Sun cc
26433965Sjdp	       * on the sparc also depends on it.
26533965Sjdp	       */
26633965Sjdp
26733965Sjdp	      if (((!S_IS_DEBUG (symbolP)
26833965Sjdp		    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
26933965Sjdp		    && S_IS_EXTERNAL (symbolP))
27033965Sjdp		   || S_GET_SEGMENT (symbolP) == bss_section)
27133965Sjdp		  && (now_seg == data_section
27233965Sjdp		      || now_seg == S_GET_SEGMENT (symbolP)))
27333965Sjdp		{
27433965Sjdp		  /*
27533965Sjdp		   *	Select which of the 2 cases this is
27633965Sjdp		   */
27733965Sjdp		  if (now_seg != data_section)
27833965Sjdp		    {
27933965Sjdp		      /*
28033965Sjdp		       *   New .comm for prev .comm symbol.
28133965Sjdp		       *	If the new size is larger we just
28233965Sjdp		       *	change its value.  If the new size
28333965Sjdp		       *	is smaller, we ignore this symbol
28433965Sjdp		       */
28533965Sjdp		      if (S_GET_VALUE (symbolP)
28633965Sjdp			  < ((unsigned) frag_now_fix ()))
28733965Sjdp			{
28833965Sjdp			  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
28933965Sjdp			}
29033965Sjdp		    }
29133965Sjdp		  else
29233965Sjdp		    {
29333965Sjdp		      /* It is a .comm/.lcomm being converted to initialized
29433965Sjdp			 data.  */
29533965Sjdp		      symbolP->sy_frag = frag_now;
29633965Sjdp#ifdef OBJ_VMS
29733965Sjdp		      S_SET_OTHER(symbolP, const_flag);
29833965Sjdp#endif
29933965Sjdp		      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
30033965Sjdp		      S_SET_SEGMENT (symbolP, now_seg);	/* keep N_EXT bit */
30133965Sjdp		    }
30233965Sjdp		}
30333965Sjdp	      else
30433965Sjdp		{
30533965Sjdp#if defined (S_GET_OTHER) && defined (S_GET_DESC)
30633965Sjdp		  as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld.",
30733965Sjdp			    sym_name,
30833965Sjdp			    segment_name (S_GET_SEGMENT (symbolP)),
30933965Sjdp			    S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
31033965Sjdp			    (long) S_GET_VALUE (symbolP));
31133965Sjdp#else
31233965Sjdp		  as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%ld.",
31333965Sjdp			    sym_name,
31433965Sjdp			    segment_name (S_GET_SEGMENT (symbolP)),
31533965Sjdp			    (long) S_GET_VALUE (symbolP));
31633965Sjdp#endif
31733965Sjdp		}
31833965Sjdp	    }			/* if the undefined symbol has no value */
31933965Sjdp	}
32033965Sjdp      else
32133965Sjdp	{
32233965Sjdp	  /* Don't blow up if the definition is the same */
32333965Sjdp	  if (!(frag_now == symbolP->sy_frag
32433965Sjdp		&& S_GET_VALUE (symbolP) == frag_now_fix ()
32533965Sjdp		&& S_GET_SEGMENT (symbolP) == now_seg))
32633965Sjdp	    as_fatal ("Symbol %s already defined.", sym_name);
32733965Sjdp	}			/* if this symbol is not yet defined */
32833965Sjdp
32933965Sjdp    }
33033965Sjdp  else
33133965Sjdp    {
33233965Sjdp      symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
33333965Sjdp			    frag_now);
33433965Sjdp#ifdef OBJ_VMS
33533965Sjdp      S_SET_OTHER (symbolP, const_flag);
33633965Sjdp#endif /* OBJ_VMS */
33733965Sjdp
33833965Sjdp      symbol_table_insert (symbolP);
33933965Sjdp    }				/* if we have seen this symbol before */
34033965Sjdp
34133965Sjdp  if (mri_common_symbol != NULL)
34233965Sjdp    {
34333965Sjdp      /* This symbol is actually being defined within an MRI common
34433965Sjdp         section.  This requires special handling.  */
34533965Sjdp      symbolP->sy_value.X_op = O_symbol;
34633965Sjdp      symbolP->sy_value.X_add_symbol = mri_common_symbol;
34733965Sjdp      symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
34833965Sjdp      symbolP->sy_frag = &zero_address_frag;
34933965Sjdp      S_SET_SEGMENT (symbolP, expr_section);
35033965Sjdp      symbolP->sy_mri_common = 1;
35133965Sjdp    }
35233965Sjdp
35333965Sjdp#ifdef tc_frob_label
35433965Sjdp  tc_frob_label (symbolP);
35533965Sjdp#endif
35633965Sjdp#ifdef obj_frob_label
35733965Sjdp  obj_frob_label (symbolP);
35833965Sjdp#endif
35933965Sjdp
36033965Sjdp  return symbolP;
36133965Sjdp}
36233965Sjdp
36333965Sjdp
36433965Sjdp/*
36533965Sjdp *			symbol_table_insert()
36633965Sjdp *
36733965Sjdp * Die if we can't insert the symbol.
36833965Sjdp *
36933965Sjdp */
37033965Sjdp
37133965Sjdpvoid
37233965Sjdpsymbol_table_insert (symbolP)
37333965Sjdp     symbolS *symbolP;
37433965Sjdp{
37533965Sjdp  register const char *error_string;
37633965Sjdp
37733965Sjdp  know (symbolP);
37833965Sjdp  know (S_GET_NAME (symbolP));
37933965Sjdp
38033965Sjdp  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
38133965Sjdp    {
38233965Sjdp      as_fatal ("Inserting \"%s\" into symbol table failed: %s",
38333965Sjdp		S_GET_NAME (symbolP), error_string);
38433965Sjdp    }				/* on error */
38533965Sjdp}				/* symbol_table_insert() */
38633965Sjdp
38733965Sjdp/*
38833965Sjdp *			symbol_find_or_make()
38933965Sjdp *
39033965Sjdp * If a symbol name does not exist, create it as undefined, and insert
39133965Sjdp * it into the symbol table. Return a pointer to it.
39233965Sjdp */
39333965SjdpsymbolS *
39433965Sjdpsymbol_find_or_make (name)
39533965Sjdp     const char *name;
39633965Sjdp{
39733965Sjdp  register symbolS *symbolP;
39833965Sjdp
39933965Sjdp  symbolP = symbol_find (name);
40033965Sjdp
40133965Sjdp  if (symbolP == NULL)
40233965Sjdp    {
40333965Sjdp      symbolP = symbol_make (name);
40433965Sjdp
40533965Sjdp      symbol_table_insert (symbolP);
40633965Sjdp    }				/* if symbol wasn't found */
40733965Sjdp
40833965Sjdp  return (symbolP);
40933965Sjdp}				/* symbol_find_or_make() */
41033965Sjdp
41133965SjdpsymbolS *
41233965Sjdpsymbol_make (name)
41333965Sjdp     CONST char *name;
41433965Sjdp{
41533965Sjdp  symbolS *symbolP;
41633965Sjdp
41733965Sjdp  /* Let the machine description default it, e.g. for register names. */
41833965Sjdp  symbolP = md_undefined_symbol ((char *) name);
41933965Sjdp
42033965Sjdp  if (!symbolP)
42133965Sjdp    symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
42233965Sjdp
42333965Sjdp  return (symbolP);
42433965Sjdp}				/* symbol_make() */
42533965Sjdp
42633965Sjdp/*
42733965Sjdp *			symbol_find()
42833965Sjdp *
42933965Sjdp * Implement symbol table lookup.
43033965Sjdp * In:	A symbol's name as a string: '\0' can't be part of a symbol name.
43133965Sjdp * Out:	NULL if the name was not in the symbol table, else the address
43233965Sjdp *	of a struct symbol associated with that name.
43333965Sjdp */
43433965Sjdp
43533965SjdpsymbolS *
43633965Sjdpsymbol_find (name)
43733965Sjdp     CONST char *name;
43833965Sjdp{
43933965Sjdp#ifdef STRIP_UNDERSCORE
44033965Sjdp  return (symbol_find_base (name, 1));
44133965Sjdp#else /* STRIP_UNDERSCORE */
44233965Sjdp  return (symbol_find_base (name, 0));
44333965Sjdp#endif /* STRIP_UNDERSCORE */
44433965Sjdp}				/* symbol_find() */
44533965Sjdp
44633965SjdpsymbolS *
44733965Sjdpsymbol_find_base (name, strip_underscore)
44833965Sjdp     CONST char *name;
44933965Sjdp     int strip_underscore;
45033965Sjdp{
45133965Sjdp  if (strip_underscore && *name == '_')
45233965Sjdp    name++;
45333965Sjdp
45433965Sjdp#ifdef tc_canonicalize_symbol_name
45533965Sjdp  {
45633965Sjdp    char *copy;
45733965Sjdp
45833965Sjdp    copy = (char *) alloca (strlen (name) + 1);
45933965Sjdp    strcpy (copy, name);
46033965Sjdp    name = tc_canonicalize_symbol_name (copy);
46133965Sjdp  }
46233965Sjdp#endif
46333965Sjdp
46433965Sjdp  if (! symbols_case_sensitive)
46533965Sjdp    {
46633965Sjdp      unsigned char *copy;
46733965Sjdp
46833965Sjdp      copy = (unsigned char *) alloca (strlen (name) + 1);
46933965Sjdp      name = (const char *) copy;
47033965Sjdp      for (; *copy != '\0'; copy++)
47133965Sjdp	if (islower (*copy))
47233965Sjdp	  *copy = toupper (*copy);
47333965Sjdp    }
47433965Sjdp
47533965Sjdp  return ((symbolS *) hash_find (sy_hash, name));
47633965Sjdp}
47733965Sjdp
47833965Sjdp/*
47933965Sjdp * Once upon a time, symbols were kept in a singly linked list.  At
48033965Sjdp * least coff needs to be able to rearrange them from time to time, for
48133965Sjdp * which a doubly linked list is much more convenient.  Loic did these
48233965Sjdp * as macros which seemed dangerous to me so they're now functions.
48333965Sjdp * xoxorich.
48433965Sjdp */
48533965Sjdp
48633965Sjdp/* Link symbol ADDME after symbol TARGET in the chain. */
48733965Sjdpvoid
48833965Sjdpsymbol_append (addme, target, rootPP, lastPP)
48933965Sjdp     symbolS *addme;
49033965Sjdp     symbolS *target;
49133965Sjdp     symbolS **rootPP;
49233965Sjdp     symbolS **lastPP;
49333965Sjdp{
49433965Sjdp  if (target == NULL)
49533965Sjdp    {
49633965Sjdp      know (*rootPP == NULL);
49733965Sjdp      know (*lastPP == NULL);
49833965Sjdp      addme->sy_next = NULL;
49933965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
50033965Sjdp      addme->sy_previous = NULL;
50133965Sjdp#endif
50233965Sjdp      *rootPP = addme;
50333965Sjdp      *lastPP = addme;
50433965Sjdp      return;
50533965Sjdp    }				/* if the list is empty */
50633965Sjdp
50733965Sjdp  if (target->sy_next != NULL)
50833965Sjdp    {
50933965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
51033965Sjdp      target->sy_next->sy_previous = addme;
51133965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
51233965Sjdp    }
51333965Sjdp  else
51433965Sjdp    {
51533965Sjdp      know (*lastPP == target);
51633965Sjdp      *lastPP = addme;
51733965Sjdp    }				/* if we have a next */
51833965Sjdp
51933965Sjdp  addme->sy_next = target->sy_next;
52033965Sjdp  target->sy_next = addme;
52133965Sjdp
52233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
52333965Sjdp  addme->sy_previous = target;
52433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
52533965Sjdp
52633965Sjdp  debug_verify_symchain (symbol_rootP, symbol_lastP);
52733965Sjdp}
52833965Sjdp
52933965Sjdp/* Set the chain pointers of SYMBOL to null. */
53033965Sjdpvoid
53133965Sjdpsymbol_clear_list_pointers (symbolP)
53233965Sjdp     symbolS *symbolP;
53333965Sjdp{
53433965Sjdp  symbolP->sy_next = NULL;
53533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
53633965Sjdp  symbolP->sy_previous = NULL;
53733965Sjdp#endif
53833965Sjdp}
53933965Sjdp
54033965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
54133965Sjdp/* Remove SYMBOLP from the list. */
54233965Sjdpvoid
54333965Sjdpsymbol_remove (symbolP, rootPP, lastPP)
54433965Sjdp     symbolS *symbolP;
54533965Sjdp     symbolS **rootPP;
54633965Sjdp     symbolS **lastPP;
54733965Sjdp{
54833965Sjdp  if (symbolP == *rootPP)
54933965Sjdp    {
55033965Sjdp      *rootPP = symbolP->sy_next;
55133965Sjdp    }				/* if it was the root */
55233965Sjdp
55333965Sjdp  if (symbolP == *lastPP)
55433965Sjdp    {
55533965Sjdp      *lastPP = symbolP->sy_previous;
55633965Sjdp    }				/* if it was the tail */
55733965Sjdp
55833965Sjdp  if (symbolP->sy_next != NULL)
55933965Sjdp    {
56033965Sjdp      symbolP->sy_next->sy_previous = symbolP->sy_previous;
56133965Sjdp    }				/* if not last */
56233965Sjdp
56333965Sjdp  if (symbolP->sy_previous != NULL)
56433965Sjdp    {
56533965Sjdp      symbolP->sy_previous->sy_next = symbolP->sy_next;
56633965Sjdp    }				/* if not first */
56733965Sjdp
56833965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
56933965Sjdp}
57033965Sjdp
57133965Sjdp/* Link symbol ADDME before symbol TARGET in the chain. */
57233965Sjdpvoid
57333965Sjdpsymbol_insert (addme, target, rootPP, lastPP)
57433965Sjdp     symbolS *addme;
57533965Sjdp     symbolS *target;
57633965Sjdp     symbolS **rootPP;
57733965Sjdp     symbolS **lastPP;
57833965Sjdp{
57933965Sjdp  if (target->sy_previous != NULL)
58033965Sjdp    {
58133965Sjdp      target->sy_previous->sy_next = addme;
58233965Sjdp    }
58333965Sjdp  else
58433965Sjdp    {
58533965Sjdp      know (*rootPP == target);
58633965Sjdp      *rootPP = addme;
58733965Sjdp    }				/* if not first */
58833965Sjdp
58933965Sjdp  addme->sy_previous = target->sy_previous;
59033965Sjdp  target->sy_previous = addme;
59133965Sjdp  addme->sy_next = target;
59233965Sjdp
59333965Sjdp  debug_verify_symchain (*rootPP, *lastPP);
59433965Sjdp}
59533965Sjdp
59633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
59733965Sjdp
59833965Sjdpvoid
59933965Sjdpverify_symbol_chain (rootP, lastP)
60033965Sjdp     symbolS *rootP;
60133965Sjdp     symbolS *lastP;
60233965Sjdp{
60333965Sjdp  symbolS *symbolP = rootP;
60433965Sjdp
60533965Sjdp  if (symbolP == NULL)
60633965Sjdp    return;
60733965Sjdp
60833965Sjdp  for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
60933965Sjdp    {
61033965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
61133965Sjdp      assert (symbolP->sy_next->sy_previous == symbolP);
61233965Sjdp#else
61333965Sjdp      /* Walk the list anyways, to make sure pointers are still good.  */
61433965Sjdp      ;
61533965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */
61633965Sjdp    }
61733965Sjdp
61833965Sjdp  assert (lastP == symbolP);
61933965Sjdp}
62033965Sjdp
62133965Sjdpvoid
62233965Sjdpverify_symbol_chain_2 (sym)
62333965Sjdp     symbolS *sym;
62433965Sjdp{
62533965Sjdp  symbolS *p = sym, *n = sym;
62633965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS
62733965Sjdp  while (symbol_previous (p))
62833965Sjdp    p = symbol_previous (p);
62933965Sjdp#endif
63033965Sjdp  while (symbol_next (n))
63133965Sjdp    n = symbol_next (n);
63233965Sjdp  verify_symbol_chain (p, n);
63333965Sjdp}
63433965Sjdp
63533965Sjdp/* Resolve the value of a symbol.  This is called during the final
63633965Sjdp   pass over the symbol table to resolve any symbols with complex
63733965Sjdp   values.  */
63833965Sjdp
63938889SjdpvalueT
64038889Sjdpresolve_symbol_value (symp, finalize)
64133965Sjdp     symbolS *symp;
64238889Sjdp     int finalize;
64333965Sjdp{
64433965Sjdp  int resolved;
64538889Sjdp  valueT final_val;
64638889Sjdp  segT final_seg;
64733965Sjdp
64833965Sjdp  if (symp->sy_resolved)
64938889Sjdp    {
65038889Sjdp      if (symp->sy_value.X_op == O_constant)
65138889Sjdp	return (valueT) symp->sy_value.X_add_number;
65238889Sjdp      else
65338889Sjdp	return 0;
65438889Sjdp    }
65533965Sjdp
65633965Sjdp  resolved = 0;
65738889Sjdp  final_seg = S_GET_SEGMENT (symp);
65833965Sjdp
65933965Sjdp  if (symp->sy_resolving)
66033965Sjdp    {
66138889Sjdp      if (finalize)
66238889Sjdp	as_bad ("Symbol definition loop encountered at %s", S_GET_NAME (symp));
66338889Sjdp      final_val = 0;
66433965Sjdp      resolved = 1;
66533965Sjdp    }
66633965Sjdp  else
66733965Sjdp    {
66838889Sjdp      symbolS *add_symbol, *op_symbol;
66938889Sjdp      offsetT left, right;
67033965Sjdp      segT seg_left, seg_right;
67138889Sjdp      operatorT op;
67233965Sjdp
67333965Sjdp      symp->sy_resolving = 1;
67433965Sjdp
67538889Sjdp      /* Help out with CSE.  */
67638889Sjdp      add_symbol = symp->sy_value.X_add_symbol;
67738889Sjdp      op_symbol = symp->sy_value.X_op_symbol;
67838889Sjdp      final_val = symp->sy_value.X_add_number;
67938889Sjdp      op = symp->sy_value.X_op;
68038889Sjdp
68138889Sjdp      switch (op)
68233965Sjdp	{
68338889Sjdp	default:
68438889Sjdp	  BAD_CASE (op);
68538889Sjdp	  break;
68633965Sjdp
68733965Sjdp	case O_absent:
68838889Sjdp	  final_val = 0;
68933965Sjdp	  /* Fall through.  */
69038889Sjdp
69133965Sjdp	case O_constant:
69238889Sjdp	  final_val += symp->sy_frag->fr_address;
69338889Sjdp	  if (final_seg == expr_section)
69438889Sjdp	    final_seg = absolute_section;
69533965Sjdp	  resolved = 1;
69633965Sjdp	  break;
69733965Sjdp
69833965Sjdp	case O_symbol:
69938889Sjdp	case O_symbol_rva:
70038889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
70138889Sjdp	do_symbol:
70233965Sjdp
70333965Sjdp	  if (symp->sy_mri_common)
70433965Sjdp	    {
70533965Sjdp	      /* This is a symbol inside an MRI common section.  The
70633965Sjdp                 relocation routines are going to handle it specially.
70733965Sjdp                 Don't change the value.  */
70838889Sjdp	      resolved = add_symbol->sy_resolved;
70933965Sjdp	      break;
71033965Sjdp	    }
71133965Sjdp
71238889Sjdp	  if (finalize && final_val == 0)
71338889Sjdp	    copy_symbol_attributes (symp, add_symbol);
71433965Sjdp
71533965Sjdp	  /* If we have equated this symbol to an undefined symbol, we
71633965Sjdp             keep X_op set to O_symbol, and we don't change
71733965Sjdp             X_add_number.  This permits the routine which writes out
71833965Sjdp             relocation to detect this case, and convert the
71933965Sjdp             relocation to be against the symbol to which this symbol
72033965Sjdp             is equated.  */
72138889Sjdp	  if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
72233965Sjdp	    {
72338889Sjdp	      if (finalize)
72438889Sjdp		{
72538889Sjdp		  symp->sy_value.X_op = O_symbol;
72638889Sjdp		  S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
72738889Sjdp		  symp->sy_value.X_add_number = final_val;
72838889Sjdp		}
72938889Sjdp	      final_val = 0;
73038889Sjdp	      resolved = add_symbol->sy_resolved;
73138889Sjdp	      goto exit_dont_set_value;
73233965Sjdp	    }
73333965Sjdp	  else
73433965Sjdp	    {
73538889Sjdp	      final_val += symp->sy_frag->fr_address + left;
73638889Sjdp	      if (final_seg == expr_section || final_seg == undefined_section)
73738889Sjdp		final_seg = S_GET_SEGMENT (add_symbol);
73833965Sjdp	    }
73933965Sjdp
74038889Sjdp	  resolved = add_symbol->sy_resolved;
74133965Sjdp	  break;
74233965Sjdp
74333965Sjdp	case O_uminus:
74433965Sjdp	case O_bit_not:
74533965Sjdp	case O_logical_not:
74638889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
74738889Sjdp
74838889Sjdp	  if (op == O_uminus)
74938889Sjdp	    left = -left;
75038889Sjdp	  else if (op == O_logical_not)
75138889Sjdp	    left = !left;
75233965Sjdp	  else
75338889Sjdp	    left = ~left;
75438889Sjdp
75538889Sjdp	  final_val += left + symp->sy_frag->fr_address;
75638889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
75738889Sjdp	    final_seg = absolute_section;
75838889Sjdp
75938889Sjdp	  resolved = add_symbol->sy_resolved;
76033965Sjdp	  break;
76133965Sjdp
76233965Sjdp	case O_multiply:
76333965Sjdp	case O_divide:
76433965Sjdp	case O_modulus:
76533965Sjdp	case O_left_shift:
76633965Sjdp	case O_right_shift:
76733965Sjdp	case O_bit_inclusive_or:
76833965Sjdp	case O_bit_or_not:
76933965Sjdp	case O_bit_exclusive_or:
77033965Sjdp	case O_bit_and:
77133965Sjdp	case O_add:
77233965Sjdp	case O_subtract:
77333965Sjdp	case O_eq:
77433965Sjdp	case O_ne:
77533965Sjdp	case O_lt:
77633965Sjdp	case O_le:
77733965Sjdp	case O_ge:
77833965Sjdp	case O_gt:
77933965Sjdp	case O_logical_and:
78033965Sjdp	case O_logical_or:
78138889Sjdp	  left = resolve_symbol_value (add_symbol, finalize);
78238889Sjdp	  right = resolve_symbol_value (op_symbol, finalize);
78338889Sjdp	  seg_left = S_GET_SEGMENT (add_symbol);
78438889Sjdp	  seg_right = S_GET_SEGMENT (op_symbol);
78533965Sjdp
78638889Sjdp	  /* Simplify addition or subtraction of a constant by folding the
78738889Sjdp	     constant into X_add_number.  */
78838889Sjdp	  if (op == O_add || op == O_subtract)
78938889Sjdp	    {
79038889Sjdp	      if (seg_right == absolute_section)
79138889Sjdp		{
79238889Sjdp		  if (op == O_add)
79338889Sjdp		    final_val += right;
79438889Sjdp		  else
79538889Sjdp		    final_val -= right;
79638889Sjdp		  op = O_symbol;
79738889Sjdp		  op_symbol = NULL;
79838889Sjdp		  goto do_symbol;
79938889Sjdp		}
80038889Sjdp	      else if (seg_left == absolute_section && op == O_add)
80138889Sjdp		{
80238889Sjdp		  op = O_symbol;
80338889Sjdp		  final_val += left;
80438889Sjdp		  add_symbol = op_symbol;
80538889Sjdp		  left = right;
80638889Sjdp		  op_symbol = NULL;
80738889Sjdp		  goto do_symbol;
80838889Sjdp		}
80938889Sjdp	    }
81038889Sjdp
81133965Sjdp	  /* Subtraction is permitted if both operands are in the same
81233965Sjdp	     section.  Otherwise, both operands must be absolute.  We
81333965Sjdp	     already handled the case of addition or subtraction of a
81433965Sjdp	     constant above.  This will probably need to be changed
81533965Sjdp	     for an object file format which supports arbitrary
81633965Sjdp	     expressions, such as IEEE-695.  */
81738889Sjdp	  /* Don't emit messages unless we're finalizing the symbol value,
81838889Sjdp	     otherwise we may get the same message multiple times.  */
81938889Sjdp	  if ((seg_left != absolute_section || seg_right != absolute_section)
82038889Sjdp	      && (op != O_subtract || seg_left != seg_right)
82138889Sjdp	      && finalize)
82233965Sjdp	    {
82333965Sjdp	      char *file;
82433965Sjdp	      unsigned int line;
82533965Sjdp
82633965Sjdp	      if (expr_symbol_where (symp, &file, &line))
82733965Sjdp		{
82833965Sjdp		  if (seg_left == undefined_section)
82933965Sjdp		    as_bad_where (file, line,
83033965Sjdp				  "undefined symbol %s in operation",
83133965Sjdp				  S_GET_NAME (symp->sy_value.X_add_symbol));
83233965Sjdp		  if (seg_right == undefined_section)
83333965Sjdp		    as_bad_where (file, line,
83433965Sjdp				  "undefined symbol %s in operation",
83533965Sjdp				  S_GET_NAME (symp->sy_value.X_op_symbol));
83633965Sjdp		  if (seg_left != undefined_section
83733965Sjdp		      && seg_right != undefined_section)
83833965Sjdp		    as_bad_where (file, line, "invalid section for operation");
83933965Sjdp		}
84033965Sjdp	      else
84133965Sjdp		{
84233965Sjdp		  if (seg_left == undefined_section)
84333965Sjdp		    as_bad ("undefined symbol %s in operation setting %s",
84433965Sjdp			    S_GET_NAME (symp->sy_value.X_add_symbol),
84533965Sjdp			    S_GET_NAME (symp));
84633965Sjdp		  if (seg_right == undefined_section)
84733965Sjdp		    as_bad ("undefined symbol %s in operation setting %s",
84833965Sjdp			    S_GET_NAME (symp->sy_value.X_op_symbol),
84933965Sjdp			    S_GET_NAME (symp));
85033965Sjdp		  if (seg_left != undefined_section
85133965Sjdp		      && seg_right != undefined_section)
85233965Sjdp		    as_bad ("invalid section for operation setting %s",
85333965Sjdp			    S_GET_NAME (symp));
85433965Sjdp		}
85533965Sjdp	    }
85633965Sjdp
85738889Sjdp	  /* Check for division by zero.  */
85838889Sjdp	  if ((op == O_divide || op == O_modulus) && right == 0)
85938889Sjdp	    {
86038889Sjdp	      /* If seg_right is not absolute_section, then we've
86138889Sjdp                 already issued a warning about using a bad symbol.  */
86238889Sjdp	      if (seg_right == absolute_section && finalize)
86338889Sjdp		{
86438889Sjdp		  char *file;
86538889Sjdp		  unsigned int line;
86638889Sjdp
86738889Sjdp		  if (expr_symbol_where (symp, &file, &line))
86838889Sjdp		    as_bad_where (file, line, "division by zero");
86938889Sjdp		  else
87038889Sjdp		    as_bad ("division by zero when setting %s",
87138889Sjdp			    S_GET_NAME (symp));
87238889Sjdp		}
87338889Sjdp
87438889Sjdp	      right = 1;
87538889Sjdp	    }
87638889Sjdp
87733965Sjdp	  switch (symp->sy_value.X_op)
87833965Sjdp	    {
87938889Sjdp	    case O_multiply:		left *= right; break;
88038889Sjdp	    case O_divide:		left /= right; break;
88138889Sjdp	    case O_modulus:		left %= right; break;
88238889Sjdp	    case O_left_shift:		left <<= right; break;
88338889Sjdp	    case O_right_shift:		left >>= right; break;
88438889Sjdp	    case O_bit_inclusive_or:	left |= right; break;
88538889Sjdp	    case O_bit_or_not:		left |= ~right; break;
88638889Sjdp	    case O_bit_exclusive_or:	left ^= right; break;
88738889Sjdp	    case O_bit_and:		left &= right; break;
88838889Sjdp	    case O_add:			left += right; break;
88938889Sjdp	    case O_subtract:		left -= right; break;
89038889Sjdp	    case O_eq:	left = left == right ? ~ (offsetT) 0 : 0; break;
89138889Sjdp	    case O_ne:	left = left != right ? ~ (offsetT) 0 : 0; break;
89238889Sjdp	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;
89338889Sjdp	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;
89438889Sjdp	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;
89538889Sjdp	    case O_gt:	left = left >  right ? ~ (offsetT) 0 : 0; break;
89638889Sjdp	    case O_logical_and:	left = left && right; break;
89738889Sjdp	    case O_logical_or:	left = left || right; break;
89838889Sjdp	    default:		abort ();
89933965Sjdp	    }
90038889Sjdp
90138889Sjdp	  final_val += symp->sy_frag->fr_address + left;
90238889Sjdp	  if (final_seg == expr_section || final_seg == undefined_section)
90338889Sjdp	    final_seg = absolute_section;
90438889Sjdp	  resolved = (add_symbol->sy_resolved && op_symbol->sy_resolved);
90533965Sjdp   	  break;
90633965Sjdp
90733965Sjdp	case O_register:
90833965Sjdp	case O_big:
90933965Sjdp	case O_illegal:
91033965Sjdp	  /* Give an error (below) if not in expr_section.  We don't
91133965Sjdp	     want to worry about expr_section symbols, because they
91233965Sjdp	     are fictional (they are created as part of expression
91333965Sjdp	     resolution), and any problems may not actually mean
91433965Sjdp	     anything.  */
91533965Sjdp	  break;
91633965Sjdp	}
91738889Sjdp
91838889Sjdp      symp->sy_resolving = 0;
91933965Sjdp    }
92033965Sjdp
92138889Sjdp  if (finalize)
92238889Sjdp    {
92338889Sjdp      S_SET_VALUE (symp, final_val);
92438889Sjdp
92538889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
92638889Sjdp      /* The old a.out backend does not handle S_SET_SEGMENT correctly
92738889Sjdp         for a stab symbol, so we use this bad hack.  */
92838889Sjdp      if (final_seg != S_GET_SEGMENT (symp))
92938889Sjdp#endif
93038889Sjdp	S_SET_SEGMENT (symp, final_seg);
93138889Sjdp    }
93238889Sjdp
93338889Sjdpexit_dont_set_value:
93433965Sjdp  /* Don't worry if we can't resolve an expr_section symbol.  */
93538889Sjdp  if (finalize)
93633965Sjdp    {
93738889Sjdp      if (resolved)
93838889Sjdp	symp->sy_resolved = 1;
93938889Sjdp      else if (S_GET_SEGMENT (symp) != expr_section)
94038889Sjdp	{
94138889Sjdp	  as_bad ("can't resolve value for symbol \"%s\"", S_GET_NAME (symp));
94238889Sjdp	  symp->sy_resolved = 1;
94338889Sjdp	}
94433965Sjdp    }
94538889Sjdp
94638889Sjdp  return final_val;
94733965Sjdp}
94833965Sjdp
94933965Sjdp/* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
95033965Sjdp   They are *really* local.  That is, they go out of scope whenever we see a
95133965Sjdp   label that isn't local.  Also, like fb labels, there can be multiple
95233965Sjdp   instances of a dollar label.  Therefor, we name encode each instance with
95333965Sjdp   the instance number, keep a list of defined symbols separate from the real
95433965Sjdp   symbol table, and we treat these buggers as a sparse array.  */
95533965Sjdp
95633965Sjdpstatic long *dollar_labels;
95733965Sjdpstatic long *dollar_label_instances;
95833965Sjdpstatic char *dollar_label_defines;
95938889Sjdpstatic unsigned long dollar_label_count;
96033965Sjdpstatic unsigned long dollar_label_max;
96133965Sjdp
96233965Sjdpint
96333965Sjdpdollar_label_defined (label)
96433965Sjdp     long label;
96533965Sjdp{
96633965Sjdp  long *i;
96733965Sjdp
96833965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
96933965Sjdp
97033965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
97133965Sjdp    if (*i == label)
97233965Sjdp      return dollar_label_defines[i - dollar_labels];
97333965Sjdp
97433965Sjdp  /* if we get here, label isn't defined */
97533965Sjdp  return 0;
97633965Sjdp}				/* dollar_label_defined() */
97733965Sjdp
97833965Sjdpstatic long
97933965Sjdpdollar_label_instance (label)
98033965Sjdp     long label;
98133965Sjdp{
98233965Sjdp  long *i;
98333965Sjdp
98433965Sjdp  know ((dollar_labels != NULL) || (dollar_label_count == 0));
98533965Sjdp
98633965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
98733965Sjdp    if (*i == label)
98833965Sjdp      return (dollar_label_instances[i - dollar_labels]);
98933965Sjdp
99033965Sjdp  /* If we get here, we haven't seen the label before, therefore its instance
99133965Sjdp     count is zero.  */
99233965Sjdp  return 0;
99333965Sjdp}
99433965Sjdp
99533965Sjdpvoid
99633965Sjdpdollar_label_clear ()
99733965Sjdp{
99833965Sjdp  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
99933965Sjdp}
100033965Sjdp
100133965Sjdp#define DOLLAR_LABEL_BUMP_BY 10
100233965Sjdp
100333965Sjdpvoid
100433965Sjdpdefine_dollar_label (label)
100533965Sjdp     long label;
100633965Sjdp{
100733965Sjdp  long *i;
100833965Sjdp
100933965Sjdp  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
101033965Sjdp    if (*i == label)
101133965Sjdp      {
101233965Sjdp	++dollar_label_instances[i - dollar_labels];
101333965Sjdp	dollar_label_defines[i - dollar_labels] = 1;
101433965Sjdp	return;
101533965Sjdp      }
101633965Sjdp
101733965Sjdp  /* if we get to here, we don't have label listed yet. */
101833965Sjdp
101933965Sjdp  if (dollar_labels == NULL)
102033965Sjdp    {
102133965Sjdp      dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
102233965Sjdp      dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
102333965Sjdp      dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
102433965Sjdp      dollar_label_max = DOLLAR_LABEL_BUMP_BY;
102533965Sjdp      dollar_label_count = 0;
102633965Sjdp    }
102733965Sjdp  else if (dollar_label_count == dollar_label_max)
102833965Sjdp    {
102933965Sjdp      dollar_label_max += DOLLAR_LABEL_BUMP_BY;
103033965Sjdp      dollar_labels = (long *) xrealloc ((char *) dollar_labels,
103133965Sjdp					 dollar_label_max * sizeof (long));
103233965Sjdp      dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
103333965Sjdp					  dollar_label_max * sizeof (long));
103433965Sjdp      dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
103533965Sjdp    }				/* if we needed to grow */
103633965Sjdp
103733965Sjdp  dollar_labels[dollar_label_count] = label;
103833965Sjdp  dollar_label_instances[dollar_label_count] = 1;
103933965Sjdp  dollar_label_defines[dollar_label_count] = 1;
104033965Sjdp  ++dollar_label_count;
104133965Sjdp}
104233965Sjdp
104333965Sjdp/*
104433965Sjdp *			dollar_label_name()
104533965Sjdp *
104633965Sjdp * Caller must copy returned name: we re-use the area for the next name.
104733965Sjdp *
104833965Sjdp * The mth occurence of label n: is turned into the symbol "Ln^Am"
104933965Sjdp * where n is the label number and m is the instance number. "L" makes
105033965Sjdp * it a label discarded unless debugging and "^A"('\1') ensures no
105133965Sjdp * ordinary symbol SHOULD get the same name as a local label
105233965Sjdp * symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
105333965Sjdp *
105433965Sjdp * fb labels get the same treatment, except that ^B is used in place of ^A.
105533965Sjdp */
105633965Sjdp
105733965Sjdpchar *				/* Return local label name. */
105833965Sjdpdollar_label_name (n, augend)
105933965Sjdp     register long n;		/* we just saw "n$:" : n a number */
106033965Sjdp     register int augend;	/* 0 for current instance, 1 for new instance */
106133965Sjdp{
106233965Sjdp  long i;
106333965Sjdp  /* Returned to caller, then copied.  used for created names ("4f") */
106433965Sjdp  static char symbol_name_build[24];
106533965Sjdp  register char *p;
106633965Sjdp  register char *q;
106733965Sjdp  char symbol_name_temporary[20];	/* build up a number, BACKWARDS */
106833965Sjdp
106933965Sjdp  know (n >= 0);
107033965Sjdp  know (augend == 0 || augend == 1);
107133965Sjdp  p = symbol_name_build;
107233965Sjdp  *p++ = 'L';
107333965Sjdp
107433965Sjdp  /* Next code just does sprintf( {}, "%d", n); */
107533965Sjdp  /* label number */
107633965Sjdp  q = symbol_name_temporary;
107733965Sjdp  for (*q++ = 0, i = n; i; ++q)
107833965Sjdp    {
107933965Sjdp      *q = i % 10 + '0';
108033965Sjdp      i /= 10;
108133965Sjdp    }
108233965Sjdp  while ((*p = *--q) != '\0')
108333965Sjdp    ++p;
108433965Sjdp
108533965Sjdp  *p++ = 1;			/* ^A */
108633965Sjdp
108733965Sjdp  /* instance number */
108833965Sjdp  q = symbol_name_temporary;
108933965Sjdp  for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
109033965Sjdp    {
109133965Sjdp      *q = i % 10 + '0';
109233965Sjdp      i /= 10;
109333965Sjdp    }
109433965Sjdp  while ((*p++ = *--q) != '\0');;
109533965Sjdp
109633965Sjdp  /* The label, as a '\0' ended string, starts at symbol_name_build. */
109733965Sjdp  return symbol_name_build;
109833965Sjdp}
109933965Sjdp
110033965Sjdp/*
110133965Sjdp * Sombody else's idea of local labels. They are made by "n:" where n
110233965Sjdp * is any decimal digit. Refer to them with
110333965Sjdp *  "nb" for previous (backward) n:
110433965Sjdp *  or "nf" for next (forward) n:.
110533965Sjdp *
110633965Sjdp * We do a little better and let n be any number, not just a single digit, but
110733965Sjdp * since the other guy's assembler only does ten, we treat the first ten
110833965Sjdp * specially.
110933965Sjdp *
111033965Sjdp * Like someone else's assembler, we have one set of local label counters for
111133965Sjdp * entire assembly, not one set per (sub)segment like in most assemblers. This
111233965Sjdp * implies that one can refer to a label in another segment, and indeed some
111333965Sjdp * crufty compilers have done just that.
111433965Sjdp *
111533965Sjdp * Since there could be a LOT of these things, treat them as a sparse array.
111633965Sjdp */
111733965Sjdp
111833965Sjdp#define FB_LABEL_SPECIAL (10)
111933965Sjdp
112033965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL];
112133965Sjdpstatic long *fb_labels;
112233965Sjdpstatic long *fb_label_instances;
112333965Sjdpstatic long fb_label_count;
112433965Sjdpstatic long fb_label_max;
112533965Sjdp
112633965Sjdp/* this must be more than FB_LABEL_SPECIAL */
112733965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
112833965Sjdp
112933965Sjdpstatic void
113033965Sjdpfb_label_init ()
113133965Sjdp{
113233965Sjdp  memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
113333965Sjdp}				/* fb_label_init() */
113433965Sjdp
113533965Sjdp/* add one to the instance number of this fb label */
113633965Sjdpvoid
113733965Sjdpfb_label_instance_inc (label)
113833965Sjdp     long label;
113933965Sjdp{
114033965Sjdp  long *i;
114133965Sjdp
114233965Sjdp  if (label < FB_LABEL_SPECIAL)
114333965Sjdp    {
114433965Sjdp      ++fb_low_counter[label];
114533965Sjdp      return;
114633965Sjdp    }
114733965Sjdp
114833965Sjdp  if (fb_labels != NULL)
114933965Sjdp    {
115033965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
115133965Sjdp	   i < fb_labels + fb_label_count; ++i)
115233965Sjdp	{
115333965Sjdp	  if (*i == label)
115433965Sjdp	    {
115533965Sjdp	      ++fb_label_instances[i - fb_labels];
115633965Sjdp	      return;
115733965Sjdp	    }			/* if we find it */
115833965Sjdp	}			/* for each existing label */
115933965Sjdp    }
116033965Sjdp
116133965Sjdp  /* if we get to here, we don't have label listed yet. */
116233965Sjdp
116333965Sjdp  if (fb_labels == NULL)
116433965Sjdp    {
116533965Sjdp      fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
116633965Sjdp      fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
116733965Sjdp      fb_label_max = FB_LABEL_BUMP_BY;
116833965Sjdp      fb_label_count = FB_LABEL_SPECIAL;
116933965Sjdp
117033965Sjdp    }
117133965Sjdp  else if (fb_label_count == fb_label_max)
117233965Sjdp    {
117333965Sjdp      fb_label_max += FB_LABEL_BUMP_BY;
117433965Sjdp      fb_labels = (long *) xrealloc ((char *) fb_labels,
117533965Sjdp				     fb_label_max * sizeof (long));
117633965Sjdp      fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
117733965Sjdp					      fb_label_max * sizeof (long));
117833965Sjdp    }				/* if we needed to grow */
117933965Sjdp
118033965Sjdp  fb_labels[fb_label_count] = label;
118133965Sjdp  fb_label_instances[fb_label_count] = 1;
118233965Sjdp  ++fb_label_count;
118333965Sjdp}
118433965Sjdp
118533965Sjdpstatic long
118633965Sjdpfb_label_instance (label)
118733965Sjdp     long label;
118833965Sjdp{
118933965Sjdp  long *i;
119033965Sjdp
119133965Sjdp  if (label < FB_LABEL_SPECIAL)
119233965Sjdp    {
119333965Sjdp      return (fb_low_counter[label]);
119433965Sjdp    }
119533965Sjdp
119633965Sjdp  if (fb_labels != NULL)
119733965Sjdp    {
119833965Sjdp      for (i = fb_labels + FB_LABEL_SPECIAL;
119933965Sjdp	   i < fb_labels + fb_label_count; ++i)
120033965Sjdp	{
120133965Sjdp	  if (*i == label)
120233965Sjdp	    {
120333965Sjdp	      return (fb_label_instances[i - fb_labels]);
120433965Sjdp	    }			/* if we find it */
120533965Sjdp	}			/* for each existing label */
120633965Sjdp    }
120733965Sjdp
120833965Sjdp  /* We didn't find the label, so this must be a reference to the
120933965Sjdp     first instance.  */
121033965Sjdp  return 0;
121133965Sjdp}
121233965Sjdp
121333965Sjdp/*
121433965Sjdp *			fb_label_name()
121533965Sjdp *
121633965Sjdp * Caller must copy returned name: we re-use the area for the next name.
121733965Sjdp *
121833965Sjdp * The mth occurence of label n: is turned into the symbol "Ln^Bm"
121933965Sjdp * where n is the label number and m is the instance number. "L" makes
122033965Sjdp * it a label discarded unless debugging and "^B"('\2') ensures no
122133965Sjdp * ordinary symbol SHOULD get the same name as a local label
122233965Sjdp * symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
122333965Sjdp *
122433965Sjdp * dollar labels get the same treatment, except that ^A is used in place of ^B. */
122533965Sjdp
122633965Sjdpchar *				/* Return local label name. */
122733965Sjdpfb_label_name (n, augend)
122833965Sjdp     long n;			/* we just saw "n:", "nf" or "nb" : n a number */
122933965Sjdp     long augend;		/* 0 for nb, 1 for n:, nf */
123033965Sjdp{
123133965Sjdp  long i;
123233965Sjdp  /* Returned to caller, then copied.  used for created names ("4f") */
123333965Sjdp  static char symbol_name_build[24];
123433965Sjdp  register char *p;
123533965Sjdp  register char *q;
123633965Sjdp  char symbol_name_temporary[20];	/* build up a number, BACKWARDS */
123733965Sjdp
123833965Sjdp  know (n >= 0);
123933965Sjdp  know (augend == 0 || augend == 1);
124033965Sjdp  p = symbol_name_build;
124133965Sjdp  *p++ = 'L';
124233965Sjdp
124333965Sjdp  /* Next code just does sprintf( {}, "%d", n); */
124433965Sjdp  /* label number */
124533965Sjdp  q = symbol_name_temporary;
124633965Sjdp  for (*q++ = 0, i = n; i; ++q)
124733965Sjdp    {
124833965Sjdp      *q = i % 10 + '0';
124933965Sjdp      i /= 10;
125033965Sjdp    }
125133965Sjdp  while ((*p = *--q) != '\0')
125233965Sjdp    ++p;
125333965Sjdp
125433965Sjdp  *p++ = 2;			/* ^B */
125533965Sjdp
125633965Sjdp  /* instance number */
125733965Sjdp  q = symbol_name_temporary;
125833965Sjdp  for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
125933965Sjdp    {
126033965Sjdp      *q = i % 10 + '0';
126133965Sjdp      i /= 10;
126233965Sjdp    }
126333965Sjdp  while ((*p++ = *--q) != '\0');;
126433965Sjdp
126533965Sjdp  /* The label, as a '\0' ended string, starts at symbol_name_build. */
126633965Sjdp  return (symbol_name_build);
126733965Sjdp}				/* fb_label_name() */
126833965Sjdp
126933965Sjdp/*
127033965Sjdp * decode name that may have been generated by foo_label_name() above.  If
127133965Sjdp * the name wasn't generated by foo_label_name(), then return it unaltered.
127233965Sjdp * This is used for error messages.
127333965Sjdp */
127433965Sjdp
127533965Sjdpchar *
127633965Sjdpdecode_local_label_name (s)
127733965Sjdp     char *s;
127833965Sjdp{
127933965Sjdp  char *p;
128033965Sjdp  char *symbol_decode;
128133965Sjdp  int label_number;
128233965Sjdp  int instance_number;
128333965Sjdp  char *type;
128433965Sjdp  const char *message_format = "\"%d\" (instance number %d of a %s label)";
128533965Sjdp
128633965Sjdp  if (s[0] != 'L')
128733965Sjdp    return s;
128833965Sjdp
128938889Sjdp  for (label_number = 0, p = s + 1; isdigit ((unsigned char) *p); ++p)
129033965Sjdp    label_number = (10 * label_number) + *p - '0';
129133965Sjdp
129233965Sjdp  if (*p == 1)
129333965Sjdp    type = "dollar";
129433965Sjdp  else if (*p == 2)
129533965Sjdp    type = "fb";
129633965Sjdp  else
129733965Sjdp    return s;
129833965Sjdp
129938889Sjdp  for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
130033965Sjdp    instance_number = (10 * instance_number) + *p - '0';
130133965Sjdp
130233965Sjdp  symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
130333965Sjdp  sprintf (symbol_decode, message_format, label_number, instance_number, type);
130433965Sjdp
130533965Sjdp  return symbol_decode;
130633965Sjdp}
130733965Sjdp
130833965Sjdp/* Get the value of a symbol.  */
130933965Sjdp
131033965SjdpvalueT
131133965SjdpS_GET_VALUE (s)
131233965Sjdp     symbolS *s;
131333965Sjdp{
131438889Sjdp  if (!s->sy_resolved && s->sy_value.X_op != O_constant)
131538889Sjdp    resolve_symbol_value (s, 1);
131633965Sjdp  if (s->sy_value.X_op != O_constant)
131733965Sjdp    {
131833965Sjdp      static symbolS *recur;
131933965Sjdp
132033965Sjdp      /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
132133965Sjdp         may call S_GET_VALUE.  We use a static symbol to avoid the
132233965Sjdp         immediate recursion.  */
132333965Sjdp      if (recur == s)
132433965Sjdp	return (valueT) s->sy_value.X_add_number;
132533965Sjdp      recur = s;
132633965Sjdp      if (! s->sy_resolved
132733965Sjdp	  || s->sy_value.X_op != O_symbol
132833965Sjdp	  || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
132933965Sjdp	as_bad ("Attempt to get value of unresolved symbol %s",
133033965Sjdp		S_GET_NAME (s));
133133965Sjdp      recur = NULL;
133233965Sjdp    }
133333965Sjdp  return (valueT) s->sy_value.X_add_number;
133433965Sjdp}
133533965Sjdp
133633965Sjdp/* Set the value of a symbol.  */
133733965Sjdp
133833965Sjdpvoid
133933965SjdpS_SET_VALUE (s, val)
134033965Sjdp     symbolS *s;
134133965Sjdp     valueT val;
134233965Sjdp{
134333965Sjdp  s->sy_value.X_op = O_constant;
134433965Sjdp  s->sy_value.X_add_number = (offsetT) val;
134533965Sjdp  s->sy_value.X_unsigned = 0;
134633965Sjdp}
134733965Sjdp
134833965Sjdpvoid
134933965Sjdpcopy_symbol_attributes (dest, src)
135033965Sjdp     symbolS *dest, *src;
135133965Sjdp{
135233965Sjdp#ifdef BFD_ASSEMBLER
135333965Sjdp  /* In an expression, transfer the settings of these flags.
135433965Sjdp     The user can override later, of course.  */
135538889Sjdp#define COPIED_SYMFLAGS	(BSF_FUNCTION | BSF_OBJECT)
135633965Sjdp  dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
135733965Sjdp#endif
135833965Sjdp
135933965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
136033965Sjdp  OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
136133965Sjdp#endif
136233965Sjdp}
136333965Sjdp
136433965Sjdp#ifdef BFD_ASSEMBLER
136533965Sjdp
136633965Sjdpint
136733965SjdpS_IS_EXTERNAL (s)
136833965Sjdp     symbolS *s;
136933965Sjdp{
137033965Sjdp  flagword flags = s->bsym->flags;
137133965Sjdp
137233965Sjdp  /* sanity check */
137338889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
137433965Sjdp    abort ();
137533965Sjdp
137633965Sjdp  return (flags & BSF_GLOBAL) != 0;
137733965Sjdp}
137833965Sjdp
137933965Sjdpint
138033965SjdpS_IS_WEAK (s)
138133965Sjdp     symbolS *s;
138233965Sjdp{
138333965Sjdp  return (s->bsym->flags & BSF_WEAK) != 0;
138433965Sjdp}
138533965Sjdp
138633965Sjdpint
138733965SjdpS_IS_COMMON (s)
138833965Sjdp     symbolS *s;
138933965Sjdp{
139033965Sjdp  return bfd_is_com_section (s->bsym->section);
139133965Sjdp}
139233965Sjdp
139333965Sjdpint
139433965SjdpS_IS_DEFINED (s)
139533965Sjdp     symbolS *s;
139633965Sjdp{
139733965Sjdp  return s->bsym->section != undefined_section;
139833965Sjdp}
139933965Sjdp
140033965Sjdpint
140133965SjdpS_IS_DEBUG (s)
140233965Sjdp     symbolS *s;
140333965Sjdp{
140433965Sjdp  if (s->bsym->flags & BSF_DEBUGGING)
140533965Sjdp    return 1;
140633965Sjdp  return 0;
140733965Sjdp}
140833965Sjdp
140933965Sjdpint
141033965SjdpS_IS_LOCAL (s)
141133965Sjdp     symbolS *s;
141233965Sjdp{
141333965Sjdp  flagword flags = s->bsym->flags;
141433965Sjdp  const char *name;
141533965Sjdp
141633965Sjdp  /* sanity check */
141738889Sjdp  if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
141833965Sjdp    abort ();
141933965Sjdp
142033965Sjdp  if (bfd_get_section (s->bsym) == reg_section)
142133965Sjdp    return 1;
142233965Sjdp
142338889Sjdp  if (flag_strip_local_absolute
142438889Sjdp      && (flags & BSF_GLOBAL) == 0
142538889Sjdp      && bfd_get_section (s->bsym) == absolute_section)
142638889Sjdp    return 1;
142738889Sjdp
142833965Sjdp  name = S_GET_NAME (s);
142933965Sjdp  return (name != NULL
143033965Sjdp	  && ! S_IS_DEBUG (s)
143133965Sjdp	  && (strchr (name, '\001')
143233965Sjdp	      || strchr (name, '\002')
143333965Sjdp	      || (! flag_keep_locals
143433965Sjdp		  && (bfd_is_local_label (stdoutput, s->bsym)
143533965Sjdp		      || (flag_mri
143633965Sjdp			  && name[0] == '?'
143733965Sjdp			  && name[1] == '?')))));
143833965Sjdp}
143933965Sjdp
144033965Sjdpint
144133965SjdpS_IS_EXTERN (s)
144233965Sjdp     symbolS *s;
144333965Sjdp{
144433965Sjdp  return S_IS_EXTERNAL (s);
144533965Sjdp}
144633965Sjdp
144733965Sjdpint
144833965SjdpS_IS_STABD (s)
144933965Sjdp     symbolS *s;
145033965Sjdp{
145133965Sjdp  return S_GET_NAME (s) == 0;
145233965Sjdp}
145333965Sjdp
145433965SjdpCONST char *
145533965SjdpS_GET_NAME (s)
145633965Sjdp     symbolS *s;
145733965Sjdp{
145833965Sjdp  return s->bsym->name;
145933965Sjdp}
146033965Sjdp
146133965SjdpsegT
146233965SjdpS_GET_SEGMENT (s)
146333965Sjdp     symbolS *s;
146433965Sjdp{
146533965Sjdp  return s->bsym->section;
146633965Sjdp}
146733965Sjdp
146833965Sjdpvoid
146933965SjdpS_SET_SEGMENT (s, seg)
147033965Sjdp     symbolS *s;
147133965Sjdp     segT seg;
147233965Sjdp{
147338889Sjdp  /* Don't reassign section symbols.  The direct reason is to prevent seg
147438889Sjdp     faults assigning back to const global symbols such as *ABS*, but it
147538889Sjdp     shouldn't happen anyway.  */
147638889Sjdp
147738889Sjdp  if (s->bsym->flags & BSF_SECTION_SYM)
147838889Sjdp    {
147938889Sjdp      if (s->bsym->section != seg)
148038889Sjdp	abort();
148138889Sjdp    }
148238889Sjdp  else
148338889Sjdp    s->bsym->section = seg;
148433965Sjdp}
148533965Sjdp
148633965Sjdpvoid
148733965SjdpS_SET_EXTERNAL (s)
148833965Sjdp     symbolS *s;
148933965Sjdp{
149033965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
149133965Sjdp    {
149233965Sjdp      /* Let .weak override .global.  */
149333965Sjdp      return;
149433965Sjdp    }
149533965Sjdp  s->bsym->flags |= BSF_GLOBAL;
149633965Sjdp  s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
149733965Sjdp}
149833965Sjdp
149933965Sjdpvoid
150033965SjdpS_CLEAR_EXTERNAL (s)
150133965Sjdp     symbolS *s;
150233965Sjdp{
150333965Sjdp  if ((s->bsym->flags & BSF_WEAK) != 0)
150433965Sjdp    {
150533965Sjdp      /* Let .weak override.  */
150633965Sjdp      return;
150733965Sjdp    }
150833965Sjdp  s->bsym->flags |= BSF_LOCAL;
150933965Sjdp  s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
151033965Sjdp}
151133965Sjdp
151233965Sjdpvoid
151333965SjdpS_SET_WEAK (s)
151433965Sjdp     symbolS *s;
151533965Sjdp{
151633965Sjdp  s->bsym->flags |= BSF_WEAK;
151733965Sjdp  s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
151833965Sjdp}
151933965Sjdp
152033965Sjdpvoid
152133965SjdpS_SET_NAME (s, name)
152233965Sjdp     symbolS *s;
152333965Sjdp     char *name;
152433965Sjdp{
152533965Sjdp  s->bsym->name = name;
152633965Sjdp}
152733965Sjdp#endif /* BFD_ASSEMBLER */
152833965Sjdp
152933965Sjdpvoid
153033965Sjdpsymbol_begin ()
153133965Sjdp{
153233965Sjdp  symbol_lastP = NULL;
153333965Sjdp  symbol_rootP = NULL;		/* In case we have 0 symbols (!!) */
153433965Sjdp  sy_hash = hash_new ();
153533965Sjdp
153633965Sjdp  memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
153733965Sjdp#ifdef BFD_ASSEMBLER
153833965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
153933965Sjdp  abs_symbol.bsym = bfd_abs_section.symbol;
154033965Sjdp#endif
154133965Sjdp#else
154233965Sjdp  /* Can't initialise a union. Sigh. */
154333965Sjdp  S_SET_SEGMENT (&abs_symbol, absolute_section);
154433965Sjdp#endif
154533965Sjdp  abs_symbol.sy_value.X_op = O_constant;
154633965Sjdp  abs_symbol.sy_frag = &zero_address_frag;
154733965Sjdp
154833965Sjdp  if (LOCAL_LABELS_FB)
154933965Sjdp    fb_label_init ();
155033965Sjdp}
155133965Sjdp
155233965Sjdp
155333965Sjdpint indent_level;
155433965Sjdp
155533965Sjdp#if 0
155633965Sjdp
155733965Sjdpstatic void
155833965Sjdpindent ()
155933965Sjdp{
156033965Sjdp  printf ("%*s", indent_level * 4, "");
156133965Sjdp}
156233965Sjdp
156333965Sjdp#endif
156433965Sjdp
156533965Sjdpvoid
156633965Sjdpprint_symbol_value_1 (file, sym)
156733965Sjdp     FILE *file;
156833965Sjdp     symbolS *sym;
156933965Sjdp{
157033965Sjdp  const char *name = S_GET_NAME (sym);
157133965Sjdp  if (!name || !name[0])
157233965Sjdp    name = "(unnamed)";
157333965Sjdp  fprintf (file, "sym %lx %s", (unsigned long) sym, name);
157433965Sjdp  if (sym->sy_frag != &zero_address_frag)
157533965Sjdp    fprintf (file, " frag %lx", (long) sym->sy_frag);
157633965Sjdp  if (sym->written)
157733965Sjdp    fprintf (file, " written");
157833965Sjdp  if (sym->sy_resolved)
157933965Sjdp    fprintf (file, " resolved");
158033965Sjdp  else if (sym->sy_resolving)
158133965Sjdp    fprintf (file, " resolving");
158233965Sjdp  if (sym->sy_used_in_reloc)
158333965Sjdp    fprintf (file, " used-in-reloc");
158433965Sjdp  if (sym->sy_used)
158533965Sjdp    fprintf (file, " used");
158633965Sjdp  if (S_IS_LOCAL (sym))
158733965Sjdp    fprintf (file, " local");
158833965Sjdp  if (S_IS_EXTERN (sym))
158933965Sjdp    fprintf (file, " extern");
159033965Sjdp  if (S_IS_DEBUG (sym))
159133965Sjdp    fprintf (file, " debug");
159233965Sjdp  if (S_IS_DEFINED (sym))
159333965Sjdp    fprintf (file, " defined");
159433965Sjdp  fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
159533965Sjdp  if (sym->sy_resolved)
159633965Sjdp    {
159733965Sjdp      segT s = S_GET_SEGMENT (sym);
159833965Sjdp
159933965Sjdp      if (s != undefined_section
160033965Sjdp          && s != expr_section)
160133965Sjdp	fprintf (file, " %lx", (long) S_GET_VALUE (sym));
160233965Sjdp    }
160333965Sjdp  else if (indent_level < 8 && S_GET_SEGMENT (sym) != undefined_section)
160433965Sjdp    {
160533965Sjdp      indent_level++;
160633965Sjdp      fprintf (file, "\n%*s<", indent_level * 4, "");
160733965Sjdp      print_expr_1 (file, &sym->sy_value);
160833965Sjdp      fprintf (file, ">");
160933965Sjdp      indent_level--;
161033965Sjdp    }
161133965Sjdp  fflush (file);
161233965Sjdp}
161333965Sjdp
161433965Sjdpvoid
161533965Sjdpprint_symbol_value (sym)
161633965Sjdp     symbolS *sym;
161733965Sjdp{
161833965Sjdp  indent_level = 0;
161933965Sjdp  print_symbol_value_1 (stderr, sym);
162033965Sjdp  fprintf (stderr, "\n");
162133965Sjdp}
162233965Sjdp
162333965Sjdpvoid
162433965Sjdpprint_expr_1 (file, exp)
162533965Sjdp     FILE *file;
162633965Sjdp     expressionS *exp;
162733965Sjdp{
162833965Sjdp  fprintf (file, "expr %lx ", (long) exp);
162933965Sjdp  switch (exp->X_op)
163033965Sjdp    {
163133965Sjdp    case O_illegal:
163233965Sjdp      fprintf (file, "illegal");
163333965Sjdp      break;
163433965Sjdp    case O_absent:
163533965Sjdp      fprintf (file, "absent");
163633965Sjdp      break;
163733965Sjdp    case O_constant:
163833965Sjdp      fprintf (file, "constant %lx", (long) exp->X_add_number);
163933965Sjdp      break;
164033965Sjdp    case O_symbol:
164133965Sjdp      indent_level++;
164233965Sjdp      fprintf (file, "symbol\n%*s<", indent_level * 4, "");
164333965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
164433965Sjdp      fprintf (file, ">");
164533965Sjdp    maybe_print_addnum:
164633965Sjdp      if (exp->X_add_number)
164733965Sjdp	fprintf (file, "\n%*s%lx", indent_level * 4, "",
164833965Sjdp		 (long) exp->X_add_number);
164933965Sjdp      indent_level--;
165033965Sjdp      break;
165133965Sjdp    case O_register:
165233965Sjdp      fprintf (file, "register #%d", (int) exp->X_add_number);
165333965Sjdp      break;
165433965Sjdp    case O_big:
165533965Sjdp      fprintf (file, "big");
165633965Sjdp      break;
165733965Sjdp    case O_uminus:
165833965Sjdp      fprintf (file, "uminus -<");
165933965Sjdp      indent_level++;
166033965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
166133965Sjdp      fprintf (file, ">");
166233965Sjdp      goto maybe_print_addnum;
166333965Sjdp    case O_bit_not:
166433965Sjdp      fprintf (file, "bit_not");
166533965Sjdp      break;
166633965Sjdp    case O_multiply:
166733965Sjdp      fprintf (file, "multiply");
166833965Sjdp      break;
166933965Sjdp    case O_divide:
167033965Sjdp      fprintf (file, "divide");
167133965Sjdp      break;
167233965Sjdp    case O_modulus:
167333965Sjdp      fprintf (file, "modulus");
167433965Sjdp      break;
167533965Sjdp    case O_left_shift:
167633965Sjdp      fprintf (file, "lshift");
167733965Sjdp      break;
167833965Sjdp    case O_right_shift:
167933965Sjdp      fprintf (file, "rshift");
168033965Sjdp      break;
168133965Sjdp    case O_bit_inclusive_or:
168233965Sjdp      fprintf (file, "bit_ior");
168333965Sjdp      break;
168433965Sjdp    case O_bit_exclusive_or:
168533965Sjdp      fprintf (file, "bit_xor");
168633965Sjdp      break;
168733965Sjdp    case O_bit_and:
168833965Sjdp      fprintf (file, "bit_and");
168933965Sjdp      break;
169033965Sjdp    case O_eq:
169133965Sjdp      fprintf (file, "eq");
169233965Sjdp      break;
169333965Sjdp    case O_ne:
169433965Sjdp      fprintf (file, "ne");
169533965Sjdp      break;
169633965Sjdp    case O_lt:
169733965Sjdp      fprintf (file, "lt");
169833965Sjdp      break;
169933965Sjdp    case O_le:
170033965Sjdp      fprintf (file, "le");
170133965Sjdp      break;
170233965Sjdp    case O_ge:
170333965Sjdp      fprintf (file, "ge");
170433965Sjdp      break;
170533965Sjdp    case O_gt:
170633965Sjdp      fprintf (file, "gt");
170733965Sjdp      break;
170833965Sjdp    case O_logical_and:
170933965Sjdp      fprintf (file, "logical_and");
171033965Sjdp      break;
171133965Sjdp    case O_logical_or:
171233965Sjdp      fprintf (file, "logical_or");
171333965Sjdp      break;
171433965Sjdp    case O_add:
171533965Sjdp      indent_level++;
171633965Sjdp      fprintf (file, "add\n%*s<", indent_level * 4, "");
171733965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
171833965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
171933965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
172033965Sjdp      fprintf (file, ">");
172133965Sjdp      goto maybe_print_addnum;
172233965Sjdp    case O_subtract:
172333965Sjdp      indent_level++;
172433965Sjdp      fprintf (file, "subtract\n%*s<", indent_level * 4, "");
172533965Sjdp      print_symbol_value_1 (file, exp->X_add_symbol);
172633965Sjdp      fprintf (file, ">\n%*s<", indent_level * 4, "");
172733965Sjdp      print_symbol_value_1 (file, exp->X_op_symbol);
172833965Sjdp      fprintf (file, ">");
172933965Sjdp      goto maybe_print_addnum;
173033965Sjdp    default:
173133965Sjdp      fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
173233965Sjdp      break;
173333965Sjdp    }
173433965Sjdp  fflush (stdout);
173533965Sjdp}
173633965Sjdp
173733965Sjdpvoid
173833965Sjdpprint_expr (exp)
173933965Sjdp     expressionS *exp;
174033965Sjdp{
174133965Sjdp  print_expr_1 (stderr, exp);
174233965Sjdp  fprintf (stderr, "\n");
174333965Sjdp}
174433965Sjdp
174533965Sjdpvoid
174633965Sjdpsymbol_print_statistics (file)
174733965Sjdp     FILE *file;
174833965Sjdp{
174933965Sjdp  hash_print_statistics (file, "symbol table", sy_hash);
175033965Sjdp}
175133965Sjdp
175233965Sjdp/* end of symbols.c */
1753