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