1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-13 15:27:46 +00:00
aap.pdp6/fe6/cmd.c
2019-12-05 00:31:20 +01:00

420 lines
7.1 KiB
C

#include "fe.h"
#include <unistd.h>
#include <fcntl.h>
#define MAXOPS 20
static char *lp;
static int numops;
static char *ops[MAXOPS];
static void
skipwhite(void)
{
while(isspace(*lp))
lp++;
}
static int
isdelim(char c)
{
return c == '\0' || 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++;
}
if(*lp == '\0') lp--;
*p = '\0';
}else{
ops[numops++] = p = lp;
while(!isdelim(*lp)){
if(*lp == '\\')
lp++;
*p++ = *lp++;
}
if(*lp == '\0') lp--;
*p = '\0';
}
}
}
void
loadsav(FILE *fp)
{
word iowd;
word w;
while(w = readwbak(fp), w != ~0){
if(w >> 27 == 0254){
printf("PC: %o\r\n", right(w));
fflush(stdout);
cpu_setpc(right(w));
started = 1;
return;
}
iowd = w;
while(left(iowd) != 0){
iowd += 01000001;
w = readwbak(fp);
if(w == ~0)
goto format;
deposit(right(iowd), w);
}
}
format:
printf("\r\nSAV format botch\r\n");
fflush(stdout);
}
void
loadsblk(FILE *fp)
{
word iowd, w, chk;
int d;
/* Skip RIM loader */
while(w = readwits(fp), w != ~0)
if(w == 0254000000001)
goto sblk;
goto format;
sblk:
/* Read a simple block */
while(w = readwits(fp), w != ~0){
/* We expect an AOBJN word here */
if((w & F0) == 0)
goto end;
iowd = w;
chk = iowd;
d = right(iowd) != 0; /* 0 is symbol table */
while(left(iowd) != 0){
w = readwits(fp);
if(w == ~0)
goto format;
chk = (chk<<1 | chk>>35) + w & FW;
if(d){
deposit(right(iowd), w);
}
iowd += 01000001;
}
if(readwits(fp) != chk)
goto format;
}
goto format;
end:
/* use the first JRST, not the second */
// w = readwits(fp);
if(left(w) != 0324000 && left(w) != 0254000)
goto format;
printf("PC: %o\r\n", right(w));
fflush(stdout);
cpu_setpc(right(w));
started = 1;
return;
format:
printf("\r\nSBLK format botch\r\n");
fflush(stdout);
}
#define MAXBLK 01000
void
dumpsblk(FILE *fp, hword start, hword end)
{
hword a;
word w, iowd, chk;
int last0;
writewits(0254000000001, fp);
for(a = start; a <= end; /*a++*/){
/* look for beginning of block */
w = examine(a);
if(w == 0){
a++;
continue;
}
/* look for end of block */
iowd = a;
last0 = 0;
for(; a <= end; a++){
if(a - iowd >= MAXBLK)
break;
w = examine(a);
if(w == 0){
if(last0){
a--;
break;
}
last0 = 1;
}else{
last0 = 0;
}
}
//printf("%lo - %o\r\n", iowd, a);
/* write block */
iowd |= (01000000 - (a-iowd)) << 18;
writewits(iowd, fp);
chk = iowd;
//printf("%lo\r\n", iowd);
while(left(iowd) != 0){
w = examine(right(iowd));
writewits(w, fp);
chk = (chk<<1 | chk>>35) + w & FW;
//printf(" %lo\r\n", w);
iowd += 01000001;
}
writewits(chk, fp);
}
w = 0324000000000 | starta;
writewits(w, fp);
writewits(w, fp);
writewits(~0, fp); // flush
//fflush(stdout);
}
static void
printops(void)
{
int i;
for(i = 0; i < numops; i++)
printf("<%s> ", ops[i]);
printf("\r\n");
fflush(stdout);
}
void
c_dump(int argc, char *argv[])
{
FILE *f;
if(argc < 2)
return;
f = fopen(ops[1], "wb");
if(f == nil)
err("?F? ");
dumpsblk(f, 020, MAXMEM-1);
fclose(f);
}
void
c_load(int argc, char *argv[])
{
FILE *f;
if(argc < 2)
return;
f = fopen(ops[1], "rb");
if(f == nil)
err("?F? ");
loadsblk(f);
fclose(f);
}
void
c_loadsav(int argc, char *argv[])
{
FILE *f;
if(argc < 2)
return;
f = fopen(ops[1], "rb");
if(f == nil)
err("?F? ");
loadsav(f);
fclose(f);
}
struct dev devtab[] = {
{ "ptr", O_RDONLY, -1, nil },
{ "ptp", O_WRONLY | O_CREAT | O_TRUNC, -1, nil },
nil, 0, 0
};
struct dev*
finddev(char *str)
{
struct dev *d;
for(d = devtab; d->devname; d++)
if(strcasecmp(d->devname, str) == 0)
return d;
return nil;
}
void
c_mount(int argc, char *argv[])
{
char *devstr, *path;
struct dev *dev;
if(argc == 1){
/* with no arguments, print mounts */
for(dev = devtab; dev->devname; dev++)
if(dev->fd >= 0)
printf("%s: %s\r\n", dev->devname, dev->path);
return;
}
if(argc < 3)
err("?A? ");
devstr = argv[1];
path = argv[2];
dev = finddev(devstr);
if(dev == nil)
err("?D? ");
if(dev->fd >= 0){
close(dev->fd);
dev->fd = -1;
free(dev->path);
dev->path = nil;
}
dev->fd = open(path, dev->mode);
if(dev->fd < 0)
err("?F? ");
dev->path = strdup(path);
}
void
c_unmount(int argc, char *argv[])
{
char *devstr;
struct dev *dev;
if(argc < 2)
err("?A? ");
devstr = argv[1];
dev = finddev(devstr);
if(dev == nil)
err("?D? ");
if(dev->fd >= 0){
close(dev->fd);
dev->fd = -1;
free(dev->path);
dev->path = nil;
}
}
struct {
char *cmd;
void (*f)(int, char **);
} cmdtab[] = {
{ "load", c_load },
{ "loadsav", c_loadsav },
{ "dump", c_dump },
{ "mount", c_mount },
{ "unmount", c_unmount },
{ nil, nil }
};
void
coloncmd(char *line)
{
int i;
lp = line;
splitops();
if(numops < 1)
return;
for(i = 0; cmdtab[i].cmd; i++)
if(strcasecmp(ops[0], cmdtab[i].cmd) == 0){
cmdtab[i].f(numops, ops);
return;
}
err("?? ");
}
void
docmd(char *cmd, char *line)
{
char buf[256];
sprintf(buf, "%s %s", cmd, line);
coloncmd(buf);
}
char *helpstr =
"\n\
? print help\n\
◊? print colon command help\n\
◊D clear input\n\
◊G start at start address\n\
<loc>◊G start at <loc>\n\
<loc>◊◊G set start address to <loc> and start\n\
◊R\n\
<loc>◊R\n\
<loc>◊◊R like their G counterparts but read-in instead of start\n\
↑Z instruction stop\n\
◊↑Z memory stop\n\
◊P continue\n\
↑N instruction step\n\
◊↑N memory step\n\
<inst>◊X execute instruction inst\n\
◊I IO reset\n\
◊Q last quantity\n\
+ addition operator\n\
- subtraction operator\n\
* multiplication operator\n\
| division operator\n\
SPACE assembly field separator\n\
, assembly field separator\n\
(word) swap word and add to current full word\n\
X(word) where X is an operator. parenthesize expression\n\
/ open\n\
\\ open, don't set .\n\
[ open, constant typeout\n\
] open, symbolic typeout\n\
! open, no typeout\n\
TAB deposit, open\n\
^ deposit, open previous\n\
↑J deposit, open next\n\
↑M deposit, close\n\
_ typeout symbolic\n\
= typeout constant\n\
\" typeout ASCII\n\
' typeout SIXBIT\n\
& typeout SQUOZE\n\
◊S ◊◊S symbolic mode\n\
◊C ◊◊C constant mode\n\
\" ◊◊\" ASCII mode\n\
◊' ◊◊' SIXBIT mode\n\
◊& ◊◊& SQUOZE mode\n\
◊H ◊◊H half word mode\n\
◊L <file> load binary file\n\
◊Y <file> dump to binary file\n\
";
char *colhelpstr =
"\n\
:load <file> load binary file\n\
:dump <file> dump to binary file\n\
:mount <dev> <file> mount file on device\n\
:unmount <dev> unmount file on device\n\
";