ack/util/grind/db_symtab.g

925 lines
21 KiB
Plaintext

/* $Header$ */
/* Symbol table reader
*/
{
#include <alloc.h>
#include <stb.h>
#include <assert.h>
#include "position.h"
#include "file.h"
#include "type.h"
#include "symbol.h"
#include "scope.h"
#include "class.h"
#include "idf.h"
#include "rd.h"
extern char *strindex();
extern long str2long();
extern double atof();
static char *DbPtr; /* current pointer in db string */
static int AllowName; /* set if NAME legal at this point */
static long ival;
static double fval;
static char *strval;
static int last_index[2];
static struct outname *currnam;
static int saw_code;
static struct literal *get_literal_space();
static struct fields *get_field_space();
static end_field();
static char *string_val();
}
%start DbParser, debugger_string;
%prefix DBS;
%lexical DBSlex;
%onerror DBSonerror;
%token INTEGER, REAL, STRING, NAME;
debugger_string
{ register p_symbol s;
char *str;
p_type tmp = 0;
int upb = 0;
}
:
name(&str)
[ /* constant name */
{ s = NewSymbol(str, CurrentScope, CONST, currnam); }
'c' const_name(s)
| /* type name */
{ s = NewSymbol(str, CurrentScope, TYPE, currnam); }
't' type_name(&(s->sy_type), s)
{ if (! s->sy_type->ty_sym) s->sy_type->ty_sym = s;
if ((s->sy_type->ty_class == T_ENUM ||
s->sy_type->ty_class == T_SUBRANGE) &&
currnam->on_desc != 0) {
s->sy_type->ty_size = currnam->on_desc;
}
}
| /* tag name (only C?) */
{ s = NewSymbol(str, CurrentScope, TAG, currnam); }
'T' type_name(&(s->sy_type), s)
{ if (! s->sy_type->ty_sym) s->sy_type->ty_sym = s;
if (s->sy_type->ty_class != T_CROSS) {
resolve_cross(s->sy_type);
}
}
| /* end scope */
'E' INTEGER
{ close_scope(); }
| /* module begin */
{ s = NewSymbol(str, CurrentScope, MODULE, currnam); }
'M' INTEGER
{ open_scope(s, 1);
s->sy_name.nm_scope = CurrentScope;
CurrentScope->sc_start = currnam->on_valu;
CurrentScope->sc_proclevel = currnam->on_desc;
add_scope_addr(CurrentScope);
}
| /* external procedure */
{ s = NewSymbol(str, FileScope, PROC, currnam); }
'P' routine(s)
| /* private procedure */
{ s = NewSymbol(str, CurrentScope, PROC, currnam); }
'Q' routine(s)
| /* external function */
{ s = NewSymbol(str, FileScope, FUNCTION, currnam); }
'F' function(s)
| /* private function */
{ s = NewSymbol(str, CurrentScope, FUNCTION, currnam); }
'f' function(s)
| /* global variable, external */
/* maybe we already know it; but we need
the type information anyway for other
types.
*/
{ s = Lookup(findidf(str), FileScope, VAR);
if (s) {
tmp = s->sy_type;
s->sy_type = 0;
} else s = NewSymbol(str, FileScope, VAR, currnam);
}
'G' type(&(s->sy_type), (int *) 0, s)
{ if (tmp) s->sy_type = tmp; }
| /* static variable */
{ s = NewSymbol(str, CurrentScope, VAR, currnam); }
'S' type(&(s->sy_type), (int *) 0, s)
| /* static variable, local scope */
{ s = NewSymbol(str, CurrentScope, VAR, currnam); }
'V' type(&(s->sy_type), (int *) 0, s)
| /* register variable */
{ s = NewSymbol(str, CurrentScope, REGVAR, currnam); }
'r' type(&(s->sy_type), (int *) 0, s)
| /* value parameter */
{ s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
'p' type(&(s->sy_type), (int *) 0, s)
{ add_param_type('p', s); }
| /* value parameter but address passed */
{ s = NewSymbol(str, CurrentScope, VARPAR, currnam); }
'i' type(&(s->sy_type), (int *) 0, s)
{ add_param_type('i', s); }
| /* variable parameter */
{ s = NewSymbol(str, CurrentScope, VARPAR, currnam); }
'v' type(&(s->sy_type), (int *) 0, s)
{ add_param_type('v', s); }
| /* local variable */
{ s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
type_name(&(s->sy_type), s)
| /* lower or upper bound of array descriptor */
[ 'A' { upb = LBOUND; }
| 'Z' { upb = UBOUND; }
]
[ ['p' | ] { s = NewSymbol(str, CurrentScope, LOCVAR, currnam);
if (upb == UBOUND) add_param_type('Z', s);
}
| [ 'V' | 'S' ] { s = NewSymbol(str, CurrentScope, VAR, currnam); }
]
type_name(&(s->sy_type), s)
{ p_symbol s1 = new_symbol();
*s1 = *s;
s->sy_class = upb;
s->sy_descr = s1;
}
| /* function result in Pascal; ignore ??? */
{ s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
'X' type_name(&(s->sy_type), s)
]
';'?
;
name(char **s;)
:
/* anything up to a ':' */
NAME { *s = strval; }
;
const_name(p_symbol cst;)
{ int type_index[2];
long iconst;
register char *p;
}
:
'='
[
/*
'b' integer_const(&(cst->sy_const.co_ival)) /* boolean */
/* |
*/
'c' integer_const(&(cst->sy_const.co_ival)) /* character */
{ cst->sy_type = char_type; }
|
'i' integer_const(&(cst->sy_const.co_ival)) /* integer */
{ cst->sy_type = long_type; }
|
'r' real_const(&(cst->sy_const.co_rval)) /* real */
{ cst->sy_type = double_type; }
|
's' string_const /* string */
{ cst->sy_const.co_sval = string_val(strval);
cst->sy_type = string_type;
}
|
'e' type_index(type_index) ',' integer_const(&(cst->sy_const.co_ival))
/* enumeration constant;
* enumeration type, value
*/
{ cst->sy_type = *tp_lookup(type_index); }
|
'S' type_index(type_index)
{ cst->sy_type = *tp_lookup(type_index);
cst->sy_const.co_setval = p =
Malloc((unsigned) cst->sy_type->ty_size);
}
[ ',' integer_const(&iconst)
{ *p++ = iconst; }
]+
/* set constant:
* settype, values of the bytes
* in the set.
*/
]
;
integer_const(long *iconst;)
{ int sign = 0; }
:
[ '+' | '-' { sign = 1; } ]?
INTEGER { *iconst = sign ? -ival : ival; }
;
real_const(double *f;)
{ int sign = 0; }
:
[ '+' | '-' { sign = 1; } ]?
REAL { *f = sign ? fval : -fval; }
;
string_const
:
STRING /* has SINGLE quotes! */
;
type_name(p_type *t; p_symbol sy;)
{ int type_index[2]; p_type *p; }
:
type_index(type_index) { p = tp_lookup(type_index); }
[
{ if (*p && (*p)->ty_class != 0 &&
(*p)->ty_class != T_CROSS) {
error("Redefining (%d,%d) %d",
type_index[0],
type_index[1],
(*p)->ty_class);
}
}
'='
type(p, type_index, sy)
|
{ if (*t && ! *p) *p = *t;
else if (*t) **t = **p;
}
]
{ if (*p == 0) *p = new_type();
*t = *p;
}
;
type_index(int *type_index;)
:
[
INTEGER { type_index[0] = 0; type_index[1] = ival; }
|
'(' INTEGER { type_index[0] = ival; }
',' INTEGER { type_index[1] = ival; }
')'
]
{ last_index[0] = type_index[0];
last_index[1] = type_index[1];
}
;
function(p_symbol p;)
:
{ p->sy_type = new_type();
p->sy_type->ty_class = T_PROCEDURE;
p->sy_type->ty_size = pointer_size;
}
type(&(p->sy_type->ty_retval), (int *) 0, (p_symbol) 0)
{ if (CurrentScope != FileScope &&
saw_code) {
/* if saw_code is not set, it is a nested
procedure
*/
close_scope();
}
saw_code = 0;
open_scope(p, 1);
p->sy_name.nm_scope = CurrentScope;
CurrentScope->sc_start = currnam->on_valu;
add_scope_addr(CurrentScope);
CurrentScope->sc_proclevel = currnam->on_desc;
}
;
routine(p_symbol p;)
:
{ p->sy_type = new_type();
p->sy_type->ty_class = T_PROCEDURE;
p->sy_type->ty_size = pointer_size;
if (CurrentScope != FileScope &&
saw_code) {
/* if saw_code is not set, it is a nested
procedure
*/
close_scope();
}
saw_code = 0;
open_scope(p, 1);
p->sy_name.nm_scope = CurrentScope;
CurrentScope->sc_start = currnam->on_valu;
add_scope_addr(CurrentScope);
CurrentScope->sc_proclevel = currnam->on_desc;
}
INTEGER ';'
type(&(p->sy_type->ty_retval), (int *) 0, (p_symbol) 0)
;
type(p_type *ptp; int *type_index; p_symbol sy;)
{ register p_type tp = *ptp ? *ptp : new_type();
p_type t1 = 0, t2 = 0;
long ic1, ic2;
int A_used = 0;
int tclass;
int tp_index[2];
char *str;
}
:
[
/* type cross reference */
/* these are used in C for references to a struct, union or
* enum that has not been declared (yet)
*/
'x'
[ 's' /* struct */
{ tclass = T_STRUCT; }
| 'u' /* union */
{ tclass = T_UNION; }
| 'e' /* enum */
{ tclass = T_ENUM; }
]
{ AllowName = 1; }
name(&str)
{ sy = Lookfromscope(str2idf(str,0),TAG,CurrentScope);
if (sy &&
(sy->sy_type->ty_class == tclass ||
sy->sy_type->ty_class == T_CROSS)) {
if (tp != *ptp) free_type(tp);
tp = sy->sy_type;
}
else {
tp->ty_class = T_CROSS;
tp->ty_size = tclass;
sy = NewSymbol(str, CurrentScope, TAG, (struct outname *) 0);
sy->sy_type = tp;
}
}
|
/* subrange */
/* the integer_const's represent the lower and the upper bound.
* A subrange type defined as subrange of itself is an integer type.
* If the second integer_const == 0, but the first is not, we
* have a floating point type with size equal to the first
* integer_const.
* Upperbound -1 means unsigned int or unsigned long.
*/
'r' type_index(tp_index) ';'
[ 'A' integer_const(&ic1) { A_used = 1; }
| integer_const(&ic1)
]
';'
[ 'A' integer_const(&ic2) { A_used |= 2; }
| integer_const(&ic2)
| 'Z' integer_const(&ic2) { A_used |= 0200; }
]
{ if (tp != *ptp) free_type(tp);
tp = subrange_type(A_used,
tp_index,
ic1,
ic2,
type_index);
}
|
/* array; first type is bound type, next type
* is element type
*/
'a' type(&t1, (int *) 0, (p_symbol) 0) ';' type(&t2, (int *) 0, (p_symbol) 0)
{ if (tp != *ptp) free_type(tp);
tp = array_type(t1, t2);
}
|
/* structure type */
's' { tp->ty_class = T_STRUCT; }
structure_type(tp, sy)
|
/* union type */
'u' { tp->ty_class = T_UNION; }
structure_type(tp, sy)
|
/* enumeration type */
'e' { tp->ty_class = T_ENUM; }
enum_type(tp)
|
/* pointer type */
'*' { tp->ty_class = T_POINTER;
tp->ty_size = pointer_size;
}
type(&(tp->ty_ptrto), (int *) 0, (p_symbol) 0)
|
/* function type */
'f' { tp->ty_class = T_PROCEDURE;
tp->ty_size = pointer_size;
}
type(&(tp->ty_retval), (int *) 0, (p_symbol) 0)
/*
[ %prefer
',' param_list(tp)
|
]
*/
|
/* procedure type */
'Q' { tp->ty_class = T_PROCEDURE;
tp->ty_size = pointer_size;
}
type(&(tp->ty_retval), (int *) 0, (p_symbol) 0)
',' param_list(tp)
|
/* another procedure type */
'p' { tp->ty_class = T_PROCEDURE;
tp->ty_size = pointer_size;
tp->ty_retval = void_type;
}
param_list(tp)
|
/* set type */
/* the first integer_const represents the size in bytes,
* the second one represents the low bound
*/
'S' { tp->ty_class = T_SET; }
type(&(tp->ty_setbase), (int *) 0, (p_symbol) 0) ';'
[
integer_const(&(tp->ty_size)) ';'
integer_const(&(tp->ty_setlow)) ';'
|
{ set_bounds(tp); }
]
|
/* file type of Pascal */
'L' { tp->ty_class = T_FILE; }
type(&(tp->ty_fileof), (int *) 0, (p_symbol) 0)
|
type_name(ptp, (p_symbol) 0)
{ if (type_index &&
(*ptp)->ty_class == 0 &&
type_index[0] == last_index[0] &&
type_index[1] == last_index[1]) {
**ptp = *void_type;
if (*ptp != tp) free_type(tp);
}
tp = *ptp;
}
]
{ if (*ptp && *ptp != tp) **ptp = *tp;
else *ptp = tp;
}
;
structure_type(register p_type tp; p_symbol sy;)
{ register struct fields *fldp;
char *str;
}
:
integer_const(&(tp->ty_size)) /* size in bytes */
{ open_scope(sy, 0);
if (sy) sy->sy_name.nm_scope = CurrentScope;
}
[
name(&str) { fldp = get_field_space(tp, str); }
type(&(fldp->fld_type), (int *) 0, (p_symbol) 0) ','
integer_const(&(fldp->fld_pos)) ',' /* offset in bits */
integer_const(&(fldp->fld_bitsize)) ';' /* size in bits */
]*
';' { end_field(tp);
close_scope();
}
;
enum_type(register p_type tp;)
{ register struct literal *litp;
long maxval = 0;
register p_symbol s;
}
:
[ { litp = get_literal_space(tp); }
name(&(litp->lit_name))
integer_const(&(litp->lit_val)) ','
{ if (maxval < litp->lit_val) maxval = litp->lit_val;
AllowName = 1;
s = NewSymbol(litp->lit_name, CurrentScope, CONST, (struct outname *) 0);
s->sy_const.co_ival = litp->lit_val;
s->sy_type = tp;
}
]*
';' { end_literal(tp, maxval); }
;
param_list(p_type t;)
{ register struct param *p;
long iconst;
}
:
integer_const(&iconst) ';' /* number of parameters */
{ t->ty_nparams = iconst;
t->ty_params = p = (struct param *)
Malloc((unsigned)(t->ty_nparams * sizeof(struct param)));
}
[
[ 'p' { p->par_kind = 'p'; }
| 'v' { p->par_kind = 'v'; }
| 'i' { p->par_kind = 'i'; }
]
type(&(p->par_type), (int *) 0, (p_symbol) 0) ';'
{ p->par_off = t->ty_nbparams;
t->ty_nbparams +=
param_size(p->par_type, p->par_kind);
p++;
}
]*
;
{
static char *db_string;
static char *DbOldPtr;
static struct outname *
DbString(n)
struct outname *n;
{
currnam = n;
DbPtr = n->on_mptr;
db_string = DbPtr;
AllowName = 1;
DbParser();
return currnam;
}
/*ARGSUSED*/
DBSmessage(n)
{
fatal("error in symbol table string \"%s\", DbPtr = \"%s\", DbOldPtr = \"%s\"",
db_string,
DbPtr,
DbOldPtr);
}
DBSonerror(tk, p)
int *p;
{
DbPtr = DbOldPtr;
/* ??? if (DBSsymb < 0) {
while (*p && *p != ';') p++;
if (*p) DbPtr = ";";
return;
}
*/
if (! tk) {
while (*p && *p != NAME) p++;
if (*p) {
AllowName = 1;
}
}
else if (tk == NAME) AllowName = 1;
}
DBSlex()
{
register char *cp = DbPtr;
int allow_name = AllowName;
register int c;
AllowName = 0;
DbOldPtr = cp;
c = *cp;
if (c == '\\' && *(cp+1) == '\0') {
currnam++;
cp = currnam->on_mptr;
DbOldPtr = cp;
c = *cp;
}
if (! c) {
DbPtr = cp;
return -1;
}
if ((! allow_name && is_token(c)) || c == ';') {
DbPtr = cp+1;
return c;
}
if (is_dig(c)) {
int retval = INTEGER;
while (++cp, is_dig(*cp)) /* nothing */;
c = *cp;
if (c == '.') {
retval = REAL;
while (++cp, is_dig(*cp)) /* nothing */;
c = *cp;
}
if (c == 'e' || c == 'E') {
char *oldcp = cp;
cp++;
c = *cp;
if (c == '-' || c == '+') {
cp++;
c = *cp;
}
if (is_dig(c)) {
retval = REAL;
while (++cp, is_dig(*cp)) /* nothing */;
}
else cp = oldcp;
}
c = *cp;
*cp = 0;
if (retval == INTEGER) {
ival = str2long(DbOldPtr, 10);
}
else {
fval = atof(DbOldPtr);
}
*cp = c;
DbPtr = cp;
return retval;
}
if (c == '\'') {
cp++;
strval = cp;
while ((c = *cp) && c != '\'') {
if (c == '\\') cp++; /* backslash escapes next character */
if (!(c = *cp)) break; /* but not a null byte */
cp++;
}
if (! c) DBSmessage(0); /* no return */
*cp = 0;
DbPtr = cp + 1;
return STRING;
}
strval = cp;
while ((c = *cp) && c != ':' && c != ',') cp++;
DbPtr = *cp ? cp+1 : cp;
*cp = 0;
return NAME;
}
static struct fields *
get_field_space(tp, s)
register p_type tp;
char *s;
{
register struct fields *p;
p_symbol sy;
if (! (tp->ty_nfields & 07)) {
tp->ty_fields = (struct fields *)
Realloc((char *) tp->ty_fields,
(tp->ty_nfields+8)*sizeof(struct fields));
}
p = &tp->ty_fields[tp->ty_nfields++];
p->fld_name = s;
p->fld_type = 0;
sy = NewSymbol(s, CurrentScope, FIELD, currnam);
sy->sy_field = p;
return p;
}
static
end_field(tp)
register p_type tp;
{
tp->ty_fields = (struct fields *)
Realloc((char *) tp->ty_fields,
tp->ty_nfields * sizeof(struct fields));
}
static struct literal *
get_literal_space(tp)
register p_type tp;
{
if (! (tp->ty_nenums & 07)) {
tp->ty_literals = (struct literal *)
Realloc((char *) tp->ty_literals,
(tp->ty_nenums+8)*sizeof(struct literal));
}
return &tp->ty_literals[tp->ty_nenums++];
}
static char *
string_val(s)
char *s;
{
register char *ns = s, *os = s;
register unsigned int i = 1;
for (;;) {
if (!*os) break;
i++;
if (*os == '\\') {
os++;
*ns++ = *os++;
}
else *ns++ = *os++;
}
*ns = '\0';
return Salloc(s, i);
}
static char *AckStrings; /* ACK a.out string table */
static struct outname *AckNames; /* ACK a.out symbol table entries */
static unsigned int NAckNames; /* Number of ACK symbol table entries */
static struct outname *EndAckNames; /* &AckNames[NAckNames] */
/* Read the symbol table from file 'f', which is supposed to be an
ACK a.out format file. Offer db strings to the db string parser.
*/
int
DbRead(f)
char *f;
{
struct outhead h;
register struct outname *n;
register struct outname *line_file = 0;
long OffsetStrings;
int lbrac_required = 0;
int needs_newscope = 0;
int lbrac_level = 0;
/* Open file, read header, and check magic word */
if (! rd_open(f)) {
fatal("%s: could not open", f);
}
rd_ohead(&h);
if (BADMAGIC(h) && h.oh_magic != O_CONVERTED) {
fatal("%s: not an object file", f);
}
/* Allocate space for name table and read it */
AckNames = (struct outname *)
Malloc((unsigned)(sizeof(struct outname) * h.oh_nname));
AckStrings = Malloc((unsigned) h.oh_nchar);
rd_name(AckNames, h.oh_nname);
rd_string(AckStrings, h.oh_nchar);
/* Adjust file offsets in name table to point at strings */
OffsetStrings = OFF_CHAR(h);
NAckNames = h.oh_nname;
EndAckNames = &AckNames[h.oh_nname];
for (n = EndAckNames; --n >= AckNames;) {
if (n->on_foff) {
if ((unsigned)(n->on_foff - OffsetStrings) >= h.oh_nchar) {
fatal("%s: error in object file", f);
}
n->on_mptr = AckStrings + (n->on_foff - OffsetStrings);
}
else n->on_mptr = 0;
}
/* Offer strings to the db string parser if they contain a ':'.
Also offer filename-line number information to add_position_addr().
Here, the order may be important.
*/
for (n = &AckNames[0]; n < EndAckNames; n++) {
int tp = n->on_type >> 8;
register p_symbol sym;
if (tp & (S_STB >> 8)) {
switch(tp) {
#ifdef N_BINCL
case N_BINCL:
n->on_valu = (long) line_file;
line_file = n;
break;
case N_EINCL:
if (line_file) {
line_file = (struct outname *) line_file->on_valu;
}
break;
#endif
case N_SO:
if (n->on_mptr[strlen(n->on_mptr)-1] == '/') {
/* another N_SO follows ... */
break;
}
clean_tp_tab();
while (CurrentScope != PervasiveScope) {
close_scope();
}
saw_code = 0;
sym = add_file(n->on_mptr);
if (! listfile) newfile(sym->sy_idf);
open_scope(sym, 0);
sym->sy_file->f_scope = CurrentScope;
FileScope = CurrentScope;
CurrentScope->sc_start = n->on_valu;
/* fall through */
case N_SOL:
if (! line_file) line_file = n;
else line_file->on_mptr = n->on_mptr;
break;
case N_MAIN:
if (! FileScope) fatal("No file scope");
newfile(FileScope->sc_definedby->sy_idf);
break;
case N_SLINE:
assert(line_file);
if (CurrentScope->sc_start) {
register p_scope sc =
get_scope_from_addr(n->on_valu);
if (sc) CurrentScope = sc;
}
if (! saw_code && !CurrentScope->sc_bp_opp) {
CurrentScope->sc_bp_opp = n->on_valu;
if (! CurrentScope->sc_start) {
CurrentScope->sc_start = n->on_valu;
add_scope_addr(CurrentScope);
}
}
saw_code = 1;
add_position_addr(line_file->on_mptr, n);
break;
case N_LBRAC: /* block, desc = nesting level */
if (lbrac_level && ! lbrac_required) {
open_scope((p_symbol) 0, 0);
saw_code = 0;
}
else {
/* Sun-4 ld does not relocate LBRAC
values, so we cannot use it
register p_scope sc =
get_scope_from_addr(n->on_valu);
if (!sc || sc->sc_bp_opp) {
}
else CurrentScope = sc;
*/
}
lbrac_level++;
needs_newscope = 1;
break;
#ifdef N_SCOPE
case N_SCOPE:
if (n->on_mptr && strindex(n->on_mptr, ':')) {
n = DbString(n);
}
break;
#endif
case N_RBRAC: /* end block, desc = nesting level */
if (CurrentScope != FileScope) close_scope();
needs_newscope = 1;
if (--lbrac_level == 0) needs_newscope = 0;
saw_code = 0;
break;
case N_FUN: /* function, value = address */
case N_GSYM: /* global variable */
case N_STSYM: /* data, static, value = address */
case N_LCSYM: /* bss, static, value = address */
case N_RSYM: /* register var, value = reg number */
case N_SSYM: /* struct/union el, value = offset */
case N_PSYM: /* parameter, value = offset from AP */
case N_LSYM: /* local sym, value = offset from FP */
if (needs_newscope) {
open_scope((p_symbol) 0, 0);
saw_code = 0;
needs_newscope = 0;
lbrac_required = 1;
}
if (n->on_mptr && strindex(n->on_mptr, ':')) {
n = DbString(n);
}
break;
default:
/*
if (n->on_mptr && (n->on_type&S_TYP) >= S_MIN) {
struct idf *id = str2idf(n->on_mptr, 0);
sym = new_symbol();
sym->sy_next = id->id_def;
id->id_def = sym;
sym->sy_class = SYMENTRY;
sym->sy_onam = *n;
sym->sy_idf = id;
}
*/
break;
}
}
}
close_scope();
add_position_addr((char *) 0, (struct outname *) 0);
clean_tp_tab();
rd_close();
return (h.oh_magic == O_CONVERTED);
}
}