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