section "ECCE1" get "Header" let start (argc,argv,envp) be $( tty.in := input () tty.out := output () selectinput (tty.in) selectoutput (tty.out) if argc = 0 then $( writef ("%S: From To? Logfile? Buffersize?*N", argv!Program) stop (20) $) Main.in := findinput (argv!F) if Main.in = 0 then $( writef ("File *"%S*" not found*N",argv!F) stop (20) $) test (L > argc) | (argv!L = 0) then $( log.out := -1 $) else $( log.out := findoutput (argv!L) if log.out = 0 then $( writef ("Ecce: Warning - can't create *"%S*"*N", argv!L) log.out := -1 $) $) test (B > argc) | (argv!B) = 0 then $( buffer.size := 128*1024 $) else $( let n = 0 let buff.string = argv!B let c = buff.string%1 let i = 1 while i <= buff.string%0 & '0'<= c <= '9' do $( n := n*10+c-'0' i := i+1 c := buff.string%i $) buffer.size := n $) if buffer.size = 0 then buffer.size := 20*1024 init.globals () a%0 := cr a%buffer.size := cr writes ("Ecce*N") if Main.in > 0 then load.file () percent ('L') $( analyse () if ok then $( printed := false execute () command := 'P' repeat.count := 1 if not printed then execute.command () $) $) repeat $) let init.globals () be $( let diff, margin = ?, ? note.file := getvec (16 / bytesperword + 1) com := getvec (max.size / bytesperword + 1) link := getvec (max.size / bytesperword + 1) text := getvec (max.size / bytesperword + 1) num := getvec (max.size) lim := getvec (max.size) com.prompt := getvec ( 4 / bytesperword + 1) a := getvec (buffer.size / bytesperword + 1) if a=0 | note.file=0 | com=0 | link=0 | text=0 | num=0 | lim=0 | com.prompt=0 then $( writes("Unable to claim buffer space*N") free.buffers() stop (20) $) // writef ("Buffer space = %N KBytes*N", buffer.size>>10) sym.type := table /* 0:127 */ ext+termin, //NL// ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ ext+termin, /*NL*/ err, /* */ ext+numb+7, /*!*/ delim, /*"*/ err, /*#*/ err, /*$*/ ext+1, /*%*/ err, /*&*/ delim, /*'*/ ext+2, /*(*/ ext+4, /*)*/ ext+numb+8, /***/ ext+5, /*+*/ ext+3, /*,*/ ext+6, /*-*/ delim, /*.*/ delim, /*slash*/ ext+numb+0, /*0*/ ext+numb+0, /*1*/ ext+numb+0, /*2*/ ext+numb+0, /*3*/ ext+numb+0, /*4*/ ext+numb+0, /*5*/ ext+numb+0, /*6*/ ext+numb+0, /*7*/ ext+numb+0, /*8*/ ext+numb+0, /*9*/ delim, /*:*/ ext+15, /*;*/ ext+2, /*<*/ delim, /*=*/ ext+4, /*>*/ 0, /*?*/ err, /*@*/ scope, /*A*/ sign+rep, /*B*/ sign+rep, /*C*/ sign+scope+txt+rep, /*D*/ sign+rep, /*E*/ sign+scope+txt+rep, /*F*/ sign+rep, /*G*/ scope, /*H*/ sign+txt+rep, /*I*/ sign+rep, /*J*/ sign+rep, /*K*/ sign+rep, /*L*/ sign+rep, /*M*/ 0, /*N*/ err, /*O*/ sign+rep, /*P*/ err, /*Q*/ sign+rep, /*R*/ sign+txt, /*S*/ sign+scope+txt+rep, /*T*/ sign+scope+txt+rep, /*U*/ sign+txt, /*V*/ err, /*W*/ err, /*X*/ err, /*Y*/ err, /*Z*/ ext+2, /*[*/ 0, /*\*/ ext+4, /*]*/ ext+6, /*^*/ delim, /*_*/ err, /*@*/ err, /*A*/ sign+rep, /*B*/ sign+rep, /*C*/ sign+scope+txt+rep, /*D*/ sign+rep, /*E*/ sign+scope+txt+rep, /*F*/ sign+rep, /*G*/ err, /*H*/ sign+txt+rep, /*I*/ sign+rep, /*J*/ sign+rep, /*K*/ sign+rep, /*L*/ sign+rep, /*M*/ err, /*N*/ err, /*O*/ sign+rep, /*P*/ err, /*Q*/ sign+rep, /*R*/ sign+txt, /*S*/ sign+scope+txt+rep, /*T*/ sign+scope+txt+rep, /*U*/ sign+txt, /*V*/ err, /*W*/ err, /*X*/ err, /*Y*/ err, /*Z*/ ext+2, /*[*/ 0, /*\*/ ext+4, /*]*/ ext+6, /*^*/ delim /*_*/ fbeg := 1 lbeg := fbeg pp := lbeg fp := buffer.size lend := fp fend := lend ms := -1 ms.back := -1 stopper := -buffer.size max.unit := -1 pending.sym := cr blank.line := true copy.string( "Note0", note.file ) noted := -1 changes := 0 in.second := false copy.string ( ">", com.prompt ) $) let copy.string (source, destination) be $( for i= 0 to source%0 do destination%i := source%i $) let free.buffers () be $( freevec (a) freevec (lim) freevec (num) freevec (text) freevec (link) freevec (com) freevec (com.prompt) freevec (note.file) $) let local.echo (sym) be $(1 if blank.line then prompt (eprompt) !sym := rdch() if log.out > 0 then $( selectoutput (log.out) wrch (!sym) selectoutput (tty.out) $) blank.line := (!sym = cr) $)1 let read.sym () be $(1 test pending.sym = 0 then local.echo (@sym) repeatwhile sym = '*S' else $(2 sym := pending.sym pending.sym := 0 $)2 $)1 let fail.with (mess,culprit) be $(1 let sign = ? test 'a' <= culprit <= 'z' then sign := '-' else test (culprit & plusbit) \= 0 then sign := '+' else sign := '*S' culprit := culprit & \plusbit if 'A' <= culprit <= 'Z' then culprit := culprit | casebit writef ("** %S %C%C*N", mess, culprit, sign) read.sym () repeatuntil sym.type!sym = sym.type!';' ok := false $)1 let read.item() be $(1 let saved.digit = '?' read.sym () if 'a' <= sym <= 'z' then sym := sym - casebit type := sym.type!sym if (type & ext) = 0 then return switchon type & 15 into $(2 case star: number := 0 return case pling: number := stopper-1 return case dig: saved.digit := sym number := 0 $(4 number := number * 10 + sym - '0' read.sym() $)4 repeatwhile '0' <= sym <= '9' pending.sym := sym sym := saved.digit // for printing in errors return default: return $)2 $)1 let percent (Command.sym) be $(1 static $( note.sec = '0' $) let Emergency = vec 256 let P, sec.no = ?, ? ok := true if 'a' <= Command.sym <= 'z' then command.sym := command.sym - casebit unless 'A' <= command.sym <= 'Z' then $(2 fail.with ("Letter for", '%') return $)2 switchon command.sym into $(2 case 'U': // to.upper.case := \0 // to.lower.case := casebit to.lower.case := 0 endcase case 'L': // to.upper.case := \casebit // to.lower.case := 0 to.lower.case := casebit endcase /* CASE 'N': to.upper.case := \0 to.lower.case := 0 ENDCASE */ case 'V': writes ("Ecce V2.1 Sat May 19 20:53:02 BST 1984*N") endcase // CASE 'W': case 'C': read.sym () repeatuntil sym.type!sym = sym.type!';' test argc = 1 then $( // ARGC = 1 => "from" only p := F // So use input file as output file $) else $( p := T $) Main.out := findoutput (argv!P) test Main.out = 0 then $( writef ("Can't create *"%S*" - supply alternative filename*N", argv!P) // $( eprompt := "File: " Copy.string ("ECCEBAK", Emergency) Main.out := findoutput (Emergency) // IF Main.out > 0 THEN BREAK // $) REPEAT writef ("Writing to file %S instead of %S*N", Emergency, argv!P) $) else $( test p = T then $( writef ("Ecce %S to %S completing.*N", argv!F, argv!T) $) else $( writef ("Ecce %S completing.*N", argv!F) $) $) selectoutput (Main.out) p := fbeg $(4 if p = pp then p := fp if p = fend then break wrch (a%p) p := p + 1 $)4 repeat endwrite () // IF Command.sym = 'W' THEN $( // selectoutput (tty.out) // pending.sym := cr // ENDCASE // $) if log.out > 0 then $( selectoutput (log.out) endwrite () $) selectoutput (tty.out) // writes ("Ecce complete*N") free.buffers () finish case 'A': if log.out > 0 then $( selectoutput (log.out) endwrite () $) selectoutput (tty.out) writes ("Aborted!*N") free.buffers () finish case 'S': local.echo (@sec.no) test sym.type!(sec.no) = sym.type!(';') then sec.no := 0 else $( test sec.no = '!' then sec.no := '?' else unless '0' <= sec.no <= '9' then $( fail.with ("%S", sec.no) return $) local.echo (@sym) if sym.type!(sym) \= sym.type!(';') then $( fail.with ("%S?", sym) return $) $) pending.sym := cr note.file%(note.file%0) := note.sec if in.second then $( let sec.out = findoutput (note.file) copy.string(">",com.prompt) if sec.out <= 0 then $( fail.with ("Cannot save context", ' ') return $) selectoutput (sec.out) p := fbeg $(4 if p = pp then p := fp if p = fend then break wrch (a%p) p := p + 1 $)4 repeat endwrite () selectoutput (tty.out) pp := fbeg - 1 fp := fend + 1 fbeg := 1 fend := buffer.size lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 lend := fp while a%lend \= cr do lend := lend + 1 in.second := false if sec.no = 0 then $( return $) $) if sec.no = 0 then sec.no := '0' note.file%(note.file%0) := sec.no note.sec := sec.no $( let sec.in = findinput (note.file) if sec.in <= 0 then $( fail.with ("Unknown context", sym) return $) copy.string(" >",com.prompt) com.prompt%1 := sec.no in.second := true a%pp := cr fbeg := pp + 1 fend := fp - 1 pp := fbeg fp := fend a%fend := cr lbeg := pp selectinput (sec.in) p := pp $( sym := rdch () if sym = endstreamch then break a%p := sym p := p + 1 if p = fend then $( fail.with ("%S corrupt - no room", ' ') endread () selectinput (tty.in) return $) $) repeat endread () selectinput (tty.in) while p \= pp do $( p := p - 1 fp := fp - 1 a%fp := a%p $) lend := fp while a%lend \= cr do lend := lend + 1 $) endcase default: fail.with ("Percent ", command.sym) $)2 read.sym() repeatuntil sym.type!sym = sym.type!';' $)1 let unchain() be $(1 $(2 pointer := last.unit if (pointer&(max.size+1)) \= 0 then pointer := pointer | (\#xff) // Sign extend if pointer < 0 then return last.unit := link%pointer if (last.unit&(max.size+1)) \= 0 then last.unit := last.unit | (\#xff) // perhaps un-necessary link%pointer := this.unit $)2 repeatuntil com%pointer = '(' $)1 let stack() be $(1 com%this.unit := command link%this.unit := pointer num!this.unit := repeat.count lim!this.unit := limit this.unit := this.unit + 1 $)1 . // End of ECCE1 section "ECCE2" get "Header" let execute.command() be $(1 let i = ? let sym = ? ok := true switchon command & (\plusbit) into $(2 case 'p': case 'P': printed := true i := lbeg $(4 if i=noted then $( writes ("******Note******") if i=lbeg then newline () $) if i=pp then $(5 if i \= lbeg then wrch ('^') i := fp $)5 if i = lend then break sym := a%i test (sym < 32) | (sym >= 127) then $(5 wrch ('<') writen (sym) wrch ('>') $)5 else wrch (sym) i := i + 1 $)4 repeat if i = fend then writes ("******End******") newline() if repeat.count = 1 then return test (command & minusbit) \= 0 then move.back () else move () return case 'g': case 'G': local.echo (@sym) if sym=':' then $(4 local.echo (@sym) pending.sym := sym if sym \= cr then printed := true ok := false return $)4 left.star () $(4 a%pp := sym pp := pp + 1 if sym = cr then break local.echo (@sym) $)4 repeat lbeg := pp if (command & minusbit) \= 0 then $(4 move.back() printed := true $)4 return case 'E': if fp = lend then $(4 ok := false return $)4 test repeat.count = 0 then $(5 fp := lend ok := false $)5 else fp := fp + 1 return case 'e': if pp = lbeg then $(4 ok := false return $)4 test repeat.count = 0 then $(5 pp := lbeg ok := false $)5 else pp := pp - 1 return case 'C': if fp = lend then $(4 ok := false return $)4 sym := a%fp test 'a' <= (sym | casebit) <= 'z' then a%pp := sym neqv casebit else a%pp := sym pp := pp + 1 fp := fp + 1 return case 'c': if pp = lbeg then $(4 ok := false return $)4 pp := pp - 1 fp := fp - 1 sym := a%pp test 'a' <= (sym | casebit) <= 'z' then a%fp := sym neqv casebit else a%fp := sym return case 'l': case 'R': test repeat.count = 0 then $( right.star() ok := false $) else right() ms.back := -1 return case 'r': case 'L': test repeat.count = 0 then $( left.star() ok := false $) else left() ms := -1 return case 'B': a%pp := cr pp := pp + 1 lbeg := pp return case 'b': fp := fp - 1 a%fp := cr lend := fp return case 'J': right.star() if fp = fend then $(4 ok := false return $)4 fp := fp + 1 lend := fp while a%lend \= cr do lend := lend + 1 return case 'j': left.star() if pp = fbeg then $(4 ok := false return $)4 pp := pp - 1 lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 return case 'M': test repeat.count = 0 then $(4 move.star() ok := false $)4 else move() return case 'm': test repeat.count = 0 then $(4 move.back.star() ok := false $)4 else $( move.back() left.star () // Compatability... $) return case 'k': case 'K': if (command & minusbit) \= 0 then $(4 move.back() if not ok then return $)4 pp := lbeg fp := lend if lend = fend then $(4 ok := false return $)4 fp := fp + 1 lend := fp while a%lend \= cr do lend := lend + 1 return case 'V': verify () return case 'v': verify.back () return case 'F': find () return case 'f': find.back () return case 'U': find () if not ok then return pp := pp.before lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 return case 'u': find.back () if not ok then return fp := fp.before lend := fp while a%lend \= cr do lend := lend + 1 return case 'D': find () if not ok then return fp := ml ms := fp return case 'd': find.back () if not ok then return pp := ml.back ms.back := pp return case 'T': find () if not ok then return while fp \= ml do $(4 a%pp := a%fp pp := pp + 1 fp := fp + 1 $)4 return case 't': find.back () if not ok then return while pp \= ml.back do $(4 fp := fp - 1 pp := pp - 1 a%fp := a%pp $)4 return case 'I': insert () return case 'i': insert.back () return case 's': case 'S': test fp = ms then fp := ml else test pp = ms.back then pp := ml.back else $(5 ok := false return $)5 test (command & minusbit) \= 0 then insert.back () else insert () return case '(': num!pointer := repeat.count repeat.count := 1 return case ')': num!this.unit := num!this.unit - 1 if 0 \= num!this.unit \= stopper then $(3 this.unit := pointer if (this.unit&128) \= 0 then this.unit := this.unit | (\#xff) $)3 repeat.count := 1 return case '\': ok := false return case '?': return case ',': this.unit := pointer - 1 return case 'N': noted := pp changes := fp-pp return case 'A': if (noted<0) | (noted>=pp) | (changes\=fp-pp) then $( ok := false return $) note.file%(note.file%0) := lim!(this.unit)+'0' $( let note.out = findoutput (note.file) let p = noted if note.out <= 0 then $( ok := false return $) selectoutput (note.out) $( wrch (a%p) p := p + 1 $) repeatuntil p=pp endwrite () selectoutput (tty.out) pp := noted lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 $) noted := -1 return case 'H': note.file%(note.file%0) := lim!(this.unit)+'0' $( let note.in = findinput (note.file) if note.in <= 0 then $( ok := false return $) selectinput (note.in) $( let p = pp $( sym := rdch () if sym = endstreamch then break a%p := sym p := p + 1 if p = fp then $( endread () selectinput (tty.in) ok := false return $) $) repeat pp := p $) lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 endread () selectinput (tty.in) $) return default: fail.with ("Unrecognised command", command) return $)2 $)1 let scan.sign() be $(1 read.sym () test sym.type!sym = sym.type!'+' then command := command | plusbit else test (sym.type!sym = sym.type!'-') & ('A' <= command <= 'Z') then command := command | minusbit else pending.sym := sym $)1 let Scan.scope() be $(1 number := 1 if 'D' \= (command & (\(minusbit | plusbit))) \= 'U' then number := 0 read.item () if (type & numb) = 0 then pending.sym := sym limit := number if ('H' = command) | (command = 'A') then $( unless (0 <= limit <= 9) then limit := '?'-'0' $) $)1 let Scan.text() be $(1 let last = ? read.sym () last := sym if (sym.type!sym & delim) = 0 then $(2 pending.sym := sym fail.with ("Text for", command) return $)2 test 'a' <= command <= 'z' then $(2 text%endpos := 0 $(3 local.echo (@sym) if sym = last then break if sym = cr then $(4 pending.sym := cr break $)4 endpos := endpos - 1 text%endpos := sym $)3 repeat pointer := endpos endpos := endpos - 1 $)2 else $(2 pointer := pos $(3 local.echo (@sym) if sym = last then break if sym = cr then $(4 pending.sym := cr break $)4 text%pos := sym pos := pos + 1 $)3 repeat text%pos := 0 pos := pos + 1 $)2 ok := true $)1 let scan.repeat () be $(1 number := 1 read.item () if (type & numb) = 0 then pending.sym := sym repeat.count := number $)1 let analyse () be $(1 let saved.type = ? ok := true pos := 0 endpos := max.size this.unit := 0 last.unit := -1 eprompt := com.prompt read.item () repeatuntil type \= sym.type!';' command := sym if command = '%' then $(2 read.sym() if sym.type!sym = sym.type!';' then $(3 pending.sym := sym sym := 0 $)3 percent (sym) ok := false //to inhibit executio return $)2 if (type & numb) \= 0 then $(2 test max.unit > 0 then num!max.unit := number else $(3 ok := false return $)3 read.item() if type \= sym.type!';' then fail.with ("?", sym) pending.sym := sym return $)2 $(2 //on items if (type & err) \= 0 then $(3 fail.with ("Command", command) return $)3 if (type & delim) \= 0 then $(3 fail.with ("Command before", command) return $)3 if (type & numb) \= 0 then $( fail.with ("Unexpected repetition count", command) return $) limit := 0 pointer := 0 repeat.count := 1 test (type & ext) = 0 then $(3 saved.type := type if (saved.type & sign) \= 0 then scan.sign () if (saved.type & scope) \= 0 then scan.scope () if (saved.type & txt) \= 0 then scan.text () if not ok then return if (saved.type & rep) \= 0 then scan.repeat () type := saved.type $)3 else $(3 switchon (type & 15) into $(4 case termin: pending.sym := cr //for skipping on error unchain () if pointer >= 0 then $(5 fail.with ("Missing", ')') return $)5 max.unit := this.unit repeat.count := 1 command := ')' stack () command := 0 stack () return case lpar: command := '(' pointer := last.unit last.unit := this.unit endcase case comma: command := ',' pointer := last.unit last.unit := this.unit endcase case rpar: command := ')' scan.repeat () unchain () if pointer < 0 then $(5 fail.with ("Missing", '(') return $)5 num!pointer := repeat.count endcase $)4 $)3 stack () read.item () command := sym $)2 repeat //on items $)1 let load.file () be $( let p = fbeg let sym = ? selectinput (Main.in) sym := rdch () while sym \= endstreamch do $( a%p := sym p := p + 1 if p = fend then $( writes ("******File too large!*N") percent ('A') $) sym := rdch () $) endread () selectinput (tty.in) while p \= fbeg do $( p := p - 1 fp := fp - 1 sym := a%p a%fp := sym $) lend := fp while a%lend \= cr do lend := lend + 1 $) . // End of ECCE2 section "ECCE3" get "Header" let execute.unit () be $(1 let culprit = ? command := com%this.unit culprit := command pointer := link%this.unit if (pointer&128) \= 0 then pointer := pointer | (\#xff) repeat.count := num!this.unit $(2 //On repeats of this.unit execute.command () repeat.count := repeat.count - 1 if ok then $(3 if repeat.count = 0 | repeat.count = stopper then return loop $)3 ok := true $(3 //scanning for end of unit (e.g. ')') unless '\' \= com%(this.unit+1) \= '?' then $(4 this.unit := this.unit + 1 return $)4 if repeat.count < 0 then return // indefinite repetition never fails $(4 //scanning for end of sequence this.unit := this.unit + 1 command := com%this.unit switchon command into $(5 case '(': this.unit := link%this.unit endcase case ',': return case ')': num!this.unit := num!this.unit - 1 repeat.count := num!this.unit break $)5 if com%this.unit = 0 then $(5 fail.with ("Failure:", culprit) return $)5 $)4 repeat //end of seq $)3 repeat //find() ')' without \ or ? $)2 repeat //executing repeats $)1 let execute () be $(1 eprompt := ":" this.unit := 0 $(2 execute.unit() if not ok then return this.unit := this.unit + 1 $)2 repeatuntil com%this.unit = 0 ok := true $)1 let case.op (sym) = valof $(1 if 'A' <= sym <= 'Z' then sym := sym | to.lower.case resultis sym $)1 let right () be $(1 ok := true if fp = lend then $(2 ok := false return $)2 a%pp := a%fp pp := pp + 1 fp := fp + 1 $)1 let left () be $(1 ok := true if pp = lbeg then $(2 ok := false return $)2 fp := fp - 1 pp := pp - 1 a%fp := a%pp $)1 let right.star() be $( until fp = lend do $(2 a%pp := a%fp pp := pp + 1 fp := fp + 1 $)2 $) let left.star() be $( until pp = lbeg do $(2 fp := fp - 1 pp := pp - 1 a%fp := a%pp $)2 $) let move () be $(1 ok := true right.star () if fp = fend then $(2 ok := false return $)2 a%pp := a%fp pp := pp + 1 fp := fp + 1 lbeg := pp lend := fp while a%lend \= cr do lend := lend + 1 ms.back := -1 $)1 let move.back() be $(1 ok := true left.star () if pp = fbeg then $(2 ok := false return $)2 fp := fp - 1 pp := pp - 1 a%fp := a%pp lend := fp lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 ms := -1 $)1 let move.star () be $(1 until fp = fend do $(2 a%pp := a%fp pp := pp + 1 fp := fp + 1 $)2 lend := fend lbeg := pp lbeg := lbeg - 1 repeatuntil a%lbeg = cr lbeg := lbeg + 1 ms.back := -1 $)1 let move.back.star () be $(1 until pp = fbeg do $(2 fp := fp - 1 pp := pp - 1 a%fp := a%pp $)2 lbeg := fbeg lend := fp while a%lend \= cr do lend := lend + 1 ms := -1 $)1 let insert () be $(1 let p = pointer ml.back := pp until text%p = 0 do $(2 a%pp := text%p pp := pp + 1 p := p+1 $)2 ms.back := pp ms := -1 $)1 let insert.back () be $(1 let p = pointer ml := fp until text%p = 0 do $(2 fp := fp - 1 a%fp := text%p p := p + 1 $)2 ms := fp ms.back := -1 $)1 let verify() be $(1 let x = ? let y = ? let test.sym = ? let sym = ? x := pointer - 1 y := -1 $(2 x := x + 1 y := y + 1 sym := case.op (text%(x)) test.sym := case.op (a%(fp + y)) $)2 repeatwhile sym = test.sym unless sym = 0 then $(2 ok := false return $)2 ms := fp mlen := y ml := fp + mlen ok := true ms.back := -1 $)1 let verify.back () be $(1 let x = ? let y = ? let test.sym = ? let sym = ? x := pointer - 1 y := 0 $(2 x := x + 1 y := y + 1 sym := case.op (text%x) test.sym := case.op (a%(pp - y)) $)2 repeatwhile sym = test.sym unless sym = 0 then $(2 ok := false return $)2 ms.back := pp mlen := y - 1 ml.back := pp - mlen ok := true ms := -1 $)1 let find() be $(1 let sym = text%pointer | casebit pp.before := pp limit := lim!this.unit if fp = ms then $(2 right () unless ok then move() $)2 $(2 if (a%fp | casebit) = sym then $(3 verify () if ok then return $)3 right () if not ok then $(3 limit := limit - 1 if limit = 0 then break move () if not ok then break $)3 $)2 repeat /* UNTIL pp = pp.before DO $(2 left () IF NOT ok THEN move.back() $)2 */ ok := false $)1 let find.back () be $(1 fp.before := fp limit := lim!this.unit if pp = ms.back then $(2 left () if not ok then move.back () $)2 $(2 verify.back () if ok then return left () if not ok then $(3 limit := limit - 1 if limit = 0 then break move.back () if not ok then break $)3 $)2 repeat /* UNTIL fp = fp.before DO $(2 right () IF NOT ok THEN move () $)2 */ ok := false $)1 . // End of ECCE3