/* EPC Imp to C Translation Release 4 Version Apr 95 */
#include "imptoc.h"
/*!This version of ECCE, derived from a paper copy believed to */
/*!date from 1975, removes PDP9/15 machine code, and other */
/*!IMP9/15 system dependencies, and I'm hopeful that as a result */
/*!it might well work if compiled with a generic Imp compiler. */
/*!RWT Feb 2002 */
/*!Code slightly rearranged to fit the model of Peter Stephen's Imp to C */
/*!translator. This now compiles and runs exactly as on the pdp9/15 */
/*!Remember to run it with redirected input, eg ecce < file.txt > file2.txt */
/*!The I/O library currently assumes you are running on Unix. */
/*!NOTE: There IS a bug in this implementation. Lines of more */
/*!than 120 characters have a newline inserted at the 120th character */
/*!on output. This *may* be an original bug rather than an artifact */
/*!of the translation or run-time library.. */
/*!GT 02 Mar 2002 */
int outstream;
static int in = 1; /* current input stream */
#define min 1 /* main input stream */
#define mout 1 /* main output stream */
#define sin 2 /* secondary input stream */
#define sextra 122 /* extra buff for sin */
#define size 30000 /* of edit buffer (bytes) */
static int mon = 0; /* monitor indic */
static int print1 = 0;
static int print2 = 0; /* print indicators */
#define stop (-5000) /* loop stop (const) */
int i, j, k, pp1, sym;
int code; /* command code letter */
int text; /* text pointer */
int num; /* repetition number */
int *mainfp; /* == fp or mfp (for sin) */
#define cbase 1
#define tbase 120
static int c[tbase - (cbase) + 1]; /* command -> <- text */
/* each command unit -- letter, parenthesis or comma -- is */
/* represented by a trio: code(+lim) text num */
/* in the case of parentheses and commas 'text' is a pointer */
/* to another command unit (not to a text string) */
int ci; /* command index (ad) */
int ti; /* text index (ad) */
static int cmax = 0; /* command max (ad) */
int stored[192 + 1]; /* defs of x,y,z */
static int pos1 = 0;
static int pos2 = 0;
static int pos3 = 0;
unsigned char byte[size + 1];
static int top = 2; /* top of buff (index) */
static int bot = size - sextra; /* bottom of buff (index) */
int lbeg; /* line start (index) */
int pp; /* previous pointer (index) */
static int fp = 0; /* file pointer (index) */
int lend; /* line end (index) */
static int fend; /* end of file in buff (index) */
static int ms = 0; /* match start (index) */
static int ml = 0; /* match limit (index) */
/* significance of file pointers: */
/* [nl] o n e nl t w . . . o nl n e x t nl . . nl l a s t nl [nl] */
/* ! ! ! ! ! ! */
/* t l p f l f */
/* o b p p e e */
/* p e n n */
/* g d d */
int type, chain; /* command input vars */
static int pend = 0; /* ditto */
static void prompt (char *s)
{ /* Emulating pdp9/15 routine */
int oldstream, c;
c = s[1 - 1];
if (c != 0) {
/* c = 0 is supposed to flush output on the 9/15 */
oldstream = outstream;
selectoutput (0);
fprintf (out_file, "%c", c);
selectoutput (oldstream);
}
}
static void loadpp (int k)
{ /* !!also increments pp */
byte[pp] = k;
pp++;
}
static void loadfp (int k)
{
byte[fp] = k;
}
static void leftstar ()
{
for (;;) {
if (pp == lbeg)
return;
fp--;
pp--;
loadfp (byte[pp]);
}
}
static void rightstar ()
{
for (;;) {
if (fp == lend)
return;
loadpp (byte[fp]);
fp++;
}
}
static int symtype[95 - 32] =
{64, 3, 3, 3, 2, 3, 3, 11,
9, 64, 3, 12, 2, 3, 3, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 1, 3, 3, 3, 64, 3,
2, 10, 18, 5, 8, 52, 10, 2,
6, 10, 10, 10, 56, 2, 2, 10,
50, 10, 22, 5, 5, 6, 2, 32,
32, 32, 3, 10, 3, 3, 3};
/* ! " # $ % & ' ( ) * + , - . / */
/* 0 1 2 3 4 5 6 7 8 9 : < = > ? */
/* @ A B C D E F G H I J K L M N O */
/* P Q R S T U V W X Y Z [ \ ] ^ _ */
static void readsym ()
{
if (pend != 0) {
sym = pend;
pend = 0;
} else {
while (pos3 != 0) {
sym = stored[pos3];
pos3++;
if (sym != nl)
return;
pos3 = pos2;
pos2 = pos1;
pos1 = 0;
}
sym = fgetc (in_file);
}
}
static void readitem ()
{
type = 1;
for (;;) {
do
readsym ();
while (sym == ' ');
if (sym < 32)
return; /* nl */
if (sym >= 96)
sym -= 32; /* ensure upper case */
type = symtype[sym - 33];
if ((type & 15) != 0)
return;
if (type != 32)
break;
pos1 = pos2;
pos2 = pos3;
pos3 = ((sym - 'X') << 6) + 1;
}
if (type == 0) {
num = sym - '0';
for (;;) {
pend = fgetc (in_file);
if (('0' > pend) || (pend > '9'))
break;
num = ((((num << 2) + num) << 1) - '0') + pend;
}
} else {
type = 0;
num = 0;
if (sym == '*')
return;
num = stop + 1;
if (sym == '?')
return;
num = stop; /* '!' */
}
}
static void unchain ()
{
do {
text = chain;
if (text == 0)
return;
chain = c[text + 1 - (cbase)];
c[text + 1 - (cbase)] = ci;
} while (c[text - (cbase)] != 'X');
}
static void stack (int v)
{
c[ci - (cbase)] = v;
ci++;
}
static void makespace ()
{
int k, p1, p2;
if (((*mainfp - pp) - 240) > 0)
return;
selectoutput (mout);
p1 = top;
p2 = (unsigned) (p1 + lbeg) >> 1; /* output about half */
if (code == 'C')
p2 = lbeg; /* but all if closing */
if (p2 == top) {
assert (_IMP_MONITOR_);
exit (0);
} /* !!logical error */
do {
k = byte[p1];
fprintf (out_file, "%c", k);
p1++;
} while (k != nl || (p1 - p2) < 0);
selectoutput (0);
lbeg = (top + lbeg) - p1;
p2 = pp;
pp = top;
for (;;) {
if (p1 == p2)
return;
loadpp (byte[p1]);
p1++;
}
}
static void readline ()
{
int k;
/* %ON %EVENT 9 %START */
/* ->eof */
/* %FINISH */
if (fp != fend) {
lend = fp;
while (byte[lend] != nl)
lend++;
return;
}
ms = 0;
print1 = 0;
print2 = 0;
selectinput (in);
fp = (bot - sextra) + 1;
do {
if (fp != bot)
k = fgetc (in_file);
else
k = nl;
if (k < 0)
goto eof;
loadfp (k);
fp++;
} while (k != nl);
fend = fp;
lend = fend - 1;
fp = (bot - sextra) + 1;
selectinput (0);
return;
eof:
fp = bot;
lend = fp;
fend = lend;
loadfp (nl);
selectinput (0);
}
static void switchinputs ()
{
static int mfp;
static int mlend;
static int mend;
static int sfp;
static int send;
if (in == min) {
leftstar ();
in = sin;
mfp = fp;
mlend = lend;
mend = fend;
mainfp = &mfp;
bot += sextra;
fp = sfp;
fend = send;
readline ();
} else {
pp = lbeg;
in = min;
bot -= sextra;
sfp = fp;
send = fend;
fp = mfp;
lend = mlend;
fend = mend;
mainfp = &fp;
}
}
static void printline ()
{
int p;
print1 = lend;
print2 = fp + pp;
p = lbeg;
for (;;) {
if (p == pp) {
if (p != lbeg && num == 0)
fprintf (out_file, "%c", '^');
p = fp;
}
if (p == lend)
break;
fprintf (out_file, "%c", byte[p]);
p++;
}
if (p == fend)
fprintf (out_file, "%s", "**END**");
fprintf (out_file, "%s", "\n");
}
static int matched ()
{
int i, j, k, l, t1, fp1, lim;
lim = c[ci - 3 - (cbase)] & (~127);
t1 = c[text - (cbase)];
l1:
pp1 = pp;
fp1 = fp;
if (fp != ms || (code != 'F' && code != 'U'))
goto l3;
k = byte[fp];
l2:
loadpp (k);
fp++;
l3:
if (fp == lend)
goto l10;
k = byte[fp];
if (k != t1)
goto l2;
i = fp;
j = text;
l6:
i++;
j--;
l = c[j - (cbase)];
if (byte[i] == l)
goto l6;
if (l != 0)
goto l2;
ms = fp;
ml = i;
return 1;
l10:
lim -= 128;
if (lim != 0 && fp != fend) {
if (code != 'U') {
loadpp (nl);
lbeg = pp;
} else
pp = pp1;
fp++;
makespace ();
readline ();
goto l1;
}
pp = pp1;
fp = fp1;
return 0;
}
int main ()
{ /* edit15: ecce for pdp9/15 */
/*initialise */
int t_value;
int t_line;
char *t_file;
int s_value;
int s_line;
char *s_file;
/*%ON %EVENT 9 %START */
/* printstring("Caught event"); newline */
/* ->eof */
/*%FINISH */
selectinput (0);
pp = top - 1;
loadpp (nl); /* for bouncing off */
lbeg = pp;
mainfp = &fp;
stored[1] = nl;
stored[65] = nl;
stored[129] = nl;
selectoutput (0);
fprintf (out_file, "%s", "EDIT\n");
readline ();
/*read command line */
l1:
prompt (">");
readitem ();
if (sym < 0)
goto eof;
if (type == 1)
goto l1;
ci = cbase;
ti = tbase;
chain = 0;
if (type == 0 && cmax != 0) {
c[cmax + 2 - (cbase)] = num;
readitem ();
if (type != 1)
goto er2;
goto go;
}
if (sym == '%') {
readsym ();
if (sym >= 96)
sym -= 32;
code = sym;
if (code <= 32)
goto er5;
readitem ();
{
t_value = (unsigned) symtype[code - 33] >> 4;
t_line = __LINE__;
t_file = __FILE__;
goto t_despatch;
}
}
l2:
i = type & 15;
if (i < 4)
goto er2;
code = sym;
text = 0;
num = 1; /* default values */
readitem ();
{
t_value = i;
t_line = __LINE__;
t_file = __FILE__;
goto t_despatch;
}
t_2:
/* %X, %Y, %Z */
if (sym != '=')
goto er1;
i = (code - 'X') << 6;
for (;;) {
readsym ();
i++;
stored[i] = sym;
if (sym == nl)
goto l1;
}
t_3:
/* %M, %F, %Q */
mon = 'M' - code;
goto l1;
t_4:
/* find */
if (type != 0)
num = 0;
t_5:
/* +del,trav,uncover */
code += num << 7;
num = 1;
if (type == 0)
readitem ();
t_6:
/* +insert,subst,verify */
if (type != 3)
goto er4;
text = ti;
i = sym;
l61:
readsym ();
if (sym != nl) {
if (sym != i) {
if (ti <= ci)
goto er6;
c[ti - (cbase)] = sym;
ti--;
goto l61;
}
} else {
pend = sym;
if (code != 'S' && code != 'I')
goto er4;
}
if (ti == text && code != 'S')
goto er4;
c[ti - (cbase)] = 0;
ti--;
goto l81;
t_8:
/* move,erase */
if (sym != '-')
goto l100;
code += 10;
l81:
readitem ();
goto l101;
t_9:
/* close bracket */
unchain ();
if (text == 0)
goto er3;
code = 'Z';
c[text + 2 - (cbase)] = num;
text += 3;
t_10:
/* +get,kill,etc. */
l100:
if (type == 3)
goto er1;
l101:
if (type == 0)
readitem ();
goto put;
t_11:
/* open bracket */
code = 'X';
goto l121;
t_12:
/* comma */
code = 'Y';
if (type == 1)
readitem ();
l121:
text = chain;
chain = ci;
num = 0;
put:
stack (code);
stack (text);
stack (num);
if ((ci + 4) >= ti)
goto er6;
if (type != 1)
goto l2;
unchain ();
if (text != 0)
goto er3;
cmax = ci;
stack ('Z');
stack (cbase);
stack (1); /* extra close b */
stack (0);
goto go;
/*command input error reports */
er1:
fprintf (out_file, "%s", " ");
fprintf (out_file, "%c", code);
er2:
code = sym;
goto er5;
er3:
fprintf (out_file, "%s", " ()");
goto er7;
er4:
fprintf (out_file, "%s", " TEXT FOR");
t_0:
er5:
fprintf (out_file, "%s", " ");
fprintf (out_file, "%c", code & 127);
goto er7;
er6:
fprintf (out_file, "%s", " SIZE");
er7:
fprintf (out_file, "%c", '?');
fprintf (out_file, "%s", "\n");
if (ci != cbase)
cmax = 0;
l10:
if (sym < 32)
goto l1;
readsym ();
goto l10;
/*execute command line */
go:
ci = cbase;
get:
code = c[ci - (cbase)] & 127;
if (code == 0)
goto l99;
text = c[ci + 1 - (cbase)];
num = c[ci + 2 - (cbase)];
ci += 3;
rep:
num--;
{
s_value = code;
s_line = __LINE__;
s_file = __FILE__;
goto s_despatch;
}
ok:
if (num != 0 && num != stop)
goto rep;
goto get;
s_92:
/* invert */
no:
if (num < 0)
goto get;
if (c[ci - (cbase)] == '\\') {
ci += 3;
goto get;
}
skp:
i = c[ci - (cbase)];
if (i == 'X')
ci = c[ci + 1 - (cbase)];
ci += 3;
if (i > 'X') {
num = c[ci - 1 - (cbase)] - 1;
goto no;
}
if (i != 0)
goto skp;
/*execution error report */
fprintf (out_file, "%s", "FAILURE: ");
if (code == 'O' || code == 'W') {
fprintf (out_file, "%c", code - 10);
code = '-';
}
fprintf (out_file, "%c", code);
if (text != 0) {
fprintf (out_file, "%c", '\'');
while (c[text - (cbase)] != 0) {
fprintf (out_file, "%c", c[text - (cbase)]);
text--;
}
fprintf (out_file, "%c", '\'');
}
fprintf (out_file, "%s", "\n");
print1 = 0;
/*end of command line */
l99:
if (sym != nl)
goto l1;
if ((mon < 0 || print1 == lend) && (mon <= 0 || print2 == (fp + pp)))
goto l1;
num = 0;
printline ();
goto l1;
/*individual commands */
s_88:
/* open bracket */
c[text + 2 - (cbase)] = num + 1;
goto get;
s_90:
/* close bracket */
if (num == 0 || num == stop)
goto get;
c[ci - 1 - (cbase)] = num;
s_89:
/* +comma */
ci = text;
goto get;
s_82:
/* right shift */
if (fp == lend)
goto no;
loadpp (byte[fp]);
fp++;
goto ok;
s_76:
/* left shift */
if (in == sin || pp == lbeg)
goto no;
fp--;
pp--;
loadfp (byte[pp]);
ms = 0;
goto ok;
s_69:
/* erase */
if (fp == lend)
goto no;
fp++;
goto ok;
s_79:
/* erase back */
if (pp == lbeg)
goto no;
pp--;
goto ok;
s_86:
/* verify */
i = fp - 1;
j = text + 1;
v1:
i++;
j--;
k = c[j - (cbase)];
if (byte[i] == k)
goto v1;
if (k != 0)
goto no;
ms = fp;
ml = i;
goto ok;
s_70:
/* find */
if (matched () == 0)
goto no;
goto ok;
s_85:
/* uncover */
if (matched () == 0)
goto no;
pp = pp1;
goto ok;
s_68:
/* delete */
if (matched () == 0)
goto no;
fp = ml;
goto ok;
s_84:
/* traverse */
if (matched () == 0)
goto no;
s_83:
/* +substitute */
if (fp == ms)
fp = ml;
s_73:
/* +insert */
makespace ();
/*! ->no %IF pp-lbeg+lend-fp > 80 */
i = text;
i1:
if (c[i - (cbase)] == 0)
goto ok;
loadpp (c[i - (cbase)]);
i--;
goto i1;
s_71:
/* get (line from tt) */
prompt (":");
/*! make space */
i = fgetc (in_file);
if (i == ':')
goto no;
leftstar ();
while (i != nl) {
loadpp (i);
i = fgetc (in_file);
}
s_66:
/* +break (insert newline) */
makespace ();
loadpp (nl);
lbeg = pp;
goto ok;
s_80:
/* print */
printline ();
if (num == 0)
goto get;
s_77:
/* +move */
rightstar ();
if (fp == fend)
goto no;
loadpp (nl);
lbeg = pp;
m1:
fp++;
makespace ();
readline ();
goto ok;
s_75:
/* kill (line) */
pp = lbeg;
fp = lend;
k1:
if (fp == fend)
goto no;
goto m1;
s_74:
/* join (delete newline) */
rightstar ();
/*! ->no %IF pp-lbeg > 80 */
goto k1;
s_87:
/* move back */
if (in == sin)
goto no;
makespace ();
if (lbeg == top)
goto no;
lend = ((fp - pp) + lbeg) - 1;
w1:
k = byte[pp - 1];
if (k == nl && pp != lbeg)
goto w2;
fp--;
pp--;
loadfp (k);
goto w1;
w2:
lbeg = pp;
ms = 0;
goto ok;
t_1:
/* %S, %C ... */
if (code == 'C')
goto eof;
switchinputs ();
goto l99;
eof:
code = 'C'; /* +eof on command stream */
if (in == sin)
switchinputs ();
for (;;) {
rightstar ();
if (fp == fend)
break;
loadpp (nl);
lbeg = pp;
fp++;
makespace ();
readline ();
}
selectoutput (mout);
while (top != pp) {
fprintf (out_file, "%c", byte[top]);
top++;
}
selectoutput (0);
if (code != 'C')
assert (_IMP_MONITOR_);
goto s_skip;
s_despatch:
switch (s_value) {
case '\\':
goto s_92;
case 'X':
goto s_88;
case 'Z':
goto s_90;
case 'Y':
goto s_89;
case 'R':
goto s_82;
case 'L':
goto s_76;
case 'E':
goto s_69;
case 'O':
goto s_79;
case 'V':
goto s_86;
case 'F':
goto s_70;
case 'U':
goto s_85;
case 'D':
goto s_68;
case 'T':
goto s_84;
case 'S':
goto s_83;
case 'I':
goto s_73;
case 'G':
goto s_71;
case 'B':
goto s_66;
case 'P':
goto s_80;
case 'M':
goto s_77;
case 'K':
goto s_75;
case 'J':
goto s_74;
case 'W':
goto s_87;
default:
BADSWITCH (s_value, s_line, s_file);
}
s_skip:;
goto t_skip;
t_despatch:
switch (t_value) {
case 2:
goto t_2;
case 3:
goto t_3;
case 4:
goto t_4;
case 5:
goto t_5;
case 6:
goto t_6;
case 8:
goto t_8;
case 9:
goto t_9;
case 10:
goto t_10;
case 11:
goto t_11;
case 12:
goto t_12;
case 0:
goto t_0;
case 1:
goto t_1;
default:
BADSWITCH (t_value, t_line, t_file);
}
t_skip:;
}
/* end of automatic translation */