/* gcc -std=gnu89 */ #include #include #include #define nl '\n' char **_argv; int _argc; static FILE *_in[3]; static FILE *_out[3]; static int _init = 0; static int _instream = 0; static int _outstream = 0; void _initstreams(void) { if (_init != 1) return; if (_argc != 4) { fprintf(stderr, "syntax: %s infile secfile outfile\n", _argv[0]); exit(1); } _in[0] = stdin; _in[1] = fopen(_argv[1], "r"); _in[2] = fopen(_argv[2], "r"); _out[0] = stderr; _out[1] = fopen(_argv[3], "w"); _out[2] = stdout; _instream = 0; _outstream = 0; } void selectinput(int channel) { if (_init == 0) { _init = 1; _initstreams(); _init = 2; } if ((channel >= 0) && (channel < 3)) { _instream = channel; } else { /* Error? */ fprintf(stderr, "selectinput(%d) \?\?\?\n", channel); exit(1); } } void selectoutput(int channel) { if (_init == 0) { _init = 1; _initstreams(); _init = 2; } if ((channel >= 0) && (channel < 3)) { _outstream = channel; } else { /* Error? */ fprintf(stderr, "selectoutput(%d) \?\?\?\n", channel); exit(1); } } /* 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 */ int main(int argc, char **argv) { /* edit15: ecce for pdp9/15 */ 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,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; /* 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; /* defs of x,y,z */ static int pos1=0, pos2=0, pos3=0; char *byte; int top = 2; /* top of buff (index) */ 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 *t[12+1] = { &&T0, &&T1, &&T2, &&T3, &&T4, &&T5, &&T6, NULL, &&T8, &&T9, &&T10, &&T11, &&T12 }; /* http://gcc.gnu.org/onlinedocs/gcc-3.0.3/gcc_5.html#SEC70 */ static void *s['\\'+1] = { /* 'A': */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &&S66, NULL, &&S68, &&S69, &&S70, &&S71, NULL, &&S73, &&S74, &&S75, &&S76, &&S77, NULL, &&S79, &&S80, NULL, &&S82, &&S83, &&S84, &&S85, &&S86, &&S87, &&S88, &&S89, &&S90, NULL, &&S92 }; /* http://gcc.gnu.org/onlinedocs/gcc-3.0.3/gcc_5.html#SEC70 */ #ifdef NEVER %on %event 9 %start /* needs manual rewrite using signal */ goto eof; %finish #endif void loadpp(int k) { /* !!also increments pp */ byte[pp] = k; pp = pp+1; } void loadfp(int k) { byte[fp] = k; } void leftstar(void) { for (;;) { if (pp == lbeg) return; fp = fp-1; pp = pp-1; loadfp(byte[pp]); } } void rightstar(void) { for (;;) { if (fp == lend) return; loadpp(byte[fp]); fp = fp+1; } } static int symtype[95+1] = { /* 33: */ /* needs fixing */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 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 [ \ ] ^ _ */ void readsym(void) { if (pend != 0) {sym=pend; pend=0; } else { while (pos3 != 0) { sym = stored[pos3]; pos3 = pos3+1; if (!(sym = nl)) return; pos3 = pos2; pos2 = pos1; pos1 = 0; } sym = fgetc(_in[_instream]); } } void readitem(void) { type = 1; for (;;) { do { readsym(); } while (!(sym != ' ')); if (sym < 32) return; /* nl */ if (sym >= 96) sym = sym-32; /* ensure upper case */ type = symtype[sym]; 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[_instream]); 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; /* '!' */ } } void unchain(void) { do { text = chain; if (text == 0) return; chain = c[text+1]; c[text+1] = ci; } while (!(c[text] == 'X')); } void stack(int v) { c[ci] = v; ci = ci+1; } void makespace(void) { int k,p1,p2; if ((*mainfp)-pp-240 > 0) return; selectoutput(mout); p1 = top; p2 = (p1+lbeg)>>1; /* ouptut about half */ if (code == 'C') p2 = lbeg; /* but all if closing */ assert (!(p2 == top)); /* !!logical error */ do { k = byte[p1]; fputc(k, _out[_outstream]); p1 = p1+1; } 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 = p1+1; } } void readline(void) { int k; #ifdef NEVER %on %event 9 %start goto eof; %finish #endif if (fp != fend) { lend = fp; while (byte[lend] != nl) lend = lend+1; return; } ms = 0; print1 = 0; print2 = 0; selectinput(in); fp = bot-sextra+1; do { if (fp != bot) k = fgetc(_in[_instream]); else k = nl; if (k<0) goto eof; loadfp(k); fp = fp+1; } 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); } void switchinputs(void) { static int mfp,mlend,mend,sfp,send; if (in == min) { leftstar(); in = sin; mfp = fp; mlend = lend; mend = fend; mainfp = &mfp; bot = bot+sextra; fp = sfp; fend = send; readline(); } else { pp = lbeg; in = min; bot = bot-sextra; sfp = fp; send = fend; fp = mfp; lend = mlend; fend = mend; mainfp = &fp; } } void printline(void) { int p; print1 = lend; print2 = fp+pp; p = lbeg; for (;;) { if (p == pp) { if ((p != lbeg) && (num == 0)) fputc('^', _out[_outstream]); p = fp; } if (p == lend) break; fputc(byte[p], _out[_outstream]); p = p+1; } if (p == fend) fprintf(_out[_outstream], "%s", "**END**"); fputc(nl, _out[_outstream]); } int matched(void) { int i,j,k,l,t1,fp1,lim; lim = (c[ci-3])&(~127); t1 = c[text]; L1: pp1 = pp; fp1 = fp; if (!((fp == ms) && ((code=='F') || (code=='U')))) goto L3; k = byte[fp]; L2: loadpp(k); fp = fp+1; L3: if (fp == lend) goto L10; k = byte[fp]; if (!(k == t1)) goto L2; i = fp; j = text; L6: i = i+1; j = j-1; l = c[j]; if (byte[i] == l) goto L6; if (l != 0) goto L2; ms = fp; ml = i; return 1; L10:lim = lim-128; if ((lim != 0) && (fp != fend)) { if (code != 'U') { loadpp(nl); lbeg = pp; } else pp = pp1; fp = fp+1; makespace(); readline(); goto L1; } pp = pp1; fp = fp1; return 0; } /* GENERATED SECTION */ _argv = argv; _argc = argc; selectinput(0); selectoutput(0); /* adjust base of array: */ c = (int *)malloc(sizeof(int) * (tbase-cbase+1)); c = c - cbase; /* command -> <- text */ stored = (int *)malloc(sizeof(int) * (192-1+1)); stored = stored - 1; byte = (char *)malloc(sizeof(char) * (size-1+1)); byte = byte - 1; /* END OF GENERATED SECTION */ /* initialise */ 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[_outstream], "%s", "EDIT\n"); readline(); /* read command line */ L1: fprintf(stderr, "%s", ">");fflush(stderr); 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] = num; readitem(); if (type != 1) goto er2; goto go; } if (sym == '%') { readsym(); if (sym >= 96) sym = sym-32; code = sym; if (code<=32) goto er5; readitem(); goto *t[(symtype[code])>>4]; } L2: i = type&15; if (i < 4) goto er2; code = sym; text = 0; num = 1; /* default values */ readitem(); goto *t[i]; T2: /* %x, %y, %z */ if (sym != '=') goto er1; i = (code-'X')<<6; for (;;) { readsym(); i = i+1; stored[i] = sym; if (sym == nl) goto L1; } T3: /* %m, %f, %q */ mon = 'M'-code; goto L1; T4: /* find */ if (!(type == 0)) num = 0; T5: /* +del,trav,uncover */ code = (num<<7)+code; num = 1; if (type == 0) readitem(); T6: /* +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] = sym; ti = ti-1; goto L61; } } else { pend = sym; if (!((code == 'S') || (code == 'I'))) goto er4; } if ((ti == text) && (code != 'S')) goto er4; c[ti] = 0; ti = ti-1; goto L81; T8: /* move,erase */ if (!(sym == '-')) goto L100; code = code+10; L81:readitem(); goto L101; T9: /* close bracket */ unchain(); if (text == 0) goto er3; code = 'Z'; c[text+2] = num; text = text+3; T10: /* +get,kill,etc. */ L100:if (type == 3) goto er1; L101:if (type == 0) readitem(); goto put; T11: /* open bracket */ code = 'X'; goto L121; T12: /* 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:fputc(' ', _out[_outstream]); fputc(code, _out[_outstream]); er2:code = sym; goto er5; er3:fprintf(_out[_outstream], "%s", " ()"); goto er7; er4:fprintf(_out[_outstream], "%s", " TEXT FOR"); T0: er5:fputc(' ', _out[_outstream]); fputc(code&127, _out[_outstream]); goto er7; er6:fprintf(_out[_outstream], "%s", " SIZE"); er7:fputc('?', _out[_outstream]); fputc(nl, _out[_outstream]); if (ci != cbase) cmax = 0; L10:if (sym<32) goto L1; readsym(); goto L10; /* execute command line */ go: ci = cbase; get:code = (c[ci])&127; if (code == 0) goto L99; text = c[ci+1]; num = c[ci+2]; ci = ci+3; rep:num = num-1; goto *s[code]; ok: if (!((num == 0) || (num == stop))) goto rep; goto get; S92: /* '\' */ /* invert */ no: if (num < 0) goto get; if (c[ci] == '\\') {ci = ci+3; goto get;}; skp:i = c[ci]; if (i == 'X') ci = c[ci+1]; ci = ci+3; if (i > 'X') {num = c[ci-1]-1; goto no;}; if (i != 0) goto skp; /* execution error report */ fprintf(_out[_outstream], "%s", "FAILURE: "); if ((code=='O') || (code=='W')) { fputc(code-10, _out[_outstream]); code = '-'; } fputc(code, _out[_outstream]); if (text != 0) { fputc('\'', _out[_outstream]); while (c[text] != 0) { fputc(c[text], _out[_outstream]); text = text-1; } fputc('\'', _out[_outstream]); } fputc(nl, _out[_outstream]); 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 */ S88: /* 'X' */ /* open bracket */ c[text+2] = num+1; goto get; S90: /* 'Z' */ /* close bracket */ if ((num == 0) || (num == stop)) goto get; c[ci-1] = num; S89: /* 'Y' */ /* +comma */ ci = text; goto get; S82: /* 'R' */ /* right shift */ if (fp == lend) goto no; loadpp(byte[fp]); fp = fp+1; goto ok; S76: /* 'L' */ /* left shift */ if ((in == sin) || (pp == lbeg)) goto no; fp = fp-1; pp = pp-1; loadfp(byte[pp]); ms = 0; goto ok; S69: /* 'E' */ /* erase */ if (fp == lend) goto no; fp = fp+1; goto ok; S79: /* 'O' */ /* erase back */ if (pp == lbeg) goto no; pp = pp-1; goto ok; S86: /* 'V' */ /* verify */ i = fp-1; j = text+1; v1: i = i+1; j = j-1; k = c[j]; if (byte[i] == k) goto v1; if (k != 0) goto no; ms = fp; ml = i; goto ok; S70: /* 'F' */ /* find */ if (matched() == 0) goto no; goto ok; S85: /* 'U' */ /* uncover */ if (matched() == 0) goto no; pp = pp1; goto ok; S68: /* 'D' */ /* delete */ if (matched() == 0) goto no; fp = ml; goto ok; S84: /* 'T' */ /* traverse */ if (matched() == 0) goto no; S83: /* 'S' */ /* +substitute */ if (fp == ms) fp = ml; S73: /* 'I' */ /* +insert */ makespace(); /* if ((pp-lbeg+lend-fp) > 80) goto no; */ i = text; i1: if (c[i] == 0) goto ok; loadpp(c[i]); i = i-1; goto i1; S71: /* 'G' */ /* get (line from tt) */ fprintf(stderr, "%s", ":");fflush(stderr); /* makespace(); */ i = fgetc(_in[_instream]); if (i == ':') goto no; leftstar(); while (i != nl) { loadpp(i); i = fgetc(_in[_instream]); } S66: /* 'B' */ /* +break (insert newline) */ makespace(); loadpp(nl); lbeg = pp; goto ok; S80: /* 'P' */ /* print */ printline(); if (num == 0) goto get; S77: /* 'M' */ /* +move */ rightstar(); if (fp == fend) goto no; loadpp(nl); lbeg = pp; m1: fp = fp+1; makespace(); readline(); goto ok; S75: /* 'K' */ /* kill (line) */ pp = lbeg; fp = lend; k1: if (fp == fend) goto no; goto m1; S74: /* 'J' */ /* join (delete newline) */ rightstar(); /* if (pp-lbeg > 80) goto no; */ goto k1; S87: /* 'W' */ /* 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 = fp-1; pp = pp-1; loadfp(k); goto w1; w2: lbeg = pp; ms = 0; goto ok; T1: /* %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 = fp+1; makespace(); readline(); } selectoutput(mout); while (top != pp) { fputc(byte[top], _out[_outstream]); top = top+1; } /* GENERATED SECTION */ selectinput(0); selectoutput(0); c = c + cbase; /* command -> <- text */ stored = stored + 1; byte = byte + 1; free(c); free(stored); free(byte); exit(0); /* END OF GENERATED SECTION */ }