Add m88k-coff target Makefile fragment.
[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 */
2b68b820
KR
315#ifdef TC_HPPA
316 pa_define_label(symbolP);
317#endif
6efd877d
KR
318
319 return;
320} /* colon() */
fecd2382 321\f
6efd877d 322
fecd2382
RP
323/*
324 * symbol_table_insert()
325 *
326 * Die if we can't insert the symbol.
327 *
328 */
329
6efd877d
KR
330void
331symbol_table_insert (symbolP)
332 symbolS *symbolP;
fecd2382 333{
6efd877d
KR
334 register char *error_string;
335
336 know (symbolP);
337 know (S_GET_NAME (symbolP));
338
339 if (*(error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (char *) symbolP)))
340 {
341 as_fatal ("Inserting \"%s\" into symbol table failed: %s",
342 S_GET_NAME (symbolP), error_string);
343 } /* on error */
344} /* symbol_table_insert() */
fecd2382
RP
345\f
346/*
347 * symbol_find_or_make()
348 *
349 * If a symbol name does not exist, create it as undefined, and insert
350 * it into the symbol table. Return a pointer to it.
351 */
6efd877d
KR
352symbolS *
353symbol_find_or_make (name)
354 char *name;
fecd2382 355{
6efd877d
KR
356 register symbolS *symbolP;
357
358 symbolP = symbol_find (name);
359
360 if (symbolP == NULL)
361 {
362 symbolP = symbol_make (name);
363
364 symbol_table_insert (symbolP);
365 } /* if symbol wasn't found */
366
367 return (symbolP);
368} /* symbol_find_or_make() */
369
370symbolS *
371symbol_make (name)
2b68b820 372 CONST char *name;
fecd2382 373{
6efd877d
KR
374 symbolS *symbolP;
375
376 /* Let the machine description default it, e.g. for register names. */
2b68b820 377 symbolP = md_undefined_symbol ((char *) name);
6efd877d
KR
378
379 if (!symbolP)
2b68b820 380 symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
6efd877d
KR
381
382 return (symbolP);
383} /* symbol_make() */
fecd2382
RP
384
385/*
386 * symbol_find()
6efd877d 387 *
fecd2382
RP
388 * Implement symbol table lookup.
389 * In: A symbol's name as a string: '\0' can't be part of a symbol name.
390 * Out: NULL if the name was not in the symbol table, else the address
391 * of a struct symbol associated with that name.
392 */
393
6efd877d
KR
394symbolS *
395symbol_find (name)
2b68b820 396 CONST char *name;
fecd2382 397{
a6c6eaf8 398#ifdef STRIP_UNDERSCORE
6efd877d 399 return (symbol_find_base (name, 1));
a6c6eaf8 400#else /* STRIP_UNDERSCORE */
6efd877d 401 return (symbol_find_base (name, 0));
fecd2382 402#endif /* STRIP_UNDERSCORE */
6efd877d 403} /* symbol_find() */
fecd2382 404
6efd877d
KR
405symbolS *
406symbol_find_base (name, strip_underscore)
2b68b820 407 CONST char *name;
6efd877d 408 int strip_underscore;
fecd2382 409{
6efd877d
KR
410 if (strip_underscore && *name == '_')
411 name++;
412 return ((symbolS *) hash_find (sy_hash, name));
fecd2382
RP
413}
414
415/*
416 * Once upon a time, symbols were kept in a singly linked list. At
417 * least coff needs to be able to rearrange them from time to time, for
418 * which a doubly linked list is much more convenient. Loic did these
419 * as macros which seemed dangerous to me so they're now functions.
420 * xoxorich.
421 */
422
423/* Link symbol ADDME after symbol TARGET in the chain. */
6efd877d
KR
424void
425symbol_append (addme, target, rootPP, lastPP)
426 symbolS *addme;
427 symbolS *target;
428 symbolS **rootPP;
429 symbolS **lastPP;
fecd2382 430{
6efd877d
KR
431 if (target == NULL)
432 {
433 know (*rootPP == NULL);
434 know (*lastPP == NULL);
435 *rootPP = addme;
436 *lastPP = addme;
437 return;
438 } /* if the list is empty */
439
440 if (target->sy_next != NULL)
441 {
fecd2382 442#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 443 target->sy_next->sy_previous = addme;
fecd2382 444#endif /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d
KR
445 }
446 else
447 {
448 know (*lastPP == target);
449 *lastPP = addme;
450 } /* if we have a next */
451
452 addme->sy_next = target->sy_next;
453 target->sy_next = addme;
454
fecd2382 455#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 456 addme->sy_previous = target;
fecd2382 457#endif /* SYMBOLS_NEED_BACKPOINTERS */
2b68b820 458}
fecd2382
RP
459
460#ifdef SYMBOLS_NEED_BACKPOINTERS
461/* Remove SYMBOLP from the list. */
6efd877d
KR
462void
463symbol_remove (symbolP, rootPP, lastPP)
464 symbolS *symbolP;
465 symbolS **rootPP;
466 symbolS **lastPP;
fecd2382 467{
6efd877d
KR
468 if (symbolP == *rootPP)
469 {
470 *rootPP = symbolP->sy_next;
471 } /* if it was the root */
472
473 if (symbolP == *lastPP)
474 {
475 *lastPP = symbolP->sy_previous;
476 } /* if it was the tail */
477
478 if (symbolP->sy_next != NULL)
479 {
480 symbolP->sy_next->sy_previous = symbolP->sy_previous;
481 } /* if not last */
482
483 if (symbolP->sy_previous != NULL)
484 {
485 symbolP->sy_previous->sy_next = symbolP->sy_next;
486 } /* if not first */
487
fecd2382 488#ifdef DEBUG
6efd877d 489 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 490#endif /* DEBUG */
2b68b820 491}
fecd2382
RP
492
493/* Set the chain pointers of SYMBOL to null. */
6efd877d
KR
494void
495symbol_clear_list_pointers (symbolP)
496 symbolS *symbolP;
fecd2382 497{
6efd877d
KR
498 symbolP->sy_next = NULL;
499 symbolP->sy_previous = NULL;
2b68b820 500}
fecd2382
RP
501
502/* Link symbol ADDME before symbol TARGET in the chain. */
6efd877d
KR
503void
504symbol_insert (addme, target, rootPP, lastPP)
505 symbolS *addme;
506 symbolS *target;
507 symbolS **rootPP;
508 symbolS **lastPP;
fecd2382 509{
6efd877d
KR
510 if (target->sy_previous != NULL)
511 {
512 target->sy_previous->sy_next = addme;
513 }
514 else
515 {
516 know (*rootPP == target);
517 *rootPP = addme;
518 } /* if not first */
519
520 addme->sy_previous = target->sy_previous;
521 target->sy_previous = addme;
522 addme->sy_next = target;
523
fecd2382 524#ifdef DEBUG
6efd877d 525 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 526#endif /* DEBUG */
2b68b820 527}
6efd877d 528
fecd2382
RP
529#endif /* SYMBOLS_NEED_BACKPOINTERS */
530
6efd877d
KR
531void
532verify_symbol_chain (rootP, lastP)
533 symbolS *rootP;
534 symbolS *lastP;
fecd2382 535{
6efd877d
KR
536 symbolS *symbolP = rootP;
537
538 if (symbolP == NULL)
2b68b820 539 return;
6efd877d
KR
540
541 for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
542 {
fecd2382 543#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 544 know (symbolP->sy_next->sy_previous == symbolP);
2b68b820
KR
545#else
546 /* Walk the list anyways, to make sure pointers are still good. */
547 *symbolP;
fecd2382 548#endif /* SYMBOLS_NEED_BACKPOINTERS */
2b68b820 549 }
6efd877d 550
2b68b820
KR
551 assert (lastP == symbolP);
552}
6efd877d 553
2b68b820
KR
554void
555verify_symbol_chain_2 (sym)
556 symbolS *sym;
557{
558 symbolS *p = sym, *n = sym;
559#ifdef SYMBOLS_NEED_BACKPOINTERS
560 while (symbol_previous (p))
561 p = symbol_previous (p);
562#endif
563 while (symbol_next (n))
564 n = symbol_next (n);
565 verify_symbol_chain (p, n);
566}
6efd877d 567
5868b1fe
ILT
568/* Resolve the value of a symbol. This is called during the final
569 pass over the symbol table to resolve any symbols with complex
570 values. */
571
572void
573resolve_symbol_value (symp)
574 symbolS *symp;
575{
576 if (symp->sy_resolved)
577 return;
578
579 if (symp->sy_resolving)
580 {
581 as_bad ("Symbol definition loop encountered at %s",
582 S_GET_NAME (symp));
583 S_SET_VALUE (symp, (valueT) 0);
584 }
585 else
586 {
587 symp->sy_resolving = 1;
588
589 if (symp->sy_value.X_seg == absolute_section)
590 S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
591 else if (symp->sy_value.X_seg == undefined_section)
592 {
593 resolve_symbol_value (symp->sy_value.X_add_symbol);
594
595#ifdef obj_frob_forward_symbol
596 /* Some object formats need to forward the segment. */
597 obj_frob_forward_symbol (symp);
598#endif
599
600 S_SET_VALUE (symp,
601 (symp->sy_value.X_add_number
602 + symp->sy_frag->fr_address
603 + S_GET_VALUE (symp->sy_value.X_add_symbol)));
604 }
c978e704
ILT
605 else if (symp->sy_value.X_seg == diff_section)
606 {
607 resolve_symbol_value (symp->sy_value.X_add_symbol);
608 resolve_symbol_value (symp->sy_value.X_subtract_symbol);
609 if (S_GET_SEGMENT (symp->sy_value.X_add_symbol)
610 != S_GET_SEGMENT (symp->sy_value.X_subtract_symbol))
611 as_bad ("%s is difference of symbols in different sections",
612 S_GET_NAME (symp));
613 S_SET_VALUE (symp,
614 (symp->sy_value.X_add_number
615 + symp->sy_frag->fr_address
616 + S_GET_VALUE (symp->sy_value.X_add_symbol)
617 - S_GET_VALUE (symp->sy_value.X_subtract_symbol)));
618 S_SET_SEGMENT (symp, absolute_section);
619 }
5868b1fe
ILT
620 else
621 {
622 /* More cases need to be added here. */
623 abort ();
624 }
625 }
626
627 symp->sy_resolved = 1;
628}
629
6efd877d
KR
630#ifdef LOCAL_LABELS_DOLLAR
631
632/* Dollar labels look like a number followed by a dollar sign. Eg, "42$".
633 They are *really* local. That is, they go out of scope whenever we see a
634 label that isn't local. Also, like fb labels, there can be multiple
635 instances of a dollar label. Therefor, we name encode each instance with
636 the instance number, keep a list of defined symbols separate from the real
637 symbol table, and we treat these buggers as a sparse array. */
638
2b68b820
KR
639static long *dollar_labels;
640static long *dollar_label_instances;
641static char *dollar_label_defines;
642static long dollar_label_count;
643static long dollar_label_max;
6efd877d
KR
644
645int
646dollar_label_defined (label)
647 long label;
648{
649 long *i;
650
651 know ((dollar_labels != NULL) || (dollar_label_count == 0));
652
653 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
654 if (*i == label)
655 return dollar_label_defines[i - dollar_labels];
6efd877d
KR
656
657 /* if we get here, label isn't defined */
2b68b820 658 return 0;
6efd877d
KR
659} /* dollar_label_defined() */
660
661static int
662dollar_label_instance (label)
663 long label;
664{
665 long *i;
666
667 know ((dollar_labels != NULL) || (dollar_label_count == 0));
668
669 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
670 if (*i == label)
671 return (dollar_label_instances[i - dollar_labels]);
6efd877d 672
2b68b820
KR
673 /* If we get here, we haven't seen the label before, therefore its instance
674 count is zero. */
675 return 0;
676}
6efd877d
KR
677
678void
679dollar_label_clear ()
680{
681 memset (dollar_label_defines, '\0', dollar_label_count);
2b68b820 682}
6efd877d
KR
683
684#define DOLLAR_LABEL_BUMP_BY 10
685
686void
687define_dollar_label (label)
688 long label;
689{
690 long *i;
691
692 for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
2b68b820
KR
693 if (*i == label)
694 {
695 ++dollar_label_instances[i - dollar_labels];
696 dollar_label_defines[i - dollar_labels] = 1;
697 return;
698 }
6efd877d
KR
699
700 /* if we get to here, we don't have label listed yet. */
701
702 if (dollar_labels == NULL)
703 {
704 dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
705 dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
706 dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
707 dollar_label_max = DOLLAR_LABEL_BUMP_BY;
708 dollar_label_count = 0;
6efd877d
KR
709 }
710 else if (dollar_label_count == dollar_label_max)
711 {
712 dollar_label_max += DOLLAR_LABEL_BUMP_BY;
713 dollar_labels = (long *) xrealloc ((char *) dollar_labels,
714 dollar_label_max * sizeof (long));
715 dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
716 dollar_label_max * sizeof (long));
717 dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
718 } /* if we needed to grow */
719
720 dollar_labels[dollar_label_count] = label;
721 dollar_label_instances[dollar_label_count] = 1;
722 dollar_label_defines[dollar_label_count] = 1;
723 ++dollar_label_count;
2b68b820 724}
6efd877d
KR
725
726/*
727 * dollar_label_name()
728 *
729 * Caller must copy returned name: we re-use the area for the next name.
730 *
2b68b820
KR
731 * The mth occurence of label n: is turned into the symbol "Ln^Am"
732 * where n is the label number and m is the instance number. "L" makes
733 * it a label discarded unless debugging and "^A"('\1') ensures no
734 * ordinary symbol SHOULD get the same name as a local label
735 * symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
6efd877d
KR
736 *
737 * fb labels get the same treatment, except that ^B is used in place of ^A.
738 */
739
740char * /* Return local label name. */
741dollar_label_name (n, augend)
742 register long n; /* we just saw "n$:" : n a number */
743 register int augend; /* 0 for current instance, 1 for new instance */
744{
745 long i;
746 /* Returned to caller, then copied. used for created names ("4f") */
747 static char symbol_name_build[24];
748 register char *p;
749 register char *q;
750 char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
751
752 know (n >= 0);
753 know (augend == 0 || augend == 1);
754 p = symbol_name_build;
755 *p++ = 'L';
756
757 /* Next code just does sprintf( {}, "%d", n); */
758 /* label number */
759 q = symbol_name_temporary;
760 for (*q++ = 0, i = n; i; ++q)
761 {
762 *q = i % 10 + '0';
763 i /= 10;
764 }
765 while ((*p = *--q) != '\0')
766 ++p;
767
768 *p++ = 1; /* ^A */
769
770 /* instance number */
771 q = symbol_name_temporary;
772 for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
773 {
774 *q = i % 10 + '0';
775 i /= 10;
776 }
777 while ((*p++ = *--q) != '\0');;
778
779 /* The label, as a '\0' ended string, starts at symbol_name_build. */
2b68b820
KR
780 return symbol_name_build;
781}
6efd877d
KR
782
783#endif /* LOCAL_LABELS_DOLLAR */
784
785#ifdef LOCAL_LABELS_FB
786
787/*
788 * Sombody else's idea of local labels. They are made by "n:" where n
789 * is any decimal digit. Refer to them with
790 * "nb" for previous (backward) n:
791 * or "nf" for next (forward) n:.
792 *
793 * We do a little better and let n be any number, not just a single digit, but
794 * since the other guy's assembler only does ten, we treat the first ten
795 * specially.
796 *
797 * Like someone else's assembler, we have one set of local label counters for
798 * entire assembly, not one set per (sub)segment like in most assemblers. This
799 * implies that one can refer to a label in another segment, and indeed some
800 * crufty compilers have done just that.
801 *
802 * Since there could be a LOT of these things, treat them as a sparse array.
803 */
804
805#define FB_LABEL_SPECIAL (10)
806
807static long fb_low_counter[FB_LABEL_SPECIAL];
808static long *fb_labels;
809static long *fb_label_instances;
810static long fb_label_count = 0;
811static long fb_label_max = 0;
812
813/* this must be more than FB_LABEL_SPECIAL */
814#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
815
816static void
817fb_label_init ()
818{
819 memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
6efd877d
KR
820} /* fb_label_init() */
821
822/* add one to the instance number of this fb label */
823void
824fb_label_instance_inc (label)
825 long label;
826{
827 long *i;
828
829 if (label < FB_LABEL_SPECIAL)
830 {
831 ++fb_low_counter[label];
832 return;
833 }
834
e154ecf4 835 if (fb_labels != NULL)
6efd877d 836 {
e154ecf4
ILT
837 for (i = fb_labels + FB_LABEL_SPECIAL;
838 i < fb_labels + fb_label_count; ++i)
6efd877d 839 {
e154ecf4
ILT
840 if (*i == label)
841 {
842 ++fb_label_instances[i - fb_labels];
843 return;
844 } /* if we find it */
845 } /* for each existing label */
846 }
6efd877d
KR
847
848 /* if we get to here, we don't have label listed yet. */
849
850 if (fb_labels == NULL)
851 {
852 fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
853 fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
854 fb_label_max = FB_LABEL_BUMP_BY;
855 fb_label_count = FB_LABEL_SPECIAL;
856
857 }
858 else if (fb_label_count == fb_label_max)
859 {
860 fb_label_max += FB_LABEL_BUMP_BY;
861 fb_labels = (long *) xrealloc ((char *) fb_labels,
862 fb_label_max * sizeof (long));
863 fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
864 fb_label_max * sizeof (long));
865 } /* if we needed to grow */
866
867 fb_labels[fb_label_count] = label;
868 fb_label_instances[fb_label_count] = 1;
869 ++fb_label_count;
870 return;
871} /* fb_label_instance_inc() */
872
873static long
874fb_label_instance (label)
875 long label;
876{
877 long *i;
878
879 if (label < FB_LABEL_SPECIAL)
880 {
881 return (fb_low_counter[label]);
882 }
883
e154ecf4 884 if (fb_labels != NULL)
6efd877d 885 {
e154ecf4
ILT
886 for (i = fb_labels + FB_LABEL_SPECIAL;
887 i < fb_labels + fb_label_count; ++i)
6efd877d 888 {
e154ecf4
ILT
889 if (*i == label)
890 {
891 return (fb_label_instances[i - fb_labels]);
892 } /* if we find it */
893 } /* for each existing label */
894 }
6efd877d 895
e154ecf4
ILT
896 /* We didn't find the label, so this must be a reference to the
897 first instance. */
898 return 0;
2b68b820 899}
6efd877d
KR
900
901/*
902 * fb_label_name()
903 *
904 * Caller must copy returned name: we re-use the area for the next name.
905 *
2b68b820
KR
906 * The mth occurence of label n: is turned into the symbol "Ln^Bm"
907 * where n is the label number and m is the instance number. "L" makes
908 * it a label discarded unless debugging and "^B"('\2') ensures no
909 * ordinary symbol SHOULD get the same name as a local label
910 * symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
6efd877d 911 *
2b68b820 912 * dollar labels get the same treatment, except that ^A is used in place of ^B. */
6efd877d
KR
913
914char * /* Return local label name. */
915fb_label_name (n, augend)
916 long n; /* we just saw "n:", "nf" or "nb" : n a number */
917 long augend; /* 0 for nb, 1 for n:, nf */
918{
919 long i;
920 /* Returned to caller, then copied. used for created names ("4f") */
921 static char symbol_name_build[24];
922 register char *p;
923 register char *q;
924 char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
925
926 know (n >= 0);
927 know (augend == 0 || augend == 1);
928 p = symbol_name_build;
929 *p++ = 'L';
930
931 /* Next code just does sprintf( {}, "%d", n); */
932 /* label number */
933 q = symbol_name_temporary;
934 for (*q++ = 0, i = n; i; ++q)
935 {
936 *q = i % 10 + '0';
937 i /= 10;
938 }
939 while ((*p = *--q) != '\0')
940 ++p;
941
942 *p++ = 2; /* ^B */
943
944 /* instance number */
945 q = symbol_name_temporary;
946 for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
947 {
948 *q = i % 10 + '0';
949 i /= 10;
950 }
951 while ((*p++ = *--q) != '\0');;
952
953 /* The label, as a '\0' ended string, starts at symbol_name_build. */
954 return (symbol_name_build);
955} /* fb_label_name() */
956
957#endif /* LOCAL_LABELS_FB */
fecd2382
RP
958
959
a6c6eaf8 960/*
6efd877d
KR
961 * decode name that may have been generated by foo_label_name() above. If
962 * the name wasn't generated by foo_label_name(), then return it unaltered.
a6c6eaf8
RP
963 * This is used for error messages.
964 */
a39116f1 965
6efd877d
KR
966char *
967decode_local_label_name (s)
968 char *s;
a6c6eaf8 969{
6efd877d
KR
970 char *p;
971 char *symbol_decode;
972 int label_number;
973 int instance_number;
974 char *type;
975 const char *message_format = "\"%d\" (instance number %d of a %s label)";
976
977 if (s[0] != 'L')
978 return (s);
979
980 for (label_number = 0, p = s + 1; isdigit (*p); ++p)
981 {
982 label_number = (10 * label_number) + *p - '0';
983 }
984
985 if (*p == 1)
986 {
987 type = "dollar";
988 }
989 else if (*p == 2)
990 {
991 type = "fb";
992 }
993 else
994 {
995 return (s);
996 }
997
998 for (instance_number = 0, p = s + 1; isdigit (*p); ++p)
999 {
1000 instance_number = (10 * instance_number) + *p - '0';
1001 }
1002
1003 symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
1004 (void) sprintf (symbol_decode, message_format, label_number,
1005 instance_number, type);
1006
1007 return (symbol_decode);
1008} /* decode_local_label_name() */
a6c6eaf8 1009
85051959
ILT
1010/* Get the value of a symbol. */
1011
1012valueT
1013S_GET_VALUE (s)
1014 symbolS *s;
1015{
1016 if (s->sy_value.X_seg != absolute_section)
5868b1fe 1017 as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
85051959
ILT
1018 return (valueT) s->sy_value.X_add_number;
1019}
1020
1021/* Set the value of a symbol. */
1022
1023void
1024S_SET_VALUE (s, val)
1025 symbolS *s;
1026 valueT val;
1027{
1028 s->sy_value.X_seg = absolute_section;
1029 s->sy_value.X_add_number = (offsetT) val;
1030}
1031
2b68b820
KR
1032#ifdef BFD_ASSEMBLER
1033
1034int
1035S_IS_EXTERNAL (s)
1036 symbolS *s;
1037{
1038 flagword flags = s->bsym->flags;
1039
1040 /* sanity check */
1041 if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
1042 abort ();
1043
1044 return (flags & (BSF_EXPORT | BSF_GLOBAL)) != 0;
1045}
1046
1047int
1048S_IS_COMMON (s)
1049 symbolS *s;
1050{
1051 return s->bsym->section == &bfd_com_section;
1052}
1053
1054int
1055S_IS_DEFINED (s)
1056 symbolS *s;
1057{
1058 return s->bsym->section != undefined_section;
1059}
1060
1061int
1062S_IS_DEBUG (s)
1063 symbolS *s;
1064{
1065 if (s->bsym->flags & BSF_DEBUGGING)
1066 return 1;
1067 return 0;
1068}
1069
1070int
1071S_IS_LOCAL (s)
1072 symbolS *s;
1073{
1074 flagword flags = s->bsym->flags;
1075
1076 /* sanity check */
1077 if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
1078 abort ();
1079
1080 return (S_GET_NAME (s)
1081 && ! S_IS_DEBUG (s)
1082 && (strchr (S_GET_NAME (s), '\001')
1083 || strchr (S_GET_NAME (s), '\002')
1084 || (S_LOCAL_NAME (s)
1085 && !flagseen['L'])));
1086}
1087
1088int
1089S_IS_EXTERN (s)
1090 symbolS *s;
1091{
1092 return S_IS_EXTERNAL (s);
1093}
1094
1095int
1096S_IS_STABD (s)
1097 symbolS *s;
1098{
1099 return S_GET_NAME (s) == 0;
1100}
1101
2b68b820
KR
1102CONST char *
1103S_GET_NAME (s)
1104 symbolS *s;
1105{
1106 return s->bsym->name;
1107}
1108
1109segT
1110S_GET_SEGMENT (s)
1111 symbolS *s;
1112{
1113 return s->bsym->section;
1114}
1115
2b68b820
KR
1116void
1117S_SET_SEGMENT (s, seg)
1118 symbolS *s;
1119 segT seg;
1120{
1121 s->bsym->section = seg;
1122}
1123
1124void
1125S_SET_EXTERNAL (s)
1126 symbolS *s;
1127{
1128 s->bsym->flags |= BSF_EXPORT | BSF_GLOBAL;
1129 s->bsym->flags &= ~BSF_LOCAL;
1130}
1131
1132void
1133S_CLEAR_EXTERNAL (s)
1134 symbolS *s;
1135{
1136 s->bsym->flags |= BSF_LOCAL;
1137 s->bsym->flags &= ~(BSF_EXPORT | BSF_GLOBAL);
1138}
1139
1140void
1141S_SET_NAME (s, name)
1142 symbolS *s;
1143 char *name;
1144{
1145 s->bsym->name = name;
1146}
1147#endif /* BFD_ASSEMBLER */
1148
8b228fe9 1149/* end of symbols.c */
This page took 0.124163 seconds and 4 git commands to generate.