1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-25 03:45:39 +00:00
aap.pdp6/emu/cmd.c
2017-02-02 19:37:19 +01:00

379 lines
5.5 KiB
C

#include "pdp6.h"
#include "args.h"
#define MAXOPS 20
static char *lp;
static int numops;
static char *ops[MAXOPS];
/* current apr */
static Apr *apr;
static void
skipwhite(void)
{
while(isspace(*lp))
lp++;
}
static int
isdelim(char c)
{
return c && strchr(" \t\n;'\"", c) != nil;
}
/* tokenize lp into ops[numops] */
static void
splitops(void)
{
char delim;
char *p;
numops = 0;
for(; *lp; lp++){
skipwhite();
if(*lp == ';' || *lp == '\0')
return;
if(numops == MAXOPS){
fprintf(stderr, "Too many arguments, ignored <%s>\n", lp);
return;
}
if(*lp == '"' || *lp == '\''){
delim = *lp++;
ops[numops++] = p = lp;
while(*lp && *lp != delim){
if(*lp == '\\')
lp++;
*p++ = *lp++;
}
*p = '\0';
}else{
ops[numops++] = p = lp;
while(!isdelim(*lp)){
if(*lp == '\\')
lp++;
*p++ = *lp++;
}
*p = '\0';
}
}
}
/* Parse an octal, decimal or hexadecimal number.
* 0nnnn is an octal number.
* nnnn. is a decimal number.
* 0xnnnn is a hexadecimal number.
* returns ~0 on error.
*/
word
parsen(char **sp)
{
char *s;
word dec, oct, hex;
char c;
int base;
s = *sp;
base = 0;
dec = oct = hex = 0;
if(s[0] == '0'){
s++;
base = 8;
if(*s == 'x' || *s == 'X'){
s++;
base = 16;
}
}
while(c = *s++){
if(c >= '0' && c <= '9')
c -= '0';
else if(c >= 'A' && c <= 'F')
c -= 'A' + 10;
else if(c >= 'a' && c <= 'f')
c -= 'a' + 10;
else if(c == '.'){
/* decimal number, but only if . is at the end */
if(base <= 10 && *s == '\0'){
base = 10;
break;
}else
goto fail;
}else
break;
oct = oct*8 + c;
dec = dec*10 + c;
hex = hex*16 + c;
if(c >= 8){
if(base < 8)
base = 8;
else
goto fail;
}
if(c >= 10){
if(base < 10)
base = 10;
else
goto fail;
}
if(c >= 16){
if(base < 16)
base = 16;
else
goto fail;
}
}
*sp = s-1;
if(base == 16) return hex;
if(base == 10) return dec;
return oct;
fail:
printf("error: number format\n");
return ~0;
}
static int
parserange(char *s, word *start, word *end)
{
*start = *end = ~0;
*start = parsen(&s);
if(*start == ~0) return 1;
if(*s == '\0'){
*end = *start;
return 0;
}else if(*s == '-' || *s == ':'){
s++;
*end = parsen(&s);
if(*end == ~0) return 1;
}
if(*s){
*start = *end = ~0;
printf("error: address format\n");
return 1;
}
return 0;
}
enum
{
FmtOct, FmtMnem
};
static void
exam(word addr, int fastmem, int format)
{
word *p;
p = getmemref(&apr->membus, addr, fastmem);
if(p == nil){
printf("Non existent memory\n");
return;
}
printf("%06lo: ", addr);
switch(format){
case FmtOct:
default:
printf("%012lo\n", *p);
break;
case FmtMnem:
printf("%s\n", disasm(*p));
break;
}
}
static void
dep(word addr, int fastmem, word w)
{
word *p;
p = getmemref(&apr->membus, addr, fastmem);
if(p == nil){
printf("Non existent memory\n");
return;
}
*p = w;
}
/* Commands */
static void
c_ex(int argc, char *argv[])
{
char *argv0 = nil;
word start, end;
int format, fastmem;
format = FmtOct;
fastmem = 1;
ARGBEGIN{
case 's': /* shadow mode */
fastmem = 0;
break;
case 'm':
format = FmtMnem;
break;
}ARGEND;
if(argc < 1)
return;
if(parserange(argv[0], &start, &end))
return;
for(; start <= end; start++)
exam(start, fastmem, format);
}
static void
c_dep(int argc, char *argv[])
{
char *argv0 = nil;
word start, end;
word w;
int fastmem;
fastmem = 1;
ARGBEGIN{
case 's':
fastmem = 0;
break;
}ARGEND;
if(argc < 2)
return;
if(parserange(argv[0], &start, &end))
return;
w = parsen(&argv[1]);
if(w == ~0)
return;
for(; start <= end; start++)
dep(start, fastmem, w);
}
enum
{
FmtUnk, FmtSav
};
static void
loadsav(FILE *fp)
{
word iowd;
word w;
while(w = readwbak(fp), w != ~0){
if(w >> 27 == 0254){
apr->pc = right(w);
return;
}
iowd = w;
while(left(iowd) != 0){
iowd += 01000001;
w = readwbak(fp);
if(w == ~0)
return;
dep(right(iowd), 0, w);
}
}
}
static void
c_load(int argc, char *argv[])
{
char *argv0 = nil;
FILE *fp;
int fmt;
fmt = FmtSav; // assume SAV for now
ARGBEGIN{
case 's':
fmt = FmtSav;
break;
}ARGEND;
if(argc < 1)
return;
fp = fopen(argv[0], "rb");
if(fp == nil){
printf("couldn't open file: %s\n", argv[0]);
return;
}
if(fmt == FmtSav)
loadsav(fp);
fclose(fp);
}
static void
c_show(int argc, char *argv[])
{
printf("Memory:\n");
showmem(&apr->membus);
}
static void
c_quit(int argc, char *argv[])
{
quit(0);
}
struct {
char *cmd;
void (*f)(int, char **);
} cmdtab[] = {
{ "examine", c_ex },
{ "deposit", c_dep },
{ "load", c_load },
{ "show", c_show },
{ "quit", c_quit },
{ "", nil}
};
void*
cmdthread(void *p)
{
size_t len, l;
char *line, *cmd;
int i, n;
int nfound;
apr = nil;
for(i = 0; i < 4; i++)
if(aprs[i]){
apr = aprs[i];
break;
}
for(;;){
line = nil;
len = 0;
printf("> ");
if(getline(&line, &len, stdin) < 0)
quit(0);
lp = line;
splitops();
if(numops){
nfound = 0;
for(i = 0; cmdtab[i].cmd[0]; i++){
cmd = cmdtab[i].cmd;
l = strlen(ops[0]);
if(strncmp(ops[0], cmd, l) == 0){
n = i;
nfound++;
}
}
if(nfound == 0)
printf("%s: not found\n", ops[0]);
else if(nfound == 1)
cmdtab[n].f(numops, ops);
else{
printf("Ambiguous command: %s\n", ops[0]);
for(i = 0; cmdtab[i].cmd[0]; i++){
cmd = cmdtab[i].cmd;
l = strlen(ops[0]);
if(strncmp(ops[0], cmd, l) == 0)
printf(" %s\n", cmd);
}
}
}
free(line);
}
return nil;
}