!TITLE View source code ! This is the source code of VIEW ! ! !<System routine ZVIEW !%SYSTEMROUTINE ZVIEW(%STRING(255)S) ! VIEW(S) !%END ! ! This is simply a call on VIEW which can be used by a program ! to ensure that it does actually call the 'system' version of ! VIEW. !> ! ! ! !<System integer fn ZVIEWREFS !%SYSTEMINTEGERFN ZVIEWREFS(%STRING(31)FILE, %STRING(255)KEYS, %C ! %INTEGER MAXREF, %RECORDARRAYNAME REF, %INTEGER SUBFILES) ! ! This function uses VIEW to scan the file FILE for the keys ! given in KEYS. Any 'hits' are returned in the record array ! REF up to a maximum of MAXREF. All the subsidiary files of ! FILE are examined automatically unless SUBFILES = 0. The number ! of 'hits' is returned as the result and may be greater than ! MAXREF. ! ! KEYS has the form ! key1 & key2 & ... ! where keyi may have an asterisk before and/or after ! ! REF is an array (1:MAXREF) of records whose format is ! %string(31)SECTION NAME, TOPIC, FILE, SECTION NUMBER ! To view a reference, call ! ZVIEW(FILE, SECTION NUMBER) ! If KEYS is null, the name and topic of the file, and each ! subfile if requested, are returned in REF. !> ! ! ! CONSTSTRINGNAME DATE = X'80C0003F' CONSTSTRINGNAME TIME = X'80C0004B' CONSTSTRING (10)NLS10 = " " CONSTSTRING (15)DEFAULT FILE = "SUBSYS.VIEWBASE" CONSTSTRING (8)VIEWDIR = "VIEWDIR2" CONSTSTRING (8)VIEWKEY = "VIEWKEYS" ! ! ! CONSTINTEGER KENT = 0 CONSTINTEGER ERCC = 1 CONSTINTEGER SITE = KENT ! CONSTINTEGER NO = 0 CONSTINTEGER YES = 1 CONSTINTEGER TOP FT = 60 CONSTINTEGER TOP PAD = 6 CONSTBYTEINTEGERARRAY PAD(1 : TOP PAD) = 35,23,17,13,11,1 ! ! ! ! RECORDFORMAT C BNF(BYTEINTEGER LEN, S1, S2, S3, INTEGER ADR) RECORDFORMAT C DIRF(STRING (30)SEC, BYTEINTEGER PER, STRING (31)NAME, INTEGER P1, P2, SUBS, LINK) OWNRECORD (DIRF)ARRAYFORMAT C DIRAF(-1:130000) RECORDFORMAT C FDF(INTEGER LINK, DSNUM, {CUR, below, is addr of next byte to be written} BYTEINTEGER STATUS, ACCESSROUTE, VALID ACTION, CUR STATE, BYTEINTEGER MODE OF USE, MODE, FILE ORG, DEV CODE, BYTEINTEGER REC TYPE, FLAGS, LM, RM, INTEGER ASVAR, AREC, RECSIZE, MINREC, MAXREC, MAXSIZE, LASTREC, CONAD, CURREC, CUR, END, TRANSFERS, DARECNUM, CURSIZE, DATASTART, STRING (31) IDEN, INTEGER KEYDESC0, KEYDESC1, RECSIZEDESC0, RECSIZEDESC1, BYTE INTEGER F77FLAG, F77FORM, F77ACCESS, F77STATUS, INTEGER F77RECL, F77NREC, IDADDR, BYTE INTEGER F77BLANK, F77UFD, SPARE1, SPARE2) RECORDFORMAT C FHDRF(INTEGER NFB, TXTST, MAX, TYPE, CHKSUM, TIMESTAMP, ADR, COUNT) RECORDFORMAT C FRAMEF(INTEGER I, T, CJ, STATE) RECORDFORMAT C MEMF(INTEGER START, STRING (11)NAME, INTEGER S1, S2, S3, S4) OWNRECORD (MEMF)ARRAYFORMAT C MEMAF(0:4095) RECORDFORMAT C FTF(STRING (46)FILE, BYTEINTEGER SSW, STRING (71)PROMPT, INTEGER CONRES, TIMESTAMP, CONBASE, DIRA, KEYA) RECORDFORMAT C REFF(STRING (31)NAME, TOPIC, FILE, SEC) OWNSTRING (31)ARRAYFORMAT C S31AF(1 : 100) RECORDFORMAT C RF(INTEGER ADR, TYPE, START, END) ! ! ! DYNAMICROUTINESPEC C CALL(STRING (31)COMMAND, STRING (255)PARAMETER) SYSTEMROUTINESPEC C CASTOUT(STRINGNAME S) DYNAMICROUTINESPEC C CLEAR(STRING (255)S) SYSTEMROUTINESPEC C CONNECT(STRING (31)FILE, INTEGER MODE, HOLE, PROT, RECORD (RF)NAME R, INTEGERNAME FLAG) SYSTEMROUTINESPEC C CONSOLE(INTEGER TYPE, INTEGERNAME START, LENGTH); ! TYPE=7 : KILL OUTPUT DYNAMICROUTINESPEC C DEFINE(STRING (255)S) SYSTEMROUTINESPEC C DESTROY(STRING (31)FILE, INTEGERNAME FLAG) SYSTEMROUTINESPEC C DISCONNECT(STRING (31)FILE, INTEGERNAME FLAG) EXTERNALINTEGERFNSPEC C DRESUME(INTEGER C, B, A) EXTERNALINTEGERFNSPEC C DSFI(STRING (31)INDEX, INTEGER FSYS, TYPE, SET, ADR) SYSTEMINTEGERFNSPEC C DTWORD(INTEGER X) SYSTEMSTRINGFNSPEC C FAILURE MESSAGE(INTEGER FLAG) SYSTEMINTEGERFNSPEC C FDMAP(INTEGER CHAN) SYSTEMSTRINGFNSPEC C HTOS(INTEGER VALUE, PLACES) SYSTEMINTEGERFNSPEC C IOCP(INTEGER EP, PARM) ROUTINESPEC C LAYNEWPAGE SYSTEMROUTINESPEC C LOAD(STRING (31)COMMAND, INTEGER I, INTEGERNAME FLAG) EXTERNALSTRING (255)FNSPEC C MODESTR SYSTEMROUTINESPEC C MODPDFILE(INTEGER ACT, STRING (31)PDFILE, STRING (11)MEMBER, STRING (31)INFILE, INTEGERNAME FLAG) ! ACT 1 INSERT ! 2 REMOVE ! 3 RENAME ! 4 CREATE PD FILE SYSTEMROUTINESPEC C NEWGEN(STRING (31)FROM, TO, INTEGERNAME FLAG) SYSTEMROUTINESPEC C OUTFILE(STRING (31)S, INTEGER LEN, MAX, PRM, INTEGERNAME ADR, RES) DYNAMICROUTINESPEC C PROMPT(STRING (255)S) SYSTEMINTEGERFNSPEC C QUERY MODE(INTEGER N) EXTERNALINTEGERFNSPEC C READID(INTEGER A) SYSTEMROUTINESPEC C REROUTECONTINGENCY(INTEGER EP, CLASS, LONGINTEGER MASK, ROUTINE STRAP(INTEGER CLASS, SUBCLASS), INTEGERNAME FLAG) EXTERNALROUTINESPEC C SETMODE(STRING (255)S) SYSTEMROUTINESPEC C SIGNAL(INTEGER EP, P1, P2, INTEGERNAME FLAG) DYNAMICROUTINESPEC C TERMINALTYPE(STRING (255)S) EXTERNALROUTINESPEC C TERMINATE SYSTEMROUTINESPEC C UCTRANSLATE(INTEGER ADR, LEN) EXTERNALINTEGERFNSPEC C UINFI(INTEGER N) EXTERNALSTRINGFNSPEC C UINFS(INTEGER N) SYSTEMSTRING (8)FNSPEC C UNPACKDATE(INTEGER P) SYSTEMSTRING (8)FNSPEC C UNPACKTIME(INTEGER P) EXTERNALINTEGERFNSPEC C VDUB(INTEGER N) EXTERNALINTEGERFNSPEC C VDUI(INTEGER N) EXTERNALSTRINGFNSPEC C VDUS(INTEGER N) STRINGFNSPEC C VIEWFN(STRING (255)S, LINE) DYNAMICROUTINESPEC C ZCOPY2 ALIAS "S#ZCOPY2" (STRING (255)S, INTEGER SILENT, INTEGERNAME FLAG) ! ! ! OWNINTEGER KK TOP REF; ! max the user can accept OWNINTEGER KK REF ADDR; ! address of REF(1) OWNINTEGER KK TOP KEY; ! number of keys (in array KKEY) OWNINTEGER KK REFI; ! number of references found OWNINTEGER KKEYPT; ! address of next avail byte in T#KEYWRK OWNINTEGER KK TOP KEYPT; ! address of max avail byte... OWNSTRING (63)ARRAY KKEY(1 : 10) ! ! ! OWNINTEGER LEVEL = 0 OWNINTEGER LAST SCREEN ID; ! previous value of SCREEN ID OWNINTEGER LIBRAR = 0; ! SET TO 1 IF USER IS LIBRAR OWNINTEGER LINT; ! set non zero on receipt of INT: K OWNINTEGER LPPAGE = 20 OWNINTEGER MAXDIR = 13000 { so need up to 17 bits and 13 bits for the 'frame' in contents } OWNINTEGER PARTIAL DISPLAY = 0; ! set non zero to get heading only OWNINTEGER RESTRICTED = 0; ! set non zero for VIEWER, LIBRAR etc OWNINTEGER SCREEN ID; ! used to record what is on display OWNINTEGER VDUI3; ! LINES/PAGE, 0=HARDCOPY OWNINTEGER VIEWMON = 0 OWNINTEGER WIDTH = 72 ! ! ! CONSTINTEGER TOP PARAMETER = 115 OWNSTRING (31)ARRAY PARAMETER(100 : TOP PARAMETER) OWNBYTEINTEGERARRAY PARAMETER USED(100 : TOP PARAMETER) OWNINTEGER SOME PARAMETER USED ! ! ! OWNINTEGER EFFING STYLE = 1 OWNSTRING (31)EFFING FILE = "" OWNSTRING (11)OUTPUT FILE ! ! ! OWNSTRING (6)PROCUSER OWNSTRING (255)SAVEMODE OWNSTRING (31)VDUS1 = ""; ! CLEAR SCREEN SEQUENCE OWNSTRING (31) START STANDOUT, END STANDOUT ! ! OWNINTEGER KSUPSUBFILES ! ! OWNRECORD (FTF)ARRAY FTS(1 : TOP FT) CONSTINTEGER TOP LEVEL = 99 OWNBYTEINTEGERARRAY FTI(1 : TOP LEVEL) ! ! ! CONSTINTEGER TOP STRIP = 100 OWNINTEGERARRAY STRIP(0 : TOP STRIP) OWNINTEGER STRIPJ ! ! ! ROUTINE MON(STRING (255)S1, S2) UNLESS VIEWMON = 0 START PRINTSTRING(S1.": ") PRINTSTRING(S2) NEWLINE FINISH END ! ! ! STRING (255)FN ITOS(INTEGER N0) STRING (11)S INTEGER I, N N = N0 N = -N IF N < 0 S = "" CYCLE I = N N = N // 10 I = I - 10 * N + '0' S = TOSTRING(I) . S EXIT UNLESS N > 0 REPEAT S = "-" . S IF N0 < 0 RESULT = S END ; ! ITOS ! ! ! ROUTINE PRINTCHS(STRING (255)S) INTEGER LEN, ADR, RES; ! KEEP IN THIS ORDER !!!! RETURN IF LENGTH(S) = 0 LEN = LENGTH(S) ADR = ADDR(S) + 1 RES = IOCP(19, ADDR(LEN)) END ! ! ! ROUTINE W(STRING (255)S) STRING (1)NP STRING (255)S1, S2 NP = TOSTRING(12) S = S1 . S2 WHILE S -> S1 . (NP) . S2 PRINTCHS(S) NEWLINE END ! ! ! ROUTINE RSTRG(STRINGNAME S) INTEGER I S = "" CYCLE READSYMBOL(I) RETURN IF I = NL S = S . TOSTRING(I) REPEAT END ; ! OF RSTRG ! ! ! INTEGERFN STOI2(STRING (255) P, INTEGERNAME I2) INTEGER TOTAL, AD, I, J STRING (255) WORK TOTAL = 0 AD = ADDR(P) A: IF P -> WORK.(" ").P THEN START -> A IF WORK = "" P = WORK." ".P FINISH I = 1 WHILE I <= BYTEINTEGER(AD) CYCLE J = BYTE INTEGER(I+AD) -> FAULT UNLESS '0' <= J <= '9' TOTAL = 10*TOTAL + J&15 I = I+1 REPEAT IF I > 1 THEN I2 = TOTAL AND RESULT = 0 FAULT: I2 = 0 RESULT = 1 END ; ! STOI2 ! ! ! ROUTINE READ VALUE(STRINGNAME S) INTEGER J, N, FAIL STRING (255)NUM, PROMPTTEXT, DEFAULT, HELP, TEMPLATE, VALUE FAIL = 1 IF S -> NUM . ("¬") . PROMPT TEXT.("¬").DEFAULT.("¬").HELP START TEMPLATE = "" UNLESS HELP -> HELP . ("¬") . TEMPLATE ! J = STOI2(NUM, N) IF J = 0 AND 100 <= N <= TOP PARAMETER START PROMPT(PROMPT TEXT . ": ") L: RSTRG(VALUE) VALUE = DEFAULT IF VALUE = "" W(HELP) AND -> L IF VALUE = "?" FAIL = 0 PARAMETER(N) = VALUE PARAMETER USED(N) = 1 SOME PARAMETER USED = 1 FINISH FINISH ! W("Incorrect use: !READ " . S) IF FAIL = 1 END ; ! READ VALUE ! ! ! ROUTINE DRAWLINE INTEGER N NEWLINE RETURN IF VDUI3 = 0; ! Not a Video CYCLE N = 1, 1, WIDTH PRINTSTRING("-") REPEAT NEWLINE END ; ! DRAWLINE ! ! ! ROUTINE BLANKLINES(INTEGER N) UNLESS VDUI3 = 0 OR N < 1 C THEN NEWLINES(N) END ! ! ! ROUTINE WRITEN(INTEGER N) PRINTSTRING(ITOS(N)) END ; ! OF WRITEN ! ! ! ROUTINE DESPACE(STRINGNAME S) INTEGER I, J, K, CH J = LENGTH(S) RETURN IF J = 0 K = 0 ! CYCLE I = 1, 1, J CH = CHARNO(S, I) UNLESS CH = ' ' START K = K + 1 CHARNO(S, K) = CH IF I > K FINISH REPEAT ! LENGTH(S) = K IF J > K END ; ! DESPACE ! ! ! STRINGFN JUST(STRING (255)S) INTEGER A, I, J I = 1 J = LENGTH(S) I = I + 1 WHILE I < J AND CHARNO(S, I) = ' ' J = J - 1 WHILE I < J AND CHARNO(S, J) = ' ' I = I - 1 A = ADDR(S) + I BYTEINTEGER(A) = J - I RESULT = STRING(A) END ! ! ! ROUTINE MOVE(INTEGER LEN, FROM, TO) *LDTB_X'18000000' *LDB_LEN *LDA_FROM *CYD_0 *LDA_TO *MV_L =DR END ! ! ! integerfn MAIL SUPPORT(string (255)s, fsubject) !! !! Offers the TELL interface, with extensions, to send a message !! via MAILER. Parameters are <address>,<file>,<subject> !! - if <file> is omitted, text is read from the console !! until nl*nl sequence. !! Various forms for address: !! usernumber (at this host assumed) ERCC27 (at 2972) !! directory name S.Shaw !! name@other host ERCC99@2980 record format frf(integer a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, string (6) a11, string (8) a12, a13, integer a14, a15, a16) record format rf(integer conad, filetype, datastart, dataend) record format paf(integer dest, srce, flag, message count, secs, ident, bad bitcomp, p6) system routine spec finfo(string (31) file, integer mode, record (frf) name fr, integer name flag) system routine spec setfname(string (40) name) system routine spec psysmes(integer root, mess) external routine spec prompt(string (15) s) external string fn spec derrs(integer flag) external routine spec setreturncode(integer flag) system routine spec connect(string (31) file, integer mode, hole, prot, record (rf) name r, integer name flag) system routine spec destroy(string (31) file, integer name flag) system routine spec disconnect(string (31) file, integer name flag) external integer fn spec dmail(record (paf) name p, integer len, adr) external integer fn spec dpermission(string (6) owner, user, string (8) date, string (11) file, integer fsys, type, adrprm) system string fn spec itos(integer n) system routine spec outfile(string (31) file, integer size, hole, prot, integer name conad, flag) system routine spec move(integer len, from, to) system routine spec uctranslate(integer addr, length) external string fn spec uinfs(integer entry) external integer fn spec uinfi(integer entry) record (paf) pa record (rf) r record (frf) fr integer len, flag, conad, i, j, nlsw, query, lines string (255) to, file, name, server, subject const integer invalid user= 201; !SS FLAG const integer tempfile= x'40000000'; !CREATE MODE const integer sscharfiletype= 3 const integer general= 233 const integer max mflag= 529 const string (28) array mailer mess(501:max mflag)= c "Invalid parameters", "Duplicate component:", "Unknown component", "Invalid command", "No valid recipients", "Too many recipients", "Addr table full", "Name table full", "Illegal name", "Mail service closed", "Recipient offline", "Message too long", "MAILER fault", "Missing component:", "No free message descriptors", "Invalid component:", "Total message kb exceeded", "Cannot return report file", "Message stored", "Forbidden component", "Create file fails", "User not accredited", "Invalid password", "Name not accredited", "Name already accredited", "Name belongs to another user", "Uncollected mail for R-name", "Invalid date/time after", "Not allowed in student procs" const string (1) snl= " " const string (12) config file="FTRANS.CFILE"; !"MANAGR.MFILE" const integer this auth flag= 8 const integer this host flag=16 const integer max fsys=99 const integer hash length= 1023 const integer station entry size= 512 own integer config conad=0 record format pointers f(integer link list displ, ftp table displ, queues, queue entry size, queue displ, queue name displ, streams, stream entry size, stream displ, remotes, remote entry size, remote displ, hash len, station, station entry size, station displ, station name displ, station addresses displ, guest no, byte integer array discs(0:max fsys), string (63) dead letters, this full host, integer expanded address displ, integer array hash t(0:hash length)) record format station f((byte integer max lines or c byte integer max ftp lines), byte integer status, (byte integer service or c byte integer ftp service), byte integer connect retry ptr, fep, address type, accounting, (byte integer q lines or byte integer ftp q lines), (integer limit or c integer ftp limit), integer last call, last response, system loaded, connect attempts, connect retry time, integer array ispare(0:4), integer seconds, bytes, integer last q response by us, p transfers, q transfers, p kb, q kb, p mail, q mail, integer name, shortest name, integer array address(1:4), integer pss entry, integer mail, integer ftp, integer description, (integer queue or c integer route), integer flags, byte integer array string space(0:375) {decrement this if more fields added, keep to 512 total}) record (pointers f) name pointers record (station f) name station integer fn connect configfile record (rf) rr integer flag connect(config file, 1!8 {read shared}, 0, 0, rr, flag) if flag#0 then printstring(" - configuration file not currently available".snl) and result = -2 config conad = rr_conad pointers == record(config conad+rr_datastart) result = 0 end ; !of connect config integer fn lookup hasht(string (127) name) const integer station entry size= 512 record format hname f(integer link, host entry, string (255) name) record (hname f) name hname entry integer i, pt, n, h byte integer array x(0:15) const byte integer array prime(1:7)= 23, 19, 11, 7, 5, 13, 17 pt = (addr(x(7))>>3)<<3 longinteger(pt) = 0 n = addr(name) byteinteger(pt+i&7) = byteinteger(pt+i&7)!!byteinteger(n+i) for i = 0, 1, length(name) h = length(name)*29 h = h+prime(i)*byteinteger(pt+i) for i = 1, 1, 7 h = h&hash length if pointers_hasht(h)#-1 start hname entry == record(config conad+pointers_hasht(h)) cycle if name=hname entry_name start ; !found it station == record(config conad+pointers_station displ+(hname entry_host entry-1)*station entry size) result = hname entry_host entry finish exit if hname entry_link=-1 hname entry == record(config conad+hname entry_link) repeat finish result = 0 end ; !of lookup hasht integer fn lookup host(string (127) name) integer res string (31) this ukac string (127) s1, s2 if connect configfile#0 then result = -1 name = s1.s2 while name->s1.(" ").s2 res = lookup hasht(name) if res#0 then result = res this ukac = uinfs(15) ! %monitor unless name->(this ukac).s1 start res = lookup hasht(this ukac.".".name); !prefix uk.ac if res#0 then result = res if name->name.(".").s1 then result = lookup hasht(name); !for arpa. finish result = -1 end ; !of lookup host routine error(integer flag, string (255) text) destroy("M#MSG", i) setreturncode(flag) if length(text)>40 then length(text) = 40 setfname(text) if flag#0 then psysmes(2, flag) end ; !OF ERROR !! routine remove end spaces(string name s) length(s) = length(s)-1 while length(s)>0 and charno(s, length(s))=' ' s = substring(s, 2, length(s)) while length(s)>0 and charno(s, 1)=' ' end integer fn check rname s = "" cycle i = 1, 1, length(to) j = charno(to, i) if 'A'<=j<='Z' or '0'<=j<='9' then s = s.tostring(j) repeat s = "NAMESERVER INQUIRE ".s.",FULL,M#DREPORT" pa = 0 flag = dmail(pa, length(s), addr(s)+1) destroy("M#DREPORT", i) if flag=0 then result = invalid user result = 0 end ; !of check rname lines = 2 to = s and subject = fsubject unless s -> to . (",") . subject query = 0 len = length(subject) query = 1 and length(subject) = len - 1 if len > 1 and charno(subject,len) = '?' if to="" then error(263, "") and -> return; !NO PARAMS uctranslate(addr(to)+1, length(to)) to = name.server while to->name.(" ").server if to->name.("@").server start i = lookup host(server) if i<=0 then error(general, "invalid host") and -> return if station_flags&this host flag#0 start if length(name)=6 then finfo(name.".A", 0, fr, flag) else flag = invalid user if flag=invalid user then error(invalid user, to) and -> return else if station_flags&this auth flag#0 start to = name if check rname#0 then error(invalid user, to) and -> return finish finish else if length(to)=6 then finfo(to.".A", 0, fr, flag) else flag = invalid user if flag=invalid user then flag = check rname else flag=0 if flag#0 then error(invalid user, to) and -> return finish outfile("M#MSG", 4096, 0, tempfile, conad, flag) if flag#0 then error(flag, "M#MSG") and -> return string(conad+31) = "To: ".to.snl."Subject: ".subject.snl.SNL.SNL i = conad+byteinteger(conad+31)+32 j = i and -> send if query = 1 printstring("Terminate your comments with an asterisk on a line by itself. ie:".snl) printstring(" Comments: *" . snl) prompt("Comments:") nlsw = nextch; !FORCE PROMPT EARLY nlsw = 1 cycle j = i, 1, i+4000 readsymbol(byteinteger(j)) if nlsw=1 and byteinteger(j)='*' and nextsymbol=nl then skipsymbol and exit if byteinteger(j)=nl then lines = lines + 1 and nlsw = 1 else nlsw = 0 repeat if j=i then error(0, "") and -> return send: len = j-conad-32 s = "MAILSERVER POST M#MSG,32,".itos(len).",M#DREPORT" disconnect("M#MSG", flag) flag = dpermission(uinfs(1), "MAILER", "", "M#MSG", uinfi(1), 2, 3) pa = 0 flag = dmail(pa, length(s), addr(s)+1) if pa_flag#0 start if pa_flag<500 then s = derrs(pa_flag) else start if pa_flag>max mflag then pa_flag = 513 s = mailer mess(pa_flag) finish error(general, s) finish else error(0, "") return: result = lines end ; ! MAIL SUPPORT ! ! ! INTEGERFN KWDSCAN(INTEGERNAME XLENGTH,XADDR, INTEGER KWDCT, C STRINGARRAYNAME KEYS) ! This routine is coded in IMP80 with embedded machine code for the 2900. ! ! This routine searches a 'keyword index' for a section which includes all ! of a set of keywords nominated by the caller. Successive calls will ! discover all such sections in the index. ! ! The index must be laid out as follows: ! Each section consists of a section name (any sequence of bytes not ! including NL, space or colon - they need not all be printable ! characters - there are no rules about the first character being ! alphabetic - the name may, but need not, be an IMP string starting ! with a 'length byte'), and the section name is immediately followed ! by a colon and a space. That is followed by one or more keywords, separated ! by single spaces. Keywords should consist of printable characters, i.e., ! format effectors and length bytes should NOT be included, and the ! three characters NL, space and colon are not permitted in keywords. ! There are no other restrictions on keywords. The last keyword of a ! section must be followed by a space and NL. The next section, if any, ! follows immediately, with no intervening characters. The first section ! in an index may, but need not, be preceded by a NL charcter. The index ! should contain no characters after the NL terminating the last section. ! ! The caller supplies the number of bytes in the index as the parameter ! XLENGTH, and the address of the first byte of the index as the ! parameter XADDR. The number of keywords to be sought is given as KWDCT, ! and the keywords themselves are supplied in IMP strings as KEYS(1:KWDCT). ! ! If a section is found whose keywords include all those nominated by the ! caller, then KWDSCAN will return the address of the first byte of the ! title of that section. If no such section is found, the result will be ! zero. In either case, XLENGTH and XADDR will be updated to specify that ! part of the index which should be scanned at the next call of KWDSCAN. ! That is, if KWDSCAN returns the address of a section title, then ! XADDR will point to the next section (if any) and XLENGTH will be ! correspondingly reduced. Thus a further call of KWDSCAN, using the ! new values of XLENGTH and XADDR, will find another section which satisfies ! the caller's keyword specification (if there is another such section). ! If there are no more sections, or if KWDSCAN returned zero after an ! unsuccessful search, then XLENGTH will be zero and XADDR will point ! to the first byte after the end of the index. ! ! The KEYS may use the same characters as are permitted for the keywords ! in the index. It is also permissible for the first and/or last ! character of any of the KEYS to be a space. If one of the KEYS starts ! with a space, then it can only be matched by a keyword in the index ! which starts with the non-space characters of the KEY. If a KEY ends ! with a space, then it is matched only by keywords which end with the ! non-space characters of the KEY. If it begins and ends with a space, ! then only keywords which exactly match all the non-space characters ! of the KEY will be acceptable. A KEY which contains no spaces can ! be matched by any keyword which includes the KEY. ! ! None of KEYS(1:KWDCT) may be a null string. KWDCT must be >0. ! ! Every occurrence of SECT MARK 1 in the data area must be followed ! by an instance of SECT MARK 2. INTEGER ARRAY CHECKTAB (0:7) INTEGER SECTPTR INTEGER ARRAY SEEN (1:KWDCT) INTEGER I, L, UNSEENCT LONG INTEGER ARRAY KEYDESCR (1:KWDCT) LONG INTEGER SDESCR, XDESCR, KDESCR, DRH CONST INTEGER SECT MARK 1 = NL ! %CONST %INTEGER SECT MARK 2 = ':' ! Bit vector descriptor to the table for TCH: KDESCR = X'0000010000000000' ! ADDR(CHECKTAB(0)) ! Pointer to the start of the section data: SECTPTR = XADDR ! Set up descriptors to the texts of the keywords: CYCLE I = KWDCT, -1, 1 KEYDESCR(I) = (LENGTHENI(X'18000000'!LENGTH(KEYS(I)))<<32) C ! (ADDR(KEYS(I))+1) REPEAT ! Descriptor to the data area supplied by the caller: XDESCR = (LENGTHENI(X'18000000'!XLENGTH)<<32) ! XADDR ! Set up the check table: CYCLE I = 0, 1, 7 CHECKTAB (I) = 0 REPEAT CYCLE I = KWDCT, -1, 1 DRH = KEYDESCR (I) *LB_(DRH); ! Get the first character of KEYS (I). *LSS_1 *ST_(KDESCR+B ); ! Set the corresponding bit in the table. REPEAT *LSS_1 *LD_KDESCR *ST_(DR +SECT MARK 1); ! Set a bit for SECT MARK 1. NEW SECT: ! When we come to a new section, we forget all about any ! KEYS that we may have seen before. CYCLE I = KWDCT, -1, 1 SEEN (I) = 0 REPEAT UNSEENCT = KWDCT ! CYCLE *LSD_KDESCR; ! Descriptor to the check table (for TCH). *LD_XDESCR; ! Descriptor to the data area - more ! accurately, to that part of it which we ! have not yet scanned. *TCH_L =DR ; ! Scan for any interesting character - ! viz., the start-of-section marker, or the ! first character of any of the KEYS. *JCC_8,<XSD>;! Go if no interesting characters have been ! found in the residue of the data area. ! ! If some interesting character has been found: *LSS_(DR +0); ! Fetch the interesting character. *UCP_SECT MARK 1; ! Is it a start-of-section marker? *JCC_8,<SOS>; ! Go if it is a start-of-section marker. ! %EXIT %IF we have found a start-of-section marker. ! ! Can we match any of the requested KEYS? *STD_XDESCR L = INTEGER(ADDR(XDESCR)) & X'00FFFFFF'; ! Length of residue of data. CYCLE I = KWDCT, -1, 1 IF SEEN(I)=0 AND LENGTH(KEYS(I))<=L THEN START DRH = KEYDESCR (I) *LD_DRH *LSD_XDESCR *CPS_L =DR *JCC_7,<TRY NEXT> ! %IF the text we have found matches KEYS(I) %THEN %START SEEN (I) = -1 UNSEENCT = UNSEENCT - 1 IF UNSEENCT=0 THEN START *LD_SDESCR *MODD_1 *CYD_0 *STUH_B *ST_SECTPTR *SWNE_L =DR ,0,10; ! %MASK=0, %REF=SECT MARK 1. *STD_SDESCR XLENGTH = INTEGER(ADDR(SDESCR)) & X'00FFFFFF' XADDR = INTEGER(ADDR(SDESCR)+4) RESULT = SECTPTR FINISH ! %FINISH TRY NEXT: FINISH REPEAT IF L<2 THEN -> XSD; ! Data exhausted. *LD_XDESCR *MODD_1 *STD_XDESCR; ! Skip past the 'interesting character'. REPEAT SOS: ! Handle a start-of-section marker: *STD_SDESCR; ! Save a pointer to the new section. ! *SWNE_%L=%DR,0,SECT MARK 2; ! Skip to the end of the section identifier. ! But that will not compile at the present, so - *SWNE_L =DR ,0,58 *STD_XDESCR; ! Save that descriptor for future reference. *J_<NEW SECT>; ! Go back to process the new section. ! XSD: XADDR = XADDR + XLENGTH XLENGTH = 0 RESULT = 0 ! LIST END ; ! KWDSCAN ! ! ! ROUTINE GETLINE(STRINGNAME LINE, INTEGERNAME T0, T1, INTEGER BASE, EOF) INTEGER L, LMAX, CH, T L = 0 LMAX = 0 LENGTH(LINE) = 255 T = T0 LOOP: CH = BYTEINTEGER(T + BASE) T = T + 1 UNLESS CH = NL START IF CH = 13 START ; ! CR LMAX = L IF L > LMAX L = 0 FINISH ELSE START IF L < 140 START L = L + 1 CHARNO(LINE, L) = CH IFC L > LMAX OR (CH # 95 AND CHARNO(LINE, L) = ' ') FINISH FINISH -> LOOP UNLESS T >= EOF FINISH ! L = LMAX IF LMAX > L LENGTH(LINE) = L T1 = T END ; ! GETLINE ! ! ! STRINGFN GETNAME(INTEGER I, DIRA, CONBASE) INTEGER T0, T1 STRING (255)LINE RECORD (DIRF)ARRAYNAME DIR RECORD (BNF)NAME BIGNAME DIR == ARRAY(DIRA+32, DIRAF) IF LENGTH(DIR(I)_NAME) < 32 C THEN RESULT = DIR(I)_NAME ! BIGNAME == RECORD(ADDR(DIR(I)_NAME)) T0 = BIGNAME_ADR GETLINE(LINE, T0, T1, CONBASE, X'70000000') {should be DIR(I)_P2} LENGTH(LINE) = BIGNAME_LEN RESULT = LINE END ; ! GETNAME ! ! ! ROUTINE DELETE FILE(STRING (255)FILE) INTEGER J STRING (255)U, F, FULL UNLESS FILE -> U . (".") . F C THEN U = PROCUSER AND F = FILE ! F = F . "_" F -> FULL . ("_") . F FULL = U . "." . FULL ! CYCLE J = 1, 1, TOPFT IF FTS(J)_FILE = FULL C THEN FTS(J) = 0 AND RETURN REPEAT END ; ! DELETE FILE ! ! ! INTEGERFN VCONNECT(STRING (255)FILE, INTEGERNAME FTINDEX, STRINGNAME MSG) ! ! ! INTEGER CONBASE, DIRA, KEYA INTEGER BASE, SUBFILEA, KEYPOINT, KEYSAVE, KEYSAVE1, KEYSTATE INTEGER CL, DL, HL, KL, SIZE, ADR, A INTEGER I, J, K, M, IMAX, CONRES STRING (255)MNAME RECORD (RF) CONR STRING (255)USER, FULL, FULLFILE, DFILE, R, LINE STRING (31)VDIR, VKEY ! ! ! RECORD (FTF)NAME FT RECORD (FHDRF)NAME H RECORD (MEMF)NAME MH RECORD (FHDRF)NAME TXT RECORD (MEMF)ARRAYNAME MEM RECORD (DIRF)ARRAYNAME DIR STRINGARRAYNAME SUBFILE ! ! ! INTEGERFN FINFO(STRING (6)USER, STRING (11)FILE) INTEGER J STRING (11)W RECORDFORMAT RF(INTEGER A,B,C,D,E,F,FSYS,SEG,G,H,I,J,STRING (6)OFF) RECORD (RF) R EXTERNALINTEGERFNSPEC DFINFO(STRING (6)USER, STRING (11)FILE, C INTEGER FSYS, ADR) W = FILE LENGTH(FILE) = 2 IF LENGTH(FILE) > 2 W = W . ITOS(UINFI(13)) IF FILE = "T#" J = DFINFO(USER, W, -1, ADDR(R)) IF J = 0 AND R_SEG > 0 C THEN RESULT = 1 C ELSE RESULT = 0; ! 0 = not already connected END ! ! ! INTEGERFN DIFF(INTEGER TA, TB) RESULT = IMOD(DTWORD(TA) - DTWORD(TB)) END ! ! ! INTEGERFN FIND(STRING (255)M) INTEGER I CYCLE I = 0, 1, TXT_COUNT - 1 RESULT = BASE + MEM(I)_START IF MEM(I)_NAME = M REPEAT RESULT = 0 END ; ! OF FIND ! ! ! STRINGFN DIRFILE INTEGER I, J, MAXDEFINE RECORD (FHDRF)NAME H MAXDEFINE = UINFI(6) << 10 ! J = 80 * (MAXDIR + 2) + 3200 IF J > MAXDEFINE START MAXDIR = ((MAXDEFINE - 3200)//80) - 2 J = 80 * (MAXDIR + 2) + 3200 FINISH ! OUTFILE(VDIR, J, 0, 0, DIRA, J) UNLESS J = 0 START RESULT = "OUTFILE" . VDIR . FAILURE MESSAGE(J) FINISH ! H == RECORD(DIRA) H_TYPE = 4; ! TYPE = DATA H_ADR = 3; ! STRUCTURE UNSPECIFIED DIR == ARRAY(DIRA+32, DIRAF) ! CYCLE I = -1, 1, 1 DIR(I) = 0 REPEAT DIR(-1)_SEC <- DFILE; ! default 'topic' ! J = MAXDIR * 128 J = MAXDEFINE IF J > MAXDEFINE OUTFILE(VKEY, J, 0, 0, KEYA, J) UNLESS J = 0 START RESULT = "OUTFILE ".VKEY . FAILURE MESSAGE(J) FINISH ! H == RECORD(KEYA) H_TYPE = 4 H_ADR = 3 KEYPOINT = KEYA + 32 ! SUBFILEA = ADDR(DIR(MAXDIR)) + 80 SUBFILE == ARRAY(SUBFILEA, S31AF) ! RESULT = "" END ! ! ! ROUTINE WRITE KEYS(INTEGER ACT, I, STRING (255)T) ! ! ACT = 0 New section ! 1 Title ! 2 Key ! ! KEY STATE = 0 new section started, KEYSAVE set ! -1 !KEY, ie no keys, KEYPOINT reset ! 1 explicit keys set STRING (255)A, B SWITCH SW(0:2) ! ! ! CONSTSTRING (255)OMIT = C ",AND,SINCE,THE,FROM,WITH, ,EXAMPLES,DESCRIPTION,INTRODUCTION," ! ! ! -> SW(ACT) SW(0): ! New section KEY SAVE = KEY POINT A = ITOS(I) . ":," STRING(KEY POINT) = A BYTEINTEGER(KEYPOINT) = NL KEY POINT = KEY POINT + LENGTH(A) + 1 KEY SAVE1 = KEYPOINT KEY STATE = 0 -> SW1 SW(1): ! Alternative title RETURN UNLESS KEY STATE = 0; ! ignore if some keys have been specified KEY POINT = KEY SAVE1 SW1: T = A . B WHILE T -> A . (":") . B; ! remove colons T = A . " " . B WHILE T -> A . (",") . B; ! turn commas into spaces T = A . " " . B WHILE T -> A . (" ") . B; ! multiple spces to single ones T = A . "," . B WHILE T -> A . (" ") . B; ! turn spaces into commas! UCTRANSLATE(ADDR(T)+1, LENGTH(T)) UNLESS T = "" B = T . ","; ! append a comma T = "" WHILE B -> A . (",") . B CYCLE IF A # "" AND ( LENGTH(A) > 2 OR T = "" = B) START A = A . "," T = T.A UNLESS OMIT -> (",".A) FINISH REPEAT IF T = "" START {what's this bit for?????} KEYSTATE = -1 KEYPOINT = KEYSAVE RETURN FINISH MOVE(LENGTH(T), ADDR(T)+1, KEY POINT) KEY POINT = KEY POINT + LENGTH(T) RETURN SW(2): UCTRANSLATE(ADDR(T)+1, LENGTH(T)) B = T . "," WHILE B -> A . (",") . B CYCLE A = JUST(A) UNLESS A = "" OR A = " " START A = A . "," MOVE(LENGTH(A), ADDR(A)+1, KEYPOINT) KEYPOINT = KEYPOINT + LENGTH(A) FINISH REPEAT END ! ! ! STRINGFN SHORTEN(INTEGER T0, I, TYPE) ! Type = 0 !< ! 1 title ! 2 subfile ! 3 topic CONSTSTRING (7)ARRAY S(0:3) = C "title", "title", "subfile", "topic" CONSTBYTEINTEGERARRAY JS(0:3) = 3, 8, 4, 8 INTEGER J, K, L, TRUNC STRING (255)Z STRINGNAME R RECORD (BNF)NAME BIGNAME Z = LINE J = JS(TYPE) K = LENGTH(Z) IF TYPE = 3 C THEN L = 29 C ELSE L = WIDTH - 2 - LENGTH(DIR(I)_SEC) ! J = J + 1 WHILE J < K AND CHARNO(Z, J) = ' ' K = K - 1 WHILE J < K AND CHARNO(Z, K) = ' ' R == STRING(ADDR(Z) + J - 1) TRUNC = YES L = K - J AND TRUNC = NO UNLESS K > J + L LENGTH(R) = L + 1 IF TRUNC = YES C THEN W(DIR(I)_SEC." Warning: ".S(TYPE)." truncated to ".R) ! IF TYPE = 3 START DIR(-1)_SEC = R FINISH ELSE START IF LENGTH(R) < 32 C THEN DIR(I)_NAME = R C ELSE START BIGNAME == RECORD(ADDR(DIR(I)_NAME)) BIGNAME_LEN = L + 1 BIGNAME_ADR = T0 + J - 1 FINISH WRITEKEYS(TYPE, I, R) IF TYPE < 2 FINISH RESULT = R END ! ! ! ROUTINE SCAN FILE(STRING (31)STEM, NAME, INTEGERNAME I, INTEGER BASE) ! Used to determine the structure of a character ! file. 'stem' is the prefix to use, without any ! trailing dots ie ! null, 1, 1.2, 1.2.3 etc INTEGER LEVEL, IX, S, J, K, T0, T, TXTEOF, I0 STRING (31)ARRAY SECS(-1:15) INTEGERARRAY PER, F, SUBS(0:15) STRING (31)SEC RECORD (FHDRF)NAME H STRING (255)Z, Z0, NULL CONSTINTEGER TOP = 10 CONSTSTRING (8)ARRAY WORD(1:TOP) = C "!TITLE ", "!SKIP", "!KEY ", "!KEY", "!TOPIC ", "!<>", "!<", "!>", "!ADDKEY ", "!HELP" SWITCH SW(1:TOP) H == RECORD(BASE) T = BASE + H_TXTST - CONBASE TXTEOF = BASE + H_NFB - CONBASE F(0) = I I0 = I DIR(I)_SEC = STEM STEM = STEM . "." UNLESS STEM = "" SECS(-1) = STEM DIR(I)_NAME = NAME WRITE KEYS(0, I, NAME) DIR(I)_P1 = T DIR(I)_P2 = 0 I = I + 1 RETURN IF I > MAXDIR DIR(I) = 0 LEVEL = 0 SUBS(0) = 0 PER(0) = 0; ! use first to get max title, then no/line L1: T0 = T; ! remember start of line GETLINE(LINE, T, T, CONBASE, TXTEOF) IX = F(LEVEL) ! IF LENGTH(LINE) > 1 AND CHARNO(LINE, 1) = '!' START CYCLE J = 1, 1, TOP -> SW(J) IF LINE -> NULL . (WORD(J)) . Z AND NULL = "" REPEAT FINISH -> L1 IF T < TXTEOF L2: IX = F(LEVEL) DIR(IX)_SUBS = SUBS(LEVEL) J = PER(LEVEL) + 5 + LENGTH(SECS(LEVEL-1)) CYCLE K = 1, 1, TOP PAD EXIT IF J > PAD(K) REPEAT K = DIR(IX)_SUBS IF K > DIR(IX)_SUBS DIR(IX)_PER = K DIR(IX)_LINK = I DIR(IX)_P2 = T IF DIR(IX)_P2 = 0; ! CLOSE PREFACE IF NECESSARY LEVEL = LEVEL - 1 -> L2 UNLESS LEVEL < 0 RETURN SW(1): ! TITLE Z = SHORTEN(T0, IX, 1) IF LEVEL > 0 START PER(LEVEL-1) = LENGTH(Z) IF LENGTH(Z) > PER(LEVEL-1) FINISH SW1: DIR(IX)_P1 = T IF DIR(IX)_P1 = T0; ! Adjust start of preface if no text yet -> L1 SW(2): ! SKIP DIR(IX)_P1 = -1 DIR(IX)_P2 = -1 -> L1 SW(3): ! KEY word1,word2,... SW(9): ! ADDKEY word1, word2, ... IF KEY STATE = 0 START KEY STATE = 1 KEY POINT = KEY SAVE1 IF J = 3 FINISH WRITE KEYS(2, I, Z) IF KEY STATE = 1 -> SW1 SW(4): ! KEY KEY STATE = -1 KEY POINT = KEY SAVE -> SW1 SW(5): ! TOPIC Z = SHORTEN(T0, 0, 3) IF F(0) = 0 -> SW1 SW(6): ! <> S = SUBS(LEVEL) + 1 SUBS(LEVEL) = S SEC = SECS(LEVEL-1) . ITOS(S) DIR(I)_SEC = SEC SECS(LEVEL) = SEC . "." DIR(IX)_P2 = T0 IF DIR(IX)_P2 <= 0 Z = SHORTEN(T0, I, 2) PER(LEVEL) = LENGTH(Z) IF LENGTH(Z) > PER(LEVEL) WHILE Z -> Z . (",") . Z0 CYCLE ; REPEAT -> IGNORE IF LENGTH(Z) > 31 SEC = Z -> IGNORE UNLESS SEC = Z J = DIR(-1)_P1 + 1 K = 1 WHILE K < J CYCLE -> IGNORE IF SUBFILE(K) = SEC; ! already in K = K + 1 REPEAT SUBFILE(J) = SEC DIR(-1)_P1 = J; ! increment count IGNORE: DIR(I)_LINK = I + 1 I = I + 1 RETURN IF I > MAXDIR -> L1 SW(7): ! < fails if more than 100 subfiles S = SUBS(LEVEL) + 1; ! also get cap exceeded SUBS(LEVEL) = S SEC = SECS(LEVEL-1) . ITOS(S) DIR(I)_SEC = SEC SECS(LEVEL) = SEC . "." DIR(IX)_P2 = T0 IF DIR(IX)_P2 = 0; ! CLOSE PREF Z = SHORTEN(T0, I, 0) PER(LEVEL) = LENGTH(Z) IF LENGTH(Z) > PER(LEVEL) LEVEL = LEVEL + 1 SUBS(LEVEL) = 0 PER(LEVEL) = 0 F(LEVEL) = I DIR(I)_P1 = T I = I + 1 RETURN IF I > MAXDIR DIR(I) = 0 -> L1 SW(8): ! > DIR(IX)_P2 = T0 IF DIR(IX)_P2 = 0 -> L1 IF I = I0+1; ! just terminate preface part ! IF LEVEL > 0 START DIR(IX)_SUBS = SUBS(LEVEL) J = PER(LEVEL) + 5 + LENGTH(SECS(LEVEL-1)) CYCLE K = 1, 1, TOP PAD EXIT IF J > PAD(K) REPEAT K = DIR(IX)_SUBS IF K > DIR(IX)_SUBS DIR(IX)_PER = K DIR(IX)_LINK = I LEVEL = LEVEL - 1 FINISH -> L1 SW(10): ! HELP DIR(-1)_P2 = I - 1 -> L1 END ; ! SCAN FILE ! ! ! ROUTINE DO DIR(INTEGER BASE, STRING (31)STEM, NAME) ! Given a PD file NAME starting ! at BASE, constructs a VIEW ! directory for it in DIR(I) ! onwards INTEGER IM, MEMS, I0, M, T0, T, TXTEOF, L RECORD (FHDRF)NAME H, MH RECORD (MEMF)ARRAYFORMAT MEMAF(0:2047) RECORD (MEMF)ARRAYNAME MEM STRING (11)MNAME STRING (255)Z, NULL INTEGER P,Q,R,S,N,XW INTEGERARRAY X(0:2047) H == RECORD(BASE) MEM == ARRAY(BASE + H_ADR, MEMAF) DIR(I)_SEC = STEM STEM = STEM . "." UNLESS STEM = "" DIR(I)_NAME = NAME; ! name of file IM = 0 MEMS = 0 DIR(I)_SUBS = 0 DIR(I)_LINK = -1 DIR(I)_P1 = 1 DIR(I)_P2 = 0 DIR(I)_PER = 0 I0 = I I = I + 1 RETURN IF I > MAXDIR DIR(I) = 0 ! ! ! N = H_COUNT RETURN IF N < 1 ! CYCLE S = 0, 1, N-1; X(S) = S; REPEAT ; ! sort member names into alpha order ! S = 1 S = S << 1 WHILE S <= N S = S - 1 ! CYCLE S = S >> 1 EXIT IF S = 0 CYCLE P = 1, 1, N-S R = P WHILE R > 0 CYCLE Q = R + S EXIT IF MEM(X(R-1))_NAME <= MEM(X(Q-1))_NAME XW = X(Q-1) X(Q-1) = X(R-1) X(R-1) = XW R = R - S REPEAT REPEAT REPEAT ! Q = -1; ! Its convenient to have the 'preface' member, if any, ! first so that its keys, if any, come first in VIEWKEYS CYCLE P = 0, 1, N-1 Q = P AND EXIT IF MEM(X(P))_NAME = "PREFACE" REPEAT ! IF Q > 0 START ; ! there is a preface and its not the first member XW = X(Q) CYCLE P = Q-1, -1, 0; ! make it the first X(P+1) = X(P) REPEAT X(0) = XW FINISH ! CYCLE P = 0, 1, N - 1; ! process each member M = X(P) MNAME = MEM(M)_NAME MH == RECORD(BASE + MEM(M)_START) ! IF MH_TYPE = 6 START ; ! another PD file DIR(IM)_LINK = I IF IM > 0 IM = I MEMS = MEMS + 1 DODIR(ADDR(MH), STEM . ITOS(MEMS), MNAME) RETURN IF I > MAXDIR IF LENGTH(DIR(IM)_NAME) > DIR(I0)_PER C THEN DIR(I0)_PER = LENGTH(DIR(IM)_NAME) FINISH ELSE START IF MH_TYPE = 3 START IF MNAME = "PREFACE" START T = ADDR(MH)+MH_TXTST-CONBASE DIR(I0)_P1 = T WRITE KEYS(0, I0, NAME) TXTEOF = ADDR(MH)+MH_NFB-CONBASE DIR(I0)_P2 = TXTEOF; ! -1 ? LOOP: CONTINUE UNLESS T < TXTEOF T0 = T GETLINE(LINE, T, T, CONBASE, TXTEOF) ! L = LENGTH(LINE) L = L - 1 IF L > 0 AND CHARNO(LINE, L) = ' ' -> LOOP IF L < 4 ! IF LINE -> NULL . ("!TITLE ") . Z AND NULL = "" START Z = SHORTEN(T0, I0, 1) -> L FINISH IF LINE -> NULL . ("!TOPIC ") . Z AND NULL = "" START Z = SHORTEN(T0, 0, 3) IF I0 = 0 -> L FINISH IF LINE = "!KEY" START KEY STATE = -1 KEY POINT = KEY SAVE -> L FINISH IF LINE -> NULL . ("!KEY ") . Z AND NULL = "" START IF KEY STATE = 0 START KEY STATE = 1 KEY POINT = KEY SAVE1 FINISH WRITEKEYS(2, I0, Z) IF KEY STATE = 1 -> L FINISH ! IF LINE -> NULL . ("!ADDKEY ") . Z AND NULL = "" START KEY STATE = 1 IF KEY STATE = 0 WRITE KEYS(2, I0, Z) IF KEY STATE = 1 L: DIR(I0)_P1 = T IF DIR(I0)_P1 = T0; ! adjust start of preface if no text yet -> LOOP FINISH ! IF LINE = "!SKIP" START DIR(I0)_P1 = -1 DIR(I0)_P2 = -1 CONTINUE FINISH -> LOOP FINISH ELSE START DIR(IM)_LINK = I IF IM > 0 IM = I MEMS = MEMS + 1 SCAN FILE(STEM.ITOS(MEMS), MNAME, I, ADDR(MH)) RETURN IF I > MAXDIR IF LENGTH(DIR(IM)_NAME) > DIR(I0)_PER C THEN DIR(I0)_PER = LENGTH(DIR(IM)_NAME) FINISH FINISH FINISH REPEAT DIR(I0)_SUBS = MEMS P = DIR(I0)_PER + 5 + LENGTH(STEM) CYCLE Q = 1, 1, TOP PAD EXIT IF P > PAD(Q) REPEAT Q = MEMS IF Q > MEMS DIR(I0)_PER = Q DIR(I0)_LINK = I END ; ! DODIR ! ! STRINGFN PICKUP(INTEGER BASE) INTEGER ADR, LEN, J, K, CH STRING (255)WK, FILE, SEC, TITLE, TOPIC RECORD (REFF)ARRAYFORMAT REFAF(1:KKTOPREF) RECORD (REFF)ARRAYNAME REF REF == ARRAY(KKREFADDR, REFAF) ADR = BASE + 32 LEN = INTEGER(BASE) - 32 ! CYCLE J = KWDSCAN(LEN, ADR, KKTOPKEY, KKEY) EXIT IF J = 0 KKREFI = KKREFI + 1 UNLESS KKREFI > KKTOPREF START K = 0 CYCLE CH = BYTEINTEGER(J) EXIT IF CH = ':' J = J + 1 K = K + 1 CHARNO(WK, K) = CH REPEAT LENGTH(WK) = K WK -> FILE.("¬").SEC.("¬").TITLE.("¬").TOPIC REF(KKREFI)_NAME <- TITLE REF(KKREFI)_TOPIC <- TOPIC REF(KKREFI)_FILE <- FILE REF(KKREFI)_SEC <- SEC FINISH REPEAT RESULT = "" END ; ! PICKUP ! !----------------------------------------------------------------------- ! MSG = "" UNLESS FILE -> USER . (".") . FULLFILE C THEN USER = PROCUSER AND FULLFILE = FILE; ! FULL is something like USER.FRED ! while FULLFILE is USER.FRED_JIM_JOE ! DFILE = FULLFILE . "_" DFILE -> DFILE . ("_") . R ! FULL <- USER . "." . DFILE FULLFILE = USER . "." . FULLFILE ! IF LENGTH(USER) > 6 OR LENGTH(DFILE) > 11 START MSG = FULLFILE . " is an invalid file name" RESULT = 1 FINISH ! FTINDEX = 1 CYCLE FT == FTS(FTINDEX) RESULT = 0 IF FT_FILE = FULLFILE -> CONNECT IF FT_FILE = "" FTINDEX = FTINDEX + 1 EXIT IF FTINDEX > TOPFT REPEAT ! MSG = "Too many files for VIEW" RESULT = 1 CONNECT: FT_PROMPT = "View: " FT_FILE = FULLFILE VDIR = "T#VDIR" . ITOS(FTINDEX) VKEY = "T#VKEY" . ITOS(FTINDEX) ! CONNECT(FULL, 0,0,0,CONR,CONRES); ! connect outermost file FT_CONRES = CONRES UNLESS CONRES = 0 START MSG = FAILURE MESSAGE(CONRES) -> OUT FINISH BASE = CONR_ADR ! IF DFILE = "T#KEYWRK" START ; ! UGH MSG = PICKUP(BASE) -> OUT FINISH ! FT_CONBASE = BASE - X'40000' H == RECORD(BASE) FT_TIMESTAMP = H_TIMESTAMP CONBASE = BASE - X'40000' MNAME = DFILE CYCLE ; ! unwind down to required member TXT == RECORD(BASE) EXIT IF LENGTH(R) = 0 UNLESS TXT_TYPE = 6 START ; ! PD FILE MSG = MNAME . " not a PD file" -> OUT FINISH MEM == ARRAY(BASE + TXT_ADR, MEMAF) UNLESS R -> MNAME . ("_") . R START ! MSG = R LENGTH(MSG) = LENGTH(MSG) - 1 MSG = MSG ." is not a valid name" -> OUT FINISH BASE = FIND(MNAME) IF BASE = 0 START MSG = "Member ".MNAME." does not exist" -> OUT FINISH REPEAT ! CONBASE = BASE - X'40000' UNLESS TXT_TYPE = 6 OR TXT_TYPE = 3 START ; ! PD MSG = MNAME." is not a PD or a character file" -> OUT FINISH ! IF TXT_TYPE = 3 AND TXT_COUNT = 2 START ; ! appears to have directories DIRA = BASE + 96 KEYA = DIRA + INTEGER(DIRA) CONBASE = BASE + INTEGER(BASE + 4) - X'40000' - TXT_CHKSUM -> SETUPDONE FINISH ! IF TXT_TXTST >= TXT_NFB ORC (TXT_TYPE = 6 AND TXT_COUNT < 1) START MSG = "File ".MNAME." empty" -> OUT FINISH ! I = 0 MSG = "" IF TXT_TYPE = 6 START ; ! PDFILE KEYSTATE = 0; ! no VIEWKEY member encountered MEM == ARRAY(BASE+TXT_ADR, MEMAF) CYCLE M = 0, 1, TXT_COUNT - 1 ! IF MEM(M)_NAME = VIEWKEY START KEYSTATE = 1 KEYA = BASE + MEM(M)_START FINISH ! IF MEM(M)_NAME = VIEWDIR START DIRA = BASE + MEM(M)_START DIR == ARRAY(DIRA + 32, DIRAF) ! H == RECORD(DIRA) CONBASE = BASE - X'40000' FT_TIMESTAMP = H_TIMESTAMP -> SET UP DONE IF DIFF(TXT_TIMESTAMP, H_TIMESTAMP) < 5 ! CONRES = 1; ! to avoid the DISCONNECT MODPDFILE(2, FULLFILE, VIEWKEY, "", J) UNLESS J = 0 START MSG = "Cannot delete " . VIEWKEY . " in " . FULLFILE -> OUT FINISH MODPDFILE(2, FULLFILE, VIEWDIR, "", J) IF J = 0 START W("Out of date " . VIEWDIR ." deleted OK") -> CONNECT FINISH W(VIEWDIR . " in " . FULLFILE . " out of date") -> OUT FINISH REPEAT IF KEYSTATE = 1 START CONRES = 1 MODPDFILE(2, FULLFILE, VIEWKEY, "", J) UNLESS J = 0 START W("Cannot delete " . VIEWKEY . " in " . FULLFILE) -> OUT FINISH -> CONNECT FINISH UNLESS USER = PROCUSER START ; ! ******************* AND SEND A MESSAGE ********** MSG = "There is no " . VIEWDIR . " in " . FULLFILE -> OUT FINISH MSG = DIRFILE; ! create temporary files -> OUT UNLESS MSG = "" DODIR(BASE, "", FULL FILE) -> TOO BIG IF I > MAXDIR J = DIR(-1)_P1; ! number of sub_files INTEGER(DIRA) = 32 + 80 * (I+1) + 32*J; ! 80 IS SIZE OF DIR RECORD IF J > 0 START IMAX = DIR(0)_LINK K = ADDR(DIR(IMAX)) CYCLE I = 1, 1, J STRING(K) = SUBFILE(I) K = K + 32 REPEAT FINISH BYTEINTEGER(KEYPOINT) = NL INTEGER(KEYA) = KEY POINT - KEYA + 1 CONRES = 1 MODPDFILE(1, FULL FILE, VIEWKEY, VKEY, J) DESTROY(VKEY, K) CONNECT(VDIR, 3, 0, 0, CONR, J); ! CONNECT IN WRITE MODE ! TO GET TIMESTAMP AS RECENT AS POSS UNLESS J = 0 START MSG = FAILURE MESSAGE(J) -> OUT FINISH MOD PD FILE(1, FULL FILE, VIEWDIR, VDIR, J) DESTROY(VDIR, K) IF J = 0 START W("New " . VIEWDIR . " inserted") -> CONNECT FINISH MSG = FAILURE MESSAGE(J) -> OUT FINISH ! ! Do character file ! MSG = DIRFILE -> OUT UNLESS MSG = "" SCAN FILE("", FULLFILE, I, BASE) -> TOO BIG IF I > MAXDIR BYTEINTEGER(KEYPOINT) = NL INTEGER(KEYA) = KEY POINT - KEYA + 1 ! { go to SET UP DONE if can't insert directories? } J = DIR(-1)_P1 INTEGER(DIRA) = 32 + 80*(I+1) + 32*J IF J > 0 START IMAX = DIR(0)_LINK K = ADDR(DIR(IMAX)) CYCLE I = 1, 1, J STRING(K) = SUBFILE(I) K = K + 32 REPEAT FINISH ! DL = INTEGER(DIRA); ! size of VIEWDIR KL = INTEGER(KEYA) CL = TXT_NFB - TXT_TXTST HL = (32 + 64 + DL + KL + 31) & (-32) SIZE = HL + CL OUTFILE(OUTPUT FILE, SIZE, 0, 0, ADR, J) UNLESS J = 0 START MSG = FAILUREMESSAGE(J) -> OUT FINISH ! H == RECORD(ADR) H_NFB = SIZE H_TXTST = HL H_TYPE = 3 H_CHKSUM = TXT_TXTST H_ADR = 32 H_COUNT = 2 A = ADR + 32 MH == RECORD(A) MH = 0 MH_START = 96 MH_NAME = VIEWDIR A = A + 32 MH == RECORD(A) MH = 0 MH_START = 96 + DL MH_NAME = VIEWKEY ! A = A + 32 MOVE(DL, DIRA, A) ! A = A + DL MOVE(KL, KEYA, A) ! A = ADR + HL MOVE(CL, BASE+TXT_TXTST, A) ! IF FULL = FULL FILE C THEN NEWGEN(OUTPUT FILE, FULL, J) C ELSE START ZCOPY2(OUTPUT FILE . "," . FULL FILE . "/W", 0, J) J = 219 IF J = -7 OR J = -10 FINISH DESTROY(VKEY, K) DESTROY(VDIR, K) ! UNLESS J = 0 START MSG = FAILUREMESSAGE(J) -> OUT FINISH ! LINE = FULLFILE . "_" LINE -> LINE . ("_") . R; ! to reconstruct 'R' ! -> CONNECT SET UP DONE: FT_CONBASE = CONBASE FT_DIRA = DIRA FT_KEYA = KEYA RESULT = 0 OUT: FT_FILE = "" RESULT = 1 TOO BIG: FT_FILE = "" RESULT = 2 LIST END ; ! VCONNECT ! ! ! INTEGERFN CHECKWORD(STRING (255)LINE, STRING (255)LOOKFOR, STRINGNAME REST) ! Looks for lines starting with words given in LOOKFOR which ! should have the form: !WORD1&!WORD2& etc INTEGER J STRING (255)NULL, WORD J = 0 WHILE LOOKFOR -> WORD . ("&") . LOOKFOR CYCLE J = J + 1 RESULT = J IF LINE -> NULL . (WORD) . REST AND NULL = "" REPEAT RESULT = 0 END ; ! CHECKWORD ! ! ! CONSTINTEGER TOPLVI = 10 CONSTINTEGER TOPLVS = 4 CONSTINTEGER TOPLV = TOPLVI + TOPLVS ! OWNINTEGERARRAY LAYI(1 : TOPLVI) OWNSTRING (63)ARRAY LAYS(1 : TOPLVS) ! CONSTBYTEINTEGERARRAY LAYI DEF(1 : TOPLVI) = C 54, 1, 2, 3, 0, 0, 72, 0, 0, 0 CONSTSTRING (15)ARRAY LAYS DEF(1 : TOPLVS) = C "C", "C", "ADF", "ADF" ! OWNINTEGER LAYLINES OWNINTEGER UNDERLINE ! ! ! LAYI1 = PAGE(54) ! LAYI2 = PAGENO(1) ! LAYI3 = TOP(2) ! LAYI4 = BOTTOM(3) ! LAYI5 ! LAYI6 = LEVEL(0) ! LAYI7 = WIDTH(72) ! LAYI8 ! LAYI9 ! LAYI10 ! ! LAYS1 = TEVEN (NL) ! LAYS2 = TODD (NL) ! LAYS3 = BEVEN (HALF.MID.PAGENO) ! LAYS4 = BODD (HALF.MID.PAGENO) ! ! A = HALF D = MID ! B = LAST E = RHM ! C = NL F = PAGENO ! G = string ! !----------------------------------------------------------------------- ! INTEGERFN QUOTATION(STRING (63)FROM, INTEGERNAME Q0, Q1, QL, C INTEGER DIRA, CONBASE) ! Examines the section whose number is in FROM and returns ! the text pointers in Q0 and Q1 ! the number of lines in QL INTEGER I, J, N STRING (63)W RECORD (DIRF)ARRAYNAME DIR DIR == ARRAY(DIRA+32, DIRAF) I = 0 FROM = FROM . "." WHILE FROM -> W . (".") . FROM CYCLE J = STOI2(W, N) I = I + 1 I = DIR(I)_LINK AND N = N - 1 WHILE N > 1 REPEAT Q0 = DIR(I)_P1 + CONBASE Q1 = DIR(I)_P2 + CONBASE J = Q0 QL = 0 WHILE J < Q1 CYCLE QL = QL + 1 IF BYTEINTEGER(J) = NL J = J + 1 REPEAT RESULT = 0 END ! ! ! ! ! ! STRINGFN VSTRING(INTEGER N) CONSTINTEGER TOP = 7 SWITCH L(1:TOP) -> L(N) IF 1 <= N <= TOP ! IF 100 <= N <= TOP PARAMETER START RESULT = PARAMETER(N) UNLESS PARAMETER USED(N) = 0 FINISH ! RESULT = "{" . ITOS(N) . "}" ! L(1): RESULT = DATE L(2): RESULT = TIME L(3): RESULT = PROCUSER; ! user number L(4): RESULT = UINFS(2); ! delivery information L(5): RESULT = UINFS(7); ! surname L(6): RESULT = UINFS(10); ! OCP L(7): RESULT = VDUS(0); ! terminal type END ; ! VSTRING ! ! ! ROUTINE UNCURL(STRING (255)LINE, INTEGERNAME L, INTEGER TYPE) ! ! REMOVES CURLY BRACKETS ! a line count is maintained in L ! TYPE is set as follows: ! 0 on line, dont print but do count lines ! 1 on line, print and count ! 2 X<-----> ! 3 F<-----> INTEGER J, N, K, I, FOUND, PAD INTEGER DP15, ORD, CNTRL STRING (255)R, X, Y, Z, A, B, C CONSTSTRING (6)ARRAY LAYOUTVAR(1 : TOPLV) = C "PAGE", "PAGENO", "TOP", "BOTTOM", "LEFT", "LEVEL", "WIDTH", "X", "Y", "Z", "TEVEN", "TODD", "BEVEN", "BODD" ! CONSTSTRING (5)ARRAY FONT(0 : 17) = C "[2;2x", "[2;1x", "[2;4x", "[5;2x", "[5;1x", "[5;4x", "[6;2x", "[6;1x", "[6;4x", "[4;2x", "[4;1x", "[4;3x", "[3;2x", "[3;1x", "[3;4x", "[1;2x", "[1;1x", "[1;3x" ! ! ! ! ! STRINGFN CLEAN(STRINGNAME S) INTEGER C, J, K J = 0 K = 0 WHILE J < LENGTH(S) CYCLE J = J + 1 C = CHARNO(S, J) UNLESS C = ' ' START C = C - 32 IF 'a' <= C <= 'z' K = K + 1 CHARNO(S, K) = C FINISH REPEAT LENGTH(S) = K RESULT = S END ! ! ! DP15 = 0 IF TYPE = 3 ANDC EFFING FILE -> X . (".DP") AND X = "" C THEN DP15 = 1 ORD = 0 CNTRL = 0 R = "" ORD = 1 AND -> PRINT IF LINE = "" ! WHILE LINE # "" CYCLE IF LINE -> X . ("{") . Y . ("}") . LINE START R = R . X AND ORD = 1 UNLESS X = "" ! IF Y = "" START R = R . "{}" ORD = 1 CONTINUE FINISH ! IF CHARNO(Y, 1) = '{' START R = R . Y . "}" ORD = 1 CONTINUE FINISH ! IF STOI2(Y, N) = 0 START R = R . VSTRING(N) ORD = 1 CONTINUE FINISH ! IF Y = "_" START IF DP15 = 1 START UNDERLINE = 1 - UNDERLINE R = R . TOSTRING(27) R = R . TOSTRING(91) R = R . TOSTRING(52) IF UNDERLINE = 1 R = R . TOSTRING(109) CNTRL = 1 FINISH CONTINUE FINISH ! IF CHARNO(Y, 1) = '!' START ; ! special directive ********** CONTINUE UNLESS TYPE = 3; ! relevant only to F<...> Y -> ("!") . Y Y -> (" ") . Y WHILE Y # "" AND CHARNO(Y, 1) = ' ' J = CHARNO(Y, 1); ! first non-blank character K = J & (-33); ! convert to upper case Y -> (TOSTRING(J)) . Y ! IF K = 'N' START { !N } LAYNEWPAGE IF LAYLINES > 0 RETURN FINISH ! IF K = 'A' START ; ! assign { !A } CYCLE X = Y AND Y = "" UNLESS Y -> X . (";") . Y C = "" C = C . CLEAN(A) . "'" . B . "'" WHILEC X -> A . ("'") . B . ("'") . X C = C . CLEAN(X) ! IF C -> X . ("=") . Z START ; ! plausible FOUND = 0 CYCLE I = 1, 1, TOPLV FOUND = 1 AND EXIT IF X = LAYOUTVAR(I) REPEAT IF I > TOPLVI START ; ! codify 'page-turn' parameter ! A = "" CYCLE B = Z AND Z = "" UNLESS Z -> B . (".") . Z EXIT IF B = "" C = "" C = "A" IF B = "HALF" C = "B" IF B = "LAST" C = "C" IF B = "NL" C = "D" IF B = "MID" C = "E" IF B = "RHM" C = "F" IF B = "PAGENO" IF CHARNO(B, 1) = '''' = CHARNO(B, LENGTH(B)) START CHARNO(B, 1) = 'G' CHARNO(B, LENGTH(B)) = 0 C = B FINISH C = LAYS(1) IF B = "TEVEN" C = LAYS(2) IF B = "TODD" C = LAYS(3) IF B = "BEVEN" C = LAYS(4) IF B = "BODD" A = A . C UNLESS C = "" REPEAT ! LAYS(I - TOPLVI) = A UNLESS A = "" FINISH ELSE START J = STOI2(Z, N) IF J = 0 START N = 1 << 30 IF I=1 AND N=0 LAYI(I) = N FINISH FINISH FINISH EXIT IF Y = "" REPEAT RETURN FINISH ! IF K = 'F' START { !Fn } J = STOI2(Y, N) IF DP15 = 1 AND J=0 AND 0<=N<=17 START R = R . TOSTRING(27) . FONT(N) CNTRL = 1 FINISH CONTINUE FINISH ! ! %IF K = 'V' %START; ! set vertical spacing (default is 6) ! J = STOI2(Y, N) ! %IF DP15 = 1 %AND J = 0 %AND (X'7A880000'<<N) < 0 %START ! R = R.TOSTRING(27)."[".Y . "{" ! CNTRL = 1 ! %FINISH ! %CONTINUE ! %FINISH ! R = R . "{!" . TOSTRING(J) . Y . "}" CONTINUE FINISH ; ! *************** R = R . "{" . Y . "}" ORD = 1 FINISH ELSE START R = R . LINE ORD = 1 EXIT FINISH REPEAT RETURN IF ORD = 0 = CNTRL PRINT: IF TYPE > 0 START ; ! print required IF TYPE = 3 START PAD = LAYI(5) N = 0 J = 0 WHILE J < LENGTH(R) CYCLE J = J + 1 SPACES(PAD) IF N = 0 K = CHARNO(R, J) PRINTCH(K) N = 1 N = 0 IF K = 13; ! a CR REPEAT NEWLINE IF ORD = 1 FINISH ELSE W(R) FINISH L = L + 1 END ; ! OF UNCURL ! ! ! ROUTINE LAYGETLINE(STRINGNAME LINE, INTEGERNAME T0, T1, INTEGER BASE, EOF) INTEGER L, CH, T L = 0 LENGTH(LINE) = 255 T = T0 LOOP: CH = BYTEINTEGER(T + BASE) T = T + 1 UNLESS CH = NL START IF L < 255 START L = L + 1 CHARNO(LINE, L) = CH FINISH -> LOOP UNLESS T >= EOF FINISH ! LENGTH(LINE) = L T1 = T END ; ! LAYGETLINE ! ! ! ! ! !----------------------------------------------------------------------- ! ! ROUTINE LAYNEWPAGE ROUTINE PAGE TURN(INTEGER PLACE) ! PLACE = 0 TOP ! 1 BOTTOM INTEGER C, MAXC, L, MAXL, MID, RHM, J, PARITY, PAGENO, K STRING (63)S, PIECE STRING (127)TEXT SWITCH SW('A':'G') ! ! ! ROUTINE CLEAR LINE C = -1 MID = 0 RHM = 0 END ! ! ! ROUTINE PRINT TEXT INTEGER J UNLESS TEXT = "" START IF C < 0 START J = LAYI(5); ! LEFT SPACES(J) IF J > 0 C = 0 FINISH ! IF RHM > 0 START ; ! text to go at RHS J = MAXC - C - LENGTH(TEXT) IF J > 0 START SPACES(J) FINISH FINISH ! IF MID > 0 START ; ! text to go in centre of line J = ((MAXC - LENGTH(TEXT)) >> 1) - C IF J > 0 START SPACES(J) C = C + J FINISH FINISH ! PRINTSTRING(TEXT) C = C + LENGTH(TEXT) TEXT = "" FINISH END ; ! PRINT TEXT ! ! ! PAGENO = LAYI(2) PARITY = PAGENO & 1; ! obtained from pageno S = LAYS(1 + PLACE << 1 + PARITY) MAXC = LAYI(7) MAXL = LAYI(3 + PLACE) L = 0 CLEAR LINE TEXT = "" ! WHILE S # "" CYCLE K = CHARNO(S, 1) S -> (TOSTRING(K)) . S -> SW(K) SW('A'): ! HALF PRINT TEXT J = MAXL >> 1 NEWLINE AND L = L + 1 WHILE L < J CLEARLINE CONTINUE SW('B'): ! LAST PRINT TEXT NEWLINE AND L = L + 1 WHILE L < MAXL - 1 CLEARLINE CONTINUE SW('C'): ! NL PRINT TEXT NEWLINE L = L + 1 RETURN IF L >= MAXL CLEARLINE CONTINUE SW('D'): ! MID IF MID = 0 START PRINT TEXT MID = 1 FINISH CONTINUE SW('E'): ! RHM IF RHM = 0 START PRINT TEXT RHM = 1 MID = -1; ! inhibit FINISH CONTINUE SW('F'): ! PAGENO IF PAGENO > 0 START TEXT = TEXT . ITOS(PAGENO) FINISH CONTINUE SW('G'): ! text S -> PIECE . (TOSTRING(0)) . S TEXT = TEXT . PIECE CONTINUE REPEAT ! PRINT TEXT J = MAXL - L NEWLINES(J) IF J > 0 END ; ! PAGE TURN ! !----------------------------------------------------------------------- ! RETURN IF LAYI(1) = 1 << 30 IF LAYLINES > 0 START ; ! initialised to -1 NEWLINES(LAYI(1) - LAYLINES) IF LAYI(1) > LAYLINES; ! page PAGE TURN(1) LAYI(2) = LAYI(2) + 1 IF LAYI(2) > 0; ! pageno FINISH ! NEWPAGE ! PAGE TURN(0) LAYLINES = 0 END ; ! LAYNEWPAGE ! !----------------------------------------------------------------------- ! ROUTINE LAYLINE(STRING (255)S) LAYNEWPAGE IF LAYLINES >= LAYI(1); ! page ! SPACES(LAYI(5)) IF LAYI(5) > 0; ! left ! PRINTSTRING(S) NEWLINE LAYLINES = LAYLINES + 1 END ; ! LAYLINE ! !----------------------------------------------------------------------- ! ROUTINE F1SUPPORT(INTEGER DIRA, CONBASE, BASEI) INTEGER FIRST I STRING (255)LINE STRING (31)BSEC RECORD (DIRF)ARRAYNAME DIR CONSTINTEGER TOP PNO = 31 INTEGERARRAY PNO(0 : TOP PNO) ! ! ! ROUTINE LAYHEADING(INTEGER I, DOTS) INTEGER P, L, S, J STRING (80)W, A J = DIR(I)_P1 ! IF J > 0 START ; ! real section - ie not a subsid file IF LAYI(1) = 1 << 30 START ; ! no 'page turns' NEWLINES(2) IF LAYLINES >= 0 FINISH ELSE START IF LAYLINES < 0 ORC (DOTS < LAYI(6) AND LAYLINES > 0) ORC LAYLINES + 6 > LAYI(1) C THEN LAYNEWPAGE C ELSE START NEWLINES(2) LAYLINES = LAYLINES + 2 FINISH FINISH FINISH ! IF I > FIRST I AND LAYI(2) > 0 AND LAYI(1) # 1 << 30 START ; ! put PAGENO into earlier contents ! list if pagenos on P = PNO(DOTS); ! pointer to relevant entry UNLESS P = 0 START PNO(DOTS) = INTEGER(P) W = ITOS(LAYI(2)); ! pageno W = " " . W WHILE LENGTH(W) < 4 W = " *" UNLESS J > 0 MOVE(4, ADDR(W) + 1, P) FINISH FINISH ! RETURN UNLESS J > 0 ! W = "" W = "*" IF DIR(I)_P1 = 0 W <- W . DIR(I)_SEC . " " . GETNAME(I, DIRA, CONBASE) W -> (" ") . W WHILE CHARNO(W, 1) = ' ' L = LENGTH(W) S = 0 S = (LAYI(7) - L) >> 1 IF LAYI(7) > L AND DOTS < LAYI(6) SPACES(S) UNLESS S = 0 LAYLINE(W) A = "" A = A . "-" WHILE LENGTH(A) < L SPACES(S) UNLESS S = 0 LAYLINE(A) NEWLINE; LAYLINES = LAYLINES + 1 END ; ! LAYHEADING ! !----------------------------------------------------------------------- ! ROUTINE LAYCONTENTS(INTEGER I, DOTS) INTEGER COUNT, PER, SUBS, L, J, P, IW INTEGERNAME CUR STRING (255)SEC, Z RECORD (FDF)NAME FD BYTEINTEGERARRAY PAD(1 : 3) J = LAYI(7) {width} PAD(1) = (J) & (-4) PAD(2) = ((J - 4) // 2) & (-4) PAD(3) = ((J - 8) // 3) & (-4) ! SEC = DIR(I)_SEC SUBS = DIR(I)_SUBS; ! how many there are ! L = 0; ! max title size encountered IW = I + 1 J = 1 WHILE J <= SUBS CYCLE Z <- GETNAME(IW, DIRA, CONBASE) L = LENGTH(Z) IF LENGTH(Z) > L IW = DIR(IW)_LINK J = J + 1 REPEAT ! L = L + 8; ! format of line is sp [sec.] ddd L dddd L = L + LENGTH(SEC) + 1 UNLESS SEC = "" ! PER = 3 PER = 2 IF L > PAD(3) PER = 1 IF L > PAD(2) ! L = (SUBS + PER - 1) // PER + 4; ! total number of lines reqd IF LAYLINES + 4 > LAYI(1) ORC (LAYLINES + L > LAYI(1) AND L < LAYI(1)) C THEN LAYNEWPAGE C ELSE START IF LAYLINES > 0 START NEWLINES(2) LAYLINES = LAYLINES + 2 FINISH FINISH ! L = PAD(PER) - 4 LAYLINE("Contents") CYCLE J = 1, 1, PER EXIT IF J > SUBS IF LAYI(1) # 1 << 30 AND LAYI(2) > 0 START SPACES(L) PRINTSTRING("Page") SPACES(4) IF J < PER FINISH REPEAT NEWLINE; LAYLINES = LAYLINES + 1 ! P = ADDR(PNO(DOTS)); ! relevant list head FD == RECORD(FDMAP(61)) CUR == FD_CUR PRINTCH(13) WHILE CUR & 3 # 0; ! get alignment right I = I + 1 COUNT = 0; ! number of things on line J = 1 WHILE J <= SUBS CYCLE Z = " " Z = "*" IF DIR(I)_P1 = 0 Z = Z . SEC . "." UNLESS SEC = "" Z = Z . ITOS(J) Z = Z . " " IF J < 100 Z = Z . " " IF J < 10 Z <- Z . GETNAME(I, DIRA, CONBASE) LENGTH(Z) = L IF LENGTH(Z) > L Z = Z . " " WHILE LENGTH(Z) < L ! SPACES(4) IF COUNT > 0 PRINTSTRING(Z) ! IF LAYI(1) # 1 << 30 AND LAYI(2) > 0 START PRINTSTRING(" ") INTEGER(P) = CUR - 4 P = INTEGER(P) FINISH ! COUNT = COUNT + 1 IF COUNT = PER START COUNT = 0 LAYLINE("") PRINTCH(13) WHILE CUR & 3 # 0; ! because we may have page-turned FINISH ! J = J + 1 I = DIR(I)_LINK REPEAT ! LAYLINE("") UNLESS COUNT = 0 END ; ! LAYCONTENTS ! !----------------------------------------------------------------------- ! ROUTINE LAYITEM(INTEGER I); ! called recursively INTEGER NI, J, Q0, Q1, QL, T, TXTEOF, DOTS STRING (31)WQ0, WQ1, WQL STRING (80)W, A STRING (255)NULL, REST DOTS = 0 W = DIR(I)_SEC DOTS = DOTS + 1 WHILE W -> A . (".") . W ! LAYHEADING(I, DOTS) NI = DIR(I)_SUBS; ! number of items T = DIR(I)_P1 TXTEOF = DIR(I)_P2 DOTS = DOTS + 1 DOTS = 0 IF I = 0 PNO(DOTS) = 0; ! because !STOP prevents LAYCONTENTS being called ! RETURN UNLESS T > 0 ! WHILE T < TXTEOF CYCLE ; ! preface part LAYGETLINE(LINE, T, T, CONBASE, TXTEOF) -> STOP IF LINE -> NULL . ("!STOP") . REST AND NULL = "" -> L1 IF CHECKWORD(LINE, "!PAGE&!PROMPT&!MAIL&!TITLE&!TOPIC&!KEY&!ADDKEY&!HELP&", REST) > 0 ! IF LINE -> NULL . ("!QUOTE ") . REST AND NULL = "" START J = QUOTATION(REST, Q0, Q1, QL, DIRA, CONBASE) -> Q FINISH ! IF LINE -> NULL . ("!XQUOTE ") . WQ0 . (",") . WQ1 . (",") . WQL AND NULL = "" START J = STOI2(WQ0, Q0) J = STOI2(WQ1, Q1) J = STOI2(WQL, QL) Q: LAYNEWPAGE IF QL < LAYI(1) < LAYLINES + QL LAYLINES = LAYLINES + QL ! WHILE Q0 < Q1 CYCLE PRINTSYMBOL(BYTEINTEGER(Q0)) Q0 = Q0 + 1 REPEAT -> L1 FINISH ! LINE -> ("!") . LINE IF LINE # "" AND CHARNO(LINE, 1) = '!' UNCURL(LINE, LAYLINES, 3) LAYNEWPAGE UNLESS LAYLINES < LAYI(1); ! page L1: REPEAT ! RETURN IF NI < 1; ! no subsections LAYCONTENTS(I, DOTS) STOP: RETURN IF NI < 1 ! I = I + 1 CYCLE J = 1, 1, NI LAYITEM(I) I = DIR(I)_LINK REPEAT END ; ! LAYITEM ! !-------------------------LAYOUT------------------------------------------ ! ROUTINE FCONTENTS INTEGER I, IMAX STRING (80)T, JUNK LAYNEWPAGE IMAX = DIR(BASEI)_LINK T = "Contents of " T = T . "Sect " . BSEC . " of " UNLESS BSEC = "" T <- T . GETNAME(0, DIRA, CONBASE) LAYLINE(T) ! I = BASEI I = 1 IF I = 0 WHILE I < IMAX CYCLE T = DIR(I)_SEC RETURN UNLESS T -> (BSEC) . JUNK ! IF DIR(I)_P1 = 0 C THEN T = "*" . T C ELSE T = " " . T ! T = T . " " AND LENGTH(T) = 12 IF LENGTH(T)<12 T = T . " " T <- T . GETNAME(I, DIRA, CONBASE) LAYLINE(T) I = I + 1 REPEAT END ! INTEGER J ! ! ! ! ! ! ! ! ! ! ! ! ! DIR == ARRAY(DIRA + 32, DIRAF) BSEC = DIR(BASEI)_SEC ! ! ! CYCLE J = 1, 1, TOPLVI; ! set defaults LAYI(J) = LAYIDEF(J) REPEAT ! CYCLE J = 1, 1, TOPLVS LAYS(J) = LAYSDEF(J) REPEAT ! LAYLINES = -1 ! IF LAST SCREEN ID < 0 C THEN FCONTENTS C ELSE START W("Extract from ".GETNAME(0, DIRA, CONBASE)) FIRSTI = BASEI LAY ITEM(BASEI) FINISH ! LAYNEWPAGE ! ! ! ! ! ! ! END ; ! F1SUPPORT ! ! ! ROUTINE F2SUPPORT(INTEGER DIRA, CONBASE, BASEI) INTEGER T1, T2, J, Q0, Q1, QL, CH STRING (31)WQ0, WQ1, WQL STRING (255)LINE, NULL, REST RECORD (DIRF)ARRAYNAME DIR DIR == ARRAY(DIRA+32, DIRAF) T1 = DIR(BASEI)_P1 T2 = DIR(BASEI)_P2 RETURN UNLESS T1 > 0 ! QL = 0 ! WHILE T1 < T2 CYCLE J = 0 WHILE T1 < T2 CYCLE CH = BYTEINTEGER(CONBASE + T1) T1 = T1 + 1 EXIT IF CH = NL J = J + 1 AND CHARNO(LINE, J) = CH IF J < 255 REPEAT LENGTH(LINE) = J ! IF J > 3 AND CHARNO(LINE, 1) = '!' START IF LINE -> NULL . ("!QUOTE ") . REST AND NULL = "" START J = QUOTATION(REST, Q0, Q1, QL, DIRA, CONBASE) -> L0 FINISH ! IF LINE -> NULL . ("!XQUOTE ").WQ0.(",").WQ1.(",").WQL AND NULL = "" START J = STOI2(WQ0, Q0) J = STOI2(WQ1, Q1) L0: WHILE Q0 < Q1 CYCLE PRINTSYMBOL(BYTEINTEGER(Q0)) Q0 = Q0 + 1 REPEAT -> L1 FINISH ! -> L1 IF CHECKWORD(LINE, "!PAGE&!PROMPT&!MAIL&!TITLE&!TOPIC&!KEY&!ADDKEY&!HELP&", REST) > 0 RETURN IF LINE -> NULL . ("!STOP") . REST AND NULL = "" FINISH ! LINE -> ("!") . LINE IF LINE # "" AND CHARNO(LINE, 1) = '!' UNCURL(LINE, QL, 3) L1: REPEAT END ; ! F2SUPPORT ! ! ! ROUTINE CLIST(INTEGER CONBASE, DIRA, BASEI, LPPAGE, PRINT, INTEGERNAME I, CJ, LINES) INTEGER COUNT, MAX, CN STRING (255)Z, BSEC, LINE RECORD (DIRF)ARRAYNAME DIR DIR == ARRAY(DIRA+32, DIRAF) BSEC = DIR(BASEI)_SEC COUNT = 0; ! number of things on line so far MAX = DIR(BASEI)_PER MAX = 1 IF MAX > 6; ! number allowed per line CN = DIR(BASEI)_SUBS; ! number of subsections LINE = ""; ! empty to start with WHILE CJ <= CN AND LINES < LPPAGE CYCLE Z = " " Z = "*" IF DIR(I)_P1 = 0 Z = Z.BSEC."." UNLESS BSEC = "" Z = Z.ITOS(CJ) Z = Z." " IF CJ<100 Z = Z." " IF CJ<10 Z = Z." ".GETNAME(I, DIRA, CONBASE) ! IF MAX > 1 START Z = Z . " " LENGTH(Z) = PAD(MAX - 1) FINISH ! LINE = LINE . " " IF COUNT > 0 LINE = LINE . Z COUNT = COUNT + 1 ! IF COUNT = MAX START COUNT = 0 W(LINE) IF PRINT > 0 LINE = "" LINES = LINES + 1 FINISH ! CJ = CJ + 1 I = DIR(I)_LINK REPEAT UNLESS LINE = "" START W(LINE) IF PRINT > 0 LINES = LINES + 1 FINISH END ; ! CLIST ! ! ! ROUTINE F3SUPPORT(INTEGER DIRA, CONBASE, BASEI) ! produces a file of material as seen on the screen except ! 1. before each screen full is written a marker ! !sec/frame or ! !C sec/frame ! 2. no little messages or prompts at the end of a screen full INTEGER I, J, L, IMAX, FR, STATE, P, PMAX, Q, QMAX, CH, IX INTEGER P0, Q0, Q1, QL STRING (31)WQ0, WQ1, WQL SWITCH SW(0:2) STRING (31)BSEC, T1 STRING (255)T, NULL, REST RECORD (DIRF)ARRAYNAME DIR ! ! ! ! ! ! ! ! ! ! DIR == ARRAY(DIRA+32, DIRAF) ! ! ! ! ! IMAX = DIR(BASEI)_LINK BSEC = DIR(BASEI)_SEC FR = 0 STATE = 0 I = BASEI I = I + 1 IF LAST SCREEN ID < 0 ! WHILE I < IMAX CYCLE FR = FR + 1 ! T = "!".DIR(I)_SEC T = "!C ".BSEC IF LAST SCREEN ID < 0 W(T."/".ITOS(FR)); ! marker ! T = GETNAME(I, DIRA, CONBASE) T1 = DIR(I)_SEC IF LAST SCREEN ID < 0 START ; ! contents mode T = "Contents of " T = T . "Sect ".BSEC." of " UNLESS BSEC = "" T = T . GETNAME(0, DIRA, CONBASE) T1 = "" FINISH T1 = T1 . "/" . ITOS(FR) IF FR > 1 T = " " . T IF LENGTH(T)+LENGTH(T1) < WIDTH - 10 J = WIDTH - 1 - LENGTH(T1) LENGTH(T) = J IF LENGTH(T) > J PRINTSTRING(T) SPACES(J - LENGTH(T) + 1) W(T1) ! CYCLE J = 1, 1, WIDTH PRINTSTRING("-") REPEAT NEWLINE ! L = 0; ! lines on 'page' IF LAST SCREEN ID < 0 START ; ! contents mode WHILE L < 20 AND I < IMAX CYCLE T = " " T = "*" IF DIR(I)_P1 = 0; ! subfile T = T . DIR(I)_SEC PRINTSTRING(T) J = 8 - LENGTH(T) SPACES(J) UNLESS J < 0 SPACE W(GETNAME(I, DIRA, CONBASE)) I = I + 1 L = L + 1 REPEAT FINISH ELSE START ; ! text mode -> SW(STATE) SW(0): P = DIR(I)_P1; ! initialise things at the start of a section PMAX = DIR(I)_P2 PMAX = -1 IF P = -1; ! a '!SKIP' section Q = 1 QMAX = DIR(I)_SUBS IX = I + 1 STATE = 1 SW(1): WHILE P < PMAX AND L < 20 CYCLE ; ! text part J = 0 P0 = P WHILE P < PMAX CYCLE ; ! get next line into T CH = BYTEINTEGER(CONBASE + P) P = P + 1 EXIT IF CH = NL J = J + 1 AND CHARNO(T, J) = CH IF J < 255 REPEAT LENGTH(T) = J ! IF J > 4 AND CHARNO(T, 1) = '!' START ! IF T -> NULL . ("!QUOTE ") . REST AND NULL = "" START J = QUOTATION(REST, Q0, Q1, QL, DIRA, CONBASE) P = P0 AND -> STOP IF L > 0 AND L + QL > 20 -> L0 FINISH ! IF T -> NULL . ("!XQUOTE ") . WQ0 . (",") . WQ1 . (",") . WQL AND NULL = "" START J = STOI2(WQL, QL) P = P0 AND -> STOP IF L > 0 AND L + QL > 20 J = STOI2(WQ0, Q0) J = STOI2(WQ1, Q1) L0: WHILE Q0 < Q1 CYCLE PRINTSYMBOL(BYTEINTEGER(Q0)) Q0 = Q0 + 1 REPEAT L = L + QL -> L1 FINISH ! -> L1 IF CHECKWORD(T, "!PROMPT&!MAIL&!TITLE&!TOPIC&!KEY&!ADDKEY&!HELP&", REST) > 0 ! IF T -> NULL . ("!STOP") . REST AND NULL = "" START STATE = 2 Q = QMAX + 1 -> STOP FINISH ! IF T -> NULL . ("!PAGE") . REST AND NULL = "" START -> SW(1) IF L = 0 -> STOP FINISH ! FINISH ! T -> ("!") . T IF T # "" AND CHARNO(T, 1) = '!' UNCURL(T, L, 2) L1: REPEAT STATE = 2 UNLESS P < PMAX SW(2): CLIST(CONBASE, DIRA, I, 20, 1, IX, Q, L); ! contents part STOP: IF STATE = 2 AND Q > QMAX START STATE = 0 I = I + 1 FR = 0 FINISH FINISH ! L = 20 - L NEWLINES(L) IF L > 0 REPEAT ! ! ! ! ! ! ! END ; ! F3SUPPORT ! ! ! ROUTINE FSUPPORT(STRING (255)Z, INTEGER DIRA, CONBASE, BASEI) INTEGER STYLE, J STRING (255)DEST, W CONSTINTEGER TOPSTYLE = 3 SWITCH SW(1 : TOPSTYLE) RETURN IF RESTRICTED = 1 ! IF Z = "" START RETURN IF EFFING FILE = "" DEST = EFFING FILE DEST = DEST . "-MOD" UNLESS CHARNO(DEST, 1) = '.' FINISH ELSE START STYLE = 1 IF Z -> Z . (",") . W START STYLE = J IF STOI2(W, J) = 0 AND J > 0 AND J <= TOPSTYLE FINISH EFFING STYLE = STYLE ! DEST = Z EFFING FILE = Z UNLESS Z -> EFFING FILE . ("/W") ORC Z -> EFFING FILE . ("-MOD") FINISH ! j = uinfi(6) j = 1024 if j > 1024 { limit to 1 meg } DEFINE("61," . OUTPUT FILE . "," . ITOS(j)) SELECT OUTPUT(61) ! ! UNDERLINE = 0 IF EFFING FILE -> W . (".DP") AND W = "" START PRINTCH(27) PRINTSTRING("[6;2x") { select font 6 for default } FINISH ! -> SW(EFFING STYLE) SW(1): F1SUPPORT(DIRA, CONBASE, BASEI); -> CLOSE SW(2): F2SUPPORT(DIRA, CONBASE, BASEI); -> CLOSE SW(3): F3SUPPORT(DIRA, CONBASE, BASEI) CLOSE: SELECT OUTPUT(0) CLOSE STREAM(61) CLEAR("61") ZCOPY2(OUTPUT FILE . "," . DEST, 0, J) J = 219 IF J = -7 OR J = -10 UNLESS J = 0 START PRINTSTRING(FAILURE MESSAGE(J)) PRINTSTRING("Output saved in " . OUTPUT FILE . " ") FINISH END ; ! FSUPPORT ! ! ! OWNINTEGER SEARCHFILEI, TOPSEARCHFILE, SEARCHFILEA ! ! ! ! ! ! ! INTEGERFN ALPHA(STRING (255)Z, INTEGER I, DIRA, CONBASE) INTEGER N, B, J STRING (31)UCNAME OWNINTEGER ALPHAI = -1 RECORD (DIRF)ARRAYNAME DIR DIR == ARRAY(DIRA+32, DIRAF) N = DIR(I)_SUBS; ! number of sub-sections IF N < 1 START -> L UNLESS ALPHAI < 0; ! life saver -> L2 IF LIBRAR = 1 W("There are no subsections") RESULT = 0 FINISH UNLESS I+N+1 = DIR(I)_LINK START -> L UNLESS ALPHAI < 0; ! life saver -> L2 IF LIBRAR = 1 W("Section not suitably structured") RESULT = 0 FINISH ALPHAI = I L: I = ALPHAI N = DIR(I)_SUBS ! B = 1 B = B << 1 WHILE B <= N B = B >> 1 J = B ! WHILE B > 1 CYCLE B = B >> 1 UCNAME <- GETNAME(I+J, DIRA, CONBASE) UCTRANSLATE(ADDR(UCNAME)+1, LENGTH(UCNAME)) UNLESS UCNAME = "" IF UCNAME >= Z C THEN J = J - B C ELSE START J = J + B IF J + B <= N FINISH REPEAT ! UCNAME <- GETNAME(I+J, DIRA, CONBASE) UCTRANSLATE(ADDR(UCNAME)+1, LENGTH(UCNAME)) UNLESS UCNAME = "" J = J - 1 IF UCNAME >= Z AND J > 1 ! RESULT = I + J L2: W("You cannot use '?' in this section, check the instructions") RESULT = 0 END ; ! ALPHA ! ! ! ROUTINE PICK UP REFS(STRINGNAME FULL, INTEGER CONBASE, DIRA, KEYA) ! ! 1. Copy the names of any subfiles of this file to the ! SEARCHFILE array, unless already present or SEARCHFILE array full. ! ! 2. If no keys, just put filename and topic into REF array. ! ! 3. Else, locate as many keys as possible in current file. ! INTEGER CH, J, K, LEN, ADR, L1, L2 STRING (31)Z STRING (255)WK,A,B RECORD (DIRF)ARRAYNAME DIR RECORD (REFF)ARRAYFORMAT REFAF(1:KKTOPREF) RECORD (REFF)ARRAYNAME REF STRINGARRAYNAME SUBFILE, SEARCHFILE REF == ARRAY(KKREFADDR, REFAF) DIR == ARRAY(DIRA+32, DIRAF) ! IF SEARCHFILEI > 0 START SEARCHFILE == ARRAY(SEARCHFILEA, S31AF) SUBFILE == ARRAY(ADDR(DIR(DIR(0)_LINK)), S31AF) ! copy names of subfiles of this file to the ! SEARCHFILE array unless they are there already J = 1 WHILE J <= DIR(-1)_P1 CYCLE Z = SUBFILE(J) CYCLE K = 1, 1, SEARCHFILEI -> NEXT IF Z = SEARCHFILE(K) REPEAT IF SEARCHFILEI < TOPSEARCHFILE START SEARCHFILEI = SEARCHFILEI + 1 SEARCHFILE(SEARCHFILEI) = Z FINISH NEXT: J = J + 1 REPEAT FINISH ! if just checking subfiles then put filename ! and topic into REF array IF KKTOPKEY = 0 START KKREFI = KKREFI + 1 UNLESS KKREFI > KKTOPREF START REF(KKREFI)_TOPIC = DIR(-1)_SEC REF(KKREFI)_FILE = FULL FINISH RETURN FINISH ! LEN = INTEGER(KEYA) - 32 ADR = KEYA + 32 UNTIL J = 0 CYCLE J = KWDSCAN(LEN, ADR, KKTOPKEY, KKEY) UNLESS J = 0 START KKREFI = KKREFI + 1 K = 0 CYCLE CH = BYTEINTEGER(J) EXIT UNLESS '0' <= CH <= '9' K = 10 * K + CH - '0' J = J + 1 REPEAT WK = GETNAME(K, DIRA, CONBASE) UNLESS KKREFI > KKTOPREF START REF(KKREFI)_NAME <- WK REF(KKREFI)_TOPIC = DIR(-1)_SEC REF(KKREFI)_FILE = FULL REF(KKREFI)_SEC = DIR(K)_SEC FINISH ! UNLESS KKEYPT = 0 START WK = A.";".B WHILE WK -> A.(":").B WK = A.B WHILE WK -> A.("¬").B WK = FULL."¬".DIR(K)_SEC."¬".WK."¬".DIR(-1)_SEC L1 = LENGTH(WK) K = J CYCLE CH = BYTEINTEGER(J); ! expect : to be first ch EXIT IF CH = NL J = J + 1 REPEAT ! ! now need to add WK and these J-K+1 bytes to KKEYPT ! onwards, PROVIDED there is enough space L2 = J - K + 1 IF KKEYPT + L1 + L2 < KKTOP KEYPT START MOVE(L1, ADDR(WK)+1, KKEYPT) MOVE(L2, K, KKEYPT + L1) KKEYPT = KKEYPT + L1 + L2 FINISH FINISH FINISH REPEAT END ; ! PICK UP REFS ! ! ! ROUTINE SPLUS STRING (31)ARRAY FILE(1:100) INTEGER J STRING (63)Z RECORD (FTF)NAME FT FT == FTS(FTI(LEVEL)) PRINTCHS(VDUS1) KKREF ADDR = ADDR(FILE(1)) KKTOP REF = 1 FILE(1) = FT_FILE J = 0 UNTIL J = KKTOPREF CYCLE J = J + 1 Z = VIEWFN(FILE(J), "S+,S!*!") REPEAT END ; ! SPLUS ! ! ! ROUTINE SPLUSA INTEGER X, I, J, IMAX STRING (127)Z, F, U STRINGARRAYNAME FILE RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR INTEGER DIRA, CONBASE FT == FTS(FTI(LEVEL)) DIRA = FT_DIRA CONBASE = FT_CONBASE DIR == ARRAY(DIRA+32, DIRAF) IMAX = DIR(0)_LINK FILE == ARRAY(KKREF ADDR, S31AF) W("Detailed structure of ".FT_FILE." (".DIR(-1)_SEC.")") W(" last changed on ". C UNPACKDATE(FT_TIME STAMP) . " at " . C UNPACKTIME(FT_TIME STAMP)) X = 0 I = 0 WHILE I < IMAX CYCLE I = I + 1 IF DIR(I)_P1 = 0 START ; ! subfile marker X = 1 Z = GETNAME(I, DIRA, CONBASE) W(DIR(I)_SEC . " " . Z) F = Z UNLESS Z -> F . (",") . Z U = PROCUSER UNLESS F -> U . (".") . F F = U . "." . F CYCLE J = 1, 1, KKTOPREF -> IN IF F = FILE(J) REPEAT KKTOPREF = KKTOPREF + 1 FILE(KKTOPREF) = F IN: FINISH REPEAT W("--- No external references ---") IF X = 0 END ; ! SPLUSA ! !----------------------------------------------------------------------- ! ROUTINE HELP(INTEGER FTINDEX) INTEGER H, P1, P2, LINES STRING (255)LINE, REST RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR PRINTCHS(VDUS1); ! CLEAR SCREEN ! FT == FTS(FTINDEX) DIR == ARRAY(FT_DIRA+32, DIRAF) H = DIR(-1)_P2 IF H > 0 START { private HELP section nominated } LINES = 0 P1 = DIR(H)_P1 P2 = DIR(H)_P2 CYCLE RETURN UNLESS P1 < P2 GETLINE(LINE, P1, P1, FT_CONBASE, P2) IF CHECKWORD(LINE, "!TITLE&!TOPIC&!KEY&!ADDKEY&!HELP&", REST) = 0 C THEN UNCURL(LINE, LINES, 1) REPEAT FINISH ! ! IF LIBRAR = 1 START W("I didn't recognise your last command. Here is a") W("short description of what you can do.") W(" ") W("= repeats the current page") W("- gives the previous page in the file, unless") W(" you are already looking at the first page") W("T goes back to the first page (Top) of the file") W("'return' by itself gives the next page, unless you") W(" are already looking at the last page") W("3.5 gives section 3.5 etc") W("name? gives the 'best' page in which to find your") W(" entry, provided you are in a suitable section") W(" DONT FORGET THE '?' !!!") W("R returns you to a higher level, eg from SERIALS") W(" to the initial page") W("QUIT leaves the system ready for the next user") W(" ") W("remember to press 'return' when you have typed your command") W(" ") W(" ") RETURN FINISH ! ! ! W("= repeat current frame, eg after reading this.") W("< re-displays the previous frame that you viewed") W("- previous frame in this file") W("/n continuation frame n in this section / alone goes to end") W("!com obey com, any single EMAS command") W("m.n section m.n .n subsection n") W("name section of that name name? alphabetic search") W("Bn set a bookmark, n in range 1 - 9 ") W("C lists the contents of this section ") W("F< > output to file or device ") W("Gn go to frame where you set Bn (in the same file)") W("K< > key search") W("Q exit from VIEW") W("R return from subfile and re-display previous frame") W("S give structure ie subfiles of current file ") W("T top of current file") W("V file VIEW file V alone for VIEW spec") W("W where am I? - files traversed -------------------------") W(" ") W("*** Int: K kills output and goes to View:") W("*** VIEW thinks your terminal is a " . VDUS(0)) W("*** use command TERMINALTYPE, outside VIEW, to change it") RETURN END ; ! HELP ! ! ! ROUTINE CONTENTS(INTEGER F, INC, FTINDEX, I) INTEGER L, IMAX, CONBASE, DIRA STRING (72)T, BSEC, T1 RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR OWNINTEGER FR ! FR is used in this routine only to keep track of which ! contents frame is on display. IF INC = 0 C THEN FR = F C ELSE FR = FR + INC FR = 0 IF FR < 0 ! FT == FTS(FTINDEX) DIRA = FT_DIRA CONBASE = FT_CONBASE DIR == ARRAY(DIRA+32, DIRAF) IMAX = DIR(I)_LINK FR = (IMAX-2-I)//LPPAGE UNLESS I+1+FR*LPPAGE < IMAX ! SCREEN ID = (1<<31) ! (I<<13) ! FR; ! id of screen to be displayed RETURN IF SCREEN ID = LAST SCREEN ID BSEC = DIR(I)_SEC ! I = I + 1 + FR * LPPAGE ! LINT = 0; ! no INT K so far PRINTCHS(VDUS1); ! CLEAR SCREEN ! IF LINT = 0 START SPACES(10) UNLESS VDUI3 = 0 T = "Contents of " T = T . "Sect ".BSEC." of " UNLESS BSEC = "" T <- T . GETNAME(0, DIRA, CONBASE) PRINTSTRING(T) T1 = "" T1 = " /" . ITOS(FR+1) IF FR > 0 SPACES(WIDTH - 10 - LENGTH(T) - LENGTH(T1)) UNLESS VDUI3 = 0; ! hardcopy PRINTSTRING(T1) DRAWLINE FINISH L = 0 WHILE L < LPPAGE AND I < IMAX CYCLE T = " " T = "*" IF DIR(I)_P1 = 0 T = T . DIR(I)_SEC T = T . " " AND LENGTH(T) = 8 IF LENGTH(T) < 8 T <- T . " " . GETNAME(I, DIRA, CONBASE) W(T) IF LINT = 0 I = I + 1 L = L + 1 REPEAT L = LPPAGE - L RETURN UNLESS LINT = 0 BLANKLINES(L) IF L > 0 ! IF I < IMAX C THEN W(START STANDOUT."...more".END STANDOUT) C ELSE W(START STANDOUT."End of contents".END STANDOUT) END ; ! CONTENTS ! ! ! STRINGFN LOCATE(STRING (255)STEM, INTEGER FTINDEX) ! ! Searches the keys and the section names in the current file looking ! for some kind of match. ! INTEGER DIRA, KEYA, CONBASE, LEN, ADR, J, K, N, CH, IMAX, I, P, EXACT, EXACTI, L, H, X ! CONSTINTEGER TOP = 64 CONSTINTEGER TOP ON SCREEN = 15 ! ! INTEGERARRAY R(1 : TOP) STRING (255)NAME, NULL STRING (255)ARRAY KEYS(1 : 1) RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR ! ! ! KEYS(1) = STEM KEYS(1) = "," . STEM . "," UNLESS LENGTH(STEM) > 2 FT == FTS(FTINDEX) DIRA = FT_DIRA KEYA = FT_KEYA CONBASE = FT_CONBASE DIR == ARRAY(DIRA+32, DIRAF) ! LEN = INTEGER(KEYA) - 32 ADR = KEYA + 32 K = 0 UNTIL J = 0 CYCLE J = KWDSCAN(LEN, ADR, 1, KEYS) UNLESS J = 0 START K = K + 1 EXIT IF K > TOP N = 0 CYCLE CH = BYTEINTEGER(J) EXIT UNLESS '0' <= CH <= '9' N = 10 * N + CH - '0' J = J + 1 REPEAT R(K) = N FINISH REPEAT ! IF K <= TOP START { not swamped with keys, so look at sec names } IMAX = DIR(0)_LINK EXACT = 0 P = 1 I = 1 WHILE I < IMAX CYCLE NAME = GETNAME(I, DIRA, CONBASE) L = LENGTH(NAME) I = I + 1 AND CONTINUE IF L = 0 UCTRANSLATE(ADDR(NAME)+1, L) H = 0 IF NAME = STEM START EXACT = EXACT + 1 EXACTI = I H = 1 FINISH ELSE START H = 1 IF LENGTH(STEM) > 2 AND NAME -> (STEM) FINISH ! IF H = 1 START { insert into array of hits } P = P + 1 WHILE P <= K AND R(P) < I IF P > K START { add to end } K = K + 1 EXIT IF K > TOP R(K) = I FINISH ELSE START IF R(P) > I START { need to insert } K = K + 1 EXIT IF K > TOP CYCLE X = K, -1, P+1 R(X) =R(X-1) REPEAT R(P) = I FINISH FINISH FINISH I = I + 1 REPEAT FINISH ! IF 1 < K <= TOP AND EXACT # 1 START { remove any refs which are subsids} I = 1 J = 1 WHILE I < K CYCLE I = I + 1 UNLESS DIR(R(I))_SEC -> NULL . (DIR(R(J))_SEC . ".") AND NULL = "" START J = J + 1 R(J) = R(I) IF I > J FINISH REPEAT K = J FINISH ! IF K = 0 START W("No match found") RESULT = "" FINISH ! I = 0 I = R(1) IF K = 1 I = EXACTI IF EXACT = 1 RESULT = DIR(I)_SEC IF I > 0 ! P = 1 CYCLE NAME = DIR(R(P))_SEC IF LENGTH(NAME) > 9 START LENGTH(NAME) = 9 NAME = NAME . "... " FINISH ELSE START NAME = NAME . " " LENGTH(NAME) = 13 FINISH W(NAME . GETNAME(R(P), DIRA, CONBASE)) P = P + 1 REPEAT UNTIL P > K OR P > TOP ON SCREEN ! W("etc, etc") IF K > TOP ON SCREEN RESULT = "" END ; ! LOCATE ! !----------------------------------------------------------------------- ! STRINGFN LOCATE2(STRING (31)STEM, INTEGER CONBASE, DIRA) INTEGER L, H, I, HITS, EXACT, EXACTI, IMAX STRING (72)NAME, J1 CONSTINTEGER TOPHIT = 16 INTEGERARRAY HIT(1:TOPHIT) RECORD (DIRF)ARRAYNAME DIR DIR == ARRAY(DIRA+32, DIRAF) IMAX = DIR(0)_LINK HITS = 0 EXACT = 0 I = 1 WHILE I < IMAX CYCLE NAME <- GETNAME(I, DIRA, CONBASE) L = LENGTH(NAME) UCTRANSLATE(ADDR(NAME)+1, L) IF L > 0 H = 0 IF NAME = STEM START ; ! exact EXACT = EXACT + 1 EXACTI = I IF EXACT = 1; ! first exact hit H = 1 FINISH ELSE START H = 1 IF LENGTH(STEM) > 2 AND NAME -> (STEM) FINISH IF H = 1 START HITS = HITS + 1 HIT(HITS) = I IF HITS <= TOPHIT FINISH I = I + 1 REPEAT ! I = 0 I = EXACTI IF EXACT = 1 I = HIT(1) IF HITS = 1 RESULT = DIR(I)_SEC IF I > 0 ! IF HITS > 0 START { make a file ??? } H = HITS H = TOPHIT IF H > TOPHIT CYCLE I = 1, 1, H J1 = DIR(HIT(I))_SEC . " " LENGTH(J1) = 8 IF LENGTH(J1) > 8 W(J1." ".GETNAME(HIT(I), DIRA, CONBASE)) REPEAT W("etc etc") IF HITS > TOPHIT RESULT = "" FINISH ! W("No match found for ".STEM) ! RESULT = "" END ; ! LOCATE ! ! ! ROUTINE WD(STRINGNAME NEXTBIT, INTEGER DIRA, CONBASE) INTEGER I, J, L, IMAX RECORD (DIRF)ARRAYNAME DIR STRINGARRAYNAME SUBFILE ! ! ! ROUTINE W(STRING (255)S) PRINTSTRING(S) NEWLINE IF L < 20 C THEN L = L + 1 C ELSE START L = 0 RSTRG(NEXTBIT) FINISH END ; ! W ! ! ! DIR == ARRAY(DIRA+32, DIRAF) IMAX = DIR(0)_LINK SUBFILE == ARRAY(ADDR(DIR(IMAX)), S31AF) L = 0 NEXTBIT = "" W("Topic: ".DIR(-1)_SEC) PRINTSTRING("Help sec: "); WRITE(DIR(-1)_P2, 1) PRINTSTRING(DIR(DIR(-1)_P2)_SEC) IF DIR(-1)_P2 > 0 W(" ") I = DIR(-1)_P1 IF I = 0 C THEN W("No subfiles") C ELSE START W("Subfiles:") CYCLE J = 1, 1, I W(SUBFILE(J)) REPEAT FINISH CYCLE I = 0, 1, IMAX - 1 WRITEN(I) PRINTSTRING("/".DIR(I)_SEC) PRINTSTRING("/") WRITE(DIR(I)_PER, 1) PRINTSTRING("/".GETNAME(I, DIRA, CONBASE)."/") WRITE(DIR(I)_P1,1) PRINTSTRING("/") WRITE(DIR(I)_P2,1) PRINTSTRING("/") WRITE(DIR(I)_SUBS, 1) PRINTSTRING("/") WRITE(DIR(I)_LINK, 1) W(" ") RETURN UNLESS NEXTBIT = "" REPEAT END ; ! WD ! ! STRINGFN FIND SUPPORT(STRINGNAME Z0, FULLFILE, INTEGER DIRA, CONBASE) INTEGER N, J, Q0, Q1, QL STRING (63)K STRING (255)KEYS, W1, W2 CONSTINTEGER TOPLKREF = 256 RECORD (REFF)ARRAY REF(1:TOPLKREF) KKREFI = 0; ! No of refs found KKTOPREF = TOPLKREF KKREFADDR = ADDR(REF(1)) Z0 = W1 . W2 WHILE Z0 -> W1 . (" ") . W2 ! KKTOPKEY = 0 KEYS = Z0 . "&" WHILE KEYS -> K . ("&") . KEYS CYCLE IF K # "" AND CHARNO(K, 1) = '*' C THEN K -> ("*") . K C ELSE K = "," . K ! IF K # "" AND CHARNO(K, LENGTH(K)) = '*' C THEN LENGTH(K) = LENGTH(K) - 1 C ELSE K = K . "," ! KKTOPKEY = KKTOPKEY + 1 KKEY(KKTOPKEY) = K EXIT IF KKTOPKEY = 10 REPEAT SEARCHFILEI = 1 ! K = VIEWFN(FULLFILE, "K!*!") ! IF KKREFI = 0 START W("No references found") RESULT = "" FINISH ! IF KKREFI > TOPLKREF START W(ITOS(KKREFI) . " references found, please be more specific") RESULT = "" FINISH ! DEFINE("61," . OUTPUT FILE . "," . ITOS(UINFI(6))) SELECT OUTPUT(61) W1 = GETNAME(0, DIRA, CONBASE) K = "" K = "s" IF KKREFI > 1 W("!TITLE " . ITOS(KKREFI) . " reference" . K . " to " . Z0 . " extracted from " . W1) CYCLE N = 1, 1, KKREFI NEWLINE IF N > 1 J = QUOTATION(REF(N)_SEC, Q0, Q1, QL, DIRA, CONBASE) K = "!XQUOTE " . ITOS(Q0) K = K . "," . ITOS(Q1) W(K . "," . ITOS(QL)) ! W("!QUOTE " . REF(N)_SEC) REPEAT SELECT OUTPUT(0) CLOSE STREAM(61) CLEAR("61") DELETE FILE(OUTPUT FILE) RESULT = VIEWFN(OUTPUT FILE, "") END ; ! FIND SUPPORT ! ! ! STRINGFN KSUPPORT(STRINGNAME KEYS, FILE) ! ! ! STRING (63)K, Z STRING (255)KEYSW STRING (31)ARRAY SEARCHFILE(1:100) INTEGER F, I, J, N CONSTINTEGER TOPLSUPREF = 200 RECORD (REFF)ARRAY REF(1:TOPLSUPREF) KKEYPT = 0 KEYSW = KEYS KSUPSUBFILES = 0; ! this file only IF CHARNO(KEYSW, LENGTH(KEYSW)) = '+' START LENGTH(KEYSW) = LENGTH(KEYSW) - 1 KEYS = KEYSW KSUPSUBFILES = 1; ! look at subfiles FINISH KKREFI = 0; ! number of refs found KKTOPREF = TOPLSUPREF KKREFADDR = ADDR(REF(1)) ! SEARCHFILEI = 1; ! number of searchfiles TOPSEARCHFILE = 100 TOPSEARCHFILE = 1 IF KSUPSUBFILES = 0; ! don't look in subfiles SEARCHFILEA = ADDR(SEARCHFILE(1)) SEARCHFILE(1) = FILE ! KKTOPKEY = 0 KEYSW = KEYSW . "&" WHILE KEYSW -> K . ("&") . KEYSW CYCLE IF K # "" AND CHARNO(K, 1) = '*' C THEN K -> ("*") . K C ELSE K = "," . K ! IF K # "" AND CHARNO(K, LENGTH(K)) = '*' C THEN LENGTH(K) = LENGTH(K) - 1 C ELSE K = K . "," ! KKTOPKEY = KKTOPKEY + 1 KKEY(KKTOPKEY) = K EXIT IF KKTOPKEY = 10 REPEAT ! F = 0 UNTIL F = SEARCHFILEI CYCLE F = F + 1 K = VIEWFN(SEARCHFILE(F), "K!*!") REPEAT ! IF KKREFI > TOPLSUPREF START ; ! far too many W("far too many references") RESULT = "" FINISH ! IF KKREFI = 0 START ; ! none W("No references found") RESULT = "" FINISH ! ! J = 1 N = 0 CYCLE I = 1, 1, KKREFI IF KEYS = REF(I)_NAME START ; ! look for exact hits N = N + 1; ! count J = I IF N = 1; ! remember the first FINISH REPEAT ! IF KKREFI = 1 OR N = 1 START ; ! only one or one exact hit RESULT = REF(J)_SEC IF REF(J)_FILE = FILE RESULT = VIEWFN(REF(J)_FILE, REF(J)_SEC) FINISH ! DELETE FILE(OUTPUT FILE) DEFINE("61," . OUTPUT FILE . ",".ITOS(UINFI(6))) SELECT OUTPUT(61) W("!TITLE " . KEYS) W(ITOS(KKREFI) . " references found") CYCLE N = 1, 1, KKREFI Z = ITOS(N) . " " LENGTH(Z) = 5 W(Z.REF(N)_NAME." - ".REF(N)_TOPIC) REPEAT W("!STOP") CYCLE N = 1, 1, KKREFI W("!<>".REF(N)_FILE.",".REF(N)_SEC) REPEAT SELECT OUTPUT(0) CLOSE STREAM(61) CLEAR("61") RESULT = VIEWFN(OUTPUT FILE, "") END ; ! KSUPPORT ! ! ! STRINGFN UNTRANSLATE(INTEGER ID, FTINDEX) INTEGER I, FR STRING (255)S RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR FT == FTS(FTINDEX) DIR == ARRAY(FT_DIRA + 32, DIRAF) ! I = ID >> 13 S = "T" S = DIR(I)_SEC IF I > 0 FR = ID & X'1FFF' S = S . "/" . ITOS(FR) IF FR > 1 RESULT = S END ! ! ROUTINE PRINTC(RECORD (FRAMEF)ARRAYNAME FRAME, C INTEGER PRINT, FR, BASEI, FTINDEX) ! Goes through the motions of displaying frame FR of section BASEI. ! Displays only if PRINT = 1 SWITCH STSW(0:1) INTEGER T0, TXTEOF, CN, I, T, CJ, STATE INTEGER DIRA, CONBASE RECORD (FTF)NAME FT RECORD (DIRF)ARRAYNAME DIR INTEGER LINES, J, Q0, Q1, QL STRING (31)BSEC, WQ0, WQ1, WQL STRING (255)Z, LINE, L0, NULL, REST STRING (6)OWNER ! ! ! ROUTINE PRINTH(INTEGER I, STRING (255)SEC, INTEGER FR) INTEGER SP STRING (255)X X = GETNAME(I, DIRA, CONBASE) SEC = SEC . "/" . ITOS(FR+1) IF FR > 0 IF STRIPJ < TOP STRIP START STRIPJ = STRIPJ + 1 STRIP(STRIPJ) = SCREEN ID FINISH ! IF VDUI3 = 0 START ; ! hardcopy PRINTSTRING(SEC) SPACES(3) PRINTSTRING(X) FINISH ELSE START PRINTCHS(VDUS1); ! CLEAR SCREEN X = " " . X IF LENGTH(X)+LENGTH(SEC) < WIDTH - 10 SP = WIDTH - LENGTH(SEC) - 1 LENGTH(X) = SP IF LENGTH(X) > SP PRINTSTRING(X) SPACES(SP + 1 - LENGTH(X)) PRINTSTRING(SEC) FINISH ! IF PARTIAL DISPLAY = 0 C THEN DRAWLINE C ELSE NEWLINE END ; ! PRINTH ! ! ! MON("PRINTC PRINT=".ITOS(PRINT), ",FR=".ITOS(FR)) FT == FTS(FTINDEX) DIRA = FT_DIRA CONBASE = FT_CONBASE DIR == ARRAY(DIRA+32, DIRAF) TXTEOF = DIR(BASEI)_P2 CN = DIR(BASEI)_SUBS LINT = 0; ! no interrupts received so far LINES = 0 BSEC = DIR(BASEI)_SEC SCREEN ID = (BASEI << 13) ! FR + 1; ! screen requested RETURN IF SCREEN ID = LAST SCREEN ID; ! already on display ! IF FR = 0 AND SOME PARAMETER USED = 1 START SOME PARAMETER USED = 0 CYCLE J = 100, 1, TOP PARAMETER PARAMETER USED(J) = 0 REPEAT FINISH ! IF PRINT = 1 START PRINTH(BASEI, BSEC, FR) PARTIAL DISPLAY = 0 AND PRINT = -1 UNLESS PARTIAL DISPLAY = 0 FINISH ELSE SCREEN ID = 0 ! ! I = FRAME(FR)_I T = FRAME(FR)_T CJ = FRAME(FR)_CJ STATE = FRAME(FR)_STATE -> STSW(STATE) STSW(0): WHILE T < TXTEOF AND LINES < LPPAGE CYCLE T0 = T GETLINE(LINE, T0, T, CONBASE, TXTEOF) IF LENGTH(LINE) > 3 AND CHARNO(LINE, 1) = '!' START ! -> L1 IF CHECKWORD(LINE, "!TITLE&!TOPIC&!KEY&!ADDKEY&!HELP&", REST) > 0 ! IF LINE -> NULL . ("!QUOTE ") . REST AND NULL = "" START J = QUOTATION(REST, Q0, Q1, QL, DIRA, CONBASE) T = T0 AND -> STOP IF LINES > 0 AND LINES + QL > LPPAGE -> L0 FINISH ! IF LINE -> NULL . ("!XQUOTE ").WQ0.(",").WQ1.(",").WQL AND NULL = "" START J = STOI2(WQL, QL) T = T0 AND -> STOP IF LINES > 0 AND LINES + QL > LPPAGE J = STOI2(WQ0, Q0) J = STOI2(WQ1, Q1) L0: IF PRINT > 0 = LINT START WHILE Q0 < Q1 CYCLE PRINTSYMBOL(BYTEINTEGER(Q0)) Q0 = Q0 + 1 REPEAT FINISH LINES = LINES + QL -> L1 FINISH ! IF LINE -> NULL . ("!READ ") . REST AND NULL = "" START READ VALUE(REST) IF PRINT > 0 = LINT -> L1 FINISH ! IF LINE -> NULL . ("!MAIL ").REST AND NULL = "" START IF PRINT > 0 = LINT START QL = LENGTH(REST) J = 0 J = 1 IF QL > 0 AND CHARNO(REST, QL) = '?' ! FT_FILE -> OWNER . (".") . Z -> L1 IF OWNER = PROCUSER AND J = 1 ! LINES = LINES + MAIL SUPPORT(REST, DIR(-1)_SEC) FINISH -> L1 FINISH ! IF LINE -> NULL . ("!PROMPT ") . REST AND NULL = "" START FT_PROMPT <- REST . " " -> L1 FINISH ! IF LINE -> NULL . ("!STOP").REST AND NULL = "" START STATE = 1 CJ = CN + 1 -> STOP FINISH ! IF LINE -> NULL . ("!PAGE") . REST AND NULL = "" START -> L1 IF LINES = 0; ! ignore 'page' at start of page -> STOP FINISH ! IF LINE -> NULL . ("!#").REST AND NULL = "" START REST -> (" ").REST WHILE CHARNO(REST, 1) = ' '; ! remove leading spaces LINES = LPPAGE IF PRINT > 0 = LINT START LINE = "" WHILE REST -> WQ0 . ("{") . WQ1 . ("}") . REST CYCLE LINE = LINE . WQ0 J = STOI2(WQ1, Q1) IF J = 0 C THEN LINE = LINE . VSTRING(Q1) C ELSE LINE = LINE . "{" . WQ1 . "}" REPEAT LINE = LINE . REST UCTRANSLATE(ADDR(LINE)+1, LENGTH(LINE)) UNLESS LINE = "" Z = "" UNLESS LINE -> LINE . (" ") . Z CALL(LINE, Z) FINISH -> L1 FINISH FINISH ! IF PRINT > 0 = LINT START LINE -> ("!").LINE IF LINE # "" AND CHARNO(LINE, 1) = '!' FINISH UNCURL(LINE, LINES, PRINT) L1: REPEAT ! STATE = 1 UNLESS T < TXTEOF STSW(1): PRINT = 0 IF LINT > 0 CLIST(CONBASE, DIRA, BASEI, LPPAGE, PRINT, I, CJ, LINES) STOP: STATE = 2 IF STATE = 1 AND CJ > CN ! FRAME(FR+1)_I = I; ! FRAME has only 128 elements FRAME(FR+1)_T = T FRAME(FR+1)_CJ = CJ FRAME(FR+1)_STATE = STATE ! RETURN IF PRINT = 0 OR LINT > 0 ! LINES = -1 IF PRINT = -1 J = LPPAGE - LINES BLANKLINES(J) IF J > 0 ! IF PRINT = -1 START W("If you want this frame, type = and press 'return'") RETURN FINISH ! IF STATE < 2 C THEN W(START STANDOUT."...more".END STANDOUT) C ELSE START IF BASEI < DIR(0)_LINK - 1 C THEN W(START STANDOUT."End of section".END STANDOUT) C ELSE W(START STANDOUT."End of file".END STANDOUT) FINISH RETURN END ; ! PRINTC ! ! ! ROUTINE STRAP(INTEGER CLASS, SUBCLASS) ! On receipt of an INT:A, C, K or Q INTEGER A, J INTEGERARRAY ENV(0:20) SUBCLASS = SUBCLASS - 'a' + 'A' IF 'a'<=SUBCLASS<='z' UNLESS SUBCLASS = 'K' START SETMODE(SAVEMODE) UNLESS SAVEMODE = "" SIGNAL(3, CLASS, SUBCLASS, J) FINISH A = ADDR(ENV(0)) J = READID(A) LINT = 1; ! set switch CONSOLE(7, J, J); ! discard output PRINTSTRING(UINFS(4)); ! repeat current prompt TERMINATE J = DRESUME(0, 0, A) END ; ! STRAP ! ! ! ROUTINE KEYS(INTEGER LEN, ADR, N) INTEGER I, J, L, P STRING (63)KEY BYTEINTEGERARRAYNAME K BYTEINTEGERARRAYFORMAT KAF(0 : 1000000) ! This procedure searches VIEWKEYS for the keys for section N ! It is not very efficient. It would be better to ! 1 do some kind of binary chop ! 2 use machine code K == ARRAY(ADR, KAF) KEY = ITOS(N) . ":" L = LENGTH(KEY) LEN = LEN - L ! CYCLE J = 0, 1, LEN IF K(J) = NL START CYCLE P = L, -1, 1 -> NO UNLESS K(J+P) = CHARNO(KEY, P) REPEAT ! J = J + L + 2 I = 0 CYCLE IF K(J) = ',' AND K(J+1) = NL START NEWLINE IF I > 0 RETURN FINISH PRINTSYMBOL(K(J)) IF K(J) = ',' AND I > 50 C THEN I = -1 AND NEWLINE I = I + 1 J = J + 1 REPEAT FINISH NO: REPEAT END ; ! KEYS ! ! ! ROUTINE CPLUS(INTEGER FTINDEX) INTEGER KLEN, J, N, I STRING (80)LINE RECORD (FTF)NAME FT BYTEINTEGERARRAYNAME K BYTEINTEGERARRAYFORMAT KAF(0 : 1000000) RECORD (DIRF)ARRAYNAME DIR ! Scans through VIEWKEYS and for each line gives the ! section number and name and associated keys FT == FTS(FTINDEX) K == ARRAY(FT_KEYA + 32, KAF) KLEN = INTEGER(FT_KEYA) - 34 DIR == ARRAY(FT_DIRA+32, DIRAF) J = 0 LOOP: RETURN IF J >= KLEN IF K(J) # NL START J = J + 1 -> LOOP FINISH ! N = 0 WHILE '0' <= K(J+1) <= '9' CYCLE J = J + 1 N = 10 * N + K(J) - '0' REPEAT ! LINE = DIR(N)_SEC LINE = LINE . " " WHILE LENGTH(LINE) < 7 LINE <- LINE . " " . GETNAME(N, FT_DIRA, FT_CONBASE) W(LINE) ! J = J + 3 I = 0 SPACES(3) CYCLE IF K(J) = ',' AND K(J+1) = NL START NEWLINE IF I > 0 -> LOOP FINISH PRINTSYMBOL(K(J)) IF K(J) = ',' AND I > 50 C THEN NEWLINE AND SPACES(3) AND I = -1 I = I + 1 J = J + 1 REPEAT END ; ! CPLUS ! ! ! ROUTINE PACKHELP SUPPORT(STRING (255)S) ! RECORDFORMAT FINDF(STRING (31)FILE, INTEGER DIRNO, TYPE, STATUS) ! SYSTEMINTEGERFNSPEC FIND(STRING (31)ENTRY, INTEGERNAME NREC, INTEGER ADR, TYPE) DYNAMICROUTINESPEC PACKHELP(STRING (255)S) INTEGER J, NREC RECORD (FINDF)ARRAY FOUND(1 : 4) ! ! ! DELETE FILE(OUTPUT FILE) DEFINE("61," . OUTPUT FILE . "," . ITOS(UINFI(6))) SELECT OUTPUT(61) ! PRINTSTRING("!TITLE HELP Information on ") IF S = "" C THEN PRINTSTRING("Packages") C ELSE PRINTSTRING(S) NEWLINE ! NREC = 4 J = FIND("PACKHELP", NREC, ADDR(FOUND(1)), 2) IF J = 0 START IF NREC = 0 START CALL("OPTION", "SEARCHDIR=PLULIB.PACKDIR") FINISH FINISH PACKHELP(S) SELECT OUTPUT(0) CLOSE STREAM(61) CLEAR("61") ! IF NREC = 0 START CALL("OPTION", "REMOVEDIR=PLULIB.PACKDIR") FINISH ! DESTROY("T#PLUOPT", J) DISCONNECT("PLULIB.HELP", J) DISCONNECT("PLULIB.PARAMS", J) DISCONNECT("PLULIB.PLUROUTINEY", J) END ! ! ! STRINGFN ANALYSE LINE(STRINGNAME LINE, INTEGER FTINDEX) ! ! ! INTEGER CONBASE, DIRA, KEYA INTEGER BASEI, FR, FRX, I, J, K, L, N, T INTEGER STRIP0; ! Initial pointer in 'strip' at this level STRING (6)FILE OWNER STRING (31)TAG STRING (63)JUNK1, JUNK2, FULLFILE STRING (255)NEXT BIT, L0, Z, R, NULL ! STRINGARRAYNAME SUBFILE RECORD (FTF)NAME FT RECORD (FRAMEF)ARRAY FRAME(0 : 127) ! RECORD (DIRF)ARRAYNAME DIR ! ! DIR(-1)_SEC : topic ! _PER ! _NAME ! _P1 : number of subfiles ! _P2 : number of 'help' section if nominated (>0) ! _SUBS ! _LINK ! ! CONSTINTEGER TOPMARK = 9 INTEGERARRAY SPECIFIC MARKS(1 : TOPMARK) ! ! SWITCH SW(0:16) CONSTINTEGER TOPSTR = 10 CONSTSTRING (4)ARRAY STR(1:TOPSTR) = C "????", "S-", "K!*!", "QUIT", "STOP", "END", "HELP", "KEYS", "C+", "B?" SWITCH STRSW(1:TOPSTR) ! ! FT == FTS(FTINDEX) CONBASE = FT_CONBASE DIRA = FT_DIRA KEYA = FT_KEYA FULLFILE = FT_FILE FULLFILE -> FILE OWNER . (".") . JUNK1 ! STRIP0 = STRIPJ ! CYCLE J = 1, 1, TOPMARK SPECIFIC MARKS(J) = -1 REPEAT ! FRX = 0 BASEI = 0 DIR == ARRAY(DIRA+32, DIRAF) SUBFILE == ARRAY(ADDR(DIR(DIR(0)_LINK)), S31AF) T = DIR(0)_P1 I = 1 FR = -1 FRAME(0)_I = 1 FRAME(0)_T = T FRAME(0)_CJ = 1 FRAME(0)_STATE = 0 ANALYSE: MON("Analyse, length", ITOS(LENGTH(LINE))) MON("and LINE", LINE) IF LENGTH(LINE) > 1 AND CHARNO(LINE, 1) = '!' START -> READLINE IF RESTRICTED = 1; ! Viewer etc LINE -> ("!") . LINE IF STOI2(LINE, J) = 0 START ; ! purely numeric VIEWMON = J -> READLINE FINISH ! Z = "" IF UINFI(16) = 1 START ; ! brackets ON IF LINE -> LINE . ("(") . Z START J = LENGTH(Z) LENGTH(Z) = J - 1 IF J > 0 AND CHARNO(Z, J) = ')' FINISH FINISH ELSE START Z = "" UNLESS LINE -> LINE . (" ") . Z FINISH ! LAST SCREEN ID = 0 CASTOUT(LINE); ! command -> READLINE IF LINE = "" CASTOUT(Z) UNLESS Z = ""; ! parameters ! IF UINFI(26) = 0 START ; ! old loader LOAD(LINE, 0, J) W("?") AND -> READLINE UNLESS J = 0 FINISH CALL(LINE, Z) REROUTECONTINGENCY(0, 65, X'2080A0002080A', STRAP, J) REROUTECONTINGENCY(3, 65, X'2080A0002080A', STRAP, J) ! does Q K C A -> READLINE FINISH ! UCTRANSLATE(ADDR(LINE)+1, LENGTH(LINE)) UNLESS LINE = "" ! IF LINE -> L0 . ("F<") . Z . (">") . R START IF L0 -> (",") START LINE -> LINE . (",") . NEXT BIT FINISH ELSE START IF L0 = "" AND (R="" OR CHARNO(R,1) = ',') START FSUPPORT(Z, DIRA, CONBASE, BASEI) -> READ LINE IF R = "" R -> (",") . LINE -> ANALYSE FINISH W("???") -> READ LINE FINISH FINISH ELSE START NEXT BIT = "" UNLESS LINE -> LINE . (",") . NEXT BIT FINISH ! LAST SCREEN ID = SCREEN ID SCREEN ID = 0 ! The logic here is as follows. ! In CONTENTS, the SID reqd is computed. If its ! the same as LAST SID then don't do anything ! ! DECODE: MON("Decode line", LINE) MON("and NEXT BIT", NEXT BIT) ! ! ! IF LINE = "" START ; ! null line - go to next continuation page IF LAST SCREEN ID < 0 START ; ! in contents mode CONTENTS(0, 1, FTINDEX, BASEI) -> NEXT PART FINISH ! FRX = FR + 1 -> FINDFRAME IF FRAME(FRX)_STATE < 2; ! not yet at end of current section J = BASEI + 1 -> NEXT PART IF J >= DIR(0)_LINK LINE = DIR(J)_SEC FINISH ! LINE -> (" ").LINE WHILE LINE # "" AND CHARNO(LINE, 1) = ' ' -> NEXTPART IF LINE = ""; ! ignore lines which are only spaces ! J = LENGTH(LINE) J = J - 1 WHILE CHARNO(LINE, J) = 32; ! strip trailing spaces LENGTH(LINE) = J ! LINE = DIR(BASEI)_SEC.LINE IF CHARNO(LINE, 1) = '.'; ! If LINE starts with '.', prefix LINE with BSEC ! FRX = 0 TAG = "" IF LINE -> LINE . ("/") . Z START ; ! This section sets FRX if user has included a '/' TAG = "/" . Z FRX = 32767 { a very big number } UNLESS Z = "" START UNLESS STOI2(Z, FRX) = 0 START W("Format is /number NOT " . LINE . "/" . Z) -> READLINE FINISH FINISH FRX = FRX - 1 FRX = 0 IF FRX < 0 IF LINE = "" START -> FINDFRAME IF LAST SCREEN ID >= 0 CONTENTS(FRX, 0, FTINDEX, BASEI) -> NEXTPART FINISH FINISH ! ! ! -> NOT SINGLE IF LENGTH(LINE) > 1; ! ************* single character commands *************** Z = "-BEQRSVW?=UCT-F-<" Z = "---QR----=--T---<" IF LIBRAR = 1 -> SW(LENGTH(Z)) IF Z -> Z . (LINE) . JUNK1 -> L1 ! ! SW(0): ! - go to previous page IF LAST SCREEN ID < 0 START ; ! in contents mode CONTENTS(0, -1, FTINDEX, BASEI) -> NEXT PART FINISH ! FRX = FR - 1 -> FINDFRAME UNLESS FRX < 0; ! previous page in current section -> NEXT PART IF BASEI = 0; ! already at the top LINE = DIR(BASEI-1)_SEC LINE = "T" IF LINE = "" LINE = LINE . "/" -> DECODE ! SW(1): ! B set a 'bookmark' W("The 'B' facility, as such, has been withdrawn and") W("replaced by 'Bn' and '<'") -> READLINE ! SW(2): ! E SW(3): ! Q -> OUT1 ! SW(4): ! R 'return' from file STRIPJ = STRIP0 + 1 -> SW(16); ! ie do an '<' ! SW(5): ! S give 'structure' L = LENGTH(LINE); ! ie 1 for S, 2 for S- UNLESS NEXT BIT = "S!*!" START IF DIR(-1)_P1 = 0 START W("there are no subsidiary files") -> NEXT PART FINISH ! J = 1 { zero SSW byte in each used FT record } CYCLE FT == FTS(J) EXIT IF FT_FILE = "" { all done } FT_SSW = 0 J = J + 1 REPEAT ! PRINTCHS(VDUS1) IF L = 1 C THEN W("file - topic") AND PRINTSTRING(FULLFILE." - ") C ELSE W("The 'topic' tree") FINISH PRINTSTRING(DIR(-1)_SEC) { the topic } IF FTS(FTINDEX)_SSW = 1 START IF L = 1 C THEN W(" circular structure!") C ELSE NEWLINE Z = "" -> RETURN FINISH ! NEWLINE FTS(FTINDEX)_SSW = 1 J = 1 WHILE J <= DIR(-1)_P1 CYCLE SPACES((LEVEL-KKTOPKEY) * 3) Z = SUBFILE(J) PRINTSTRING(Z." - ") IF L = 1 Z = VIEWFN(Z, LINE.",S!*!") J = J + 1 REPEAT IF NEXT BIT = "S!*!" C THEN Z = "" AND -> RETURN C ELSE -> NEXT PART SW(6): ! V equivalent to V default-file LINE = "V " . DEFAULT FILE -> DECODE SW(7): ! W where am I? PRINTCHS(VDUS1) CYCLE J = 1, 1, LEVEL FT == FTS(FTI(J)) W(FT_FILE." (".UNPACKDATE(FT_TIME STAMP). C " at ".UNPACKTIME(FT_TIME STAMP).")") REPEAT -> NEXT PART SW(8): ! ? HELP(FTINDEX) PROMPT("View (= to get last frame again): ") RSTRG(LINE) -> ANALYSE SW(9): ! = LAST SCREEN ID = 0 IF NEXT BIT = "" START { really want to display } J = 1 Z = "=" FINISH ELSE START J = 0 Z = "=," . NEXT BIT FINISH ! IF STRIPJ > STRIP0 START ; ! we have displayed something in the file LINE = UNTRANSLATE(STRIP(STRIPJ), FTINDEX) STRIPJ = STRIPJ - J -> DECODE FINISH RESULT = Z SW(10): ! U W("The 'U' command has been withdrawn") W("Can you use < instead?") -> READLINE SW(11): ! C CONTENTS(0, 0, FTINDEX, BASEI) ->NEXTPART SW(12): ! T I = 0 -> L2 SW(13): SW(14): ! F FSUPPORT("", DIRA, CONBASE, BASEI) -> NEXT PART SW(15): SW(16): ! < IF NEXT BIT = "" START { want to return to previous frame} { and give a partial display } PARTIAL DISPLAY = 1 J = 2 Z = "<" FINISH ELSE START { dont want to display } J = 1 Z = "<," . NEXT BIT FINISH ! IF STRIPJ >= STRIP0 + 2 START ; ! there is a previous frame in this file LINE = UNTRANSLATE(STRIP(STRIPJ - 1), FTINDEX) STRIPJ = STRIPJ - J -> DECODE FINISH RESULT = Z ! !----------------------------------------------------------------------- NOT SINGLE: ! ! CYCLE J = 1, 1, TOPSTR -> STRSW(J) IF LINE = STR(J) REPEAT -> NOT STR STRSW(1): ! ???? WD(NEXTBIT, DIRA, CONBASE) IF LIBRAR = 0 -> NEXT PART STRSW(2): ! S- -> NEXT PART IF LIBRAR = 1 -> SW(5) STRSW(3): ! K!*! PICKUPREFS(FULLFILE, CONBASE, DIRA, KEYA) Z = "" -> RETURN STRSW(4): ! QUIT STRSW(5): ! STOP STRSW(6): ! END -> OUT1 STRSW(7): ! HELP -> SW(8) { as for ? } STRSW(8): ! KEYS KEYS(INTEGER(KEYA)-32, KEYA+32, BASEI) -> NEXT PART STRSW(9): ! C+ CPLUS(FTINDEX) -> NEXT PART STRSW(10): ! B? L = 0 CYCLE J = 1, 1, TOPMARK IF SPECIFIC MARKS(J) # -1 START L = 1 PRINTSYMBOL('B') PRINTSTRING(ITOS(J)) IF J < 10 C THEN PRINTSTRING(": ") C ELSE PRINTSTRING(": ") W(UNTRANSLATE(SPECIFIC MARKS(J), FTINDEX)) FINISH REPEAT W("No bookmarks set") IF L = 0 -> NEXT PART ! !----------------------------------------------------------------------- ! NOT STR: ! IF LINE -> NULL . ("B") . Z AND NULL = "" AND STOI2(Z, J) = 0 START ; ! Bn IF STRIPJ > STRIP0 START IF 1 <= J <= TOPMARK C THEN SPECIFIC MARKS(J) = STRIP(STRIPJ) C ELSE W("n must be in range 1-" . ITOS(TOPMARK) . " for Bn") FINISH ELSE W("Need a frame on display for the bookmark") -> NEXT PART FINISH ! IF LINE -> NULL . ("G") . Z AND NULL = "" AND STOI2(Z, J) = 0 START ; ! Gn IF 1 <= J <= TOPMARK AND SPECIFIC MARKS(J) # -1 C THEN LINE = UNTRANSLATE(SPECIFIC MARKS(J), FTINDEX) AND -> DECODE W("G" . Z . " not set") -> NEXTPART FINISH ! IF LINE = "S+" AND LIBRAR = 0 START IF NEXTBIT = "" C THEN SPLUS C ELSE SPLUSA AND -> OUT1 -> READLINE FINISH ! IF LINE -> Z . ("?") . JUNK1 AND JUNK1 = "" START ; ! alphabetic search -> SW(8) IF Z = ""; ! turn nulls into call on Help J = ALPHA(Z, BASEI, DIRA, CONBASE) -> READLINE IF J = 0; ! error result I = J -> L2 FINISH ! ! ! -> LIBSKIP IF LIBRAR = 1 IF LINE -> NULL . ("V ") . Z AND NULL = "" START ; ! recursive call LINE = VIEWFN(Z, NEXT BIT) -> READ LINE IF LINE = "" -> ANALYSE FINISH ! IF LINE -> NULL . ("K<") . Z . (">") AND NULL = "" START ; ! key search LINE = KSUPPORT(Z, FULLFILE) -> READ LINE IF LINE = "" -> ANALYSE FINISH ! LIBSKIP: IF LINE -> NULL . ("FIND ") . Z AND NULL = "" START LINE = FIND SUPPORT(Z, FULLFILE, DIRA, CONBASE) -> READ LINE IF LINE = ""; ! error exit -> ANALYSE FINISH ! ! %IF LINE -> NULL . ("U").Z %AND NULL = "" %START; ! UP A LEVEL OR MORE ! J = 1 ! %UNLESS Z = "" %START ! -> KEYWORD %UNLESS STOI2(Z, J) = 0 ! %FINISH ! -> KEYWORD %UNLESS J > 0 !! ! Z = DIR(BASEI)_SEC . "." ! P = 0 ! P = P + 1 %WHILE Z -> PART(P) . (".") . Z ! P = P - J ! LINE = "T" ! %WHILE P > 0 %CYCLE ! P = P - 1 ! %IF LINE = "T" %C ! %THEN LINE = "" %C ! %ELSE LINE = "." . LINE ! LINE = PART(P) . LINE ! %REPEAT ! LINE = LINE . TAG ! -> DECODE ! %FINISH !----------------------------------------------------------------------- ! ! get here with line = A.B.C... ! go to KEYWORD if A, B, C, ... not all numeric L1: K = 0 L0 = LINE . "." WHILE L0 -> Z . (".") . L0 CYCLE -> KEYWORD UNLESS STOI2(Z,N)=0 -> NS UNLESS 1 <= N <= DIR(K)_SUBS K = K + 1 K = DIR(K)_LINK AND N = N - 1 WHILE N > 1 IF DIR(K)_P1 <= 0 START LENGTH(L0) = LENGTH(L0) - 1 IF LENGTH(L0) > 0 I = K -> SUBFILE FINISH REPEAT I = K ! ! ! ! ! L2: ! at this point want frame FRX of section I -> NEXT PART IF LAST SCREEN ID = (I << 13) ! FRX+1; ! already on display FR = -1 BASEI = I T = DIR(I)_P1 IF T <= 0 START L0 = "" -> SUBFILE FINISH FRAME(0)_I = BASEI + 1 FRAME(0)_T = T FRAME(0)_CJ = 1 FRAME(0)_STATE = 0 FINDFRAME: MON("FINDFRAME, FRX=".ITOS(FRX), ",FR=".ITOS(FR)) ! find frame FRX of current (text) section IF FRX <= FR START FR = FRX FRX = -1 -> BACK FINISH ! FRXLOOP: -> NEXTPART IF FRX < 0 ! IF FRAME(FR+1)_STATE < 2 START FR = FR + 1 FRX = -1 IF FRX = FR BACK: J = 0; ! print not required J = 1 IF FRX < 0 AND NEXTBIT = ""; ! is PRINTC(FRAME, J, FR, BASEI, FTINDEX) -> FRXLOOP FINISH FRX = -1 -> BACK KEYWORD: ! LINE = LOCATE(LINE, CONBASE, DIRA) LINE = LOCATE(LINE, FTINDEX) -> READ LINE IF LINE = ""; ! nothing or multiple -> L1 ! NS: I = 0 AND -> L2 IF LIBRAR = 1; ! ie go to top W("No such section as " . LINE) -> READLINE ! !----------------------------------------------------------------------- ! SUBFILE: ! come here with I, L0 and TAG I = I + 1 IF DIR(I)_P1 < 0 Z = GETNAME(I, DIRA, CONBASE) ! IF Z -> Z . (",") . JUNK2 START NEXT BIT = JUNK2 FINISH ELSE START L0 = L0 . TAG IF L0 # "" START IF NEXT BIT = "" C THEN NEXT BIT = L0 C ELSE NEXT BIT = L0 . "," . NEXT BIT FINISH FINISH ! IF Z = "#PACKHELP" START PACKHELP SUPPORT(NEXT BIT) Z = OUTPUT FILE NEXT BIT = "" FINISH ! LINE = VIEWFN(Z, NEXT BIT) -> READ LINE IF LINE = "" -> ANALYSE NEXT PART: UNLESS NEXT BIT = "" START LINE = NEXT BIT -> ANALYSE FINISH READLINE: PROMPT(FT_PROMPT) RSTRG(LINE) -> ANALYSE OUT1: RESULT = "Q" RETURN: RESULT = Z END ; ! ANALYSE LINE ! ! ! STRING (63)FN VIEWFN(STRING (255)FILE, FIRST LINE) INTEGER J, FTINDEX, SPECIALCALL STRING (255)LINE SWITCH SPOUT(0:3) ! ! VIEWFN is called ! either to display a frame ! or to check keys or something ! ! Result is ! either "" which is essentially an error ! or a VIEW command line, <, = or Q possibly followed by something ! ! Result is relevant only when displaying things. ZVIEW2 is the only ! higher level caller of VIEWFN to use the result. ! J = LENGTH(FIRST LINE) IF J > 1 AND CHARNO(FIRST LINE, J) = '?' AND CHARNO(FIRST LINE, J-1) = ',' C THEN VIEW MON = 1 AND LENGTH(FIRST LINE) = J - 2 MON("VIEWFN, FIRST LINE", FIRST LINE) ! SPECIAL CALL = 0 SPECIAL CALL = 1 IF FIRSTLINE = "K!*!" SPECIAL CALL = 2 IF FIRSTLINE = "S,S!*!" SPECIAL CALL = 3 IF FIRSTLINE = "S-,S!*!" ! LEVEL = LEVEL + 1 IF LEVEL > TOP LEVEL START LINE = "Too many levels of recursion" -> OUT FINISH ! OUTPUT FILE = "T#VIEWOUT" . ITOS(LEVEL) ! DESPACE(FILE) UCTRANSLATE(ADDR(FILE)+1, LENGTH(FILE)) UCTRANSLATE(ADDR(FIRST LINE)+1, LENGTH(FIRST LINE)) J = VCONNECT(FILE, FTINDEX, LINE) -> OUT IF J = 1 -> TOO BIG IF J = 2 ! FTI(LEVEL) = FTINDEX LINE = FIRST LINE LINE = "T" IF LINE = "" ! LINE = ANALYSE LINE(LINE, FTINDEX) -> RETURN TOO BIG: LINE = "More than ".ITOS(MAXDIR)." sections" OUT: -> SPOUT(SPECIAL CALL) SPOUT(0): ! not a special call W("VIEW fails " . LINE) LINE = "" -> RETURN SPOUT(1): ! scanning keys, ignore failure messages -> RETURN SPOUT(2): ! structure determination W(LINE) -> RETURN SPOUT(3): W("faulty file found") RETURN: LEVEL = LEVEL - 1 OUTPUT FILE = "T#VIEWOUT" . ITOS(LEVEL) MON("VIEWFN returns to level", ITOS(LEVEL)) RESULT = LINE END ; ! VIEWFN ! !----------------------------------------------------------------------- ! ROUTINE VIEW INIT INTEGER J CYCLE J = 1, 1, TOPFT FTS(J) = 0 REPEAT ! LAST SCREEN ID = 0 LEVEL = 0 PARTIAL DISPLAY = 0 PROCUSER = UINFS(1) SCREEN ID = 0 VIEWMON = 0 END ; ! VIEW INIT ! ! ! SYSTEMROUTINE ZVIEW2(STRING (255)S, STRINGNAME PARM) INTEGER I, J, ADR STRING (255)NEXT VIEW INIT VDUI3 = 0; ! lines/page ---- initialise own variables LPPAGE = 20 VDUS1 = ""; ! clear screen sequence LIBRAR = 1 IF PROCUSER = "LIBRAR" ! ADR = ADDR(NEXT) J = DSFI(PROCUSER, -1, 18, 0, ADR) RESTRICTED = 1 IF J = 0 START RESTRICTED = 0 UNLESS NEXT = "#VIEWER" FINISH ! TERMINAL TYPE("") IF RESTRICTED = 1 REROUTECONTINGENCY(3, 65, X'2080A0002080A', STRAP, I) ! SAVEMODE = "" IF SITE = KENT START SAVEMODE = MODESTR SETMODE("H=0,W=0") FINISH ! IF VDUI(1) > 0 START ; ! user has set terminal type WIDTH = VDUI(2) WIDTH = WIDTH - 1 IF VDUB(4) # 0 START STANDOUT = VDUS(17) END STANDOUT = VDUS(18) VDUI3 = VDUI(3); ! lines/page, 0 = hardcopy LPPAGE = VDUI3 - 4 IF VDUI3 > 0 LPPAGE = 20 IF LPPAGE > 20 VDUS1 = VDUS(1) IF VDUI3 > 0 START ; ! its a video IF VDUS1 = "" C THEN VDUS1 = NLS10 C ELSE VDUS1 = VDUS1 . TOSTRING(13) FINISH FINISH ! NEXT = "" UNLESS S -> S . (",") . NEXT S = DEFAULT FILE IF S = "" ! PARM = VIEWFN(S, NEXT) ! REROUTECONTINGENCY(0, 0, 0, STRAP, I) SETMODE(SAVEMODE) UNLESS SAVEMODE = "" END ; ! ZVIEW2 ! ! ! SYSTEMROUTINE ZVIEW(STRING (255)S) STRING (255)PARM ZVIEW2(S, PARM) END ; ! ZVIEW ! !----------------------------------------------------------------------- ! ! !----------------------------------------------------------------------- ! EXTERNALROUTINE VIEW(STRING (255)S) ZVIEW(S) END ; ! VIEW ! ! !----------------------------------------------------------------------- ! SYSTEMINTEGERFN ZVIEWREFS(STRING (31)FILE, STRING (255)KEYS, C INTEGER MAXREF, RECORD (REFF)ARRAYNAME REF, INTEGER SUBFILES) ! ! This function uses VIEW to scan the file FILE for the keys ! given in KEYS. Any 'hits' are returned in the record array ! REF up to a maximum of MAXREF. All the subsidiary files of ! FILE are examined automatically unless SUBFILES = 0. The number ! of 'hits' is returned as the result and may be greater than ! MAXREF. ! ! KEYS has the form ! key1 & key2 & ... ! where keyi may have an asterisk before and/or after ! ! REF is an array (1:MAXREF) of records whose format is ! %string(31)SECTION NAME, TOPIC, FILE, SECTION NUMBER ! To view a reference, call ! ZVIEW(FILE, SECTION NUMBER) STRING (63)K STRING (31)ARRAY SEARCHFILE(1:100) INTEGER F, KEYADR, J RECORD (FHDRF)NAME H VIEW INIT KKREFI = 0; ! number of refs found KKTOPREF = MAXREF KKREFADDR = ADDR(REF(1)) ! RESULT = 0 IF FILE = "" UCTRANSLATE(ADDR(FILE)+1, LENGTH(FILE)) SEARCHFILEI = 1; ! number of searchfiles TOPSEARCHFILE = 100 TOPSEARCHFILE = 1 IF SUBFILES = 0; ! don't look in subfiles SEARCHFILEA = ADDR(SEARCHFILE(1)) SEARCHFILE(1) = FILE ! KKTOPKEY = 0 UNLESS KEYS = "" START UCTRANSLATE(ADDR(KEYS)+1, LENGTH(KEYS)) KEYS = KEYS . "&" WHILE KEYS -> K . ("&") . KEYS CYCLE IF K # "" AND CHARNO(K, 1) = '*' C THEN K -> ("*") . K C ELSE K = "," . K ! IF K # "" AND CHARNO(K, LENGTH(K)) = '*' C THEN LENGTH(K) = LENGTH(K) - 1 C ELSE K = K . "," ! UNLESS K = "" START KKTOPKEY = KKTOPKEY + 1 KKEY(KKTOPKEY) = K FINISH EXIT IF KKTOPKEY = 10 REPEAT FINISH ! KKEYPT = 0 UNLESS FILE = "T#KEYWRK" START OUTFILE("T#KEYWRK", 32768, 0, 0, KEYADR, J) UNLESS J = 0 START W("T#KEY WRK ".FAILURE MESSAGE(J)) RESULT = 0 FINISH BYTEINTEGER(KEYADR + 32) = NL KKEYPT = KEYADR + 33 KKTOP KEYPT = KKEYPT + 32768 - 40; ! cautious FINISH ! F = 0 UNTIL F = SEARCHFILEI CYCLE F = F + 1 K = VIEWFN(SEARCHFILE(F), "K!*!") REPEAT ! UNLESS FILE = "T#KEYWRK" START H == RECORD(KEYADR) H_TYPE = 4 H_ADR = 3 H_NFB = KKEYPT - KEYADR FINISH ! RESULT = KKREFI END ; ! ZVIEWREFS ENDOFFILE