xref: /plan9/sys/src/cmd/vi/cmd.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3bd389b36SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <mach.h>
53e12c5d1SDavid du Colombier #include <ctype.h>
63e12c5d1SDavid du Colombier #define Extern extern
73e12c5d1SDavid du Colombier #include "mips.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier char	buf[128], lastcmd[128];
103e12c5d1SDavid du Colombier char	fmt = 'X';
113e12c5d1SDavid du Colombier int	width = 60;
123e12c5d1SDavid du Colombier int	inc;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier ulong	expr(char*);
153e12c5d1SDavid du Colombier ulong	expr1(char*);
163e12c5d1SDavid du Colombier char*	term(char*, ulong*);
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier char *
193e12c5d1SDavid du Colombier nextc(char *p)
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier 	while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
223e12c5d1SDavid du Colombier 		p++;
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier 	if(*p == '\n')
253e12c5d1SDavid du Colombier 		*p = '\0';
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier 	return p;
283e12c5d1SDavid du Colombier }
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier char *
313e12c5d1SDavid du Colombier numsym(char *addr, ulong *val)
323e12c5d1SDavid du Colombier {
333e12c5d1SDavid du Colombier 	char tsym[128], *t;
343e12c5d1SDavid du Colombier 	static char *delim = "`'<>/\\@*|-~+-/=?\n";
353e12c5d1SDavid du Colombier 	Symbol s;
363e12c5d1SDavid du Colombier 	char c;
373e12c5d1SDavid du Colombier 
383e12c5d1SDavid du Colombier 	t = tsym;
393e12c5d1SDavid du Colombier 	while(c = *addr) {
403e12c5d1SDavid du Colombier 		if(strchr(delim, c))
413e12c5d1SDavid du Colombier 			break;
423e12c5d1SDavid du Colombier 		*t++ = c;
433e12c5d1SDavid du Colombier 		addr++;
443e12c5d1SDavid du Colombier 	}
453e12c5d1SDavid du Colombier 	t[0] = '\0';
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	if(strcmp(tsym, ".") == 0) {
483e12c5d1SDavid du Colombier 		*val = dot;
493e12c5d1SDavid du Colombier 		return addr;
503e12c5d1SDavid du Colombier 	}
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 	if(lookup(0, tsym, &s))
533e12c5d1SDavid du Colombier 		*val = s.value;
543e12c5d1SDavid du Colombier 	else {
553e12c5d1SDavid du Colombier 		if(tsym[0] == '#')
563e12c5d1SDavid du Colombier 			*val = strtoul(tsym+1, 0, 16);
573e12c5d1SDavid du Colombier 		else
583e12c5d1SDavid du Colombier 			*val = strtoul(tsym, 0, 0);
593e12c5d1SDavid du Colombier 	}
603e12c5d1SDavid du Colombier 	return addr;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier ulong
643e12c5d1SDavid du Colombier expr(char *addr)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier 	ulong t, t2;
673e12c5d1SDavid du Colombier 	char op;
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier 	if(*addr == '\0')
703e12c5d1SDavid du Colombier 		return dot;
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier 	addr = numsym(addr, &t);
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	if(*addr == '\0')
753e12c5d1SDavid du Colombier 		return t;
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier 	addr = nextc(addr);
783e12c5d1SDavid du Colombier 	op = *addr++;
793e12c5d1SDavid du Colombier 	numsym(addr, &t2);
803e12c5d1SDavid du Colombier 	switch(op) {
813e12c5d1SDavid du Colombier 	default:
823e12c5d1SDavid du Colombier 		Bprint(bioout, "expr syntax\n");
833e12c5d1SDavid du Colombier 		return 0;
843e12c5d1SDavid du Colombier 	case '+':
853e12c5d1SDavid du Colombier 		t += t2;
863e12c5d1SDavid du Colombier 		break;
873e12c5d1SDavid du Colombier 	case '-':
883e12c5d1SDavid du Colombier 		t -= t2;
893e12c5d1SDavid du Colombier 		break;
903e12c5d1SDavid du Colombier 	case '%':
913e12c5d1SDavid du Colombier 		t /= t2;
923e12c5d1SDavid du Colombier 		break;
933e12c5d1SDavid du Colombier 	case '&':
943e12c5d1SDavid du Colombier 		t &= t2;
953e12c5d1SDavid du Colombier 		break;
963e12c5d1SDavid du Colombier 	case '|':
973e12c5d1SDavid du Colombier 		t |= t2;
983e12c5d1SDavid du Colombier 		break;
993e12c5d1SDavid du Colombier 	}
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier 	return t;
1023e12c5d1SDavid du Colombier }
1033e12c5d1SDavid du Colombier 
1043e12c5d1SDavid du Colombier int
1053e12c5d1SDavid du Colombier buildargv(char *str, char **args, int max)
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	int na = 0;
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	while (na < max) {
1103e12c5d1SDavid du Colombier 		while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
1113e12c5d1SDavid du Colombier 			str++;
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 		if(*str == '\0')
1143e12c5d1SDavid du Colombier 			return na;
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier 		args[na++] = str;
1173e12c5d1SDavid du Colombier 		while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
1183e12c5d1SDavid du Colombier 			str++;
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier 		if(*str == '\n')
1213e12c5d1SDavid du Colombier 			*str = '\0';
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier 		if(*str == '\0')
1243e12c5d1SDavid du Colombier 			break;
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier 		*str++ = '\0';
1273e12c5d1SDavid du Colombier 	}
1283e12c5d1SDavid du Colombier 	return na;
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier void
1323e12c5d1SDavid du Colombier colon(char *addr, char *cp)
1333e12c5d1SDavid du Colombier {
1343e12c5d1SDavid du Colombier 	int argc;
1353e12c5d1SDavid du Colombier 	char *argv[100];
136219b2ee8SDavid du Colombier 	char tbuf[512];
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier 	cp = nextc(cp);
1393e12c5d1SDavid du Colombier 	switch(*cp) {
1403e12c5d1SDavid du Colombier 	default:
1413e12c5d1SDavid du Colombier 		Bprint(bioout, "?\n");
1423e12c5d1SDavid du Colombier 		return;
1433e12c5d1SDavid du Colombier 	case 'b':
1443e12c5d1SDavid du Colombier 		breakpoint(addr, cp+1);
1453e12c5d1SDavid du Colombier 		return;
1463e12c5d1SDavid du Colombier 
1473e12c5d1SDavid du Colombier 	case 'd':
1483e12c5d1SDavid du Colombier 		delbpt(addr);
1493e12c5d1SDavid du Colombier 		return;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	/* These fall through to print the stopped address */
1523e12c5d1SDavid du Colombier 	case 'r':
1533e12c5d1SDavid du Colombier 		reset();
1543e12c5d1SDavid du Colombier 		argc = buildargv(cp+1, argv, 100);
155219b2ee8SDavid du Colombier 		initstk(argc, argv);
1563e12c5d1SDavid du Colombier 		count = 0;
1573e12c5d1SDavid du Colombier 		atbpt = 0;
1583e12c5d1SDavid du Colombier 		run();
1593e12c5d1SDavid du Colombier 		break;
1603e12c5d1SDavid du Colombier 	case 'c':
1613e12c5d1SDavid du Colombier 		count = 0;
1623e12c5d1SDavid du Colombier 		atbpt = 0;
1633e12c5d1SDavid du Colombier 		run();
1643e12c5d1SDavid du Colombier 		break;
1653e12c5d1SDavid du Colombier 	case 's':
1663e12c5d1SDavid du Colombier 		cp = nextc(cp+1);
1673e12c5d1SDavid du Colombier 		count = 0;
1683e12c5d1SDavid du Colombier 		if(*cp)
1693e12c5d1SDavid du Colombier 			count = strtoul(cp, 0, 0);
1703e12c5d1SDavid du Colombier 		if(count == 0)
1713e12c5d1SDavid du Colombier 			count = 1;
1723e12c5d1SDavid du Colombier 		atbpt = 0;
1733e12c5d1SDavid du Colombier 		run();
1743e12c5d1SDavid du Colombier 		break;
1753e12c5d1SDavid du Colombier 	}
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	dot = reg.pc;
1783e12c5d1SDavid du Colombier 	Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
179219b2ee8SDavid du Colombier 	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
180219b2ee8SDavid du Colombier 	Bprint(bioout, tbuf);
1813e12c5d1SDavid du Colombier 	if(fmt == 'z')
1823e12c5d1SDavid du Colombier 		printsource(dot);
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier 	Bprint(bioout, "\n");
1853e12c5d1SDavid du Colombier }
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 
1883e12c5d1SDavid du Colombier void
1893e12c5d1SDavid du Colombier dollar(char *cp)
1903e12c5d1SDavid du Colombier {
191*7dd7cddfSDavid du Colombier 	int nr;
192*7dd7cddfSDavid du Colombier 
1933e12c5d1SDavid du Colombier 	cp = nextc(cp);
1943e12c5d1SDavid du Colombier 	switch(*cp) {
1953e12c5d1SDavid du Colombier 	default:
1963e12c5d1SDavid du Colombier 		Bprint(bioout, "?\n");
1973e12c5d1SDavid du Colombier 		break;
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 	case 'c':
2003e12c5d1SDavid du Colombier 		stktrace(*cp);
2013e12c5d1SDavid du Colombier 		break;
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier 	case 'C':
2043e12c5d1SDavid du Colombier 		stktrace(*cp);
2053e12c5d1SDavid du Colombier 		break;
2063e12c5d1SDavid du Colombier 
2073e12c5d1SDavid du Colombier 	case 'b':
2083e12c5d1SDavid du Colombier 		dobplist();
2093e12c5d1SDavid du Colombier 		break;
2103e12c5d1SDavid du Colombier 
2113e12c5d1SDavid du Colombier 	case 'r':
2123e12c5d1SDavid du Colombier 		dumpreg();
2133e12c5d1SDavid du Colombier 		break;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	case 'R':
2163e12c5d1SDavid du Colombier 		dumpreg();
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	case 'f':
2193e12c5d1SDavid du Colombier 		dumpfreg();
2203e12c5d1SDavid du Colombier 		break;
2213e12c5d1SDavid du Colombier 
2223e12c5d1SDavid du Colombier 	case 'F':
2233e12c5d1SDavid du Colombier 		dumpdreg();
2243e12c5d1SDavid du Colombier 		break;
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier 	case 'q':
2273e12c5d1SDavid du Colombier 		exits(0);
2283e12c5d1SDavid du Colombier 		break;
2293e12c5d1SDavid du Colombier 
2303e12c5d1SDavid du Colombier 	case 'Q':
2313e12c5d1SDavid du Colombier 		isum();
2323e12c5d1SDavid du Colombier 		tlbsum();
2333e12c5d1SDavid du Colombier 		segsum();
2343e12c5d1SDavid du Colombier 		break;
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier 	case 't':
2373e12c5d1SDavid du Colombier 		cp++;
2383e12c5d1SDavid du Colombier 		switch(*cp) {
2393e12c5d1SDavid du Colombier 		default:
240*7dd7cddfSDavid du Colombier 			Bprint(bioout, "$t[0sicr#]\n");
2413e12c5d1SDavid du Colombier 			break;
2423e12c5d1SDavid du Colombier 		case '\0':
2433e12c5d1SDavid du Colombier 			trace = 1;
2443e12c5d1SDavid du Colombier 			break;
2453e12c5d1SDavid du Colombier 		case '0':
2463e12c5d1SDavid du Colombier 			trace = 0;
2473e12c5d1SDavid du Colombier 			sysdbg = 0;
2483e12c5d1SDavid du Colombier 			calltree = 0;
2493e12c5d1SDavid du Colombier 			break;
2503e12c5d1SDavid du Colombier 		case 's':
2513e12c5d1SDavid du Colombier 			sysdbg = 1;
2523e12c5d1SDavid du Colombier 			break;
2533e12c5d1SDavid du Colombier 		case 'i':
2543e12c5d1SDavid du Colombier 			trace = 1;
2553e12c5d1SDavid du Colombier 			break;
2563e12c5d1SDavid du Colombier 		case 'c':
2573e12c5d1SDavid du Colombier 			calltree = 1;
2583e12c5d1SDavid du Colombier 			break;
259*7dd7cddfSDavid du Colombier 		case 'r':
260*7dd7cddfSDavid du Colombier 			nr = atoi(cp+1);
261*7dd7cddfSDavid du Colombier 			if(nr < 0 || nr > 31) {
262*7dd7cddfSDavid du Colombier 				print("bad register\n");
263*7dd7cddfSDavid du Colombier 				break;
264*7dd7cddfSDavid du Colombier 			}
265*7dd7cddfSDavid du Colombier 			rtrace ^= (1<<nr);
266*7dd7cddfSDavid du Colombier 			print("%.8ux\n", rtrace);
267*7dd7cddfSDavid du Colombier 			break;
2683e12c5d1SDavid du Colombier 		}
2693e12c5d1SDavid du Colombier 		break;
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier 	case 'i':
2723e12c5d1SDavid du Colombier 		cp++;
2733e12c5d1SDavid du Colombier 		switch(*cp) {
2743e12c5d1SDavid du Colombier 		default:
2753e12c5d1SDavid du Colombier 			Bprint(bioout, "$i[itsa]\n");
2763e12c5d1SDavid du Colombier 			break;
2773e12c5d1SDavid du Colombier 		case 'i':
2783e12c5d1SDavid du Colombier 			isum();
2793e12c5d1SDavid du Colombier 			break;
2803e12c5d1SDavid du Colombier 		case 't':
2813e12c5d1SDavid du Colombier 			tlbsum();
2823e12c5d1SDavid du Colombier 			break;
2833e12c5d1SDavid du Colombier 		case 's':
2843e12c5d1SDavid du Colombier 			segsum();
2853e12c5d1SDavid du Colombier 			break;
2863e12c5d1SDavid du Colombier 		case 'a':
2873e12c5d1SDavid du Colombier 			isum();
2883e12c5d1SDavid du Colombier 			tlbsum();
2893e12c5d1SDavid du Colombier 			segsum();
2903e12c5d1SDavid du Colombier 			iprofile();
2913e12c5d1SDavid du Colombier 			break;
2923e12c5d1SDavid du Colombier 		case 'p':
2933e12c5d1SDavid du Colombier 			iprofile();
2943e12c5d1SDavid du Colombier 			break;
2953e12c5d1SDavid du Colombier 		}
2963e12c5d1SDavid du Colombier 	}
2973e12c5d1SDavid du Colombier }
2983e12c5d1SDavid du Colombier 
2993e12c5d1SDavid du Colombier int
3003e12c5d1SDavid du Colombier pfmt(char fmt, int mem, ulong val)
3013e12c5d1SDavid du Colombier {
3023e12c5d1SDavid du Colombier 	int c, i;
3033e12c5d1SDavid du Colombier 	Symbol s;
3043e12c5d1SDavid du Colombier 	char *p, ch, str[1024];
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier 	c = 0;
3073e12c5d1SDavid du Colombier 	switch(fmt) {
3083e12c5d1SDavid du Colombier 	default:
3093e12c5d1SDavid du Colombier 		Bprint(bioout, "bad modifier\n");
3103e12c5d1SDavid du Colombier 		return 0;
3113e12c5d1SDavid du Colombier 	case 'o':
312*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
3133e12c5d1SDavid du Colombier 		inc = 2;
3143e12c5d1SDavid du Colombier 		break;
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier 	case 'O':
317*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
3183e12c5d1SDavid du Colombier 		inc = 4;
3193e12c5d1SDavid du Colombier 		break;
3203e12c5d1SDavid du Colombier 
3213e12c5d1SDavid du Colombier 	case 'q':
322*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
3233e12c5d1SDavid du Colombier 		inc = 2;
3243e12c5d1SDavid du Colombier 		break;
3253e12c5d1SDavid du Colombier 
3263e12c5d1SDavid du Colombier 	case 'Q':
327*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
3283e12c5d1SDavid du Colombier 		inc = 4;
3293e12c5d1SDavid du Colombier 		break;
3303e12c5d1SDavid du Colombier 
3313e12c5d1SDavid du Colombier 	case 'd':
3323e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
3333e12c5d1SDavid du Colombier 		inc = 2;
3343e12c5d1SDavid du Colombier 		break;
3353e12c5d1SDavid du Colombier 
3363e12c5d1SDavid du Colombier 
3373e12c5d1SDavid du Colombier 	case 'D':
3383e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
3393e12c5d1SDavid du Colombier 		inc = 4;
3403e12c5d1SDavid du Colombier 		break;
3413e12c5d1SDavid du Colombier 
3423e12c5d1SDavid du Colombier 	case 'x':
3433e12c5d1SDavid du Colombier 		c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
3443e12c5d1SDavid du Colombier 		inc = 2;
3453e12c5d1SDavid du Colombier 		break;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	case 'X':
3483e12c5d1SDavid du Colombier 		c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
3493e12c5d1SDavid du Colombier 		inc = 4;
3503e12c5d1SDavid du Colombier 		break;
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier 	case 'u':
3533e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
3543e12c5d1SDavid du Colombier 		inc = 2;
3553e12c5d1SDavid du Colombier 		break;
3563e12c5d1SDavid du Colombier 
3573e12c5d1SDavid du Colombier 	case 'U':
3583e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
3593e12c5d1SDavid du Colombier 		inc = 4;
3603e12c5d1SDavid du Colombier 		break;
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier 	case 'b':
363*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
3643e12c5d1SDavid du Colombier 		inc = 1;
3653e12c5d1SDavid du Colombier 		break;
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	case 'c':
368*7dd7cddfSDavid du Colombier 		c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
3693e12c5d1SDavid du Colombier 		inc = 1;
3703e12c5d1SDavid du Colombier 		break;
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier 	case 'C':
3733e12c5d1SDavid du Colombier 		ch = mem ? getmem_b(dot) : val;
3743e12c5d1SDavid du Colombier 		if(isprint(ch))
3753e12c5d1SDavid du Colombier 			c = Bprint(bioout, "%c ", ch);
3763e12c5d1SDavid du Colombier 		else
3773e12c5d1SDavid du Colombier 			c = Bprint(bioout, "\\x%.2x ", ch);
3783e12c5d1SDavid du Colombier 		inc = 1;
3793e12c5d1SDavid du Colombier 		break;
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier 	case 's':
3823e12c5d1SDavid du Colombier 		i = 0;
3833e12c5d1SDavid du Colombier 		while(ch = getmem_b(dot+i))
3843e12c5d1SDavid du Colombier 			str[i++] = ch;
3853e12c5d1SDavid du Colombier 		str[i] = '\0';
3863e12c5d1SDavid du Colombier 		dot += i;
3873e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%s", str);
3883e12c5d1SDavid du Colombier 		inc = 0;
3893e12c5d1SDavid du Colombier 		break;
3903e12c5d1SDavid du Colombier 
3913e12c5d1SDavid du Colombier 	case 'S':
3923e12c5d1SDavid du Colombier 		i = 0;
3933e12c5d1SDavid du Colombier 		while(ch = getmem_b(dot+i))
3943e12c5d1SDavid du Colombier 			str[i++] = ch;
3953e12c5d1SDavid du Colombier 		str[i] = '\0';
3963e12c5d1SDavid du Colombier 		dot += i;
3973e12c5d1SDavid du Colombier 		for(p = str; *p; p++)
3983e12c5d1SDavid du Colombier 			if(isprint(*p))
3993e12c5d1SDavid du Colombier 				c += Bprint(bioout, "%c", *p);
4003e12c5d1SDavid du Colombier 			else
401*7dd7cddfSDavid du Colombier 				c += Bprint(bioout, "\\x%.2ux", *p);
4023e12c5d1SDavid du Colombier 		inc = 0;
4033e12c5d1SDavid du Colombier 		break;
4043e12c5d1SDavid du Colombier 
4053e12c5d1SDavid du Colombier 	case 'Y':
4063e12c5d1SDavid du Colombier 		p = ctime(mem ? getmem_b(dot) : val);
4073e12c5d1SDavid du Colombier 		p[30] = '\0';
4083e12c5d1SDavid du Colombier 		c = Bprint(bioout, "%s", p);
4093e12c5d1SDavid du Colombier 		inc = 4;
4103e12c5d1SDavid du Colombier 		break;
4113e12c5d1SDavid du Colombier 
4123e12c5d1SDavid du Colombier 	case 'a':
413219b2ee8SDavid du Colombier 		symoff(str, sizeof(str), dot, CTEXT);
414219b2ee8SDavid du Colombier 		c = Bprint(bioout, str);
4153e12c5d1SDavid du Colombier 		inc = 0;
4163e12c5d1SDavid du Colombier 		break;
4173e12c5d1SDavid du Colombier 
4183e12c5d1SDavid du Colombier 	case 'e':
4193e12c5d1SDavid du Colombier 		for (i = 0; globalsym(&s, i); i++)
4203e12c5d1SDavid du Colombier 			Bprint(bioout, "%-15s #%lux\n", s.name,	getmem_4(s.value));
4213e12c5d1SDavid du Colombier 		inc = 0;
4223e12c5d1SDavid du Colombier 		break;
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 	case 'i':
425219b2ee8SDavid du Colombier 		inc = _mipscoinst(symmap, dot, str, sizeof(str));
426219b2ee8SDavid du Colombier 		if (inc < 0) {
427219b2ee8SDavid du Colombier 			Bprint(bioout, "vi: %r\n");
428219b2ee8SDavid du Colombier 			return 0;
429219b2ee8SDavid du Colombier 		}
430219b2ee8SDavid du Colombier 		c = Bprint(bioout, str);
4313e12c5d1SDavid du Colombier 		break;
4323e12c5d1SDavid du Colombier 
4333e12c5d1SDavid du Colombier 	case 'n':
4343e12c5d1SDavid du Colombier 		c = width+1;
4353e12c5d1SDavid du Colombier 		inc = 0;
4363e12c5d1SDavid du Colombier 		break;
4373e12c5d1SDavid du Colombier 
4383e12c5d1SDavid du Colombier 	case '-':
4393e12c5d1SDavid du Colombier 		c = 0;
4403e12c5d1SDavid du Colombier 		inc = -1;
4413e12c5d1SDavid du Colombier 		break;
4423e12c5d1SDavid du Colombier 
4433e12c5d1SDavid du Colombier 	case '+':
4443e12c5d1SDavid du Colombier 		c = 0;
4453e12c5d1SDavid du Colombier 		inc = 1;
4463e12c5d1SDavid du Colombier 		break;
4473e12c5d1SDavid du Colombier 
4483e12c5d1SDavid du Colombier 	case '^':
4493e12c5d1SDavid du Colombier 		c = 0;
4503e12c5d1SDavid du Colombier 		if(inc > 0)
4513e12c5d1SDavid du Colombier 			inc = -inc;
4523e12c5d1SDavid du Colombier 		break;
4533e12c5d1SDavid du Colombier 
4543e12c5d1SDavid du Colombier 	case 'z':
4553e12c5d1SDavid du Colombier 		if (findsym(dot, CTEXT, &s))
4563e12c5d1SDavid du Colombier 			Bprint(bioout, "  %s() ", s.name);
4573e12c5d1SDavid du Colombier 		printsource(dot);
4583e12c5d1SDavid du Colombier 		inc = 0;
4593e12c5d1SDavid du Colombier 		break;
4603e12c5d1SDavid du Colombier 	}
4613e12c5d1SDavid du Colombier 	return c;
4623e12c5d1SDavid du Colombier }
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier void
4653e12c5d1SDavid du Colombier eval(char *addr, char *p)
4663e12c5d1SDavid du Colombier {
4673e12c5d1SDavid du Colombier 	ulong val;
4683e12c5d1SDavid du Colombier 
4693e12c5d1SDavid du Colombier 	val = expr(addr);
4703e12c5d1SDavid du Colombier 	p = nextc(p);
4713e12c5d1SDavid du Colombier 	if(*p == '\0') {
4723e12c5d1SDavid du Colombier 		p[0] = fmt;
4733e12c5d1SDavid du Colombier 		p[1] = '\0';
4743e12c5d1SDavid du Colombier 	}
4753e12c5d1SDavid du Colombier 	pfmt(*p, 0, val);
4763e12c5d1SDavid du Colombier 	Bprint(bioout, "\n");
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier 
4793e12c5d1SDavid du Colombier void
4803e12c5d1SDavid du Colombier quesie(char *p)
4813e12c5d1SDavid du Colombier {
4823e12c5d1SDavid du Colombier 	int c, count, i;
483219b2ee8SDavid du Colombier 	char tbuf[512];
4843e12c5d1SDavid du Colombier 
4853e12c5d1SDavid du Colombier 	c = 0;
486219b2ee8SDavid du Colombier 	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
487219b2ee8SDavid du Colombier 	Bprint(bioout, "%s?\t", tbuf);
4883e12c5d1SDavid du Colombier 
4893e12c5d1SDavid du Colombier 	while(*p) {
4903e12c5d1SDavid du Colombier 		p = nextc(p);
4913e12c5d1SDavid du Colombier 		if(*p == '"') {
4923e12c5d1SDavid du Colombier 			for(p++; *p && *p != '"'; p++) {
4933e12c5d1SDavid du Colombier 				Bputc(bioout, *p);
4943e12c5d1SDavid du Colombier 				c++;
4953e12c5d1SDavid du Colombier 			}
4963e12c5d1SDavid du Colombier 			if(*p)
4973e12c5d1SDavid du Colombier 				p++;
4983e12c5d1SDavid du Colombier 			continue;
4993e12c5d1SDavid du Colombier 		}
5003e12c5d1SDavid du Colombier 		count = 0;
5013e12c5d1SDavid du Colombier 		while(*p >= '0' && *p <= '9')
5023e12c5d1SDavid du Colombier 			count = count*10 + (*p++ - '0');
5033e12c5d1SDavid du Colombier 		if(count == 0)
5043e12c5d1SDavid du Colombier 			count = 1;
5053e12c5d1SDavid du Colombier 		p = nextc(p);
5063e12c5d1SDavid du Colombier 		if(*p == '\0') {
5073e12c5d1SDavid du Colombier 			p[0] = fmt;
5083e12c5d1SDavid du Colombier 			p[1] = '\0';
5093e12c5d1SDavid du Colombier 		}
5103e12c5d1SDavid du Colombier 		for(i = 0; i < count; i++) {
5113e12c5d1SDavid du Colombier 			c += pfmt(*p, 1, 0);
5123e12c5d1SDavid du Colombier 			dot += inc;
5133e12c5d1SDavid du Colombier 			if(c > width) {
5143e12c5d1SDavid du Colombier 				Bprint(bioout, "\n");
515219b2ee8SDavid du Colombier 				symoff(tbuf, sizeof(tbuf), dot, CTEXT);
516219b2ee8SDavid du Colombier 				Bprint(bioout, "%s?\t", tbuf);
5173e12c5d1SDavid du Colombier 				c = 0;
5183e12c5d1SDavid du Colombier 			}
5193e12c5d1SDavid du Colombier 		}
5203e12c5d1SDavid du Colombier 		fmt = *p++;
5213e12c5d1SDavid du Colombier 		p = nextc(p);
5223e12c5d1SDavid du Colombier 	}
5233e12c5d1SDavid du Colombier 	Bprint(bioout, "\n");
5243e12c5d1SDavid du Colombier }
5253e12c5d1SDavid du Colombier 
5263e12c5d1SDavid du Colombier void
5273e12c5d1SDavid du Colombier catcher(void *a, char *msg)
5283e12c5d1SDavid du Colombier {
5293e12c5d1SDavid du Colombier 	USED(a);
5303e12c5d1SDavid du Colombier 	if(strcmp(msg, "interrupt") != 0)
5313e12c5d1SDavid du Colombier 		noted(NDFLT);
5323e12c5d1SDavid du Colombier 
5333e12c5d1SDavid du Colombier 	count = 1;
5343e12c5d1SDavid du Colombier 	print("vi\n");
5353e12c5d1SDavid du Colombier 	noted(NCONT);
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier 
5383e12c5d1SDavid du Colombier void
5393e12c5d1SDavid du Colombier setreg(char *addr, char *cp)
5403e12c5d1SDavid du Colombier {
5413e12c5d1SDavid du Colombier 	int rn;
5423e12c5d1SDavid du Colombier 
5433e12c5d1SDavid du Colombier 	dot = expr(addr);
5443e12c5d1SDavid du Colombier 	cp = nextc(cp);
5453e12c5d1SDavid du Colombier 	if(strcmp(cp, "pc") == 0) {
5463e12c5d1SDavid du Colombier 		reg.pc = dot;
5473e12c5d1SDavid du Colombier 		return;
5483e12c5d1SDavid du Colombier 	}
5493e12c5d1SDavid du Colombier 	if(strcmp(cp, "sp") == 0) {
5503e12c5d1SDavid du Colombier 		reg.r[29] = dot;
5513e12c5d1SDavid du Colombier 		return;
5523e12c5d1SDavid du Colombier 	}
5533e12c5d1SDavid du Colombier 	if(strcmp(cp, "mh") == 0) {
5543e12c5d1SDavid du Colombier 		reg.mhi = dot;
5553e12c5d1SDavid du Colombier 		return;
5563e12c5d1SDavid du Colombier 	}
5573e12c5d1SDavid du Colombier 	if(strcmp(cp, "ml") == 0) {
5583e12c5d1SDavid du Colombier 		reg.mlo = dot;
5593e12c5d1SDavid du Colombier 		return;
5603e12c5d1SDavid du Colombier 	}
5613e12c5d1SDavid du Colombier 	if(*cp++ == 'r') {
5623e12c5d1SDavid du Colombier 		rn = strtoul(cp, 0, 10);
5633e12c5d1SDavid du Colombier 		if(rn > 0 && rn < 32) {
5643e12c5d1SDavid du Colombier 			reg.r[rn] = dot;
5653e12c5d1SDavid du Colombier 			return;
5663e12c5d1SDavid du Colombier 		}
5673e12c5d1SDavid du Colombier 	}
5683e12c5d1SDavid du Colombier 	Bprint(bioout, "bad register\n");
5693e12c5d1SDavid du Colombier }
5703e12c5d1SDavid du Colombier 
5713e12c5d1SDavid du Colombier void
5723e12c5d1SDavid du Colombier cmd(void)
5733e12c5d1SDavid du Colombier {
5743e12c5d1SDavid du Colombier 	char *p, *a, *cp, *gotint;
5753e12c5d1SDavid du Colombier 	char addr[128];
5763e12c5d1SDavid du Colombier 	static char *cmdlet = ":$?/=>";
5773e12c5d1SDavid du Colombier 	int n, i;
5783e12c5d1SDavid du Colombier 
5793e12c5d1SDavid du Colombier 	notify(catcher);
5803e12c5d1SDavid du Colombier 
5813e12c5d1SDavid du Colombier 	dot = reg.pc;
5823e12c5d1SDavid du Colombier 	setjmp(errjmp);
5833e12c5d1SDavid du Colombier 
5843e12c5d1SDavid du Colombier 	for(;;) {
5853e12c5d1SDavid du Colombier 		Bflush(bioout);
5863e12c5d1SDavid du Colombier 		p = buf;
5873e12c5d1SDavid du Colombier 		n = 0;
5883e12c5d1SDavid du Colombier 		for(;;) {
5893e12c5d1SDavid du Colombier 			i = Bgetc(bin);
5903e12c5d1SDavid du Colombier 			if(i < 0)
5913e12c5d1SDavid du Colombier 				exits(0);
5923e12c5d1SDavid du Colombier 			*p++ = i;
5933e12c5d1SDavid du Colombier 			n++;
5943e12c5d1SDavid du Colombier 			if(i == '\n')
5953e12c5d1SDavid du Colombier 				break;
5963e12c5d1SDavid du Colombier 		}
5973e12c5d1SDavid du Colombier 
5983e12c5d1SDavid du Colombier 		if(buf[0] == '\n')
5993e12c5d1SDavid du Colombier 			strcpy(buf, lastcmd);
6003e12c5d1SDavid du Colombier 		else {
6013e12c5d1SDavid du Colombier 			buf[n-1] = '\0';
6023e12c5d1SDavid du Colombier 			strcpy(lastcmd, buf);
6033e12c5d1SDavid du Colombier 		}
6043e12c5d1SDavid du Colombier 		p = buf;
6053e12c5d1SDavid du Colombier 		a = addr;
6063e12c5d1SDavid du Colombier 
6073e12c5d1SDavid du Colombier 		for(;;) {
6083e12c5d1SDavid du Colombier 			p = nextc(p);
6093e12c5d1SDavid du Colombier 			if(*p == 0 || strchr(cmdlet, *p))
6103e12c5d1SDavid du Colombier 				break;
6113e12c5d1SDavid du Colombier 			*a++ = *p++;
6123e12c5d1SDavid du Colombier 		}
6133e12c5d1SDavid du Colombier 
6143e12c5d1SDavid du Colombier 		*a = '\0';
6153e12c5d1SDavid du Colombier 		cmdcount = 1;
6163e12c5d1SDavid du Colombier 		cp = strchr(addr, ',');
6173e12c5d1SDavid du Colombier 		if(cp != 0) {
6183e12c5d1SDavid du Colombier 			if(cp[1] == '#')
6193e12c5d1SDavid du Colombier 				cmdcount = strtoul(cp+2, &gotint, 16);
6203e12c5d1SDavid du Colombier 			else
6213e12c5d1SDavid du Colombier 				cmdcount = strtoul(cp+1, &gotint, 0);
6223e12c5d1SDavid du Colombier 			*cp = '\0';
6233e12c5d1SDavid du Colombier 		}
6243e12c5d1SDavid du Colombier 
6253e12c5d1SDavid du Colombier 		switch(*p) {
6263e12c5d1SDavid du Colombier 		case '$':
6273e12c5d1SDavid du Colombier 			dollar(p+1);
6283e12c5d1SDavid du Colombier 			break;
6293e12c5d1SDavid du Colombier 		case ':':
6303e12c5d1SDavid du Colombier 			colon(addr, p+1);
6313e12c5d1SDavid du Colombier 			break;
6323e12c5d1SDavid du Colombier 		case '/':
6333e12c5d1SDavid du Colombier 		case '?':
6343e12c5d1SDavid du Colombier 			dot = expr(addr);
6353e12c5d1SDavid du Colombier 			for(i = 0; i < cmdcount; i++)
6363e12c5d1SDavid du Colombier 				quesie(p+1);
6373e12c5d1SDavid du Colombier 			break;
6383e12c5d1SDavid du Colombier 		case '=':
6393e12c5d1SDavid du Colombier 			eval(addr, p+1);
6403e12c5d1SDavid du Colombier 			break;
6413e12c5d1SDavid du Colombier 		case '>':
6423e12c5d1SDavid du Colombier 			setreg(addr, p+1);
6433e12c5d1SDavid du Colombier 			break;
6443e12c5d1SDavid du Colombier 		default:
6453e12c5d1SDavid du Colombier 			Bprint(bioout, "?\n");
6463e12c5d1SDavid du Colombier 			break;
6473e12c5d1SDavid du Colombier 		}
6483e12c5d1SDavid du Colombier 	}
6493e12c5d1SDavid du Colombier }
650