!*********************************************************************** !* !* Program to read files from a TRIPOS tape !* !* Copyright (C) R.D. Eager University of Kent MCMLXXXIII !* !*********************************************************************** ! constantinteger version = 2; ! Major version number constantinteger edit = 1; ! Edit number within major version ! !*********************************************************************** !* !* Constants !* !*********************************************************************** ! constantinteger no = 0, yes = 1 constantinteger sscharfiletype = 3; ! Subsystem file type constantinteger blksize = 800; ! Size of tape blocks constantinteger chan = 1; ! Channel for tape operations constantinteger maxaction = 5 constantbyteintegerarray actions(1:maxaction) = c 'E','P','H','L','V' constantbyteintegerarray monc(0:11) = c 31,28,31,30,31,30,31,31,30,31,30,31 constantstring (1) snl = " " constantstring (3)array mons(0:11) = c "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" ! ! !*********************************************************************** !* !* Record and array formats !* !*********************************************************************** ! recordformat hf(integer dataend,datastart,filesize,filetype,c sum,datetime,format,records) recordformat rf(integer conad,filetype,datastart,dataend) ! ! !*********************************************************************** !* !* Subsystem references !* !*********************************************************************** ! systemroutinespec changefilesize(string (31) file, integer newsize,integername flag) systemroutinespec connect(string (31) file,integer mode,hole, prot,record (rf)name r,integername flag) externalstringfunctionspec date systemroutinespec destroy(string (31) file,integername flag) systemroutinespec disconnect(string (31) file,integername flag) systemstringfunctionspec failuremessage(integer mess) systemstringfunctionspec itos(integer n) systemroutinespec modpdfile(integer ep,string (31) pdfile, string (11) member,string (31) infile, integername flag) systemroutinespec move(integer length,from,to) systemstringfunctionspec nexttemp systemroutinespec outfile(string (31) file,integer size,hole, prot,integername conad,flag) externalintegerfunctionspec outpos systemintegerfunctionspec parmap externalroutinespec prompt(string (255) s) systemintegerfunctionspec pstoi(string (63) s) systemroutinespec setpar(string (255) s) externalroutinespec set return code(integer i) systemstringfunctionspec spar(integer n) externalstringfunctionspec time systemroutinespec trim(string (31) file,integername flag) systemroutinespec uctranslate(integer ad,len) ! externalroutinespec define(string (255) s) ! ! !*********************************************************************** !* !* Magnetic tape interface routines !* !*********************************************************************** ! externalroutinespec askmag(integer channel,string (7) vol, integername flag) externalroutinespec readmag(integer channel,ad,integername len,flag) externalroutinespec rewindmag(integer channel) externalroutinespec skipmag(integer channel,n) externalroutinespec skiptmmag(integer channel,n) externalroutinespec unloadmag(integer channel) ! ! !*********************************************************************** !* !* Own variables !* !*********************************************************************** ! owninteger masktype; ! Used to record type of current mask ! ! !*********************************************************************** !* !* Service routines !* !*********************************************************************** ! stringfunction specmessage(integer n) switch sw(1000:1000) ! -> sw(n) ! sw(1000): result = "Failed to claim tape" end ; ! of specmessage ! ! routine fail(integer n) string (255) s ! selectoutput(0) if n < 1000 then s = failuremessage(n) else s = specmessage(n) printstring(snl."TRIPOSMT fails -".s) unloadmag(chan) set return code(n) stop end ; ! of fail ! ! routine reset rewindmag(chan) skipmag(chan,1) end ; ! of reset ! ! routine skiptm(integer n) integer i ! for i = 1,1,n cycle skiptmmag(chan,1) repeat end ; ! of skiptm ! ! routine readline(stringname s) integer c ! s = "" cycle cycle readsymbol(c) exit if c = nl s <- s.tostring(c) repeat while length(s) > 0 and charno(s,length(s)) = ' ' cycle length(s) = length(s) - 1 repeat exit unless s = "" repeat uctranslate(addr(s)+1,length(s)) end ; ! of readline ! ! integerfunction match(string (63) s,mask) ! masktype = 0 before initialisation, ! 1 for *A*, ! 2 for *A, ! 3 for A* or A*B, ! 4 for A ownstring (15) masks,maskt string (63) work1,work2 switch typ(1:4) ! result = yes if mask = "*" or mask = "" ! Common case if masktype = 0 then start ; ! First time in for this mask - analyse it if mask -> work1.("*").masks and work1 = "" then start if charno(masks,length(masks)) = '*' then start maskt = substring(masks,1,length(masks)-1) masktype = 1 finish else start maskt = masks masktype = 2 finish finish else start if mask -> masks.("*").maskt then start masktype = 3 finish else masktype = 4 finish finish ! -> typ(masktype) ! typ(4): if mask = s then result = yes else result = no ! typ(3): unless s -> work1.(masks).s and work1 = "" then result = no if maskt = "" then result = yes ! typ(2): typ(1): unless s -> work1.(maskt).work2 then result = no if masktype = 1 then result = yes while s -> work1.(maskt).work2 cycle if work2 = "" then result = yes s = substring(s,length(work1)+2,length(s)) repeat result = no end ; ! of match ! ! integerfunction checkswitch(integer c) integer i ! for i = 1,1,maxaction cycle if c = actions(i) then result = i repeat result = -1 end ; ! of checkswitch ! ! routine getcommand(integername type,stringname srce,dest) integer l string (63) line string (255) work1,work2 ! type = 0 readline(line) line = work1.work2 while line -> work1.(" ").work2 l = length(line) if l >= 2 then start if charno(line,l-1) = '/' then start type = checkswitch(charno(line,l)) length(line) = l - 2 finish finish if line -> work1.("/").work2 then start type = -1 return finish ! if line -> work1.("=").work2 then start dest <- work1 srce <- work2 finish else start dest = "" srce <- line finish end ; ! of getcommand ! ! integerfunction wild(string (31) s) if s -> ("*") then result = yes result = no end ; ! of wild ! ! stringfunction tdate(integer n) integer year,month,m string (2) y string (9) s ! year = n//1000 n = n - year*1000 month = 0 cycle m = monc(month) if month = 1 and year//4*4 = year then m = m + 1 exit if n <= m month = month + 1 n = n - m repeat s = itos(n) y = itos(year) if length(y) = 1 then y = "0".y if length(s) = 1 then s = "0".s result = s."-".mons(month)."-".y end ; ! of tdate ! ! routine printhelp printstring(" Program call is: TRIPOSMT(tape[,commands]) Command format is: destination=source/switch where one or two items may be null. ") printstring(" File specs are: up to 17 alphanumeric characters where an asterisk is also allowed, denoting a 'wild' component that matches any substring. ") printstring(" Switches are: /E - exit from TRIPOSMT. /P - set current pdfile.") printstring(" /H - print this help text. /L - give a directory of all or part of the tape. /V - display version number of TRIPOSMT. ") end ; ! of printhelp ! ! routine directory(stringname mask) integer ad,len,flag,i,adw,blocks,files,wildcard string (255) work byteintegerarray buf(0:blksize-1) ! ad = addr(buf(0)) adw = addr(work) + 1 ! rewindmag(chan) len = blksize readmag(chan,ad,len,flag) if flag # 0 then start if flag = 1 then printstring("?Unexpected tape mark".snl) else c printstring("?Tape read error".snl) reset return finish move(6,ad+4,adw) length(work) = 6 while charno(work,length(work)) = ' ' cycle length(work) = length(work) - 1 repeat printstring(snl."Directory mt:".work." on ") printstring(date." at ".time.snl.snl) ! wildcard = wild(mask) files = 0 blocks = 0 cycle len = blksize readmag(chan,ad,len,flag) exit if flag = 1; ! Final tape mark if flag > 1 then start printstring("?Tape read error".snl) reset return finish move(4,ad,addr(i)) if i # m'HDR1' then start printstring("?HDR1 not found when expected".snl) reset return finish length(work) = 17 move(17,ad+4,adw) for i = 17,-1,1 cycle if charno(work,i) # ' ' then exit length(work) = length(work) - 1 repeat if match(work,mask) = no then start skiptm(3) continue finish printstring(work) files = files + 1 printstring("/".itos(files)) spaces(24-outpos) skiptm(2) len = blksize readmag(chan,ad,len,flag) move(4,ad,addr(i)) if i # m'EOF1' then start printstring("?EOF1 not found where expected".snl) reset return finish move(6,ad+54,adw) length(work) = 6 i = pstoi(work); ! Number of blocks blocks = blocks + i write(i,3) printstring(" Block") if i = 1 then space else printsymbol('s') space move(5,ad+42,adw) length(work) = 5 printstring(tdate(pstoi(work)).snl) exit if wildcard = no skiptmmag(chan,1) repeat ! printstring(snl."Total of ".itos(blocks)." block") printsymbol('s') unless blocks = 1 printstring(" in ".itos(files)." file") printsymbol('s') unless files = 1 newlines(2) end ; ! of directory ! ! routine transfer(stringname srce,dest,pdfile) integer i,pd,rewound,ad,len,flag,ptr,conad,adt,wildcard string (11) name string (31) out,temp byteintegerarray buf(0:blksize-1) record (rf) rr record (hf)name r ! dest = "*" if dest = "" ad = addr(buf(0)) adt = addr(temp) + 1 if wild(srce) = yes then start wildcard = yes reset rewound = yes finish else start wildcard = no rewound = no finish ! cycle len = blksize readmag(chan,ad,len,flag) if flag > 1 then start printstring("?Tape read error".snl) reset return finish if flag = 1 then start ; ! Final tape mark reset if rewound = no then start rewound = yes continue finish if wildcard = no then printstring("?File not found".snl) return finish move(4,ad,addr(i)) if i # m'HDR1' then start printstring("?HDR1 not found when expected".snl) reset return finish length(temp) = 17 move(17,ad+4,adt) for i = 17,-1,1 cycle if charno(temp,i) # ' ' then exit length(temp) = length(temp) - 1 repeat if match(temp,srce) = no then start skiptm(3) continue finish ! skiptmmag(chan,1); ! Skip to just before first data block name <- temp if wildcard = yes then start printstring("[".name."]".snl) finish if wild(dest) = yes then out = name else out = dest if pdfile # "" then start out = "T#".nexttemp pd = yes finish else pd = no outfile(out,4096,0,0,conad,flag) if flag # 0 then start printstring("%".failuremessage(flag)) skiptm(2) continue finish r == record(conad) r_filetype = sscharfiletype ptr = r_dataend ! cycle len = blksize readmag(chan,ad,len,flag) if flag > 1 or (flag = 0 and len # blksize) then start printstring("?Tape read error".snl) destroy(out,flag) reset return finish if flag = 1 then exit ; ! End of file len = halfinteger(ad+blksize-2) if ptr + len >= r_filesize then start i = (r_filesize+131072) & (¬131071) changefilesize(out,i,flag) if flag = 261 then start ; ! VM hole too small disconnect(out,flag) changefilesize(out,i,flag) if flag = 0 then connect(out,3,0,0,rr,flag) if flag = 0 then start conad = rr_conad r == record(conad); ! Re-map - it may have moved finish finish if flag # 0 then start printstring("?".failuremessage(flag)) skiptm(2) return finish r_filesize = i finish move(len,ad,conad+ptr) ptr = ptr + len repeat ! r_dataend = ptr trim(out,flag) skiptmmag(chan,1) ! if pd = yes then start connect(pdfile,0,0,0,rr,flag) if flag = 218 then start ; ! Create pdfile modpdfile(4,pdfile,"","",flag) if flag # 0 then start printstring("?".failuremessage(flag)) return finish finish name = dest if wild(dest) = no modpdfile(2,pdfile,name,"",flag); ! Delete any existing member of same name modpdfile(1,pdfile,name,out,flag);! Insert new member if flag # 0 then start printstring("?".failuremessage(flag)) return finish destroy(out,flag) finish else start disconnect(out,flag) finish unless wildcard = yes then exit repeat end ; ! of transfer ! ! !*********************************************************************** !* !* T R I P O S M T !* !*********************************************************************** ! externalroutine triposmt(string (255) parms) integer flag,type string (6) vol string (11) pdfile string (31) input,srce,dest switch sw(0:maxaction) ! set return code(9999) setpar(parms) if parmap > 3 then fail(263); ! Wrong number of parameters vol <- spar(1) input <- spar(2) if vol = "" then fail(263); ! Wrong number of parameters if input = "" then input = ".IN" define("1,".input) selectinput(1) ! askmag(chan,vol,flag) if flag # 0 then fail(1000); ! Failed to claim tape reset ! pdfile = "" prompt("*") cycle masktype = 0 getcommand(type,srce,dest) if type < 0 or (type = 0 and srce = "") then start printstring("?Illegal command".snl) continue finish -> sw(type) ! sw(0): transfer(srce,dest,pdfile) continue ! sw(1): ! /E exit ! sw(2): ! /P pdfile <- srce if dest # "" then start printstring("%File ".dest." ignored".snl) finish continue ! sw(3): ! /H unless srce = "" = dest then start printstring("%Files ignored".snl) finish printhelp continue ! sw(4): ! /L if dest # "" then start printstring("%File ".dest." ignored".snl) finish if srce = "" then srce = "*" directory(srce) reset continue ! sw(5): ! /V unless srce = "" = dest then start printstring("%Files ignored".snl) finish printstring("Version: E".itos(version).".".itos(edit).snl) continue repeat ! unloadmag(chan) set return code(0) end ; ! of triposmt endoffile