ref: 4dbb99f478d68eaeea4c043a839454cb807c2c7d
dir: /sys/src/cmd/5i/cmd.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <mach.h> #include <ctype.h> #include "arm.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.r[15]; 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': stktrace(*cp); break; case 'C': stktrace(*cp); break; case 'b': dobplist(); break; case 'r': dumpreg(); break; case 'R': dumpreg(); case 'f': dumpfreg(); break; case 'F': dumpdreg(); break; case 'q': exits(0); break; case 'Q': isum(); tlbsum(); 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[itsa]\n"); break; case 'i': isum(); break; case 't': tlbsum(); break; case 's': segsum(); break; case 'a': isum(); tlbsum(); 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); c = Bprint(bioout, 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, "5i: %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) { static int hit = 0; hit++; if(hit > 5) exits(0); USED(a); if(strcmp(msg, "interrupt") != 0) noted(NDFLT); count = 1; print("5i\n"); noted(NCONT); } void setreg(char *addr, char *cp) { int rn; dot = expr(addr); cp = nextc(cp); if(strcmp(cp, "pc") == 0) { reg.r[15] = dot; return; } if(strcmp(cp, "sp") == 0) { reg.r[13] = dot; return; } if(*cp++ == 'r') { rn = strtoul(cp, 0, 10); if(rn > 0 && rn < 16) { 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.r[15]; setjmp(errjmp); for(;;) { Bflush(bioout); p = buf; n = 0; while(n < sizeof(buf)) { 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; } } }