1 /*
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)stabstring.c 5.6 (Berkeley) 03/05/91";
10 #endif /* not lint */
11
12 /*
13 * String information interpretation
14 *
15 * The string part of a stab entry is broken up into name and type information.
16 */
17
18 #include "defs.h"
19 #include "stabstring.h"
20 #include "object.h"
21 #include "main.h"
22 #include "symbols.h"
23 #include "names.h"
24 #include "languages.h"
25 #include "tree.h"
26 #include <a.out.h>
27 #include <ctype.h>
28
29 #ifndef public
30 #endif
31
32 /*
33 * Special characters in symbol table information.
34 */
35
36 #define CONSTNAME 'c'
37 #define TYPENAME 't'
38 #define TAGNAME 'T'
39 #define MODULEBEGIN 'm'
40 #define EXTPROCEDURE 'P'
41 #define PRIVPROCEDURE 'Q'
42 #define INTPROCEDURE 'I'
43 #define EXTFUNCTION 'F'
44 #define PRIVFUNCTION 'f'
45 #define INTFUNCTION 'J'
46 #define EXTVAR 'G'
47 #define MODULEVAR 'S'
48 #define OWNVAR 'V'
49 #define REGVAR 'r'
50 #define VALUEPARAM 'p'
51 #define VARIABLEPARAM 'v'
52 #define LOCALVAR /* default */
53
54 /*
55 * Type information special characters.
56 */
57
58 #define T_SUBRANGE 'r'
59 #define T_ARRAY 'a'
60 #define T_OLDOPENARRAY 'A'
61 #define T_OPENARRAY 'O'
62 #define T_DYNARRAY 'D'
63 #define T_SUBARRAY 'E'
64 #define T_RECORD 's'
65 #define T_UNION 'u'
66 #define T_ENUM 'e'
67 #define T_PTR '*'
68 #define T_FUNCVAR 'f'
69 #define T_PROCVAR 'p'
70 #define T_IMPORTED 'i'
71 #define T_SET 'S'
72 #define T_OPAQUE 'o'
73 #define T_FILE 'd'
74
75 /*
76 * Table of types indexed by per-file unique identification number.
77 */
78
79 #define NTYPES 1000
80
81 private Symbol typetable[NTYPES];
82
initTypeTable()83 public initTypeTable ()
84 {
85 bzero(typetable, sizeof(typetable));
86 (*language_op(curlang, L_MODINIT))(typetable);
87 }
88
89 /*
90 * Put an nlist entry into the symbol table.
91 * If it's already there just add the associated information.
92 *
93 * Type information is encoded in the name following a ":".
94 */
95
96 private Symbol constype();
97 private Char *curchar;
98
99 #define skipchar(ptr, ch) \
100 { \
101 if (*ptr != ch) { \
102 panic("expected char '%c', found '%s'", ch, ptr); \
103 } \
104 ++ptr; \
105 }
106
107 #define optchar(ptr, ch) \
108 { \
109 if (*ptr == ch) { \
110 ++ptr; \
111 } \
112 }
113
114 #ifdef sun
115 # define chkcont(ptr) \
116 { \
117 if (*ptr == '\\' or *ptr == '?') { \
118 ptr = getcont(); \
119 } \
120 }
121 #else if notsun
122 # define chkcont(ptr) \
123 { \
124 if (*ptr == '?') { \
125 ptr = getcont(); \
126 } \
127 }
128 #endif
129
130 #define newSym(s, n) \
131 { \
132 s = insert(n); \
133 s->level = curblock->level + 1; \
134 s->language = curlang; \
135 s->block = curblock; \
136 }
137
138 #define makeVariable(s, n, off) \
139 { \
140 newSym(s, n); \
141 s->class = VAR; \
142 s->symvalue.offset = off; \
143 getType(s); \
144 }
145
146 #define makeParameter(s, n, cl, off) \
147 { \
148 if ((s = lookup(n)) == nil or s->block != curblock) { \
149 newSym(s, n); \
150 s->storage = STK; \
151 s->class = cl; \
152 s->symvalue.offset = off; \
153 getType(s); \
154 } \
155 curparam->chain = s; \
156 curparam = s; \
157 }
158
entersym(name,np)159 public entersym (name, np)
160 String name;
161 struct nlist *np;
162 {
163 Symbol s;
164 register char *p, *q, *r;
165 register Name n;
166 char c;
167
168 p = index(name, ':');
169 *p = '\0';
170 c = *(p+1);
171 if (autostrip and streq(language_name(curlang), "c++")) {
172 /*
173 * Strip off redundant prefixes from C++ names.
174 * Static variables are prefixed with _static_.
175 * Formal arguments of functions are prefixed with _au0_.
176 * Automatic variables are prefixed with _au[1-9][0-9]*_.
177 * Class members are prefixed with _T_, where T is a class tag.
178 */
179 if (strncmp("_static_", name, 8) == 0 and name[8] != '\0') {
180 name += 8;
181 }
182 q = name;
183 if (*q++ == '_' and *q++ == 'a' and *q++ == 'u' and isdigit(*q++)) {
184 while (isdigit(*q))
185 ++q;
186 if (*q++ == '_' and *q != '\0')
187 name = q;
188 }
189 q = name;
190 if (*q++ == '_' and c == EXTFUNCTION) {
191 /*
192 * Punt on static class members, for speed.
193 */
194 for (r = q; (r = index(r, '_')) != nil; ++r) {
195 if (r == q) {
196 continue;
197 }
198 *r = '\0';
199 s = lookup(identname(q, true));
200 if (s != nil and s->class == TYPE) {
201 char *newname = r + 1;
202 if (*newname != '\0') {
203 name = newname;
204 break;
205 }
206 }
207 *r = '_';
208 }
209 }
210 }
211 n = identname(name, true);
212 chkUnnamedBlock();
213 curchar = p + 2;
214 switch (c) {
215 case CONSTNAME:
216 newSym(s, n);
217 constName(s);
218 break;
219
220 case TYPENAME:
221 newSym(s, n);
222 typeName(s);
223 break;
224
225 case TAGNAME:
226 s = symbol_alloc();
227 s->name = n;
228 s->level = curblock->level + 1;
229 s->language = curlang;
230 s->block = curblock;
231 tagName(s);
232 break;
233
234 case MODULEBEGIN:
235 publicRoutine(&s, n, MODULE, np->n_value, false);
236 curmodule = s;
237 break;
238
239 case EXTPROCEDURE:
240 publicRoutine(&s, n, PROC, np->n_value, false);
241 break;
242
243 case PRIVPROCEDURE:
244 privateRoutine(&s, n, PROC, np->n_value);
245 break;
246
247 case INTPROCEDURE:
248 publicRoutine(&s, n, PROC, np->n_value, true);
249 break;
250
251 case EXTFUNCTION:
252 publicRoutine(&s, n, FUNC, np->n_value, false);
253 break;
254
255 case PRIVFUNCTION:
256 privateRoutine(&s, n, FUNC, np->n_value);
257 break;
258
259 case INTFUNCTION:
260 publicRoutine(&s, n, FUNC, np->n_value, true);
261 break;
262
263 case EXTVAR:
264 extVar(&s, n, np->n_value);
265 break;
266
267 case MODULEVAR:
268 if (curblock->class != MODULE) {
269 exitblock();
270 }
271 makeVariable(s, n, np->n_value);
272 s->storage = EXT;
273 s->level = program->level;
274 s->block = curmodule;
275 getExtRef(s);
276 break;
277
278 case OWNVAR:
279 makeVariable(s, n, np->n_value);
280 ownVariable(s, np->n_value);
281 getExtRef(s);
282 break;
283
284 case REGVAR:
285 makeVariable(s, n, np->n_value);
286 s->storage = INREG;
287 break;
288
289 case VALUEPARAM:
290 makeParameter(s, n, VAR, np->n_value);
291 # ifdef IRIS
292 /*
293 * Bug in SGI C compiler -- generates stab offset
294 * for parameters with size added in.
295 */
296 if (s->storage == STK and curlang == findlanguage(".c")) {
297 s->symvalue.offset -= size(s);
298 }
299 # endif
300 break;
301
302 case VARIABLEPARAM:
303 makeParameter(s, n, REF, np->n_value);
304 break;
305
306 default: /* local variable */
307 --curchar;
308 makeVariable(s, n, np->n_value);
309 s->storage = STK;
310 break;
311 }
312 if (tracesyms) {
313 printdecl(s);
314 fflush(stdout);
315 }
316 }
317
318 /*
319 * Enter a named constant.
320 */
321
constName(s)322 private constName (s)
323 Symbol s;
324 {
325 integer i;
326 double d;
327 char *p, buf[1000];
328
329 s->class = CONST;
330 skipchar(curchar, '=');
331 p = curchar;
332 ++curchar;
333 switch (*p) {
334 case 'b':
335 s->type = t_boolean;
336 s->symvalue.constval = build(O_LCON, getint());
337 break;
338
339 case 'c':
340 s->type = t_char;
341 s->symvalue.constval = build(O_LCON, getint());
342 break;
343
344 case 'i':
345 s->type = t_int;
346 s->symvalue.constval = build(O_LCON, getint());
347 break;
348
349 case 'r':
350 sscanf(curchar, "%lf", &d);
351 while (*curchar != '\0' and *curchar != ';') {
352 ++curchar;
353 }
354 --curchar;
355 s->type = t_real;
356 s->symvalue.constval = build(O_FCON, d);
357 break;
358
359 case 's':
360 p = &buf[0];
361 skipchar(curchar, '\'');
362 while (*curchar != '\'') {
363 *p = *curchar;
364 ++p;
365 ++curchar;
366 }
367 *p = '\0';
368 s->symvalue.constval = build(O_SCON, strdup(buf));
369 s->type = s->symvalue.constval->nodetype;
370 break;
371
372 case 'e':
373 getType(s);
374 skipchar(curchar, ',');
375 s->symvalue.constval = build(O_LCON, getint());
376 break;
377
378 case 'S':
379 getType(s);
380 skipchar(curchar, ',');
381 i = getint(); /* set size */
382 skipchar(curchar, ',');
383 i = getint(); /* number of bits in constant */
384 s->symvalue.constval = build(O_LCON, 0);
385 break;
386
387 default:
388 s->type = t_int;
389 s->symvalue.constval = build(O_LCON, 0);
390 printf("[internal error: unknown constant type '%c']", *p);
391 break;
392 }
393 s->symvalue.constval->nodetype = s->type;
394 }
395
396 /*
397 * Enter a type name.
398 */
399
typeName(s)400 private typeName (s)
401 Symbol s;
402 {
403 register integer i;
404
405 s->class = TYPE;
406 s->language = curlang;
407 s->block = curblock;
408 s->level = curblock->level + 1;
409 i = getint();
410 if (i == 0) {
411 panic("bad input on type \"%s\" at \"%s\"", symname(s), curchar);
412 } else if (i >= NTYPES) {
413 panic("too many types in file \"%s\"", curfilename());
414 }
415 /*
416 * A hack for C typedefs that don't create new types,
417 * e.g. typedef unsigned int Hashvalue;
418 * or typedef struct blah BLAH;
419 */
420 if (*curchar != '=') {
421 s->type = typetable[i];
422 if (s->type == nil) {
423 s->type = symbol_alloc();
424 typetable[i] = s->type;
425 }
426 } else {
427 if (typetable[i] != nil) {
428 typetable[i]->language = curlang;
429 typetable[i]->class = TYPE;
430 typetable[i]->type = s;
431 } else {
432 typetable[i] = s;
433 }
434 skipchar(curchar, '=');
435 getType(s);
436 }
437 }
438
439 /*
440 * Enter a tag name.
441 */
442
tagName(s)443 private tagName (s)
444 Symbol s;
445 {
446 register integer i;
447
448 s->class = TAG;
449 i = getint();
450 if (i == 0) {
451 panic("bad input on tag \"%s\" at \"%s\"", symname(s), curchar);
452 } else if (i >= NTYPES) {
453 panic("too many types in file \"%s\"", curfilename());
454 }
455 if (typetable[i] != nil) {
456 typetable[i]->language = curlang;
457 typetable[i]->class = TYPE;
458 typetable[i]->type = s;
459 } else {
460 typetable[i] = s;
461 }
462 skipchar(curchar, '=');
463 getType(s);
464 }
465
466 /*
467 * Setup a symbol entry for a public procedure or function.
468 *
469 * If it contains nested procedures, then it may already be defined
470 * in the current block as a MODULE.
471 */
472
publicRoutine(s,n,class,addr,isinternal)473 private publicRoutine (s, n, class, addr, isinternal)
474 Symbol *s;
475 Name n;
476 Symclass class;
477 Address addr;
478 boolean isinternal;
479 {
480 Symbol nt, t;
481
482 newSym(nt, n);
483 if (isinternal) {
484 markInternal(nt);
485 }
486 enterRoutine(nt, class);
487 find(t, n) where
488 t != nt and t->class == MODULE and t->block == nt->block
489 endfind(t);
490 if (t == nil) {
491 t = nt;
492 } else {
493 t->language = nt->language;
494 t->class = nt->class;
495 t->type = nt->type;
496 t->chain = nt->chain;
497 t->symvalue = nt->symvalue;
498 nt->class = EXTREF;
499 nt->symvalue.extref = t;
500 delete(nt);
501 curparam = t;
502 changeBlock(t);
503 }
504 if (t->block == program) {
505 t->level = program->level;
506 } else if (t->class == MODULE) {
507 t->level = t->block->level;
508 } else if (t->block->class == MODULE) {
509 t->level = t->block->block->level;
510 } else {
511 t->level = t->block->level + 1;
512 }
513 *s = t;
514 }
515
516 /*
517 * Setup a symbol entry for a private procedure or function.
518 */
519
privateRoutine(s,n,class,addr)520 private privateRoutine (s, n, class, addr)
521 Symbol *s;
522 Name n;
523 Symclass class;
524 Address addr;
525 {
526 Symbol t;
527 boolean isnew;
528
529 find(t, n) where
530 t->level == curmodule->level and t->class == class
531 endfind(t);
532 if (t == nil) {
533 isnew = true;
534 t = insert(n);
535 } else {
536 isnew = false;
537 }
538 t->language = curlang;
539 enterRoutine(t, class);
540 if (isnew) {
541 t->symvalue.funcv.src = false;
542 t->symvalue.funcv.inlne = false;
543 t->symvalue.funcv.beginaddr = addr;
544 newfunc(t, codeloc(t));
545 findbeginning(t);
546 }
547 *s = t;
548 }
549
550 /*
551 * Set up for beginning a new procedure, function, or module.
552 * If it's a function, then read the type.
553 *
554 * If the next character is a ",", then read the name of the enclosing block.
555 * Otherwise assume the previous function, if any, is over, and the current
556 * routine is at the same level.
557 */
558
enterRoutine(s,class)559 private enterRoutine (s, class)
560 Symbol s;
561 Symclass class;
562 {
563 s->class = class;
564 if (class == FUNC) {
565 getType(s);
566 }
567 if (s->class != MODULE) {
568 getExtRef(s);
569 } else if (*curchar == ',') {
570 ++curchar;
571 }
572 if (*curchar != '\0') {
573 exitblock();
574 enterNestedBlock(s);
575 } else {
576 if (curblock->class == FUNC or curblock->class == PROC) {
577 exitblock();
578 }
579 if (class == MODULE) {
580 exitblock();
581 }
582 enterblock(s);
583 }
584 curparam = s;
585 }
586
587 /*
588 * Handling an external variable is tricky, since we might already
589 * know it but need to define it's type for other type information
590 * in the file. So just in case we read the type information anyway.
591 */
592
extVar(symp,n,off)593 private extVar (symp, n, off)
594 Symbol *symp;
595 Name n;
596 integer off;
597 {
598 Symbol s, t;
599
600 find(s, n) where
601 s->level == program->level and s->class == VAR
602 endfind(s);
603 if (s == nil) {
604 makeVariable(s, n, off);
605 s->storage = EXT;
606 s->level = program->level;
607 s->block = curmodule;
608 getExtRef(s);
609 } else {
610 t = constype(nil);
611 }
612 *symp = s;
613 }
614
615 /*
616 * Check to see if the stab string contains the name of the external
617 * reference. If so, we create a symbol with that name and class EXTREF, and
618 * connect it to the given symbol. This link is created so that when
619 * we see the linker symbol we can resolve it to the given symbol.
620 */
621
getExtRef(s)622 private getExtRef (s)
623 Symbol s;
624 {
625 char *p;
626 Name n;
627 Symbol t;
628
629 if (*curchar == ',' and *(curchar + 1) != '\0') {
630 p = index(curchar + 1, ',');
631 *curchar = '\0';
632 if (p != nil) {
633 *p = '\0';
634 n = identname(curchar + 1, false);
635 curchar = p + 1;
636 } else {
637 n = identname(curchar + 1, true);
638 }
639 t = insert(n);
640 t->language = s->language;
641 t->class = EXTREF;
642 t->block = program;
643 t->level = program->level;
644 t->symvalue.extref = s;
645 }
646 }
647
648 /*
649 * Find a block with the given identifier in the given outer block.
650 * If not there, then create it.
651 */
652
findBlock(id,m)653 private Symbol findBlock (id, m)
654 String id;
655 Symbol m;
656 {
657 Name n;
658 Symbol s;
659
660 n = identname(id, true);
661 find(s, n) where s->block == m and isblock(s) endfind(s);
662 if (s == nil) {
663 s = insert(n);
664 s->block = m;
665 s->language = curlang;
666 s->class = MODULE;
667 s->level = m->level + 1;
668 }
669 return s;
670 }
671
672 /*
673 * Enter a nested block.
674 * The block within which it is nested is described
675 * by "module{:module}[:proc]".
676 */
677
enterNestedBlock(b)678 private enterNestedBlock (b)
679 Symbol b;
680 {
681 register char *p, *q;
682 Symbol m, s;
683 Name n;
684
685 q = curchar;
686 p = index(q, ':');
687 m = program;
688 while (p != nil) {
689 *p = '\0';
690 m = findBlock(q, m);
691 q = p + 1;
692 p = index(q, ':');
693 }
694 if (*q != '\0') {
695 m = findBlock(q, m);
696 }
697 b->level = m->level + 1;
698 b->block = m;
699 pushBlock(b);
700 }
701
702 /*
703 * Enter a statically-allocated variable defined within a routine.
704 *
705 * Global BSS variables are chained together so we can resolve them
706 * when the start of common is determined. The list is kept in order
707 * so that f77 can display all vars in a COMMON.
708 */
709
ownVariable(s,addr)710 private ownVariable (s, addr)
711 Symbol s;
712 Address addr;
713 {
714 s->storage = EXT;
715 /* s->level = 1; */
716 if (curcomm) {
717 if (commchain != nil) {
718 commchain->symvalue.common.chain = s;
719 } else {
720 curcomm->symvalue.common.offset = (integer) s;
721 }
722 commchain = s;
723 s->symvalue.common.offset = addr;
724 s->symvalue.common.chain = nil;
725 }
726 }
727
728 /*
729 * Get a type from the current stab string for the given symbol.
730 */
731
getType(s)732 private getType (s)
733 Symbol s;
734 {
735 Symbol t, addtag();
736
737 if (s->class == TAG) {
738 t = addtag(s);
739 t->type = constype(nil);
740 s->type = t->type;
741 } else {
742 s->type = constype(nil);
743 }
744 }
745
746 /*
747 * Construct a type out of a string encoding.
748 */
749
750 private Rangetype getRangeBoundType();
751
constype(type)752 private Symbol constype (type)
753 Symbol type;
754 {
755 register Symbol t;
756 register integer n;
757 char class;
758 char *p;
759
760 while (*curchar == '@') {
761 p = index(curchar, ';');
762 if (p == nil) {
763 fflush(stdout);
764 fprintf(stderr, "missing ';' after type attributes");
765 } else {
766 curchar = p + 1;
767 }
768 }
769 if (isdigit(*curchar)) {
770 n = getint();
771 if (n >= NTYPES) {
772 panic("too many types in file \"%s\"", curfilename());
773 }
774 if (*curchar == '=') {
775 if (typetable[n] != nil) {
776 t = typetable[n];
777 } else {
778 t = symbol_alloc();
779 typetable[n] = t;
780 }
781 ++curchar;
782 constype(t);
783 } else {
784 t = typetable[n];
785 if (t == nil) {
786 t = symbol_alloc();
787 typetable[n] = t;
788 }
789 }
790 } else {
791 if (type == nil) {
792 t = symbol_alloc();
793 } else {
794 t = type;
795 }
796 t->language = curlang;
797 t->level = curblock->level + 1;
798 t->block = curblock;
799 class = *curchar++;
800 switch (class) {
801 case T_SUBRANGE:
802 consSubrange(t);
803 break;
804
805 case T_ARRAY:
806 t->class = ARRAY;
807 t->chain = constype(nil);
808 skipchar(curchar, ';');
809 chkcont(curchar);
810 t->type = constype(nil);
811 break;
812
813 case T_OLDOPENARRAY:
814 t->class = DYNARRAY;
815 t->symvalue.ndims = 1;
816 t->type = constype(nil);
817 t->chain = t_int;
818 break;
819
820 case T_OPENARRAY:
821 consDynarray(t, OPENARRAY);
822 break;
823
824 case T_DYNARRAY:
825 consDynarray(t, DYNARRAY);
826 break;
827
828 case T_SUBARRAY:
829 t->class = SUBARRAY;
830 t->symvalue.ndims = getint();
831 skipchar(curchar, ',');
832 t->type = constype(nil);
833 t->chain = t_int;
834 break;
835
836 case T_RECORD:
837 consRecord(t, RECORD);
838 break;
839
840 case T_UNION:
841 consRecord(t, VARNT);
842 break;
843
844 case T_ENUM:
845 consEnum(t);
846 break;
847
848 case T_PTR:
849 t->class = PTR;
850 t->type = constype(nil);
851 break;
852
853 /*
854 * C function variables are different from Modula-2's.
855 */
856 case T_FUNCVAR:
857 t->class = FFUNC;
858 t->type = constype(nil);
859 if (streq(language_name(curlang), "modula-2")) {
860 skipchar(curchar, ',');
861 consParamlist(t);
862 }
863 break;
864
865 case T_PROCVAR:
866 t->class = FPROC;
867 consParamlist(t);
868 break;
869
870 case T_IMPORTED:
871 consImpType(t);
872 break;
873
874 case T_SET:
875 t->class = SET;
876 t->type = constype(nil);
877 break;
878
879 case T_OPAQUE:
880 consOpaqType(t);
881 break;
882
883 case T_FILE:
884 t->class = FILET;
885 t->type = constype(nil);
886 break;
887
888 default:
889 badcaseval(class);
890 }
891 }
892 return t;
893 }
894
895 /*
896 * Construct a subrange type.
897 */
898
consSubrange(t)899 private consSubrange (t)
900 Symbol t;
901 {
902 t->class = RANGE;
903 t->type = constype(nil);
904 skipchar(curchar, ';');
905 chkcont(curchar);
906 t->symvalue.rangev.lowertype = getRangeBoundType();
907 t->symvalue.rangev.lower = getint();
908 skipchar(curchar, ';');
909 chkcont(curchar);
910 t->symvalue.rangev.uppertype = getRangeBoundType();
911 t->symvalue.rangev.upper = getint();
912 }
913
914 /*
915 * Figure out the bound type of a range.
916 *
917 * Some letters indicate a dynamic bound, ie what follows
918 * is the offset from the fp which contains the bound; this will
919 * need a different encoding when pc a['A'..'Z'] is
920 * added; J is a special flag to handle fortran a(*) bounds
921 */
922
getRangeBoundType()923 private Rangetype getRangeBoundType ()
924 {
925 Rangetype r;
926
927 switch (*curchar) {
928 case 'A':
929 r = R_ARG;
930 curchar++;
931 break;
932
933 case 'T':
934 r = R_TEMP;
935 curchar++;
936 break;
937
938 case 'J':
939 r = R_ADJUST;
940 curchar++;
941 break;
942
943 default:
944 r = R_CONST;
945 break;
946 }
947 return r;
948 }
949
950 /*
951 * Construct a dynamic array descriptor.
952 */
953
consDynarray(t,c)954 private consDynarray (t, c)
955 register Symbol t;
956 Symclass c;
957 {
958 t->class = c;
959 t->symvalue.ndims = getint();
960 skipchar(curchar, ',');
961 t->type = constype(nil);
962 t->chain = t_int;
963 }
964
965 /*
966 * Construct a record or union type.
967 */
968
consRecord(t,class)969 private consRecord (t, class)
970 Symbol t;
971 Symclass class;
972 {
973 register Symbol u;
974 register char *cur, *p;
975 Name name;
976 integer d;
977
978 t->class = class;
979 t->symvalue.offset = getint();
980 d = curblock->level + 1;
981 u = t;
982 chkcont(curchar);
983 cur = curchar;
984 while (*cur != ';' and *cur != '\0') {
985 p = index(cur, ':');
986 if (p == nil) {
987 panic("index(\"%s\", ':') failed", curchar);
988 }
989 *p = '\0';
990 if (
991 autostrip and
992 *cur == '_' and
993 streq(language_name(curlang), "c++")
994 ) {
995 /*
996 * Strip off redundant prefixes from C++ names.
997 * Class members are prefixed with _T_, where T is a class tag.
998 */
999 register char *q, *r;
1000 Symbol s;
1001
1002 /*
1003 * The slow way... Check for members defined in the base class.
1004 */
1005 for (q = cur + 1, r = q; (r = index(r, '_')) != nil; ++r) {
1006 if (r == q) {
1007 continue;
1008 }
1009 *r = '\0';
1010 s = lookup(identname(q, true));
1011 if (s != nil and s->class == TYPE) {
1012 char *newcur = r + 1;
1013 if (*newcur != '\0') {
1014 cur = newcur;
1015 break;
1016 }
1017 }
1018 *r = '_';
1019 }
1020 }
1021 name = identname(cur, true);
1022 u->chain = newSymbol(name, d, FIELD, nil, nil);
1023 cur = p + 1;
1024 u = u->chain;
1025 u->language = curlang;
1026 curchar = cur;
1027 u->type = constype(nil);
1028 skipchar(curchar, ',');
1029 u->symvalue.field.offset = getint();
1030 skipchar(curchar, ',');
1031 u->symvalue.field.length = getint();
1032 skipchar(curchar, ';');
1033 chkcont(curchar);
1034 cur = curchar;
1035 }
1036 if (*cur == ';') {
1037 ++cur;
1038 }
1039 curchar = cur;
1040 }
1041
1042 /*
1043 * Construct an enumeration type.
1044 */
1045
consEnum(t)1046 private consEnum (t)
1047 Symbol t;
1048 {
1049 register Symbol u;
1050 register char *p;
1051 register integer count;
1052
1053 t->class = SCAL;
1054 count = 0;
1055 u = t;
1056 while (*curchar != ';' and *curchar != '\0' and *curchar != ',') {
1057 p = index(curchar, ':');
1058 assert(p != nil);
1059 *p = '\0';
1060 u->chain = insert(identname(curchar, true));
1061 curchar = p + 1;
1062 u = u->chain;
1063 u->language = curlang;
1064 u->class = CONST;
1065 u->level = curblock->level + 1;
1066 u->block = curblock;
1067 u->type = t;
1068 u->symvalue.constval = build(O_LCON, (long) getint());
1069 ++count;
1070 skipchar(curchar, ',');
1071 chkcont(curchar);
1072 }
1073 if (*curchar == ';') {
1074 ++curchar;
1075 }
1076 t->symvalue.iconval = count;
1077 }
1078
1079 /*
1080 * Construct a parameter list for a function or procedure variable.
1081 */
1082
consParamlist(t)1083 private consParamlist (t)
1084 Symbol t;
1085 {
1086 Symbol p;
1087 integer i, d, n, paramclass;
1088
1089 n = getint();
1090 skipchar(curchar, ';');
1091 p = t;
1092 d = curblock->level + 1;
1093 for (i = 0; i < n; i++) {
1094 p->chain = newSymbol(nil, d, VAR, nil, nil);
1095 p = p->chain;
1096 p->type = constype(nil);
1097 skipchar(curchar, ',');
1098 paramclass = getint();
1099 if (paramclass == 0) {
1100 p->class = REF;
1101 }
1102 skipchar(curchar, ';');
1103 chkcont(curchar);
1104 }
1105 }
1106
1107 /*
1108 * Construct an imported type.
1109 * Add it to a list of symbols to get fixed up.
1110 */
1111
consImpType(t)1112 private consImpType (t)
1113 Symbol t;
1114 {
1115 register char *p;
1116 Symbol tmp;
1117
1118 p = curchar;
1119 while (*p != ',' and *p != ';' and *p != '\0') {
1120 ++p;
1121 }
1122 if (*p == '\0') {
1123 panic("bad import symbol entry '%s'", curchar);
1124 }
1125 t->class = TYPEREF;
1126 t->symvalue.typeref = curchar;
1127 if (*p == ',') {
1128 curchar = p + 1;
1129 tmp = constype(nil);
1130 } else {
1131 curchar = p;
1132 }
1133 skipchar(curchar, ';');
1134 *p = '\0';
1135 }
1136
1137 /*
1138 * Construct an opaque type entry.
1139 */
1140
consOpaqType(t)1141 private consOpaqType (t)
1142 Symbol t;
1143 {
1144 register char *p;
1145 register Symbol s;
1146 register Name n;
1147 boolean def;
1148
1149 p = curchar;
1150 while (*p != ';' and *p != ',') {
1151 if (*p == '\0') {
1152 panic("bad opaque symbol entry '%s'", curchar);
1153 }
1154 ++p;
1155 }
1156 def = (Boolean) (*p == ',');
1157 *p = '\0';
1158 n = identname(curchar, true);
1159 find(s, n) where s->class == TYPEREF endfind(s);
1160 if (s == nil) {
1161 s = insert(n);
1162 s->class = TYPEREF;
1163 s->type = nil;
1164 }
1165 curchar = p + 1;
1166 if (def) {
1167 s->type = constype(nil);
1168 skipchar(curchar, ';');
1169 }
1170 t->class = TYPE;
1171 t->type = s;
1172 }
1173
1174 /*
1175 * Read an integer from the current position in the type string.
1176 */
1177
getint()1178 private integer getint ()
1179 {
1180 register integer n;
1181 register char *p;
1182 register Boolean isneg;
1183
1184 n = 0;
1185 p = curchar;
1186 if (*p == '-') {
1187 isneg = true;
1188 ++p;
1189 } else {
1190 isneg = false;
1191 }
1192 while (isdigit(*p)) {
1193 n = 10*n + (*p - '0');
1194 ++p;
1195 }
1196 curchar = p;
1197 return isneg ? (-n) : n;
1198 }
1199
1200 /*
1201 * Add a tag name. This is a kludge to be able to refer
1202 * to tags that have the same name as some other symbol
1203 * in the same block.
1204 */
1205
addtag(s)1206 private Symbol addtag (s)
1207 register Symbol s;
1208 {
1209 register Symbol t;
1210 char buf[100];
1211
1212 if (streq(language_name(curlang), "c++")) {
1213 t = insert(s->name);
1214 t->class = TYPE;
1215 } else {
1216 sprintf(buf, "$$%.90s", ident(s->name));
1217 t = insert(identname(buf, false));
1218 t->class = TAG;
1219 }
1220 t->language = s->language;
1221 t->block = s->block;
1222 return t;
1223 }
1224