!Version E6 introduces an 'unwind' facility. As the edit session proceeds, a ! note is taken of changes to the file, in as cryptic a manner as possible, in ! byte integer array un. ! The user can now give a command line in the format '->n', where n is a number ! (default 1. 0 and * have their usual meanings). The un array is then used ! to unwind (or 'undo') the editing by that number of command lines. The ! settings of other items by use of '%' commands are not saved and thus remain ! as they were when the '-' command was used. This includes the macros ! and the secondary input & output files. ! If the command is given as '-n', then the last n command lines which changed ! the file are unwound. ! Simple text formatting has been added, using basic command 'A' ('Adjust') in ! primary input mode, and %A to define parameters. 'A' in secondary input mode ! ('Abstract') is not affected. ! 'A' formats paragraphs. A paragraph is delimited by blank lines, or the ! start or end of the file. If the current position is within a paragraph when ! 'A' is obeyed, that paragraph is Adjusted. The current position is then ! moved to the next non-blank line, i.e. it traverses at least one blank line ! (the paragraph terminator), and possibly more. If the current position is on ! a blank line when 'A' is obeyed, it merely causes a move to the next ! non-blank line. ! What does 'A' do? If the first line of the paragraph starts in column one, ! then 'A' will line-fill the paragraph, using the third %A parameter ('line ! length'). If the first line of the paragraph starts with a space character, ! then the paragraph is line-filled as before, but with the first line indented ! by the second %A parameter ('paragraph indent'), and the WHOLE paragraph ! given a left margin of 'margin' spaces (the first %A parameter). Multiple ! spaces are preserved, except at the start of lines where any spaces are ! ignored (apart form the first line, where a space character has a special ! significance as described above). ! If a line FINISHES with a space then that line is not reformatted, except ! that initial spaces are replaced by 'margin' spaces, if applicable. This ! also applies to the first line of a paragraph, but it will not have ! 'paragraph indent' applied in this case. This facility is provided as a ! simple way of preventing tables etc. from being line-filled. ! The %A parameters are reported by >%A , and can be set by a command of the ! form >%A=a,b,c where a, b and c are integers. If any is omitted then the ! corresponding parameter retains its previous value. Thus the following ! inputs are all valid: ! Like the macros etc., the %A values can be saved in the ! profile by use of %P. Their default values are 0,0,80 . ! Note that the second parameter, 'paragraph indent', can be negative - this is ! useful for numbered or lettered lists where the first line sticks out to the ! left. The other values are set to 0 if given as negative. ! Some tidying up of the source has also been carried out: fp becomes cp (for ! 'current position') and tfp becomes fp. All comments are now in lower case. ! (August 1982) !Version E5 causes Int: W, X and Y (and w, x and y) to be noted and the editing ! to be saved in file ECCE#BACKUP (see %B in version E4). These can occur when ! the System is still running but has become inaccessible due to a communicat- ! ions failure. In addition, a warning message is output if ECCE#BACKUP is ! found to exist at the start of the edit session. ! It is also now possible to call other commands while editing. The format ! is '! command parameters'. The parameters are deemed to start after ! the first '(' in the line, or after the first space if there is no '(' in ! the line. Spaces between '!' and the command verb are discarded. ! I have withdrawn the meaning of '!' on its own ('repeat indefinitely the ! previous command line') because it was never documented and now might be ! given inadvertently. Various checks are made on return from the command that ! none of the files used by ECCE has been tampered with. The edit is aborted ! if the work file has been changed, but this is unlikely to occur. Note that ! ECCE can be called. Appropriate warning messages are output if the other ! files have been altered. ! (August 1982) !Version E4 introduces %B to copy the current state of the file to ECCE#BACKUP, ! F- to search backwards, %W (e.g.) to print out the current value of the ! W macro, and a message whenever a file is written to. ! (July 1982) !Version E3 makes use of the profile facility, in which each user has his ! own profile (held in SS#PROFILE), which for ECCE specifies the initial ! values of %U/%L and %Q/%M/%F and the macros %W %X %Y %Z. The first time ! that a user calls version E3 of the program, he gets a message summarising ! the facility. The user can set up his profile at any time by using the new ! command %P. This stores the prevailing values of the above items. ! By this means it will be possible to combine the service version of ECCE, the ! E series (my own developments) and IMPMOD (a version of ECCE with predefined ! macros to assist in the translation of programs from IMP to IMP80). ! Edinner is a routine again. The rather elaborate noting of the earliest ! change has been discarded. The file is written back unless there have been ! no changes at all. ! (May 1982) !Version E2 improves the file handling: the input file is not immediately ! copied to the workfile. Instead the pointers after the hole point at the ! input file. It cannot of course be changed, but if the user never ! changes the file, the hole never moves from the start and so the input ! file is never moved to the workfile. This represents quite a saving ! in page write-outs. ! In addition, edinner has been made a function. It returns the displacement ! from the start of the file of the first change to the file. This value ! can then be used in deciding how to produce the output file. If the ! output file is the input file, then (given certain conditions to ensure ! that the move is correct) it is possible to copy only the changed part, ! having connected the output file in write mode. ! (April 1982) !Version E1 introduces W as a macro and predefines W, X, Y and Z (see code). ! The entry points are E, S, R. ! (April 1981) ! The following notes refer to service versions of ECCE (held in source form ! as ERCC63.PDECCE_HDEDITnS). The 'E' series (above) is derived from the ! versions below. The 'E' versions are held in ERCC63.PDE_EnS. !Version 24 introduces ^....^ for text marking, and @ to reference last text ! marked. Thus i@ inserts last text marked, at current position. !Version 23 corrects an error in d. Also enables '`' to be used as a delimiter. !Version 22 corrects some errors in the moving of the hole. !Version 21 has l and r in sin. Also the hole can be left behind - it is ! brought up to fp only when text is to be added or removed. tfp ! always points to the first character after the hole. !Version 17 has c,%l,%u + %s=file,%o=file +pd members output + l,r in sin. !Version 9 has %check removed. !Version 7 includes recap. !Version 6 allows invert in sin mode + %check. !This version includes l (look). !File based heavily on version 2.1 of EMAS 4/75 version of Hamish !Dewar's compatible text editor. ! ECCE for EMAS: V 2.1 08/03/77 !! systemroutinespec changefilesize(string (31) file, integer newsize, integername flag) externalroutinespec prompt(string (15) s) systemroutinespec move(integer bytes, from, to) conststring (1) snl=" " systemroutinespec trim(string (31) s, integername flag) systemroutinespec psysmes(integer root, flag) recordformat finf(integer conad, filetype, datastart, dataend) systemroutinespec connect(string (31) s integer a,m,p, record (finf)name r integername f) systemroutinespec outfile(string (31) s integer l,m,p, integername c,f) systemroutinespec newgen(string (31) s,t integername f) systemroutinespec rename(string (31) s,t integername f) systemroutinespec destroy(string (31) s, integername f) systemintegermapspec comreg(integer i) systemroutinespec setfname(string (40) name) systemroutinespec sendfile(string (31) file, string (16) dev, string (11) name, integer copies, forms, integername flag) systemroutinespec modpdfile(integer ep, string (31) pdfile, string (11) memb, string (31) infile, integername flag) externalstringfnspec uinfs(integer type) externalintegerfnspec uinfi(integer type) externalintegerfnspec exist(string (31) filename) externalroutinespec read profile(string (11) key, name info, integername version, flag) externalroutinespec write profile(string (11) key, name info, integername version, flag) routinespec connect input(string (255) file, integername head, start, size, f) routinespec makeupper(stringname s) routinespec sendoutput(string (31) file, out, integername flag) integerfnspec checkoutputfile(string (31) s) integerfnspec check distinct(string (31) s, t) endoflist constbyteintegerarray upper(0 : 255) = c 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 constbyteintegerarray lower(0 : 255) = c 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 list routine edinner(integername whead, wtop, wend, shead, stop, send, string (31) work, secinput) ! [wtop, wend) give the address range of the work file ! [stop, send] give the address range of the input file (by default the secondary file) ! On return, the edited file is given by [wtop,wend)+[stop,send]. constinteger p version=4; ! Version of profiling. constinteger stopper=-5000; !Loop stop constinteger hole min=256; !Minimum permissible hole size. integer in disp; !Input file displacement (wrt workfile). integername mon; !Monitor indic integer print1, print2; !Print indics integer cmax; !Command cell max string (2) prom; !Command prompt integer ci; !Command index integer ti; !Text index integer code; !Command code integer snum; !Search limit number integer codesnum; !Snum/code integer text; !Text string pointer integer num; !Repetition number integer lenx; !Text length integer len; !Text length (-1) integer lend; !Line end (ad) integer sin; !Secondary input ind integername top, end, lbeg, pp, fp, cp; ! Pointer variables to current file. integer mtop, mend, mlbeg, mpp, mfp, mcp; !Variables relating to main file. integer slbeg, spp, sfp, scp; !Variables relating to secondary file. integer ms; !Match start (ad) integer ml; !Match limit (ad) integer seconad; !Addr of secondary output string (31) secoutput; !Secondary output file string (9) outwork; !Secondary output workfile record (finf) r string (31) tempname integer marker; !For note integer cbase; !Command base (const ad) integer tbase; !Text base (const ad) integerarray cc(1 : 404); !Command sequence (4*101) byteintegerarray tt(1 : 255); !Text strings byteintegerarray attt(1:255); !For @ string. integer atlend, ataddr, atlen, atbase integer type, ctype, pend, chain; !Command input vars integer i, j, cp0, cp1, sym, k, lim, flag, margin, cline, npp integer showflag; ! = 192 if called from show integername mask; !Case bit mask for %l and %u integer range; !End pointer for text location byteintegerarray copytext(1 : 80); !For case converted locate text integer adcopytext; !Address of array byteintegerarrayformat bform(0 : 255) byteintegerarrayname convert byteintegerarrayname stored; !Defs of w,x,y,z (4 * 128 bytes) integer pos1, pos2, pos3, pos4; !Def pointers integer stype, btype, mynl, dr0, dr1; !Assembler variables integer accdr0, accdr1, assvar; !More assembler variables integername amargin, apgap, aline integer oldpp, oldfp, un0, up0, up1, up; ! Unwinding variables. byteintegerarray un(0:4095); ! Unwind storage array. string (50) command, parms integer pvsn; !For profile handling recordformat prof f(integer mon, mask, byteintegerarray stored(0:512), integerarray adparm(1:3)) record (prof f) prof systemroutinespec reroute contingency(integer ep, class, longinteger mask, routine close(integer a,b), integername flag) systemroutinespec signal(integer ep, class, subclass, integername flag) !Symbol types:- 0:num, 1:termin, 2:illegal, 3:quote, ! 4:f, 5: d,t,u, 6: i,s,v, 8:m,e, 10: g,k !Bits 2**7,6=11 indicates command valid only in sin mode !Bits 2**7,6=01 indicates command valid in both modes !Bits 2**7,6=00 indicates command valid only in primary input mode !Bits 2**5,4 gives % command sub-codes constbyteintegerarray symtype(33 : 95) = c 64, 3, 3, 3, 2, 3, 3,75,73,64, 3,76, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3,64, 3, 90,26,24, 5, 8,116,10, 2, 6,10,10,90,120,202,18, 90,50,74,22,69,21,70, 32,32,32,32, 3,74, 3, 78, 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 [ ¬ ] ^ _ ! Workfile: ! |.............| (hole) |............................| ! ! ! ! ! ! ! top pp fp cp (>=fp) end routine readsym !READ COMMAND SYMBOL if pend # 0 then sym = pend and pend = 0 else start while pos4 # 0 cycle ; !Macro expansion sym = stored(pos4) pos4 = pos4+1 if sym # nl then return pos4 = pos3; pos3 = pos2; pos2 = pos1; pos1 = 0 repeat readch(sym) finish end routine read item cycle type = 1 read sym until sym # ' ' if sym < ' ' then return ; !Treat any control as nl sym = upper(sym); !Ensure upper case if sym>=96 then type = symtype(sym-32) c else type = symtype(sym) if type&15 # 0 then return ; !Return unless numeric or w,x,y,z if type # 32 then exit ; !W,x,y,z macro calls pos1 = pos2; pos2 = pos3; pos3 = pos4 pos4 = (sym-'W')<<7+1 repeat if type=0 start ; !Decimal digit num = sym-'0' cycle read sym exit unless '0' <= sym <= '9' num = 10*num+sym-'0' repeat pend = sym finish else start type = 0; num = 0 num = stopper+1 if sym = '?' num = stopper if sym = '!' finish end routine iwrite(integer a) if a<0 then printch('-') and a = -a iwrite(a//10) if a>=10 printch('0'+a-a//10*10) end ; ! iwrite. routine print line constinteger marker = '^' integer p print1 = lend; print2 = pp+cp p = lbeg p = fp if p = pp while p # lend cycle printch(byteinteger(p)) p = p+1 p = fp if p = pp printch(marker) if num = 1 and p = cp repeat printstring("**end**") if p > end printch(nl) end routine find lbeg lbeg = cp+1 lbeg = lbeg-1 until lbeg=fp or byteinteger(lbeg-1)=nl if lbeg=fp start lbeg = pp+1 lbeg = lbeg-1 until lbeg=top or byteinteger(lbeg-1)=nl finish end ; ! Of %routine find lbeg. routine find lend(integername err) integer j ! lend = fp ! -> ok %if fp > fend %or byteinteger(fp) = nl ! %until byteinteger(lend) = nl %cycle ! lend = lend+1 ! %repeat !*m* mcode locate line end !Increase lend until it points to nl err = 0 lend = cp return if cp > end or byteinteger(cp) = nl j = end-lend+1 *ldtb_stype *ldb_j *lda_lend; !Search from lend *lb_mynl; !Load B reg with nl *put_x'A300'; !SWNE *jcc_8,<abdn>; !Not found -> *std_dr0; !Store descriptor lend = dr1; !Set result !*e* locate return abdn: err = 1 end ; ! Of %routine find lend. routine unchain l1: text = chain if text # 0 start chain = integer(text+4) integer(text+4) = ci -> l1 if integer(text) # 'X' finish end routine switch to secondary file top == stop; end == send lbeg == slbeg pp == spp; fp == sfp; cp == scp end ; ! of switch to secondary file. routine switch to main file top == mtop; end == mend lbeg == mlbeg pp == mpp; fp == mfp; cp == mcp end ; ! of switch to main file. routine switch modes if sin = 0 start ; ! Switch to secondary mode switch to secondary file sin = -1; prom = ">>" finish else start switch to main file sin = 0; prom = ">" finish end ; ! Of %routine switch modes. ! The following routines are used in the storage of the editing, and in ! 'unwinding' the editing when the user requests it. routine un val(integer value, byteinteger type) ! Stores a value and a type of change in the un array. Also updates ! the pointer up. ! Format in array un is [ [text] [padding] value type ] ... ! The padding is to ensure that value (a 4-byte integer) is always ! word aligned. It follows that type (a byte integer) is also word ! aligned, and that text, if present, starts one byte after a word ! boundary. integer p return if byteinteger(un0+up&4095)=type#255; ! Same as last one - ignore. up = up+8 integer(un0+(up-4)&4095) = value byteinteger(un0+up&4095) = type return unless type=255; ! Start of command line. ! See if record of command line just completed has overwritten itself or ! overwritten the start of the editing record. We have: ! up0 < up1 <= up ! where up0&4095 points to the start of the editing record ! up1&4095 points to the start of the command line record ! up0&4095 points to the last type stored if up-up1>4096-8 start ! Command line has overwritten itself. ! Correct pointers (none of the editing can be saved) up0 = up-8 integer(un0+(up0-4)&4095) = 0 byteinteger(un0+up0&4095) = 0 finish else if up-up0>4096-8 start ! Start of editing record overwritten. Throw away early command lines. cycle p = up0+12 p = p+4 while 247#byteinteger(un0+p&4095)#255 ! Here we are scanning for a "start of command line" code. ! In so doing we are scanning what could be stored text, but ! the byte patterns being sought do not correspond to printable ! symbols, so should not prove a problem. This might not be ! true if the technique were applied to non-printable material. up0 = p-8; ! New record start position (possibly). repeat until up-up0<=4096-8 integer(un0+(up0-4)&4095) = 0 byteinteger(un0+up0&4095) = 0 finish up0 = up0&4095; up = up&4095 up = up+4096 if up<up0 up1 = up; ! Points to start of new command line ! Now look for previous command line in array. If no ! changes have occurred to the file between the two then mark ! the earlier one as not a stopping point. p = up-8 p = p-8 while byteinteger(un0+p&4095)=6; ! Hole movement - does not change file. byteinteger(un0+p&4095) = 247 if byteinteger(un0+p&4095)=255 end ; ! Of %routine un val. routine un text(integer from, to, save, byteinteger type) integer textp, size, i size = to-from textp = up+1; ! Pointer to text position. up = ((textp+size+3)>>2)<<2+4 textp = textp&4095 while size#0 cycle i = 4096-textp; ! Space to end of un array. i = size if i>size move(i, from, un0+textp) textp = (textp+i)&4095 size = size-i from = from+i repeat integer(un0+(up-4)&4095) = save byteinteger(un0+up&4095) = type end ; ! Of %routine untext. routine update un pointers ! Note: only called when in primary mode. if pp#oldpp start if pp<oldpp then un text(pp, oldpp, oldpp, 2) else un val(oldpp, 3) oldpp = pp finish if fp#oldfp+in disp start if fp>oldfp+in disp then un text(oldfp+in disp, fp, oldfp, 4) c else un val(oldfp, 5) oldfp = fp-in disp finish end ; ! Of %routine update un pointers. routine mark command line update un pointers unval(cp-in disp, 255) end ; ! Of %routine mark command line. routine reval(integer change) ! Restores stored file changes (held in array un). ! If change=0, then reaching the start of any command line causes reval to terminate. ! If change#0, then only file-changing command lines cause termination. ! Type settings: ! 0 - start of recording (should not occur here) ! 1 - unused ! 2 - pp change with text between two positions ! 3 - pp change ! 4 - fp change with text between two positions ! 5 - fp change ! 6 - pp (for hole movement) ! 247 - cp change (does not terminate reval) ! 255 - cp change (terminates reval) byteinteger type integer val, to, size, textp, i switch sw(0:7) cycle type = byteinteger(un0+up) up = (up-4)&4095 val = integer(un0+up) ->sw(type&7) sw(7): cp = val+in disp up = (up-4)&4095 exit if change=0 or type=255 continue sw(3): pp = val up = (up-4)&4095 continue sw(5): fp = val+in disp up = (up-4)&4095 continue sw(2): ! pp with text (pp<val) size = val-pp; to = pp; pp = val ->copy text sw(4): ! fp with text (val<fp) val = val+in disp size = fp-val; to = val; fp = val copy text: up = (((up-size-1)>>2)<<2)&4095 textp = up+1 while size#0 cycle i = 4096-textp i = size if i>size move(i,un0+textp,to) if wtop<=to<=wend+1 textp = (textp+i)&4095 to = to+i size = size-i repeat continue sw(6): ! move the hole so that pp becomes val. if val<pp start size = pp-val fp = fp-size; pp = pp-size move(size, pp, fp+in disp) if wtop<=fp+in disp<=wend+1 finishelsestart size = val-pp move(size, fp+in disp, pp) fp = fp+size; pp = pp+size finish up = (up-4)&4095 continue sw(1): ! Unused. printstring("**unwinding record corrupt - edit abandoned.".snl) monitor ; stop sw(0): ! Start of editing record. up = (up+4)&4095 exit repeat end ; ! Of %routine rval. routine unwind editing(integer change) ! num (global variable) is the number of command lines to be unwound, ! if possible. This corresponds to the number of cp settings to be ! obeyed in array un. ! If change=0, then reaching the start of any command line causes rval to terminate. ! If change#0, then only file-changing command lines cause termination of rval. mark command line; up = (up-8)&4095 print1 = 0; ! So that current line will be printed out. cycle reval(change); ! Rewinds editing back to the start of a command line. if byteinteger(un0+up)=0 start ; ! Start of recording. printstring("**start of editing record**".snl) exit finish num = num-1 repeat until num=0 oldpp = pp oldfp = fp-in disp find lbeg end ; ! Of %routine unwind editing. ! End of routines relating to unwinding of editing. routine move hole integer j update un pointers atlend=0; print2 = 0 j = cp-fp returnif j=0 lbeg = lbeg-(fp-pp) if fp<=lbeg<=cp; !Assumes that hole is moving to current line move(j,fp,pp) un val(pp, 6); ! Note movement of hole. pp = pp+j fp = cp oldpp = pp; oldfp = fp-in disp end ; !Move hole. routine transfer input ! Transfers remainder of input file to work file. integer i, j j = mend+1-fp; ! Amount to move. i = wend-(mend-fp); ! Destination. move(j,fp,i) j = cp-fp fp = i in disp = 0; ! Used by unwinding code. print2 = -1 if print2=pp+cp cp = fp+j unless wtop<=cp<=wend+1 print2 = pp+cp if print2=-1 lbeg = lbeg+wend-mend unless wtop<=lbeg<=wend+1 ! i.e. unless already referring to work file. print1 = -1 if print1=lend lend = lend+wend-mend unless wtop<=lend<=wend+1 print1 = lend if print1=-1 mend = wend end ; ! Of %routine transfer input. routine fail save(integer class, subclass) ! Called after W, X or Y interrupt (uc or lc). Writes editing to ECCE#BACKUP. integer conad, flag, i reroute contingency(0, 0, 0, failsave, flag) ! Now write to file. i = mpp-mtop + mend-mfp+1 + 32; ! 32 for file header. destroy("ECCE#BACKUP", flag) outfile("ECCE#BACKUP", -i, i, 0, conad, flag) if flag=0 start ; ! OK integer(conad) = i; ! Set file size in header. integer(conad+12) = 3; ! Character file. i = conad+32 move(mpp-mtop,mtop,i); ! Part before hole. i = i+mpp-mtop move(mend-mfp+1,mfp,i); ! Part after hole. finish signal(3, class, subclass, flag) end ; ! Of %routine fail save. integerfn verify file(string (31) file, integer conad) record (finf) r integer flag result = 0 if file="" or conad=0 connect(file, 0, 0, 0, r, flag) result = 0 if flag=0 and r_conad=conad result = 1 end ; ! Of %integerfn verify file. routine call(string (31) command, string (255) param, integer name flag) system routine spec enter(integer mode,dr0,dr1, string (255) param) system routine spec findentry(string (31) entry, integer type,dad, string name file, integer name dr0,dr1,flag) system routine spec load(string (31) name, integer type, integer name flag) system routine spec unload(integer curgla) system long integer fn spec loadep(string (31) entry, integername type, flag, integer load level) system integer fn spec currentll system routine spec unload2(integer ll, failstate) integer savecomreg44,dr0,dr1,type,ll,status longinteger desc string (1) dummys savecomreg44 = comreg(44) if uinfi(26)=0 start ; ! Old loader. load(command,0,flag) ->err if flag#0 findentry(command,0,0,dummys,dr0,dr1,flag) ->err if flag#0 enter(2,dr0,dr1,param) unload(savecomreg44) finishelsestart ; ! New loader. ll = currentll type = 2; ! Code type being sought. desc = loadep(command, type, flag, ll) if flag=0 start ; ! Successfully loaded. ! desc contains descriptor. dr0 = desc>>32 dr1 = desc&x'000ffffffff' enter(2,dr0,dr1,param) status = 0 finishelse status=1 unload2(ll,status) finish err: psysmes(73+showflag//192,flag) if flag#0 end ; ! of call switch vsn(0:p version) switch c(0 : 14) switch s('@' : '¬') switch pc('A' : 'U'); !For independent % commands comreg(24) = 0; !Set return code stype = x'58000000'; !String descriptor btype = x'18000000'; !Byte descriptor mynl = 10; !Newline amargin == prof_adparm(1) apgap == prof_adparm(2) aline == prof_adparm(3) mon == prof_mon mask == prof_mask stored == prof_stored ! Now read profile info for this user. read profile("ECCE", prof, pvsn, i) pvsn = p version if pvsn>p version -> vsn(pvsn) vsn(0): ! No profile info stored. Set it up with basic defaults. vsn(1): vsn(2): mon = 0 mask = 32 string(addr(stored(0))) = snl string(addr(stored(128))) = snl string(addr(stored(256))) = snl string(addr(stored(384))) = snl if i>4 start printstring("Profile file cannot be accessed. Default options assumed.".snl) finish vsn(3): printstring("**Additional facilities in this version of ECCE. Please VIEW(SUBSYS.NEWECCE) for details.".snl) amargin = 0 apgap = 0 aline = 80 vsn(4): pvsn = pversion and write profile("ECCE",prof,pvsn,i) if pvsn#p version ! End of profile reading and analysis. if mask = 0 then convert == array(addr(lower(0)), bform) else c convert == array(addr(upper(0)), bform) print1 = 0; print2 = 0 cmax = 0; ms = 0; ml = 0 pos1 = 0; pos2 = 0; pos3 = 0; pos4 = 0 tempname = "" marker = 0 secoutput = ""; outwork = "" num = 0 adcopytext = addr(copytext(1)) seconad = 0 tbase = addr(tt(1)); cbase = addr(cc(1)) atbase = addr(attt(1)) attt(1) = 0; atlen = -1 atlend = 0 ! On entry stop and send point to the primary input file. Thus, a) the ! primary input file is by default the secondary input file also, and ! b) we use stop and send when assigning 'm' variables to the right of the hole. mtop = wtop; ! mtop never changes from this value (separate vars strictly unnecessary). mend = send; ! Initially, "main" pointers to right of hole refer to input. mlbeg = mtop mpp = mtop mfp = stop mcp = mfp slbeg = stop spp = stop sfp = stop scp = sfp ! The 'm' variables refer to the main input - initially a combination of ! the work file and the input file. ! The 's' variables refer to the secondary input - by default the input ! file. switch to main file; ! This points top, lbeg, pp, etc at the 'm' variables. ! 'Unwinding' variables. un0 = addr(un(0)); integer(un0) = 0 up0 = 4; un(up0) = 0; up1 = up0; up = up0 in disp = send-wend; ! Displacement of input file wrt work file. Used in unwinding. oldpp = pp oldfp = fp-in disp; ! oldfp is the last value fp would have had in the workfile. if mtop=stop then sin = -1 and showflag = 192 else start ! When edinner is called from show, the 'main' variables and the 'secondary' ! variables have the same values - the input file is the 'main' file and ! the 'secondary' file. sin = 0 showflag = 0 if exist("ECCE#BACKUP")#0 start printstring(c "**Warning: When you last used ECCE, a copy of your edited file was made, either when you gave the command %B to ECCE or when the System went down. This is called ECCE#BACKUP. It will be destroyed if you leave ECCE".snl) printstring(c " by typing %C. If you want to keep it either leave ECCE now by using Int:A, and rename it before using ECCE again, or rename it without leaving ECCE by typing:".snl.snl) printstring(c " >!RENAME ECCE#BACKUP,newname where newname is not the name of one of your current files.".snl) finish reroute contingency(3, 65, X'700000007'<<('W'-64), failsave, i) ! This causes Int: W, X or Y (or w, x or y) to be trapped. finish sym = nextch; ! Force out initial prompt. skipsymbol if sym=nl prom = ">" !Find end of current line set: lend = cp lend = lend+1 while lend < end and byteinteger(lend) # nl ! lend now either points to nl at end of current line, or to eof. !Monitor current line c0: -> c1 if sym # nl -> c1 unless (mon >= 0 and print1 # lend) or (mon > 0 c and print2 # pp+cp) num = 1; print line !Read command line c1: prompt(prom) ci = cbase; ti = tbase; pend = 0; chain = 0 read item until type # 1; !(ignore nls) if type = 0 start ; ! Repetition or ! command. if sym='!' start ; ! Subsystem command (probably). parms = uinfs(1); ->erq if charno(parms,4)='U'; ! No students!! ! First read command line command = "" readsym until sym#' ' for i = 1,1,50 cycle exit if sym=nl command = command.tostring(sym) readsym repeat ->c1 if command=""; ! Ignore. unless command -> ("(") start command = command."(".parms if command -> command.(" ").parms finish command = command.parms while command -> command.(" ").parms ! Now command contains a '(' character before the parameters, if any. parms = ")" unless command -> command.("(").parms length(parms) = length(parms)-1 if charno(parms,length(parms))=')' make upper(command); make upper(parms) for i = 1,1,length(command) cycle j = charno(command, i) ->erq unless 'A'<=j<='Z' or (i>1 and '0'<=j<='9') repeat if showflag=0 start if sin=-1 then j = 1 and switch modes else j = 0 transfer input unless wtop<=fp<=wend+1; ! To avoid problems with input file. switch modes and find lend(j) if j=1 finish i = integer(whead+20); ! Date last connected in write mode. call(command,parms,flag) ->c1 if flag#0; ! Failure, so no problem with files. flag = verify file(work, whead); ! Workfile. if flag#0 or integer(whead+20)#i start printstring("**ECCE workfile changed or destroyed - edit abandoned.".snl) if showflag#192 printstring("**File ".work." changed or destroyed - show abandoned.".snl) if showflag=192 stop finish flag = verify file(secinput, shead) unless stop=0 if flag#0 start printstring("**Warning: %S undefined - redefine if wanted.".snl) stop = 0; send = -1 scp = stop; slbeg = stop spp = stop; sfp = stop flag = 0 finish flag = verify file(outwork, seconad) if flag#0 start printstring("**Warning: %O workfile corrupted. Redefine %O before use.".snl) seconad = 0 finish ->c1 finish ; ! End of !Command code. ->er2 if cmax=0 integer(cmax+8) = num read item; -> er1 if type # 1 -> go finish if sym = '%' start read sym sym = upper(sym) code = sym -> er5 if code < 'A' ctype = symtype(code)>>4&3 -> c(ctype) finish if sym='-' start ; ! Undo some editing. ->er2 if sin#0; ! Only allowed in primary input mode. read item if sym='>' then i = 0 and read item else i = 1 if type=0 then read item else num = 1; ! Number read (assigned to num). ->er2 unless type=1; ! Should be a separator. ! Thus ->3 causes last 3 command lines to be unwound, ! and -3 causes last 3 'changing' command lines to be unwound. unwind editing(i) ->set finish c2: ctype = type&15; -> er2 if ctype < 4 -> er0 if (¬sin!!type)&192 = 0 ! 192= 2**6 + 2**7. SEE COMMENTS ABOVE SYMTYPE DECLARATION. ! SIN= 0 IF IN PRIMARY INPUT ! =-1 IF IN SECONDARY INPUT code = sym; !Command letter text = 0; num = 1; len = 0; !Default values read item; ! next item known -> c(ctype) c(4): !find if sym='-' start ; ! F- code = 'Q' read item finish num = 0 unless type = 0; ! Default search range for f or f- is whole file. c(5): !+del,trav,uncover code = num<<7+code; num = 1 read item if type = 0 c(6): !+insert,subst,verify -> er4 if type # 3 if sym='@' start text = atbase len = atlen -> c81 finish text = ti i = sym cycle read sym exit if sym = i if sym = nl then pend = nl and exit -> er6 if ti-tbase = 255 byteinteger(ti) = sym; ti = ti+1 repeat len = ti-text-1; !length - 1 -> c81 c(8): !move, erase, case -> c90 unless sym = '-' if code = 'C' then code = 'H' else code = code+10 ! 'c' to 'h', 'e' to 'o', 'm' to 'w'. c81: read item -> c91 c(9): !Close bracket unchain; -> er3 if text = 0 ! unchain makes text point at the corresponding open bracket ! and gives ',' and '(' the address of this ')' instruction. code = 'Z'; integer(text+8) = num c(10): !get, kill, n, a, etc. c90: -> er1 if type = 3; ! No text string permitted. c91: read item if type = 0 -> put c(14): ! ^ (@ string marker). code = '@' -> put; ! no repetition allowed. c(11): !open bracket code = 'X' -> c95 c(12): !comma code = 'Y' read item if type = 1; !Ignore following nl c95: ! Chain set to current command address and later integer(ci+4) set to text - ! the previous chain value. (ci+4) is set to the corresponding ')' instruction ! address (by unchain). text = chain; chain = ci num = 0 put: integer(ci) = code; integer(ci+4) = text integer(ci+8) = num; integer(ci+12) = len ci = ci+16; -> er6 if ci-cbase > 1600 -> c2 unless type = 1 unchain; -> er3 if text # 0 cmax = ci integer(ci) = 'Z'; integer(ci+4) = cbase-16; ! "Global" brackets. integer(ci+8) = 1; integer(ci+12) = 0 -> go er0: if showflag = 0 then printstring("Secondary input") c else printstring("Show") -> er2 er1: printch(' ') printch(code) er2: code = sym -> er5 er3: printstring("Brackets") -> erq er4: printstring("Text for") c(0): er5: printch(' ') printch('F') and code = '-' if code&127='Q' printch(code&127) -> erq er6: printstring("Size") erq: printch('?') printch(nl) er7: cmax = 0 if ci # cbase sym = pend if pend # 0 skp: -> c1 if sym = nl; read sym -> skp !Execute command line go: mark command line if sin=0; ! For unwinding ci = cbase-16 get: ci = ci+16 codesnum = integer(ci); text = integer(ci+4) num = integer(ci+8); len = integer(ci+12) code = codesnum&127 -> s(code) lok: find lend(i) -> abdn if i#0 ok: num = num-1 -> get if num = 0 or num = stopper -> s(code) s(92): !invert no: -> get if num <= 0 ci = ci+16 -> get if integer(ci) = 92; ! I.e. if next code is inversion. while integer(ci)&127 <= 'X' cycle ;! Skipping for ',' ')' or '¬' ci = integer(ci+4) if integer(ci) = 'X'; ! Skip past corresponding ')' if a '(' ci = ci+16 repeat num = integer(ci+8) -> no unless ci = cmax; ! Test for inversion or keep skipping if not the end of the command string -> c0 if num <= 0 ! Failure does not matter in this case. Or could be alternative execution (comma). !Execution error printstring("Failure: ") if code='O' or code='W' or code='H' or code='Q' start if code='H' then code = 'C' else if code='Q' then c code = 'F' else code = code-10 printch(code); code = '-' finish printch(code) if text # 0 start printch('''') while len >= 0 cycle printch(byteinteger(text)) text = text+1; len = len-1 repeat printch('''') finish printch(nl) print1 = 0 read ch(sym) while sym # nl; ! Throw away other command strings on current line -> c0 !Individual commands s('X'): !open bracket integer(text+8) = num; ! Sets the repetition count at the corresponding close bracket -> get s('Z'): !Close bracket num = num-1 if num = 0 or num = stopper start -> get unless ci = cmax -> c0 finish integer(ci+8) = num ci = text -> get s('Y'): !comma ci = text-16 -> get s('R'): !right-shift if num<=0 then cp = lend else cp = cp+num cp = lend and ->no if cp>lend -> get s('L'): !left-shift -> no if lbeg=cp or (fp=cp and lbeg=pp) if cp = fp start transfer input unless wtop<=fp<=wend+1 and sin=0 fp = fp-1; pp = pp-1 byteinteger(fp) = byteinteger(pp) finishelsestart cp = lbeg+1 and num = 1 if num=0 and fp<=lbeg<cp finish cp = cp-1 ms = 0 -> ok s('@'): ! @ string marker. if atlend # lend start ; !New string being marked. ataddr=cp atlend=lend finishelsestart ; !Second marker - string now defined. atlend=0 i=cp-ataddr if i>0 then j=ataddr else j=cp and i=-i code='^' and -> no if i>255; ! String too long. atlen=i-1 k=j+i i=0 while j<k cycle byteinteger(atbase+i) = byteinteger(j) i=i+1; j=j+1 repeat ! Now scan command string array for @ references. j = cbase while j<cmax cycle integer(j+12)=atlen if integer(j+4)=atbase j=j+16 repeat finish -> ok s('E'): !erase move hole if num<=0 then cp = lend elsestart cp = cp+num cp = lend and fp = cp and ->no if cp>lend finish fp = cp -> get s('O'): !erase back move hole pp = lbeg and -> get if num<=0 pp = pp-num -> get if pp>=lbeg pp = lbeg; -> no s('C'): !case invert move hole cycle exit if cp=lend if 'A'<=byteinteger(cp)&x'DF'<='Z' then c byteinteger(pp) = byteinteger(cp)!!32 else c byteinteger(pp) = byteinteger(cp) pp = pp+1; fp = fp+1; cp = cp+1 num = num-1 repeat until num=0 or num=stopper ->no s('H'): !case invert backwards transfer input unless wtop<=fp<=wend+1 move hole cycle exit if pp=lbeg cp = cp-1; fp = fp-1; pp = pp-1 if 'A' <= byteinteger(pp)&x'DF' <= 'Z' then c byteinteger(cp) = byteinteger(pp)!!32 else c byteinteger(cp) = byteinteger(pp) num = num-1 repeat until num=0 or num=stopper ms = 0 -> no s('V'): !verify !*i* verify i = cp; k = cp+len+1 j = text while i<k and convert(byteinteger(i))=convert(byteinteger(j)) cycle i = i+1; j = j+1 repeat ->no if i<k ms = cp ml = i -> get; !No repetition count on v s('D'): !delete s('T'): !traverse j = 0 -> f0 s('U'): !uncover move hole s('F'): !find j = ms !* TEXT LOCATION !* NOTES: !* ms: address of string just located !* ml: address of byte after located string !* j: saved value of ms, or 0 to show that ms does not apply !* cp0: saved value of cp !* cp1: cp0, or last nl before current cp f0: !Save values, and find range of search ms = cp and ml = cp and -> ok if len<0 snum = codesnum>>7; !Line range count k = mask<<8!byteinteger(text); !First char case masked cp1 = cp; !Last nl before cp cp0 = cp; !Save cp cp = cp+1 if cp = j; !Dont find same twice dr1 = end+1; !In case of unlimited search i = cp while snum > 0 and i <= end cycle ; !Count nls to get range of search j = end-i+1; !Limit of search for nls *ldtb_stype *ldb_j; !Length *lda_i; !Start *lb_mynl; !Find nl *swne_l =dr *jcc_8,<abdn>; !Fatal error *std_dr0 i = dr1+1; !nl found snum = snum-1; !Decrement count repeat range = dr1-1 !* Convert text to upper case? lenx = len+1; !Text length if mask > 0 then start ; !Convert required *ldtb_btype; !First move it *ldb_lenx; !Length *lda_text; !From *cyd_0 *lda_adcopytext; !To *mv_l =dr dr0 = x'58000000'!LENX; !Now convert dr1 = adcopytext accdr0 = x'18000100' accdr1 = addr(convert(0)) *ld_dr0 *lsd_accdr0 *ttr_l =dr text = adcopytext finish until cp > range cycle ; !Find first char i = range-cp-lenx+2; !Length of search if i > 0 then start assvar = cp *ldtb_stype *ldb_i; !Length *lda_assvar; !Start *lb_k; !Required char *swne_l =dr *jcc_4,<f83>; !Found -> finish cp = range+1; !Set to bottom exit f83: !Char found: now compare with text *std_dr0; !Store desc cp = dr1 cycle i = 0,1,len if byteinteger(text+i) # convert(byteinteger(cp+i)) c then -> f85 repeat exit f85: ! match fails cp = cp+1 repeat !* Search complete i = cp+lenx; !Match end pointer cp1 = cp; !Reset cp1 cp1 = cp1-1 while cp1 # cp0 and byteinteger(cp1-1) # nl if cp > range start ; !Failure in complete range lend = cp cp = cp1 if code = 'U' start fp = cp lbeg = pp if cp1 > end finish else start lbeg = cp1 if cp1 # cp0 finish -> no finish !* Match successful - reset pointers ms = cp ml = i lbeg = cp1 if cp1 # cp0 and code # 'U' move hole if code = 'D' cp = ml if code = 'T' or code = 'D' fp = cp if code = 'U' or code = 'D' -> ok if cp1 = cp0 -> lok s('S'): !substitute -> no if cp # ms move hole cp = ml; fp = ml s('I'): !+insert -> ok if len < 0 move hole -> no if pp-lbeg > 160 or cp > end !*m* insert assvar = pp lenx = len+1 *ldtb_btype *ldb_lenx *lda_text; !From *cyd_0 *lda_assvar; !To *put_x'B300'; !Move pp = pp+lenx !*e* i1: -> ok unless pp<=cp<=pp+hole min -> abdn s('Q'): !find- ms = cp and ml = cp and ->ok if len<0 cp1 = cp snum = codesnum>>7; ! No of newlines max to traverse. k = convert(byteinteger(text)); ! First byte of string. lim = fp; ! cp must be >= lim. cycle ; ! scans back from current position. cp = cp-1 if cp<lim start i = 0 and exit if lim=top; ! Failure. lim = top; cp = pp continue finish j = convert(byteinteger(cp)) if j=nl start snum = snum-1 i = 0 and exit if snum=0; ! Out of range - failure. cp1 = cp; ! Marks the latest nl encountered. finishelseif j=k start ; ! Found first char of string. cp0 = cp; i = 1 for j=1,1,len cycle cp = cp+1; cp = fp if cp=pp i = 0 and exit unless convert(byteinteger(text+j)) = c convert(byteinteger(cp)) repeat exit if i = 1; ! Text found. cp = cp0; ! Failure - reset cp. finish repeat ! Move hole and reset pointers as necessary. if i=1 start ; ! Success. cp = cp0; ! Start of located string if byteinteger(cp1)=nl and cp1#lend start ; ! Moved to an earlier line. lend = cp1 ! Find lbeg j = cp cycle j = pp if j=fp lbeg = j j = j-1 repeat until lbeg=top or byteinteger(j)=nl finish finishelsestart ; ! Failure. if byteinteger(cp1)=nl and cp1#lend start cp = cp+1; lbeg = cp; lend = cp1 finishelse cp = cp1; ! Same line - pointer does not change. finish ! Now move text around as necessary. unless fp<=cp<=end+1 start ; ! Need to move hole. transfer input unless wtop<=fp<=wend+1; ! Can only be primary file here. j = pp-cp un val(pp, 6); ! Flag hole movement for unwinding. pp = pp-j; fp = fp-j cp = fp move(j,pp,fp) oldpp = pp oldfp = fp-in disp lend = lend+cp-pp if lend<cp finish if i=1 start ; ! Success ms = cp; ml = cp+len+1 ->ok finish ms = 0 ->no s('G'): !get (line from tt) cp = lbeg if fp<lbeg<cp move hole prompt(":") read ch(k) -> no if k = ':' transfer input unless wtop<=fp<=wend+1 or pp=lbeg while pp # lbeg cycle fp = fp-1; cp = cp-1; pp = pp-1 byteinteger(cp) = byteinteger(pp) repeat while k # nl cycle byteinteger(pp) = k; pp = pp+1 read ch(k) repeat s('B'): !+break move hole byteinteger(pp) = nl; pp = pp+1 lbeg = pp -> i1 s('P'): !print print line -> ok if num = 1 s('M'): !move -> no if cp > end lend = end and num = 1 if num = 0 and code = 'M'; ! M* cp = lend+1 lbeg = cp -> lok s('K'): !kill ->no if cp>end move hole pp = lbeg ! Move current position to start of appropriate line, and delete ! all lines traversed. if num=1 then num=0 and cp = lend+1 else c if num<=0 then cp = end+1 elsestart i = cp while num>0 and i<=end cycle j = end-i+1; !Limit of search for nls *ldtb_stype *ldb_j; !Length *lda_i; !Start *lb_mynl; !Find nl *swne_l =dr *jcc_8,<abdn>; !Fatal error *std_dr0 i = dr1+1; !nl found num = num-1; !Decrement count repeat cp = i finish fp = cp num = 1 and ->lok unless cp>end ! Failure here if num>0 lend = cp ->no s('J'): !join -> no if lend >= end cp = lend move hole -> no if pp-lbeg > 120 cp = lend+1; fp = cp -> lok s('W'): !move back ms = 0 !*i* move back -> no if lbeg = top print1 = 0 if num = 0 start ; !m-* num = 1 lbeg = top+1 cp = fp finish else if fp<lbeg<=cp start ! Start of current line is to right of hole. ! Note that lbeg is never equal to fp. lend = lbeg-1 lbeg = lbeg-1 until lbeg = fp or byteinteger(lbeg-1) = nl cp = lbeg -> ok unless lbeg = fp ! If lbeg=fp then start of previous line is to left of hole (or =pp). ! Note that cp=fp here. lbeg = pp+1 finish else cp = fp lbeg = lbeg-1 until lbeg = top or byteinteger(lbeg-1) = nl if pp>lbeg start ; ! Note: can only be in primary file. transfer input unless in disp=0 update un pointers j = pp-lbeg un val(pp, 6); ! Flag hole movement for unwinding. pp = pp-j cp = cp-j fp = cp move(j,pp,cp) oldpp = pp oldfp = fp-in disp finish -> lok s('N'): !note marker = cp -> ok s('A'): !adjust or abstract if sin=0 start ; ! Adjust cp = lbeg if fp<lbeg<cp move hole transfer input unless lbeg=pp or in disp=0 while pp#lbeg cycle fp = fp-1; pp = pp-1; cp = cp-1 byteinteger(fp) = byteinteger(pp) repeat ! Now have hole just before line, lbeg=pp, cp=fp. cycle ; ! num ->no if cp>end margin = -1 cycle ; ! Input line exit if fp=lend; ! Blank line. if margin=-1 start ; ! Look for first line of para. i = lbeg-1 i = i-1 while i>top and (byteinteger(i)#nl or byteinteger(i-1)#nl) i = i+1 unless i=top; ! i points to lbeg of first line. if i<lbeg start ; ! Move back to first line. transfer input unless in disp=0 unval(pp,6); ! For unwinding. j = pp-i; fp = fp-j; pp=i move(j,pp,fp) oldpp = pp; oldfp = fp-in disp lbeg = i cp = fp find lend(i) ->abdn if i#0 finish if byteinteger(fp)=' ' start ; ! Margin to be indented. margin = amargin i = margin+apgap; i = 0 if i<0 finishelsestart margin = 0 i = 0 finish ! Now output left margin for first line. cline = i npp = pp byteinteger(npp) = ' ' and npp = npp+1 and i = i-1 while i>0 finish ; ! Of paragraph initialisation. fp = fp+1 while byteinteger(fp)=' '; ! Skip over left margin fp = fp-1 if fp=lend ! Note that a line of spaces does not terminate a paragraph. if byteinteger(lend-1)=' ' start ! Do not format this line. if pp>top and byteinteger(pp-1)#nl start byteinteger(pp) = nl pp = pp+1 lbeg = pp finish i = margin byteinteger(pp) = ' ' and pp = pp+1 and i = i-1 while i>0 byteinteger(pp) = byteinteger(fp) and pp = pp+1 and c fp = fp+1 until fp=lend cline = aline; ! To force a line. finish ! Now output this input line. while fp#lend cycle if byteinteger(fp)#' ' start ; ! Start of a word. j = 1 j = j+1 while fp+j<lend and byteinteger(fp+j)#' ' if cline+j>aline start ! Word does not fit on line. Take a new line. byteinteger(pp) = nl; pp = pp+1 lbeg = pp i = margin; ! Initial spaces cline = margin npp = pp byteinteger(npp) = ' ' and npp = npp+1 and i=i-1 while i>0 finish ! Now place word. cline = cline+j j = fp+j pp = npp byteinteger(pp) = byteinteger(fp) and pp = pp+1 and c fp = fp+1 until fp=j npp = pp finishelsestart ; ! Space character. j = 1 j = j+1 while byteinteger(fp+j)=' ' fp = fp+j cline = cline+j npp = pp byteinteger(npp) = ' ' and npp = npp+1 and j = j-1 while j>0 finish repeat ! Now move to next input line. fp = lend+1; cp = fp find lend(i) -> abdn if i#0 exit if cp=lend ! exit if input line just dealt with was last of paragraph. if pp>lbeg and byteinteger(pp-1)#' ' start npp = pp byteinteger(npp) = ' '; npp = npp+1 cline = cline+1 finish repeat ; ! Input line ! Now find a non-blank line cycle byteinteger(pp) = nl; pp = pp+1; lbeg = pp exit unless fp=lend<=end fp = lend+1; cp = fp find lend(i) ->abdn if i#0 repeat num = num-1 repeat until num=0 or num=stopper ->get finish ! Abstract if showflag > seconad then -> no; !Require %o= in SHOW -> no unless top <= marker <= cp len = cp-marker; ! Size of extract. if seconad = 0 then start ; !Merge with primary switch to main file ->abdn if (pp-top) + (end-fp) + len + hole min > wend-wtop ! I.e. give up if < hole min bytes of spare space left move hole move(len,marker,pp) pp = pp+len; lbeg = pp switch to secondary file -> ok finish i = integer(seconad)+len; !Add to secondary output if i > integer(seconad+8) then start ; !Too small changefilesize(outwork,i,k) if k # 0 then start connect(outwork,3,i,0,r,k) changefilesize(outwork,i,k) if k # 0 then psysmes(45,k) and -> er7 !Extend fails seconad = r_conad finish integer(seconad+8) = ((i+4095)>>12)<<12; !Round up finish k = seconad+integer(seconad) move(len,marker,k) integer(seconad) = i -> ok !Special commands c(3): !%f, %m, %q mon = 'M'-code -> c1 c(2): ! %w, %x, %y, %z macro definitions read item j = (code-'W')<<7 printstring(string(addr(stored(j)))) and ->c1 if sym=nl -> er1 if sym # '=' i = j+1 cycle read sym stored(i) = sym byteinteger(addr(stored(j))) = i-j and ->c1 if sym=nl i = i+1 -> er6 if i&127=0 repeat abdn: printstring("Line or file too big.".snl) comreg(24) = 4 -> pc('C') c(1): !more % commands - l, u, s, c read item ->er1 if sym#'=' and type#1 -> pc(code) pc('A'): !Set or report 'Adjust' pointers. if sym#'=' start ! Print out current setting of parameters. printstring("Margin "); iwrite(amargin) printstring(snl."Paragraph indent "); iwrite(apgap) printstring(snl."Line length "); iwrite(aline) printch(nl) -> c1 finish ! Set adjust params. for i=1,1,3 cycle read item if sym='-' then j = -1 and read item else j = 1 prof_adparm(i) = j*num and read item if type=0 exit unless sym=',' repeat amargin = 0 if amargin<0 aline = 0 if aline<0 ->c1 if type=1 ->erq pc('B'): !Back up file ->er0 unless showflag=0 i = mpp-mtop + mend-mfp+1 + 32; ! 32 for file header. outfile("ECCE#BACKUP", -i, i, 0, j, k) if k#0 start printstring("Not enough workfile space. %C recommended.".snl) -> er7 finish integer(j) = i; ! Set file size in header. integer(j+12) = 3; ! Character file. j = j+32 move(mpp-mtop,mtop,j); ! Part before hole. j = J+mpp-mtop move(mend-mfp+1,mfp,j); ! Part after hole. printstring("File ECCE#BACKUP written to.".snl) -> c1 pc('L'): !lower mode mask = 0 convert == array(addr(lower(0)),bform) -> c1 pc('U'): !upper mode mask = 32 convert == array(addr(upper(0)),bform) -> c1 pc('S'): !switch input if showflag > 0 then -> c(0) mark command line if sin=0 cmax = 0; ! Prevents command line repetition, after mode switch. if sym = '=' then start ; !New sec input tempname = "" cycle i = 1,1,31 read sym until sym # ' ' unless nl # sym # ';' then exit tempname = tempname.tostring(sym) repeat makeupper(tempname) i = check distinct(tempname,secoutput) if i # 0 then psysmes(8,i) and -> er7; !Inconsistent file use connect input(tempname,j,k,len,i) if i # 0 then psysmes(8,i) and -> er7; !Connect fails secinput = tempname stop = k send = stop+len-1 send = send-1 while send >= stop c and byteinteger(send) # nl scp = stop; slbeg = stop spp = stop; sfp = stop switch modes if sin=0 finish else switch modes -> set pc('O'): !secondary output if seconad # 0 then start ; !Dispatch file if charno(secoutput,1) = '.' c then sendfile(outwork,secoutput,"EOUTPUT",0,0,i) c else sendoutput(outwork,secoutput,i) if i # 0 then psysmes(6,i) seconad = 0 finish secoutput = "" if sym # '=' then -> c1; !No param tempname = "" cycle i = 1,1,31 readsym until sym # ' ' unless nl # sym # ';' then exit tempname = tempname.tostring(sym) repeat makeupper(tempname) if charno(tempname,1) # '.' then start i = check distinct(tempname,secinput) if i = 0 then i = checkoutputfile(tempname) if i # 0 then psysmes(10,i) and -> er7 finish i = '0' i = i+1 while exist("T#ESOUT".tostring(i))#0 i = '0' if i>'4' outwork = "T#ESOUT".tostring(i) outfile(outwork,-4096,4096,0,seconad,i) if i # 0 then psysmes(10,i) and seconad = 0 and -> er7 !Create fails secoutput = tempname integer(seconad+12) = 3; !Character file -> c1 pc('P'): !profile (i.e. set it) write profile("ECCE",prof,pvsn,i) -> c1 pc('C'): !close if seconad # 0 then start ; !Dispatch file if charno(secoutput,1) = '.' c then sendfile(outwork,secoutput,"EOUTPUT",0,0,i) c else sendoutput(outwork,secoutput,i) if i # 0 then psysmes(6,i) finish if showflag = 0 start if sin=-1 start switch to main file sin = 0 finish ! Set parms. wtop = top; wend = pp; stop = fp; send = end finish end ; ! of edinner integerfn checkoutputfile(string (31) s) record (finf)r string (31) member, user integer flag, i, j if s -> user.(".").s and user # uinfs(1) c then setfname(s) and result = 258 unless s -> s.("_").member then member = "" connect(s,0,0,0,r,flag) if member # "" then start if r_filetype # 6 then result = 286; !Not a pd file ! PD file must exist. if flag = 0 then start ; ! OK - it does exist setfname(member) if 1 <= length(member) <= 11 then start cycle i = 1,1,length(member) j = charno(member,i) unless 'A' <= upper(j) <= 'Z' c or (i>1 and '0' <= j <= '9') then result = 270 repeat ! See whether member exists flag = -exist(s."_".member); ! If member exists, set flag to -1. finish else flag = 270; !Invalid membername finish finish else start ; ! PD file member not specified. if flag = 0 and r_filetype = 6 then flag = 310; ! Not allowed to overwrite a PD file. flag = -1 if flag=0; ! May need to issue warning later - output exists. flag = 0 if flag = 218; !Need not exist finish result = flag end ; !Of check output file integerfn checkdistinct(string (31) s, t) string (31) member if s -> s.("_").member then start finish if t -> t.("_").member then start finish if s = t then result = 266; !Inconsistent file use result = 0 end ; !Of check distinct routine makeupper(stringname s) integer dr0, dr1, accdr0, accdr1 dr0 = x'58000000'!length(s) dr1 = addr(s)+1 accdr0 = x'18000100' accdr1 = addr(upper(0)) *ld_dr0 *lsd_accdr0 *ttr_l =dr end ; !Of makeupper routine sendoutput(string (31) file, out, integername f) string (31) s1, s2 trim(file,f) if f # 0 start printstring("Unable to trim workfile ".file." - Ecce fails.".snl) return finish if out -> s1.("_").s2 then start modpdfile(2,s1,s2,"",f); !Destroy first modpdfile(1,s1,s2,file,f) if f#0 start printstring("Unable to write to pdfile ".s1.snl) newgen(file,"ECCE#BACKUP",f) if f#0 then rename(file,"ECCE#BACKUP",f) if f=0 then printstring("Edited text left in file ECCE#BACKUP.".snl) f = 1; ! To prevent ECCE#BACKUP from being deleted! finish else destroy(file,f) and f=0 finish else start newgen(file,out,f) if f # 0 then rename(file,out,f) finish printstring("File ".out." written to.".snl) if f=0 end ; !Of send output routine connect input(string (255) file, integername conad,start,size,f) record (finf) r conad = 0; start = 0; size = 0; f = 0 unless 1 <= length(file) <= 31 then f = 220 and return if file # ".N" and file # ".NULL" start connect(file,0,0,0,r,f); !Any mode,any size,no protect if f # 0 then return if r_filetype = 3 start conad = r_conad start = r_conad+r_datastart size = r_dataend-r_datastart finish else start f = 267; !Invalid filetype setfname(file) finish finish end ; !Of connect input externalroutine ecce(string (255) in) integer workhead, worktop, workend, inhead, intop, inend, oinend integer insize, worksize, holesize integer f, j string (255) out string (8) work !Start: decompose and vet params if in -> in.("/").out then in = in.",".out unless in -> in.(",").out then out = in if out -> in.(",").out then -> er1 makeupper(in) if in = "" or in = ".N" then in = ".NULL" makeupper(out); !In case of ".NULL" unless out = ".N" or out = ".NULL" then start f = checkoutputfile(out) if f > 0 then -> er if f=-1 and in#out start ! f is -1 if output file exists. printstring("**Warning: overwriting file ".out.". If you do not want".snl) printstring("to lose current contents, use Int:A now to get out of ECCE.".snl) finish finish !Setup files connect input(in,inhead,intop,insize,f) -> er if f # 0 work = "T#ETEMP" f = 1 for j= '0',1,'4' cycle f = 0 and exit if exist(work.tostring(j))=0 repeat j = '0' if f=1 work = work.tostring(j) holesize = 262144; ! 1/4 meg hole. cycle worksize = insize + holesize outfile(work,-worksize,worksize,0,workhead,f) exit if f=0 ->er if holesize = 4096; ! 4K - minimum reasonable. holesize = holesize>>1 repeat if inhead#0 and integer(inhead+4)>32 start move(integer(inhead+4)-32,inhead+32,workhead+32) ! Copy last part of unusual input file header integer(workhead+4) = integer(inhead+4) finish integer(workhead+8) = worksize; worksize = worksize-integer(workhead+4) integer(workhead+12) = 3; ! Type=character worktop = workhead+integer(workhead+4) workend = worktop+worksize-2*integer(workhead+4) inend = intop+insize-1 inend = inend-1 and insize = insize-1 while inend>=intop and byteinteger(inend)#nl oinend = inend prompt("Edit".tostring(13).tostring(nl).">") edinner(workhead, worktop, workend, inhead, intop, inend, work, in) ! Edited file: [worktop,workend) + [intop,inend] worksize = workend-worktop + inend+1-intop if out=".NULL" or (in=out and insize=worksize and inend=oinend and c worktop=workend) then f = 0 elsestart ! File must be written back. j = inend-intop+1 move(j,intop,workend) integer(workhead) = worksize+integer(workhead+4) sendoutput(work,out,f) finish destroy("ECCE#BACKUP",f) if f=0 and out#"ECCE#BACKUP" return er1: print string( c " Form is E(old) or E(old,new) or E(,new)".snl) comreg(24) = 8 return er: comreg(24) = f; !Set return code psysmes(73,f) if f > 0 end ; !Of e externalroutine show(string (255) in) integer intop, inend, inhead, insize, f if in = "" then in = "T#LIST"; !Use compiler default listing file if none specified makeupper(in) connect input(in,inhead,intop,insize,f) -> er if f # 0 if intop = 0 then f = 220 and -> er; !No ".N" prompt("Show".tostring(13).tostring(nl).">") inend = intop+insize-1 inend = inend-1 while inend>=intop and byteinteger(inend)#nl edinner(inhead, intop, inend, inhead, intop, inend, in, "") return er: comreg(24) = f; !Set return code psysmes(74,f) if f > 0 return end ; !Of show externalroutine recap(string (255) in) systemroutinespec get journal(stringname file, integername flag) string (31) file integer flag if in = "" then start get journal(file,flag) if flag = 0 then show(file) finish else flag = 215; !Too many params if flag > 0 then psysmes(75,flag) comreg(24) = flag; !Set return code end ; !Of recap endoffile