BSD 4 release
[unix-history] / usr / src / cmd / sdb / display.c
index bf79f28..57a500b 100644 (file)
@@ -1,10 +1,18 @@
+static char sccsid[] = "@(#)display.c 4.1 10/9/80";
 #include "head.h"
 #include <a.out.h>
 #include "head.h"
 #include <a.out.h>
+#include <stab.h>
 #include "cdefs.h"
 struct user u;
 BKPTR  bkpthead;
 #include "cdefs.h"
 struct user u;
 BKPTR  bkpthead;
-/* initialize frame pointers to top of call stack */
 
 
+#ifdef FLEXNAMES
+#define        bread(a,b,c)    stread(b,c)
+#define        blseek(a,b,c)   stseek(b,c)
+#endif
+
+/* initialize frame pointers to top of call stack */
+/*  MACHINE DEPENDENT */
 struct proct *
 initframe() {
        argp = *(ADDR *) (((ADDR) &u) + AP);
 struct proct *
 initframe() {
        argp = *(ADDR *) (((ADDR) &u) + AP);
@@ -12,7 +20,7 @@ initframe() {
        callpc = *(ADDR *) (((ADDR) &u) + PC);
        if ((frame == 0) || (frame & 0xf0000000 != 0x70000000))
                return(badproc);
        callpc = *(ADDR *) (((ADDR) &u) + PC);
        if ((frame == 0) || (frame & 0xf0000000 != 0x70000000))
                return(badproc);
-       return(adrtoproc(callpc++));  /* ++ because UNIX backs up instrs */
+       return(adrtoprocp(callpc++));  /* ++ because UNIX backs up instrs */
 }
 
 
 }
 
 
@@ -21,431 +29,217 @@ nextframe() {
        callpc = get(frame+16, DSP);
        argp = get(frame+8, DSP);
        frame = get(frame+12, DSP) & EVEN;
        callpc = get(frame+16, DSP);
        argp = get(frame+8, DSP);
        frame = get(frame+12, DSP) & EVEN;
+       if (callpc > 0x70000000) {  /* error handler kludge */
+               callpc = get(argp+12, DSP);
+               argp = get(frame+8, DSP);
+               frame = get(frame+12, DSP) & EVEN;
+       }
        if ((frame == 0) || (frame & 0xf0000000 != 0x70000000))
                return(badproc);
        if ((frame == 0) || (frame & 0xf0000000 != 0x70000000))
                return(badproc);
-       return(adrtoproc(callpc-1));
-}
-
-/* print call frame */
-prframe() {
-       int narg;
-       char *p;
-       struct proct *procp;
-       
-       if ((procp = initframe()) == badproc) return;
-       do {
-               if (get(frame+12, DSP) == 0) return;
-               p = procp->pname;
-               if (p[0] == '_')
-                       printf("%.7s(", p+1);
-               else
-                       printf("%.8s(", p);
-               narg = get(argp, DSP);
-               if (narg & ~0xff) narg = 0;
-               while (narg) {
-                       printf("%d", get(argp+=4, DSP));
-                       if (--narg != 0) printf(",");
-               }
-               printf(")");
-               if (procp->sfptr != badfile)
-                       printf("   [%s:%d]", adrtofilep(callpc-1)->sfilename,
-                               adrtolineno(callpc-1));
-               printf("\n");
-       } while ((procp = nextframe()) != badproc);
-}
-
-STRING         signals[] = {
-               "",
-               "hangup",
-               "interrupt",
-               "quit",
-               "illegal instruction",
-               "trace/BPT",
-               "IOT",
-               "EMT",
-               "floating exception",
-               "killed",
-               "bus error",
-               "memory fault",
-               "bad system call",
-               "broken pipe",
-               "alarm call",
-               "terminated",
-};
-INT            signo;
-
-sigprint() {
-       printf("%s", signals[signo]);
+       return(adrtoprocp(callpc-1));
 }
 
 }
 
-
 /* returns core image address for variable */
 /* returns core image address for variable */
-formaddr(proc, class, addr)
-register char *proc;
+/*  MACHINE DEPENDENT */
+ADDR
+formaddr(class, addr)
 register char class;
 ADDR addr; {
 register char class;
 ADDR addr; {
-if (debug) printf("formaddr(%s, %o, %d)\n", proc,class & 0377,addr);
+if (debug) printf("formaddr(%o, %d)\n", class & 0377, addr);
        switch(class & STABMASK) {
        case N_RSYM:
        switch(class & STABMASK) {
        case N_RSYM:
-               if (getframe(proc) < 0) return(-1);
+               return(stackreg(addr));
        case N_GSYM:
        case N_SSYM:
        case N_STSYM:
        case N_GSYM:
        case N_SSYM:
        case N_STSYM:
+       case N_LCSYM:
                return(addr);
                
        case N_PSYM:
                return(addr);
                
        case N_PSYM:
-               if (getframe(proc) < 0) return(-1);
                return(argp+addr);
                
        case N_LSYM:
                return(argp+addr);
                
        case N_LSYM:
-               if (getframe(proc) < 0) return(-1);
                return(frame+addr);
 
        default:
                return(frame+addr);
 
        default:
-               printf("Bad class in formaddr: 0%o: (%d, %d)\n",
-                       class & 0377, proc, addr);
+               printf("Bad class in formaddr: 0%o",
+                       class & 0377);
                return(0);
        }
 }
 
                return(0);
        }
 }
 
-/* sets frame pointers to procedure proc */
-getframe(proc)
-register char *proc; {
-       register struct proct *procp, *fprocp;
-       
-       procp = findproc(proc);
-       if (procp == badproc) {
-               printf("%s: Bad procedure name\n", proc);
-               return(-1);
-       }
-       for (fprocp = initframe(); fprocp != badproc; fprocp = nextframe()) {
-               if (procp == fprocp) return(0);
-       }
-       printf("%s: Not an active procedure\n", proc);
-       return(-1);
-}
-
 char class;
 
 char class;
 
-/* returns address of proc:var. Sets externals class and subflag */
+/*
+ *  stackreg(reg):
+ * If the register for the current frame is somewhere on the stack
+ * then return the address of where it is, otherwise its still in
+ * the register so return the register number.
+ * We distinguish the two by noting that register numbers are less
+ * than 16 and that stack addresses are greater.
+ *
+ *  MACHINE DEPENDENT
+ */
 ADDR
 ADDR
-varaddr(proc, var)
-char *proc, *var; {
-       register struct proct *procp;
-       register ADDR addr;
-       char *p;
-       int localflag;
-       
-       if (debug) printf("varaddr(%s,%s)\n", proc, var);
-       localflag = 0;
-       subflag = 0;
-       procp = initframe();
-       do {
-               if (eqstr(proc, procp->pname)) goto found;
-       } while ((procp=nextframe()) != badproc);
-       localflag = 1;
-found:
-       if (eqany(var[0], ".->")) {
-               class = N_GSYM;
-               addr = integ;
-       }
-       else {
-               if (localflag || slookup(var, adrtostoffset(callpc-1)) == -1) {
-                       if (globallookup(var,findfile(curfile)->stf_offset) == -1) {
-                               if (localflag)
-                                       printf("%.8s not found\n", var);
-                               else
-                                       printf("%.8s:%s not found\n", proc, var);
-                               return(-1);
-                       }
+stackreg(reg) {
+       register int curframe, regfl, mask, i;
+       struct proct *procp;
+       ADDR regaddr;
+
+       curframe = frame;
+       regaddr = reg;
+       regfl = 0x10000 << reg;
+       for (procp=initframe(); frame!=curframe; procp=nextframe()) {
+               if (procp == badproc) {
+                       error("Stackreg error: frame");
+                       return(-1);
                }
                }
-       class = sl_class & STABMASK;
-       addr = (class == N_LSYM) ? -sl_addr : sl_addr;
-       addr = formaddr(proc, class, addr);
-       }
-       if (addr == -1) return(-1);
-       for (p=var; *p; p++) {
-               if (*p == '.' && *(p+1) != '\0') {
-                       if (class == N_RSYM) {
-                               error("Not with a register variable");
-                               return(-1);
-                       }
-                       p++;
-                       if (localflag || slookup(p, adrtostoffset(callpc-1)) == -1) {
-                               if (globallookup(p, findfile(curfile)->stf_offset) == -1) {     
-                                       if (localflag)
-                                               printf("%s not found\n", var);
-                                       else
-                                               printf("%.8s:%s not found\n", proc, var);
-                                       return(-1);
-                               }
+               mask = get(frame+4, DSP);
+               if (mask & regfl) {
+                       regaddr = frame + 20;
+                       for (i=0; i<reg; i++) {
+                               if (mask & 0x10000)
+                                       regaddr += WORDSIZE;
+                               mask = mask >> 1;
                        }
                        }
-                       if ((sl_class & STABMASK) != N_SSYM) {
-                               error("Not a structure element");
+                       if (!(mask & 0x10000)) {
+                               error("Stackreg error: contents");
                                return(-1);
                        }
                                return(-1);
                        }
-                       addr += sl_addr;
-                       subflag = 0;
-               }
-               if (eqany(*p, "->") != '\0') {
-                       addr = getindir(class, addr, sl_type);
-                       class = N_GSYM;
-                       if (debug) printf("Address %d after getval\n", addr);
-                       for (; eqany(*p, "->"); p++) ;
-                       if (*p == '\0') break;
-                       if (localflag ||
-                                  slookup(p, adrtostoffset(callpc-1)) == -1) {
-                               if (globallookup(p, findfile(curfile)->stf_offset) == -1) {     
-                                       if (localflag)
-                                               printf("%s not found\n", var);
-                                       else
-                                               printf("%.8s:%s not found\n", proc, var);
-                                       return(-1);
-                               }
-                       }
-                       addr += sl_addr;
-                       subflag = 0;
-               }
-               if (*p == '[' && *(p+1) != '\0') {
-                       long i;
-                       p++;
-                       i = readint(&p);
-                       if (debug) printf("Size %d\n", typetosize(sl_type, sl_size));
-                       addr = getindir(class, addr, sl_type);
-                       addr += typetosize(sl_type, sl_size)*i;  
-                       class = N_GSYM;
-                       subflag++;
                }
        }
                }
        }
-       return(addr);
+       return(regaddr);
 }
 
 }
 
-/* displays value of proc:var, returns its address */
+/* returns address of proc:var. Sets externals class and subflag */
 ADDR
 ADDR
-dispvar(proc, var, fmt)
-char *proc, *var, *fmt; {
-       ADDR addr;
-       addr = varaddr(proc, var);
-       if (addr == -1) return(-1);
-       
-       prvar(sl_type, addr, fmt, class, subflag);
-       
-       return(addr);
+varaddr(proc, var)
+char *proc, *var; {
+       return(findvar(proc, var, "", 0));
 }
 
 }
 
-prvar(type, addr, fmt, class, subflag) 
-ADDR addr;
-char *fmt, class; short type; {
-
-       dispf(addr, fmt, class, type, subflag);
+/*
+ * displays values of variables matching proc:var, 
+ * returns its address
+ */
+ADDR
+dispvar(proc, var, fmt)
+char *proc, *var, *fmt; {
+       return(findvar(proc, var, fmt, 1));
 }
 
 }
 
-prdebug() {
+/*
+ * Find and print values of all variables matching proc:var
+ *     using specified format.
+ * Returns address of last matching variable.
+ *
+ * prvar==0 => no output,
+ * prvar==1 => output value,
+ * prvar==2 => output addr
+ */
+ADDR
+findvar(proc, var, fmt, prvar)
+char *proc, *var, *fmt; {
+       ADDR addr = -1, a = -1;
+       int metaflag = 0, match=0, nullflag=0, depthcnt = -1;
+       char *comblk;
        register struct proct *procp;
        register struct proct *procp;
-       register struct filet *filep;
-       
-       printf("dot=%d\n", dot);
-       printf("extstart = %d\n", extstart);
-       for(filep=files;filep->sfilename[0];filep++)
-               printf("%s offs %d @ %d flag %d addr %d\n", filep->sfilename, filep->stf_offset, filep, filep->lineflag, filep->faddr);
-       for(procp=procs;procp->pname[0];procp++)
-               printf("%8.8s addr %d; offs %d; sfptr %d; line %d\n",
-                       procp->pname, procp->paddr, procp->st_offset, procp->sfptr,
-                       procp->lineno);
-}
 
 
-/* display addr using format desc or class s */
-char pd[] = "%x\n";
-dispf(addr, desc, class, type, subflag)
-char *desc; short type; ADDR addr; {
-       int i;
-       char *p;
-       char dlen, dfmt;
-       long value;
-       union {
-               struct {
-                       char c[WORDSIZE]; 
-                       };
-               struct {
-                       int w;
-               };
-               struct {
-                       float f;
-               }
-       } word;
-       union {
-               struct{
-                       int w1, w2;
-               };
-               struct {
-                       double d;
-               };
-       } dbl;
-
-       class &= STABMASK;
-       if (desc[0]  == '\0') desc = typetodesc(type, subflag);
-       odesc = desc;
-       otype = type;
-       oclass = class;
-       if (debug) printf("dispf(%d,%s,0%o,0%o)\n", addr,desc,class,type);
-       pd[1] = dfmt = 'd';
-       dlen = '\0';
-       for (p = desc; *p; p++) {
-               switch (*p) {
-                       case 'l':
-                       case 'h':
-                       case 'b':
-                               dlen = *p;
-                               break;
+       if (percentflag) {      /* kludge for register names */
+               return(regout(var, prvar, fmt));
+       }
 
 
-                       case 'c':
-                       case 'd':
-                       case 'o':
-                       case 'x':
-                       case 'u':
-                       case 's':
-                       case 'a':
-                       case 'f':
-                       case 'g':
-                               pd[1] = dfmt = *p;
-                               break;
+       if (var[0] == '\0') {
+               error("Unexpected null variable name");
+               return(-1);
+       }
 
 
-                       default:
-                               printf("Illegal descriptor: %c\n", *p);
-                               return;
-                       }
-               }
-               
-               switch (dfmt) {
-               default:
-                       if (class == N_RSYM) {
-                               if ((addr > 0 && addr < 6) || addr > 11) {
-                                       printf("Bad register var %d\n", addr);
-                                       return;
-                               }
-                               value = *(ADDR *)(((ADDR) &u) + R0 + (WORDSIZE)*addr);
-                       }
-                       else {
-                               value = getval(addr, dfmt);
-                       }
+       metaflag = eqany('*', proc) || eqany('?', proc) ||
+               eqany('*', var) || eqany('?', var);
+       
+       if (proc[0] == '\0') {
+               nullflag++;
+               proc = curproc()->pname;
+       }
 
 
-                       switch (dfmt) {
-                       case 'u':
-                       case 'x':
-                       case 'o':
-                               switch (dlen) {
-                               case 'h':
-                                       value = (unsigned short) value;
-                                       break;
-                               case 'b':
-                                       value = (unsigned char) value;
-                                       break;
-                               case 'l':
-                                       value = (unsigned long) value;
-                                       break;
-                               }
-                               break;
+       comblk = colonflag ? "" : "*";
 
 
-                       default:
-                               switch (dlen) {
-                               case 'h':
-                                       value = (short) value;
-                                       break;
-                               case 'b':
-                                       value = (char) value;
-                                       break;
-                               case 'l':
-                                       value = (long) value;
-                                       break;
-                               }
-                       }
-                       if (value > 0) {
-                               if (value > 9  &&  dfmt == 'x')
-                                       printf("0x");
-                               else if (value > 7  &&  dfmt == 'o')
-                                       printf("0");
-                       }
-                       if (dfmt == 'c') {
-                               if ((value & 0177) < ' ') 
-                                       printf("^%c\n", value + ('A' - 1));
-                               else if ((value & 0177) == 0177)
-                                       printf("^?\n");
-                               else
-                                       printf(pd, value);
-                       } else
-                               printf(pd, value);
-                       return;
-                       
-               case 'f':
-                       pd[1] = 'g';
-                       word.w = getval(addr,dfmt);
-                       printf(pd, word.f);
-                       return;
-
-               case 'g':
-                       pd[1] = 'g';
-                       dbl.w1 = getval(addr, dfmt);
-                       dbl.w2 = getval(addr+WORDSIZE, dfmt);
-                       printf(pd, dbl.d);
-                       return;
-
-               case 's':
-                       addr = getindir(class, addr, type);
-                               
-               case 'a':
-                       for (;;) {
-                               word.w = getval(addr, 'd');
-                               for (i=0; i<WORDSIZE; i++) {
-                                       if (word.c[i] == 0) goto l1;
-                                       printf("%c", word.c[i]);
+       if (integ && !eqany(var[0], "->.[")) {  
+               depthcnt = integ;
+       }
+       if (integ) {
+               if (eqany(var[0], "->.[")) 
+                       match++;
+               else
+                       depthcnt = integ;
+       }
+
+       procp = initframe();
+       if (!eqany(var[0], "->.[") && !(nullflag && colonflag)) {
+               do {
+                       if (eqpat(proc, procp->pname)) {
+                               match++;
+                               if (--depthcnt==0 || integ==0) {
+                                       a = outvar(procp->pname, var, fmt,
+                                               metaflag, integ, N_GSYM, 
+                                               0, prname, comblk, prvar);
+                                       if (a != -1)
+                                               addr = a;
+                                       if (depthcnt == 0)
+                                               break;
                                }
                                }
-                               addr += WORDSIZE;
                        }
                        }
-
-       l1:     printf("\n");
-               return;
+               } while ((procp=nextframe()) != badproc);
        }
        }
-}
 
 
-/* print breakpoints */
-prbkpt() {
-       register BKPTR bkptr;
-       register int cnt;
-
-       cnt = 0;
-       
-       for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt)
-               if (bkptr->flag) {
-                       cnt++;
-                       printf("%.8s:%d\n", adrtoprocp(bkptr->loc)->pname,
-                               adrtolineno(bkptr->loc));
+       if ((colonflag || metaflag || a == -1) && 
+                       (nullflag || eqpat(proc, ""))) {
+               a = outvar("", var, fmt, metaflag, integ,
+                       N_GSYM, 0, prname, comblk, prvar);
+               if (a != -1) {
+                       addr = a;
+                       match++;
                }
                }
-       if (cnt == 0) 
-               printf("No breakpoints set\n");
-}
-
-idbkpt() {
-       register BKPTR bkptr;
-       register int yesflg, cnt;
-       register char c;
-       
-       cnt = 0;
+       }
 
 
-       for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt)
-               if (bkptr->flag) {
-                       printf("%.8s:%d ? ", adrtoprocp(bkptr->loc)->pname,
-                               adrtolineno(bkptr->loc));
-                       yesflg = 0;
-                       cnt++;
-                       do {
-                               c = getchar();
-                               if (c == 'y' || c == 'd') yesflg++;
-                       } while (c != '\n');
-                       if (yesflg)
-                               bkptr->flag = 0;
+       if (match==0 && colonflag) {
+               procp = initframe();
+               do {
+                       if (eqstr(curproc()->pname, procp->pname))
+                               break;
+               } while ((procp=nextframe()) != badproc);
+               a = outvar(curproc()->pname, var, fmt, metaflag,
+                       integ, N_GSYM, 0, prname, 
+                       nullflag ? "_BLNK_" : proc, prvar);
+               if (a != -1) {
+                       addr = a;
+                       match++;
                }
                }
-       if (cnt == 0)
-               printf("No breakpoints set\n");
+       }
+
+       if (addr == -1 && match == 0) {
+               addr = extoutvar(var, fmt, metaflag, prvar);
+               if (addr != -1)
+                       return(addr);
+       }
+       if (match == 0) {
+               printf("%s not an active procedure\n", proc);
+               return(-1);
+       }
+       if (addr == -1) {
+               if (var[0] == '.')
+                       var++;
+               if (proc[0])
+#ifndef FLEXNAMES
+                       printf("%.16s:%s not found\n", proc, var);
+#else
+                       printf("%s:%s not found\n", proc, var);
+#endif
+               else
+                       printf("%s not found\n", var);
+               return(-1);
+       }
+       return(addr);
 }
 
 char *
 }
 
 char *
@@ -476,19 +270,21 @@ short type; {
        
        ptr = ftn = ary = 0;
        
        
        ptr = ftn = ary = 0;
        
-       for (;; type = DECREF(type)) {
+       desc = typedesc[type&BTMASK];
+       for (; type & TMASK; type = DECREF(type)) {
                if (ISPTR(type)) ptr++;
                else if (ISFTN(type)) ftn++;
                else if (ISARY(type)) ary++;
                if (ISPTR(type)) ptr++;
                else if (ISFTN(type)) ftn++;
                else if (ISARY(type)) ary++;
-               else {
-                       desc = typedesc[type];
-                       break;
-               }
        }
        
        }
        
-       if ((ptr-subflag == 1  || ary-subflag == 1)  &&  desc[0] == 'c') return("s");
-       if (debug) printf ("PTR %d; FTN %d; ARY %d; DESC %s\n",ptr,ftn,ary,desc);
+       if ((ptr-subflag == 1  || ary-subflag == 1)  &&  desc[0] == 'c')
+               return("s");
+       if (debug)
+               printf ("PTR %d; FTN %d; ARY %d; DESC %s\n",ptr,ftn,ary,desc);
+       if (ptr + ary ==  subflag)
+               return(desc);
        if (ptr) return("x");
        if (ptr) return("x");
+       if (ptr==1 && ftn==1) return("p");
        return(desc);
 }
 
        return(desc);
 }
 
@@ -519,18 +315,211 @@ short type; {
        
        ptr = ftn = ary = 0;
        
        
        ptr = ftn = ary = 0;
        
-       for (;; type = DECREF(type)) {
+       size = typesize[type&BTMASK];
+       for (; type & TMASK; type = DECREF(type)) {
                if (ISPTR(type)) ptr++;
                else if (ISFTN(type)) ftn++;
                else if (ISARY(type)) ary++;
                if (ISPTR(type)) ptr++;
                else if (ISFTN(type)) ftn++;
                else if (ISARY(type)) ary++;
-               else {
-                       size = typesize[type];
-                       break;
-               }
        }
        
        }
        
-       if (debug) printf ("PTR %d; FTN %d; ARY %d; SIZE %d; STSIZE %d\n",ptr,ftn,ary,size,stsize);
+       if (debug)
+               printf ("PTR %d; FTN %d; ARY %d; SIZE %d; STSIZE %d\n",
+                               ptr,ftn,ary,size,stsize);
        if (ptr>1) return(4);
        if (ptr>1) return(4);
-       if (size == 0) return(stsize ? stsize : 1);
+       if (size == 0) return(stsize);
        else return(size);
 }
        else return(size);
 }
+
+
+/* print breakpoints */
+prbkpt() {
+       register BKPTR bkptr;
+       register int cnt;
+       char *cmdp;
+
+       cnt = 0;
+       
+       for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt)
+               if (bkptr->flag) {
+                       cnt++;
+                       printbkpt("", adrtoprocp(bkptr->loc), bkptr->loc);
+                       cmdp = bkptr->comm;
+                       if (*cmdp != '\n') {
+                               printf("   <");
+                               while (*cmdp != '\n')
+                                       printf("%c", *cmdp++);
+                               printf(">\n");
+                       }
+                       else
+                               printf("\n");
+               }
+       if (cnt == 0) 
+               printf("No breakpoints set\n");
+}
+
+/* interactively delete breakpoints */
+
+idbkpt() {
+       register BKPTR bkptr;
+       register int yesflg, cnt;
+       register char c;
+       
+       cnt = 0;
+
+       for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt)
+               if (bkptr->flag) {
+                       printbkpt(" ? ", adrtoprocp(bkptr->loc), bkptr->loc);
+                       yesflg = 0;
+                       cnt++;
+                       do {
+                               c = getchar();
+                               if (c == 'y' || c == 'd') yesflg++;
+                       } while (c != '\n');
+                       if (yesflg)
+                               bkptr->flag = 0;
+               }
+       if (cnt == 0)
+               printf("No breakpoints set\n");
+}
+
+/* delete all breakpoints */
+
+dabkpt() {
+       register BKPTR bkptr;
+       
+       for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt)
+               bkptr->flag = 0;
+}
+/* 
+ * Print name of breakpoint for a, b, d commands:
+ */
+printbkpt(s, procp, dot)
+char *s; struct proct *procp; ADDR dot; {
+       adrtolineno(dot);
+       if (dot != lnfaddr)
+               printf("0x%x (", dot);
+       prlnoff(procp, dot);
+       if (dot != lnfaddr)
+               printf(")");
+       printf("%s", s);
+}
+
+/* print call frame */
+prframe() {
+       prfrx(0);
+}
+
+/* set top to print just the top procedure */
+prfrx(top) {
+       int narg;
+       long offset;
+       register char class;
+       register int endflg;
+       char *p;
+       struct proct *procp;
+       struct nlist stentry;
+       
+       if ((procp = initframe()) == badproc) return;
+       do {
+               if (get(frame+12, DSP) == 0) return;
+               p = procp->pname;
+               if (eqstr("__dbsubc", p)) return;
+               if (p[0] == '_') {
+                       endflg = 1;
+#ifndef FLEXNAMES
+                       printf("%.15s(", p+1);
+#else
+                       printf("%s(", p+1);
+#endif
+               }
+               else {
+#ifndef FLEXNAMES
+                       printf("%.16s(", p);
+#else
+                       printf("%s(", p);
+#endif
+                       endflg = 0;
+               }
+               if (endflg == 0) {
+                       offset = procp->st_offset;
+                       blseek(&sbuf, offset, 0);
+                       do {
+                               if (bread(&sbuf, &stentry, sizeof stentry) <
+                                                       sizeof stentry) {
+                                       endflg++;
+                                       break;
+                               }
+                               class = stentry.n_type & STABMASK;
+                       } while (class == N_FUN);
+                       while (class != N_PSYM) {
+                               if (bread(&sbuf, &stentry, sizeof stentry) <
+                                                       sizeof stentry) {
+                                       endflg++;
+                                       break;
+                               }
+                               class = stentry.n_type & STABMASK;
+                               if (class == N_FUN) {
+                                       endflg++;
+                                       break;
+                               }
+                       }
+               }
+
+               narg = get(argp, DSP);
+               if (narg & ~0xff) narg = 0;
+               argp += WORDSIZE;
+               while (narg) {
+                       if (endflg) {
+                               printf("%d", get(argp, DSP));
+                               argp += 4;
+                       } else {
+                               int length;
+#ifndef FLEXNAMES
+                               printf("%.16s=", stentry.n_name);
+#else
+                               printf("%s=", stentry.n_un.n_name);
+#endif
+                               dispx(argp, "", N_GSYM, stentry.n_desc,
+                                       0, 0, DSP);
+                               length = typetosize(stentry.n_desc, 0);
+                               if (length > WORDSIZE)
+                                       argp += length;
+                               else
+                                       argp += WORDSIZE;
+                       }
+                       do {
+                               if (endflg) break;
+                               if (bread(&sbuf, &stentry, sizeof stentry) <
+                                                       sizeof stentry) {
+                                       endflg++;
+                                       break;
+                               }
+                               class = stentry.n_type & STABMASK;
+                               if (class == N_FUN) {
+                                       endflg++;
+                                       break;
+                               }
+                       } while (class != N_PSYM);
+               l1:     if (--narg != 0) printf(",");
+               }
+               printf(")");
+               if (debug) printf("  @ 0x%x ", callpc);
+               if (procp->sfptr != badfile)
+                       printf("   [%s:%d]", adrtofilep(callpc-1)->sfilename,
+                               adrtolineno(callpc-1));
+               printf("\n");
+       } while (((procp = nextframe()) != badproc) && !top);
+}
+
+INT            signo;
+STRING         signals[];
+extern nsig;
+sigprint()
+{
+
+       if (signo < nsig)
+               printf("%s", signals[signo]);
+       else
+               printf("signal %d???", signals[signo]);
+}