121624Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621624Sdist */ 1718234Slinton 1816623Ssam #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)stabstring.c 5.4 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 2116623Ssam 2216623Ssam /* 2316623Ssam * String information interpretation 2416623Ssam * 2516623Ssam * The string part of a stab entry is broken up into name and type information. 2616623Ssam */ 2716623Ssam 2816623Ssam #include "defs.h" 2916623Ssam #include "stabstring.h" 3016623Ssam #include "object.h" 3116623Ssam #include "main.h" 3216623Ssam #include "symbols.h" 3316623Ssam #include "names.h" 3416623Ssam #include "languages.h" 3518234Slinton #include "tree.h" 3616623Ssam #include <a.out.h> 3716623Ssam #include <ctype.h> 3816623Ssam 3916623Ssam #ifndef public 4016623Ssam #endif 4116623Ssam 4216623Ssam /* 4316623Ssam * Special characters in symbol table information. 4416623Ssam */ 4516623Ssam 4618234Slinton #define CONSTNAME 'c' 4716623Ssam #define TYPENAME 't' 4816623Ssam #define TAGNAME 'T' 4916623Ssam #define MODULEBEGIN 'm' 5016623Ssam #define EXTPROCEDURE 'P' 5116623Ssam #define PRIVPROCEDURE 'Q' 5216623Ssam #define INTPROCEDURE 'I' 5316623Ssam #define EXTFUNCTION 'F' 5416623Ssam #define PRIVFUNCTION 'f' 5516623Ssam #define INTFUNCTION 'J' 5616623Ssam #define EXTVAR 'G' 5716623Ssam #define MODULEVAR 'S' 5816623Ssam #define OWNVAR 'V' 5916623Ssam #define REGVAR 'r' 6016623Ssam #define VALUEPARAM 'p' 6116623Ssam #define VARIABLEPARAM 'v' 6216623Ssam #define LOCALVAR /* default */ 6316623Ssam 6416623Ssam /* 6516623Ssam * Type information special characters. 6616623Ssam */ 6716623Ssam 6816623Ssam #define T_SUBRANGE 'r' 6916623Ssam #define T_ARRAY 'a' 7018234Slinton #define T_OLDOPENARRAY 'A' 7118234Slinton #define T_OPENARRAY 'O' 7218234Slinton #define T_DYNARRAY 'D' 7318234Slinton #define T_SUBARRAY 'E' 7416623Ssam #define T_RECORD 's' 7516623Ssam #define T_UNION 'u' 7616623Ssam #define T_ENUM 'e' 7716623Ssam #define T_PTR '*' 7816623Ssam #define T_FUNCVAR 'f' 7916623Ssam #define T_PROCVAR 'p' 8016623Ssam #define T_IMPORTED 'i' 8116623Ssam #define T_SET 'S' 8216623Ssam #define T_OPAQUE 'o' 8318234Slinton #define T_FILE 'd' 8416623Ssam 8516623Ssam /* 8616623Ssam * Table of types indexed by per-file unique identification number. 8716623Ssam */ 8816623Ssam 8916623Ssam #define NTYPES 1000 9016623Ssam 9116623Ssam private Symbol typetable[NTYPES]; 9216623Ssam 9316623Ssam public initTypeTable () 9416623Ssam { 9516623Ssam bzero(typetable, sizeof(typetable)); 9616623Ssam (*language_op(curlang, L_MODINIT))(typetable); 9716623Ssam } 9816623Ssam 9916623Ssam /* 10016623Ssam * Put an nlist entry into the symbol table. 10116623Ssam * If it's already there just add the associated information. 10216623Ssam * 10316623Ssam * Type information is encoded in the name following a ":". 10416623Ssam */ 10516623Ssam 10616623Ssam private Symbol constype(); 10716623Ssam private Char *curchar; 10816623Ssam 10916623Ssam #define skipchar(ptr, ch) \ 11016623Ssam { \ 11116623Ssam if (*ptr != ch) { \ 11216623Ssam panic("expected char '%c', found '%s'", ch, ptr); \ 11316623Ssam } \ 11416623Ssam ++ptr; \ 11516623Ssam } 11616623Ssam 11716623Ssam #define optchar(ptr, ch) \ 11816623Ssam { \ 11916623Ssam if (*ptr == ch) { \ 12016623Ssam ++ptr; \ 12116623Ssam } \ 12216623Ssam } 12316623Ssam 12433336Sdonn #ifdef sun 12533336Sdonn # define chkcont(ptr) \ 12616623Ssam { \ 12733336Sdonn if (*ptr == '\\' or *ptr == '?') { \ 12833336Sdonn ptr = getcont(); \ 12933336Sdonn } \ 13033336Sdonn } 13133336Sdonn #else if notsun 13233336Sdonn # define chkcont(ptr) \ 13333336Sdonn { \ 13416623Ssam if (*ptr == '?') { \ 13516623Ssam ptr = getcont(); \ 13616623Ssam } \ 13716623Ssam } 13833336Sdonn #endif 13916623Ssam 14016623Ssam #define newSym(s, n) \ 14116623Ssam { \ 14216623Ssam s = insert(n); \ 14316623Ssam s->level = curblock->level + 1; \ 14416623Ssam s->language = curlang; \ 14516623Ssam s->block = curblock; \ 14616623Ssam } 14716623Ssam 14816623Ssam #define makeVariable(s, n, off) \ 14916623Ssam { \ 15016623Ssam newSym(s, n); \ 15116623Ssam s->class = VAR; \ 15216623Ssam s->symvalue.offset = off; \ 15316623Ssam getType(s); \ 15416623Ssam } 15516623Ssam 15616623Ssam #define makeParameter(s, n, cl, off) \ 15716623Ssam { \ 15834259Sdonn if ((s = lookup(n)) == nil or s->block != curblock) { \ 15934259Sdonn newSym(s, n); \ 16034259Sdonn s->storage = STK; \ 16134259Sdonn s->class = cl; \ 16234259Sdonn s->symvalue.offset = off; \ 16334259Sdonn getType(s); \ 16434259Sdonn } \ 16516623Ssam curparam->chain = s; \ 16616623Ssam curparam = s; \ 16716623Ssam } 16816623Ssam 16916623Ssam public entersym (name, np) 17016623Ssam String name; 17116623Ssam struct nlist *np; 17216623Ssam { 17333336Sdonn Symbol s; 17433336Sdonn register char *p, *q, *r; 17516623Ssam register Name n; 17616623Ssam char c; 17716623Ssam 17816623Ssam p = index(name, ':'); 17916623Ssam *p = '\0'; 18016623Ssam c = *(p+1); 18133336Sdonn if (autostrip and streq(language_name(curlang), "c++")) { 18233336Sdonn /* 18333336Sdonn * Strip off redundant prefixes from C++ names. 18433336Sdonn * Static variables are prefixed with _static_. 18533336Sdonn * Formal arguments of functions are prefixed with _au0_. 18633336Sdonn * Automatic variables are prefixed with _au[1-9][0-9]*_. 18733336Sdonn * Class members are prefixed with _T_, where T is a class tag. 18833336Sdonn */ 18933336Sdonn if (strncmp("_static_", name, 8) == 0 and name[8] != '\0') { 19033336Sdonn name += 8; 19133336Sdonn } 19233336Sdonn q = name; 19333336Sdonn if (*q++ == '_' and *q++ == 'a' and *q++ == 'u' and isdigit(*q++)) { 19433336Sdonn while (isdigit(*q)) 19533336Sdonn ++q; 19633336Sdonn if (*q++ == '_' and *q != '\0') 19733336Sdonn name = q; 19833336Sdonn } 19933336Sdonn q = name; 20033336Sdonn if (*q++ == '_' and c == EXTFUNCTION) { 20133336Sdonn /* 20233336Sdonn * Punt on static class members, for speed. 20333336Sdonn */ 20433336Sdonn for (r = q; (r = index(r, '_')) != nil; ++r) { 20533336Sdonn if (r == q) { 20633336Sdonn continue; 20733336Sdonn } 20833336Sdonn *r = '\0'; 20933336Sdonn s = lookup(identname(q, true)); 21033336Sdonn if (s != nil and s->class == TYPE) { 21133336Sdonn char *newname = r + 1; 21233336Sdonn if (*newname != '\0') { 21333336Sdonn name = newname; 21433336Sdonn break; 21533336Sdonn } 21633336Sdonn } 21733336Sdonn *r = '_'; 21833336Sdonn } 21933336Sdonn } 22033336Sdonn } 22116623Ssam n = identname(name, true); 22216623Ssam chkUnnamedBlock(); 22316623Ssam curchar = p + 2; 22416623Ssam switch (c) { 22518234Slinton case CONSTNAME: 22618234Slinton newSym(s, n); 22718234Slinton constName(s); 22818234Slinton break; 22918234Slinton 23016623Ssam case TYPENAME: 23116623Ssam newSym(s, n); 23216623Ssam typeName(s); 23316623Ssam break; 23416623Ssam 23516623Ssam case TAGNAME: 23618234Slinton s = symbol_alloc(); 23718234Slinton s->name = n; 23818234Slinton s->level = curblock->level + 1; 23918234Slinton s->language = curlang; 24018234Slinton s->block = curblock; 24116623Ssam tagName(s); 24216623Ssam break; 24316623Ssam 24416623Ssam case MODULEBEGIN: 24518234Slinton publicRoutine(&s, n, MODULE, np->n_value, false); 24616623Ssam curmodule = s; 24716623Ssam break; 24816623Ssam 24916623Ssam case EXTPROCEDURE: 25018234Slinton publicRoutine(&s, n, PROC, np->n_value, false); 25116623Ssam break; 25216623Ssam 25316623Ssam case PRIVPROCEDURE: 25416623Ssam privateRoutine(&s, n, PROC, np->n_value); 25516623Ssam break; 25616623Ssam 25716623Ssam case INTPROCEDURE: 25818234Slinton publicRoutine(&s, n, PROC, np->n_value, true); 25916623Ssam break; 26016623Ssam 26116623Ssam case EXTFUNCTION: 26218234Slinton publicRoutine(&s, n, FUNC, np->n_value, false); 26316623Ssam break; 26416623Ssam 26516623Ssam case PRIVFUNCTION: 26616623Ssam privateRoutine(&s, n, FUNC, np->n_value); 26716623Ssam break; 26816623Ssam 26916623Ssam case INTFUNCTION: 27018234Slinton publicRoutine(&s, n, FUNC, np->n_value, true); 27116623Ssam break; 27216623Ssam 27316623Ssam case EXTVAR: 27418234Slinton extVar(&s, n, np->n_value); 27516623Ssam break; 27616623Ssam 27716623Ssam case MODULEVAR: 27816623Ssam if (curblock->class != MODULE) { 27916623Ssam exitblock(); 28016623Ssam } 28116623Ssam makeVariable(s, n, np->n_value); 28233336Sdonn s->storage = EXT; 28316623Ssam s->level = program->level; 28416623Ssam s->block = curmodule; 28516623Ssam getExtRef(s); 28616623Ssam break; 28716623Ssam 28816623Ssam case OWNVAR: 28916623Ssam makeVariable(s, n, np->n_value); 29016623Ssam ownVariable(s, np->n_value); 29116623Ssam getExtRef(s); 29216623Ssam break; 29316623Ssam 29416623Ssam case REGVAR: 29516623Ssam makeVariable(s, n, np->n_value); 29633336Sdonn s->storage = INREG; 29716623Ssam break; 29816623Ssam 29916623Ssam case VALUEPARAM: 30016623Ssam makeParameter(s, n, VAR, np->n_value); 30133336Sdonn # ifdef IRIS 30233336Sdonn /* 30333336Sdonn * Bug in SGI C compiler -- generates stab offset 30433336Sdonn * for parameters with size added in. 30533336Sdonn */ 30634259Sdonn if (s->storage == STK and curlang == findlanguage(".c")) { 30733336Sdonn s->symvalue.offset -= size(s); 30833336Sdonn } 30933336Sdonn # endif 31016623Ssam break; 31116623Ssam 31216623Ssam case VARIABLEPARAM: 31316623Ssam makeParameter(s, n, REF, np->n_value); 31416623Ssam break; 31516623Ssam 31616623Ssam default: /* local variable */ 31716623Ssam --curchar; 31816623Ssam makeVariable(s, n, np->n_value); 31933336Sdonn s->storage = STK; 32016623Ssam break; 32116623Ssam } 32216623Ssam if (tracesyms) { 32316623Ssam printdecl(s); 32416623Ssam fflush(stdout); 32516623Ssam } 32616623Ssam } 32716623Ssam 32816623Ssam /* 32918234Slinton * Enter a named constant. 33018234Slinton */ 33118234Slinton 33218234Slinton private constName (s) 33318234Slinton Symbol s; 33418234Slinton { 33518234Slinton integer i; 33618234Slinton double d; 33718234Slinton char *p, buf[1000]; 33818234Slinton 33918234Slinton s->class = CONST; 34018234Slinton skipchar(curchar, '='); 34118234Slinton p = curchar; 34218234Slinton ++curchar; 34318234Slinton switch (*p) { 34418234Slinton case 'b': 34518234Slinton s->type = t_boolean; 34618234Slinton s->symvalue.constval = build(O_LCON, getint()); 34718234Slinton break; 34818234Slinton 34918234Slinton case 'c': 35018234Slinton s->type = t_char; 35118234Slinton s->symvalue.constval = build(O_LCON, getint()); 35218234Slinton break; 35318234Slinton 35418234Slinton case 'i': 35518234Slinton s->type = t_int; 35618234Slinton s->symvalue.constval = build(O_LCON, getint()); 35718234Slinton break; 35818234Slinton 35918234Slinton case 'r': 36018234Slinton sscanf(curchar, "%lf", &d); 36118234Slinton while (*curchar != '\0' and *curchar != ';') { 36218234Slinton ++curchar; 36318234Slinton } 36418234Slinton --curchar; 36518234Slinton s->type = t_real; 36618234Slinton s->symvalue.constval = build(O_FCON, d); 36718234Slinton break; 36818234Slinton 36918234Slinton case 's': 37018234Slinton p = &buf[0]; 37118234Slinton skipchar(curchar, '\''); 37218234Slinton while (*curchar != '\'') { 37318234Slinton *p = *curchar; 37418234Slinton ++p; 37518234Slinton ++curchar; 37618234Slinton } 37718234Slinton *p = '\0'; 37818234Slinton s->symvalue.constval = build(O_SCON, strdup(buf)); 37918234Slinton s->type = s->symvalue.constval->nodetype; 38018234Slinton break; 38118234Slinton 38218234Slinton case 'e': 38318234Slinton getType(s); 38418234Slinton skipchar(curchar, ','); 38518234Slinton s->symvalue.constval = build(O_LCON, getint()); 38618234Slinton break; 38718234Slinton 38818234Slinton case 'S': 38918234Slinton getType(s); 39018234Slinton skipchar(curchar, ','); 39118234Slinton i = getint(); /* set size */ 39218234Slinton skipchar(curchar, ','); 39318234Slinton i = getint(); /* number of bits in constant */ 39418234Slinton s->symvalue.constval = build(O_LCON, 0); 39518234Slinton break; 39618234Slinton 39718234Slinton default: 39818234Slinton s->type = t_int; 39918234Slinton s->symvalue.constval = build(O_LCON, 0); 40018234Slinton printf("[internal error: unknown constant type '%c']", *p); 40118234Slinton break; 40218234Slinton } 40318234Slinton s->symvalue.constval->nodetype = s->type; 40418234Slinton } 40518234Slinton 40618234Slinton /* 40716623Ssam * Enter a type name. 40816623Ssam */ 40916623Ssam 41016623Ssam private typeName (s) 41116623Ssam Symbol s; 41216623Ssam { 41316623Ssam register integer i; 41416623Ssam 41516623Ssam s->class = TYPE; 41616623Ssam s->language = curlang; 41716623Ssam s->block = curblock; 41816623Ssam s->level = curblock->level + 1; 41916623Ssam i = getint(); 42016623Ssam if (i == 0) { 42116623Ssam panic("bad input on type \"%s\" at \"%s\"", symname(s), curchar); 42216623Ssam } else if (i >= NTYPES) { 42316623Ssam panic("too many types in file \"%s\"", curfilename()); 42416623Ssam } 42516623Ssam /* 42616623Ssam * A hack for C typedefs that don't create new types, 42716623Ssam * e.g. typedef unsigned int Hashvalue; 42816623Ssam * or typedef struct blah BLAH; 42916623Ssam */ 43016623Ssam if (*curchar != '=') { 43116623Ssam s->type = typetable[i]; 43216623Ssam if (s->type == nil) { 43316623Ssam s->type = symbol_alloc(); 43416623Ssam typetable[i] = s->type; 43516623Ssam } 43616623Ssam } else { 43716623Ssam if (typetable[i] != nil) { 43816623Ssam typetable[i]->language = curlang; 43916623Ssam typetable[i]->class = TYPE; 44016623Ssam typetable[i]->type = s; 44116623Ssam } else { 44216623Ssam typetable[i] = s; 44316623Ssam } 44416623Ssam skipchar(curchar, '='); 44516623Ssam getType(s); 44616623Ssam } 44716623Ssam } 44816623Ssam 44916623Ssam /* 45016623Ssam * Enter a tag name. 45116623Ssam */ 45216623Ssam 45316623Ssam private tagName (s) 45416623Ssam Symbol s; 45516623Ssam { 45616623Ssam register integer i; 45716623Ssam 45816623Ssam s->class = TAG; 45916623Ssam i = getint(); 46016623Ssam if (i == 0) { 46116623Ssam panic("bad input on tag \"%s\" at \"%s\"", symname(s), curchar); 46216623Ssam } else if (i >= NTYPES) { 46316623Ssam panic("too many types in file \"%s\"", curfilename()); 46416623Ssam } 46516623Ssam if (typetable[i] != nil) { 46616623Ssam typetable[i]->language = curlang; 46716623Ssam typetable[i]->class = TYPE; 46816623Ssam typetable[i]->type = s; 46916623Ssam } else { 47016623Ssam typetable[i] = s; 47116623Ssam } 47216623Ssam skipchar(curchar, '='); 47316623Ssam getType(s); 47416623Ssam } 47516623Ssam 47616623Ssam /* 47716623Ssam * Setup a symbol entry for a public procedure or function. 47818234Slinton * 47918234Slinton * If it contains nested procedures, then it may already be defined 48018234Slinton * in the current block as a MODULE. 48116623Ssam */ 48216623Ssam 48318234Slinton private publicRoutine (s, n, class, addr, isinternal) 48418234Slinton Symbol *s; 48518234Slinton Name n; 48616623Ssam Symclass class; 48716623Ssam Address addr; 48818234Slinton boolean isinternal; 48916623Ssam { 49018234Slinton Symbol nt, t; 49118234Slinton 49218234Slinton newSym(nt, n); 49318234Slinton if (isinternal) { 49418234Slinton markInternal(nt); 49518234Slinton } 49618234Slinton enterRoutine(nt, class); 49718234Slinton find(t, n) where 49818234Slinton t != nt and t->class == MODULE and t->block == nt->block 49918234Slinton endfind(t); 50018234Slinton if (t == nil) { 50118234Slinton t = nt; 50218234Slinton } else { 50318234Slinton t->language = nt->language; 50418234Slinton t->class = nt->class; 50518234Slinton t->type = nt->type; 50618234Slinton t->chain = nt->chain; 50718234Slinton t->symvalue = nt->symvalue; 50818234Slinton nt->class = EXTREF; 50918234Slinton nt->symvalue.extref = t; 51018234Slinton delete(nt); 51118234Slinton curparam = t; 51218234Slinton changeBlock(t); 51318234Slinton } 51418234Slinton if (t->block == program) { 51518234Slinton t->level = program->level; 51618234Slinton } else if (t->class == MODULE) { 51718234Slinton t->level = t->block->level; 51818234Slinton } else if (t->block->class == MODULE) { 51918234Slinton t->level = t->block->block->level; 52018234Slinton } else { 52118234Slinton t->level = t->block->level + 1; 52218234Slinton } 52318234Slinton *s = t; 52416623Ssam } 52516623Ssam 52616623Ssam /* 52716623Ssam * Setup a symbol entry for a private procedure or function. 52816623Ssam */ 52916623Ssam 53016623Ssam private privateRoutine (s, n, class, addr) 53116623Ssam Symbol *s; 53216623Ssam Name n; 53316623Ssam Symclass class; 53416623Ssam Address addr; 53516623Ssam { 53616623Ssam Symbol t; 53716623Ssam boolean isnew; 53816623Ssam 53916623Ssam find(t, n) where 54016623Ssam t->level == curmodule->level and t->class == class 54116623Ssam endfind(t); 54216623Ssam if (t == nil) { 54316623Ssam isnew = true; 54416623Ssam t = insert(n); 54516623Ssam } else { 54616623Ssam isnew = false; 54716623Ssam } 54816623Ssam t->language = curlang; 54916623Ssam enterRoutine(t, class); 55016623Ssam if (isnew) { 55116623Ssam t->symvalue.funcv.src = false; 55216623Ssam t->symvalue.funcv.inline = false; 55316623Ssam t->symvalue.funcv.beginaddr = addr; 55416623Ssam newfunc(t, codeloc(t)); 55516623Ssam findbeginning(t); 55616623Ssam } 55716623Ssam *s = t; 55816623Ssam } 55916623Ssam 56016623Ssam /* 56116623Ssam * Set up for beginning a new procedure, function, or module. 56216623Ssam * If it's a function, then read the type. 56316623Ssam * 56416623Ssam * If the next character is a ",", then read the name of the enclosing block. 56516623Ssam * Otherwise assume the previous function, if any, is over, and the current 56616623Ssam * routine is at the same level. 56716623Ssam */ 56816623Ssam 56916623Ssam private enterRoutine (s, class) 57016623Ssam Symbol s; 57116623Ssam Symclass class; 57216623Ssam { 57316623Ssam s->class = class; 57416623Ssam if (class == FUNC) { 57516623Ssam getType(s); 57616623Ssam } 57716623Ssam if (s->class != MODULE) { 57816623Ssam getExtRef(s); 57916623Ssam } else if (*curchar == ',') { 58016623Ssam ++curchar; 58116623Ssam } 58216623Ssam if (*curchar != '\0') { 58316623Ssam exitblock(); 58416623Ssam enterNestedBlock(s); 58516623Ssam } else { 58616623Ssam if (curblock->class == FUNC or curblock->class == PROC) { 58716623Ssam exitblock(); 58816623Ssam } 58916623Ssam if (class == MODULE) { 59016623Ssam exitblock(); 59116623Ssam } 59216623Ssam enterblock(s); 59316623Ssam } 59416623Ssam curparam = s; 59516623Ssam } 59616623Ssam 59716623Ssam /* 59818234Slinton * Handling an external variable is tricky, since we might already 59918234Slinton * know it but need to define it's type for other type information 60018234Slinton * in the file. So just in case we read the type information anyway. 60118234Slinton */ 60218234Slinton 60318234Slinton private extVar (symp, n, off) 60418234Slinton Symbol *symp; 60518234Slinton Name n; 60618234Slinton integer off; 60718234Slinton { 60818234Slinton Symbol s, t; 60918234Slinton 61018234Slinton find(s, n) where 61118234Slinton s->level == program->level and s->class == VAR 61218234Slinton endfind(s); 61318234Slinton if (s == nil) { 61418234Slinton makeVariable(s, n, off); 61533336Sdonn s->storage = EXT; 61618234Slinton s->level = program->level; 61718234Slinton s->block = curmodule; 61818234Slinton getExtRef(s); 61918234Slinton } else { 62018234Slinton t = constype(nil); 62118234Slinton } 62218234Slinton *symp = s; 62318234Slinton } 62418234Slinton 62518234Slinton /* 62616623Ssam * Check to see if the stab string contains the name of the external 62716623Ssam * reference. If so, we create a symbol with that name and class EXTREF, and 62816623Ssam * connect it to the given symbol. This link is created so that when 62916623Ssam * we see the linker symbol we can resolve it to the given symbol. 63016623Ssam */ 63116623Ssam 63216623Ssam private getExtRef (s) 63316623Ssam Symbol s; 63416623Ssam { 63516623Ssam char *p; 63616623Ssam Name n; 63716623Ssam Symbol t; 63816623Ssam 63916623Ssam if (*curchar == ',' and *(curchar + 1) != '\0') { 64016623Ssam p = index(curchar + 1, ','); 64116623Ssam *curchar = '\0'; 64216623Ssam if (p != nil) { 64316623Ssam *p = '\0'; 64416623Ssam n = identname(curchar + 1, false); 64516623Ssam curchar = p + 1; 64616623Ssam } else { 64716623Ssam n = identname(curchar + 1, true); 64816623Ssam } 64916623Ssam t = insert(n); 65016623Ssam t->language = s->language; 65116623Ssam t->class = EXTREF; 65216623Ssam t->block = program; 65316623Ssam t->level = program->level; 65416623Ssam t->symvalue.extref = s; 65516623Ssam } 65616623Ssam } 65716623Ssam 65816623Ssam /* 65916623Ssam * Find a block with the given identifier in the given outer block. 66016623Ssam * If not there, then create it. 66116623Ssam */ 66216623Ssam 66316623Ssam private Symbol findBlock (id, m) 66416623Ssam String id; 66516623Ssam Symbol m; 66616623Ssam { 66716623Ssam Name n; 66816623Ssam Symbol s; 66916623Ssam 67016623Ssam n = identname(id, true); 67116623Ssam find(s, n) where s->block == m and isblock(s) endfind(s); 67216623Ssam if (s == nil) { 67316623Ssam s = insert(n); 67416623Ssam s->block = m; 67516623Ssam s->language = curlang; 67616623Ssam s->class = MODULE; 67716623Ssam s->level = m->level + 1; 67816623Ssam } 67916623Ssam return s; 68016623Ssam } 68116623Ssam 68216623Ssam /* 68316623Ssam * Enter a nested block. 68416623Ssam * The block within which it is nested is described 68516623Ssam * by "module{:module}[:proc]". 68616623Ssam */ 68716623Ssam 68816623Ssam private enterNestedBlock (b) 68916623Ssam Symbol b; 69016623Ssam { 69116623Ssam register char *p, *q; 69216623Ssam Symbol m, s; 69316623Ssam Name n; 69416623Ssam 69516623Ssam q = curchar; 69616623Ssam p = index(q, ':'); 69716623Ssam m = program; 69816623Ssam while (p != nil) { 69916623Ssam *p = '\0'; 70016623Ssam m = findBlock(q, m); 70116623Ssam q = p + 1; 70216623Ssam p = index(q, ':'); 70316623Ssam } 70416623Ssam if (*q != '\0') { 70516623Ssam m = findBlock(q, m); 70616623Ssam } 70716623Ssam b->level = m->level + 1; 70816623Ssam b->block = m; 70916623Ssam pushBlock(b); 71016623Ssam } 71116623Ssam 71216623Ssam /* 71316623Ssam * Enter a statically-allocated variable defined within a routine. 71416623Ssam * 71516623Ssam * Global BSS variables are chained together so we can resolve them 71616623Ssam * when the start of common is determined. The list is kept in order 71716623Ssam * so that f77 can display all vars in a COMMON. 71816623Ssam */ 71916623Ssam 72016623Ssam private ownVariable (s, addr) 72116623Ssam Symbol s; 72216623Ssam Address addr; 72316623Ssam { 72433336Sdonn s->storage = EXT; 72533336Sdonn /* s->level = 1; */ 72616623Ssam if (curcomm) { 72716623Ssam if (commchain != nil) { 72816623Ssam commchain->symvalue.common.chain = s; 72916623Ssam } else { 73016623Ssam curcomm->symvalue.common.offset = (integer) s; 73116623Ssam } 73216623Ssam commchain = s; 73316623Ssam s->symvalue.common.offset = addr; 73416623Ssam s->symvalue.common.chain = nil; 73516623Ssam } 73616623Ssam } 73716623Ssam 73816623Ssam /* 73916623Ssam * Get a type from the current stab string for the given symbol. 74016623Ssam */ 74116623Ssam 74216623Ssam private getType (s) 74316623Ssam Symbol s; 74416623Ssam { 74533336Sdonn Symbol t, addtag(); 74633336Sdonn 74716623Ssam if (s->class == TAG) { 74833336Sdonn t = addtag(s); 74933336Sdonn t->type = constype(nil); 75033336Sdonn s->type = t->type; 75133336Sdonn } else { 75233336Sdonn s->type = constype(nil); 75316623Ssam } 75416623Ssam } 75516623Ssam 75616623Ssam /* 75716623Ssam * Construct a type out of a string encoding. 75816623Ssam */ 75916623Ssam 76016623Ssam private Rangetype getRangeBoundType(); 76116623Ssam 76216623Ssam private Symbol constype (type) 76316623Ssam Symbol type; 76416623Ssam { 76516623Ssam register Symbol t; 76616623Ssam register integer n; 76716623Ssam char class; 76818234Slinton char *p; 76916623Ssam 77018234Slinton while (*curchar == '@') { 77118234Slinton p = index(curchar, ';'); 77218234Slinton if (p == nil) { 77318234Slinton fflush(stdout); 77418234Slinton fprintf(stderr, "missing ';' after type attributes"); 77518234Slinton } else { 77618234Slinton curchar = p + 1; 77718234Slinton } 77818234Slinton } 77916623Ssam if (isdigit(*curchar)) { 78016623Ssam n = getint(); 78116623Ssam if (n >= NTYPES) { 78216623Ssam panic("too many types in file \"%s\"", curfilename()); 78316623Ssam } 78416623Ssam if (*curchar == '=') { 78516623Ssam if (typetable[n] != nil) { 78616623Ssam t = typetable[n]; 78716623Ssam } else { 78816623Ssam t = symbol_alloc(); 78916623Ssam typetable[n] = t; 79016623Ssam } 79116623Ssam ++curchar; 79216623Ssam constype(t); 79316623Ssam } else { 79416623Ssam t = typetable[n]; 79516623Ssam if (t == nil) { 79616623Ssam t = symbol_alloc(); 79716623Ssam typetable[n] = t; 79816623Ssam } 79916623Ssam } 80016623Ssam } else { 80116623Ssam if (type == nil) { 80216623Ssam t = symbol_alloc(); 80316623Ssam } else { 80416623Ssam t = type; 80516623Ssam } 80616623Ssam t->language = curlang; 80716623Ssam t->level = curblock->level + 1; 80816623Ssam t->block = curblock; 80916623Ssam class = *curchar++; 81016623Ssam switch (class) { 81116623Ssam case T_SUBRANGE: 81216623Ssam consSubrange(t); 81316623Ssam break; 81416623Ssam 81516623Ssam case T_ARRAY: 81616623Ssam t->class = ARRAY; 81716623Ssam t->chain = constype(nil); 81816623Ssam skipchar(curchar, ';'); 81916623Ssam chkcont(curchar); 82016623Ssam t->type = constype(nil); 82116623Ssam break; 82216623Ssam 82318234Slinton case T_OLDOPENARRAY: 82418234Slinton t->class = DYNARRAY; 82518234Slinton t->symvalue.ndims = 1; 82618234Slinton t->type = constype(nil); 82718234Slinton t->chain = t_int; 82818234Slinton break; 82918234Slinton 83016623Ssam case T_OPENARRAY: 83133336Sdonn consDynarray(t, OPENARRAY); 83233336Sdonn break; 83333336Sdonn 83418234Slinton case T_DYNARRAY: 83533336Sdonn consDynarray(t, DYNARRAY); 83618234Slinton break; 83718234Slinton 83818234Slinton case T_SUBARRAY: 83918234Slinton t->class = SUBARRAY; 84018234Slinton t->symvalue.ndims = getint(); 84118234Slinton skipchar(curchar, ','); 84216623Ssam t->type = constype(nil); 84318234Slinton t->chain = t_int; 84416623Ssam break; 84516623Ssam 84616623Ssam case T_RECORD: 84716623Ssam consRecord(t, RECORD); 84816623Ssam break; 84916623Ssam 85016623Ssam case T_UNION: 85116623Ssam consRecord(t, VARNT); 85216623Ssam break; 85316623Ssam 85416623Ssam case T_ENUM: 85516623Ssam consEnum(t); 85616623Ssam break; 85716623Ssam 85816623Ssam case T_PTR: 85916623Ssam t->class = PTR; 86016623Ssam t->type = constype(nil); 86116623Ssam break; 86216623Ssam 86316623Ssam /* 86416623Ssam * C function variables are different from Modula-2's. 86516623Ssam */ 86616623Ssam case T_FUNCVAR: 86716623Ssam t->class = FFUNC; 86816623Ssam t->type = constype(nil); 86933336Sdonn if (streq(language_name(curlang), "modula-2")) { 87016623Ssam skipchar(curchar, ','); 87116623Ssam consParamlist(t); 87216623Ssam } 87316623Ssam break; 87416623Ssam 87516623Ssam case T_PROCVAR: 87616623Ssam t->class = FPROC; 87716623Ssam consParamlist(t); 87816623Ssam break; 87916623Ssam 88016623Ssam case T_IMPORTED: 88116623Ssam consImpType(t); 88216623Ssam break; 88316623Ssam 88416623Ssam case T_SET: 88516623Ssam t->class = SET; 88616623Ssam t->type = constype(nil); 88716623Ssam break; 88816623Ssam 88916623Ssam case T_OPAQUE: 89016623Ssam consOpaqType(t); 89116623Ssam break; 89216623Ssam 89318234Slinton case T_FILE: 89418234Slinton t->class = FILET; 89518234Slinton t->type = constype(nil); 89618234Slinton break; 89718234Slinton 89816623Ssam default: 89916623Ssam badcaseval(class); 90016623Ssam } 90116623Ssam } 90216623Ssam return t; 90316623Ssam } 90416623Ssam 90516623Ssam /* 90616623Ssam * Construct a subrange type. 90716623Ssam */ 90816623Ssam 90916623Ssam private consSubrange (t) 91016623Ssam Symbol t; 91116623Ssam { 91216623Ssam t->class = RANGE; 91316623Ssam t->type = constype(nil); 91416623Ssam skipchar(curchar, ';'); 91516623Ssam chkcont(curchar); 91616623Ssam t->symvalue.rangev.lowertype = getRangeBoundType(); 91716623Ssam t->symvalue.rangev.lower = getint(); 91816623Ssam skipchar(curchar, ';'); 91916623Ssam chkcont(curchar); 92016623Ssam t->symvalue.rangev.uppertype = getRangeBoundType(); 92116623Ssam t->symvalue.rangev.upper = getint(); 92216623Ssam } 92316623Ssam 92416623Ssam /* 92516623Ssam * Figure out the bound type of a range. 92616623Ssam * 92716623Ssam * Some letters indicate a dynamic bound, ie what follows 92816623Ssam * is the offset from the fp which contains the bound; this will 92916623Ssam * need a different encoding when pc a['A'..'Z'] is 93016623Ssam * added; J is a special flag to handle fortran a(*) bounds 93116623Ssam */ 93216623Ssam 93316623Ssam private Rangetype getRangeBoundType () 93416623Ssam { 93516623Ssam Rangetype r; 93616623Ssam 93716623Ssam switch (*curchar) { 93816623Ssam case 'A': 93916623Ssam r = R_ARG; 94016623Ssam curchar++; 94116623Ssam break; 94216623Ssam 94316623Ssam case 'T': 94416623Ssam r = R_TEMP; 94516623Ssam curchar++; 94616623Ssam break; 94716623Ssam 94816623Ssam case 'J': 94916623Ssam r = R_ADJUST; 95016623Ssam curchar++; 95116623Ssam break; 95216623Ssam 95316623Ssam default: 95416623Ssam r = R_CONST; 95516623Ssam break; 95616623Ssam } 95716623Ssam return r; 95816623Ssam } 95916623Ssam 96016623Ssam /* 96118234Slinton * Construct a dynamic array descriptor. 96218234Slinton */ 96318234Slinton 96433336Sdonn private consDynarray (t, c) 96518234Slinton register Symbol t; 96633336Sdonn Symclass c; 96718234Slinton { 96833336Sdonn t->class = c; 96918234Slinton t->symvalue.ndims = getint(); 97018234Slinton skipchar(curchar, ','); 97118234Slinton t->type = constype(nil); 97218234Slinton t->chain = t_int; 97318234Slinton } 97418234Slinton 97518234Slinton /* 97616623Ssam * Construct a record or union type. 97716623Ssam */ 97816623Ssam 97916623Ssam private consRecord (t, class) 98016623Ssam Symbol t; 98116623Ssam Symclass class; 98216623Ssam { 98316623Ssam register Symbol u; 98416623Ssam register char *cur, *p; 98516623Ssam Name name; 98616623Ssam integer d; 98716623Ssam 98816623Ssam t->class = class; 98916623Ssam t->symvalue.offset = getint(); 99016623Ssam d = curblock->level + 1; 99116623Ssam u = t; 99233336Sdonn chkcont(curchar); 99316623Ssam cur = curchar; 99416623Ssam while (*cur != ';' and *cur != '\0') { 99516623Ssam p = index(cur, ':'); 99616623Ssam if (p == nil) { 99716623Ssam panic("index(\"%s\", ':') failed", curchar); 99816623Ssam } 99916623Ssam *p = '\0'; 100033336Sdonn if ( 100133336Sdonn autostrip and 100233336Sdonn *cur == '_' and 100333336Sdonn streq(language_name(curlang), "c++") 100433336Sdonn ) { 100533336Sdonn /* 100633336Sdonn * Strip off redundant prefixes from C++ names. 100733336Sdonn * Class members are prefixed with _T_, where T is a class tag. 100833336Sdonn */ 100933336Sdonn register char *q, *r; 101033336Sdonn Symbol s; 101133336Sdonn 101233336Sdonn /* 101333336Sdonn * The slow way... Check for members defined in the base class. 101433336Sdonn */ 101533336Sdonn for (q = cur + 1, r = q; (r = index(r, '_')) != nil; ++r) { 101633336Sdonn if (r == q) { 101733336Sdonn continue; 101833336Sdonn } 101933336Sdonn *r = '\0'; 102033336Sdonn s = lookup(identname(q, true)); 102133336Sdonn if (s != nil and s->class == TYPE) { 102233336Sdonn char *newcur = r + 1; 102333336Sdonn if (*newcur != '\0') { 102433336Sdonn cur = newcur; 102533336Sdonn break; 102633336Sdonn } 102733336Sdonn } 102833336Sdonn *r = '_'; 102933336Sdonn } 103033336Sdonn } 103116623Ssam name = identname(cur, true); 103216623Ssam u->chain = newSymbol(name, d, FIELD, nil, nil); 103316623Ssam cur = p + 1; 103416623Ssam u = u->chain; 103516623Ssam u->language = curlang; 103616623Ssam curchar = cur; 103716623Ssam u->type = constype(nil); 103816623Ssam skipchar(curchar, ','); 103916623Ssam u->symvalue.field.offset = getint(); 104016623Ssam skipchar(curchar, ','); 104116623Ssam u->symvalue.field.length = getint(); 104216623Ssam skipchar(curchar, ';'); 104316623Ssam chkcont(curchar); 104416623Ssam cur = curchar; 104516623Ssam } 104616623Ssam if (*cur == ';') { 104716623Ssam ++cur; 104816623Ssam } 104916623Ssam curchar = cur; 105016623Ssam } 105116623Ssam 105216623Ssam /* 105316623Ssam * Construct an enumeration type. 105416623Ssam */ 105516623Ssam 105616623Ssam private consEnum (t) 105716623Ssam Symbol t; 105816623Ssam { 105916623Ssam register Symbol u; 106016623Ssam register char *p; 106116623Ssam register integer count; 106216623Ssam 106316623Ssam t->class = SCAL; 106416623Ssam count = 0; 106516623Ssam u = t; 106633336Sdonn while (*curchar != ';' and *curchar != '\0' and *curchar != ',') { 106716623Ssam p = index(curchar, ':'); 106816623Ssam assert(p != nil); 106916623Ssam *p = '\0'; 107016623Ssam u->chain = insert(identname(curchar, true)); 107116623Ssam curchar = p + 1; 107216623Ssam u = u->chain; 107316623Ssam u->language = curlang; 107416623Ssam u->class = CONST; 107516623Ssam u->level = curblock->level + 1; 107616623Ssam u->block = curblock; 107716623Ssam u->type = t; 107818234Slinton u->symvalue.constval = build(O_LCON, (long) getint()); 107916623Ssam ++count; 108016623Ssam skipchar(curchar, ','); 108116623Ssam chkcont(curchar); 108216623Ssam } 108316623Ssam if (*curchar == ';') { 108416623Ssam ++curchar; 108516623Ssam } 108616623Ssam t->symvalue.iconval = count; 108716623Ssam } 108816623Ssam 108916623Ssam /* 109016623Ssam * Construct a parameter list for a function or procedure variable. 109116623Ssam */ 109216623Ssam 109316623Ssam private consParamlist (t) 109416623Ssam Symbol t; 109516623Ssam { 109616623Ssam Symbol p; 109716623Ssam integer i, d, n, paramclass; 109816623Ssam 109916623Ssam n = getint(); 110016623Ssam skipchar(curchar, ';'); 110116623Ssam p = t; 110216623Ssam d = curblock->level + 1; 110316623Ssam for (i = 0; i < n; i++) { 110416623Ssam p->chain = newSymbol(nil, d, VAR, nil, nil); 110516623Ssam p = p->chain; 110616623Ssam p->type = constype(nil); 110716623Ssam skipchar(curchar, ','); 110816623Ssam paramclass = getint(); 110916623Ssam if (paramclass == 0) { 111016623Ssam p->class = REF; 111116623Ssam } 111216623Ssam skipchar(curchar, ';'); 111316623Ssam chkcont(curchar); 111416623Ssam } 111516623Ssam } 111616623Ssam 111716623Ssam /* 111816623Ssam * Construct an imported type. 111916623Ssam * Add it to a list of symbols to get fixed up. 112016623Ssam */ 112116623Ssam 112216623Ssam private consImpType (t) 112316623Ssam Symbol t; 112416623Ssam { 112516623Ssam register char *p; 112616623Ssam Symbol tmp; 112716623Ssam 112816623Ssam p = curchar; 112916623Ssam while (*p != ',' and *p != ';' and *p != '\0') { 113016623Ssam ++p; 113116623Ssam } 113216623Ssam if (*p == '\0') { 113316623Ssam panic("bad import symbol entry '%s'", curchar); 113416623Ssam } 113516623Ssam t->class = TYPEREF; 113616623Ssam t->symvalue.typeref = curchar; 113716623Ssam if (*p == ',') { 113816623Ssam curchar = p + 1; 113916623Ssam tmp = constype(nil); 114018234Slinton } else { 114118234Slinton curchar = p; 114216623Ssam } 114316623Ssam skipchar(curchar, ';'); 114416623Ssam *p = '\0'; 114516623Ssam } 114616623Ssam 114716623Ssam /* 114816623Ssam * Construct an opaque type entry. 114916623Ssam */ 115016623Ssam 115116623Ssam private consOpaqType (t) 115216623Ssam Symbol t; 115316623Ssam { 115416623Ssam register char *p; 115516623Ssam register Symbol s; 115616623Ssam register Name n; 115716623Ssam boolean def; 115816623Ssam 115916623Ssam p = curchar; 116016623Ssam while (*p != ';' and *p != ',') { 116116623Ssam if (*p == '\0') { 116216623Ssam panic("bad opaque symbol entry '%s'", curchar); 116316623Ssam } 116416623Ssam ++p; 116516623Ssam } 116616623Ssam def = (Boolean) (*p == ','); 116716623Ssam *p = '\0'; 116816623Ssam n = identname(curchar, true); 116916623Ssam find(s, n) where s->class == TYPEREF endfind(s); 117016623Ssam if (s == nil) { 117116623Ssam s = insert(n); 117216623Ssam s->class = TYPEREF; 117316623Ssam s->type = nil; 117416623Ssam } 117516623Ssam curchar = p + 1; 117616623Ssam if (def) { 117716623Ssam s->type = constype(nil); 117816623Ssam skipchar(curchar, ';'); 117916623Ssam } 118016623Ssam t->class = TYPE; 118116623Ssam t->type = s; 118216623Ssam } 118316623Ssam 118416623Ssam /* 118516623Ssam * Read an integer from the current position in the type string. 118616623Ssam */ 118716623Ssam 118816623Ssam private integer getint () 118916623Ssam { 119016623Ssam register integer n; 119116623Ssam register char *p; 119216623Ssam register Boolean isneg; 119316623Ssam 119416623Ssam n = 0; 119516623Ssam p = curchar; 119616623Ssam if (*p == '-') { 119716623Ssam isneg = true; 119816623Ssam ++p; 119916623Ssam } else { 120016623Ssam isneg = false; 120116623Ssam } 120216623Ssam while (isdigit(*p)) { 120316623Ssam n = 10*n + (*p - '0'); 120416623Ssam ++p; 120516623Ssam } 120616623Ssam curchar = p; 120716623Ssam return isneg ? (-n) : n; 120816623Ssam } 120916623Ssam 121016623Ssam /* 121116623Ssam * Add a tag name. This is a kludge to be able to refer 121216623Ssam * to tags that have the same name as some other symbol 121316623Ssam * in the same block. 121416623Ssam */ 121516623Ssam 121633336Sdonn private Symbol addtag (s) 121716623Ssam register Symbol s; 121816623Ssam { 121916623Ssam register Symbol t; 122016623Ssam char buf[100]; 122116623Ssam 122233336Sdonn if (streq(language_name(curlang), "c++")) { 122333336Sdonn t = insert(s->name); 122433336Sdonn t->class = TYPE; 122533336Sdonn } else { 122633336Sdonn sprintf(buf, "$$%.90s", ident(s->name)); 122733336Sdonn t = insert(identname(buf, false)); 122833336Sdonn t->class = TAG; 122933336Sdonn } 123016623Ssam t->language = s->language; 123116623Ssam t->block = s->block; 123233336Sdonn return t; 123316623Ssam } 1234