* Makefile.in (refcard.dvi): Use srcdir where necessary.
[deliverable/binutils-gdb.git] / gas / symbols.c
CommitLineData
fecd2382 1/* symbols.c -symbol table-
6efd877d 2
2b68b820 3 Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
6efd877d 4
a39116f1 5 This file is part of GAS, the GNU Assembler.
6efd877d 6
a39116f1
RP
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
6efd877d 11
a39116f1
RP
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
6efd877d 16
a39116f1
RP
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
fecd2382 20
2b68b820
KR
21#define DEBUG
22
6efd877d
KR
23#include <ctype.h>
24
fecd2382
RP
25#include "as.h"
26
27#include "obstack.h" /* For "symbols.h" */
28#include "subsegs.h"
29
30#ifndef WORKING_DOT_WORD
31extern int new_broken_words;
32#endif
fecd2382 33
2b68b820
KR
34/* symbol-name => struct symbol pointer */
35static struct hash_control *sy_hash;
fecd2382 36
a39116f1 37/* Below are commented in "symbols.h". */
6efd877d
KR
38symbolS *symbol_rootP;
39symbolS *symbol_lastP;
40symbolS abs_symbol;
fecd2382 41
6efd877d
KR
42symbolS *dot_text_symbol;
43symbolS *dot_data_symbol;
44symbolS *dot_bss_symbol;
fecd2382 45
6efd877d 46struct obstack notes;
fecd2382 47
85825401 48static void fb_label_init PARAMS ((void));
fecd2382 49
fecd2382 50void
6efd877d 51symbol_begin ()
fecd2382 52{
6efd877d
KR
53 symbol_lastP = NULL;
54 symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
55 sy_hash = hash_new ();
56 memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
2b68b820
KR
57#ifdef BFD_ASSEMBLER
58 abs_symbol.bsym = bfd_abs_section.symbol;
59#else
60 /* Can't initialise a union. Sigh. */
61 S_SET_SEGMENT (&abs_symbol, absolute_section);
62#endif
6efd877d
KR
63#ifdef LOCAL_LABELS_FB
64 fb_label_init ();
65#endif /* LOCAL_LABELS_FB */
fecd2382 66}
fecd2382 67
fecd2382
RP
68/*
69 * symbol_new()
70 *
71 * Return a pointer to a new symbol.
72 * Die if we can't make a new symbol.
73 * Fill in the symbol's values.
74 * Add symbol to end of symbol chain.
75 *
76 *
77 * Please always call this to create a new symbol.
78 *
79 * Changes since 1985: Symbol names may not contain '\0'. Sigh.
80 * 2nd argument is now a SEG rather than a TYPE. The mapping between
81 * segments and types is mostly encapsulated herein (actually, we inherit it
82 * from macros in struc-symbol.h).
83 */
84
6efd877d
KR
85symbolS *
86symbol_new (name, segment, value, frag)
2b68b820 87 CONST char *name; /* It is copied, the caller can destroy/modify */
6efd877d 88 segT segment; /* Segment identifier (SEG_<something>) */
2b68b820 89 valueT value; /* Symbol value */
6efd877d 90 fragS *frag; /* Associated fragment */
fecd2382 91{
6efd877d
KR
92 unsigned int name_length;
93 char *preserved_copy_of_name;
94 symbolS *symbolP;
95
96 name_length = strlen (name) + 1; /* +1 for \0 */
97 obstack_grow (&notes, name, name_length);
98 preserved_copy_of_name = obstack_finish (&notes);
2b68b820
KR
99#ifdef STRIP_UNDERSCORE
100 if (preserved_copy_of_name[0] == '_')
101 preserved_copy_of_name++;
102#endif
6efd877d
KR
103 symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
104
105 /* symbol must be born in some fixed state. This seems as good as any. */
106 memset (symbolP, 0, sizeof (symbolS));
107
2b68b820
KR
108
109#ifdef BFD_ASSEMBLER
110 symbolP->bsym = bfd_make_empty_symbol (stdoutput);
111 assert (symbolP->bsym != 0);
112 symbolP->bsym->udata = (PTR) symbolP;
113#endif
6efd877d 114 S_SET_NAME (symbolP, preserved_copy_of_name);
6efd877d
KR
115
116 S_SET_SEGMENT (symbolP, segment);
117 S_SET_VALUE (symbolP, value);
2b68b820 118 symbol_clear_list_pointers(symbolP);
6efd877d
KR
119
120 symbolP->sy_frag = frag;
2b68b820 121#ifndef BFD_ASSEMBLER
6efd877d
KR
122 symbolP->sy_number = ~0;
123 symbolP->sy_name_offset = ~0;
2b68b820 124#endif
6efd877d
KR
125
126 /*
2b68b820
KR
127 * Link to end of symbol chain.
128 */
6efd877d
KR
129 symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
130
131 obj_symbol_new_hook (symbolP);
132
fecd2382 133#ifdef DEBUG
2b68b820 134 verify_symbol_chain(symbol_rootP, symbol_lastP);
fecd2382 135#endif /* DEBUG */
fecd2382 136
2b68b820
KR
137 return symbolP;
138}
fecd2382 139\f
6efd877d 140
fecd2382
RP
141/*
142 * colon()
143 *
144 * We have just seen "<name>:".
145 * Creates a struct symbol unless it already exists.
146 *
147 * Gripes if we are redefining a symbol incompatibly (and ignores it).
148 *
149 */
6efd877d
KR
150void
151colon (sym_name) /* just seen "x:" - rattle symbols & frags */
152 register char *sym_name; /* symbol name, as a cannonical string */
153 /* We copy this string: OK to alter later. */
fecd2382 154{
6efd877d
KR
155 register symbolS *symbolP; /* symbol we are working with */
156
fecd2382 157#ifdef LOCAL_LABELS_DOLLAR
2b68b820
KR
158 /* Sun local labels go out of scope whenever a non-local symbol is
159 defined. */
6efd877d
KR
160
161 if (*sym_name != 'L')
162 dollar_label_clear ();
163#endif /* LOCAL_LABELS_DOLLAR */
164
fecd2382 165#ifndef WORKING_DOT_WORD
6efd877d
KR
166 if (new_broken_words)
167 {
168 struct broken_word *a;
169 int possible_bytes;
170 fragS *frag_tmp;
171 char *frag_opcode;
172
2b68b820
KR
173 extern const int md_short_jump_size;
174 extern const int md_long_jump_size;
175 possible_bytes = (md_short_jump_size
176 + new_broken_words * md_long_jump_size);
6efd877d
KR
177
178 frag_tmp = frag_now;
179 frag_opcode = frag_var (rs_broken_word,
180 possible_bytes,
181 possible_bytes,
182 (relax_substateT) 0,
183 (symbolS *) broken_words,
184 0L,
185 NULL);
186
187 /* We want to store the pointer to where to insert the jump table in the
2b68b820
KR
188 fr_opcode of the rs_broken_word frag. This requires a little
189 hackery. */
190 while (frag_tmp
191 && (frag_tmp->fr_type != rs_broken_word
192 || frag_tmp->fr_opcode))
6efd877d
KR
193 frag_tmp = frag_tmp->fr_next;
194 know (frag_tmp);
195 frag_tmp->fr_opcode = frag_opcode;
196 new_broken_words = 0;
197
198 for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
199 a->dispfrag = frag_tmp;
200 }
201#endif /* WORKING_DOT_WORD */
202
203 if ((symbolP = symbol_find (sym_name)) != 0)
204 {
2b68b820
KR
205#ifdef RESOLVE_SYMBOL_REDEFINITION
206 if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
6efd877d 207 return;
2b68b820 208#endif
6efd877d 209 /*
2b68b820
KR
210 * Now check for undefined symbols
211 */
6efd877d
KR
212 if (!S_IS_DEFINED (symbolP))
213 {
214 if (S_GET_VALUE (symbolP) == 0)
215 {
216 symbolP->sy_frag = frag_now;
2b68b820
KR
217#ifdef OBJ_VMS
218 S_GET_OTHER(symbolP) = const_flag;
fecd2382 219#endif
2b68b820 220 S_SET_VALUE (symbolP, (valueT) ((char*)obstack_next_free (&frags) - frag_now->fr_literal));
6efd877d 221 S_SET_SEGMENT (symbolP, now_seg);
fecd2382 222#ifdef N_UNDF
6efd877d 223 know (N_UNDF == 0);
fecd2382 224#endif /* if we have one, it better be zero. */
6efd877d
KR
225
226 }
227 else
228 {
229 /*
2b68b820
KR
230 * There are still several cases to check:
231 * A .comm/.lcomm symbol being redefined as
232 * initialized data is OK
233 * A .comm/.lcomm symbol being redefined with
234 * a larger size is also OK
235 *
236 * This only used to be allowed on VMS gas, but Sun cc
237 * on the sparc also depends on it.
238 */
239
240 if (((!S_IS_DEBUG (symbolP)
241 && !S_IS_DEFINED (symbolP)
242 && S_IS_EXTERNAL (symbolP))
243 || S_GET_SEGMENT (symbolP) == bss_section)
244 && (now_seg == data_section
245 || now_seg == S_GET_SEGMENT (symbolP)))
6efd877d
KR
246 {
247 /*
2b68b820
KR
248 * Select which of the 2 cases this is
249 */
250 if (now_seg != data_section)
6efd877d
KR
251 {
252 /*
2b68b820
KR
253 * New .comm for prev .comm symbol.
254 * If the new size is larger we just
255 * change its value. If the new size
256 * is smaller, we ignore this symbol
257 */
6efd877d 258 if (S_GET_VALUE (symbolP)
2b68b820 259 < ((unsigned) frag_now_fix ()))
6efd877d 260 {
2b68b820 261 S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
6efd877d
KR
262 }
263 }
264 else
265 {
85825401
ILT
266 /* It is a .comm/.lcomm being converted to initialized
267 data. */
6efd877d 268 symbolP->sy_frag = frag_now;
2b68b820
KR
269#ifdef OBJ_VMS
270 S_GET_OTHER(symbolP) = const_flag;
271#endif /* OBJ_VMS */
272 S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
6efd877d
KR
273 S_SET_SEGMENT (symbolP, now_seg); /* keep N_EXT bit */
274 }
275 }
276 else
277 {
2b68b820
KR
278#if defined (S_GET_OTHER) && defined (S_GET_DESC)
279 as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld.",
6efd877d
KR
280 sym_name,
281 segment_name (S_GET_SEGMENT (symbolP)),
2b68b820
KR
282 S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
283 (long) S_GET_VALUE (symbolP));
284#else
285 as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.",
6efd877d
KR
286 sym_name,
287 segment_name (S_GET_SEGMENT (symbolP)),
6efd877d 288 S_GET_VALUE (symbolP));
2b68b820 289#endif
6efd877d
KR
290 }
291 } /* if the undefined symbol has no value */
292 }
293 else
294 {
295 /* Don't blow up if the definition is the same */
296 if (!(frag_now == symbolP->sy_frag
2b68b820 297 && S_GET_VALUE (symbolP) == (char*)obstack_next_free (&frags) - frag_now->fr_literal
6efd877d
KR
298 && S_GET_SEGMENT (symbolP) == now_seg))
299 as_fatal ("Symbol %s already defined.", sym_name);
300 } /* if this symbol is not yet defined */
301
302 }
303 else
304 {
305 symbolP = symbol_new (sym_name,
306 now_seg,
2b68b820 307 (valueT) ((char*)obstack_next_free (&frags) - frag_now->fr_literal),
6efd877d 308 frag_now);
2b68b820 309#ifdef OBJ_VMS
6efd877d 310 S_SET_OTHER (symbolP, const_flag);
2b68b820 311#endif /* OBJ_VMS */
fecd2382 312
6efd877d
KR
313 symbol_table_insert (symbolP);
314 } /* if we have seen this symbol before */
1e9cf565
ILT
315
316#ifdef tc_frob_label
317 tc_frob_label (symbolP);
2b68b820 318#endif
6efd877d
KR
319
320 return;
321} /* colon() */
fecd2382 322\f
6efd877d 323
fecd2382
RP
324/*
325 * symbol_table_insert()
326 *
327 * Die if we can't insert the symbol.
328 *
329 */
330
6efd877d
KR
331void
332symbol_table_insert (symbolP)
333 symbolS *symbolP;
fecd2382 334{
6efd877d
KR
335 register char *error_string;
336
337 know (symbolP);
338 know (S_GET_NAME (symbolP));
339
340 if (*(error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (char *) symbolP)))
341 {
342 as_fatal ("Inserting \"%s\" into symbol table failed: %s",
343 S_GET_NAME (symbolP), error_string);
344 } /* on error */
345} /* symbol_table_insert() */
fecd2382
RP
346\f
347/*
348 * symbol_find_or_make()
349 *
350 * If a symbol name does not exist, create it as undefined, and insert
351 * it into the symbol table. Return a pointer to it.
352 */
6efd877d
KR
353symbolS *
354symbol_find_or_make (name)
355 char *name;
fecd2382 356{
6efd877d
KR
357 register symbolS *symbolP;
358
359 symbolP = symbol_find (name);
360
361 if (symbolP == NULL)
362 {
363 symbolP = symbol_make (name);
364
365 symbol_table_insert (symbolP);
366 } /* if symbol wasn't found */
367
368 return (symbolP);
369} /* symbol_find_or_make() */
370
371symbolS *
372symbol_make (name)
2b68b820 373 CONST char *name;
fecd2382 374{
6efd877d
KR
375 symbolS *symbolP;
376
377 /* Let the machine description default it, e.g. for register names. */
2b68b820 378 symbolP = md_undefined_symbol ((char *) name);
6efd877d
KR
379
380 if (!symbolP)
2b68b820 381 symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
6efd877d
KR
382
383 return (symbolP);
384} /* symbol_make() */
fecd2382
RP
385
386/*
387 * symbol_find()
6efd877d 388 *
fecd2382
RP
389 * Implement symbol table lookup.
390 * In: A symbol's name as a string: '\0' can't be part of a symbol name.
391 * Out: NULL if the name was not in the symbol table, else the address
392 * of a struct symbol associated with that name.
393 */
394
6efd877d
KR
395symbolS *
396symbol_find (name)
2b68b820 397 CONST char *name;
fecd2382 398{
a6c6eaf8 399#ifdef STRIP_UNDERSCORE
6efd877d 400 return (symbol_find_base (name, 1));
a6c6eaf8 401#else /* STRIP_UNDERSCORE */
6efd877d 402 return (symbol_find_base (name, 0));
fecd2382 403#endif /* STRIP_UNDERSCORE */
6efd877d 404} /* symbol_find() */
fecd2382 405
6efd877d
KR
406symbolS *
407symbol_find_base (name, strip_underscore)
2b68b820 408 CONST char *name;
6efd877d 409 int strip_underscore;
fecd2382 410{
6efd877d
KR
411 if (strip_underscore && *name == '_')
412 name++;
413 return ((symbolS *) hash_find (sy_hash, name));
fecd2382
RP
414}
415
416/*
417 * Once upon a time, symbols were kept in a singly linked list. At
418 * least coff needs to be able to rearrange them from time to time, for
419 * which a doubly linked list is much more convenient. Loic did these
420 * as macros which seemed dangerous to me so they're now functions.
421 * xoxorich.
422 */
423
424/* Link symbol ADDME after symbol TARGET in the chain. */
6efd877d
KR
425void
426symbol_append (addme, target, rootPP, lastPP)
427 symbolS *addme;
428 symbolS *target;
429 symbolS **rootPP;
430 symbolS **lastPP;
fecd2382 431{
6efd877d
KR
432 if (target == NULL)
433 {
434 know (*rootPP == NULL);
435 know (*lastPP == NULL);
436 *rootPP = addme;
437 *lastPP = addme;
438 return;
439 } /* if the list is empty */
440
441 if (target->sy_next != NULL)
442 {
fecd2382 443#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 444 target->sy_next->sy_previous = addme;
fecd2382 445#endif /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d
KR
446 }
447 else
448 {
449 know (*lastPP == target);
450 *lastPP = addme;
451 } /* if we have a next */
452
453 addme->sy_next = target->sy_next;
454 target->sy_next = addme;
455
fecd2382 456#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 457 addme->sy_previous = target;
fecd2382 458#endif /* SYMBOLS_NEED_BACKPOINTERS */
2b68b820 459}
fecd2382
RP
460
461#ifdef SYMBOLS_NEED_BACKPOINTERS
462/* Remove SYMBOLP from the list. */
6efd877d
KR
463void
464symbol_remove (symbolP, rootPP, lastPP)
465 symbolS *symbolP;
466 symbolS **rootPP;
467 symbolS **lastPP;
fecd2382 468{
6efd877d
KR
469 if (symbolP == *rootPP)
470 {
471 *rootPP = symbolP->sy_next;
472 } /* if it was the root */
473
474 if (symbolP == *lastPP)
475 {
476 *lastPP = symbolP->sy_previous;
477 } /* if it was the tail */
478
479 if (symbolP->sy_next != NULL)
480 {
481 symbolP->sy_next->sy_previous = symbolP->sy_previous;
482 } /* if not last */
483
484 if (symbolP->sy_previous != NULL)
485 {
486 symbolP->sy_previous->sy_next = symbolP->sy_next;
487 } /* if not first */
488
fecd2382 489#ifdef DEBUG
6efd877d 490 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 491#endif /* DEBUG */
2b68b820 492}
fecd2382
RP
493
494/* Set the chain pointers of SYMBOL to null. */
6efd877d
KR
495void
496symbol_clear_list_pointers (symbolP)
497 symbolS *symbolP;
fecd2382 498{
6efd877d
KR
499 symbolP->sy_next = NULL;
500 symbolP->sy_previous = NULL;
2b68b820 501}
fecd2382
RP
502
503/* Link symbol ADDME before symbol TARGET in the chain. */
6efd877d
KR
504void
505symbol_insert (addme, target, rootPP, lastPP)
506 symbolS *addme;
507 symbolS *target;
508 symbolS **rootPP;
509 symbolS **lastPP;
fecd2382 510{
6efd877d
KR
511 if (target->sy_previous != NULL)
512 {
513 target->sy_previous->sy_next = addme;
514 }
515 else
516 {
517 know (*rootPP == target);
518 *rootPP = addme;
519 } /* if not first */
520
521 addme->sy_previous = target->sy_previous;
522 target->sy_previous = addme;
523 addme->sy_next = target;
524
fecd2382 525#ifdef DEBUG
6efd877d 526 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 527#endif /* DEBUG */
2b68b820 528}
6efd877d 529
fecd2382
RP
530#endif /* SYMBOLS_NEED_BACKPOINTERS */
531
6efd877d
KR
532void
533verify_symbol_chain (rootP, lastP)
534 symbolS *rootP;
535 symbolS *lastP;
fecd2382 536{
6efd877d
KR
537 symbolS *symbolP = rootP;
538
539 if (symbolP == NULL)
2b68b820 540 return;
6efd877d
KR
541
542 for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
543 {
fecd2382 544#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 545 know (symbolP->sy_next->sy_previous == symbolP);
2b68b820
KR
546#else
547 /* Walk the list anyways, to make sure pointers are still good. */
548 *symbolP;
fecd2382 549#endif /* SYMBOLS_NEED_BACKPOINTERS */
2b68b820 550 }
6efd877d 551
2b68b820
KR
552 assert (lastP == symbolP);
553}
6efd877d 554
2b68b820
KR
555void
556verify_symbol_chain_2 (sym)
557 symbolS *sym;
558{
559 symbolS *p = sym, *n = sym;
560#ifdef SYMBOLS_NEED_BACKPOINTERS
561 while (symbol_previous (p))
562 p = symbol_previous (p);
563#endif
564 while (symbol_next (n))
565 n = symbol_next (n);
566 verify_symbol_chain (p, n);
567}
6efd877d 568
5868b1fe
ILT
569/* Resolve the value of a symbol. This is called during the final
570 pass over the symbol table to resolve any symbols with complex
571 values. */
572
573void
574resolve_symbol_value (symp)
575 symbolS *symp;
576{
577 if (symp->sy_resolved)
578 return;
579
580 if (symp->sy_resolving)
581 {
582 as_bad ("Symbol definition loop encountered at %s",
583 S_GET_NAME (symp));
584 S_SET_VALUE (symp, (valueT) 0);
585 }
586 else
587 {
588 symp->sy_resolving = 1;
589
590 if (symp->sy_value.X_seg == absolute_section)
591 S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
592 else if (symp->sy_value.X_seg == undefined_section)
593 {
594 resolve_symbol_value (symp->sy_value.X_add_symbol);
595
596#ifdef obj_frob_forward_symbol
597 /* Some object formats need to forward the segment. */
598 obj_frob_forward_symbol (symp);
599#endif
600
601 S_SET_VALUE (symp,
602 (symp->sy_value.X_add_number
603 + symp->sy_frag->fr_address
604 + S_GET_VALUE (symp->sy_value.X_add_symbol)));
605 }
c978e704
ILT
606 else if (symp->sy_value.X_seg == diff_section)
607 {
608 resolve_symbol_value (symp->sy_value.X_add_symbol);
609 resolve_symbol_value (symp->sy_value.X_subtract_symbol);
610 if (S_GET_SEGMENT (symp->sy_value.X_add_symbol)
611 != S_GET_SEGMENT (symp->sy_value.X_subtract_symbol))
612 as_bad ("%s is difference of symbols in different sections",
613 S_GET_NAME (symp));
614 S_SET_VALUE (symp,
615 (symp->sy_value.X_add_number
616 + symp->sy_frag->fr_address
617 + S_GET_VALUE (symp->sy_value.X_add_symbol)
618 - S_GET_VALUE (symp->sy_value.X_subtract_symbol)));
619 S_SET_SEGMENT (symp, absolute_section);
620 }
5868b1fe
ILT
621 else
622 {
623 /* More cases need to be added here. */
624 abort ();
625 }
626 }
627
628 symp->sy_resolved = 1;
629}
630
6efd877d
KR
631#ifdef LOCAL_LABELS_DOLLAR
632
633/* Dollar labels look like a number followed by a dollar sign. Eg, "42$".
634 They are *really* local. That is, they go out of scope whenever we see a
635 label that isn't local. Also, like fb labels, there can be multiple
636 instances of a dollar label. Therefor, we name encode each instance with
637 the instance number, keep a list of defined symbols separate from the real
638 symbol table, and we treat these buggers as a sparse array. */
639
2b68b820
KR
640static long *dollar_labels;
641static long *dollar_label_instances;
642static char *dollar_label_defines;
643static long dollar_label_count;
644static long dollar_label_max;
6efd877d
KR
645
646int
647dollar_label_defined (label)
648 long label;
649{
650 long *i;
651
652 know ((dollar_labels != NULL) || (dollar_label_count == 0));
653
654 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
655 if (*i == label)
656 return dollar_label_defines[i - dollar_labels];
6efd877d
KR
657
658 /* if we get here, label isn't defined */
2b68b820 659 return 0;
6efd877d
KR
660} /* dollar_label_defined() */
661
662static int
663dollar_label_instance (label)
664 long label;
665{
666 long *i;
667
668 know ((dollar_labels != NULL) || (dollar_label_count == 0));
669
670 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
671 if (*i == label)
672 return (dollar_label_instances[i - dollar_labels]);
6efd877d 673
2b68b820
KR
674 /* If we get here, we haven't seen the label before, therefore its instance
675 count is zero. */
676 return 0;
677}
6efd877d
KR
678
679void
680dollar_label_clear ()
681{
682 memset (dollar_label_defines, '\0', dollar_label_count);
2b68b820 683}
6efd877d
KR
684
685#define DOLLAR_LABEL_BUMP_BY 10
686
687void
688define_dollar_label (label)
689 long label;
690{
691 long *i;
692
693 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
694 if (*i == label)
695 {
696 ++dollar_label_instances[i - dollar_labels];
697 dollar_label_defines[i - dollar_labels] = 1;
698 return;
699 }
6efd877d
KR
700
701 /* if we get to here, we don't have label listed yet. */
702
703 if (dollar_labels == NULL)
704 {
705 dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
706 dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
707 dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
708 dollar_label_max = DOLLAR_LABEL_BUMP_BY;
709 dollar_label_count = 0;
6efd877d
KR
710 }
711 else if (dollar_label_count == dollar_label_max)
712 {
713 dollar_label_max += DOLLAR_LABEL_BUMP_BY;
714 dollar_labels = (long *) xrealloc ((char *) dollar_labels,
715 dollar_label_max * sizeof (long));
716 dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
717 dollar_label_max * sizeof (long));
718 dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
719 } /* if we needed to grow */
720
721 dollar_labels[dollar_label_count] = label;
722 dollar_label_instances[dollar_label_count] = 1;
723 dollar_label_defines[dollar_label_count] = 1;
724 ++dollar_label_count;
2b68b820 725}
6efd877d
KR
726
727/*
728 * dollar_label_name()
729 *
730 * Caller must copy returned name: we re-use the area for the next name.
731 *
2b68b820
KR
732 * The mth occurence of label n: is turned into the symbol "Ln^Am"
733 * where n is the label number and m is the instance number. "L" makes
734 * it a label discarded unless debugging and "^A"('\1') ensures no
735 * ordinary symbol SHOULD get the same name as a local label
736 * symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
6efd877d
KR
737 *
738 * fb labels get the same treatment, except that ^B is used in place of ^A.
739 */
740
741char * /* Return local label name. */
742dollar_label_name (n, augend)
743 register long n; /* we just saw "n$:" : n a number */
744 register int augend; /* 0 for current instance, 1 for new instance */
745{
746 long i;
747 /* Returned to caller, then copied. used for created names ("4f") */
748 static char symbol_name_build[24];
749 register char *p;
750 register char *q;
751 char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
752
753 know (n >= 0);
754 know (augend == 0 || augend == 1);
755 p = symbol_name_build;
756 *p++ = 'L';
757
758 /* Next code just does sprintf( {}, "%d", n); */
759 /* label number */
760 q = symbol_name_temporary;
761 for (*q++ = 0, i = n; i; ++q)
762 {
763 *q = i % 10 + '0';
764 i /= 10;
765 }
766 while ((*p = *--q) != '\0')
767 ++p;
768
769 *p++ = 1; /* ^A */
770
771 /* instance number */
772 q = symbol_name_temporary;
773 for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
774 {
775 *q = i % 10 + '0';
776 i /= 10;
777 }
778 while ((*p++ = *--q) != '\0');;
779
780 /* The label, as a '\0' ended string, starts at symbol_name_build. */
2b68b820
KR
781 return symbol_name_build;
782}
6efd877d
KR
783
784#endif /* LOCAL_LABELS_DOLLAR */
785
786#ifdef LOCAL_LABELS_FB
787
788/*
789 * Sombody else's idea of local labels. They are made by "n:" where n
790 * is any decimal digit. Refer to them with
791 * "nb" for previous (backward) n:
792 * or "nf" for next (forward) n:.
793 *
794 * We do a little better and let n be any number, not just a single digit, but
795 * since the other guy's assembler only does ten, we treat the first ten
796 * specially.
797 *
798 * Like someone else's assembler, we have one set of local label counters for
799 * entire assembly, not one set per (sub)segment like in most assemblers. This
800 * implies that one can refer to a label in another segment, and indeed some
801 * crufty compilers have done just that.
802 *
803 * Since there could be a LOT of these things, treat them as a sparse array.
804 */
805
806#define FB_LABEL_SPECIAL (10)
807
808static long fb_low_counter[FB_LABEL_SPECIAL];
809static long *fb_labels;
810static long *fb_label_instances;
811static long fb_label_count = 0;
812static long fb_label_max = 0;
813
814/* this must be more than FB_LABEL_SPECIAL */
815#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
816
817static void
818fb_label_init ()
819{
820 memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
6efd877d
KR
821} /* fb_label_init() */
822
823/* add one to the instance number of this fb label */
824void
825fb_label_instance_inc (label)
826 long label;
827{
828 long *i;
829
830 if (label < FB_LABEL_SPECIAL)
831 {
832 ++fb_low_counter[label];
833 return;
834 }
835
e154ecf4 836 if (fb_labels != NULL)
6efd877d 837 {
e154ecf4
ILT
838 for (i = fb_labels + FB_LABEL_SPECIAL;
839 i < fb_labels + fb_label_count; ++i)
6efd877d 840 {
e154ecf4
ILT
841 if (*i == label)
842 {
843 ++fb_label_instances[i - fb_labels];
844 return;
845 } /* if we find it */
846 } /* for each existing label */
847 }
6efd877d
KR
848
849 /* if we get to here, we don't have label listed yet. */
850
851 if (fb_labels == NULL)
852 {
853 fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
854 fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
855 fb_label_max = FB_LABEL_BUMP_BY;
856 fb_label_count = FB_LABEL_SPECIAL;
857
858 }
859 else if (fb_label_count == fb_label_max)
860 {
861 fb_label_max += FB_LABEL_BUMP_BY;
862 fb_labels = (long *) xrealloc ((char *) fb_labels,
863 fb_label_max * sizeof (long));
864 fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
865 fb_label_max * sizeof (long));
866 } /* if we needed to grow */
867
868 fb_labels[fb_label_count] = label;
869 fb_label_instances[fb_label_count] = 1;
870 ++fb_label_count;
871 return;
872} /* fb_label_instance_inc() */
873
874static long
875fb_label_instance (label)
876 long label;
877{
878 long *i;
879
880 if (label < FB_LABEL_SPECIAL)
881 {
882 return (fb_low_counter[label]);
883 }
884
e154ecf4 885 if (fb_labels != NULL)
6efd877d 886 {
e154ecf4
ILT
887 for (i = fb_labels + FB_LABEL_SPECIAL;
888 i < fb_labels + fb_label_count; ++i)
6efd877d 889 {
e154ecf4
ILT
890 if (*i == label)
891 {
892 return (fb_label_instances[i - fb_labels]);
893 } /* if we find it */
894 } /* for each existing label */
895 }
6efd877d 896
e154ecf4
ILT
897 /* We didn't find the label, so this must be a reference to the
898 first instance. */
899 return 0;
2b68b820 900}
6efd877d
KR
901
902/*
903 * fb_label_name()
904 *
905 * Caller must copy returned name: we re-use the area for the next name.
906 *
2b68b820
KR
907 * The mth occurence of label n: is turned into the symbol "Ln^Bm"
908 * where n is the label number and m is the instance number. "L" makes
909 * it a label discarded unless debugging and "^B"('\2') ensures no
910 * ordinary symbol SHOULD get the same name as a local label
911 * symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
6efd877d 912 *
2b68b820 913 * dollar labels get the same treatment, except that ^A is used in place of ^B. */
6efd877d
KR
914
915char * /* Return local label name. */
916fb_label_name (n, augend)
917 long n; /* we just saw "n:", "nf" or "nb" : n a number */
918 long augend; /* 0 for nb, 1 for n:, nf */
919{
920 long i;
921 /* Returned to caller, then copied. used for created names ("4f") */
922 static char symbol_name_build[24];
923 register char *p;
924 register char *q;
925 char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
926
927 know (n >= 0);
928 know (augend == 0 || augend == 1);
929 p = symbol_name_build;
930 *p++ = 'L';
931
932 /* Next code just does sprintf( {}, "%d", n); */
933 /* label number */
934 q = symbol_name_temporary;
935 for (*q++ = 0, i = n; i; ++q)
936 {
937 *q = i % 10 + '0';
938 i /= 10;
939 }
940 while ((*p = *--q) != '\0')
941 ++p;
942
943 *p++ = 2; /* ^B */
944
945 /* instance number */
946 q = symbol_name_temporary;
947 for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
948 {
949 *q = i % 10 + '0';
950 i /= 10;
951 }
952 while ((*p++ = *--q) != '\0');;
953
954 /* The label, as a '\0' ended string, starts at symbol_name_build. */
955 return (symbol_name_build);
956} /* fb_label_name() */
957
958#endif /* LOCAL_LABELS_FB */
fecd2382
RP
959
960
a6c6eaf8 961/*
6efd877d
KR
962 * decode name that may have been generated by foo_label_name() above. If
963 * the name wasn't generated by foo_label_name(), then return it unaltered.
a6c6eaf8
RP
964 * This is used for error messages.
965 */
a39116f1 966
6efd877d
KR
967char *
968decode_local_label_name (s)
969 char *s;
a6c6eaf8 970{
6efd877d
KR
971 char *p;
972 char *symbol_decode;
973 int label_number;
974 int instance_number;
975 char *type;
976 const char *message_format = "\"%d\" (instance number %d of a %s label)";
977
978 if (s[0] != 'L')
979 return (s);
980
981 for (label_number = 0, p = s + 1; isdigit (*p); ++p)
982 {
983 label_number = (10 * label_number) + *p - '0';
984 }
985
986 if (*p == 1)
987 {
988 type = "dollar";
989 }
990 else if (*p == 2)
991 {
992 type = "fb";
993 }
994 else
995 {
996 return (s);
997 }
998
999 for (instance_number = 0, p = s + 1; isdigit (*p); ++p)
1000 {
1001 instance_number = (10 * instance_number) + *p - '0';
1002 }
1003
1004 symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
1005 (void) sprintf (symbol_decode, message_format, label_number,
1006 instance_number, type);
1007
1008 return (symbol_decode);
1009} /* decode_local_label_name() */
a6c6eaf8 1010
85051959
ILT
1011/* Get the value of a symbol. */
1012
1013valueT
1014S_GET_VALUE (s)
1015 symbolS *s;
1016{
1017 if (s->sy_value.X_seg != absolute_section)
5868b1fe 1018 as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
85051959
ILT
1019 return (valueT) s->sy_value.X_add_number;
1020}
1021
1022/* Set the value of a symbol. */
1023
1024void
1025S_SET_VALUE (s, val)
1026 symbolS *s;
1027 valueT val;
1028{
1029 s->sy_value.X_seg = absolute_section;
1030 s->sy_value.X_add_number = (offsetT) val;
1031}
1032
2b68b820
KR
1033#ifdef BFD_ASSEMBLER
1034
1035int
1036S_IS_EXTERNAL (s)
1037 symbolS *s;
1038{
1039 flagword flags = s->bsym->flags;
1040
1041 /* sanity check */
1042 if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
1043 abort ();
1044
1045 return (flags & (BSF_EXPORT | BSF_GLOBAL)) != 0;
1046}
1047
1048int
1049S_IS_COMMON (s)
1050 symbolS *s;
1051{
1052 return s->bsym->section == &bfd_com_section;
1053}
1054
1055int
1056S_IS_DEFINED (s)
1057 symbolS *s;
1058{
1059 return s->bsym->section != undefined_section;
1060}
1061
1062int
1063S_IS_DEBUG (s)
1064 symbolS *s;
1065{
1066 if (s->bsym->flags & BSF_DEBUGGING)
1067 return 1;
1068 return 0;
1069}
1070
1071int
1072S_IS_LOCAL (s)
1073 symbolS *s;
1074{
1075 flagword flags = s->bsym->flags;
1076
1077 /* sanity check */
1078 if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
1079 abort ();
1080
1081 return (S_GET_NAME (s)
1082 && ! S_IS_DEBUG (s)
1083 && (strchr (S_GET_NAME (s), '\001')
1084 || strchr (S_GET_NAME (s), '\002')
1085 || (S_LOCAL_NAME (s)
1086 && !flagseen['L'])));
1087}
1088
1089int
1090S_IS_EXTERN (s)
1091 symbolS *s;
1092{
1093 return S_IS_EXTERNAL (s);
1094}
1095
1096int
1097S_IS_STABD (s)
1098 symbolS *s;
1099{
1100 return S_GET_NAME (s) == 0;
1101}
1102
2b68b820
KR
1103CONST char *
1104S_GET_NAME (s)
1105 symbolS *s;
1106{
1107 return s->bsym->name;
1108}
1109
1110segT
1111S_GET_SEGMENT (s)
1112 symbolS *s;
1113{
1114 return s->bsym->section;
1115}
1116
2b68b820
KR
1117void
1118S_SET_SEGMENT (s, seg)
1119 symbolS *s;
1120 segT seg;
1121{
1122 s->bsym->section = seg;
1123}
1124
1125void
1126S_SET_EXTERNAL (s)
1127 symbolS *s;
1128{
1129 s->bsym->flags |= BSF_EXPORT | BSF_GLOBAL;
1130 s->bsym->flags &= ~BSF_LOCAL;
1131}
1132
1133void
1134S_CLEAR_EXTERNAL (s)
1135 symbolS *s;
1136{
1137 s->bsym->flags |= BSF_LOCAL;
1138 s->bsym->flags &= ~(BSF_EXPORT | BSF_GLOBAL);
1139}
1140
1141void
1142S_SET_NAME (s, name)
1143 symbolS *s;
1144 char *name;
1145{
1146 s->bsym->name = name;
1147}
1148#endif /* BFD_ASSEMBLER */
1149
8b228fe9 1150/* end of symbols.c */
This page took 0.138403 seconds and 4 git commands to generate.