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