%%s 3/0/3373 %%d D 1.2 04-Apr-82 13:53:29 tools 2 1 %%c added bigeddef to ed.w in order to build biged on VMS, permitting %%c the editing of up to 25,000 line files (Why anyone wants to edit files %%c that large is beyond me, but some do!) %%s 0/0/0 %%d D 1.1 25-Mar-82 12:04:34 v1.1 1 0 %%c Version 1.1 is the Spring 1982 Distribution of the LBL/Hughes release %%c of the Software Tools Virtual Operating System software and documentation. %%T %%I 1 #-h- cbuf 395 asc 25-mar-82 07:46:19 v1.1 (sw-tools v1.1) # /cbuf/ common block # put on a file called 'cbuf' # Used only by the editor common /cbuf/ buf(MAXBUF), lastbf, free integer buf, lastbf, free # buf(k+0) PREV Index of previous line in buf.(MSB = MARK bit.) # buf(k+1) NEXT Index of next line in buf. # buf(k+2) CURR Index of current line in tbuf. (in-memory version) # buf(k+2) SEEKADR Index of first word of pointer. (scratch-file version) #-h- cdel 336 asc 25-mar-82 07:46:20 v1.1 (sw-tools v1.1) # /cdel/ - common block for editor; holds information about the # most recently deleted range of lines. # put on a file called 'cdel' # Used only by the editor. common /cdel/ delcnt, fstdel, lstdel integer delcnt # Number of lines deleted. integer fstdel # Index of first line deleted. integer lstdel # Index of last line deleted. #-h- cfile 168 asc 25-mar-82 07:46:22 v1.1 (sw-tools v1.1) ## cfile common block - for editor # put on a file named 'cfile' # Used only by the editor common /cfile/ savfil(FILENAMESIZE) character savfil #remembered file name #-h- clines 819 asc 25-mar-82 07:46:24 v1.1 (sw-tools v1.1) # /clines/ - common block for editor; holds line flags # put on a file called 'clines' # Used only by the editor common /clines/ line1, line2, nlines, curln, lastln, print, cursav, oldlin, oldndx, ifmod, number, autoin integer line1 # first line number integer line2 # second line number integer nlines # number of line numbers specified integer curln # current line: value of dot integer lastln # last line: value of $ integer print # flag to cause/suppress printing of line count integer cursav # value of current line before new command integer oldlin # last line number used by getind integer oldndx # last index returned by getind integer ifmod # Set if buffer has been modified since last write. integer number # Set if lines are to be numbered. integer autoin # Set if autoindent is desired. #-h- clru 252 asc 25-mar-82 07:46:26 v1.1 (sw-tools v1.1) common / clru / lrup(RESIDENT_PAGES), mrup(RESIDENT_PAGES), pfnp(RESIDENT_PAGES) integer lrup # index to less recently used pages integer mrup # index to more recently used pages integer pfnp # index to page frame entry mapped in this physical page #-h- cnoreg 183 asc 25-mar-82 07:46:27 v1.1 (sw-tools v1.1) # /cnoreg/ - common block to hold number register for editor # put in a file called 'cnoreg' # used by ch and ed common / cnoreg / noreg integer noreg # number register for editor #-h- cpat 141 asc 25-mar-82 07:46:29 v1.1 (sw-tools v1.1) # /cpat/ - common block for editor # put on a file named 'cpat' # Used only by the editor common /cpat/ pat(MAXPAT) integer pat # pattern #-h- csclin 193 asc 25-mar-82 07:46:31 v1.1 (sw-tools v1.1) ## csclin common block - for editor # put on a file named 'csclin' # Used only by the editor common /csclin/ lin(MAXLINE) character lin # scratch line for reading lines to be injected #-h- cscrat 297 asc 25-mar-82 07:46:32 v1.1 (sw-tools v1.1) # /cscrat/ - common block for editor; holds scratch file info # put on a file called 'cscrat' # Used only by the editor common /cscrat/ scr, scrend(2) , scrfil(FILENAMESIZE) integer scr # scratch file id integer scrend # end of info on scratch file character scrfil # name of scratch file #-h- cspwn 227 asc 25-mar-82 07:46:34 v1.1 (sw-tools v1.1) # cspwn - common block with arrays for spawning stuff # used by dopip and typset common / cspwn / argara(ARGBUFSIZE), filara(FILENAMESIZE) character argara # buffer for command character filara # buffer for scratch file name #-h- cstack 259 asc 25-mar-82 07:46:35 v1.1 (sw-tools v1.1) common / cstack / level, vrbs(MAX_LEVEL), desc(MAX_LEVEL) integer level # index into desc for current input file; init = 1 integer vrbs # whether to echo each input line on ERROUT; init = NO filedes desc # array of input file descriptors; desc(1) = STDIN #-h- ctbuf 176 asc 25-mar-82 07:46:35 v1.1 (sw-tools v1.1) # /ctbuf/ common block for in-memory text buffer. # Put on a file called 'ctbuf' # Used only by the editor common /ctbuf/ tbuf(MAXTXT), txtend character tbuf integer txtend #-h- ctbufs 106 asc 25-mar-82 07:46:35 v1.1 (sw-tools v1.1) common / ctbufs / edtbuf(FILENAMESIZE, MAXTBUFS) character edtbuf # name of scratch files for temp buffs #-h- ctxt 171 asc 25-mar-82 07:46:36 v1.1 (sw-tools v1.1) # /ctxt/ - common block for editor # put on a file called 'ctxt' # Used only by the editor common /ctxt/ txt(MAXLINE) character txt # text line for matching and output #-h- cvfile 210 asc 25-mar-82 07:46:36 v1.1 (sw-tools v1.1) common / cvfile / virunt, virend, vpfile(FILENAMESIZE) filedes virunt # ratfor unit to page file; init = ERR linepointer virend # address of end-of-file for paging file character vpfile # name of paging file #-h- cvirt 279 asc 25-mar-82 07:46:38 v1.1 (sw-tools v1.1) common / cvirt / virind(PF_SIZE), phyind(PF_SIZE), dskadr(PF_SIZE) integer virind # starting virtual index of this page integer phyind # starting physical index of this page # if == 0, not resident; if < 0, page is dirty linepointer dskadr # address of page in paging file #-h- patdef 787 asc 25-mar-82 07:46:39 v1.1 (sw-tools v1.1) ## definitions for the pattern matching routines # put on a file named 'defns' # Used by pattern.r and ed & sedit tools define(ANY,'?') define(BOL,'%') define(BOT,'{') define(CCL,'[') define(CCLEND,']') define(CHAR,'a') define(CLOSIZE,4) define(CLOSURE,'*') define(CLOSURE1,'+') # closure of one or more occurrences # i.e. (pat)+ == (pat)(pat)* define(COUNT,1) define(EOL,'$') define(EOT,'}') define(MAXTAG,10) define(NCCL,'n') define(PREVCL,2) define(START,3) define(DITTO,(-3)) define(SECTION,(-4)) # /ctag/ - common block to hold section limits for ch # put in a file called 'ctag' # Used by find, ch, and ed #common /ctag/ taglim(MAXTAG2) #integer taglim define(I_CTAG,common/ctag/taglim(arith(2,*,MAXTAG)) integer taglim) #-h- ed.r 54091 asc 25-mar-82 07:47:03 v1.1 (sw-tools v1.1) #-h- defns 3277 asc 25-mar-82 07:42:48 v1.1 (sw-tools v1.1) # definitions for editor # put on a file called 'defns' # Used only by the editor # # the editor may be tailored in several ways # # if one defines the symbol IN_MEM via define(IN_MEM,) # then the editor will use an in-memory buffer for the text as opposed # to keeping it on a temporary file. # # if the symbol LARGE_ADDRESS_SPACE is defined in symbols, then the # editor can handle files up to 10,000 lines long. Otherwise, the # editor is built to handle 500 lines. # # For RSX-11M only, defining the symbol DO_PAGING via define(DO_PAGING,) # causes a virtual-memory version of the editor to be built. As such, # files up to 8,000 lines long can be edited # ifnotdef(MAX_ED_LINES) ifdef(LARGE_ADDRESS_SPACE) define(MAX_ED_LINES,10000) elsedef define(MAX_ED_LINES,500) enddef ifdef(DO_PAGING) define(MAX_ED_LINES,8000) enddef enddef ifnotdef(PROMPT_STRING) define(PROMPT_STRING,": ") enddef ifnotdef(USE_STRING) define(USE_STRING,"usage: ed [-] [-p[string]] [-n] [-v] [file].") enddef include patdef # definitions for pattern matching stuff define(NUMBER_REGISTER,(-5)) # code for number register # definitions for commands define(APPENDCOM,'a') define(BROWSE,'b') define(CHANGE,'c') define(DELCOM,'d') define(ENTER,'e') define(PRINTFIL,'f') define(GLOBAL,'g') define(HELPCOM,'h') define(INSERT,'i') define(JOINCOM,'j') define(KOPYCOM,'k') define(LIST,'l') define(MOVECOM,'m') define(NREGCOM,'n') define(QUIT,'q') define(READCOM,'r') define(SUBSTITUTE,'s') define(TYPESET,'t') define(UNDELETE,'u') define(WRITECOM,'w') define(EXCLUDE,'x') define(PRINTCUR,'=') define(COMMENT,'#') define(PREVLINE,'-') define(NEXTLINE,'+') define(CURLINE,'.') define(LASTLINE,'$') define(BACKUPLINE,'-') define(SCAN,'/') define(BACKSCAN,'\') define(SPAWNCOM,'^') define(PIPECOM,'|') define(PERCENCOM,'%') define(REDIRECTCOM,'<') define(PRINT,'p') define(MARKED,'y') define(NOMARK,'n') define(BACKWARD,-1) define(FORWARD,0) define(NOSTATUS,1) define(LINE0,1) define(MAX_LEVEL,2) define(ABORTED,CHILD_ABORTED) # abort flag # definitions for fields of line descriptors define(PREV,0) define(NEXT,1) define(CURR,2) define(SEEKADR,2) define(MARK,3) define(LENG,4) ifdef(IN_MEM) define(BUFENT,3) # number of words per line descriptor. define(MAXTXT,arith(MAX_ED_LINES,*,40)) # average chars/line. elsedef define(BUFENT,arith(2,+,arith(CHAR_PER_LPTR,/,CHAR_PER_INT))) enddef # Calculate size of buffer array => BUFENT * (MAX_ED_LINES + 2). # The 2 is to account for dummy lines before and after real lines. define(MAXBUF,arith(BUFENT,*,arith(MAX_ED_LINES,+,2))) # some definitions for the BROWSE command define(SCREENSIZE,22) define(FORWARD,'+') define(CENTER,'.') define(BACKWARD,'-') define(MAXTBUFS,3) # number of auxiliary text buffers ($1..$n) define(MAXPROMPT,11) # max length of prompt string # # definitions for virtual memory stuff # ifdef(DO_PAGING) define(RESIDENT_PAGES,8) # permits 512 linepointers resident define(LINES_PER_PAGE,64) # line pointers per virtual page define(PF_SIZE,arith(arith(arith(MAX_ED_LINES,+,1),/,LINES_PER_PAGE),+,1)) define(MAXBUF,arith(arith(LINES_PER_PAGE,*,BUFENT),*,RESIDENT_PAGES)) define(PAGE_SIZE,arith(arith(LINES_PER_PAGE,*,BUFENT),*,CHAR_PER_INT)) enddef #-h- main 2376 asc 25-mar-82 07:42:53 v1.1 (sw-tools v1.1) ## Ed -- Main routine for text editor. DRIVER(ed) character lin(MAXLINE) character clower # function(s) integer ckglob, clrbuf, docmd, doglob, doread, getarg # function(s) integer getlst, prompt # function(s) integer i, len, status, cleard include cfile include clines include cpat include cbuf include cstack ifdef(DO_AUTOIN) PB_DECL(512) enddef string pstr(MAXPROMPT) PROMPT_STRING data print / YES / # Print line counts by default. call query( USE_STRING ) call inited ifdef(DO_AUTOIN) call pbinit(512) enddef call setbuf number = NO # Default is no line numbers. autoin = NO # Default is no autoindent. pat(1) = EOS savfil(1) = EOS # Pick up file name and possible flag(s) for( i = 1 ; getarg( i, lin, MAXLINE) != EOF ; i = i + 1 ) { if( lin(1) == '-' ) { if( lin(2) == EOS ) print = NO else if( clower( lin(2) ) == 'n' ) number = YES else if( clower( lin(2) ) == 'p' ) { lin(arith(MAXPROMPT,+,2)) = EOS call scopy( lin, 3, pstr, 1) } else if (clower( lin(2) ) == 'v' ) vrbs(1) = YES } else { call strcpy( lin, savfil) if( doread( 0, savfil, ENTER) == ERR ) call remark( "?." ) } } cleard = NO for (level=1; level > 0; level = level - 1) { repeat { ifdef(DO_ASTS) call setast(NO) enddef status = prompt( pstr, lin, desc(level)) if (status == EOF) break if( status != ERR ) { if (vrbs(level) == YES) call putlin(lin, ERROUT) i = 1 cursav = curln if( getlst( lin, i, status) == OK ) { if( ckglob( lin, i, status) == OK ) status = doglob( lin, i, status) else if( status != ERR & status != ABORTED ) status = docmd( lin, i, NO, status) # else error, do nothing } } if( status == ERR ) { call remark( "?." ) curln = cursav } ifdef(DO_ASTS) else if( status == ABORTED ) { call remark( "...interrupted..." ) curln = cursav } enddef else if( status == EOF ) if (level > 1) break else if( clrbuf(QUIT) == OK ) # will return ERR if changes since last w { cleard = YES break } # else OK, loop } if (level > 1) call close(desc(level)) } if (cleard == NO) status = clrbuf(EOF) call ended DRETURN end #-h- append 436 asc 25-mar-82 07:42:57 v1.1 (sw-tools v1.1) ## Append -- Append lines after `line'. integer function append( line, glob) integer inject, inplin # function(s) integer glob, line include clines include csclin include cstack if( glob == YES ) return(ERR) curln = line repeat { if( inplin( lin, desc(level), curln + 1 ) == EOF ) return(EOF) else if( lin(1) == '.' & lin(2) == '@n' ) return(OK) else if( inject(lin) == ERR ) return(ERR) } end #-h- browse 804 asc 25-mar-82 07:42:58 v1.1 (sw-tools v1.1) ## Browse -- Display a screen of lines. integer function browse( line, lin, i) character direc, lin(ARB) integer curscr, i, lin1, lin2, line, screen integer ctoi, doprnt # function(s) include clines data screen, curscr / SCREENSIZE, SCREENSIZE / if( lin(i) == '@n' ) { direc = FORWARD screen = curscr } else { if( lin(i) == FORWARD | lin(i) == CENTER | lin(i) == BACKWARD ) { direc = lin(i) i = i + 1 } else direc = FORWARD screen = ctoi( lin, i) - 1 if( screen <= 0 ) screen = curscr else curscr = screen } if( direc == FORWARD ) lin1 = line else if( direc == CENTER ) lin1 = line - ( screen / 2 ) else lin1 = line - screen lin2 = lin1 + screen lin1 = max( 1, lin1) lin2 = min( lin2, lastln) browse = doprnt( lin1, lin2, PRINT) return end #-h- catsub 1246 asc 25-mar-82 07:43:01 v1.1 (sw-tools v1.1) ## CatSub -- Add replacement text to end of new. subroutine catsub( lin, from, to, sub, new, k, maxnew) integer addset, ctoi, itoc # function(s) integer from, i, j, junk, k, maxnew, to character c, lin(MAXLINE), new(maxnew), sub(MAXPAT) I_CTAG # include tag common block include cnoreg for( i = 1 ; sub(i) != EOS ; i = i + 1 ) { if( sub(i) == DITTO ) for( j = from ; j < to ; j = j + 1 ) junk = addset( lin(j), new, k, maxnew) else if( sub(i) == SECTION ) { i = i + 1 n = sub(i) if( n <= 0 | n > MAXTAG ) call error( "? In CatSub: illegal section." ) for( j = taglim( 2 * n - 1 ) ; j < taglim( 2 * n ) ; j = j + 1 ) junk = addset( lin(j), new, k, maxnew) } else if( sub(i) == NUMBER_REGISTER ) { k = k + itoc( noreg, new(k), maxnew - k + 1 ) i = i + 1 c = sub(i) if( c == '+' | c == '-' ) { i = i + 1 if( sub(i) != ' ' & sub(i) != '@t' ) { junk = ctoi( sub, i) if( junk == 0 ) junk = 1 } else junk = 1 if( c == '+' ) noreg = noreg + junk else noreg = noreg - junk } i = i - 1 # went one too far } else junk = addset( sub(i), new, k, maxnew) } return end #-h- ckglob 1334 asc 25-mar-82 07:43:03 v1.1 (sw-tools v1.1) ## CkGlob -- If global prefix, mark lines to be affected. integer function ckglob( lin, i, status) character lin(MAXLINE) integer defalt, getind, gettxt, match, nextln, optpat # function(s) ifdef(DO_ASTS) integer getast # function(s) integer gotast enddef integer gflag, i, k, line, status character clower # function(s) include cbuf include clines include cpat include ctxt if( clower( lin(i) ) != GLOBAL & clower( lin(i) ) != EXCLUDE ) status = EOF else { if( clower( lin(i) ) == GLOBAL ) gflag = YES else gflag = NO i = i + 1 if( optpat( lin, i) == ERR | defalt( 1, lastln, status) == ERR ) status = ERR else { i = i + 1 for( line = line1 ; line <= line2 ; line = line + 1 ) { ifdef(DO_ASTS) if( getast(gotast) == YES ) { status = ABORTED return(ABORTED) } enddef k = gettxt(line) if( match( txt, pat) == gflag ) call setb( k, MARK, YES) else call setb( k, MARK, NO) } for( line = nextln(line2) ; line != line1 ; line = nextln(line) ) { ifdef(DO_ASTS) if( getast(gotast) == YES ) { status = ABORTED return(ABORTED) } enddef k = getind(line) call setb( k, MARK, NO) } status = OK } } return(status) end #-h- ckp 363 asc 25-mar-82 07:43:05 v1.1 (sw-tools v1.1) ## CkP - Check for `p' or `l' after command. integer function ckp( lin, i, pflag, status) character c, lin(MAXLINE) integer i, j, pflag, status character clower # function(s) j = i c = clower( lin(j) ) if( c == PRINT | c == LIST ) { j = j + 1 pflag = c } else pflag = NO if( lin(j) == '@n' ) status = OK else status = ERR return(status) end #-h- clrbuf 831 asc 25-mar-82 07:43:05 v1.1 (sw-tools v1.1) ## ClrBuf -- Clear buffer if user is serious. integer function clrbuf(comand) character comand integer junk integer isatty, prompt, remove # function(s) include clines include csclin ifnotdef( IN_MEM ) include cscrat enddef ifdef(DO_PAGING) include cvfile enddef ifdef(prompt) string null "" enddef string pstr "Are you SURE? (y means YES) " if( comand != EOF & ifmod == YES & isatty(STDIN) == YES ) { junk = prompt( pstr, lin, STDIN) if( lin(1) != 'y' & lin(1) != 'Y' ) return(ERR) } ifnotdef( IN_MEM ) # Remove scratch file, if used. call close(scr) junk = remove(scrfil) enddef ifdef(prompt) if (comand == QUIT) call logend(null, junk) enddef ifdef(DO_PAGING) if (virunt != ERR) { call close(virunt) junk = remove(vpfile) call virint } enddef return(OK) end #-h- conct 465 asc 25-mar-82 07:43:06 v1.1 (sw-tools v1.1) ## Conct -- Concat line to next line if necessary. integer function conct( nbr, lin) integer i, junk, nbr integer gettxt # function(s) character lin(ARB) include clines include ctxt for( i = 1 ; lin(i) != EOS ; i = i + 1 ) # check for lack of '@n' if( lin(i) == '@n' ) return(OK) if( nbr + 1 > lastln ) # no next line return(ERR) junk = gettxt( nbr + 1 ) call scopy( txt, 1, lin, i) call delete( nbr + 1, nbr + 1, junk) return(OK) end #-h- defalt 277 asc 25-mar-82 07:43:07 v1.1 (sw-tools v1.1) ## Defalt -- Set defaulted line numbers. integer function defalt( def1, def2, status) integer def1, def2, status include clines if( nlines == 0 ) { line1 = def1 line2 = def2 } if( line1 > line2 | line1 <= 0 ) status = ERR else status = OK return(status) end #-h- delete 698 asc 25-mar-82 07:43:09 v1.1 (sw-tools v1.1) ## Delete -- Delete lines `from' through `to'. integer function delete( from, to, status) integer getind, nextln, prevln # function(s) integer from, k1, k2, status, to include cdel include clines if( from <= 0 ) status = ERR else { if( delcnt != 0 ) # Return last lines deleted to free list. call ptfndx( fstdel, lstdel) fstdel = getind(from) # Save index of first line deleted. lstdel = getind(to) # Save index of last line deleted. k1 = getind( prevln(from) ) k2 = getind( nextln(to) ) delcnt = to - from + 1 # Save number of lines deleted. lastln = lastln - delcnt curln = prevln(from) call relink( k1, k2, k1, k2) status = OK } return(status) end #-h- docmd 4453 asc 25-mar-82 07:43:13 v1.1 (sw-tools v1.1) ## DoCmd -- Handle all editor commands except globals. integer function docmd( lin, i, glob, status) character file(MAXLINE), lin(MAXLINE), sub(MAXPAT) character clower, comand integer append, delete, doprnt, doread, dowrit, lmove, subst, undel integer ckp, defalt, getfn, getone, getrhs, nextln, optpat, prevln integer typset, dojoin, donreg, dopip, doset integer gflag, glob, i, line3, pflag, status, kopy, dospwn, browse integer clrbuf, dostak include cfile include clines include cpat pflag = NO # may be set by d, m, s status = ERR comand = clower( lin(i)) # Make sure comparing with lower case. i = i + 1 # Point at next character. if( comand == 's' ) # Process SET command as special case for now... andif( lin(i) == 'e' | lin(i) == 'E' ) { status = doset( lin, i) return(status) } select(comand) { case APPENDCOM: if( lin(i) == '@n' ) status = append( line2, glob) case CHANGE: if( lin(i) == '@n' ) andif( defalt( curln, curln, status) == OK ) andif( delete( line1, line2, status) == OK ) status = append( prevln(line1), glob) case DELCOM: if( ckp( lin, i, pflag, status) == OK ) andif( defalt( curln, curln, status) == OK ) andif( delete( line1, line2, status) == OK ) andif( nextln(curln) != 0 ) curln = nextln(curln) case HELPCOM: { call dohelp status = OK } case INSERT: if( lin(i) == '@n' ) status = append( prevln(line2), glob) case JOINCOM: if( ckp( lin, i, pflag, status) == OK ) andif( defalt( curln, nextln(curln), status) == OK ) status = dojoin( line1, line2) case PRINTCUR: if( ckp(lin, i, pflag, status) == OK ) { call putdec( line2, 1) call putc('@n') } case NREGCOM: status = donreg( lin, i) case MOVECOM: { if( getone( lin, i, line3, status) == EOF ) status = ERR if( status == OK ) andif( ckp( lin, i, pflag, status) == OK ) andif( defalt( curln, curln, status) == OK ) status = lmove(line3) } case KOPYCOM: { if( getone( lin, i, line3, status) == EOF ) status = ERR if( status == OK ) andif( ckp( lin, i, pflag, status) == OK ) andif( defalt( curln, curln, status) == OK ) status = kopy(line3) } case SUBSTITUTE: if( optpat( lin, i) == OK ) andif( getrhs( lin, i, sub, gflag) == OK ) andif( ckp( lin, i + 1, pflag, status) == OK ) andif( defalt( curln, curln, status) == OK ) status = subst( sub, gflag) case SPAWNCOM: status = dospwn( lin, i) case ENTER: if( nlines == 0 ) andif( getfn( lin, i, file) == OK ) if( clrbuf(ENTER) == OK ) { call strcpy( file, savfil) call setbuf status = doread( 0, file, ENTER) } else status = OK case PRINTFIL: if( nlines == 0 ) andif( getfn( lin, i, file) == OK ) { call strcpy( file, savfil) call putlin(savfil, STDOUT) call putc('@n') status = OK } case READCOM: if( getfn( lin, i, file) == OK ) status = doread( line2, file, READCOM) case WRITECOM: if( getfn( lin, i, file) == OK ) andif( defalt( 1, lastln, status) == OK ) status = dowrit( line1, line2, file) case PRINT, LIST: if( lin(i) == '@n' ) andif( defalt( curln, curln, status) == OK ) status = doprnt( line1, line2, comand) case BROWSE: if( defalt( curln, curln, status) == OK ) status = browse( line2, lin, i) case COMMENT: status = OK case BACKUPLINE: { if( nlines == 0 ) line2 = prevln(curln) status = doprnt( line2, line2, PRINT) } case QUIT: if( lin(i) == '@n' & nlines == 0 & glob == NO ) status = EOF case TYPESET: status = typset( lin, i) case UNDELETE: if( lin(i) == '@n' ) status = undel( line2, glob) case PERCENCOM: { call percen status = OK } case PIPECOM: if (defalt(1, lastln, status) == OK) status = dopip( line1, line2, lin, i) case REDIRECTCOM: status = dostak(lin, i) case '@n': { if( nlines == 0 ) line2 = nextln(curln) status = doprnt( line2, line2, PRINT) } } # If none of the above were executed, status is ERR. if( status == OK ) andif( pflag == PRINT | pflag == LIST ) status = doprnt( curln, curln, pflag) return(status) end #-h- doglob 1220 asc 25-mar-82 07:43:16 v1.1 (sw-tools v1.1) ## DoGlob -- Do command at lin(i) on all marked lines. integer function doglob( lin, i, status) character lin(MAXLINE) integer docmd, getind, getlst, nextln, prompt integer value(2) ifdef(DO_ASTS) integer getast # function(s) integer gotast enddef integer count, i, istart, k, line, status, last include cbuf include clines include cstack string gpstr "g_" for( last = length(lin) ; lin( last - 1 ) == '@@' ; last = length(lin) ) { lin( last - 1 ) = '@n' junk = prompt( gpstr, lin(last), desc(level)) } status = OK count = 0 line = line1 istart = i repeat { ifdef(DO_ASTS) if( getast(gotast) == YES ) { status = ABORTED return(ABORTED) } enddef k = getind(line) call getb( k, MARK, value) if( value(1) == YES ) { call setb( k, MARK, NO) cursav = line i = istart repeat { curln = line if( getlst( lin, i, status) == OK ) andif( docmd( lin, i, YES, status) == OK ) count = 0 while( lin(i) != '@n' ) i = i + 1 i = i + 1 if( lin(i) == EOS ) break } } else { line = nextln(line) count = count + 1 } } until( count > lastln | status != OK ) return(status) end #-h- dohelp 277 asc 25-mar-82 07:43:17 v1.1 (sw-tools v1.1) ## DoHelp -- Print help file. subroutine dohelp integer open # function(s) filedes fd string hlpfil "~bin/ed.hlp" fd = open( hlpfil, READ) if( fd != ERR ) { call fcopy( fd, STDOUT) call close(fd) } else call remark( "Sorry, no help is available." ) return end #-h- dojoin 1139 asc 25-mar-82 07:43:17 v1.1 (sw-tools v1.1) ## DoJoin -- Join (from,to) into one line. integer function dojoin( from, to) integer from, to integer i, j, junk, k, savcln, status integer delete, gettxt, injext, prevln # function(s) include clines include csclin include ctxt if( from <= 0 ) status = ERR else { status = OK if( from < to ) { j = 1 for( i = from ; i <= to ; i = i + 1 ) { junk = gettxt(i) if( 1 < j & j < MAXCARD ) # Ensure whitespace. if( lin( j - 1 ) != ' ' & lin( j - 1 ) != '@t' ) if( txt(1) != ' ' & txt(1) != '@t' ) { lin(j) = ' ' # add whitespace j = j + 1 } for( k = 1 ; txt(k) != '@n' & txt(k) != EOS ; k = k + 1 ) if( j >= MAXCARD ) { status = ERR break 2 } else { lin(j) = txt(k) j = j + 1 } } lin(j) = '@n' lin( j + 1 ) = EOS if( status == OK ) { savcln = curln curln = prevln(curln) if( delete( from, to, status) == OK ) status = inject(lin) else curln = savcln } } } return(status) end #-h- donreg 731 asc 25-mar-82 07:43:18 v1.1 (sw-tools v1.1) ## DoNReg -- Process number register commands. integer function donreg( lin, i) character lin(ARB), op integer dif, i, j, pflag, status integer ctoi, index # function(s) include cnoreg string legal "=+-" status = OK pflag = NO if( lin(i) == '@n' ) pflag = YES else { op = lin(i) if( index( legal, op) == 0 ) status = ERR else { j = i + 1 dif = ctoi( lin, j) if( dif == 0 & op != '=' ) dif = 1 if( op == '+' ) noreg = noreg + dif else if( op == '=' ) noreg = dif else noreg = noreg - dif if( lin(j) == 'p' | lin(j) == 'P' ) pflag = YES } } if( status == OK & pflag == YES ) { call putdec( noreg, 1) call putc('@n') } return(status) end #-h- dopip 954 asc 25-mar-82 07:43:20 v1.1 (sw-tools v1.1) ## DoPip -- Pipe the current buffer through other tools. integer function dopip( l1, l2, lin, i) integer dospwn, dowrit, getwrd, length, remove # function(s) integer i, j, k, len, modtmp, prttmp, status, l1, l2, junk character lin(ARB) include clines include cspwn string blkles " <" string seed "pip" modtmp = ifmod # Save state of ifmod flag prttmp = print # Save state of print flag print = NO call scratf( seed, filara) if( dowrit( l1, l2, filara) != ERR ) { j = i len = getwrd( lin, j, argara) # Extract verb. k = j # stash index of rest of command j = len + 1 call stcopy( blkles, 1, argara, j) call stcopy( filara, 1, argara, j) call stcopy( lin, k, argara, j) j = 1 status = dospwn( argara, j) } else { call remark( "? Can't create scratch file." ) status = ERR } junk = remove(filara) ifmod = modtmp # Restore state of ifmod flag print = prttmp # Restore state of print flag return(status) end #-h- doprnt 1059 asc 25-mar-82 07:43:23 v1.1 (sw-tools v1.1) ## DoPrnt -- Print lines `from' through `to'. integer function doprnt( from, to, comand) integer gettxt # function(s) integer from, i, j, k, to ifdef( DO_ASTS ) integer getast # function(s) integer gotast enddef character c, comand include clines include ctxt if( from <= 0 ) return(ERR) else { for( i = from ; i <= to ; i = i + 1 ) { ifdef( DO_ASTS ) if( getast(gotast) == YES ) return(ABORTED) enddef j = gettxt(i) call ptlnum( i, STDOUT) # Output line number, if requested. if( comand == PRINT ) call putlin( txt, STDOUT) else { for( k = 1 ; txt(k) != EOS ; k = k + 1 ) { if( txt(k) >= ' ' ) call putch( txt(k), STDOUT) else if( txt(k) == '@n' ) # Make end-of-lines visible { call putch( '$', STDOUT) call putch( '@n', STDOUT) } else { call putch( '^', STDOUT) c = txt(k) + '@@' call putch( c, STDOUT) } } } } curln = to return(OK) } end #-h- doread 1062 asc 25-mar-82 07:43:25 v1.1 (sw-tools v1.1) ## DoRead -- Read `file' into scratch after `line'. integer function doread( line, file, comand) character comand, file(MAXLINE) filedes fd filedes open # function(s) integer access, getlin, inject, remove # function(s) integer count, line, junk include clines include cfile include csclin include cstack if( comand == ENTER ) # enter new file - open at READWRITE access = READWRITE else # read command - open at READ access = READ call findit( file, lin) # Translate text buffer names. fd = open( lin, access) if( fd == ERR ) return(ERR) else { curln = line doread = OK for( count = 0 ; getlin( lin, fd) != EOF ; count = count + 1 ) { doread = inject(lin) if( doread == ERR ) break } call close(fd) if ((print == YES & level == 1) | vrbs(level) == YES) { call putdec( count, 1) call putc('@n') } if( comand == ENTER ) { ifmod = NO # Reset modified-since-last-write switch. if( count == 0 ) # Kill the zombie. (dpm 15-Jul-81) junk = remove(file) } } return end #-h- doset 609 asc 25-mar-82 07:43:27 v1.1 (sw-tools v1.1) ### DoSet Process SET command for editor. integer function doset( lin, ndx) character cmdwrd(FILENAMESIZE), lin(ARB) integer i, j, junk, ndx, set integer getwrd, indexs # function(s) include clines i = ndx + 1 if( lin(i) == 't' | lin(i) == 'T' ) # Skip `t' in `set'. i = i + 1 junk = getwrd( lin, i, cmdwrd) call fold(cmdwrd) if( cmdwrd(1) == 'n' & cmdwrd(2) == 'o' ) # Determine polarity. { set = NO j = 3 } else { set = YES j = 1 } if( cmdwrd(j) == 'a' ) # Autoindent option. autoin = set else if( cmdwrd(j) == 'n' ) # Number option. number = set else return(ERR) return(OK) end #-h- dospwn 1131 asc 25-mar-82 07:43:30 v1.1 (sw-tools v1.1) ## DoSpwn - Spawn a shell command from within the editor. integer function dospwn(lin, i) character lin(ARB), proces(FILENAMESIZE), args(ARGBUFSIZE), desc(PIDSIZE) integer i, j, spawn, init, k, int, create, loccom include ctbufs string sh "sh" string suffix IMAGE_SUFFIX data init / YES / if( init == YES ) { call impath(args) # get search path if( loccom( sh, args, suffix, proces) != BINARY ) { call remark( "? Cannot find `sh' image file." ) return(ERR) } k = 1 call stcopy( sh, 1, args, k) call chcopy( ' ', args, k) for( j = 1 ; j <= MAXTBUFS ; j = j + 1 ) { call stcopy( edtbuf( 1, j), 1, args, k) args(k) = ' ' k = k + 1 } args(k) = EOS init = NO } call skipbl( lin, i) # extra blanks not necessary if (lin(i) == '@n' | lin(i) == EOS) status = spawn(proces, sh, desc, WAIT) else { int = create (edtbuf(1,1), WRITE) if (int == ERR) status = ERR else { for (j=i; lin(j) != EOS; j=j+1) call putch(lin(j), int) call close(int) status = spawn(proces, args, desc, WAIT) } } if (status != OK) status = ERR return(status) end #-h- dostak 666 asc 25-mar-82 07:43:32 v1.1 (sw-tools v1.1) integer function dostak(line, i) character line(ARB), file(FILENAMESIZE) integer i integer getwrd, loccom, index filedes unit filedes open include cstack include csclin string suffix ".ed@e@n" if (level >= MAX_LEVEL) return(ERR) else if (getwrd(line, i, lin) == 0) return(ERR) else { call findit(lin, file) call impath(lin) if (loccom(file, lin, suffix, file) != ASCII) return(ERR) else { unit = open(file, READ) level = level + 1 desc(level) = unit vrbs(level) = NO if (getwrd(line, i, file) > 0) { call fold(file) if (index(file, 'v') > 0) vrbs(level) = YES } } } return(OK) end #-h- dowrit 1040 asc 25-mar-82 07:43:34 v1.1 (sw-tools v1.1) ## DoWrit -- Write `from' through `to' into file. integer function dowrit( from, to, file) character file(MAXLINE), lin(FILENAMESIZE) filedes fd integer create, gettxt # function(s) integer from, k, line, to, access include ctxt include clines include cfile include cstack access = WRITE k = 1 if (file(1) == '>') # have >file | >>file { k = 2 if (file(2) == '>') # have >>file { k = 3 access = APPEND } } call scopy(file, k, txt, 1) call findit( txt, lin) # Translate text buffer names. fd = create( lin, access) if( fd == ERR ) { call putlin( "? Can't write output file named `", ERROUT) call putlin( file, ERROUT) call remark( "'." ) return(ERR) } else { for( line = from ; line <= to ; line = line + 1 ) { k = gettxt(line) call putlin( txt, fd) } call close(fd) if ((print == YES & level == 1) | vrbs(level) == YES) { call putdec( to - from + 1, 1) call putc('@n') } ifmod = NO # Reset "modified since last write" switch. return(OK) } end #-h- ended 206 asc 25-mar-82 07:43:37 v1.1 (sw-tools v1.1) ## EndEd -- Cleanup routine for the editor. subroutine ended integer i, junk integer remove include ctbufs for( i = 1 ; i <= MAXTBUFS ; i = i + 1 ) junk = remove( edtbuf( 1, i) ) return end #-h- findit 346 asc 25-mar-82 07:43:38 v1.1 (sw-tools v1.1) ## FindIt -- Translate `$n' buffer names into scratch file names. subroutine findit( in, out) character in(ARB), out(ARB) integer i, n integer ctoi # function(s) include ctbufs call strcpy( in, out) if( in(1) == '$' ) { i = 2 n = ctoi( in, i) + 1 if( 1 < n & n <= MAXTBUFS ) call strcpy( edtbuf( 1, n), out) } return end #-h- getb 800 asc 25-mar-82 07:43:40 v1.1 (sw-tools v1.1) ## GetB -- Retrieve `value' of `type' in buf(ndx). subroutine getb( virndx, type, value) integer virndx, type, ndx integer value(2) # In-memory version uses only value(1) ifdef(DO_PAGING) integer xindex integer virphy enddef include cbuf ifdef(DO_PAGING) xindex = virphy(virndx, ndx) elsedef ndx = virndx enddef if( type == PREV ) # The leftmost bit of this word holds MARK. value(1) = abs( buf( ndx + PREV ) ) else if( type == NEXT ) value(1) = buf( ndx + NEXT ) else if( type == MARK ) { if( buf( ndx + PREV ) < 0 ) value(1) = YES else value(1) = NO } ifdef( IN_MEM ) else if( type == CURR ) value(1) = buf( ndx + CURR ) elsedef else if( type == SEEKADR ) { value(1) = buf( ndx + SEEKADR ) value(2) = buf( ndx + arith(SEEKADR,+,1) ) } enddef return end #-h- getfn 528 asc 25-mar-82 07:43:42 v1.1 (sw-tools v1.1) ## GetFN -- Get file name from `lin(i)'. integer function getfn( lin, i, file) character file(MAXLINE), lin(MAXLINE) integer i, j, k include cfile getfn = ERR if( lin(i) == ' ' | lin(i) == '@t' ) { j = i + 1 # get new file name call skipbl( lin, j) for( k = 1 ; lin(j) != '@n' ; k = k + 1 ) { file(k) = lin(j) j = j + 1 } file(k) = EOS if( k > 1 ) getfn = OK } else if( lin(i) == '@n' & savfil(1) != EOS ) { call strcpy( savfil, file) # or old name getfn = OK } # else error return end #-h- getind 703 asc 25-mar-82 07:43:44 v1.1 (sw-tools v1.1) ## GetInd -- Locate line index in buffer. integer function getind(line) integer j, k, line integer nextln, prevln # function(s) include clines data oldndx / ERR / data oldlin / -2 / if( oldndx != ERR & line == nextln(oldlin) & line != 0 ) call getb( oldndx, NEXT, k) else if( oldndx != ERR & line == oldlin ) k = oldndx else if( oldndx != ERR & line == prevln(oldlin) ) call getb( oldndx, PREV, k) else { k = LINE0 if( line < lastln / 2 ) for( j = 0 ; j < line ; j = j + 1 ) # search forward call getb( k, NEXT, k) else for( j = lastln ; j >= line ; j = j - 1 ) # search backwards call getb( k, PREV, k) } oldlin = line oldndx = k getind = k return end #-h- getlst 576 asc 25-mar-82 07:43:46 v1.1 (sw-tools v1.1) ## GetLst -- Collect line numbers at `lin(i)'; increment `i'. integer function getlst( lin, i, status) character lin(MAXLINE) integer getone # function(s) integer i, num, status include clines line2 = 0 for( nlines = 0 ; getone( lin, i, num, status) == OK ; ) { line1 = line2 line2 = num nlines = nlines + 1 if( lin(i) != ',' & lin(i) != ';' ) break if( lin(i) == ';' ) curln = num i = i + 1 } nlines = min( nlines, 2) if( nlines == 0 ) line2 = curln if( nlines <= 1 ) line1 = line2 if( status != ERR ) status = OK return(status) end #-h- getnum 1145 asc 25-mar-82 07:43:48 v1.1 (sw-tools v1.1) ## GetNum -- Convert one term to line number. integer function getnum( lin, i, pnum, status) character lin(MAXLINE) integer ctoi, index, length, optpat, ptscan # function(s) integer i, j, pnum, status include clines include cpat string digits "0123456789" string pnl "p@n" getnum = OK if( index( digits, lin(i) ) > 0 ) { pnum = ctoi( lin, i) i = i - 1 # move back; to be advanced at the end } else if( lin(i) == CURLINE ) pnum = curln else if( lin(i) == LASTLINE ) pnum = lastln else if( lin(i) == PREVLINE ) pnum = curln - 1 else if( lin(i) == NEXTLINE ) pnum = curln + 1 else if( lin(i) == SCAN | lin(i) == BACKSCAN ) { if( index( lin( i + 1 ), lin(i) ) == 0 ) # Add matching delim to line. { j = length(lin) call chcopy( lin(i), lin, j) call stcopy( pnl, 1, lin, j) # Add ``p'' to force print. } if( optpat( lin, i) == ERR ) # build the pattern getnum = ERR else if( lin(i) == SCAN ) getnum = ptscan( FORWARD, pnum) else getnum = ptscan( BACKWARD, pnum) } else getnum = EOF if( getnum == OK ) i = i + 1 # point at next character to be examined status = getnum return end #-h- getone 866 asc 25-mar-82 07:43:50 v1.1 (sw-tools v1.1) ## GetOne -- Evaluate one line number expression. integer function getone( lin, i, num, status) character lin(MAXLINE) integer getnum # function(s) integer i, istart, mul, num, pnum, status include clines istart = i num = 0 call skipbl( lin, i) if( getnum( lin, i, num, status) == OK ) # first term repeat # + or - terms { call skipbl( lin, i) if( lin(i) != '+' & lin(i) != '-' ) { status = EOF break } if( lin(i) == '+' ) mul = +1 else mul = -1 i = i + 1 call skipbl( lin, i) if( getnum( lin, i, pnum, status) == OK ) num = num + mul * pnum if( status == EOF ) status = ERR } until( status != OK ) if( num < 0 | num > lastln ) status = ERR if( status == ERR ) getone = ERR else if( i <= istart ) getone = EOF else getone = OK status = getone return end #-h- getrhs 686 asc 25-mar-82 07:43:52 v1.1 (sw-tools v1.1) ## GetRHS -- Get substitution string for `s' command. integer function getrhs( lin, i, sub, gflag) character lin(MAXLINE), sub(MAXPAT) integer index, length, maksub # function(s) integer gflag, i, j character clower # function(s) string pnl "p@n" getrhs = ERR if( lin(i) == EOS ) return if( lin( i + 1 ) == EOS ) return if( index( lin( i + 1 ), lin(i) ) == 0 ) # Insert matching delim at end. { j = length(lin) call chcopy( lin(i), lin, j) call stcopy( pnl, 1, lin, j) # Add ``p'' to force print. } i = maksub( lin, i + 1, lin(i), sub) if( i == ERR ) return if( clower( lin( i + 1 ) ) == GLOBAL ) { i = i + 1 gflag = YES } else gflag = NO return(OK) end #-h- gettxt 603 asc 25-mar-82 07:43:55 v1.1 (sw-tools v1.1) ## GetTxt -- Locate text for line and make available. integer function gettxt(line) integer getind # function(s) integer j integer loc(2) # In-memory version uses only loc(1) integer line include cbuf include ctxt ifnotdef( IN_MEM ) include cscrat elsedef include ctbuf enddef string null "" j = getind(line) ifdef( IN_MEM ) call getb( j, CURR, loc) call scopy( tbuf, loc(1), txt, 1) elsedef if( line != 0 ) { call getb( j, SEEKADR, loc) call seek( loc, scr) call readfl( txt, dummy, scr) } else call strcpy( null, txt) enddef return(j) end #-h- gtfndx 372 asc 25-mar-82 07:43:55 v1.1 (sw-tools v1.1) ## GtFNdx -- Get index of free line descriptor. integer function gtfndx(newind) include cbuf if( free != 0 ) # something in free list { newind = free call getb( free, NEXT, free) # relink free list } else if( lastbf + BUFENT <= arith(arith(MAX_ED_LINES,+,2),*,BUFENT) ) { newind = lastbf lastbf = lastbf + BUFENT } else newind = ERR return(newind) end #-h- inited 591 asc 25-mar-82 07:43:56 v1.1 (sw-tools v1.1) ## InitEd -- Initialization routine for text editor. subroutine inited character num(2) integer i, j, junk integer itoc # function(s) include ctbufs include cnoreg include cstack string edt "edt" for( j = 1 ; j <= MAXTBUFS ; j = j + 1 ) { i = j - 1 junk = itoc( i, num, 2) edt(3) = num(1) call scratf( edt, edtbuf( 1, j) ) } noreg = 0 # Initialize number register. level = 1 # initialize input stack level vrbs(1) = NO # first level not verbose desc(1) = STDIN # unit for first level ifdef(DO_PAGING) call virint # initialize virtual memory enddef return end #-h- inject 471 asc 25-mar-82 07:43:57 v1.1 (sw-tools v1.1) ## Inject -- Insert `lin' after `curln', write scratch. integer function inject(lin) character lin(MAXLINE) integer getind, maklin, nextln # function(s) integer i, k1, k2, k3 include clines for( i = 1 ; lin(i) != EOS ; ) { i = maklin( lin, i, k3) if( i == ERR ) return(ERR) k1 = getind(curln) k2 = getind( nextln(curln) ) call relink( k1, k3, k3, k2) call relink( k3, k2, k1, k3) curln = curln + 1 lastln = lastln + 1 } return(OK) end #-h- inplin 904 asc 25-mar-82 07:43:58 v1.1 (sw-tools v1.1) ## InpLin -- Conditionally output line number, then get line. integer function inplin( lin, chn, num) character lin(ARB), pstr(9) integer chn, i, n, num integer itoc, prompt # function(s) include clines ifdef(DO_AUTOIN) string indstr(MAXLINE) "" enddef string tail "=>" if( number == YES ) { n = itoc( num, pstr, 7) # format number no wider than 6 chars for( i = 6 ; i > 0 ; [i = i - 1; n = n - 1] ) # right justify, blank fill if (n > 0) pstr(i) = pstr(n) else pstr(i) = ' ' call scopy( tail, 1, pstr, 7) } else pstr(1) = EOS ifdef(DO_AUTOIN) if( autoin == YES ) # Perform autoindent. call pbstr(indstr) enddef inplin = prompt( pstr, lin, chn) ifdef(DO_AUTOIN) if( autoin == YES ) # Remember indentation of line. { for( i = 1 ; lin(i) == ' ' | lin(i) == '@t' ; i = i + 1 ) indstr(i) = lin(i) indstr(i) = EOS } enddef return end #-h- kopy 501 asc 25-mar-82 07:44:00 v1.1 (sw-tools v1.1) ## Kopy -- Kopy a range of lines. integer function kopy(line3) integer junk, line3, nline, offset integer gettxt, inject # function(s) include clines include ctxt if( line1 <= 0 ) kopy = ERR else { kopy = OK curln = line3 for( nline = line1 ; nline <= line2 ; nline = nline + 1 ) { if( nline > line3 ) offset = nline - line1 else offset = 0 junk = gettxt( nline + offset ) kopy = inject(txt) if( kopy == ERR ) break } } return end #-h- lmove 743 asc 25-mar-82 07:44:02 v1.1 (sw-tools v1.1) ## LMove -- Move `line1' through `line2' after `line3'. integer function lmove(line3) integer getind, nextln, prevln # function(s) integer delta, k0, k1, k2, k3, k4, k5, line3 include clines if( line1 <= 0 | ( line1 <= line3 & line3 <= line2 ) ) lmove = ERR else { k0 = getind( prevln(line1) ) k3 = getind( nextln(line2) ) k1 = getind(line1) k2 = getind(line2) call relink( k0, k3, k0, k3) delta = line2 - line1 + 1 lastln = lastln - delta if( line3 > line1 ) { curln = line3 line3 = line3 - delta } else curln = line3 + delta k4 = getind(line3) k5 = getind( nextln(line3) ) call relink( k4, k1, k2, k5) call relink( k2, k5, k4, k1) lastln = lastln + delta lmove = OK } return end #-h- maklin 1383 asc 25-mar-82 07:44:04 v1.1 (sw-tools v1.1) ## MakLin -- Enter new line into memory. integer function maklin( lin, i, newind) character lin(MAXLINE) integer addset, gtfndx, note # function(s) integer i, j, junk, newind, newptr include cbuf include ctxt include clines ifdef( IN_MEM ) include ctbuf elsedef integer txtend include cscrat enddef maklin = ERR oldndx = ERR if( gtfndx(newind) == ERR ) { call remark( "? Line descriptor space limit exceeded." ) return } ifdef( IN_MEM ) if( ( txtend + MAXLINE ) > MAXTXT ) { call remark( "? Text space limit exceeded." ) return } newptr = txtend for( j = i ; lin(j) != EOS ; ) { junk = addset( lin(j), tbuf, txtend, MAXTXT) j = j + 1 if( lin( j - 1 ) == '@n' ) break } if( addset( EOS, tbuf, txtend, MAXTXT) == NO ) { call ptfndx( newind, newind) # Return line descriptor to free list. return } call setb( newind, CURR, newptr) # Set pointer to new text. elsedef txtend = 1 for( j = i ; lin(j) != EOS ; ) { junk = addset( lin(j), txt, txtend, MAXLINE) j = j + 1 if( lin( j - 1 ) == '@n' ) break } if( addset( EOS, txt, txtend, MAXLINE) == NO ) { call ptfndx( newind, newind) # Return free block index. return } call setb( newind, SEEKADR, scrend) call seek( scrend, scr) call putlin( txt, scr) junk = note(scrend, scr) enddef call setb( newind, MARK, NO) return(j) # Next character to be examined in lin. end #-h- maksub 937 asc 25-mar-82 07:44:07 v1.1 (sw-tools v1.1) ## MakSub -- Make substitution string in `sub'. integer function maksub( arg, from, delim, sub) character esc # function(s) character arg(MAXARG), delim, sub(MAXPAT) integer addset, ctoi, type # function(s) integer from, i, j, junk j = 1 for( i = from ; arg(i) != delim & arg(i) != EOS ; i = i + 1 ) { if( arg(i) == AND ) junk = addset( DITTO, sub, j, MAXPAT) else if( arg(i) == '$' & type( arg( i + 1 ) ) == DIGIT ) { i = i + 1 n = ctoi( arg, i) junk = addset( SECTION, sub, j, MAXPAT) junk = addset( n, sub, j, MAXPAT) i = i - 1 } else if( arg(i) == '$' & ( arg(i+1) == 'n' | arg(i+1) == 'N' ) ) { i = i + 1 junk = addset( NUMBER_REGISTER, sub, j, MAXPAT) } else junk = addset( esc( arg, i), sub, j, MAXPAT) } if( arg(i) != delim ) # missing delimiter maksub = ERR else if( addset( EOS, sub, j, MAXPAT) == NO ) # no room maksub = ERR else maksub = i return end #-h- mapphy 786 asc 25-mar-82 07:44:09 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) subroutine mapphy(i) integer i, n, j, pnd, junk integer note filedes create include cvirt include cvfile include clru string vpf "vpf" if (virunt == ERR) { call scratf(vpf, vpfile) virunt = create(vpfile, B_READWRITE) if (virunt == ERR) call error("Cannot open paging file.") junk = note(virend, virunt) } n = lrup(1) # lru header to be paged j = pfnp(n) # page frame index of outgoing page pnd = abs(phyind(j)) # save physical index of page call pagout(j) # page out, if dirty phyind(i) = pnd # physical index of incoming page call pagin(i) # page it into memory pfnp(n) = i # page 'i' is now mapped call mruset(n) # make n the most recently used page return end enddef #-h- mruset 376 asc 25-mar-82 07:44:11 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) subroutine mruset(n) integer n, i, j include clru if (n != 1) { j = lrup(n) # unlink n from list i = mrup(n) # ... mrup(j) = i # ... lrup(i) = j # ... i = mrup(1) # link n into MRU position mrup(1) = n # ... lrup(i) = n # ... lrup(n) = 1 # ... mrup(n) = i # ... } return end enddef #-h- nextln 168 asc 25-mar-82 07:44:12 v1.1 (sw-tools v1.1) ## NextLn - Get line after `line'. integer function nextln(line) integer line include clines nextln = line + 1 if( nextln > lastln ) nextln = 0 return end #-h- optpat 497 asc 25-mar-82 07:44:14 v1.1 (sw-tools v1.1) ## OptPat -- Make pattern if specified at `lin(i)'. integer function optpat( lin, i) character lin(MAXLINE) integer makpat # function(s) integer i include cpat if( lin(i) == EOS ) i = ERR else if( lin( i + 1 ) == EOS ) i = ERR else if( lin( i + 1 ) == lin(i) ) # repeated delimiter i = i + 1 # leave existing pattern alone else i = makpat( lin, i + 1, lin(i), pat) if( pat(1) == EOS ) i = ERR if( i == ERR ) { pat(1) = EOS optpat = ERR } else optpat = OK return end #-h- pagin 441 asc 25-mar-82 07:44:16 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) subroutine pagin(i) integer i, n, junk integer readf, ptreq include cvirt include cvfile include cbuf n = phyind(i) if (ptreq(dskadr(i), NULLPOINTER) == YES) # demand 0 page { junk = n + arith(LINES_PER_PAGE,*,BUFENT) for ( ; n < junk; n=n+1) buf(n) = 0 } else { call seek(dskadr(i), virunt) junk = readf(buf(n), PAGE_SIZE, virunt) } return end enddef #-h- pagout 638 asc 25-mar-82 07:44:18 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) subroutine pagout(j) integer j, n, junk, reset integer writef, ptreq, note include cvirt include cvfile include cbuf if (phyind(j) < 0) # page is dirty, write it out { n = abs(phyind(j)) if (ptreq(dskadr(j), NULLPOINTER) == YES) # must write at end of file { call ptrcpy(virend, dskadr(j)) reset = YES # reset EOF address } else reset = NO call seek(dskadr(j), virunt) junk = writef(buf(n), PAGE_SIZE, virunt) if (reset == YES) junk = note(virend, virunt) } phyind(j) = 0 # page now non-resident return end enddef #-h- pdirty 287 asc 25-mar-82 07:44:20 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) subroutine pdirty(i) integer i, n include cvirt include clru phyind(i) = -abs(phyind(i)) # mark page as dirty for (n=1; n <= RESIDENT_PAGES; n=n+1) if (pfnp(n) == i) break call mruset(n) # put in MRU position return end enddef #-h- percen 598 asc 25-mar-82 07:44:21 v1.1 (sw-tools v1.1) ## Percen - Show percent of line pointer & text space used. subroutine percen include cbuf ifdef( IN_MEM ) include ctbuf enddef integer chrper, linper #linper = lastbf * 100 / arith(arith(MAX_ED_LINES,+,2),*,BUFENT) linper = lastbf / arith(arith(arith(MAX_ED_LINES,+,2),*,BUFENT),/,100) call putdec( linper, 2) call putlin( " percent of line descriptors used.", STDOUT) call putc('@n') ifdef( IN_MEM ) #chrper = txtend * 100 / MAXTXT chrper = txtend / arith(MAXTXT,/,100) call putdec( chrper, 2) call putlin( " percent of text space used.", STDOUT) call putc('@n') enddef return end #-h- prevln 171 asc 25-mar-82 07:44:23 v1.1 (sw-tools v1.1) ## PrevLn -- Get line before `line'. integer function prevln(line) integer line include clines prevln = line - 1 if( prevln < 0 ) prevln = lastln return end #-h- ptfndx 182 asc 25-mar-82 07:44:24 v1.1 (sw-tools v1.1) ## PtFNdx -- Return line descriptor(s) to free list. subroutine ptfndx( start, stop) integer start, stop include cbuf call setb( stop, NEXT, free) free = start return end #-h- ptlnum 239 asc 25-mar-82 07:44:26 v1.1 (sw-tools v1.1) ## PtLNum - Conditionally output line number on `fd'. subroutine ptlnum( num, fd) filedes fd integer num include clines string tail "=>" if( number == YES ) { call putint( num, 6, fd) call putlin( tail, fd) } return end #-h- ptscan 418 asc 25-mar-82 07:44:28 v1.1 (sw-tools v1.1) ## PtScan -- Scan for next occurrence of pattern. integer function ptscan( way, num) integer gettxt, match, nextln, prevln # function(s) integer k, num, way include clines include cpat include ctxt num = curln repeat { if( way == FORWARD ) num = nextln(num) else num = prevln(num) k = gettxt(num) if( match( txt, pat) == YES ) return(OK) } until( num == curln ) return(ERR) end #-h- readfl 331 asc 25-mar-82 07:44:30 v1.1 (sw-tools v1.1) ## ReadFl -- Read line from file (random access). subroutine readfl( buffer, count, int) # note -- in this implementation, a call to getlin is made rather # than reading a specified number of characters. integer count, int, junk integer getlin # function(s) character buffer(ARB) junk = getlin( buffer, int) return end #-h- relink 198 asc 25-mar-82 07:44:31 v1.1 (sw-tools v1.1) ## Relink -- Rewrite two half line links. subroutine relink( a, x, y, b) integer a, b, x, y include clines oldndx = ERR call setb( x, PREV, a) call setb( y, NEXT, b) ifmod = YES return end #-h- setb 970 asc 25-mar-82 07:44:33 v1.1 (sw-tools v1.1) ## SetB - Set `type' in buf(ndx) to `value'. subroutine setb( virndx, type, value) integer virndx, type, ndx integer value(2) # In-memory version uses only value(1) ifdef(DO_PAGING) integer xindex integer virphy enddef include cbuf ifdef(DO_PAGING) xindex = virphy(virndx, ndx) elsedef ndx = virndx enddef if( type == PREV ) # The leftmost bit of this word holds MARK. { if( buf( ndx + PREV ) < 0 ) buf( ndx + PREV ) = -value(1) else buf( ndx + PREV ) = value(1) } else if( type == NEXT ) buf( ndx + NEXT ) = value(1) else if( type == MARK ) { if( value(1) == YES ) buf( ndx + PREV ) = -abs( buf( ndx + PREV ) ) else buf( ndx + PREV ) = abs( buf( ndx + PREV ) ) } ifdef( IN_MEM ) else if( type == CURR ) buf( ndx + CURR ) = value(1) elsedef else if( type == SEEKADR ) { buf( ndx + SEEKADR ) = value(1) buf( ndx + arith(SEEKADR,+,1) ) = value(2) } enddef ifdef(DO_PAGING) call pdirty(xindex) enddef return end #-h- setbuf 805 asc 25-mar-82 07:44:35 v1.1 (sw-tools v1.1) ## SetBuf -- Initialize line storage buffer. subroutine setbuf integer k, junk integer note include cbuf include cdel include clines ifdef( IN_MEM ) include ctbuf elsedef integer create include cscrat string fil "eds" enddef string null "" ifdef(IN_MEM) txtend = LINE0 elsedef call scratf( fil, scrfil) # Get unique name for scratch file. scr = create( scrfil, READWRITE) if( scr == ERR ) call cant(scrfil) junk = note(scrend, scr) enddef lastbf = LINE0 free = 0 # Initialize list of free line descriptors. call maklin( null, 1, k) # Create empty line 0. call relink( k, k, k, k) # Establish initial linked list. curln = 0 lastln = 0 cursav = 0 delcnt = 0 # Number of lines deleted. ifmod = NO # Initialize changes since last w variables. return end #-h- subst 1255 asc 25-mar-82 07:44:37 v1.1 (sw-tools v1.1) ## Subst -- Substitute "sub" for occurrences of pattern. integer function subst( sub, gflag) character new(MAXLINE), sub(MAXPAT) integer addset, amatch, conct, gettxt, injext # function(s) integer gflag, j, junk, k, lastm, line, m, status, subbed include clines include cpat include ctxt subst = ERR if( line1 <= 0 ) return for( line = line1 ; line <= line2 ; line = line + 1 ) { j = 1 subbed = NO junk = gettxt(line) lastm = 0 for( k = 1 ; txt(k) != EOS ; ) { if( gflag == YES | subbed == NO ) m = amatch( txt, k, pat) else m = 0 if( m > 0 & lastm != m ) # replace matched text { subbed = YES call catsub( txt, k, m, sub, new, j, MAXLINE) lastm = m } if( m == 0 | m == k ) # no match or null match { junk = addset( txt(k), new, j, MAXLINE) k = k + 1 } else # skip matched text k = m } if( subbed == YES ) { if( addset( EOS, new, j, MAXLINE) == NO ) { subst = ERR break } subst = conct( line, new) #check for conctenation if( subst == ERR ) break call delete( line, line, status) # remembers dot subst = inject(new) if( subst == ERR ) break subst = OK } } return end #-h- typset 874 asc 25-mar-82 07:44:40 v1.1 (sw-tools v1.1) ## Typset - ``format'' the current buffer. integer function typset( lin, i) integer dospwn, dowrit, remove # function(s) integer i, j, modtmp, prttmp, status, junk character lin(ARB) include cspwn include clines string fmtstr "format " string seed "fmt" modtmp = ifmod # Save state of ifmod flag prttmp = print # Save state of print flag print = NO call scratf( seed, filara) if( dowrit( 1, lastln, filara) != ERR ) { j = 1 call stcopy( fmtstr, 1, argara, j) call stcopy( lin, i, argara, j) if( argara( j - 1 ) == '@n' ) j = j - 1 call chcopy( ' ', argara, j) call stcopy( filara, 1, argara, j) j = 1 status = dospwn( argara, j) } else { call remark( "? Can't create scratch file." ) status = ERR } junk = remove(filara) ifmod = modtmp # Restore state of ifmod flag print = prttmp # Restore state of print flag return end #-h- undel 581 asc 25-mar-82 07:44:43 v1.1 (sw-tools v1.1) ## UnDel -- Undelete last lines deleted; insert them after `line'. integer function undel( line, glob) integer getind, nextln, prevln # function(s) integer glob, line integer k1, k2, status include cdel include clines if( delcnt == 0 | glob == YES ) return(ERR) else { curln = line k1 = getind(curln) k2 = getind( nextln(curln) ) if( curln == lastln ) curln = curln + delcnt else curln = nextln(curln) lastln = lastln + delcnt call relink( k1, fstdel, lstdel, k2) call relink( lstdel, k2, k1, fstdel) delcnt = 0 return(OK) } end #-h- virint 653 asc 25-mar-82 07:44:44 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) # virint - initialize virtual array for line pointers subroutine virint integer i, j include cvirt include cvfile include clru for ([i=1; j=1]; i <= PF_SIZE; [i=i+1; j=j+arith(LINES_PER_PAGE,*,BUFENT)]) { virind(i) = j # starting virtual index call ptrcpy(NULLPOINTER,dskadr(i)) # initially not in paging file if (i <= RESIDENT_PAGES) phyind(i) = j else phyind(i) = 0 } virunt = ERR for (i=1; i <= RESIDENT_PAGES; i=i+1) { lrup(i) = i - 1 mrup(i) = i + 1 pfnp(i) = i } lrup(1) = RESIDENT_PAGES mrup(RESIDENT_PAGES) = 1 return end enddef #-h- virphy 288 asc 25-mar-82 07:44:46 v1.1 (sw-tools v1.1) ifdef(DO_PAGING) integer function virphy(virtnd, physnd) integer virtnd, physnd, i include cvirt i = ((virtnd - 1) / arith(LINES_PER_PAGE,*,BUFENT)) + 1 if (phyind(i) == 0) call mapphy(i) physnd = abs(phyind(i)) + (virtnd - virind(i)) return(i) end enddef #-h- edef 389 asc 25-mar-82 07:47:46 v1.1 (sw-tools v1.1) define(DO_ASTS,) # Poll for ASTs (interrupts) periodically. define(prompt,ledpmt) # Incorporate fancy CLI features. define(IN_MEM,) # Use in-memory text buffer instead of # scratch file. define(MAX_ED_LINES,10000) # Maximum number of line descriptors. define(PROMPT_STRING,"* ") define(DO_AUTOIN,) # do autoindent define(USE_STRING,"usage: e [-] [-p[string]] [-n] [-v] [file].") #-h- ed.hlp 627 asc 25-mar-82 07:47:48 v1.1 (sw-tools v1.1) Append Change Insert Edit File (after) (range) (before) e [] f [] (.)a (.,.)c (.)i Read (after) Write (.)r [] (1,$)w [] . . . Delete Print Browse Move Kopy (range) (range) (screen) (range)(after) (range)(after) (.,.)d (.,.)p (.)b[.|-] (.,.)m (.,.)k Substitute Global Xcept (.,.)s/old/new/ or (1,$)g/text/command (1,$)x/text/command (.,.)s/old/new/g Metacharacters Equals Comment ? (any char) % (first char on line) * (closure) @ (escape) $ (last char on line) & (ditto) (.)= # text @n (newline) @t (tab) c1-c2 (range) [...] (class) #-h- e.fmt 1356 asc 25-mar-82 07:47:50 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd E (1) 12-Aug-81 extended version of "ed" with command editing & history .sy e [-] [-pprompt] [-n] [-v] [file] .ds e is an extended version of ed which uses virtual memory rather than a scratch file for its text storage. This makes it considerably faster than ed. In addition, command editing & history are supported; see the writeup on "esh" for more information. .sp Other commands and features which may not have found their way into ed: .in +5 .sp .ti -3 1. There is a terse help command, invoked via `h'. .ti -3 .sp 2. One can cause the current contents of the buffer to be roffed by issuing the "typeset" command via `t'. This causes format to be spawned, formatting the buffer contents to the terminal. The buffer contents are not affected. If more sophisticated use of format is necessary, or you deires to spawn something other than format, see the ed writeup for the `^' command. .sp .ti -3 3. A command is available to see how much of the virtual memory array space has been used via `%'. If you exhaust the array space with many changes, simply writing the file followed by the enter command will cause garbage collection to occur. .sp .in -5 For information on the other commands to e, consult the manual entry for ed. .fl .au The extra features of e above those of ed are due to Dave Martin. .sa ed - text editor .bu #-h- ed.fmt 17885 asc 25-mar-82 07:47:57 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Ed (1) 21-Apr-78 line-oriented text editor .sy ed [-] [-pstring] [-n] [-v] [file] .ds Ed is a text editor. If the 'file' argument is given, the file is read into ed's buffer so that it can be edited and its name is remembered for possible future use. Ed operates on a copy of any file it is editing; changes made in the copy have no effect on the file until a w (write) command is given. The optional '-' suppresses the printing of line counts by the e (edit), r (read), and w (write) commands. The -p flag may be used to specify ed's prompt string. The default is ": ". If prompting is not desired, a bare -p in the command line will turn it off. The -n flag indicates that you want to see line numbers prepended to each line of the buffer. The -v flag indicates that each command is to be echoed on error output as it is executed. Ed accepts commands from script files as well as a terminal. To do this, invoke ed and substitute the script file name for the standard input, as follows - ed [file]