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