


    /* 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 /*0x0*/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 /*0x0*/loadpp(int k) {	/*!!also increments pp*/
 byte [pp]=k;	 pp++;
}
 
static void /*0x0*/loadfp(int k) {
 byte [fp]=k;
}
 
static void /*0x0*/leftstar() {
for (;;) {
if (pp==lbeg)  return ;
 fp--;	 pp--;
 loadfp(byte [pp]);
}
}
 
static void /*0x0*/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 /*0x0*/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 /*0x0*/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 /*0x0*/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 /*0x0*/stack(int v) {
 c [ci-(cbase)]=v;	 ci++;
}
 
static void /*0x0*/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 /*0x0*/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 /*0x0*/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 /*0x0*/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 */

