xref: /csrg-svn/old/dbx/stabstring.c (revision 16623)
1 #ifndef lint
2 static	char sccsid[] = "@(#)stabstring.c	1.1 (Berkeley) 06/23/84"; /* 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 
68 private Symbol typetable[NTYPES];
69 
70 public 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 
83 private Symbol constype();
84 private 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 
134 public entersym (name, np)
135 String name;
136 struct 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 
252 private typeName (s)
253 Symbol 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 
295 private tagName (s)
296 Symbol 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 
322 private publicRoutine (s, class, addr)
323 Symbol s;
324 Symclass class;
325 Address 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 
335 private privateRoutine (s, n, class, addr)
336 Symbol *s;
337 Name n;
338 Symclass class;
339 Address 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 
374 private enterRoutine (s, class)
375 Symbol s;
376 Symclass 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 
409 private getExtRef (s)
410 Symbol 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 
440 private Symbol findBlock (id, m)
441 String id;
442 Symbol 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 
465 private enterNestedBlock (b)
466 Symbol 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 
497 private ownVariable (s, addr)
498 Symbol s;
499 Address 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 
518 private getType (s)
519 Symbol 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 
547 private Rangetype getRangeBoundType();
548 
549 private Symbol constype (type)
550 Symbol 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 
664 private consSubrange (t)
665 Symbol 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 
688 private 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 
719 private consRecord (t, class)
720 Symbol t;
721 Symclass 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 
764 private consEnum (t)
765 Symbol 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 
801 private consParamlist (t)
802 Symbol 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 
830 private consImpType (t)
831 Symbol 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 
858 private consOpaqType (t)
859 Symbol 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 
895 private 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 
923 private addtag (s)
924 register 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 }
936