plan9front/sys/src/games/mix/repl.c

292 lines
4.0 KiB
C

#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <bio.h>
#include <avl.h>
#include "mix.h"
int
getf(char *line)
{
long a, b;
if(*line == '\0')
return 5;
if(*line++ != '(')
return -1;
a = strtol(line, &line, 10);
if(*line++ != ':')
return -1;
b = strtol(line, &line, 10);
if(*line != ')')
return -1;
return F(a, b);
}
int
disp(char *line)
{
int f;
long m;
if(setjmp(errjmp) == 1)
return -1;
m = strtol(line, &line, 10);
if((f = getf(line)) == -1)
return -1;
print("%d\n", V(cells[m], f));
return 0;
}
int
dispreg(char *line)
{
vlong rax;
char c;
int i, f;
u32int reg;
if(setjmp(errjmp) == 1)
return -1;
switch(c = *line++) {
case 'a':
if(*line == 'x') {
rax = ra & MASK5;
rax <<= 5 * BITS;
rax |= rx & MASK5;
if(ra >> 31)
rax = -rax;
print("%lld\n", rax);
return 0;
} else
reg = ra;
break;
case 'x':
reg = rx;
break;
case 'j':
reg = ri[0];
break;
default:
if(!isdigit(c))
return -1;
i = c - '0';
if(i < 1 || i > 6)
return -1;
reg = ri[i];
}
if((f = getf(line)) == -1)
return -1;
print("%d\n", V(reg, f));
return 0;
}
int
breakp(char *line)
{
long l;
line = strskip(line);
if(!isdigit(*line))
return -1;
l = strtol(line, nil, 10);
if(l < 0 || l > 4000)
return -1;
bp[l] ^= 1;
return 0;
}
int
asm(char *l)
{
char *file;
if(yydone) {
print("Assembly complete\n");
return 0;
}
l = strskip(l);
if(*l++ == '<') {
Bterm(&bin);
l = strskip(l);
file = estrdup(strim(l));
if(asmfile(file) == -1) {
free(file);
return -1;
}
Binit(&bin, 0, OREAD);
free(file);
return 0;
}
line = 1;
filename = "<stdin>";
if(setjmp(errjmp) == 0)
yyparse();
Bterm(&bin);
Binit(&bin, 0, OREAD);
return 0;
}
int
disasm(char *line)
{
long l;
line = strskip(line);
if(!isdigit(*line))
return -1;
l = strtol(line, nil, 10);
if(l < 0 || l > 4000)
return -1;
print("%I\n", cells[l]);
return 0;
}
void
mixprint(int m, int words)
{
int i;
u32int *wp, w;
Rune buf[6], *rp;
wp = cells+m;
while(words-- > 0) {
rp = buf;
w = *wp++;
for(i = 4; i > -1; i--)
*rp++ = mixtorune(w>>i*BITS & MASK1);
*rp = '\0';
print("%S", buf);
}
print("\n");
}
int
out(char *line)
{
long l, i;
line = strskip(line);
i = 1;
if(*line == '(') {
l = strtol(strskip(line+1), &line, 10);
line = strskip(line);
if(*line != ',')
return -1;
i = strtol(strskip(line+1), &line, 10);
line = strskip(line);
if(*line != ')')
return -1;
} else {
if(!isdigit(*line))
return -1;
l = strtol(line, nil, 10);
}
mixprint(l, i);
return 0;
}
void
clearsyms(Sym *s)
{
if(s == nil)
return;
clearsyms((Sym*)s->c[0]);
clearsyms((Sym*)s->c[1]);
free(s);
}
void
repl(int go)
{
char *line, c;
int len, once;
Binit(&bin, 0, OREAD);
if(go && vmstart != -1) {
once = 0;
goto Go;
}
for(;;) {
print("MIX ");
if((line = Brdline(&bin, '\n')) == nil)
return;
if((len = Blinelen(&bin)) == 1)
continue;
line[len-1] = '\0';
once = 0;
switch(c = line[0]) {
Err:
print("?\n");
break;
default:
if(!isdigit(c))
goto Err;
if(disp(line) == -1)
goto Err;
break;
case 'a':
if(asm(line+1) == -1)
goto Err;
break;
case 'b':
if(breakp(line+1) == -1)
goto Err;
break;
case 'c':
ra = rx = ri[0] = ri[1] = ri[2] = ri[3] = ri[4] = ri[5] = ri[6] = 0;
memset(cells, 0, sizeof(cells));
vmstart = -1;
yydone = 0;
clearsyms((Sym*)syms->root);
syms->root = nil;
sinit();
break;
case 'd':
if(disasm(line+1) == -1)
goto Err;
break;
case 'o':
if(out(line+1) == -1)
goto Err;
break;
case 'r':
if(dispreg(line+1) == -1)
goto Err;
break;
case 's':
once = 1;
case 'g':
Go:
if(vmstart == -1)
goto Err;
if(setjmp(errjmp) == 0)
vmstart = mixvm(vmstart, once);
else
break;
if(go)
exits(nil);
if(vmstart == -1)
print("halted\n");
else
print("at %d:\t%I\n", vmstart, cells[vmstart]);
break;
case 'x':
return;
}
}
}