* Copyright (c) 1983 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)stabstring.c 5.5 (Berkeley) %G%";
* String information interpretation
* The string part of a stab entry is broken up into name and type information.
* Special characters in symbol table information.
#define PRIVPROCEDURE 'Q'
#define VARIABLEPARAM 'v'
#define LOCALVAR /* default */
* Type information special characters.
#define T_OLDOPENARRAY 'A'
* Table of types indexed by per-file unique identification number.
private Symbol typetable
[NTYPES
];
bzero(typetable
, sizeof(typetable
));
(*language_op(curlang
, L_MODINIT
))(typetable
);
* Put an nlist entry into the symbol table.
* If it's already there just add the associated information.
* Type information is encoded in the name following a ":".
private Symbol
constype();
#define skipchar(ptr, ch) \
panic("expected char '%c', found '%s'", ch, ptr); \
#define optchar(ptr, ch) \
if (*ptr == '\\' or *ptr == '?') { \
s->level = curblock->level + 1; \
#define makeVariable(s, n, off) \
s->symvalue.offset = off; \
#define makeParameter(s, n, cl, off) \
if ((s = lookup(n)) == nil or s->block != curblock) { \
s->symvalue.offset = off; \
public entersym (name
, np
)
register char *p
, *q
, *r
;
if (autostrip
and streq(language_name(curlang
), "c++")) {
* Strip off redundant prefixes from C++ names.
* Static variables are prefixed with _static_.
* Formal arguments of functions are prefixed with _au0_.
* Automatic variables are prefixed with _au[1-9][0-9]*_.
* Class members are prefixed with _T_, where T is a class tag.
if (strncmp("_static_", name
, 8) == 0 and name
[8] != '\0') {
if (*q
++ == '_' and *q
++ == 'a' and *q
++ == 'u' and isdigit(*q
++)) {
if (*q
++ == '_' and *q
!= '\0')
if (*q
++ == '_' and c
== EXTFUNCTION
) {
* Punt on static class members, for speed.
for (r
= q
; (r
= index(r
, '_')) != nil
; ++r
) {
s
= lookup(identname(q
, true));
if (s
!= nil
and s
->class == TYPE
) {
n
= identname(name
, true);
s
->level
= curblock
->level
+ 1;
publicRoutine(&s
, n
, MODULE
, np
->n_value
, false);
publicRoutine(&s
, n
, PROC
, np
->n_value
, false);
privateRoutine(&s
, n
, PROC
, np
->n_value
);
publicRoutine(&s
, n
, PROC
, np
->n_value
, true);
publicRoutine(&s
, n
, FUNC
, np
->n_value
, false);
privateRoutine(&s
, n
, FUNC
, np
->n_value
);
publicRoutine(&s
, n
, FUNC
, np
->n_value
, true);
extVar(&s
, n
, np
->n_value
);
if (curblock
->class != MODULE
) {
makeVariable(s
, n
, np
->n_value
);
s
->level
= program
->level
;
makeVariable(s
, n
, np
->n_value
);
ownVariable(s
, np
->n_value
);
makeVariable(s
, n
, np
->n_value
);
makeParameter(s
, n
, VAR
, np
->n_value
);
* Bug in SGI C compiler -- generates stab offset
* for parameters with size added in.
if (s
->storage
== STK
and curlang
== findlanguage(".c")) {
s
->symvalue
.offset
-= size(s
);
makeParameter(s
, n
, REF
, np
->n_value
);
default: /* local variable */
makeVariable(s
, n
, np
->n_value
);
* Enter a named constant.
s
->symvalue
.constval
= build(O_LCON
, getint());
s
->symvalue
.constval
= build(O_LCON
, getint());
s
->symvalue
.constval
= build(O_LCON
, getint());
sscanf(curchar
, "%lf", &d
);
while (*curchar
!= '\0' and *curchar
!= ';') {
s
->symvalue
.constval
= build(O_FCON
, d
);
while (*curchar
!= '\'') {
s
->symvalue
.constval
= build(O_SCON
, strdup(buf
));
s
->type
= s
->symvalue
.constval
->nodetype
;
s
->symvalue
.constval
= build(O_LCON
, getint());
i
= getint(); /* set size */
i
= getint(); /* number of bits in constant */
s
->symvalue
.constval
= build(O_LCON
, 0);
s
->symvalue
.constval
= build(O_LCON
, 0);
printf("[internal error: unknown constant type '%c']", *p
);
s
->symvalue
.constval
->nodetype
= s
->type
;
s
->level
= curblock
->level
+ 1;
panic("bad input on type \"%s\" at \"%s\"", symname(s
), curchar
);
} else if (i
>= NTYPES
) {
panic("too many types in file \"%s\"", curfilename());
* A hack for C typedefs that don't create new types,
* e.g. typedef unsigned int Hashvalue;
* or typedef struct blah BLAH;
s
->type
= symbol_alloc();
if (typetable
[i
] != nil
) {
typetable
[i
]->language
= curlang
;
typetable
[i
]->class = TYPE
;
panic("bad input on tag \"%s\" at \"%s\"", symname(s
), curchar
);
} else if (i
>= NTYPES
) {
panic("too many types in file \"%s\"", curfilename());
if (typetable
[i
] != nil
) {
typetable
[i
]->language
= curlang
;
typetable
[i
]->class = TYPE
;
* Setup a symbol entry for a public procedure or function.
* If it contains nested procedures, then it may already be defined
* in the current block as a MODULE.
private publicRoutine (s
, n
, class, addr
, isinternal
)
t
!= nt
and t
->class == MODULE
and t
->block
== nt
->block
t
->language
= nt
->language
;
t
->symvalue
= nt
->symvalue
;
if (t
->block
== program
) {
t
->level
= program
->level
;
} else if (t
->class == MODULE
) {
t
->level
= t
->block
->level
;
} else if (t
->block
->class == MODULE
) {
t
->level
= t
->block
->block
->level
;
t
->level
= t
->block
->level
+ 1;
* Setup a symbol entry for a private procedure or function.
private privateRoutine (s
, n
, class, addr
)
t
->level
== curmodule
->level
and t
->class == class
t
->symvalue
.funcv
.src
= false;
t
->symvalue
.funcv
.inline = false;
t
->symvalue
.funcv
.beginaddr
= addr
;
* Set up for beginning a new procedure, function, or module.
* If it's a function, then read the type.
* If the next character is a ",", then read the name of the enclosing block.
* Otherwise assume the previous function, if any, is over, and the current
* routine is at the same level.
private enterRoutine (s
, class)
if (s
->class != MODULE
) {
} else if (*curchar
== ',') {
if (curblock
->class == FUNC
or curblock
->class == PROC
) {
* Handling an external variable is tricky, since we might already
* know it but need to define it's type for other type information
* in the file. So just in case we read the type information anyway.
private extVar (symp
, n
, off
)
s
->level
== program
->level
and s
->class == VAR
s
->level
= program
->level
;
* Check to see if the stab string contains the name of the external
* reference. If so, we create a symbol with that name and class EXTREF, and
* connect it to the given symbol. This link is created so that when
* we see the linker symbol we can resolve it to the given symbol.
if (*curchar
== ',' and *(curchar
+ 1) != '\0') {
p
= index(curchar
+ 1, ',');
n
= identname(curchar
+ 1, false);
n
= identname(curchar
+ 1, true);
t
->language
= s
->language
;
t
->level
= program
->level
;
* Find a block with the given identifier in the given outer block.
* If not there, then create it.
private Symbol
findBlock (id
, m
)
find(s
, n
) where s
->block
== m
and isblock(s
) endfind(s
);
* The block within which it is nested is described
* by "module{:module}[:proc]".
private enterNestedBlock (b
)
* Enter a statically-allocated variable defined within a routine.
* Global BSS variables are chained together so we can resolve them
* when the start of common is determined. The list is kept in order
* so that f77 can display all vars in a COMMON.
private ownVariable (s
, addr
)
commchain
->symvalue
.common
.chain
= s
;
curcomm
->symvalue
.common
.offset
= (integer
) s
;
s
->symvalue
.common
.offset
= addr
;
s
->symvalue
.common
.chain
= nil
;
* Get a type from the current stab string for the given symbol.
* Construct a type out of a string encoding.
private Rangetype
getRangeBoundType();
private Symbol
constype (type
)
while (*curchar
== '@') {
fprintf(stderr
, "missing ';' after type attributes");
panic("too many types in file \"%s\"", curfilename());
if (typetable
[n
] != nil
) {
t
->level
= curblock
->level
+ 1;
t
->chain
= constype(nil
);
consDynarray(t
, OPENARRAY
);
consDynarray(t
, DYNARRAY
);
t
->symvalue
.ndims
= getint();
* C function variables are different from Modula-2's.
if (streq(language_name(curlang
), "modula-2")) {
* Construct a subrange type.
t
->symvalue
.rangev
.lowertype
= getRangeBoundType();
t
->symvalue
.rangev
.lower
= getint();
t
->symvalue
.rangev
.uppertype
= getRangeBoundType();
t
->symvalue
.rangev
.upper
= getint();
* Figure out the bound type of a range.
* Some letters indicate a dynamic bound, ie what follows
* is the offset from the fp which contains the bound; this will
* need a different encoding when pc a['A'..'Z'] is
* added; J is a special flag to handle fortran a(*) bounds
private Rangetype
getRangeBoundType ()
* Construct a dynamic array descriptor.
private consDynarray (t
, c
)
t
->symvalue
.ndims
= getint();
* Construct a record or union type.
private consRecord (t
, class)
t
->symvalue
.offset
= getint();
while (*cur
!= ';' and *cur
!= '\0') {
panic("index(\"%s\", ':') failed", curchar
);
streq(language_name(curlang
), "c++")
* Strip off redundant prefixes from C++ names.
* Class members are prefixed with _T_, where T is a class tag.
* The slow way... Check for members defined in the base class.
for (q
= cur
+ 1, r
= q
; (r
= index(r
, '_')) != nil
; ++r
) {
s
= lookup(identname(q
, true));
if (s
!= nil
and s
->class == TYPE
) {
name
= identname(cur
, true);
u
->chain
= newSymbol(name
, d
, FIELD
, nil
, nil
);
u
->symvalue
.field
.offset
= getint();
u
->symvalue
.field
.length
= getint();
* Construct an enumeration type.
while (*curchar
!= ';' and *curchar
!= '\0' and *curchar
!= ',') {
u
->chain
= insert(identname(curchar
, true));
u
->level
= curblock
->level
+ 1;
u
->symvalue
.constval
= build(O_LCON
, (long) getint());
t
->symvalue
.iconval
= count
;
* Construct a parameter list for a function or procedure variable.
private consParamlist (t
)
integer i
, d
, n
, paramclass
;
for (i
= 0; i
< n
; i
++) {
p
->chain
= newSymbol(nil
, d
, VAR
, nil
, nil
);
* Construct an imported type.
* Add it to a list of symbols to get fixed up.
while (*p
!= ',' and *p
!= ';' and *p
!= '\0') {
panic("bad import symbol entry '%s'", curchar
);
t
->symvalue
.typeref
= curchar
;
* Construct an opaque type entry.
while (*p
!= ';' and *p
!= ',') {
panic("bad opaque symbol entry '%s'", curchar
);
def
= (Boolean
) (*p
== ',');
n
= identname(curchar
, true);
find(s
, n
) where s
->class == TYPEREF
endfind(s
);
* Read an integer from the current position in the type string.
private integer
getint ()
* Add a tag name. This is a kludge to be able to refer
* to tags that have the same name as some other symbol
private Symbol
addtag (s
)
if (streq(language_name(curlang
), "c++")) {
sprintf(buf
, "$$%.90s", ident(s
->name
));
t
= insert(identname(buf
, false));
t
->language
= s
->language
;