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