File:  [Research Unix] / researchv9 / jtools / src / pi / symtab.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include "symtab.pri"
#include "dtype.pri"
#include "symbol.h"
#include "srctext.pub"
#include "phrase.pub"
#include "format.pub"
#include "core.pub"
SRCFILE("symtab.c")

int FunctionGathered, UTypeGathered, FunctionStubs, UTypeStubs;
int IdToSymCalls, StrCmpCalls;

UType *SymTab::utypelist() { return utype; }

int HASHF(register char *s)
{
	register unsigned h = 0;
	while( *s ) h = (h<<1)^*(s++);
	return h % HASH;
}

int nccdemangle(char **text, char *classname)
{
	register char *cp = *text;
	if (!classname && !strncmp(cp, "__", 2) ) {	// Locals
		cp += 2;
		if (*cp >= '0' && *cp <= '9') {
			do
				cp++;
			while (*cp >= '0' && *cp <= '9');
			*text = cp;
			return 1;
		}
	}
	cp++;
	while (*cp) {
	  if (*cp == '_' && cp[1] == '_') {
		if (cp[2] == 'F') {	// Functions
			*cp = 0;
			return 1;
		} else if (cp[2] >= '0' && cp[2] <= '9') { // Class members
			*cp = 0;
			cp += 2;
			int nchar = 0;
			int ndigits = 0;
			do {
				nchar = nchar * 10 + *cp - '0';
				ndigits++;
				cp++;
			} while (*cp >= '0' && *cp <= '9');
			if (!classname || strlen(classname) != nchar ||
			    strncmp(cp, classname, nchar)) {
				static char proto[256];
				strncpy(proto,cp,nchar);
				strcpy(proto+nchar, "::");
				strcat(proto, *text);
				strcpy(*text, proto);
				if (--ndigits) {
					cp += nchar;
					while (ndigits--)
						*--cp = 0;
				}
			}
			return 1;
		}
	  }
	  cp++;
	}
	return 0;
}

int ccdemangle(char **text, char *classname)
{
	register char *cp = *text;
	if (*cp++ != '_')
		return 0;
	if (classname) {
		int l = strlen(classname);
		if (!strncmp(cp, classname, l) && cp[l] == '_') {
			*text = &cp[l+1];
			return 1;
		}
	} else if (!strncmp(cp, "au", 2)) {
		cp += 2;
		while (*cp >= '0' && *cp <= '9')
			cp++;
		if (*cp++ == '_') {
			*text = cp;
			return 1;
		}
	}
	return 0;
}

void SymTab::uncfront(Var *v, char *classname )
{
	for( ; v; v = (Var*)v->rsib ) {
		if (!ccdemangle(&v->_text, classname))
			nccdemangle(&v->_text, classname);
	}
}

SSet::SSet(char a)
{
	v[0] = a;
	v[1] = 0;
}

SSet::SSet(char a, char b, char c, char d, char e, char f, char g )
{
	v[0] = a; v[1] = b; v[2] = c; v[3] = d;
	v[4] = e; v[5] = f; v[6] = g; v[7] = 0;
}

char *DiscName(UDisc d)
{
	switch( d ){
	case U_ARG:	return "arg";
	case U_AUT:	return "aut";
	case U_REG:	return "reg";
	case U_STA:	return "sta";
	case U_FST:	return "Sta";
	case U_GLB:	return "Glb";
	default:	return Name("U_%d",d);
	}
}

char *SymTab::stabpath()	{ OK("SymTab::stabpath"); return _core->stabpath(); }
char *SymTab::warn()	{ OK("SymTab::warn"); return _warn; }
Pad *SymTab::pad()	{ OK(0); return _pad; }

void SymTab::showutype(UType *u)		// cf Var.showutype(UTpe*)
{
	trace("%d.showutype(%d))", this, u); VOK;
	u->show(LEAVE, SELECTLINE);
}

void SymTab::banner()
{
	trace("%d.banner()", this);	VOK;
	if( !_pad ) return;
	_pad->banner("User Defined Types: %s", _core->procpath());
	_pad->name("Types %s", basename(_core->procpath()));
	_pad->options(TRUNCATE);
	Menu m;
	Action a = (Action)&SymTab::showutype;
	char *index(char*,char);
	for( UType *u = utype; u; u = (UType *)u->rsib ){
		if( u->type.isstrun() )
			m.sort(sf("%s\240",u->text()), a, (long) u);
	}
	_pad->menu(m);
}

SymTab::SymTab(Core* c,int stabfd, SymTab *i, long r)
{
	trace("%d.SymTab(%d,%d)", this, c, stabfd); VOK;
	_core = c;
	fd = stabfd;
	inherit = i;
	relocation = r;
	_blk = new Block(this, 0, 0, sf("%s.glb_blk",
					 stabpath()?stabpath():""));
}

void SymTab::opentypes()
{
	if( !_pad ){
		_pad = new Pad((PadRcv*) this);
		banner();
	}
	_pad->makecurrent();
}

SymTab::~SymTab()
{
	void abort();
	trace( "%d.~SymTab()", this ); VOK;
	if( _pad ) delete _pad;
	if( strings ) delete strings;
	Source *_rootrsib;
	for( ; _root; _root = _rootrsib){
		_rootrsib = (Source*) _root->rsib;	// new malloc
		_root->srctext->userclose();
		delete _root;
	}
	for( int i = 0; i <= TOSYM; ++i )
	  for( int j = 0; j < HASH; ++j )
	    for( Symbol *s = hashtable[i][j]; s; s = s->hashlink )
		switch( s->disc() ){
		case U_UTYPE:	delete (UType*)s; break;
		case U_GLB:
		case U_STA:	((Var*)s)->type.free();
				delete (Var*)  s;
				break;
		case U_FUNC:	delete (Func*) s; break;
		case U_STMT:	delete (Stmt*) s; break;
		default:	abort();
		}				
}

Core *SymTab::core()		{ OK(0); return _core; }
Source *SymTab::root()		{ OK(0); return _root; }
long SymTab::modtime()		{ OK(0); return modified(fd); }
Block *SymTab::blk()		{ OK(0); return _blk; }
long SymTab::magic()		{ OK(0); return _magic; }

Var *SymTab::globregs(Block *b, int r)
{
	Var *g = 0;
	int i;

	trace("%d.globregs(%d,%d)", this, b, r);	OK(0);
	for( i = 0; i<r; ++i ){
		g = new Var(this, b, g, U_REG, sf("$%s",_core->regname(i)) );
		g->range.lo = i;
		g->type.pcc = LONG;
		if( !b->var ) b->var = g;
	}
	return g;
}

char *SymTab::dump()
{
	int i, j;
	Symbol *s;

	OK("SymTab::dump");
	trace( "stabpath()=%s entries=%d", stabpath(), strings );
	trace( "strings=%d strsize=%d", strings, strsize );
	for( i = 0; i <= TOSYM; ++i )
		for( j = 0; j < HASH; ++j )
			for( s = hashtable[i][j]; s; s = s->hashlink )
				trace( "%s", s->dump() );
	return "SymTab::dump";
}

void SymTab::read()
{
	char *error;

	trace( "%d.read()", this );	VOK;
	trace( "symtab modified %d", modtime() );
	_root = 0;
	if( error = gethdr() )
		_warn = sf( "symbol table header: %s; go on", error );
	else if( !entries )
		_warn = "symbol table missing; go on";
	else if( !(_root = tree()) )
		_warn = sf( "%s; go on", _warn ? _warn : "symbol table error" );
	trace( "%s", dump() );
}

void SymTab::enter( Symbol *s )
{
	int i, h;

	trace( "%d.enter(%d) %s %d", this, s, s->dump(), HASHF(s->_text) ); VOK;
	s->hashlink = hashtable[i=s->disc()&TOSYM][h=HASHF(s->_text)];
	hashtable[i][h] = s;
}


Block *SymTab::fakeblk()		/* VAX  ap offsets */
{
	Block *b;
	int i;
	Var *a = 0;

	b = new Block( this, 0, 0, "?().arg_blk" );
	new Block( this, b, 0, "?().lcl_blk" );
	for( i = 1; i <= 3; ++i ){
		a = new Var( this, b, a, U_ARG, sf( "$arg%d", i ) );
		if( i==1 ) b->var = a;
		a->range.lo = (i+1)*4;
		a->type.pcc = INT;
	}
	return b;
}

Symbol *SymTab::idtosym(SSet set, register char *id, int lev)
{
	register int i, h;
	register Symbol *s;

	trace("%d.idtosym(%d,%s) %d", this, set.v[0], id?id:"0", HASHF(id)); OK(0);
	++IdToSymCalls;
	if( !id ) return 0;
	h = HASHF(id);
	for( i = 0; set.v[i]; ++i ){
		trace( "%s", DiscName(set.v[i]) );
		for( s = hashtable[set.v[i]&TOSYM][h]; s; s = s->hashlink ){
			trace( "%s", s->dump() );
			++StrCmpCalls;
			if( eqstr(id,s->_text) ) return s;
		}
	}
	return (lev>0 && inherit) ? inherit->idtosym(set,id,lev-1) : 0;
}

inline Symbol *LookupCache::match(SSet _set, long _loc)
{
	return !strcmp(_set.v, set.v) && loc == _loc ? sym : 0;
}

void LookupCache::save(SSet _set, long _loc, Symbol *_sym)
{
	set = _set;
	loc = _loc;
	sym = _sym;
}

int LoctosymHit, Loctosym;
Symbol *SymTab::loctosym(SSet set, register long loc, int lev)
{
	register h, best_lo = 0, s_lo;
	register Symbol *s, *best = 0;
	register i, setvi;
	Symbol   *ibest;

	trace( "%d.loctosym(%d,%d)", this, set.v[0], loc ); OK(0);
	++Loctosym;
	if( s = loctosymcache.match(set, loc) ){
		++LoctosymHit;
		return s;
	}
	for( i = 0; setvi = set.v[i]; ++i ){
		setvi &= TOSYM;
		for( h = 0; h < HASH; ++h ){
			for( s = hashtable[setvi][h]; s; s = s->hashlink ){
				s_lo = s->range.lo;
				if( loc < s_lo
				||( best && best_lo >= s_lo )
				||( s->range.hi && loc > s->range.hi ) )
					continue;
				best = s;
				best_lo = best->range.lo;
				if( loc == best_lo ) goto returnbest;
			}
		}
	}
	if( lev>0 && inherit && (ibest = inherit->loctosym(set,loc,lev-1)) ){
		if( !best || ibest->range.lo > best->range.lo ){
			best = ibest;
			goto returnbest;
		}
	}
returnbest:
	loctosymcache.save(set, loc, best);
	return best;
}

char *SymTab::symaddr(long a)
{
	trace( "%d.symaddr(%d)", this, a ); OK("SymTab::symaddr");
	return Format(F_SYMBOLIC, this).f(a);
}

Index SymTab::utypecarte(short sorety)
{
	Menu m;
	UType *u;
	Action a = (Action)&Phrase::applycast;
	char *index(char*,char);

	trace( "%d.utypecarte(%d)", this, sorety );	OK(ZIndex);
	if( !castix[sorety].null() ) return castix[sorety];
	for( u = utype; u; u = (UType *)u->rsib ){
		if( ::index(u->text(),'$') ) continue;		/* $ ? */
		if( u->type.pcc == sorety )
			m.sort( sf("%s\240",u->text()), a, (long) &u->type );
	}
	if( inherit && !inherit->utypecarte(sorety).null() ){
		Menu s;
		s.first(inherit->utypecarte(sorety));
		m.last(s.index("inherit"));
	}
	return castix[sorety] = m.index();
}

Block *SymTab::gatherfunc(Func*)		{ IF_LIVE(1) return 0; }
Var *SymTab::gatherutype(UType*)		{ IF_LIVE(1) return 0; }

void SymbolStats()
{
	void WireTap(...);

	int fpc = FunctionStubs ? FunctionGathered*100/FunctionStubs : 0;
	int upc = UTypeStubs ? UTypeGathered*100/UTypeStubs : 0;
	static int prevfpc = -1, prevupc = -1;
	if( fpc>prevfpc || upc>prevupc )
		WireTap("FG=%d FS=%d UG=%d US=%d\n", FunctionGathered,
			FunctionStubs, UTypeGathered, UTypeStubs);
	prevfpc = fpc;
	prevupc = upc;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.