!!!!! Simple emulation of EMAS VIEW for VAX/VMS and APM !!!!! !!!!!!!!! Hamish Dewar April 1983 !!!!!!!!! !Implements VIEW commands on a VMS/APM text file: ! only basic commands implemented; index generated on fly ! !$IF VAX !%externalintegerfnspec CONNECT(%string(127) file, ! %integername start,length,%integer mode) {\V10IMP %include "IMP_INCLUDE:CONNECT.INC" {V10IMP} from IMP include connect include "VTI.IMP" ! externalroutine VIEW(string (255) filename) owninteger MAXCOL=72 !$IF APM {%routine CONNECT FILE(%string(127) file,%integer mode, { %integername start,len) {%shortspec(16_35C4) uno {%bytespec(16_372C) lockout {%integer i,j,xno,blocks,bytes,size {%string(255) fscomm {%routine GET(%integername v) {%integer k { v = 0 { %cycle { i = i+1; k = charno(fscomm,i) { i = i-1 %if k < ' ' { k = k-'0' { %return %if k < 0 { v = v<<4+k { %repeat {%end {%routine READ { %cycle { size = 512; size = bytes %if bytes < 512 { size = etherread(15,byteinteger(i),size) { i = i+size; bytes = bytes-size { %repeat %until size # 512 { lockout = 0 {%end { %on %event 9 %start { lockout = 0 { charno(fscomm,2) = size-2; printstring(string(addr(charno(fscomm,2)))) { %signal 4 { %finish { bytes = 0; blocks = 0 { %if file # "" %start {!Send Readfile request to filestore { lockout = 1 { fscomm = "Z".tostring(uno+'0').file.tostring(nl) { etherwrite(15,charno(fscomm,1),length(fscomm)) {!Read response { size = etherread(15,charno(fscomm,1),255) { %signal 9 %if charno(fscomm,1) = '-' {!Extract info { i = 0 { get(blocks); get(bytes) { bytes = blocks<<9-bytes; !size of file in bytes { %finish { len = bytes { size = blocks<<9; !VM size {!Allocate space { *MOVE D6,i; *MOVE A7,j; !**Heap -><- Stack ** { %if i+size >= j %start; !no space { bytes = 0 { read { printstring("*Insufficient space for file"); newline { %signal 4 { %finish { i = i-256; !HP displaced by 256 { start = i { *ADD size,D6 { read %if bytes # 0 {%END {! {%begin {%routine VIEW(%string(255) filename) {%owninteger MAXCOL=80 !$FINISH ! !Current status variables: constinteger MAXLINE=20, LET=32 owninteger COL=0, SKIPPING=0, LINE=0 integer IDENT,PAGE,TEXTAD,LENGTH integer STARTAD,LIMAD,FLAG,COMMAND,MORE,FOUND !Directive index: constinteger DIRBOUND=1000, PAGEBOUND=100 integer DIRMAX,PAGEMAX,MAXPAGE,MAXTEXTPAGE,CHARMAX recordformat DIRINFO(integer address, byteinteger level,number, shortinteger parent,brother) record (dirinfo)array DIR(0:dirbound) !Page information for current section only integerarray PSTART(1:pagebound) integerarray FOUNDID(1:maxline) byteintegerarray CHAR(1:127) constinteger EVEN=\1 routine SKIP LINE return if textad >= limad !$IF VAX textad = textad+(shortinteger(textad)+3)&even !$IF APM { textad = textad+1 %until byteinteger(textad-1) < ' ' !$FINISH end routine CREATE DIRECTORY(integer parent,level) ! Set up DIR for all sections and sub-sections, ! TEXTAD pointing at first sub-section of PARENT record (dirinfo)name d integer num,code,p num = 1 cycle dirmax = dirmax+1; p = dirmax d == dir(p) d_address = textad d_level = level; d_number = num d_parent = parent cycle d_brother = -(dirmax+1) cycle skip line return if textad >= limad !$IF VAX repeat until shortinteger(textad) >= 2 and byteinteger(textad+2) = '!' code = byteinteger(textad+3) !$IF APM { %repeat %until byteinteger(textad) = '!' { code = byteinteger(textad+1) !$FINISH if code = '>' start ; !end-of-section return if p = 0 p = 0 finish if code = '<' start exit if p = 0; !brother create directory(p,level+1); !sons p = 0 finish repeat d_brother = dirmax+1; num = num+1 repeat end ; !CREATE DIR routine SEARCH FOR STRING integer id integerfn MATCHED integer a,k,ad,lim !$IF VAX ad = dir(id)_address; lim = ad+shortinteger(ad)+2 ad = ad+4; !past length bytes & '!<' while ad+charmax <= lim cycle if byteinteger(ad)!let = command start ; !first char match a = ad; k = 0 cycle a = a+1; k = k+1 result = 1 if k > charmax repeat until byteinteger(a)!let # char(k) finish ad = ad+1 until ad = lim or byteinteger(ad) = ' ' ad = ad+1 repeat result = 0 !$IF APM { ad = dir(id)_address+2 { %cycle { %while byteinteger(ad) <= ' ' %cycle { %result = 0 %if byteinteger(ad) < ' ' { ad = ad+1 { %repeat { %if byteinteger(ad)!let = command %start; !first char match { a = ad; k = 0 { %cycle { a = a+1; k = k+1 { %result = 1 %if k > charmax { %repeat %until byteinteger(a)!let # char(k) { %finish { ad = ad+1 %until byteinteger(ad) <= ' ' { %repeat !$FINISH end found = 0; id = 1 while id <= dirmax cycle if matched # 0 start found = found+1; foundid(found) = id return if found = maxline-1 id = |dir(id)_brother|; !don't look at descendants too finish else id = id+1 repeat end ; !SEARCH FOR STRING routine NEWLINE print symbol(nl) if skipping = 0 line = line+1; col = 0 end routine SPACES(integer n) while n > 0 cycle print symbol(' '); col = col+1; n = n-1 repeat end routine PUT NUM(integer n) put num(n//10) and n = n-n//10*10 if n >= 10 print symbol(n+'0'); col = col+1 end routine PRINT IDENT(integer id) record (dirinfo)name d d == dir(id) if d_parent # 0 start print ident(d_parent); print symbol('.'); col = col+1 finish put num(d_number) end routine PRINT TITLE(integer id) integer ad,length !$IF VAX ad = dir(id)_address; length = shortinteger(ad)-2 col = col+length ad = ad+4; !past length bytes & '!<' while length > 0 cycle print symbol(byteinteger(ad)) ad = ad+1; length = length-1 repeat !$IF APM { ad = dir(id)_address+2 { %while byteinteger(ad) >= ' ' %cycle { print symbol(byteinteger(ad)) { ad = ad+1; col = col+1 { %repeat !$FINISH end routine PRINT LINE integer ad,length !$IF VAX ad = textad; length = shortinteger(ad) textad = textad+(length+3)&even ad = ad+2 while length > 0 cycle print symbol(byteinteger(ad)) ad = ad+1; length = length-1 repeat newline !$IF APM { %cycle { print symbol(byteinteger(textad)) { textad = textad+1 { %repeat %until byteinteger(textad-1) < ' ' { line = line+1; col = 0 !$FINISH end routine RULE LINE integer i !$IF VAX print symbol('-') for i = 1,1,maxcol !$IF APM { set shade(graphical+intense) { print symbol('`') %for i = 1,1,maxcol { set shade(0) !$FINISH newline end routine SET IDENT(integer i) ident = i; page = 1 pagemax = 0; maxpage = 999; maxtextpage = 999 end routine PRINT CONTENT(integer page) owninteger max,maxid,maxnum integer i,k,col1,blanks,code,id record (dirinfo)name d integerfn LINELENGTH(integer ad) integer ad1 ad1 = ad ad = ad+1 until byteinteger(ad-1) < ' ' result = ad-ad1-1 end blanks = 0; more = 0; line = 0 if page <= maxtextpage start textad = pstart(page) cycle return if textad >= limad !$IF VAX length = shortinteger(textad) exit if length >= 2 and byteinteger(textad+2) = '!' if length = 0 start textad = textad+2; blanks = blanks+1 !$IF APM { %exit %if byteinteger(textad) = '!' { %if byteinteger(textad) < ' ' %start { textad = textad+1; blanks = blanks+1 !$FINISH finish else start more = textad and return if line+blanks+1 > maxline if skipping = 0 start newline and blanks = blanks-1 while blanks > 0 print line finish else start line = line+blanks+1; blanks = 0 skip line finish finish repeat !Directive located !$IF VAX code = byteinteger(textad+3) !$IF APM { code = byteinteger(textad+1) !$FINISH if code!let = 'p' start ; !"!PAGE" skip line; more = textad return finish create directory(0,0) if ident = 0 and dirmax = 0 maxtextpage = page return if ident = dirmax id = ident+1 return if dir(id)_parent # ident; !no subsections !Explore subsections to find number,maxwidth d == dir(id) !$IF VAX max = shortinteger(d_address) while d_brother > 0 cycle d == dir(d_brother) max = shortinteger(d_address) if shortinteger(d_address) > max repeat !$IF APM { max = linelength(d_address) { %while d_brother > 0 %cycle { d == dir(d_brother) { k = linelength(d_address) { max = k %if k > max { %repeat { max = max+2 !$FINISH maxnum = d_number maxid = d_level+d_level+3; maxid = maxid+1 if maxnum > 9 finish else id = pstart(page) !Contents col1 = 0 cycle newline and blanks = 0 if blanks # 0; !restrict to 1 more = id and return if line >= maxline col1 = col1+maxid if skipping = 0 start print ident(id) spaces(col1-col) print title(id) finish id = dir(id)_brother exit if id <= 0 col1 = col1+max if col1+maxid+max <= maxcol start spaces(col1-col) if skipping = 0 finish else start newline; col1 = 0 finish repeat newline end ; !PRINT CONTENT routine PRINT PAGE integer length,blanks,code while pagemax < page cycle more = 0 if pagemax = 0 start if ident = 0 then textad = startad c else textad = dir(ident)_address and skip line more = textad finish else if pagemax # maxpage start skipping = 1 print content(pagemax) skipping = 0 finish if more = 0 start maxpage = pagemax; page = maxpage exit finish pagemax = pagemax+1; pstart(pagemax) = more repeat at(0,0); clear frame spaces(10); col = 10 if ident = 0 start ; !at start of file print string(filename) finish else start print title(ident) spaces(60-col) print ident(ident) print symbol('/') and put num(page) if page > 1 finish newline rule line print content(page) if more = 0 start maxpage = pagemax finish else if pagemax = page start pagemax = pagemax+1; pstart(pagemax) = more finish end ; !PRINT PAGE routine READ COMMAND ! Read command and adjust IDENT and PAGE for required page integer i,sym,error routine READ(integername j) j = -1; return unless '0' <= sym <= '9' j = 0 cycle j = j*10+sym-'0'; j = 99 if j > 99 read symbol(sym) repeat until not '0' <= sym <= '9' end routine READ IDENT !First character in SYM integer i,j error = 1 if sym # '/' start i = 0; i = ident if sym = '.' cycle read symbol(sym) if sym = '.' read(j) return if j < 0 or i >= dirmax or dir(i+1)_parent # i i = i+1 cycle j = j-1 exit if j <= 0 i = dir(i)_brother return if i <= 0 repeat repeat until sym # '.' set ident(i) finish read symbol(sym) and read(page) if sym = '/' error = 0 if page > 0 end cycle at(22,0) if more # 0 then printstring("...more ") c else if ident >= dirmax then printstring("End. ") printstring("View:"); clear line read symbol(sym) until sym # ' ' command = sym command = command!let if 'A' <= command <= 'Z' if sym < ' ' start ; !plain control key command = 'q' and return if sym = 'z'&31; !^Z if more # 0 then page = page+1 c else if ident < dirmax then set ident(ident+1) return finish if sym = '-' start if page > 1 then page = page-1 c else if ident # 0 then set ident(ident-1) and page = 99 read symbol(sym) while sym >= ' ' return finish if '0' <= sym <= '9' or sym = '.' or sym = '/' start read ident read symbol(sym) while sym >= ' ' return if error = 0 at(23,0); print string(" No such section"); clear line finish else start read symbol(sym); !second symbol if sym < ' ' start return if command = 'q' set ident(0) and return if command = 't' set ident(dir(ident)_parent) and return if command = 'u' at(17,0); newline printstring(" RETURN: next page -: previous page") newline printstring(" t: top of file u: up one level") newline printstring(" <n>: section <n> x...x: locate 'x...x'") newline printstring(" q: quit program") newline finish else start charmax = 0 cycle charmax = charmax+1; char(charmax) = sym read symbol(sym) repeat until sym < ' ' search for string set ident(foundid(1)) and return if found = 1 if found = 0 start at(23,0); print string("No references found"); clear line finish else start at(maxline+1-found,0); newline for i = 1,1,found cycle if i # maxline-1 start spaces(2) print ident(foundid(i)) spaces(10-col) print title(foundid(i)) finish else print string(" and so on") newline repeat finish finish finish repeat end ; !READ COMMAND !Start of VIEW: connect file on event 4,9 start printstring("View fails"); newline return finish connect file(filename,0,startad,limad) limad = limad+startad dir(0) = 0; dir(0)_address = startad dirmax = 0 set ident(0) cycle print page read command repeat until command = 'q' end ; !VIEW !$IF VAX !Final part only for compilation as runnable program !{\V10IMP %externalstring(255)%fnspec CLIPARAM !{V10IMP} %from imp %include pam !%begin ! define video(-1) ! set video mode(screenmode) ! view(cliparam) ! set video mode(0) !%end endoffile !$IF APM {%integer k,dir {%ownstring(255) s="VIEW:SYSTEM" { prompt("") { read symbol(k) %until k # ' ' { %if k > ' ' %start { s = ""; dir = 0 { %cycle { dir = 1 %if k = ':' { s = s.tostring(k) { read symbol(k) { %repeat %until k <= ' ' { s = "VIEW:".s %if dir = 0 { %finish { set video mode(screenmode&(\single)) { view(s) { set video mode(0) { print ch(nl) {%endofprogram !$FINISH