/* 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 */