* ch-exp.y: Remove ambiguities. Fix or add support for
[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". */
6efd877d
KR
40symbolS *symbol_rootP;
41symbolS *symbol_lastP;
42symbolS abs_symbol;
fecd2382 43
6efd877d
KR
44symbolS *dot_text_symbol;
45symbolS *dot_data_symbol;
46symbolS *dot_bss_symbol;
fecd2382 47
6efd877d 48struct obstack notes;
fecd2382 49
85825401 50static void fb_label_init PARAMS ((void));
fecd2382 51
fecd2382 52void
6efd877d 53symbol_begin ()
fecd2382 54{
6efd877d
KR
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. */
6efd877d
KR
60#ifdef LOCAL_LABELS_FB
61 fb_label_init ();
62#endif /* LOCAL_LABELS_FB */
fecd2382 63}
fecd2382 64
fecd2382
RP
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
6efd877d
KR
82symbolS *
83symbol_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 */
fecd2382 88{
6efd877d
KR
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
a6c6eaf8 101#ifdef STRIP_UNDERSCORE
6efd877d
KR
102 S_SET_NAME (symbolP, (*preserved_copy_of_name == '_'
103 ? preserved_copy_of_name + 1
104 : preserved_copy_of_name));
fecd2382 105#else /* STRIP_UNDERSCORE */
6efd877d 106 S_SET_NAME (symbolP, preserved_copy_of_name);
fecd2382 107#endif /* STRIP_UNDERSCORE */
6efd877d
KR
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 /*
fecd2382
RP
120 * Link to end of symbol chain.
121 */
6efd877d
KR
122 symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
123
124 obj_symbol_new_hook (symbolP);
125
fecd2382 126#ifdef DEBUG
6efd877d 127 /* verify_symbol_chain(symbol_rootP, symbol_lastP); */
fecd2382 128#endif /* DEBUG */
fecd2382 129
6efd877d
KR
130 return (symbolP);
131} /* symbol_new() */
fecd2382 132\f
6efd877d 133
fecd2382
RP
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 */
6efd877d
KR
143void
144colon (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. */
fecd2382 147{
6efd877d
KR
148 register symbolS *symbolP; /* symbol we are working with */
149
fecd2382 150#ifdef LOCAL_LABELS_DOLLAR
6efd877d
KR
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
fecd2382 157#ifndef WORKING_DOT_WORD
6efd877d
KR
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
a39116f1 179 fr_opcode of the rs_broken_word frag. This requires a little hackery */
6efd877d
KR
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 {
fecd2382 193#ifdef VMS
6efd877d 194 /*
a39116f1
RP
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 */
6efd877d
KR
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 /*
a39116f1
RP
202 * If the old symbol is .comm and it has a size of zero,
203 * we override it with the new symbol value.
204 */
6efd877d
KR
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 /*
a39116f1
RP
216 * Now check for undefined symbols
217 */
6efd877d
KR
218 if (!S_IS_DEFINED (symbolP))
219 {
220 if (S_GET_VALUE (symbolP) == 0)
221 {
222 symbolP->sy_frag = frag_now;
fecd2382 223#ifdef VMS
6efd877d 224 symbolP->sy_other = const_flag;
fecd2382 225#endif
6efd877d
KR
226 S_SET_VALUE (symbolP, obstack_next_free (&frags) - frag_now->fr_literal);
227 S_SET_SEGMENT (symbolP, now_seg);
fecd2382 228#ifdef N_UNDF
6efd877d 229 know (N_UNDF == 0);
fecd2382 230#endif /* if we have one, it better be zero. */
6efd877d
KR
231
232 }
233 else
234 {
235 /*
a39116f1
RP
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 */
6efd877d 245 /* char New_Type = SEGMENT_TO_SYMBOL_TYPE((int) now_seg); */
a6c6eaf8
RP
246#ifdef MANY_SEGMENTS
247#define SEG_BSS SEG_E2
248#define SEG_DATA SEG_E1
249#endif
6efd877d
KR
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 /*
a39116f1
RP
257 * Select which of the 2 cases this is
258 */
6efd877d
KR
259 if (now_seg != SEG_DATA)
260 {
261 /*
a39116f1
RP
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 */
6efd877d
KR
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 {
85825401
ILT
277 /* It is a .comm/.lcomm being converted to initialized
278 data. */
6efd877d 279 symbolP->sy_frag = frag_now;
fecd2382 280#ifdef VMS
6efd877d 281 symbolP->sy_other = const_flag;
fecd2382 282#endif /* VMS */
6efd877d
KR
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 {
fecd2382 289#ifdef OBJ_COFF
6efd877d
KR
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));
fecd2382 294#else /* OBJ_COFF */
6efd877d
KR
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));
fecd2382 300#endif /* OBJ_COFF */
6efd877d
KR
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);
fecd2382 320#ifdef VMS
6efd877d 321 S_SET_OTHER (symbolP, const_flag);
fecd2382 322#endif /* VMS */
fecd2382 323
6efd877d
KR
324 symbol_table_insert (symbolP);
325 } /* if we have seen this symbol before */
326
327 return;
328} /* colon() */
fecd2382 329\f
6efd877d 330
fecd2382
RP
331/*
332 * symbol_table_insert()
333 *
334 * Die if we can't insert the symbol.
335 *
336 */
337
6efd877d
KR
338void
339symbol_table_insert (symbolP)
340 symbolS *symbolP;
fecd2382 341{
6efd877d
KR
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() */
fecd2382
RP
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 */
6efd877d
KR
360symbolS *
361symbol_find_or_make (name)
362 char *name;
fecd2382 363{
6efd877d
KR
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
378symbolS *
379symbol_make (name)
380 char *name;
fecd2382 381{
6efd877d
KR
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() */
fecd2382
RP
397
398/*
399 * symbol_find()
6efd877d 400 *
fecd2382
RP
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
6efd877d
KR
407symbolS *
408symbol_find (name)
409 char *name;
fecd2382 410{
a6c6eaf8 411#ifdef STRIP_UNDERSCORE
6efd877d 412 return (symbol_find_base (name, 1));
a6c6eaf8 413#else /* STRIP_UNDERSCORE */
6efd877d 414 return (symbol_find_base (name, 0));
fecd2382 415#endif /* STRIP_UNDERSCORE */
6efd877d 416} /* symbol_find() */
fecd2382 417
6efd877d
KR
418symbolS *
419symbol_find_base (name, strip_underscore)
420 char *name;
421 int strip_underscore;
fecd2382 422{
6efd877d
KR
423 if (strip_underscore && *name == '_')
424 name++;
425 return ((symbolS *) hash_find (sy_hash, name));
fecd2382
RP
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. */
6efd877d
KR
437void
438symbol_append (addme, target, rootPP, lastPP)
439 symbolS *addme;
440 symbolS *target;
441 symbolS **rootPP;
442 symbolS **lastPP;
fecd2382 443{
6efd877d
KR
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 {
fecd2382 455#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 456 target->sy_next->sy_previous = addme;
fecd2382 457#endif /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d
KR
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
fecd2382 468#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 469 addme->sy_previous = target;
fecd2382 470#endif /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d 471
fecd2382 472#ifdef DEBUG
6efd877d 473 /* verify_symbol_chain(*rootPP, *lastPP); */
fecd2382 474#endif /* DEBUG */
6efd877d
KR
475
476 return;
477} /* symbol_append() */
fecd2382
RP
478
479#ifdef SYMBOLS_NEED_BACKPOINTERS
480/* Remove SYMBOLP from the list. */
6efd877d
KR
481void
482symbol_remove (symbolP, rootPP, lastPP)
483 symbolS *symbolP;
484 symbolS **rootPP;
485 symbolS **lastPP;
fecd2382 486{
6efd877d
KR
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
fecd2382 507#ifdef DEBUG
6efd877d 508 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 509#endif /* DEBUG */
6efd877d
KR
510
511 return;
512} /* symbol_remove() */
fecd2382
RP
513
514/* Set the chain pointers of SYMBOL to null. */
6efd877d
KR
515void
516symbol_clear_list_pointers (symbolP)
517 symbolS *symbolP;
fecd2382 518{
6efd877d
KR
519 symbolP->sy_next = NULL;
520 symbolP->sy_previous = NULL;
521} /* symbol_clear_list_pointers() */
fecd2382
RP
522
523/* Link symbol ADDME before symbol TARGET in the chain. */
6efd877d
KR
524void
525symbol_insert (addme, target, rootPP, lastPP)
526 symbolS *addme;
527 symbolS *target;
528 symbolS **rootPP;
529 symbolS **lastPP;
fecd2382 530{
6efd877d
KR
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
fecd2382 545#ifdef DEBUG
6efd877d 546 verify_symbol_chain (*rootPP, *lastPP);
fecd2382 547#endif /* DEBUG */
6efd877d
KR
548
549 return;
550} /* symbol_insert() */
551
fecd2382
RP
552#endif /* SYMBOLS_NEED_BACKPOINTERS */
553
6efd877d
KR
554void
555verify_symbol_chain (rootP, lastP)
556 symbolS *rootP;
557 symbolS *lastP;
fecd2382 558{
6efd877d
KR
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 {
fecd2382 568#ifdef SYMBOLS_NEED_BACKPOINTERS
6efd877d 569 /*$if (symbolP->sy_previous) {
a39116f1
RP
570 know(symbolP->sy_previous->sy_next == symbolP);
571 } else {
572 know(symbolP == rootP);
6efd877d
KR
573 }$*//* both directions */
574 know (symbolP->sy_next->sy_previous == symbolP);
fecd2382 575#else /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d 576 ;
fecd2382 577#endif /* SYMBOLS_NEED_BACKPOINTERS */
6efd877d
KR
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
595static long *dollar_labels = NULL;
596static long *dollar_label_instances = NULL;
597static char *dollar_label_defines = NULL;
598static long dollar_label_count = 0;
599static long dollar_label_max = 0;
600
601int
602dollar_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
621static int
622dollar_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
642void
643dollar_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
651void
652define_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
709char * /* Return local label name. */
710dollar_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
776static long fb_low_counter[FB_LABEL_SPECIAL];
777static long *fb_labels;
778static long *fb_label_instances;
779static long fb_label_count = 0;
780static 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
785static void
786fb_label_init ()
787{
788 memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
6efd877d
KR
789} /* fb_label_init() */
790
791/* add one to the instance number of this fb label */
792void
793fb_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
838static long
839fb_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
875char * /* Return local label name. */
876fb_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 */
fecd2382
RP
919
920
a6c6eaf8 921/*
6efd877d
KR
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.
a6c6eaf8
RP
924 * This is used for error messages.
925 */
a39116f1 926
6efd877d
KR
927char *
928decode_local_label_name (s)
929 char *s;
a6c6eaf8 930{
6efd877d
KR
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() */
a6c6eaf8 970
8b228fe9 971/* end of symbols.c */
This page took 0.106919 seconds and 4 git commands to generate.