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