summaryrefslogtreecommitdiff
path: root/sys/src/cmd/qi/cmd.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/qi/cmd.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/qi/cmd.c')
-rwxr-xr-xsys/src/cmd/qi/cmd.c644
1 files changed, 644 insertions, 0 deletions
diff --git a/sys/src/cmd/qi/cmd.c b/sys/src/cmd/qi/cmd.c
new file mode 100755
index 000000000..02fc422e7
--- /dev/null
+++ b/sys/src/cmd/qi/cmd.c
@@ -0,0 +1,644 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include <bio.h>
+#include <mach.h>
+#define Extern extern
+#include "power.h"
+
+char buf[128], lastcmd[128];
+char fmt = 'X';
+int width = 60;
+int inc;
+
+ulong expr(char*);
+ulong expr1(char*);
+char* term(char*, ulong*);
+
+char *
+nextc(char *p)
+{
+ while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
+ p++;
+
+ if(*p == '\n')
+ *p = '\0';
+
+ return p;
+}
+
+char *
+numsym(char *addr, ulong *val)
+{
+ char tsym[128], *t;
+ static char *delim = "`'<>/\\@*|-~+-/=?\n";
+ Symbol s;
+ char c;
+
+ t = tsym;
+ while(c = *addr) {
+ if(strchr(delim, c))
+ break;
+ *t++ = c;
+ addr++;
+ }
+ t[0] = '\0';
+
+ if(strcmp(tsym, ".") == 0) {
+ *val = dot;
+ return addr;
+ }
+
+ if(lookup(0, tsym, &s))
+ *val = s.value;
+ else {
+ if(tsym[0] == '#')
+ *val = strtoul(tsym+1, 0, 16);
+ else
+ *val = strtoul(tsym, 0, 0);
+ }
+ return addr;
+}
+
+ulong
+expr(char *addr)
+{
+ ulong t, t2;
+ char op;
+
+ if(*addr == '\0')
+ return dot;
+
+ addr = numsym(addr, &t);
+
+ if(*addr == '\0')
+ return t;
+
+ addr = nextc(addr);
+ op = *addr++;
+ numsym(addr, &t2);
+ switch(op) {
+ default:
+ Bprint(bioout, "expr syntax\n");
+ return 0;
+ case '+':
+ t += t2;
+ break;
+ case '-':
+ t -= t2;
+ break;
+ case '%':
+ t /= t2;
+ break;
+ case '&':
+ t &= t2;
+ break;
+ case '|':
+ t |= t2;
+ break;
+ }
+
+ return t;
+}
+
+int
+buildargv(char *str, char **args, int max)
+{
+ int na = 0;
+
+ while (na < max) {
+ while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
+ str++;
+
+ if(*str == '\0')
+ return na;
+
+ args[na++] = str;
+ while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
+ str++;
+
+ if(*str == '\n')
+ *str = '\0';
+
+ if(*str == '\0')
+ break;
+
+ *str++ = '\0';
+ }
+ return na;
+}
+
+void
+colon(char *addr, char *cp)
+{
+ int argc;
+ char *argv[100];
+ char tbuf[512];
+
+ cp = nextc(cp);
+ switch(*cp) {
+ default:
+ Bprint(bioout, "?\n");
+ return;
+ case 'b':
+ breakpoint(addr, cp+1);
+ return;
+
+ case 'd':
+ delbpt(addr);
+ return;
+
+ /* These fall through to print the stopped address */
+ case 'r':
+ reset();
+ argc = buildargv(cp+1, argv, 100);
+ initstk(argc, argv);
+ count = 0;
+ atbpt = 0;
+ run();
+ break;
+ case 'c':
+ count = 0;
+ atbpt = 0;
+ run();
+ break;
+ case 's':
+ cp = nextc(cp+1);
+ count = 0;
+ if(*cp)
+ count = strtoul(cp, 0, 0);
+ if(count == 0)
+ count = 1;
+ atbpt = 0;
+ run();
+ break;
+ }
+
+ dot = reg.pc;
+ Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
+ symoff(tbuf, sizeof(tbuf), dot, CTEXT);
+ Bprint(bioout, tbuf);
+ if(fmt == 'z')
+ printsource(dot);
+
+ Bprint(bioout, "\n");
+}
+
+
+void
+dollar(char *cp)
+{
+ cp = nextc(cp);
+ switch(*cp) {
+ default:
+ Bprint(bioout, "?\n");
+ break;
+
+ case 'c':
+ case 'C':
+ stktrace(*cp);
+ break;
+
+ case 'b':
+ dobplist();
+ break;
+
+ case 'r':
+ dumpreg();
+ break;
+
+ case 'R':
+ dumpreg();
+ /* fall through */
+
+ case 'f':
+ dumpfreg();
+ break;
+
+ case 'F':
+ dumpdreg();
+ break;
+
+ case 'q':
+ exits(0);
+ break;
+
+ case 'Q':
+ isum();
+ segsum();
+ break;
+
+ case 't':
+ cp++;
+ switch(*cp) {
+ default:
+ Bprint(bioout, ":t[0sic]\n");
+ break;
+ case '\0':
+ trace = 1;
+ break;
+ case '0':
+ trace = 0;
+ sysdbg = 0;
+ calltree = 0;
+ break;
+ case 's':
+ sysdbg = 1;
+ break;
+ case 'i':
+ trace = 1;
+ break;
+ case 'c':
+ calltree = 1;
+ break;
+ }
+ break;
+
+ case 'i':
+ cp++;
+ switch(*cp) {
+ default:
+ Bprint(bioout, "$i[isa]\n");
+ break;
+ case 'i':
+ isum();
+ break;
+ case 's':
+ segsum();
+ break;
+ case 'a':
+ isum();
+ segsum();
+ iprofile();
+ break;
+ case 'p':
+ iprofile();
+ break;
+ }
+ }
+}
+
+int
+pfmt(char fmt, int mem, ulong val)
+{
+ int c, i;
+ Symbol s;
+ char *p, ch, str[1024];
+
+ c = 0;
+ switch(fmt) {
+ default:
+ Bprint(bioout, "bad modifier\n");
+ return 0;
+ case 'o':
+ c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
+ inc = 2;
+ break;
+
+ case 'O':
+ c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
+ inc = 4;
+ break;
+
+ case 'q':
+ c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
+ inc = 2;
+ break;
+
+ case 'Q':
+ c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
+ inc = 4;
+ break;
+
+ case 'd':
+ c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
+ inc = 2;
+ break;
+
+
+ case 'D':
+ c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
+ inc = 4;
+ break;
+
+ case 'x':
+ c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
+ inc = 2;
+ break;
+
+ case 'X':
+ c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
+ inc = 4;
+ break;
+
+ case 'u':
+ c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
+ inc = 2;
+ break;
+
+ case 'U':
+ c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
+ inc = 4;
+ break;
+
+ case 'b':
+ c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
+ inc = 1;
+ break;
+
+ case 'c':
+ c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
+ inc = 1;
+ break;
+
+ case 'C':
+ ch = mem ? getmem_b(dot) : val;
+ if(isprint(ch))
+ c = Bprint(bioout, "%c ", ch);
+ else
+ c = Bprint(bioout, "\\x%.2x ", ch);
+ inc = 1;
+ break;
+
+ case 's':
+ i = 0;
+ while(ch = getmem_b(dot+i))
+ str[i++] = ch;
+ str[i] = '\0';
+ dot += i;
+ c = Bprint(bioout, "%s", str);
+ inc = 0;
+ break;
+
+ case 'S':
+ i = 0;
+ while(ch = getmem_b(dot+i))
+ str[i++] = ch;
+ str[i] = '\0';
+ dot += i;
+ for(p = str; *p; p++)
+ if(isprint(*p))
+ c += Bprint(bioout, "%c", *p);
+ else
+ c += Bprint(bioout, "\\x%.2ux", *p);
+ inc = 0;
+ break;
+
+ case 'Y':
+ p = ctime(mem ? getmem_b(dot) : val);
+ p[30] = '\0';
+ c = Bprint(bioout, "%s", p);
+ inc = 4;
+ break;
+
+ case 'a':
+ symoff(str, sizeof(str), dot, CTEXT);
+ Bprint(bioout, "%s", str);
+ inc = 0;
+ break;
+
+ case 'e':
+ for (i = 0; globalsym(&s, i); i++)
+ Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
+ inc = 0;
+ break;
+
+ case 'I':
+ case 'i':
+ inc = machdata->das(symmap, dot, fmt, str, sizeof(str));
+ if (inc < 0) {
+ Bprint(bioout, "qi: %r\n");
+ return 0;
+ }
+ c = Bprint(bioout, "\t%s", str);
+ break;
+
+ case 'n':
+ c = width+1;
+ inc = 0;
+ break;
+
+ case '-':
+ c = 0;
+ inc = -1;
+ break;
+
+ case '+':
+ c = 0;
+ inc = 1;
+ break;
+
+ case '^':
+ c = 0;
+ if(inc > 0)
+ inc = -inc;
+ break;
+
+ case 'z':
+ if (findsym(dot, CTEXT, &s))
+ Bprint(bioout, " %s() ", s.name);
+ printsource(dot);
+ inc = 0;
+ break;
+ }
+ return c;
+}
+
+void
+eval(char *addr, char *p)
+{
+ ulong val;
+
+ val = expr(addr);
+ p = nextc(p);
+ if(*p == '\0') {
+ p[0] = fmt;
+ p[1] = '\0';
+ }
+ pfmt(*p, 0, val);
+ Bprint(bioout, "\n");
+}
+
+void
+quesie(char *p)
+{
+ int c, count, i;
+ char tbuf[512];
+
+ c = 0;
+ symoff(tbuf, sizeof(tbuf), dot, CTEXT);
+ Bprint(bioout, "%s?\t", tbuf);
+
+ while(*p) {
+ p = nextc(p);
+ if(*p == '"') {
+ for(p++; *p && *p != '"'; p++) {
+ Bputc(bioout, *p);
+ c++;
+ }
+ if(*p)
+ p++;
+ continue;
+ }
+ count = 0;
+ while(*p >= '0' && *p <= '9')
+ count = count*10 + (*p++ - '0');
+ if(count == 0)
+ count = 1;
+ p = nextc(p);
+ if(*p == '\0') {
+ p[0] = fmt;
+ p[1] = '\0';
+ }
+ for(i = 0; i < count; i++) {
+ c += pfmt(*p, 1, 0);
+ dot += inc;
+ if(c > width) {
+ Bprint(bioout, "\n");
+ symoff(tbuf, sizeof(tbuf), dot, CTEXT);
+ Bprint(bioout, "%s?\t", tbuf);
+ c = 0;
+ }
+ }
+ fmt = *p++;
+ p = nextc(p);
+ }
+ Bprint(bioout, "\n");
+}
+
+void
+catcher(void *a, char *msg)
+{
+ USED(a);
+ if(strcmp(msg, "interrupt") != 0)
+ noted(NDFLT);
+
+ count = 1;
+ print("qi\n");
+ noted(NCONT);
+}
+
+void
+setreg(char *addr, char *cp)
+{
+ int rn;
+
+ dot = expr(addr);
+ cp = nextc(cp);
+ if(strcmp(cp, "pc") == 0) {
+ reg.pc = dot;
+ return;
+ }
+ if(strcmp(cp, "sp") == 0) {
+ reg.r[1] = dot;
+ return;
+ }
+ if(strcmp(cp, "lr") == 0) {
+ reg.lr = dot;
+ return;
+ }
+ if(strcmp(cp, "ctr") == 0) {
+ reg.ctr = dot;
+ return;
+ }
+ if(strcmp(cp, "fpscr") == 0) {
+ reg.fpscr = dot;
+ return;
+ }
+ if(strcmp(cp, "xer") == 0) {
+ reg.xer = dot;
+ return;
+ }
+ if(strcmp(cp, "cr") == 0) {
+ reg.cr = dot;
+ return;
+ }
+ if(*cp++ == 'r') {
+ rn = strtoul(cp, 0, 10);
+ if(rn > 0 && rn < 32) {
+ reg.r[rn] = dot;
+ return;
+ }
+ }
+ Bprint(bioout, "bad register\n");
+}
+
+void
+cmd(void)
+{
+ char *p, *a, *cp, *gotint;
+ char addr[128];
+ static char *cmdlet = ":$?/=>";
+ int n, i;
+
+ notify(catcher);
+
+ dot = reg.pc;
+ setjmp(errjmp);
+
+ for(;;) {
+ Bflush(bioout);
+ p = buf;
+ n = 0;
+ for(;;) {
+ i = Bgetc(bin);
+ if(i < 0)
+ exits(0);
+ *p++ = i;
+ n++;
+ if(i == '\n')
+ break;
+ }
+
+ if(buf[0] == '\n')
+ strcpy(buf, lastcmd);
+ else {
+ buf[n-1] = '\0';
+ strcpy(lastcmd, buf);
+ }
+ p = buf;
+ a = addr;
+
+ for(;;) {
+ p = nextc(p);
+ if(*p == 0 || strchr(cmdlet, *p))
+ break;
+ *a++ = *p++;
+ }
+
+ *a = '\0';
+ cmdcount = 1;
+ cp = strchr(addr, ',');
+ if(cp != 0) {
+ if(cp[1] == '#')
+ cmdcount = strtoul(cp+2, &gotint, 16);
+ else
+ cmdcount = strtoul(cp+1, &gotint, 0);
+ *cp = '\0';
+ }
+
+ switch(*p) {
+ case '$':
+ dollar(p+1);
+ break;
+ case ':':
+ colon(addr, p+1);
+ break;
+ case '/':
+ case '?':
+ dot = expr(addr);
+ for(i = 0; i < cmdcount; i++)
+ quesie(p+1);
+ break;
+ case '=':
+ eval(addr, p+1);
+ break;
+ case '>':
+ setreg(addr, p+1);
+ break;
+ default:
+ Bprint(bioout, "?\n");
+ break;
+ }
+ }
+}