+/*
+ * Print out the information about a call, i.e.,
+ * routine name, parameter values, and source location.
+ */
+
+private printcallinfo (f, frp)
+Symbol f;
+Frame frp;
+{
+ Lineno line;
+ Address savepc;
+
+ savepc = frp->save_pc;
+ if (frp->save_fp != reg(FRP)) {
+ savepc -= 1;
+ }
+ printname(stdout, f);
+ if (not isinline(f)) {
+ printparams(f, frp);
+ }
+ line = srcline(savepc);
+ if (line != 0) {
+ printf(", line %d", line);
+ printf(" in \"%s\"\n", srcfilename(savepc));
+ } else {
+ printf(" at 0x%x\n", savepc);
+ }
+}
+
+/*
+ * Set the current function to the given symbol.
+ * We must adjust "curframe" so that subsequent operations are
+ * not confused; for simplicity we simply clear it.
+ */
+
+public setcurfunc (f)
+Symbol f;
+{
+ curfunc = f;
+ curframe = nil;
+}
+
+/*
+ * Return the frame for the current function.
+ * The space for the frame is allocated statically.
+ */
+
+public Frame curfuncframe ()
+{
+ static struct Frame frame;
+ Frame frp;
+
+ if (curframe == nil) {
+ frp = findframe(curfunc);
+ curframe = &curframerec;
+ *curframe = *frp;
+ } else {
+ frp = &frame;
+ *frp = *curframe;
+ }
+ return frp;
+}
+
+/*
+ * Set curfunc to be N up/down the stack from its current value.
+ */
+
+public up (n)
+integer n;
+{
+ integer i;
+ Symbol f;
+ Frame frp;
+ boolean done;
+
+ if (not isactive(program)) {
+ error("program is not active");
+ } else if (curfunc == nil) {
+ error("no current function");
+ } else {
+ i = 0;
+ f = curfunc;
+ frp = curfuncframe();
+ done = false;
+ do {
+ if (frp == nil) {
+ done = true;
+ error("not that many levels");
+ } else if (i >= n) {
+ done = true;
+ curfunc = f;
+ curframe = &curframerec;
+ *curframe = *frp;
+ showaggrs = false;
+ printcallinfo(curfunc, curframe);
+ } else if (f == program) {
+ done = true;
+ error("not that many levels");
+ } else {
+ frp = nextfunc(frp, &f);
+ }
+ ++i;
+ } while (not done);
+ }
+}
+
+public down (n)
+integer n;
+{
+ integer i, depth;
+ Frame frp, curfrp;
+ Symbol f;
+ struct Frame frame;
+
+ if (not isactive(program)) {
+ error("program is not active");
+ } else if (curfunc == nil) {
+ error("no current function");
+ } else {
+ depth = 0;
+ frp = &frame;
+ getcurfunc(frp, &f);
+ if (curframe == nil) {
+ curfrp = findframe(curfunc);
+ curframe = &curframerec;
+ *curframe = *curfrp;
+ }
+ while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) {
+ frp = nextfunc(frp, &f);
+ ++depth;
+ }
+ if (f == nil or n > depth) {
+ error("not that many levels");
+ } else {
+ depth -= n;
+ frp = &frame;
+ getcurfunc(frp, &f);
+ for (i = 0; i < depth; i++) {
+ frp = nextfunc(frp, &f);
+ assert(frp != nil);
+ }
+ curfunc = f;
+ *curframe = *frp;
+ showaggrs = false;
+ printcallinfo(curfunc, curframe);
+ }
+ }
+}
+