xref: /csrg-svn/old/dbx/runtime.vax.c (revision 15784)
112546Scsvaf 
29678Slinton /* Copyright (c) 1982 Regents of the University of California */
39678Slinton 
4*15784Ssam static char sccsid[] = "@(#)runtime.vax.c 1.10 12/30/83";
59678Slinton 
69678Slinton /*
79678Slinton  * Runtime organization dependent routines, mostly dealing with
89678Slinton  * activation records.
99678Slinton  */
109678Slinton 
119678Slinton #include "defs.h"
129678Slinton #include "runtime.h"
139678Slinton #include "process.h"
149678Slinton #include "machine.h"
159678Slinton #include "events.h"
169678Slinton #include "mappings.h"
179678Slinton #include "symbols.h"
189678Slinton #include "tree.h"
199678Slinton #include "eval.h"
209678Slinton #include "operators.h"
219678Slinton #include "object.h"
2212546Scsvaf #include <sys/param.h>
239678Slinton 
249678Slinton #ifndef public
259678Slinton typedef struct Frame *Frame;
269678Slinton 
279678Slinton #include "machine.h"
289678Slinton #endif
299678Slinton 
309678Slinton #define NSAVEREG 12
319678Slinton 
329678Slinton struct Frame {
339678Slinton     Integer condition_handler;
349678Slinton     Integer mask;
359678Slinton     Address save_ap;		/* argument pointer */
369678Slinton     Address save_fp;		/* frame pointer */
379678Slinton     Address save_pc;		/* program counter */
389678Slinton     Word save_reg[NSAVEREG];	/* not necessarily there */
399678Slinton };
409678Slinton 
419678Slinton private Boolean walkingstack = false;
429678Slinton 
439678Slinton /*
449678Slinton  * Set a frame to the current activation record.
459678Slinton  */
469678Slinton 
479678Slinton private getcurframe(frp)
489678Slinton register Frame frp;
499678Slinton {
509678Slinton     register int i;
519678Slinton 
529678Slinton     checkref(frp);
539678Slinton     frp->mask = reg(NREG);
549678Slinton     frp->save_ap = reg(ARGP);
559678Slinton     frp->save_fp = reg(FRP);
5612051Slinton     frp->save_pc = reg(PROGCTR) + 1;
579678Slinton     for (i = 0; i < NSAVEREG; i++) {
589678Slinton 	frp->save_reg[i] = reg(i);
599678Slinton     }
609678Slinton }
619678Slinton 
629678Slinton /*
639678Slinton  * Return a pointer to the next activation record up the stack.
649678Slinton  * Return nil if there is none.
659678Slinton  * Writes over space pointed to by given argument.
669678Slinton  */
679678Slinton 
689678Slinton #define bis(b, n) ((b & (1 << (n))) != 0)
699678Slinton 
709678Slinton private Frame nextframe(frp)
719678Slinton Frame frp;
729678Slinton {
739678Slinton     register Frame newfrp;
749678Slinton     struct Frame frame;
759678Slinton     register Integer i, j, mask;
7612546Scsvaf     Address prev_frame, callpc;
7713937Slinton     static Integer ntramp = 0;
789678Slinton 
799678Slinton     newfrp = frp;
8012546Scsvaf     prev_frame = frp->save_fp;
8112546Scsvaf 
8213937Slinton /*
8313937Slinton  *  The check for interrupt generated frames is taken from adb with only
8413937Slinton  *  partial understanding.  If you're in "sub" and on a sigxxx "sigsub"
8513937Slinton  *  gets control, then the stack does NOT look like <main, sub, sigsub>.
8612546Scsvaf  *
8712546Scsvaf  *  As best I can make out it looks like:
8812546Scsvaf  *
8913937Slinton  *     <main, (machine check exception block + sub), sysframe, sigsub>.
9013937Slinton  *
9113937Slinton  *  When the signal occurs an exception block and a frame for the routine
9213937Slinton  *  in which it occured are pushed on the user stack.  Then another frame
9313937Slinton  *  is pushed corresponding to a call from the kernel to sigsub.
9413937Slinton  *
9512546Scsvaf  *  The addr in sub at which the exception occured is not in sub.save_pc
9613937Slinton  *  but in the machine check exception block.  It is at the magic address
9714620Ssam  *  fp + 84.
9812546Scsvaf  *
9912546Scsvaf  *  The current approach ignores the sys_frame (what adb reports as sigtramp)
10013937Slinton  *  and takes the pc for sub from the exception block.  This allows the
10113937Slinton  *  "where" command to report <main, sub, sigsub>, which seems reasonable.
10212546Scsvaf  */
10312546Scsvaf 
10413937Slinton nextf:
10513937Slinton     dread(&frame, prev_frame, sizeof(struct Frame));
10613937Slinton     if (ntramp == 1) {
10714620Ssam 	dread(&callpc, prev_frame + 84, sizeof(callpc));
10813937Slinton     } else {
10913937Slinton 	callpc = frame.save_pc;
11013937Slinton     }
1119678Slinton     if (frame.save_fp == nil) {
1129678Slinton 	newfrp = nil;
11313937Slinton     } else if (callpc > 0x80000000 - 0x200 * UPAGES ) {
11412546Scsvaf 	 ntramp++;
11512546Scsvaf 	 prev_frame = frame.save_fp;
11612546Scsvaf 	 goto nextf;
11713937Slinton     } else {
11812546Scsvaf 	frame.save_pc = callpc;
11913937Slinton         ntramp = 0;
1209678Slinton 	mask = ((frame.mask >> 16) & 0x0fff);
1219678Slinton 	j = 0;
1229678Slinton 	for (i = 0; i < NSAVEREG; i++) {
1239678Slinton 	    if (bis(mask, i)) {
1249678Slinton 		newfrp->save_reg[i] = frame.save_reg[j];
1259678Slinton 		++j;
1269678Slinton 	    }
1279678Slinton 	}
1289678Slinton 	newfrp->condition_handler = frame.condition_handler;
1299678Slinton 	newfrp->mask = mask;
1309678Slinton 	newfrp->save_ap = frame.save_ap;
1319678Slinton 	newfrp->save_fp = frame.save_fp;
1329678Slinton 	newfrp->save_pc = frame.save_pc;
1339678Slinton     }
1349678Slinton     return newfrp;
1359678Slinton }
1369678Slinton 
1379678Slinton /*
1389678Slinton  * Return the frame associated with the given function.
1399678Slinton  * If the function is nil, return the most recently activated frame.
1409678Slinton  *
1419678Slinton  * Static allocation for the frame.
1429678Slinton  */
1439678Slinton 
1449678Slinton public Frame findframe(f)
1459678Slinton Symbol f;
1469678Slinton {
1479678Slinton     register Frame frp;
1489678Slinton     static struct Frame frame;
14911866Slinton     Symbol p;
1509678Slinton 
1519678Slinton     frp = &frame;
1529678Slinton     getcurframe(frp);
153*15784Ssam     if (f == nil)
154*15784Ssam 	return (frp);
155*15784Ssam     /*
156*15784Ssam      * Starting at the current stack frame,
157*15784Ssam      * walk backwards looking for a symbol
158*15784Ssam      * match.  Beware of local blocks which
159*15784Ssam      * have a back pointer but no stack frame.
160*15784Ssam      */
161*15784Ssam     p = whatblock(frp->save_pc);
162*15784Ssam     while (p != f) {
163*15784Ssam 	if (p == program) {
164*15784Ssam 	    frp = nil;
165*15784Ssam 	    break;
166*15784Ssam 	}
167*15784Ssam 	if (isinline(p)) {
168*15784Ssam 	    p = container(p);
169*15784Ssam 	    continue;
170*15784Ssam 	}
171*15784Ssam 	frp = nextframe(frp);
172*15784Ssam 	if (frp == nil)
173*15784Ssam 	   break;
174*15784Ssam 	p = whatblock(frp->save_pc);
1759678Slinton     }
176*15784Ssam     return (frp);
1779678Slinton }
1789678Slinton 
1799678Slinton /*
1809678Slinton  * Find the return address of the current procedure/function.
1819678Slinton  */
1829678Slinton 
1839678Slinton public Address return_addr()
1849678Slinton {
1859678Slinton     Frame frp;
1869678Slinton     Address addr;
1879678Slinton     struct Frame frame;
1889678Slinton 
1899678Slinton     frp = &frame;
1909678Slinton     getcurframe(frp);
1919678Slinton     frp = nextframe(frp);
1929678Slinton     if (frp == nil) {
1939678Slinton 	addr = 0;
1949678Slinton     } else {
1959678Slinton 	addr = frp->save_pc;
1969678Slinton     }
1979678Slinton     return addr;
1989678Slinton }
1999678Slinton 
2009678Slinton /*
2019678Slinton  * Push the value associated with the current function.
2029678Slinton  */
2039678Slinton 
2049678Slinton public pushretval(len, isindirect)
2059678Slinton Integer len;
2069678Slinton Boolean isindirect;
2079678Slinton {
2089678Slinton     Word r0;
2099678Slinton 
2109678Slinton     r0 = reg(0);
2119678Slinton     if (isindirect) {
2129678Slinton 	rpush((Address) r0, len);
2139678Slinton     } else {
2149678Slinton 	switch (len) {
2159678Slinton 	    case sizeof(char):
2169678Slinton 		push(char, r0);
2179678Slinton 		break;
2189678Slinton 
2199678Slinton 	    case sizeof(short):
2209678Slinton 		push(short, r0);
2219678Slinton 		break;
2229678Slinton 
2239678Slinton 	    default:
2249678Slinton 		if (len == sizeof(Word)) {
2259678Slinton 		    push(Word, r0);
2269678Slinton 		} else if (len == 2*sizeof(Word)) {
2279678Slinton 		    push(Word, r0);
2289678Slinton 		    push(Word, reg(1));
2299678Slinton 		} else {
2309678Slinton 		    panic("not indirect in pushretval?");
2319678Slinton 		}
2329678Slinton 		break;
2339678Slinton 	}
2349678Slinton     }
2359678Slinton }
2369678Slinton 
2379678Slinton /*
2389678Slinton  * Return the base address for locals in the given frame.
2399678Slinton  */
2409678Slinton 
2419678Slinton public Address locals_base(frp)
2429678Slinton register Frame frp;
2439678Slinton {
2449678Slinton     return (frp == nil) ? reg(FRP) : frp->save_fp;
2459678Slinton }
2469678Slinton 
2479678Slinton /*
2489678Slinton  * Return the base address for arguments in the given frame.
2499678Slinton  */
2509678Slinton 
2519678Slinton public Address args_base(frp)
2529678Slinton register Frame frp;
2539678Slinton {
2549678Slinton     return (frp == nil) ? reg(ARGP) : frp->save_ap;
2559678Slinton }
2569678Slinton 
2579678Slinton /*
2589678Slinton  * Return saved register n from the given frame.
2599678Slinton  */
2609678Slinton 
2619678Slinton public Word savereg(n, frp)
2629678Slinton register Integer n;
2639678Slinton register Frame frp;
2649678Slinton {
2659678Slinton     register Word w;
2669678Slinton 
2679678Slinton     if (frp == nil) {
2689678Slinton 	w = reg(n);
2699678Slinton     } else {
2709678Slinton 	switch (n) {
2719678Slinton 	    case ARGP:
2729678Slinton 		w = frp->save_ap;
2739678Slinton 		break;
2749678Slinton 
2759678Slinton 	    case FRP:
2769678Slinton 		w = frp->save_fp;
2779678Slinton 		break;
2789678Slinton 
2799678Slinton 	    case STKP:
2809678Slinton 		w = reg(STKP);
2819678Slinton 		break;
2829678Slinton 
2839678Slinton 	    case PROGCTR:
2849678Slinton 		w = frp->save_pc;
2859678Slinton 		break;
2869678Slinton 
2879678Slinton 	    default:
2889678Slinton 		assert(n >= 0 and n < NSAVEREG);
2899678Slinton 		w = frp->save_reg[n];
2909678Slinton 		break;
2919678Slinton 	}
2929678Slinton     }
2939678Slinton     return w;
2949678Slinton }
2959678Slinton 
2969678Slinton /*
2979678Slinton  * Return the nth argument to the current procedure.
2989678Slinton  */
2999678Slinton 
3009678Slinton public Word argn(n, frp)
3019678Slinton Integer n;
3029678Slinton Frame frp;
3039678Slinton {
3049678Slinton     Word w;
3059678Slinton 
3069678Slinton     dread(&w, args_base(frp) + (n * sizeof(Word)), sizeof(w));
3079678Slinton     return w;
3089678Slinton }
3099678Slinton 
3109678Slinton /*
3119678Slinton  * Calculate the entry address for a procedure or function parameter,
3129678Slinton  * given the address of the descriptor.
3139678Slinton  */
3149678Slinton 
3159678Slinton public Address fparamaddr(a)
3169678Slinton Address a;
3179678Slinton {
3189678Slinton     Address r;
3199678Slinton 
3209678Slinton     dread(&r, a, sizeof(r));
3219678Slinton     return r;
3229678Slinton }
3239678Slinton 
3249678Slinton /*
3259678Slinton  * Print a list of currently active blocks starting with most recent.
3269678Slinton  */
3279678Slinton 
3289678Slinton public wherecmd()
3299678Slinton {
3309678Slinton     walkstack(false);
3319678Slinton }
3329678Slinton 
3339678Slinton /*
3349678Slinton  * Dump the world to the given file.
3359678Slinton  * Like "where", but variables are dumped also.
3369678Slinton  */
3379678Slinton 
3389678Slinton public dump()
3399678Slinton {
3409678Slinton     walkstack(true);
3419678Slinton }
3429678Slinton 
3439678Slinton /*
3449678Slinton  * Walk the stack of active procedures printing information
3459678Slinton  * about each active procedure.
3469678Slinton  */
3479678Slinton 
3489678Slinton private walkstack(dumpvariables)
3499678Slinton Boolean dumpvariables;
3509678Slinton {
3519678Slinton     register Frame frp;
3529678Slinton     register Symbol f;
3539678Slinton     register Boolean save;
3549678Slinton     register Lineno line;
3559678Slinton     struct Frame frame;
3569678Slinton 
3579678Slinton     if (notstarted(process)) {
3589678Slinton 	error("program is not active");
3599678Slinton     } else {
3609678Slinton 	save = walkingstack;
3619678Slinton 	walkingstack = true;
3629678Slinton 	frp = &frame;
3639678Slinton 	getcurframe(frp);
3649678Slinton 	f = whatblock(frp->save_pc);
3659678Slinton 	do {
3669678Slinton 	    printf("%s", symname(f));
36714442Slinton 	    if (not isinline(f)) {
36814442Slinton 		printparams(f, frp);
36914442Slinton 	    }
3709841Slinton 	    line = srcline(frp->save_pc - 1);
3719678Slinton 	    if (line != 0) {
3729678Slinton 		printf(", line %d", line);
3739841Slinton 		printf(" in \"%s\"\n", srcfilename(frp->save_pc - 1));
3749678Slinton 	    } else {
3759678Slinton 		printf(" at 0x%x\n", frp->save_pc);
3769678Slinton 	    }
3779678Slinton 	    if (dumpvariables) {
3789678Slinton 		dumpvars(f, frp);
3799678Slinton 		putchar('\n');
3809678Slinton 	    }
38114442Slinton 	    if (isinline(f)) {
38214442Slinton 		f = container(f);
38314442Slinton 	    } else {
38414442Slinton 		frp = nextframe(frp);
38514442Slinton 		if (frp != nil) {
38614442Slinton 		    f = whatblock(frp->save_pc);
38714442Slinton 		}
3889678Slinton 	    }
38911866Slinton 	} while (frp != nil and f != program);
3909678Slinton 	if (dumpvariables) {
3919678Slinton 	    printf("in \"%s\":\n", symname(program));
3929678Slinton 	    dumpvars(program, nil);
3939678Slinton 	    putchar('\n');
3949678Slinton 	}
3959678Slinton 	walkingstack = save;
3969678Slinton     }
3979678Slinton }
3989678Slinton 
3999678Slinton /*
4009678Slinton  * Find the entry point of a procedure or function.
4019678Slinton  */
4029678Slinton 
4039678Slinton public findbeginning(f)
4049678Slinton Symbol f;
4059678Slinton {
4069678Slinton     f->symvalue.funcv.beginaddr += 2;
4079678Slinton }
4089678Slinton 
4099678Slinton /*
4109678Slinton  * Return the address corresponding to the first line in a function.
4119678Slinton  */
4129678Slinton 
4139678Slinton public Address firstline(f)
4149678Slinton Symbol f;
4159678Slinton {
4169678Slinton     Address addr;
4179678Slinton 
4189678Slinton     addr = codeloc(f);
4199678Slinton     while (linelookup(addr) == 0 and addr < objsize) {
4209678Slinton 	++addr;
4219678Slinton     }
4229678Slinton     if (addr == objsize) {
4239678Slinton 	addr = -1;
4249678Slinton     }
4259678Slinton     return addr;
4269678Slinton }
4279678Slinton 
4289678Slinton /*
4299678Slinton  * Catcher drops strike three ...
4309678Slinton  */
4319678Slinton 
4329678Slinton public runtofirst()
4339678Slinton {
4349678Slinton     Address addr;
4359678Slinton 
4369678Slinton     addr = pc;
4379678Slinton     while (linelookup(addr) == 0 and addr < objsize) {
4389678Slinton 	++addr;
4399678Slinton     }
4409678Slinton     if (addr < objsize) {
4419678Slinton 	stepto(addr);
4429678Slinton     }
4439678Slinton }
4449678Slinton 
4459678Slinton /*
4469678Slinton  * Return the address corresponding to the end of the program.
4479678Slinton  *
4489678Slinton  * We look for the entry to "exit".
4499678Slinton  */
4509678Slinton 
4519678Slinton public Address lastaddr()
4529678Slinton {
4539678Slinton     register Symbol s;
4549678Slinton 
4559678Slinton     s = lookup(identname("exit", true));
4569678Slinton     if (s == nil) {
4579678Slinton 	panic("can't find exit");
4589678Slinton     }
4599678Slinton     return codeloc(s);
4609678Slinton }
4619678Slinton 
4629678Slinton /*
4639678Slinton  * Decide if the given function is currently active.
4649678Slinton  *
4659678Slinton  * We avoid calls to "findframe" during a stack trace for efficiency.
4669678Slinton  * Presumably information evaluated while walking the stack is active.
4679678Slinton  */
4689678Slinton 
4699678Slinton public Boolean isactive(f)
4709678Slinton Symbol f;
4719678Slinton {
4729678Slinton     register Boolean b;
4739678Slinton 
4749678Slinton     if (isfinished(process)) {
4759678Slinton 	b = false;
4769678Slinton     } else {
4779678Slinton 	if (walkingstack or f == program or
4789678Slinton 	  (ismodule(f) and isactive(container(f)))) {
4799678Slinton 	    b = true;
4809678Slinton 	} else {
4819678Slinton 	    b = (Boolean) (findframe(f) != nil);
4829678Slinton 	}
4839678Slinton     }
4849678Slinton     return b;
4859678Slinton }
4869678Slinton 
4879678Slinton /*
4889678Slinton  * Evaluate a call to a procedure.
4899678Slinton  */
4909678Slinton 
4919678Slinton public callproc(procnode, arglist)
4929678Slinton Node procnode;
4939678Slinton Node arglist;
4949678Slinton {
4959678Slinton     Symbol proc;
4969678Slinton     Integer argc;
4979678Slinton 
4989678Slinton     if (procnode->op != O_SYM) {
4999678Slinton 	beginerrmsg();
5009678Slinton 	fprintf(stderr, "can't call \"");
5019678Slinton 	prtree(stderr, procnode);
5029678Slinton 	fprintf(stderr, "\"");
5039678Slinton 	enderrmsg();
5049678Slinton     }
5059678Slinton     assert(procnode->op == O_SYM);
5069678Slinton     proc = procnode->value.sym;
5079678Slinton     if (not isblock(proc)) {
5089678Slinton 	error("\"%s\" is not a procedure or function", symname(proc));
5099678Slinton     }
5109678Slinton     pushenv();
5119678Slinton     pc = codeloc(proc);
5129678Slinton     argc = pushargs(proc, arglist);
5139678Slinton     beginproc(proc, argc);
5149678Slinton     isstopped = true;
5159678Slinton     event_once(build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
5169678Slinton 	buildcmdlist(build(O_PROCRTN, proc)));
5179678Slinton     cont();
5189678Slinton     /* NOTREACHED */
5199678Slinton }
5209678Slinton 
5219678Slinton /*
5229678Slinton  * Push the arguments on the process' stack.  We do this by first
5239678Slinton  * evaluating them on the "eval" stack, then copying into the process'
5249678Slinton  * space.
5259678Slinton  */
5269678Slinton 
5279678Slinton private Integer pushargs(proc, arglist)
5289678Slinton Symbol proc;
5299678Slinton Node arglist;
5309678Slinton {
5319678Slinton     Stack *savesp;
5329678Slinton     int argc, args_size;
5339678Slinton 
5349678Slinton     savesp = sp;
5359678Slinton     argc = evalargs(proc, arglist);
5369678Slinton     args_size = sp - savesp;
5379678Slinton     setreg(STKP, reg(STKP) - args_size);
5389678Slinton     dwrite(savesp, reg(STKP), args_size);
5399678Slinton     sp = savesp;
5409678Slinton     return argc;
5419678Slinton }
5429678Slinton 
5439678Slinton /*
5449678Slinton  * Evaluate arguments left-to-right.
5459678Slinton  */
5469678Slinton 
5479678Slinton private Integer evalargs(proc, arglist)
5489678Slinton Symbol proc;
5499678Slinton Node arglist;
5509678Slinton {
5519678Slinton     Node p, exp;
5529678Slinton     Symbol arg;
5539678Slinton     Stack *savesp;
5549678Slinton     Address addr;
5559678Slinton     Integer count;
5569678Slinton 
5579678Slinton     savesp = sp;
5589678Slinton     count = 0;
5599678Slinton     arg = proc->chain;
5609678Slinton     for (p = arglist; p != nil; p = p->value.arg[1]) {
5619678Slinton 	if (p->op != O_COMMA) {
5629678Slinton 	    panic("evalargs: arglist missing comma");
5639678Slinton 	}
5649678Slinton 	if (arg == nil) {
5659678Slinton 	    sp = savesp;
5669678Slinton 	    error("too many parameters to %s", symname(proc));
5679678Slinton 	}
5689678Slinton 	exp = p->value.arg[0];
5699678Slinton 	if (not compatible(arg->type, exp->nodetype)) {
5709678Slinton 	    sp = savesp;
5719678Slinton 	    error("expression for parameter %s is of wrong type", symname(arg));
5729678Slinton 	}
5739678Slinton 	if (arg->class == REF) {
5749678Slinton 	    if (exp->op != O_RVAL) {
5759678Slinton 		sp = savesp;
5769678Slinton 		error("variable expected for parameter \"%s\"", symname(arg));
5779678Slinton 	    }
5789678Slinton 	    addr = lval(exp->value.arg[0]);
5799678Slinton 	    push(Address, addr);
5809678Slinton 	} else {
5819678Slinton 	    eval(exp);
5829678Slinton 	}
5839678Slinton 	arg = arg->chain;
5849678Slinton 	++count;
5859678Slinton     }
5869678Slinton     if (arg != nil) {
5879678Slinton 	sp = savesp;
5889678Slinton 	error("not enough parameters to %s", symname(proc));
5899678Slinton     }
5909678Slinton     return count;
5919678Slinton }
5929678Slinton 
5939678Slinton public procreturn(f)
5949678Slinton Symbol f;
5959678Slinton {
5969678Slinton     flushoutput();
5979678Slinton     putchar('\n');
5989678Slinton     printname(stdout, f);
5999678Slinton     printf(" returns successfully\n", symname(f));
6009678Slinton     popenv();
6019678Slinton     erecover();
6029678Slinton }
6039678Slinton 
6049678Slinton /*
6059678Slinton  * Push the current environment.
6069678Slinton  */
6079678Slinton 
6089678Slinton private pushenv()
6099678Slinton {
6109678Slinton     push(Address, pc);
6119678Slinton     push(Lineno, curline);
6129678Slinton     push(String, cursource);
6139678Slinton     push(Boolean, isstopped);
6149678Slinton     push(Symbol, curfunc);
6159678Slinton     push(Word, reg(PROGCTR));
6169678Slinton     push(Word, reg(STKP));
6179678Slinton }
6189678Slinton 
6199678Slinton /*
6209678Slinton  * Pop back to the real world.
6219678Slinton  */
6229678Slinton 
6239678Slinton public popenv()
6249678Slinton {
6259678Slinton     register String filename;
6269678Slinton 
6279678Slinton     setreg(STKP, pop(Word));
6289678Slinton     setreg(PROGCTR, pop(Word));
6299678Slinton     curfunc = pop(Symbol);
6309678Slinton     isstopped = pop(Boolean);
6319678Slinton     filename = pop(String);
6329678Slinton     curline = pop(Lineno);
6339678Slinton     pc = pop(Address);
6349678Slinton     setsource(filename);
6359678Slinton }
6369678Slinton 
6379678Slinton /*
6389678Slinton  * Flush the debuggee's standard output.
6399678Slinton  *
6409678Slinton  * This is VERY dependent on the use of stdio.
6419678Slinton  */
6429678Slinton 
6439678Slinton public flushoutput()
6449678Slinton {
6459678Slinton     register Symbol p, iob;
6469678Slinton     register Stack *savesp;
6479678Slinton 
6489678Slinton     p = lookup(identname("fflush", true));
6499678Slinton     while (p != nil and not isblock(p)) {
6509678Slinton 	p = p->next_sym;
6519678Slinton     }
6529678Slinton     if (p != nil) {
6539678Slinton 	iob = lookup(identname("_iob", true));
6549678Slinton 	if (iob != nil) {
6559678Slinton 	    pushenv();
6569678Slinton 	    pc = codeloc(p);
6579678Slinton 	    savesp = sp;
6589678Slinton 	    push(long, address(iob, nil) + sizeof(struct _iobuf));
6599678Slinton 	    setreg(STKP, reg(STKP) - sizeof(long));
6609678Slinton 	    dwrite(savesp, reg(STKP), sizeof(long));
6619678Slinton 	    sp = savesp;
6629678Slinton 	    beginproc(p, 1);
6639678Slinton 	    stepto(return_addr());
6649678Slinton 	    popenv();
6659678Slinton 	}
6669678Slinton     }
6679678Slinton }
668