File:  [Research Unix] / researchv9 / jtools / src / pi / frame.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 "frame.pri"
#include "core.pub"
#include "symbol.h"
#include "symtab.pub"
#include "format.pub"
#include "expr.pub"
#include "phrase.pri"
#include "parse.h"
#include "process.pub"
#include "bpts.pub"
#include "journal.pub"
SRCFILE("frame.c")

CallStk::CallStk(long s, Core *c)
{
	fpf = new FpFrame[size = s];
	core = c;
}

CallStk::~CallStk()
{
	delete fpf;
}

Frame CallStk::frame(long l)
{
	Frame f = core->frameabove(l==0 ? 0 : fpf[l-1].fp);	// cfront bug
	return f;
}

Frame::Frame(Core *c)	// cfront bug - c = 0
{
	core = c;
	level = 0;
	fp = ap = pc = nargs = regsave = regbase = 0;
	func = 0;
	pad = 0;
	phraset = 0;
}

Frame::Frame()		// cfront bug - c = 0
{
	core = 0;
	level = 0;
	fp = ap = pc = nargs = regsave = regbase = 0;
	func = 0;
	pad = 0;
	phraset = 0;
}

void Frame::pop()
{
	trace("%d.pop()", this); VOK;
	core->process()->pop();
}

SymTab *Frame::symtab()	{ OK(0); return core->symtab(); }
	
int Frame::addsymbols()
{
	trace("%d.addsymbols()", this);	OK(0);
	func = (Func*) symtab()->loctosym(U_FUNC, pc);
	return func!=0;
}

void Frame::hostclose()
{
	Phrase *p, *psib;

	trace("%d.hostclose()", this); VOK;
	if( pad ) delete pad;
	pad = 0;
	invalidate();
	for( p = phraset; p; p = psib ){
		psib = p->sib;			// new malloc
		p->expr->setspy(0);		// why?
		delete p;
	}
}

void Frame::banner()
{
	Bls t;
	trace("%d.banner()", this); VOK;
	if( pad ){
		pad->banner("%s:", text(t));
		pad->name(func ? func->text() : "?()");
	}
}

void Frame::opencallersframe()
{
	trace("%d.opencallersframe()", this); VOK;
	Frame *c = caller();
	if( c ) c->open();
}

Frame *Frame::caller()
{
	trace("%d.caller()", this); OK(0);
	return core->process()->frame(level+1);
}

void Frame::open(long svp)
{
	Menu m;

	trace("%d.open()", this); VOK;
	if( !pad ){
		pad = new Pad( (PadRcv*) this );
		if( func->stmt(pc) )
			m.last( sf("src text",func->text()), (Action)&Frame::select );
		if( core->process()->frame(level+1) )
			m.last( "caller's frame", (Action) &Frame::opencallersframe );
		m.last( "changed spies ", (Action)&Frame::changes, 1 );
		m.last( varcarte() );
		m.last( regcarte() );
		pad->menu(m);
	}
	banner();
	if( svp!=SVP ) pad->makecurrent();
}

int Frame::changes(long verbose)
{
	Phrase *p;
	long changes = 0, key = 0x40000000, spies = 0;

	trace("%d.changes()", this); OK(0);

	for( p = phraset; p; p = p->sib )
		if( p->expr->spy ){
			Bls b;
			++spies;
			if( p->changed(b) ){
				++changes;
				core->process()->journal()->insert("%s",b.text);
			}
		}
	if( verbose && pad ){
		pad->removeline(key);	
		if( spies == 0 )
			pad->insert( key, SELECTLINE, "no spies in this frame" );
		else if( changes==0 )
			pad->insert( key, SELECTLINE, "no spies changed" );
	}
	return changes;
}	

char *Frame::text(Bls &buf)
{
	Var *arg;
	Stmt *stmt = 0;

	trace("%d.text()", this);	OK("Frame::text");
	if( !func ) return sf( "pc=%d ?()", pc );
	if( core->online() )
		stmt = core->process()->bpts()->bptstmt(pc);
	if( !stmt ) stmt = func->stmt(pc);
	if( stmt )
		buf.af("%s", stmt->text(pc));
	else
		buf.af( "%s+%d", func->_text, pc - func->range.lo );
	buf.af(" %s(", func->_text);
	for( int i = 1; arg = func->argument(i); ++i ){
		if( i>1 ) buf.af(",");
		E_Sym(arg)->evaltext(this,buf);		// should use a stack expr
	}
	return buf.af( ")" );
}

void Frame::select(long svp)
{
	Stmt *stmt = 0;

	trace("%d.select(%d)", this, svp);	VOK;
	if( core->online() )
		stmt = core->process()->bpts()->bptstmt(pc);
	if( !stmt && func ) stmt = func->stmt(pc);
	if( stmt ) stmt->select(svp);
}

long Frame::saved(int r, int size) { return core->saved(this,r,size); }

long Frame::regloc(int r, int size)		/* what about r>=12 on vax ? */
{
	if( !this ) return 0;
	long loc = saved(r,size);
	if( loc ) return loc;
	if( level == 0 ) return core->regloc(r,size);
	return core->process()->frame(level-1)->regloc(r,size);
}

long Frame::locate(Var *v)
{
	trace("%d.locate(%d) %s %d", this, v, v->_text, v->range.lo);
	IF_LIVE( !v ) return 0;
	switch( (int) v->disc() ){
	case U_GLB:
	case U_STA:
	case U_FST:
	case U_FUNC:
		IF_LIVE(!v->range.lo) return 0;		/* this == 0 */
		return    v->range.lo;
	case U_ARG:
		IF_LIVE(!this || !ap) return 0;
		return ap+v->range.lo;
	case U_AUT:
		IF_LIVE(!this || !fp) return 0;
		return fp+v->range.lo;
	case U_REG:
		IF_LIVE(!this) return 0;
		if( level == 0 )	/* SAME AS CODE ABOVE! */
			return core->regloc(v->range.lo, v->type.size_of());
		return core->process()->frame(level-1)->regloc(v->range.lo, v->type.size_of());
	}
	IF_LIVE( 1 ) return 0;
}

Cslfd *Frame::peek(long loc, Cslfd* fail)
{
	trace("%d.peek(0x%X,%d)", this, loc, fail); OK(0);
	return core->peek(loc, fail);
}

char *Frame::special(char *id, long loc )
{
	trace("%d.special(%s,0x%X)", this, id, loc); OK(0);
	return core->special(id, loc);
}

char *Frame::peekstring(long loc, char *fail)
{
	trace("%d.peekstring(0x%X,%s)", this, loc, fail?fail:"0"); OK(0);
	return core->peekstring(loc, fail);
}

char *Frame::poke(long loc, long data, int bytes)
{
	trace("%d.poke(0x%X,0x%X,%d)", this, loc, data, bytes); OK(0);
	return core->poke(loc, data, bytes);
}

char *Frame::pokedbl(long loc, double data, int bytes)	/* broke float poke */
{
	trace("%d.pokedbl(0x%X,%g,%d)", this, loc, data, bytes); OK(0);
	return core->pokedbl(loc, data, bytes);
}

char *Frame::blockmove(long s, long d, long ct)
{
	trace("%d.blockmove(0x%X,0x%X,%d)", this, s, d, ct); OK("Frame::blockmove");
	return core->blockmove(s, d, ct);
}

char *Frame::help()
{
	trace("%d.help()", this);
	return "<expr> {evaluate in this scope}";
}

char *Frame::kbd(char *s)
{
	Parse y(G_EXPR,0);
	Expr *e;
	char *error;

	trace("%d.kbd(%s)", this, s);	OK("kbd");
	if( !(e = (Expr*)y.parse(s)) ){
		pad->error( "%s: %s", y.error, s );
		return 0;
	}
	if( error = makephrase(e) ) pad->error( "%s", error );
	return 0;
}

#define GAP 2
void Frame::freekey(long k)
{
	Phrase *p;
	int found = 0;

	trace("%d.freekey(%d)", this, k); VOK;
	for( p = phraset; p; p = p->sib )
		if( p->key >= k ){
			p->key += GAP;
			found = 1;
		}
	if( found ) pad->makegap(k,GAP);
}

char *Frame::makephrase(Expr *e,long k)
{
	Bls b;
	Phrase *p;
	char *error = 0;

	trace("%d.makephrase(%d,%d)", this, e, k); OK("Frame::makephrase");
	if( !e ) return "not and expr";
	if( !k ) k = UniqueKey();
	for( p = phraset; p; p = p->sib )
		if( p->key == k || p->expr == e) break;
	if( !p ) phraset = p = new Phrase(this, phraset, e, k);
	e->evaltext(this,b);
	if( e->evalerr ){
		Attrib a = ACCEPT_KBD;
		switch( e->op ){
		case O_TYPEOF: break;
		case O_INDEX:  if( e->sub2->op == O_RANGE ) break;
		default:
		   pad->insert(p->key, a, (PadRcv*)p ,e->carte(0), "%s", e->text());
		}
		return sf( "%s", b.text );
	}
	Attrib a = ACCEPT_KBD|SELECTLINE;
	if( e->spy ) a |= DONT_CUT;
	pad->insert(p->key, a, (PadRcv*)p, e->carte(this), "%s", b.text);
	return 0;

}

void Frame::pickvar(Var *v)
{
	char *error;

	trace("%d.pickvar(%d)", this, v); VOK;
	if( error = makephrase(E_Sym(v)) )		/* who owns this expr? */
		pad->error(error);
}

Index Frame::varcarte()
{
	Var   *v, *d;
	Menu  m;
	int   limit = 75, n;
	char *q = "'''''''''''''''";

	if( !func ) return ZIndex;
	BlkVars bv(func->blk(pc));
	while( (v = bv.gen()) && limit-->0 ){
		BlkVars  dup(0);
		dup = bv;
		for( n = 0; d = dup.gen(); )
			if( !strcmp(d->_text,v->_text) ) ++n;
		Bls id( "%s%0.*s\240%s", v->_text, n, q, DiscName(v->disc()));
		m.sort( id.text, (Action)&Frame::pickvar, (long) v);
	}
	return m.index();
}

//	void Frame::ambiguous(char *id, BlkVars &bl)
//	{
//		Var *v;					VOK;
//	
//		while( v = bl.gen() )
//			if( !strcmp(v->text(),id) ){
//				PadsWarn("more than one %s in %s (use the menu)",
//					id, func->text() );
//				return;
//			}
//	}

Var *Frame::idtosym(char *id)	// ever called with id==0 ?
{
	Var *v;

	trace("%d.idtosym(%s)", this, id?id:"0");	OK(0);
	if( !id ) return 0;
	if( func ) {
		BlkVars bl((Block*)func->blk()->child);		// blk(pc) ?
		while( v = bl.gen() )
			if( !strcmp(v->text(),id) ){
//				ambiguous(id, bl);
				return v;
			}
	}
	BlkVars bg(core->symtab()->blk());	// idtosym doesn't work for regs
	while( v = bg.gen() )
		if( !strcmp(v->text(),id) ) return v;
	return (Var*) symtab()->idtosym(SSet(U_GLB,U_FUNC), id);
}

Index Frame::carte()
{
	trace("%d.carte()", this);	OK(ZIndex);
	if( !func ) return ZIndex;
		Bls o("open %s frame", func->text());
		Menu m(o.text, (Action)&Frame::open);
		Stmt *stmt = func->stmt(pc);
		if( stmt ){
			Bls s("show %s", stmt->text());
			m.last(s.text, (Action)&Frame::select);
		}
		if( core->online() && core->process()->frame(0) == this )
			m.last("pop off callstack", (Action)&Frame::pop);
		return m.index();
}

Globals::Globals(Core *c):(c)
{
	trace("%d.Globals(%d)", this, c);	VOK;
}

void Globals::banner()
{
	trace("%d.banner()", this); VOK;
	if( pad ){
		pad->banner("Globals: %s", core->procpath());
		pad->name("Globals");
	}
}

void Globals::open(long)
{
	Var *g;
	Menu m;

	trace( "%d.open()", this );	VOK;
	if( !pad ){
		BlkVars bv(core->symtab()->blk());
		pad = new Pad( (PadRcv *) this );
		banner();
		while( g = bv.gen() ){
			if( g->range.lo && g->disc() == U_GLB ){
				Bls id("%s\240%s", g->_text, DiscName(g->disc()));
				m.sort(id.text, (Action)&Frame::pickvar, (long) g);
			}
		}
		m.first("changed spies", (Action)&Frame::changes, 1);
		m.last(regcarte());
		pad->menu(m);
		ix = m.index();
	}
	pad->makecurrent();
}

void Globals::addvars(Menu *m)
{
	Menu combine;
	trace("%d.addvars(%d)", this, m);	VOK;
	if( !pad ) open();
	combine.first(ix);
	combine.last(m->index());
	pad->menu(combine);
	ix = combine.index();
	pad->makecurrent();
}

Index Frame::regcarte()
{
	Var *v;
	Menu m;

	trace("%d.regcarte()", this);	OK(ZIndex);
	BlkVars bv( core->symtab()->blk() );
	while( v = bv.gen() )
		if( v->disc() == U_REG )
			m.last(v->text(), (Action)&Frame::pickvar, (long)v);
	return m.index("registers\240");
}

unix.superglobalmegacorp.com

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