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