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