correct comment
[unix-history] / usr / src / old / dbx / stabstring.c
CommitLineData
21e15a40
SL
1#ifndef lint
2static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/27 10:24:04 linton Exp */
3#endif
4
5/*
6 * String information interpretation
7 *
8 * The string part of a stab entry is broken up into name and type information.
9 */
10
11#include "defs.h"
12#include "stabstring.h"
13#include "object.h"
14#include "main.h"
15#include "symbols.h"
16#include "names.h"
17#include "languages.h"
18#include <a.out.h>
19#include <ctype.h>
20
21#ifndef public
22#endif
23
24/*
25 * Special characters in symbol table information.
26 */
27
28#define TYPENAME 't'
29#define TAGNAME 'T'
30#define MODULEBEGIN 'm'
31#define EXTPROCEDURE 'P'
32#define PRIVPROCEDURE 'Q'
33#define INTPROCEDURE 'I'
34#define EXTFUNCTION 'F'
35#define PRIVFUNCTION 'f'
36#define INTFUNCTION 'J'
37#define EXTVAR 'G'
38#define MODULEVAR 'S'
39#define OWNVAR 'V'
40#define REGVAR 'r'
41#define VALUEPARAM 'p'
42#define VARIABLEPARAM 'v'
43#define LOCALVAR /* default */
44
45/*
46 * Type information special characters.
47 */
48
49#define T_SUBRANGE 'r'
50#define T_ARRAY 'a'
51#define T_OPENARRAY 'A'
52#define T_RECORD 's'
53#define T_UNION 'u'
54#define T_ENUM 'e'
55#define T_PTR '*'
56#define T_FUNCVAR 'f'
57#define T_PROCVAR 'p'
58#define T_IMPORTED 'i'
59#define T_SET 'S'
60#define T_OPAQUE 'o'
61
62/*
63 * Table of types indexed by per-file unique identification number.
64 */
65
66#define NTYPES 1000
67
68private Symbol typetable[NTYPES];
69
70public initTypeTable ()
71{
72 bzero(typetable, sizeof(typetable));
73 (*language_op(curlang, L_MODINIT))(typetable);
74}
75
76/*
77 * Put an nlist entry into the symbol table.
78 * If it's already there just add the associated information.
79 *
80 * Type information is encoded in the name following a ":".
81 */
82
83private Symbol constype();
84private Char *curchar;
85
86#define skipchar(ptr, ch) \
87{ \
88 if (*ptr != ch) { \
89 panic("expected char '%c', found '%s'", ch, ptr); \
90 } \
91 ++ptr; \
92}
93
94#define optchar(ptr, ch) \
95{ \
96 if (*ptr == ch) { \
97 ++ptr; \
98 } \
99}
100
101#define chkcont(ptr) \
102{ \
103 if (*ptr == '?') { \
104 ptr = getcont(); \
105 } \
106}
107
108#define newSym(s, n) \
109{ \
110 s = insert(n); \
111 s->level = curblock->level + 1; \
112 s->language = curlang; \
113 s->block = curblock; \
114}
115
116#define makeVariable(s, n, off) \
117{ \
118 newSym(s, n); \
119 s->class = VAR; \
120 s->symvalue.offset = off; \
121 getType(s); \
122}
123
124#define makeParameter(s, n, cl, off) \
125{ \
126 newSym(s, n); \
127 s->class = cl; \
128 s->symvalue.offset = off; \
129 curparam->chain = s; \
130 curparam = s; \
131 getType(s); \
132}
133
134public entersym (name, np)
135String name;
136struct nlist *np;
137{
138 Symbol s;
139 char *p;
140 register Name n;
141 char c;
142
143 p = index(name, ':');
144 *p = '\0';
145 c = *(p+1);
146 n = identname(name, true);
147 chkUnnamedBlock();
148 curchar = p + 2;
149 switch (c) {
150 case TYPENAME:
151 newSym(s, n);
152 typeName(s);
153 break;
154
155 case TAGNAME:
156 newSym(s, n);
157 tagName(s);
158 break;
159
160 case MODULEBEGIN:
161 newSym(s, n);
162 publicRoutine(s, MODULE, np->n_value);
163 curmodule = s;
164 break;
165
166 case EXTPROCEDURE:
167 newSym(s, n);
168 publicRoutine(s, PROC, np->n_value);
169 break;
170
171 case PRIVPROCEDURE:
172 privateRoutine(&s, n, PROC, np->n_value);
173 break;
174
175 case INTPROCEDURE:
176 newSym(s, n);
177 markInternal(s);
178 publicRoutine(s, PROC, np->n_value);
179 break;
180
181 case EXTFUNCTION:
182 newSym(s, n);
183 publicRoutine(s, FUNC, np->n_value);
184 break;
185
186 case PRIVFUNCTION:
187 privateRoutine(&s, n, FUNC, np->n_value);
188 break;
189
190 case INTFUNCTION:
191 newSym(s, n);
192 markInternal(s);
193 publicRoutine(s, FUNC, np->n_value);
194 break;
195
196 case EXTVAR:
197 find(s, n) where
198 s->level == program->level and s->class == VAR
199 endfind(s);
200 if (s == nil) {
201 makeVariable(s, n, np->n_value);
202 s->level = program->level;
203 s->block = program;
204 getExtRef(s);
205 }
206 break;
207
208 case MODULEVAR:
209 if (curblock->class != MODULE) {
210 exitblock();
211 }
212 makeVariable(s, n, np->n_value);
213 s->level = program->level;
214 s->block = curmodule;
215 getExtRef(s);
216 break;
217
218 case OWNVAR:
219 makeVariable(s, n, np->n_value);
220 ownVariable(s, np->n_value);
221 getExtRef(s);
222 break;
223
224 case REGVAR:
225 makeVariable(s, n, np->n_value);
226 s->level = -(s->level);
227 break;
228
229 case VALUEPARAM:
230 makeParameter(s, n, VAR, np->n_value);
231 break;
232
233 case VARIABLEPARAM:
234 makeParameter(s, n, REF, np->n_value);
235 break;
236
237 default: /* local variable */
238 --curchar;
239 makeVariable(s, n, np->n_value);
240 break;
241 }
242 if (tracesyms) {
243 printdecl(s);
244 fflush(stdout);
245 }
246}
247
248/*
249 * Enter a type name.
250 */
251
252private typeName (s)
253Symbol s;
254{
255 register integer i;
256
257 s->class = TYPE;
258 s->language = curlang;
259 s->block = curblock;
260 s->level = curblock->level + 1;
261 i = getint();
262 if (i == 0) {
263 panic("bad input on type \"%s\" at \"%s\"", symname(s), curchar);
264 } else if (i >= NTYPES) {
265 panic("too many types in file \"%s\"", curfilename());
266 }
267 /*
268 * A hack for C typedefs that don't create new types,
269 * e.g. typedef unsigned int Hashvalue;
270 * or typedef struct blah BLAH;
271 */
272 if (*curchar != '=') {
273 s->type = typetable[i];
274 if (s->type == nil) {
275 s->type = symbol_alloc();
276 typetable[i] = s->type;
277 }
278 } else {
279 if (typetable[i] != nil) {
280 typetable[i]->language = curlang;
281 typetable[i]->class = TYPE;
282 typetable[i]->type = s;
283 } else {
284 typetable[i] = s;
285 }
286 skipchar(curchar, '=');
287 getType(s);
288 }
289}
290
291/*
292 * Enter a tag name.
293 */
294
295private tagName (s)
296Symbol s;
297{
298 register integer i;
299
300 s->class = TAG;
301 i = getint();
302 if (i == 0) {
303 panic("bad input on tag \"%s\" at \"%s\"", symname(s), curchar);
304 } else if (i >= NTYPES) {
305 panic("too many types in file \"%s\"", curfilename());
306 }
307 if (typetable[i] != nil) {
308 typetable[i]->language = curlang;
309 typetable[i]->class = TYPE;
310 typetable[i]->type = s;
311 } else {
312 typetable[i] = s;
313 }
314 skipchar(curchar, '=');
315 getType(s);
316}
317
318/*
319 * Setup a symbol entry for a public procedure or function.
320 */
321
322private publicRoutine (s, class, addr)
323Symbol s;
324Symclass class;
325Address addr;
326{
327 enterRoutine(s, class);
328 s->level = program->level;
329}
330
331/*
332 * Setup a symbol entry for a private procedure or function.
333 */
334
335private privateRoutine (s, n, class, addr)
336Symbol *s;
337Name n;
338Symclass class;
339Address addr;
340{
341 Symbol t;
342 boolean isnew;
343
344 find(t, n) where
345 t->level == curmodule->level and t->class == class
346 endfind(t);
347 if (t == nil) {
348 isnew = true;
349 t = insert(n);
350 } else {
351 isnew = false;
352 }
353 t->language = curlang;
354 enterRoutine(t, class);
355 if (isnew) {
356 t->symvalue.funcv.src = false;
357 t->symvalue.funcv.inline = false;
358 t->symvalue.funcv.beginaddr = addr;
359 newfunc(t, codeloc(t));
360 findbeginning(t);
361 }
362 *s = t;
363}
364
365/*
366 * Set up for beginning a new procedure, function, or module.
367 * If it's a function, then read the type.
368 *
369 * If the next character is a ",", then read the name of the enclosing block.
370 * Otherwise assume the previous function, if any, is over, and the current
371 * routine is at the same level.
372 */
373
374private enterRoutine (s, class)
375Symbol s;
376Symclass class;
377{
378 s->class = class;
379 if (class == FUNC) {
380 getType(s);
381 }
382 if (s->class != MODULE) {
383 getExtRef(s);
384 } else if (*curchar == ',') {
385 ++curchar;
386 }
387 if (*curchar != '\0') {
388 exitblock();
389 enterNestedBlock(s);
390 } else {
391 if (curblock->class == FUNC or curblock->class == PROC) {
392 exitblock();
393 }
394 if (class == MODULE) {
395 exitblock();
396 }
397 enterblock(s);
398 }
399 curparam = s;
400}
401
402/*
403 * Check to see if the stab string contains the name of the external
404 * reference. If so, we create a symbol with that name and class EXTREF, and
405 * connect it to the given symbol. This link is created so that when
406 * we see the linker symbol we can resolve it to the given symbol.
407 */
408
409private getExtRef (s)
410Symbol s;
411{
412 char *p;
413 Name n;
414 Symbol t;
415
416 if (*curchar == ',' and *(curchar + 1) != '\0') {
417 p = index(curchar + 1, ',');
418 *curchar = '\0';
419 if (p != nil) {
420 *p = '\0';
421 n = identname(curchar + 1, false);
422 curchar = p + 1;
423 } else {
424 n = identname(curchar + 1, true);
425 }
426 t = insert(n);
427 t->language = s->language;
428 t->class = EXTREF;
429 t->block = program;
430 t->level = program->level;
431 t->symvalue.extref = s;
432 }
433}
434
435/*
436 * Find a block with the given identifier in the given outer block.
437 * If not there, then create it.
438 */
439
440private Symbol findBlock (id, m)
441String id;
442Symbol m;
443{
444 Name n;
445 Symbol s;
446
447 n = identname(id, true);
448 find(s, n) where s->block == m and isblock(s) endfind(s);
449 if (s == nil) {
450 s = insert(n);
451 s->block = m;
452 s->language = curlang;
453 s->class = MODULE;
454 s->level = m->level + 1;
455 }
456 return s;
457}
458
459/*
460 * Enter a nested block.
461 * The block within which it is nested is described
462 * by "module{:module}[:proc]".
463 */
464
465private enterNestedBlock (b)
466Symbol b;
467{
468 register char *p, *q;
469 Symbol m, s;
470 Name n;
471
472 q = curchar;
473 p = index(q, ':');
474 m = program;
475 while (p != nil) {
476 *p = '\0';
477 m = findBlock(q, m);
478 q = p + 1;
479 p = index(q, ':');
480 }
481 if (*q != '\0') {
482 m = findBlock(q, m);
483 }
484 b->level = m->level + 1;
485 b->block = m;
486 pushBlock(b);
487}
488
489/*
490 * Enter a statically-allocated variable defined within a routine.
491 *
492 * Global BSS variables are chained together so we can resolve them
493 * when the start of common is determined. The list is kept in order
494 * so that f77 can display all vars in a COMMON.
495 */
496
497private ownVariable (s, addr)
498Symbol s;
499Address addr;
500{
501 s->level = 1;
502 if (curcomm) {
503 if (commchain != nil) {
504 commchain->symvalue.common.chain = s;
505 } else {
506 curcomm->symvalue.common.offset = (integer) s;
507 }
508 commchain = s;
509 s->symvalue.common.offset = addr;
510 s->symvalue.common.chain = nil;
511 }
512}
513
514/*
515 * Get a type from the current stab string for the given symbol.
516 */
517
518private getType (s)
519Symbol s;
520{
521 s->type = constype(nil);
522 if (s->class == TAG) {
523 addtag(s);
524 }
525}
526
527/*
528 * Construct a type out of a string encoding.
529 *
530 * The forms of the string are
531 *
532 * <number>
533 * <number>=<type>
534 * r<type>;<number>;<number> -- subrange
535 * a<type>;<type> -- array[index] of element
536 * A<type> -- open array
537 * s<size>{<name>:<type>;<number>;<number>}-- record
538 * u<size>{<name>:<type>;<number>;<number>}-- union
539 * *<type> -- pointer
540 * f<type>,<integer>;<paramlist> -- function variable
541 * p<integer>;<paramlist> -- procedure variable
542 * S<type> -- set of type
543 * o<name>[,<type>] -- opaque type
544 * i<name>,<type> -- imported type
545 */
546
547private Rangetype getRangeBoundType();
548
549private Symbol constype (type)
550Symbol type;
551{
552 register Symbol t;
553 register integer n;
554 char class;
555
556 if (isdigit(*curchar)) {
557 n = getint();
558 if (n >= NTYPES) {
559 panic("too many types in file \"%s\"", curfilename());
560 }
561 if (*curchar == '=') {
562 if (typetable[n] != nil) {
563 t = typetable[n];
564 } else {
565 t = symbol_alloc();
566 typetable[n] = t;
567 }
568 ++curchar;
569 constype(t);
570 } else {
571 t = typetable[n];
572 if (t == nil) {
573 t = symbol_alloc();
574 typetable[n] = t;
575 }
576 }
577 } else {
578 if (type == nil) {
579 t = symbol_alloc();
580 } else {
581 t = type;
582 }
583 t->language = curlang;
584 t->level = curblock->level + 1;
585 t->block = curblock;
586 class = *curchar++;
587 switch (class) {
588 case T_SUBRANGE:
589 consSubrange(t);
590 break;
591
592 case T_ARRAY:
593 t->class = ARRAY;
594 t->chain = constype(nil);
595 skipchar(curchar, ';');
596 chkcont(curchar);
597 t->type = constype(nil);
598 break;
599
600 case T_OPENARRAY:
601 t->class = ARRAY;
602 t->chain = t_open;
603 t->type = constype(nil);
604 break;
605
606 case T_RECORD:
607 consRecord(t, RECORD);
608 break;
609
610 case T_UNION:
611 consRecord(t, VARNT);
612 break;
613
614 case T_ENUM:
615 consEnum(t);
616 break;
617
618 case T_PTR:
619 t->class = PTR;
620 t->type = constype(nil);
621 break;
622
623 /*
624 * C function variables are different from Modula-2's.
625 */
626 case T_FUNCVAR:
627 t->class = FFUNC;
628 t->type = constype(nil);
629 if (not streq(language_name(curlang), "c")) {
630 skipchar(curchar, ',');
631 consParamlist(t);
632 }
633 break;
634
635 case T_PROCVAR:
636 t->class = FPROC;
637 consParamlist(t);
638 break;
639
640 case T_IMPORTED:
641 consImpType(t);
642 break;
643
644 case T_SET:
645 t->class = SET;
646 t->type = constype(nil);
647 break;
648
649 case T_OPAQUE:
650 consOpaqType(t);
651 break;
652
653 default:
654 badcaseval(class);
655 }
656 }
657 return t;
658}
659
660/*
661 * Construct a subrange type.
662 */
663
664private consSubrange (t)
665Symbol t;
666{
667 t->class = RANGE;
668 t->type = constype(nil);
669 skipchar(curchar, ';');
670 chkcont(curchar);
671 t->symvalue.rangev.lowertype = getRangeBoundType();
672 t->symvalue.rangev.lower = getint();
673 skipchar(curchar, ';');
674 chkcont(curchar);
675 t->symvalue.rangev.uppertype = getRangeBoundType();
676 t->symvalue.rangev.upper = getint();
677}
678
679/*
680 * Figure out the bound type of a range.
681 *
682 * Some letters indicate a dynamic bound, ie what follows
683 * is the offset from the fp which contains the bound; this will
684 * need a different encoding when pc a['A'..'Z'] is
685 * added; J is a special flag to handle fortran a(*) bounds
686 */
687
688private Rangetype getRangeBoundType ()
689{
690 Rangetype r;
691
692 switch (*curchar) {
693 case 'A':
694 r = R_ARG;
695 curchar++;
696 break;
697
698 case 'T':
699 r = R_TEMP;
700 curchar++;
701 break;
702
703 case 'J':
704 r = R_ADJUST;
705 curchar++;
706 break;
707
708 default:
709 r = R_CONST;
710 break;
711 }
712 return r;
713}
714
715/*
716 * Construct a record or union type.
717 */
718
719private consRecord (t, class)
720Symbol t;
721Symclass class;
722{
723 register Symbol u;
724 register char *cur, *p;
725 Name name;
726 integer d;
727
728 t->class = class;
729 t->symvalue.offset = getint();
730 d = curblock->level + 1;
731 u = t;
732 cur = curchar;
733 while (*cur != ';' and *cur != '\0') {
734 p = index(cur, ':');
735 if (p == nil) {
736 panic("index(\"%s\", ':') failed", curchar);
737 }
738 *p = '\0';
739 name = identname(cur, true);
740 u->chain = newSymbol(name, d, FIELD, nil, nil);
741 cur = p + 1;
742 u = u->chain;
743 u->language = curlang;
744 curchar = cur;
745 u->type = constype(nil);
746 skipchar(curchar, ',');
747 u->symvalue.field.offset = getint();
748 skipchar(curchar, ',');
749 u->symvalue.field.length = getint();
750 skipchar(curchar, ';');
751 chkcont(curchar);
752 cur = curchar;
753 }
754 if (*cur == ';') {
755 ++cur;
756 }
757 curchar = cur;
758}
759
760/*
761 * Construct an enumeration type.
762 */
763
764private consEnum (t)
765Symbol t;
766{
767 register Symbol u;
768 register char *p;
769 register integer count;
770
771 t->class = SCAL;
772 count = 0;
773 u = t;
774 while (*curchar != ';' and *curchar != '\0') {
775 p = index(curchar, ':');
776 assert(p != nil);
777 *p = '\0';
778 u->chain = insert(identname(curchar, true));
779 curchar = p + 1;
780 u = u->chain;
781 u->language = curlang;
782 u->class = CONST;
783 u->level = curblock->level + 1;
784 u->block = curblock;
785 u->type = t;
786 u->symvalue.iconval = getint();
787 ++count;
788 skipchar(curchar, ',');
789 chkcont(curchar);
790 }
791 if (*curchar == ';') {
792 ++curchar;
793 }
794 t->symvalue.iconval = count;
795}
796
797/*
798 * Construct a parameter list for a function or procedure variable.
799 */
800
801private consParamlist (t)
802Symbol t;
803{
804 Symbol p;
805 integer i, d, n, paramclass;
806
807 n = getint();
808 skipchar(curchar, ';');
809 p = t;
810 d = curblock->level + 1;
811 for (i = 0; i < n; i++) {
812 p->chain = newSymbol(nil, d, VAR, nil, nil);
813 p = p->chain;
814 p->type = constype(nil);
815 skipchar(curchar, ',');
816 paramclass = getint();
817 if (paramclass == 0) {
818 p->class = REF;
819 }
820 skipchar(curchar, ';');
821 chkcont(curchar);
822 }
823}
824
825/*
826 * Construct an imported type.
827 * Add it to a list of symbols to get fixed up.
828 */
829
830private consImpType (t)
831Symbol t;
832{
833 register char *p;
834 Symbol tmp;
835
836 p = curchar;
837 while (*p != ',' and *p != ';' and *p != '\0') {
838 ++p;
839 }
840 if (*p == '\0') {
841 panic("bad import symbol entry '%s'", curchar);
842 }
843 t->class = TYPEREF;
844 t->symvalue.typeref = curchar;
845 curchar = p + 1;
846 if (*p == ',') {
847 curchar = p + 1;
848 tmp = constype(nil);
849 }
850 skipchar(curchar, ';');
851 *p = '\0';
852}
853
854/*
855 * Construct an opaque type entry.
856 */
857
858private consOpaqType (t)
859Symbol t;
860{
861 register char *p;
862 register Symbol s;
863 register Name n;
864 boolean def;
865
866 p = curchar;
867 while (*p != ';' and *p != ',') {
868 if (*p == '\0') {
869 panic("bad opaque symbol entry '%s'", curchar);
870 }
871 ++p;
872 }
873 def = (Boolean) (*p == ',');
874 *p = '\0';
875 n = identname(curchar, true);
876 find(s, n) where s->class == TYPEREF endfind(s);
877 if (s == nil) {
878 s = insert(n);
879 s->class = TYPEREF;
880 s->type = nil;
881 }
882 curchar = p + 1;
883 if (def) {
884 s->type = constype(nil);
885 skipchar(curchar, ';');
886 }
887 t->class = TYPE;
888 t->type = s;
889}
890
891/*
892 * Read an integer from the current position in the type string.
893 */
894
895private integer getint ()
896{
897 register integer n;
898 register char *p;
899 register Boolean isneg;
900
901 n = 0;
902 p = curchar;
903 if (*p == '-') {
904 isneg = true;
905 ++p;
906 } else {
907 isneg = false;
908 }
909 while (isdigit(*p)) {
910 n = 10*n + (*p - '0');
911 ++p;
912 }
913 curchar = p;
914 return isneg ? (-n) : n;
915}
916
917/*
918 * Add a tag name. This is a kludge to be able to refer
919 * to tags that have the same name as some other symbol
920 * in the same block.
921 */
922
923private addtag (s)
924register Symbol s;
925{
926 register Symbol t;
927 char buf[100];
928
929 sprintf(buf, "$$%.90s", ident(s->name));
930 t = insert(identname(buf, false));
931 t->language = s->language;
932 t->class = TAG;
933 t->type = s->type;
934 t->block = s->block;
935}