file reorg, pathnames.h, paths.h
[unix-history] / usr / src / old / dbx / runtime.tahoe.c
CommitLineData
f530962e
SL
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
dbc03deb 8static char sccsid[] = "@(#)runtime.tahoe.c 5.3 (Berkeley) %G%";
f530962e
SL
9#endif not lint
10
dbc03deb 11static char rcsid[] = "$Header: runtime.tahoe.c,v 1.6 88/01/11 21:26:56 donn Exp $";
f530962e
SL
12
13/*
14 * Runtime organization dependent routines, mostly dealing with
15 * activation records.
16 */
17
18#include "defs.h"
19#include "runtime.h"
20#include "process.h"
21#include "machine.h"
22#include "events.h"
23#include "mappings.h"
24#include "symbols.h"
25#include "tree.h"
26#include "eval.h"
27#include "operators.h"
28#include "object.h"
f530962e
SL
29
30#ifndef public
31#include "machine.h"
32
33typedef struct Frame {
34 Address save_pc; /* program counter */
35 integer mask:16; /* register save mask */
36 integer removed:16; /* 4*number of arguments + 4 */
37 Address save_fp; /* frame pointer */
38#define NSAVEREG 13
39 Word save_reg[NSAVEREG]; /* not necessarily there */
40} *Frame;
41#endif
42
43private Frame curframe = nil;
44private struct Frame curframerec;
45private Boolean walkingstack = false;
46
47#define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)
48
dbc03deb 49#define inSignalHandler(addr) \
f530962e
SL
50 (((addr) < 0xc0000000) and ((addr) > 0xc0000000 - 0x400 * UPAGES))
51
52typedef struct {
53 Node callnode;
54 Node cmdnode;
55 boolean isfunc;
56} CallEnv;
57
58private CallEnv endproc;
59
60/*
61 * Set a frame to the current activation record.
62 */
63
64private getcurframe(frp)
65Frame frp;
66{
67 register int i;
68 long x;
69
70 checkref(frp);
71 frp->save_fp = reg(FRP);
72 dread(&x, frp->save_fp-4, 4);
73 frp->mask = x >> 16;
74 frp->removed = x & 0xffff;
75 frp->save_pc = reg(PROGCTR);
76 for (i = 0; i < NSAVEREG; i++) {
77 frp->save_reg[i] = reg(i);
78 }
79}
80
81/*
82 * Get the saved registers from one frame to another
83 * given mask specifying which registers were actually saved.
84 */
85
86#define bis(b, n) ((b & (1 << (n))) != 0)
87
88private getsaveregs (newfrp, frp, mask)
89Frame newfrp, frp;
90integer mask;
91{
92 integer i, j;
93
94 j = 0;
95 for (i = 0; i < NSAVEREG; i++) {
96 if (bis(mask, i)) {
97 newfrp->save_reg[i] = frp->save_reg[j];
98 ++j;
99 }
100 }
101}
102
103/*
104 * Return a pointer to the next activation record up the stack.
105 * Return nil if there is none.
106 * Writes over space pointed to by given argument.
107 */
108
109private Frame nextframe(frp)
110Frame frp;
111{
112 Frame newfrp;
113 struct Frame frame;
114 long x;
dbc03deb 115 Address prev_frame, callpc;
f530962e
SL
116 static integer ntramp = 0;
117
118 newfrp = frp;
119 prev_frame = frp->save_fp;
120
121/*
122 * The check for interrupt generated frames is taken from adb with only
123 * partial understanding. If you're in "sub" and on a sigxxx "sigsub"
124 * gets control, then the stack does NOT look like <main, sub, sigsub>.
125 *
126 * As best I can make out it looks like:
127 *
128 * <main, (machine check exception block + sub), sysframe, sigsub>.
129 *
130 * When the signal occurs an exception block and a frame for the routine
131 * in which it occured are pushed on the user stack. Then another frame
132 * is pushed corresponding to a call from the kernel to sigsub.
133 *
134 * The addr in sub at which the exception occured is not in sub.save_pc
135 * but in the machine check exception block. It is at the magic address
136 * fp + 84.
137 *
138 * The current approach ignores the sys_frame (what adb reports as sigtramp)
139 * and takes the pc for sub from the exception block. This allows the
140 * "where" command to report <main, sub, sigsub>, which seems reasonable.
141 */
142
143nextf:
144 dread(&frame, prev_frame-8, sizeof(struct Frame));
145 if (ntramp == 1) {
146 dread(&callpc, prev_frame+44, sizeof(callpc));
147 } else {
148 callpc = frame.save_pc;
149 }
150 if (frame.save_fp == nil or frame.save_pc == (Address) -1) {
151 newfrp = nil;
dbc03deb 152 } else if (inSignalHandler(callpc)) {
f530962e
SL
153 ntramp++;
154 prev_frame = frame.save_fp;
155 goto nextf;
156 } else {
157 ntramp = 0;
158 getsaveregs(newfrp, &frame, frame.mask);
159 dread(&x, frame.save_fp-4, sizeof (x));
160 newfrp->mask = x >> 16;
161 newfrp->removed = x & 0xffff;
162 newfrp->save_fp = frame.save_fp;
163 newfrp->save_pc = callpc;
164 }
165 return newfrp;
166}
167
168/*
169 * Get the current frame information in the given Frame and store the
170 * associated function in the given value-result parameter.
171 */
172
173private getcurfunc (frp, fp)
174Frame frp;
175Symbol *fp;
176{
177 getcurframe(frp);
178 *fp = whatblock(frp->save_pc);
179}
180
181/*
182 * Return the frame associated with the next function up the call stack, or
183 * nil if there is none. The function is returned in a value-result parameter.
184 * For "inline" functions the statically outer function and same frame
185 * are returned.
186 */
187
188public Frame nextfunc (frp, fp)
189Frame frp;
190Symbol *fp;
191{
192 Symbol t;
193 Frame nfrp;
194
195 t = *fp;
196 checkref(t);
197 if (isinline(t)) {
198 t = container(t);
199 nfrp = frp;
200 } else {
201 nfrp = nextframe(frp);
202 if (nfrp == nil) {
203 t = nil;
204 } else {
205 t = whatblock(nfrp->save_pc);
206 }
207 }
208 *fp = t;
209 return nfrp;
210}
211
212/*
213 * Return the frame associated with the given function.
214 * If the function is nil, return the most recently activated frame.
215 *
216 * Static allocation for the frame.
217 */
218
219public Frame findframe(f)
220Symbol f;
221{
222 Frame frp;
223 static struct Frame frame;
224 Symbol p;
225 Boolean done;
226
227 frp = &frame;
228 getcurframe(frp);
229 if (f != nil) {
230 if (f == curfunc and curframe != nil) {
231 *frp = *curframe;
232 } else {
233 done = false;
234 p = whatblock(frp->save_pc);
235 do {
236 if (p == f) {
237 done = true;
238 } else if (p == program) {
239 done = true;
240 frp = nil;
241 } else {
242 frp = nextfunc(frp, &p);
243 if (frp == nil) {
244 done = true;
245 }
246 }
247 } while (not done);
248 }
249 }
250 return frp;
251}
252
253/*
254 * Set the registers according to the given frame pointer.
255 */
256
257public getnewregs (addr)
258Address addr;
259{
260 struct Frame frame;
261 integer i, j, mask;
262
263 dread(&frame, addr-8, sizeof(frame));
264 setreg(FRP, frame.save_fp);
265 setreg(PROGCTR, frame.save_pc);
266 mask = frame.mask;
267 j = 0;
268 for (i = 0; i < NSAVEREG; i++) {
269 if (bis(mask, i)) {
270 setreg(i, frame.save_reg[j]);
271 ++j;
272 }
273 }
274 pc = frame.save_pc;
275 setcurfunc(whatblock(pc));
276}
277
278/*
279 * Find the return address of the current procedure/function.
280 */
281
282public Address return_addr()
283{
284 Frame frp;
285 Address addr;
286 struct Frame frame;
287
288 frp = &frame;
289 getcurframe(frp);
290 frp = nextframe(frp);
291 if (frp == nil) {
292 addr = 0;
293 } else {
294 addr = frp->save_pc;
295 }
296 return addr;
297}
298
299/*
300 * Push the value associated with the current function.
301 */
302
303public pushretval(len, isindirect)
304integer len;
305boolean isindirect;
306{
307 Word r0;
308
309 r0 = reg(0);
310 if (isindirect) {
311 rpush((Address) r0, len);
312 } else {
313 switch (len) {
314 case sizeof(char):
315 push(char, r0);
316 break;
317
318 case sizeof(short):
319 push(short, r0);
320 break;
321
322 default:
323 if (len == sizeof(Word)) {
324 push(Word, r0);
325 } else if (len == 2*sizeof(Word)) {
326 push(Word, r0);
327 push(Word, reg(1));
328 } else {
329 error("[internal error: bad size %d in pushretval]", len);
330 }
331 break;
332 }
333 }
334}
335
336/*
337 * Return the base address for locals in the given frame.
338 */
339
340public Address locals_base(frp)
341Frame frp;
342{
343 return (frp == nil ? reg(FRP) : frp->save_fp);
344}
345
346/*
347 * Return the base address for arguments in the given frame.
348 */
349
350public Address args_base(frp)
351Frame frp;
352{
353 return (frp == nil ? reg(FRP) : frp->save_fp);
354}
355
356/*
357 * Return saved register n from the given frame.
358 */
359
360public Word savereg(n, frp)
361integer n;
362Frame frp;
363{
364 Word w;
365
366 if (frp == nil) {
367 w = reg(n);
368 } else {
369 switch (n) {
370
371 case FRP:
372 w = frp->save_fp;
373 break;
374
375 case STKP:
376 w = reg(STKP);
377 break;
378
379 case PROGCTR:
380 w = frp->save_pc;
381 break;
382
383 default:
384 assert(n >= 0 and n < NSAVEREG);
385 w = frp->save_reg[n];
386 break;
387 }
388 }
389 return w;
390}
391
392/*
393 * Return the nth argument to the current procedure.
394 */
395
396public Word argn(n, frp)
397integer n;
398Frame frp;
399{
dbc03deb 400 Address argaddr;
f530962e
SL
401 Word w;
402
dbc03deb
DS
403 argaddr = args_base(frp) + (n * sizeof(Word));
404 dread(&w, argaddr, sizeof(w));
f530962e
SL
405 return w;
406}
407
408/*
409 * Print a list of currently active blocks starting with most recent.
410 */
411
412public wherecmd()
413{
414 walkstack(false);
415}
416
417/*
418 * Print the variables in the given frame or the current one if nil.
419 */
420
421public dump (func)
422Symbol func;
423{
424 Symbol f;
425 Frame frp;
426
427 if (func == nil) {
428 f = curfunc;
429 if (curframe != nil) {
430 frp = curframe;
431 } else {
432 frp = findframe(f);
433 }
434 } else {
435 f = func;
436 frp = findframe(f);
437 }
438 showaggrs = true;
439 printcallinfo(f, frp);
440 dumpvars(f, frp);
441}
442
443/*
444 * Dump all values.
445 */
446
447public dumpall ()
448{
449 walkstack(true);
450}
451
452/*
453 * Walk the stack of active procedures printing information
454 * about each active procedure.
455 */
456
457private walkstack(dumpvariables)
458Boolean dumpvariables;
459{
460 Frame frp;
461 boolean save;
462 Symbol f;
463 struct Frame frame;
464
465 if (notstarted(process) or isfinished(process)) {
466 error("program is not active");
467 } else {
468 save = walkingstack;
469 walkingstack = true;
470 showaggrs = dumpvariables;
471 frp = &frame;
472 getcurfunc(frp, &f);
473 for (;;) {
474 printcallinfo(f, frp);
475 if (dumpvariables) {
476 dumpvars(f, frp);
477 putchar('\n');
478 }
479 frp = nextfunc(frp, &f);
480 if (frp == nil or f == program) {
481 break;
482 }
483 }
484 if (dumpvariables) {
485 printf("in \"%s\":\n", symname(program));
486 dumpvars(program, nil);
487 putchar('\n');
488 }
489 walkingstack = save;
490 }
491}
492
493/*
494 * Print out the information about a call, i.e.,
495 * routine name, parameter values, and source location.
496 */
497
498private printcallinfo (f, frp)
499Symbol f;
500Frame frp;
501{
502 Lineno line;
503 Address savepc;
504
505 savepc = frp->save_pc;
506 if (frp->save_fp != reg(FRP)) {
507 savepc -= 1;
508 }
509 printname(stdout, f);
510 if (not isinline(f)) {
511 printparams(f, frp);
512 }
513 line = srcline(savepc);
514 if (line != 0) {
515 printf(", line %d", line);
516 printf(" in \"%s\"\n", srcfilename(savepc));
517 } else {
518 printf(" at 0x%x\n", savepc);
519 }
520}
521
522/*
523 * Set the current function to the given symbol.
524 * We must adjust "curframe" so that subsequent operations are
525 * not confused; for simplicity we simply clear it.
526 */
527
528public setcurfunc (f)
529Symbol f;
530{
531 curfunc = f;
532 curframe = nil;
533}
534
535/*
536 * Return the frame for the current function.
537 * The space for the frame is allocated statically.
538 */
539
540public Frame curfuncframe ()
541{
542 static struct Frame frame;
543 Frame frp;
544
545 if (curframe == nil) {
546 frp = findframe(curfunc);
547 curframe = &curframerec;
548 *curframe = *frp;
549 } else {
550 frp = &frame;
551 *frp = *curframe;
552 }
553 return frp;
554}
555
556/*
557 * Set curfunc to be N up/down the stack from its current value.
558 */
559
560public up (n)
561integer n;
562{
563 integer i;
564 Symbol f;
565 Frame frp;
566 boolean done;
567
568 if (not isactive(program)) {
569 error("program is not active");
570 } else if (curfunc == nil) {
571 error("no current function");
572 } else {
573 i = 0;
574 f = curfunc;
575 frp = curfuncframe();
576 done = false;
577 do {
578 if (frp == nil) {
579 done = true;
580 error("not that many levels");
581 } else if (i >= n) {
582 done = true;
583 curfunc = f;
584 curframe = &curframerec;
585 *curframe = *frp;
586 showaggrs = false;
587 printcallinfo(curfunc, curframe);
588 } else if (f == program) {
589 done = true;
590 error("not that many levels");
591 } else {
592 frp = nextfunc(frp, &f);
593 }
594 ++i;
595 } while (not done);
596 }
597}
598
599public down (n)
600integer n;
601{
602 integer i, depth;
603 Frame frp, curfrp;
604 Symbol f;
605 struct Frame frame;
606
607 if (not isactive(program)) {
608 error("program is not active");
609 } else if (curfunc == nil) {
610 error("no current function");
611 } else {
612 depth = 0;
613 frp = &frame;
614 getcurfunc(frp, &f);
615 if (curframe == nil) {
616 curfrp = findframe(curfunc);
617 curframe = &curframerec;
618 *curframe = *curfrp;
619 }
620 while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) {
621 frp = nextfunc(frp, &f);
622 ++depth;
623 }
624 if (f == nil or n > depth) {
625 error("not that many levels");
626 } else {
627 depth -= n;
628 frp = &frame;
629 getcurfunc(frp, &f);
630 for (i = 0; i < depth; i++) {
631 frp = nextfunc(frp, &f);
632 assert(frp != nil);
633 }
634 curfunc = f;
635 *curframe = *frp;
636 showaggrs = false;
637 printcallinfo(curfunc, curframe);
638 }
639 }
640}
641
642/*
643 * Find the entry point of a procedure or function.
644 */
645
646public findbeginning (f)
647Symbol f;
648{
649 if (isinternal(f)) {
650 f->symvalue.funcv.beginaddr += 15;
651 } else {
dbc03deb 652 f->symvalue.funcv.beginaddr += FUNCOFFSET;
f530962e
SL
653 }
654}
655
656/*
657 * Return the address corresponding to the first line in a function.
658 */
659
660public Address firstline(f)
661Symbol f;
662{
663 Address addr;
664
665 addr = codeloc(f);
666 while (linelookup(addr) == 0 and addr < objsize) {
667 ++addr;
668 }
669 if (addr == objsize) {
670 addr = -1;
671 }
672 return addr;
673}
674
675/*
676 * Catcher drops strike three ...
677 */
678
679public runtofirst()
680{
dbc03deb 681 Address addr, endaddr;
f530962e
SL
682
683 addr = pc;
dbc03deb
DS
684 endaddr = objsize + CODESTART;
685 while (linelookup(addr) == 0 and addr < endaddr) {
f530962e
SL
686 ++addr;
687 }
dbc03deb 688 if (addr < endaddr) {
f530962e
SL
689 stepto(addr);
690 }
691}
692
693/*
694 * Return the address corresponding to the end of the program.
695 *
696 * We look for the entry to "exit".
697 */
698
699public Address lastaddr()
700{
701 Symbol s;
702
703 s = lookup(identname("exit", true));
704 if (s == nil) {
705 panic("can't find exit");
706 }
707 return codeloc(s);
708}
709
710/*
711 * Decide if the given function is currently active.
712 *
713 * We avoid calls to "findframe" during a stack trace for efficiency.
714 * Presumably information evaluated while walking the stack is active.
715 */
716
dbc03deb 717public Boolean isactive (f)
f530962e
SL
718Symbol f;
719{
720 Boolean b;
721
722 if (isfinished(process)) {
723 b = false;
724 } else {
dbc03deb 725 if (walkingstack or f == program or f == nil or
f530962e
SL
726 (ismodule(f) and isactive(container(f)))) {
727 b = true;
728 } else {
729 b = (Boolean) (findframe(f) != nil);
730 }
731 }
732 return b;
733}
734
735/*
736 * Evaluate a call to a procedure.
737 */
738
739public callproc(exprnode, isfunc)
740Node exprnode;
741boolean isfunc;
742{
743 Node procnode, arglist;
744 Symbol proc;
745 integer argc;
746
747 procnode = exprnode->value.arg[0];
748 arglist = exprnode->value.arg[1];
749 if (procnode->op != O_SYM) {
750 beginerrmsg();
751 fprintf(stderr, "can't call \"");
752 prtree(stderr, procnode);
753 fprintf(stderr, "\"");
754 enderrmsg();
755 }
756 assert(procnode->op == O_SYM);
757 proc = procnode->value.sym;
758 if (not isblock(proc)) {
759 error("\"%s\" is not a procedure or function", symname(proc));
760 }
761 endproc.isfunc = isfunc;
762 endproc.callnode = exprnode;
763 endproc.cmdnode = topnode;
764 pushenv();
765 pc = codeloc(proc);
766 argc = pushargs(proc, arglist);
dbc03deb 767 setreg(FRP, 1); /* have to ensure it's non-zero for return_addr() */
f530962e
SL
768 beginproc(proc, argc);
769 event_once(
770 build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
771 buildcmdlist(build(O_PROCRTN, proc))
772 );
773 isstopped = false;
774 if (not bpact()) {
775 isstopped = true;
776 cont(0);
777 }
778 /*
779 * bpact() won't return true, it will call printstatus() and go back
780 * to command input if a breakpoint is found.
781 */
782 /* NOTREACHED */
783}
784
785/*
786 * Push the arguments on the process' stack. We do this by first
787 * evaluating them on the "eval" stack, then copying into the process'
788 * space.
789 */
790
791private integer pushargs(proc, arglist)
792Symbol proc;
793Node arglist;
794{
795 Stack *savesp;
796 int argc, args_size;
797
798 savesp = sp;
799 argc = evalargs(proc, arglist);
800 args_size = sp - savesp;
801 setreg(STKP, reg(STKP) - args_size);
802 dwrite(savesp, reg(STKP), args_size);
803 sp = savesp;
804 return argc;
805}
806
807/*
808 * Check to see if an expression is correct for a given parameter.
809 * If the given parameter is false, don't worry about type inconsistencies.
810 *
811 * Return whether or not it is ok.
812 */
813
814private boolean chkparam (actual, formal, chk)
815Node actual;
816Symbol formal;
817boolean chk;
818{
819 boolean b;
820
821 b = true;
822 if (chk) {
823 if (formal == nil) {
824 beginerrmsg();
825 fprintf(stderr, "too many parameters");
826 b = false;
827 } else if (not compatible(formal->type, actual->nodetype)) {
828 beginerrmsg();
829 fprintf(stderr, "type mismatch for %s", symname(formal));
830 b = false;
831 }
832 }
833 if (b and formal != nil and
834 isvarparam(formal) and not isopenarray(formal->type) and
835 not (
836 actual->op == O_RVAL or actual->nodetype == t_addr or
837 (
838 actual->op == O_TYPERENAME and
839 (
840 actual->value.arg[0]->op == O_RVAL or
841 actual->value.arg[0]->nodetype == t_addr
842 )
843 )
844 )
845 ) {
846 beginerrmsg();
847 fprintf(stderr, "expected variable, found \"");
848 prtree(stderr, actual);
849 fprintf(stderr, "\"");
850 b = false;
851 }
852 return b;
853}
854
855/*
856 * Pass an expression to a particular parameter.
857 *
858 * Normally we pass either the address or value, but in some cases
859 * (such as C strings) we want to copy the value onto the stack and
860 * pass its address.
861 *
862 * Another special case raised by strings is the possibility that
863 * the actual parameter will be larger than the formal, even with
864 * appropriate type-checking. This occurs because we assume during
865 * evaluation that strings are null-terminated, whereas some languages,
866 * notably Pascal, do not work under that assumption.
867 */
868
869private passparam (actual, formal)
870Node actual;
871Symbol formal;
872{
873 boolean b;
874 Address addr;
875 Stack *savesp;
876 integer actsize, formsize;
877
878 if (formal != nil and isvarparam(formal) and
879 (not isopenarray(formal->type))
880 ) {
881 addr = lval(actual->value.arg[0]);
882 push(Address, addr);
883 } else if (passaddr(formal, actual->nodetype)) {
884 savesp = sp;
885 eval(actual);
886 actsize = sp - savesp;
887 setreg(STKP, reg(STKP) - roundup(actsize, sizeof (Word)));
888 dwrite(savesp, reg(STKP), actsize);
889 sp = savesp;
890 push(Address, reg(STKP));
891 if (formal != nil and isopenarray(formal->type)) {
892 push(integer, actsize div size(formal->type->type));
893 }
894 } else if (formal != nil) {
895 formsize = size(formal);
896 savesp = sp;
897 eval(actual);
898 actsize = sp - savesp;
899 if (actsize > formsize) {
900 sp -= (actsize - formsize);
901 }
902 } else {
903 eval(actual);
904 }
905}
906
907/*
908 * Evaluate an argument list left-to-right.
909 */
910
911private integer evalargs(proc, arglist)
912Symbol proc;
913Node arglist;
914{
915 Node p, actual;
916 Symbol formal;
917 Stack *savesp;
918 integer count;
919 boolean chk;
920
921 savesp = sp;
922 count = 0;
923 formal = proc->chain;
924 chk = (boolean) (not nosource(proc));
925 for (p = arglist; p != nil; p = p->value.arg[1]) {
926 assert(p->op == O_COMMA);
927 actual = p->value.arg[0];
928 if (not chkparam(actual, formal, chk)) {
929 fprintf(stderr, " in call to %s", symname(proc));
930 sp = savesp;
931 enderrmsg();
932 }
933 passparam(actual, formal);
934 if (formal != nil) {
935 formal = formal->chain;
936 }
937 ++count;
938 }
939 if (chk) {
940 if (formal != nil) {
941 sp = savesp;
942 error("not enough parameters to %s", symname(proc));
943 }
944 }
945 return count;
946}
947
dbc03deb
DS
948/*
949 * Evaluate an argument list without any type checking.
950 * This is only useful for procedures with a varying number of
951 * arguments that are compiled -g.
952 */
953
954private integer unsafe_evalargs (proc, arglist)
955Symbol proc;
956Node arglist;
957{
958 Node p;
959 integer count;
960
961 count = 0;
962 for (p = arglist; p != nil; p = p->value.arg[1]) {
963 assert(p->op == O_COMMA);
964 eval(p->value.arg[0]);
965 ++count;
966 }
967 return count;
968}
969
f530962e
SL
970public procreturn(f)
971Symbol f;
972{
973 integer retvalsize;
974 Node tmp;
975 char *copy;
976
977 flushoutput();
978 popenv();
979 if (endproc.isfunc) {
980 retvalsize = size(f->type);
981 if (retvalsize > sizeof(long)) {
982 pushretval(retvalsize, true);
983 copy = newarr(char, retvalsize);
984 popn(retvalsize, copy);
985 tmp = build(O_SCON, copy);
986 } else {
987 tmp = build(O_LCON, (long) (reg(0)));
988 }
989 tmp->nodetype = f->type;
990 tfree(endproc.callnode);
991 *(endproc.callnode) = *(tmp);
992 dispose(tmp);
993 eval(endproc.cmdnode);
994 } else {
995 putchar('\n');
996 printname(stdout, f);
dbc03deb 997 printf(" returns successfully\n");
f530962e
SL
998 }
999 erecover();
1000}
1001
1002/*
1003 * Push the current environment.
1004 */
1005
1006private pushenv()
1007{
1008 push(Address, pc);
1009 push(Lineno, curline);
1010 push(String, cursource);
1011 push(Boolean, isstopped);
1012 push(Symbol, curfunc);
1013 push(Frame, curframe);
1014 push(struct Frame, curframerec);
1015 push(CallEnv, endproc);
1016 push(Word, reg(PROGCTR));
1017 push(Word, reg(STKP));
1018}
1019
1020/*
1021 * Pop back to the real world.
1022 */
1023
1024public popenv()
1025{
1026 String filename;
1027
1028 setreg(STKP, pop(Word));
1029 setreg(PROGCTR, pop(Word));
1030 endproc = pop(CallEnv);
1031 curframerec = pop(struct Frame);
1032 curframe = pop(Frame);
1033 curfunc = pop(Symbol);
1034 isstopped = pop(Boolean);
1035 filename = pop(String);
1036 curline = pop(Lineno);
1037 pc = pop(Address);
1038 setsource(filename);
1039}
1040
1041/*
1042 * Flush the debuggee's standard output.
1043 *
1044 * This is VERY dependent on the use of stdio.
1045 */
1046
1047public flushoutput()
1048{
1049 Symbol p, iob;
1050 Stack *savesp;
1051
1052 p = lookup(identname("fflush", true));
1053 while (p != nil and not isblock(p)) {
1054 p = p->next_sym;
1055 }
1056 if (p != nil) {
1057 iob = lookup(identname("_iob", true));
1058 if (iob != nil) {
1059 pushenv();
1060 pc = codeloc(p);
1061 savesp = sp;
1062 push(long, address(iob, nil) + sizeof(struct _iobuf));
1063 setreg(STKP, reg(STKP) - sizeof(long));
1064 dwrite(savesp, reg(STKP), sizeof(long));
1065 sp = savesp;
1066 beginproc(p, 1);
1067 stepto(return_addr());
1068 popenv();
1069 }
1070 }
1071}