ack/util/grind/symbol.c
1990-08-31 18:22:53 +00:00

238 lines
4.3 KiB
C

/* $Header$ */
/* Symbol handling */
#include <alloc.h>
#include <out.h>
#include <stb.h>
#include <assert.h>
#include "position.h"
#include "file.h"
#include "idf.h"
#include "type.h"
#include "symbol.h"
#include "scope.h"
#include "tree.h"
#include "operator.h"
p_symbol currfile;
p_symbol
NewSymbol(s, scope, class, nam)
char *s;
register p_scope scope;
struct outname *nam;
{
register p_symbol sym;
sym = new_symbol();
sym->sy_idf = str2idf(s, 0);
sym->sy_scope = scope;
sym->sy_prev_sc = scope->sc_symbs;
scope->sc_symbs = sym;
sym->sy_next = sym->sy_idf->id_def;
sym->sy_idf->id_def = sym;
sym->sy_class = class;
switch(class) {
case MODULE:
case PROC:
case FUNCTION:
case VAR:
case REGVAR:
case LOCVAR:
case VARPAR:
sym->sy_name.nm_value = nam->on_valu;
break;
default:
break;
}
return sym;
}
/* Lookup a definition for 'id' in scope 'scope' with class in the 'class'
bitset.
*/
p_symbol
Lookup(id, scope, class)
struct idf *id;
p_scope scope;
int class;
{
register p_symbol p = id ? id->id_def : 0;
while (p) {
if (p->sy_scope == scope && (p->sy_class & class)) {
return p;
}
p = p->sy_next;
}
return (p_symbol) 0;
}
/* Lookup a definition for 'id' with class in the 'class' bitset,
starting in scope 'sc' and also looking in enclosing scopes.
*/
p_symbol
Lookfromscope(id, class, sc)
register struct idf *id;
int class;
register p_scope sc;
{
if (! id) return (p_symbol) 0;
while (sc) {
register p_symbol sym = id->id_def;
while (sym) {
if (sym->sy_scope == sc && (sym->sy_class & class)) {
return sym;
}
sym = sym->sy_next;
}
sc = sc->sc_static_encl;
}
return (p_symbol) 0;
}
/* Lookup a definition for 'id' with class in the 'class' bitset,
starting in scope 'CurrentScope' and also looking in enclosing scopes.
*/
p_symbol
Lookfor(id, class)
register struct idf *id;
int class;
{
return Lookfromscope(id, class, CurrentScope);
}
extern char *strrindex();
p_symbol
add_file(s)
char *s;
{
register p_symbol sym = NewSymbol(s,
PervasiveScope,
FILESYM,
(struct outname *) 0);
register char *p;
sym->sy_file = new_file();
sym->sy_file->f_sym = sym;
p = strrindex(s, '.');
if (p) {
char c = *p;
p_symbol sym1;
*p = 0;
sym1 = NewSymbol(Salloc(s, (unsigned) strlen(s)+1),
PervasiveScope,
FILELINK,
(struct outname *) 0);
*p = c;
sym1->sy_filelink = sym;
}
return sym;
}
/* Determine if the OP_SELECT tree indicated by 'p' could lead to scope 'sc'.
*/
static int
consistent(p, sc)
p_tree p;
p_scope sc;
{
p_tree arg;
p_symbol sym;
assert(p->t_oper == OP_SELECT);
sc = sc->sc_static_encl;
if (!sc) return 0;
p = p->t_args[0];
switch(p->t_oper) {
case OP_NAME:
sym = Lookfromscope(p->t_idf, FILELINK|FILESYM|PROC|MODULE, sc);
return sym != 0;
case OP_SELECT:
arg = p->t_args[1];
sym = Lookfromscope(arg->t_idf, FILELINK|FILESYM|PROC|MODULE, sc);
if (sym == 0) return 0;
return consistent(p, sym->sy_scope);
default:
assert(0);
}
return 0; /* notreached? */
}
/* Try to find the name referred to in the node indicated by 'p', and
try to be just a little bit intelligent about it.
*/
p_symbol
identify(p, class_set)
p_tree p;
int class_set;
{
p_symbol sym = 0;
register p_symbol s;
p_tree arg;
switch(p->t_oper) {
case OP_NAME:
if (! p->t_sc) p->t_sc = CurrentScope;
sym = Lookfromscope(p->t_idf, class_set, p->t_sc);
if (sym) {
/* Found it. */
break;
}
/* We could not find it using scope p->t_sc; now we try to identify
it using class_set. If this results in only one definition, we
take this one.
*/
s = p->t_idf->id_def;
while (s) {
if (s->sy_class & class_set) {
if (sym) {
error("could not identify \"%s\"", p->t_str);
sym = 0;
break;
}
sym = s;
}
s = s->sy_next;
}
if (!sym && !s) {
error("could not find \"%s\"", p->t_str);
}
break;
case OP_SELECT:
arg = p->t_args[1];
assert(arg->t_oper == OP_NAME);
s = arg->t_idf->id_def;
sym = 0;
while (s) {
if ((s->sy_class & class_set) && consistent(p, s->sy_scope)) {
if (sym) {
error("could not identify \"%s\"", arg->t_str);
sym = 0;
}
sym = s;
}
s = s->sy_next;
}
if (!sym && !s) {
error("could not find \"%s\"", arg->t_str);
}
break;
default:
assert(0);
}
return sym;
}