+#
+/*
+
+ C debugger
+
+*/
+
+#include "/usr/sys/param.h"
+#include "/usr/sys/user.h"
+
+int fcore;
+int fsym;
+int symoff;
+char *lp;
+int errflg;
+int symlen;
+int symct;
+char symbol[8];
+int symflg;
+int symval;
+char ssymbol[8];
+int ssymflg;
+int ssymval;
+char line[128];
+int regbuf[512];
+char **uregs ®buf[512];
+char *rtsize;
+int pc -2;
+int r5 -9;
+int dot;
+int tdot;
+int dotinc 2;
+int lastcom '/';
+int lastype 'o';
+char *symfil "a.out";
+char *corfil "core";
+int callist[50];
+int *callp &callist[0];
+
+main(argc, argv)
+char **argv;
+{
+ int onintr();
+
+ if (argc==2)
+ symfil = argv[1];
+ if (argc>2) {
+ corfil = argv[1];
+ symfil = argv[2];
+ }
+ if ((fcore = open(corfil, 0)) < 0) {
+ printf("%s not found\n", corfil);
+ return;
+ }
+ if ((fsym = open(symfil, 0)) < 0) {
+ printf("%s not found\n", symfil);
+ return;
+ }
+ read(fsym, regbuf, 020);
+ if (regbuf[0]!=0410 && regbuf[0]!=0407) { /* magic */
+ printf("Bad format: %s\n", symfil);
+ return;
+ }
+ symoff = regbuf[1] + regbuf[2];
+ symlen = regbuf[4];
+ if (regbuf[7] != 1)
+ symoff =<< 1;
+ symoff =+ 020;
+ read(fcore, regbuf, 1024);
+ regbuf->u_tsize =<< 6;
+ regbuf->u_dsize =<< 6;
+ regbuf->u_ssize =<< 6;
+ rtsize = (regbuf->u_tsize+017777) & ~017777;
+ setexit();
+ signal(2, onintr);
+loop:
+ if (errflg) {
+ printf("?\n");
+ errflg = 0;
+ }
+ lp = line;
+ while ((*lp = getchar()) != '\n')
+ if (*lp++ == '\0')
+ return;
+ lp = line;
+ command();
+ goto loop;
+}
+
+command()
+{
+ register adrflg, n;
+
+ adrflg = expr();
+ if (errflg)
+ return;
+ n = getcnt();
+ if (lastcom=='$')
+ lastcom = '/';
+ if (*lp == '\n') {
+ if (!adrflg)
+ dot =+ dotinc;
+ } else
+ lastcom = *lp++;
+ if (*lp != '\n')
+ lastype = *lp++;
+ if (*lp != '\n') {
+ errflg++;
+ return;
+ }
+ if (adrflg)
+ dot = tdot;
+ while(n) {
+ scommand(n);
+ if (errflg)
+ return;
+ if (--n)
+ dot =+ dotinc;
+ }
+}
+
+scommand(n)
+{
+ register w, c;
+ double fw;
+ struct { int i[4]; };
+
+ switch(lastcom) {
+
+ case '/':
+ w = cget(dot);
+ switch(lastype) {
+
+ case 'o':
+ printf("%.1o\n", w);
+ dotinc = 2;
+ return;
+
+ case 'i':
+ printf("%d\n", w);
+ dotinc = 2;
+ return;
+
+ case 'f':
+ fw = 0.0;
+ fw.i[0] = w;
+ fw.i[1] = cget(dot+2);
+ printf("%e\n", fw);
+ dotinc = 4;
+ return;
+
+ case 'd':
+ fw.i[0] = w;
+ fw.i[1] = cget(dot+2);
+ fw.i[2] = cget(dot+4);
+ fw.i[3] = cget(dot+6);
+ printf("%e\n", fw);
+ dotinc = 8;
+ return;
+ }
+ errflg++;
+ return;
+
+ case '\\':
+ printf("%.1o\n", cget(dot) & 0377);
+ dotinc = 1;
+ return;
+
+ case '=':
+ printf("%.1o\n", dot);
+ return;
+
+ case '\'':
+ printc(cget(dot) & 0377);
+ if (n<=1)
+ putchar('\n');
+ dotinc = 1;
+ return;
+
+ case '"':
+ w = cget(dot);
+ while(c = cget(w++)&0377)
+ printc(c);
+ putchar('\n');
+ return;
+
+ case '&':
+ vallook(cget(dot));
+ if (errflg)
+ reset();
+ printf("%.8s\n", ssymbol);
+ return;
+
+ case '$':
+ printtrace();
+ return;
+ }
+ errflg++;
+}
+
+getcnt()
+{
+ register t1, t2;
+
+ if (*lp != ',')
+ return(1);
+ lp++;
+ t1 = tdot;
+ if (expr() == 0) {
+ tdot = t1;
+ return(1);
+ }
+ t2 = tdot;
+ tdot = t1;
+ return(t2);
+}
+
+cget(n)
+{
+ register w;
+
+ w = get(n);
+ if (errflg)
+ reset();
+ return(w);
+}
+
+printc(c)
+{
+ if (c<' ' || c>'}')
+ printf("\\%o", c);
+ else
+ printf("%c", c);
+}
+
+expr()
+{
+ char tsym[10];
+ int i, t1, t2, donef, adrflg, lastop, b;
+
+ tdot = 0;
+ adrflg = 0;
+ lastop = '+';
+ ssymval = 0;
+ donef = 0;
+loop:
+ if (*lp >= 'a' && *lp <= 'z' || *lp=='_') {
+ i = 0;
+ tsym[i++] = '_';
+ adrflg++;
+ while(*lp>='a'&&*lp<='z' || *lp>='0'&&*lp<='9' || *lp=='_') {
+ if (i < 8)
+ tsym[i++] = *lp;
+ lp++;
+ }
+ while (i<8)
+ tsym[i++] = '\0';
+ if (symlook(tsym) == 0) {
+ errflg++;
+ reset();
+ }
+ goto loop;
+ }
+ if (*lp>='0' && *lp<='9') {
+ adrflg++;
+ ssymval = 0;
+ if (*lp == '0')
+ b = 8;
+ else
+ b = 10;
+ while (*lp>='0' && *lp<='9') {
+ ssymval =* b;
+ ssymval =+ *lp++ -'0';
+ }
+ goto loop;
+ }
+ switch (*lp) {
+
+ default:
+ donef++;
+
+ case '+':
+ case '-':
+ switch(lastop) {
+
+ case '+':
+ tdot =+ ssymval;
+ goto op;
+
+ case '-':
+ tdot =- ssymval;
+
+ op:
+ if (donef)
+ return(adrflg);
+ else
+ lastop = *lp++;
+ }
+ goto loop;
+
+ case ' ':
+ case '\t':
+ lp++;
+ goto loop;
+
+ case '(':
+ lp++;
+ adrflg++;
+ t1 = tdot;
+ ssymval = getarg();
+ tdot = t1;
+ goto loop;
+
+ case '[':
+ lp++;
+ t1 = ssymval;
+ t2 = tdot;
+ if (expr() == 0)
+ tdot = 0;
+ ssymval = get(t1 + (tdot<<1));
+ if (errflg)
+ reset();
+ tdot = t2;
+ if (*lp == ']')
+ lp++;
+ goto loop;
+ }
+}
+
+getarg()
+{
+ register level, arg, t1;
+
+ t1 = tdot;
+ expr();
+ level = tdot;
+ if (*lp++ != ',')
+ error();
+ expr();
+ arg = tdot;
+ if (*lp++ != ')')
+ error();
+ if (level >= callp-callist)
+ error();
+ ssymval = callist[level] - 8 - 2*arg;
+ tdot = t1;
+}
+error()
+{
+ errflg++;
+ reset();
+}
+
+printtrace()
+{
+ int tpc, tr5, narg, argp, i;
+
+ tpc = uregs[pc];
+ tr5 = uregs[r5];
+ if (symlook("savr5"))
+ if (narg = get(ssymval))
+ tr5 = narg;
+ callp = &callist[0];
+ while (errflg == 0) {
+ narg = findroutine(tpc, tr5);
+ printf("%2d: %.8s(", callp-callist, ssymbol);
+ if (--narg >= 0)
+ printf("%.1o", get(tr5+4));
+ argp = tr5+4;
+ while(--narg >= 0)
+ printf(",%.1o", get(argp =+ 2));
+ printf(")\n");
+ tpc = get(tr5+2);
+ if (callp < &callist[50])
+ *callp++ = tr5;
+ if ((tr5 = get(tr5)) == 0)
+ break;
+ }
+}
+
+findroutine(rpc, rr5)
+{
+ int callpt, inst, narg;
+
+ callpt = get(rr5+2);
+ if ((inst=get(callpt-4)) == 04737) /* jsr pc,*$... */
+ narg = 1;
+ else if ((inst&~077)==04700) /* jsr pc,... */
+ narg = 0;
+ else {
+ errflg++;
+ return(0);
+ }
+ vallook((inst==04767?callpt:0) + get(callpt-2));
+ inst = get(callpt);
+ if (inst == 05726) /* tst (sp)+ */
+ return(narg+1);
+ if (inst == 022626) /* cmp (sp)+,(sp)+ */
+ return(narg+2);
+ if (inst == 062706) /* add $n,sp */
+ return(narg+get(callpt+2)/2);
+ return(narg);
+}
+
+symlook(symstr)
+char *symstr;
+{
+ symset();
+ while(symget()) {
+ if (eqstr(symbol, symstr)) {
+ savsym();
+ return(1);
+ }
+ }
+ return(0);
+}
+
+eqstr(as1, as2)
+int *as1, *as2;
+{
+ register int *s1, *s2, *es1;
+
+ s1 = as1;
+ s2 = as2;
+ for (es1 = s1+4; s1 < es1; )
+ if (*s1++ != *s2++)
+ return(0);
+ return(1);
+}
+
+vallook(value)
+{
+ symset();
+ while(symget())
+ if (symval == value && (symflg&037) == 2) {
+ savsym('_');
+ return;
+ }
+ errflg++;
+}
+
+get(aaddr)
+char *aaddr;
+{
+ int w;
+ register char *addr;
+
+ addr = aaddr;
+ w = 0;
+ if (addr < regbuf->u_tsize) {
+ seek(fsym, addr+020, 0);
+ if (read(fsym, &w, 2) != 2)
+ errflg++;
+ return(w);
+ }
+ if (addr < rtsize+regbuf->u_dsize)
+ addr =- rtsize;
+ else if (-addr < regbuf->u_ssize)
+ addr =+ regbuf->u_dsize + regbuf->u_ssize;
+ else
+ errflg++;
+ seek(fcore, addr+1024, 0);
+ if (read(fcore, &w, 2) < 2)
+ errflg++;
+ return(w);
+}
+
+symset()
+{
+ symct = symlen;
+ seek(fsym, symoff, 0);
+}
+
+symget()
+{
+ if ((symct =- 12) < 0)
+ return(0);
+ return(read(fsym, symbol, 12) == 12);
+}
+
+savsym(skip)
+{
+ int ch;
+ char *p, *q;
+
+ p = symbol;
+ q = ssymbol;
+ while (p<symbol+8 && (ch = *p++)) {
+ if (ch == skip)
+ continue;
+ *q++ = ch;
+ }
+ while (q < ssymbol+8)
+ *q++ = '\0';
+ ssymflg = symflg;
+ ssymval = symval;
+}
+
+onintr()
+{
+ putchar('\n');
+ errflg++;
+ reset();
+}