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 (¬es, name, name_length); 10733965Sjdp preserved_copy_of_name = obstack_finish (¬es); 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 (¬es, 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 (¬es, 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