static char sccsid
[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/27 10:24:04 linton Exp */
* 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.
* 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) \
s->level = curblock->level + 1; \
#define makeVariable(s, n, off) \
s->symvalue.offset = off; \
#define makeParameter(s, n, cl, off) \
s->symvalue.offset = off; \
public entersym (name
, np
)
n
= identname(name
, true);
publicRoutine(s
, MODULE
, np
->n_value
);
publicRoutine(s
, PROC
, np
->n_value
);
privateRoutine(&s
, n
, PROC
, np
->n_value
);
publicRoutine(s
, PROC
, np
->n_value
);
publicRoutine(s
, FUNC
, np
->n_value
);
privateRoutine(&s
, n
, FUNC
, np
->n_value
);
publicRoutine(s
, FUNC
, np
->n_value
);
s
->level
== program
->level
and s
->class == VAR
makeVariable(s
, n
, np
->n_value
);
s
->level
= program
->level
;
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
);
makeParameter(s
, n
, REF
, np
->n_value
);
default: /* local variable */
makeVariable(s
, n
, np
->n_value
);
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.
private publicRoutine (s
, class, addr
)
s
->level
= program
->level
;
* 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
) {
* 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.
* The forms of the string are
* r<type>;<number>;<number> -- subrange
* a<type>;<type> -- array[index] of element
* s<size>{<name>:<type>;<number>;<number>}-- record
* u<size>{<name>:<type>;<number>;<number>}-- union
* f<type>,<integer>;<paramlist> -- function variable
* p<integer>;<paramlist> -- procedure variable
* o<name>[,<type>] -- opaque type
* i<name>,<type> -- imported type
private Rangetype
getRangeBoundType();
private Symbol
constype (type
)
panic("too many types in file \"%s\"", curfilename());
if (typetable
[n
] != nil
) {
t
->level
= curblock
->level
+ 1;
t
->chain
= constype(nil
);
* C function variables are different from Modula-2's.
if (not streq(language_name(curlang
), "c")) {
* 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 record or union type.
private consRecord (t
, class)
t
->symvalue
.offset
= getint();
while (*cur
!= ';' and *cur
!= '\0') {
panic("index(\"%s\", ':') failed", curchar
);
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') {
u
->chain
= insert(identname(curchar
, true));
u
->level
= curblock
->level
+ 1;
u
->symvalue
.iconval
= 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
sprintf(buf
, "$$%.90s", ident(s
->name
));
t
= insert(identname(buf
, false));
t
->language
= s
->language
;