File:  [Research Unix] / researchv9 / jtools / src / pi / process.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 "hostcore.h"
#include "process.pri"
#include "srcdir.h"
#include "expr.pub"
#include "master.pub"
#include "bpts.pri"
#include "memory.pub"
#include "asm.pub"
#include "symtab.pub"
#include "symbol.h"
#include "srctext.pub"
#include "format.pub"
#include "journal.pub"
SRCFILE("process.c")

void Process::pop()
{
	trace("%d.pop()", this); VOK;
	journal()->insert("pop");
	char *error = 0;
	if( core->behavs() == ACTIVE ){
		stop();
		sleep(1);
	}
	if( !error ) error = core->popcallstack();
	if( error ) insert(ERRORKEY, error);
	habeascorpus(STMT_STEPPED, changes());
}

char *Process::kbd(char *s)
{
	trace("%d.kbd(%s)", this, s); OK("Process::kbd");
	journal()->insert("kbd: %s", s);
	char p[256], c[256], e[256];
	long l;
	if( 3 == sscanf(s, "bpt %[^:]:%d %s", p, &l, e) ){
		BptReq r(p, l, e);
		return r.set(this);
	}
	if( 2 == sscanf(s, " bpt %[^:]:%d", p, &l, e) ){
		BptReq r(p, l);
		return r.set(this);
	}
	if( 3 == sscanf(s, "bpt %[^{}]%[{}] %s", p, c, e) ){
		BptReq r(p, c, e);
		return r.set(this);
	}
	if( 2 == sscanf(s, "bpt %[^{}]%[{}]", p, c) ){
		BptReq r(p, c);
		return r.set(this);
	}
	return help();
}

char *Process::help()
{
	return "<ugly-keyboard-language> { cat /usr/jerq/lib/pi.help }";
}

Process::Process(Process *sib, char *p, char *s, char *c)
{
	trace( "%d.Process(%d,%s,%s,%s)",this,sib,p,s,c); VOK;
	sibling = sib;
	procpath = p ? sf("%s",p) : 0;
	stabpath = s ? sf("%s",s) : 0;
	comment  = c ? sf("%s",c) : 0;
	stoprequest = 0;
	cycles = 0;
	_prefix = 0;
	srcdir = 0;
	parent = 0;
	isdead = 0;
	padlines = 0;
}

void Process::currentstmt()
{
	trace( "%d.currentstmt()", this ); VOK;

	if( !callstk ){
		insert(ERRORKEY, "cannot show source (there is no callstack yet)");
		return;
	}
	for( long l = 0; l < callstk->size; ++l ){
		Frame *f = frame(l);
		if( !f->func ) continue;
		Stmt *stmt = f->func->stmt(f->pc);
/*		Stmt *stmt = (Stmt*) core->symtab()->loctosym(U_STMT, f->pc); */
		if( stmt ){
			stmt->select();
			return;
		}
	}
	insert(ERRORKEY, "cannot show source for any frame on callstack");
	pad->makecurrent();
}

Index Process::carte() { return ZIndex; }

void Process::closeframes()
{
	trace( "%d.closeframes()", this );	VOK;
	if( callstk ) {
		for( long l = callstk->size-1; l>=0; --l ){
			if( callstk->fpf[l].frame ){
			 	callstk->fpf[l].frame->hostclose();
				delete callstk->fpf[l].frame;
				callstk->fpf[l].frame = 0;
			}
		}
		delete callstk;
		callstk = 0;
	}
}

void Process::userclose()
{
	trace( "%d.userclose()", this );	VOK;
	if( _journal ){
		_journal->hostclose();
		delete _journal;
		_journal = 0;
	}
	if( _bpts ){
		_bpts->hostclose();
		delete _bpts;
		_bpts = 0;
	}
	if( srcdir ){
		srcdir->hostclose();
		delete srcdir;
		srcdir = 0;
	}
	if( memory ){
		memory->userclose();
		delete memory;
		memory = 0;
	}
	if( _asm ){
		_asm->userclose();
		delete _asm;
		_asm = 0;
	}
	closeframes();
	if( core ){
		core->close();
		delete core;
		core = 0;
	}
	if( globals ){
		globals->hostclose();
		delete globals;
		globals = 0;
	}
	if( pad ){
		delete pad;
		pad = 0;
	}
	isdead = 1;
	master->insert(this);
	master->makeproc(procpath, stabpath, comment);
}

Bpts *Process::bpts() { return _bpts; }

SymTab	*Process::symtab() { return core->symtab(); }

void Process::banner()
{
	trace( "%d.banner()", this );	VOK;
	if( pad ){
		pad->name(procpath);				/* basename ? */
		pad->banner("Process: %s", procpath);
	}
}

void Process::openpad()
{
	trace("%d.openpad(%d)", this);	VOK;
	if( !pad ){
		pad = new Pad( (PadRcv*) this );
		pad->options(TRUNCATE|NO_TILDE);
		banner();
		pad->lines(padlines = ERRORKEY);
		pad->clear();			/* from a previous attempt! */
		pad->makecurrent();
	}
	pad->makecurrent();
}

void Process::openglobals(Menu *m)
{
	trace("%d.openglobals()", this);	VOK;
	if( !globals ) globals = new Globals(core);
	globals->open();
	if( m) globals->addvars(m);
}

void Process::opentypes()
{
	trace("%d.opentypes()", this);	VOK;
	core->symtab()->opentypes();
}

void Process::srcfiles()
{
	trace( "%d.srcfiles()", this );	VOK;
	if( !srcdir ) srcdir = new SrcDir( this );
	srcdir->open();
}

void Process::merge()
{
	trace( "%d.merge()",this,); VOK;
	CallStk *old = callstk;
	callstk = core->callstack();
	if( !callstk ){
		if (old) {
			callstk = old;
			closeframes();
		}
		insert(ERRORKEY, "cannot obtain callstack");
		return;
	}
	if( !old ) return;
	long c = callstk->size-1, i;
	for( long o = old->size-1; o>=0; --o ){
		Frame *of;
		if( of = old->fpf[o].frame ){
			for( i = c; i>=0; --i )
				if( callstk->fpf[i].func == old->fpf[o].func )
					break;
			if( i >= 0 ){
				Frame nf = callstk->frame(i);
				of->ap = nf.ap;
				of->fp = nf.fp;
				of->pc = nf.pc;
				of->regbase = nf.regbase;
				of->regsave = nf.regsave;
				if( of->pad ){
					of->banner();
					of->changes();
				}
				callstk->fpf[i].frame = of;
				of->level = i;
				c = i-1;
			} else {
				of->hostclose();
				delete of;
			}
		}
	}
	delete old;
}

void Process::mergeback(long)	/* arg never used - should go away */
{
	trace( "%d.mergeback()", this );	VOK;
	
	if( core->behavs() == ACTIVE ){
		stop();
		if( core->behavs() == ACTIVE ){
			insert(ERRORKEY, "process not stopped");
			return;
		}
	}
	merge();
	pad->lines(padlines = ERRORKEY);
	if( callstk ) pad->lines(padlines = callstk->size+ERRORKEY);
	linereq(BEHAVSKEY);		// it gets linereq'd?
}

Frame *Process::frame(long l)
{
	trace("%d.frame(%d)", this, l); OK(0);
	if( !callstk || l < 0 || l >= callstk->size ) return 0;
	Frame *f = callstk->fpf[l].frame;
	if( f ) return f;
	f = callstk->fpf[l].frame = new Frame(core);	// gets its own oid
	PadRcv save = *(PadRcv*)f;			// save PadRcv part
	*f = callstk->frame(l);
	*(PadRcv*)f = save;				// restore PadRcv part
	f->func = callstk->fpf[l].func;
	f->level = l;
	return f;
}

void Process::linereq(long l, Attrib a)
{
	trace("%d.linereq(%d,%x)", this, l, a); VOK;
	if( l <= ERRORKEY ){
		pad->insert(l, a, "%s", bls[l].text);
		journal()->insert("%s", bls[l].text);
		return;
	}
	if( padlines && l>padlines ) return;	// too late
	Frame *f = frame(l-ERRORKEY-1);
	Bls t;
	pad->insert(l, a|DONT_CUT, (PadRcv*)f, f->carte(), "%s", f->text(t));
	if( l == ERRORKEY+1 )
		journal()->insert("%s", t.text);
}

void Process::insert(long l, PRINTF_ARGS)
{
	trace("%d.insert(%d)", this, l); VOK;
	if( l == ERRORKEY ){			// ERROR doesn't change much
		Bls cmp;
		cmp.af(PRINTF_COPY);
		if( !strcmp(cmp.text, bls[ERRORKEY].text) )
			return;
	}
	if( l > ERRORKEY ) return;
	bls[l].clear();
	bls[l].af(PRINTF_COPY);
	pad->insert(l, DONT_CUT, "%s", bls[l].text);
}

void Process::openframe(long pc, char *k)
{
	trace( "%d.openframe(%d)", this, pc );	VOK;

	Func *func = (Func*) symtab()->loctosym(U_FUNC, pc);
	if( !func ){
		pad->insert(ERRORKEY, "cannot find function");
		return;
	}
	if( !callstk ){
		pad->insert(ERRORKEY, "there is no callstack yet");
		return;
	}
	long l;
	Frame *f = 0;
	for( l = 0; l < callstk->size; ++l )
		if( callstk->fpf[l].func == func ){
			f = frame(l);
			f->open();
			break;
		}
	if( !f ){
		mergeback(2);
		insert(ERRORKEY, "%s is not on callstack", func->text());
		pad->makecurrent();
		return;
	}
	for( ++l; l < callstk->size; ++l )
		if( callstk->fpf[l].func == func ){
			f->pad->insert(1, "called recursively - deepest instance");
			break;
		}
	if( f && k ) f->kbd(k);
}

void Process::openmemory(long a)
{
	trace( "%d.openmemory(%d)", this, a );	VOK;
	if( !memory ) memory = new Memory(core);
	memory->open(a);
}

void Process::openasm(long a)
{
	trace("%d.openasm()", this);	VOK;
	if( !_asm ) _asm = core->newAsm();
	if( a!= -1 ) _asm->open(a);
}

void Process::openjournal()
{
	trace("%d.openjournal()", this);	VOK;
	if( !_journal)
		_journal = new Journal(basename(core->procpath()));
	journal()->open();
}

Journal *Process::journal()
{
	trace("%d.journal()", this);	OK(0);
	return _journal;
}

void Process::openbpts()
{
	trace( "%d.openbpts()", this );	VOK;
	bpts()->pad->makecurrent();
}

void Process::stop()
{
	trace( "%d.stop()", this );		VOK;

	IF_LIVE( !core->online() ) return;
	journal()->insert("stop");
	insert(ERRORKEY, 0);
	switch( core->behavs() ){
	case ACTIVE:
		insert(ERRORKEY, core->stop());
		sleep(1);
		cycle();		/* will ignore next cycle from term */
		return;
	default:
		stoprequest = 1;
		habeascorpus(core->behavs(),changes());
	}
}

void Process::stmtstep(long i)
{
	char *error = 0;
	class Stmt *stmt;
	long changed = 0;

	trace("%d.stmtstep(%d)", this, i);		VOK;
	journal()->insert("step %d stmts", i);
	insert(ERRORKEY, 0);
	stoprequest = 0;
	for( ; i>0 && !error && changed==0; --i ){
		if( i>1 ) insert(BEHAVSKEY, "step %d statements", i);
		if( !(stmt = (Stmt*) symtab()->loctosym(U_STMT, core->pc())) )
			error = "cannot locate start stmt for step";
		else
			error = core->step(stmt->range.lo, stmt->range.hi);
		if( !error ) changed = changes();
	}
	insert(ERRORKEY, error);
	if( error ){
		docycle();
		return;
	}
	habeascorpus(STMT_STEPPED, changed);
}

void Process::stepinto()
{
	char *error = 0;
	class Stmt *stmt;
	long time(long*), t0 = time(0), timeout = 10, changed = 0;

	trace( "%d.stepinto()", this );		VOK;
	journal()->insert("step into function");
	insert(ERRORKEY, 0);
	stoprequest = 0;
	if( !(stmt = (Stmt*) symtab()->loctosym(U_STMT, core->pc())) )
		error = "cannot locate start stmt for step into";
	while( !error && changed==0 ){
		if( core->pc() < stmt->range.lo ) break;
		if( core->pc() >= stmt->range.hi ) break;
		error = core->step();
		if( !error && time(0) > t0+timeout )
			error = sf( "step into timeout (%d secs)", timeout );
		if( !error )
			changed = changes();
	}
	if( !error )
		error = core->stepprolog();
	insert(ERRORKEY, error);
	if( error ){
		docycle();
		return;
	}
	habeascorpus(STMT_STEPPED, changed);
}

void Process::instrstep(long i)
{
	char *error = 0;
	long changed = 0;

	trace("%d.instrstep(%d)", this, i);		VOK;
	journal()->insert("step %d instructions", i);
	stoprequest = 0;
	insert(ERRORKEY, 0);
	while( i>0 && !error && changed==0 ){
		insert(BEHAVSKEY, "step %d instructions", i--);
		error = core->step();
		if( !error ) changed = changes();
	}
	insert(ERRORKEY, error);
	if( error ){
		docycle();
		return;
	}
	habeascorpus(INST_STEPPED,changed);
	openasm( core->pc() );
}

void Process::stepover(long lo, long hi)
{
	trace( "%d.stepover()", this );		VOK;
	journal()->insert("step over call");
	stoprequest = 0;
	char *error = core->step(lo, hi);
	insert(ERRORKEY, error);
	if( error ){
		docycle();
		return;
	}
	habeascorpus(INST_STEPPED, changes());
	openasm(core->pc());
}

void Process::go()
{
	Behavs b = core->behavs();
	char *error = 0;

	trace( "%d.go() %s", this, BehavsName(b) );	VOK;
	journal()->insert("run");
	stoprequest = 0;
	switch( b ){
	case ACTIVE:
	case ERRORED:
		habeascorpus(b,0);
		break;
	case BREAKED:
		if( !error ) error = core->step();
	case INST_STEPPED:
	case STMT_STEPPED:
	case PENDING:
	case HALTED:
		if( !error ) _bpts->lay();
		if( !error ) error = core->run();
	}
	insert(ERRORKEY, error);
	docycle();
}

void Process::cycle()
{
	trace( "%d.cycle() %d", this );		VOK;
	if( cycles <= 0 ) return;
	--cycles;
	docycle();
}

void Process::docycle()
{
	Behavs b;
	
	trace( "%d.docycle() %d", this );		VOK;
	b = core->behavs();
	switch( b ){
	case ACTIVE:
		pad->alarm(1);
		++cycles;
		break;
	case HALTED:
	case PENDING:
	case BREAKED:
		if (core->online()) _bpts->lift();
		break;
	default:
		break;
	}
	habeascorpus(b, b!=ERRORED ? changes() : 0);
}

void Process::habeascorpus(Behavs b, long c)
{
	char *error;
	Bls *t = &bls[BEHAVSKEY];
	Frame *f;

	trace( "%d.habeascorpus(%d, c)", this, b, c );	VOK;
	t->clear();
	if( c > 0 ) t->af( "%d %s changed ", c, c==1 ? "spy" : "spies" );
	t->af( "%s ", BehavsName(b) );
	switch( b ){
		case HALTED: break;	// shut up cfront
		case BREAKED: {
			class Stmt *stmt = bpts()->bptstmt(core->pc());
			if( !stmt || stoprequest ) break;
			Expr *e = stmt->condition;
			if( !e || e==Q_BPT ) break;
			delete core->callstack();	// term needs refreshed
			Frame cf = core->frameabove(0);
			cf.addsymbols();
			stmt->condtext->clear();
			stmt->condtext->af("[%d] ", ++stmt->hits);
			e->evaltext(&cf, *stmt->condtext);
			Bls j;
			journal()->insert("%s", stmt->journal(j));
			if( e->val.lng || c>0 )
				break;
			if( !e->evalerr ){
				pad->alarm();
				++cycles;
			}
			stmt->select();
			if( e->evalerr ){
				insert(ERRORKEY, "%s", stmt->condtext->text);
				break;
			}
			error = core->step();
			if( !error ) _bpts->lay();
			if( !error ) error = core->run();
			insert(ERRORKEY, error);
			return;
		}
		case ERRORED:
			t->af( core->problem() );
			break;
		case PENDING:
			t->af(core->eventname());
			break;
		case ACTIVE:
			t->af( "%s ", core->resources() );	// fall thru
		case INST_STEPPED:
		case STMT_STEPPED:
			long pc = core->pc();
			if( pc ){
				if( *symtab()->symaddr(pc) )
					t->af( "pc=%s", symtab()->symaddr(pc) );
				else
					t->af( "pc=%d", pc );
			}
			break;
	}
	switch( b ){
		case ACTIVE:
			pad->lines(padlines = ERRORKEY);
		case ERRORED:
			linereq(BEHAVSKEY);
			break;
		case HALTED:
		case BREAKED:
		case INST_STEPPED:
		case STMT_STEPPED:
		case PENDING:
			mergeback(2);
			if( globals ) globals->changes();
			if( b!=INST_STEPPED && (f = frame(0)) )
				f->select(b != STMT_STEPPED ? SVP : 0);
	}
}

int Process::changes()
{
	int changed = 0;
	Frame *f;

	trace( "%d.changes()", this );		OK(0);
	if( callstk )
		for( long l = 0; l < callstk->size; ++l )
			if( f = callstk->fpf[l].frame )
				changed += f->changes();
	if( globals ) changed += globals->changes();
	if( memory ) changed += memory->changes();
	return changed;
}

char *Process::prefix(char *p)
{
	trace( "%d.prefix(%s) %s", this, p, _prefix );	OK("Process::prefix");
	if( *p=='/' && _prefix && strncmp(_prefix, "/n/",  3) )
		return p;
	if( p && _prefix )
		return sf( "%s/%s", _prefix, *p=='/' ? p+1 : p );
	return p;
}

void Process::slavedriver(Process *sd)
{
	trace("%d.slavedriver(%d)", this, sd);		VOK;
	if( sd == this ){
		pad->insert(ERRORKEY, "slave must be different process");
		return;
	}
	pad->insert(ERRORKEY, "slave of %s", sd->procpath);
	sd->pad->insert(ERRORKEY, "master of %s", procpath);
	sd->_slave = this;
	core->slavedriver(sd->core);
}

Process *Process::slave()
{
	trace("%d.slave()", this); OK(0);
	return _slave;
}

unix.superglobalmegacorp.com

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