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