RECORDFORMAT C FRF(INTEGER CONAD, FILETYPE, DATASTART, DATEND, SIZE, RUP, EEP, MODE, USERS, ARCH, STRING (6)TRAN, STRING (8)DATE, TIME, INTEGER COUNT, SPARE1, SPARE2) CONSTINTEGER TOP = 100 RECORDFORMAT C HF(INTEGER END, START, SIZE, TYPE, SUM, DATETIME, ADR, RECS, TOPFILE, STRING (31)ARRAY FILE(1 : TOP), STRING (31)ARRAY TOPIC(1 : TOP), INTEGERARRAY KEY(1 : TOP), INTEGER KEYAREA) RECORDFORMAT C MF(INTEGER PDT, REFERENCES, STRING (6) USER, STRING (20) CALL) RECORDFORMAT C REFF(STRING (31)SECTION NAME, SECTION NO, INTEGER FILENO) RECORDFORMAT C RF(INTEGER CONAD, FILETYPE, DATASTART, DATAEND) ! ! ! SYSTEMROUTINESPEC C CONNECT(STRING (31)FILE, INTEGER MODE, HOLE, PROTECT, RECORD (RF)NAME R, INTEGERNAME FLAG) SYSTEMROUTINESPEC C DISCONNECT(STRING (31)FILE, INTEGERNAME FLAG) EXTERNALINTEGERFNSPEC C DSFI(STRING (31)INDEX, INTEGER FSYS, TYPE, SET, ADR) SYSTEMINTEGERFNSPEC C DTWORD(INTEGER DT) SYSTEMSTRINGFNSPEC C FAILUREMESSAGE(INTEGER FLAG) SYSTEMROUTINESPEC C FINFO(STRING (31)FILE, INTEGER MODE, RECORD (FRF)NAME R, INTEGERNAME FLAG) SYSTEMSTRINGFNSPEC C ITOS(INTEGER N) EXTERNALSTRING (255)FUNCTIONSPEC C MODESTR SYSTEMROUTINESPEC C MOVE(INTEGER LEN, FROM, TO) EXTERNALROUTINESPEC C PROMPT(STRING (255)S) SYSTEMINTEGERFNSPEC C PSTOI(STRING (63)S) SYSTEMINTEGERFUNCTIONSPEC C QUERYMODE(INTEGER N) EXTERNALROUTINESPEC C SET RETURN CODE(INTEGER I) SYSTEMROUTINESPEC C SETFNAME(STRING (63) S) EXTERNALROUTINESPEC C SETMODE(STRING (255) S) EXTERNALSTRINGFNSPEC C UINFS(INTEGER ENTRY) EXTERNALINTEGERFNSPEC C VDUB(INTEGER N) EXTERNALINTEGERFNSPEC C VDUI(INTEGER N) EXTERNALSTRINGFNSPEC C VDUS(INTEGER N) SYSTEMROUTINESPEC C ZVIEW2(STRING (255)PARMS, STRINGNAME RETURN) SYSTEMROUTINESPEC C UCTRANSLATE(INTEGER AD, LEN) SYSTEMINTEGERFNSPEC C CURRENT PACKED DT ! ! ! OWNINTEGER DTEXTRACT OWNINTEGER TOPIC FILE OWNINTEGER QUERY OWNINTEGER PTRNS0 OWNINTEGER OCP0 CONSTSTRINGNAME TIME = X'80C0004B' CONSTINTEGER YES= 1 CONSTINTEGER NO = 0 CONSTINTEGER REF LIMIT= 10 CONSTINTEGER MAX REFS= 100 CONSTINTEGER RECLENGTH= 36 CONSTSTRING (31) MONFILE= "SUBSYS.HELPMON" OWNBYTEINTEGERARRAY P(1 : 160); ! see LAYOUT and DISPLAY OWNINTEGER TOPMOD = 0 OWNBYTEINTEGERARRAY MODIFIED(1 : TOP) OWNSTRING (31) START STANDOUT, END STANDOUT ! ! OWNINTEGER REF COUNT, RED REF COUNT OWNRECORD (REFF) ARRAY REFS(1:MAXREFS) OWNRECORD (REFF) ARRAY RED REFS(1:MAX REFS) CONSTINTEGER TOP KEY = 8 OWNSTRING (63)ARRAY KEY(1:TOPKEY) OWNSTRING (63)ARRAY REDKEY(1:TOP KEY) OWNBYTEINTEGERARRAY STAR(1:TOPKEY) OWNBYTEINTEGERARRAY REDSTAR(1:TOP KEY) OWNINTEGER KEYCOUNT, REDKEYFLAG ! ! ! ! ! ! ROUTINE Q(STRING (255)S) INTEGER J, PTRNS, OCP RETURN IF QUERY = NO J = DSFI("", -1, 24, 0, ADDR(PTRNS)) J = DSFI("", -1, 28, 0, ADDR(OCP)) PRINTSTRING(TIME) PRINTSTRING(" PTRNS"); WRITE(PTRNS - PTRNS0, 3) PRINTSTRING(" OCP"); WRITE(OCP - OCP0, 3) SPACE PRINTSTRING(S) NEWLINE END ; ! Q ! ! ! ROUTINE PRINTCHS(STRING (255)S) INTEGER J CYCLE J = 1, 1, LENGTH(S) PRINTCH(CHARNO(S, J)) REPEAT END ; ! PRINTCHS ! ! ! ROUTINE RSTRG(STRINGNAME S) INTEGER J S = "" CYCLE READ SYMBOL(J) RETURN IF J = NL S = S . TOSTRING(J) REPEAT END ! ! ! ROUTINE W(STRING (255)S) PRINTCHS(S) NEWLINE END ; ! W ! ! ! RECORDFORMAT C DIRF(STRING (30)SEC, BYTEINTEGER B, STRING (31)NAME, INTEGER I1, I2, I3, I4) OWNRECORD (DIRF)ARRAYFORMAT C VDIRAF(-1 : 32768) RECORDFORMAT C PDF(INTEGER START, STRING (11) NAME, INTEGER HOLE, S5, S6, S7) RECORDFORMAT C PDHF(INTEGER DATAEND, DATASTART, SIZE, FILETYPE, SUM, DATETIME, ADIR, COUNT) OWNRECORD (PDF)ARRAYFORMAT C DIRAF(0:4095) ! ! ! ! ! ! SYSTEMROUTINESPEC C OUTFILE(STRING (31) FILE, INTEGER SIZE, HOLE, PROT, INTEGERNAME CONAD, FLAG) ! ! !*********************************************************************** !* !* Service routines !* !*********************************************************************** ! CONSTINTEGER SILENT = NO ! !----------------------------------------------------------------------- ! ROUTINE CONNECT2(STRING (63)FILE, INTEGER MODE, HOLE, PROT, RECORD (RF) NAME RR, INTEGERNAME FLAG) ! This is a generalised version of CONNECT. INTEGER BASE, NEWBASE, I STRING (31)MEM STRING (255) FILEF, FULL, REM RECORD (RF) R1 RECORD (PDHF) NAME H RECORD (PDF) ARRAYNAME DIR IF FILE = "" START SETFNAME(FILE) FLAG = 220; ! Invalid filename RETURN FINISH ! ! FILEF = FILE."_" FILEF -> FULL.("_").REM CONNECT(FULL, MODE, HOLE, PROT, R1, FLAG) RETURNIF FLAG # 0 ! BASE = R1_CONAD ! CYCLE H == RECORD(BASE) EXITIF REM = "" IF H_FILETYPE # 6 {SSPDFILETYPE} START FULL <- FULL." is not a PD file" IF LENGTH(FULL) > 40 START FULL = SUBSTRING(FULL, LENGTH(FULL) - 36, LENGTH(FULL)) FULL = "...".FULL FINISH SETFNAME(FULL) FLAG = 233; ! General flag RETURN FINISH ! DIR == ARRAY(BASE + H_ADIR, DIRAF) UNLESS REM - > MEM.("_").REM START IF LENGTH(FILE) > 40 START LENGTH(FILE) = 37 FILE = FILE."..." FINISH SETFNAME(FILE) FLAG = 220; ! Invalid filename RETURN FINISH ! NEWBASE = 0 FOR I = 0, 1, H_COUNT - 1 CYCLE IF DIR(I)_NAME = MEM START NEWBASE = BASE + DIR(I)_START EXIT FINISH REPEAT ! IF NEWBASE = 0 START SETFNAME(MEM) FLAG = 288; ! Member does not exist RETURN FINISH ! BASE = NEWBASE FULL = FULL."_".MEM REPEAT ! RR_CONAD = BASE RR_FILETYPE = H_FILETYPE RR_DATASTART = H_DATASTART RR_DATAEND = H_DATAEND END ; ! connect2 ! !------------------------------------------------------------ ! INTEGERFN EXTRACT(RECORD (HF)NAME H, STRING (255)FILE) INTEGER J, K, F, CFLAG, CH, DIRA, KEYA INTEGER K1, N, L RECORD (RF)R, KR, VR BYTEINTEGERARRAYNAME KEYS BYTEINTEGERARRAYFORMAT KEYSF(0 : 1000000) RECORD (DIRF)ARRAY NAME DIR STRING (255)NAME RECORD (PDHF)NAME HDR H_TYPE = 4; ! Data H_ADR = 3; ! Structure not specified K = ADDR(H_KEYAREA) BYTEINTEGER(K) = 10 K = K + 1 ! H_TOPFILE = 1 H_FILE(1) = FILE ! F = 1 Q("Subfile: " . H_FILE(F)) H_KEY(F) = K - ADDR(H) CONNECT2(H_FILE(F), 1, 0, 0, R, CFLAG) -> NEXT UNLESS CFLAG = 0 ! HDR == RECORD(R_CONAD) IF HDR_FILETYPE = 3 START IF HDR_COUNT = 2 START DIRA = R_CONAD + 96 KEYA = DIRA + INTEGER(DIRA) + 32 DIRA = DIRA + 32 FINISH ELSE -> NEXT FINISH ELSE START CONNECT2(H_FILE(F) . "_VIEWKEYS", 1, 0, 0, KR, CFLAG) -> NEXT UNLESS CFLAG = 0 ! CONNECT2(H_FILE(F) . "_VIEWDIR2", 1, 0, 0, VR, CFLAG) -> NEXT UNLESS CFLAG = 0 ! DIRA = VR_CONAD+VR_DATASTART KEYA = KR_CONAD+KR_DATASTART FINISH ! DIR == ARRAY(DIRA, VDIRAF) KEYS == ARRAY(KEYA, KEYSF) ! H_TOPIC(F) = DIR(-1)_SEC K1 = INTEGER(KEYA-32) - 34; ! end of Viewkeys file J = 0 LOOP: -> NEXT IF J >= K1 J = J + 1 AND -> LOOP UNLESS KEYS(J) = NL N = 0 WHILE '0' <= KEYS(J+1) <= '9' CYCLE J = J + 1 N = N * 10 + KEYS(J) - '0' REPEAT ! IF LENGTH(DIR(N)_NAME) < 32 C THEN NAME = DIR(N)_NAME C ELSE START LENGTH(NAME) = 31 MOVE(31, R_CONAD+INTEGER(ADDR(DIR(N)_NAME)+4)-X'40000', ADDR(NAME)+1) FINISH ! NAME = NAME . "¬" . DIR(N)_SEC L = LENGTH(NAME) MOVE(L, ADDR(NAME)+1, K) K = K + L ! CYCLE J = J + 1 CH = KEYS(J) BYTEINTEGER(K) = CH AND K = K + 1 UNLESS CH = ' ' REPEAT UNTIL CH = NL -> LOOP NEXT: Q(H_FILE(F) . FAILUREMESSAGE(CFLAG)) UNLESS CFLAG = 0 ! H_END = K - ADDR(H) Q("End: " . ITOS(H_END)) RESULT = CFLAG END ; ! EXTRACT ! !----------------------------------------------------------------------- ! INTEGERFN KWDSCAN(INTEGERNAME XLENGTH, XADDR, ORIGINAL, INTEGER KWDCT, RED KEY FLAG, STRINGARRAYNAME RED KEY, KEY, BYTEINTEGERARRAYNAME RED STAR, STAR) ! 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 PREVIOUS CH INTEGER I, L, UNSEENCT LONG INTEGER ARRAY REDKEYDESCR, 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 REDKEYDESCR(I) = (LENGTHENI(X'18000000'!LENGTH(REDKEY(I)))<<32) C ! (ADDR(RED KEY(I)) + 1) IF RED KEY FLAG = 1 START KEYDESCR(I) = (LENGTHENI(X'18000000'!LENGTH(KEY(I)))<<32) C ! (ADDR(KEY(I))+1) FINISH 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 = REDKEYDESCR (I) *LB_(DRH); ! Get the first character of KEYS (I). *LSS_1; ! reduced keys have the same initial letter *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. ORIGINAL = 1; ! assume found original keys unless proved wrong 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 RED KEYS? *STD_XDESCR L = INTEGER(ADDR(XDESCR)) & X'00FFFFFF'; ! Length of residue of data. PREVIOUS CH = BYTEINTEGER(INTEGER(ADDR(XDESCR)+4)-1) CYCLE I = KWDCT, -1, 1 IF SEEN(I) = 0 AND LENGTH(RED KEY(I)) <= L START DRH = REDKEYDESCR(I) *LD_DRH *LSD_XDESCR *CPS_L =DR *JCC_7,<TRY NEXT> -> TRY NEXT IF REDSTAR(I) = 0 AND PREVIOUS CH # ',' -> ORIG MATCH IF RED KEY FLAG = 0; ! only one set of keys IF LENGTH(KEY(I)) <= L START ; ! possible DRH = KEYDESCR(I) *LD_DRH *LSD_XDESCR *CPS_L =DR *JCC_7,<NOTORIG> -> ORIG MATCH IF STAR(I) = 1 OR PREVIOUS CH = ',' FINISH NOT ORIG: ORIGINAL = 0 ORIG MATCH: SEEN (I) = -1 UNSEENCT = UNSEENCT - 1 IF UNSEENCT = 0 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 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 ! END ; ! KWDSCAN ! !----------------------------------------------------------------------- ! INTEGERFN FINDREFS(RECORD (HF)NAME H, STRINGARRAYNAME REDKEY, KEY, BYTEINTEGERARRAYNAME REDSTAR, STAR, RECORD (REFF)ARRAYNAME RED REF, REF, INTEGER MAXREF, KEY COUNT, RED KEY FLAG, INTEGERNAME REF COUNT) ! INTEGER J, RED REF COUNT, A, F, ADR, LEN, ORIGINAL STRING (63)SNAME, SNO INTEGERNAME COUNT RECORD (REFF)ARRAYNAME R ! ROUTINE GET(STRINGNAME S, INTEGERNAME J, INTEGER STOP) INTEGER A0, A, CH A0 = ADDR(S) + 1 A = A0 CYCLE CH = BYTEINTEGER(J) J = J + 1 EXIT IF CH = STOP BYTEINTEGER(A) = CH A = A + 1 REPEAT LENGTH(S) = A - A0 END ; ! GET ! ROUTINE SAVE REF(RECORD (REFF)ARRAYNAME REF, INTEGERNAME COUNT, STRINGNAME SNAME, SNO, INTEGER FILE, MAX) STRING (31)BEFORE STRING (255)W W = SNO . "." COUNT = COUNT + 1 IF COUNT <= MAX START IF COUNT > 1 ANDC FILE = REF(COUNT-1)_FILE NO ANDC W -> BEFORE . (REF(COUNT-1)_SECTION NO . ".") AND BEFORE = "" C THEN COUNT = COUNT - 1 C ELSE START REF(COUNT)_SECTION NAME = SNAME REF(COUNT)_SECTION NO = SNO REF(COUNT)_FILE NO = FILE FINISH FINISH END ; ! SAVE REF ! ADR = ADDR(H_KEYAREA) LEN = ADDR(H) + H_END - ADR RED REF COUNT = 0 REF COUNT = 0 ! CYCLE J = KWDSCAN(LEN, ADR, ORIGINAL, KEY COUNT, RED KEY FLAG, RED KEY, KEY, RED STAR, STAR) EXIT IF J = 0 ! GET(SNAME, J, '¬') GET(SNO, J, ':') ! A = J - ADDR(H) CYCLE F = H_TOPFILE, -1, 1 EXIT IF A > H_KEY(F) REPEAT ! IF ORIGINAL = 0 C THEN COUNT == RED REF COUNT AND R == RED REF C ELSE COUNT == REF COUNT AND R == REF SAVE REF(R, COUNT, SNAME, SNO, F, MAXREF) ! REPEAT Q("Red ref count " . ITOS(RED REF COUNT)) Q(" Ref count " . ITOS(REF COUNT)) RESULT = RED REF COUNT END ; ! FINDREFS ! !----------------------------------------------------------------------- ! ROUTINE SYMBOLS(INTEGER N, SYMBOL) WHILE N > 0 CYCLE PRINTSYMBOL(SYMBOL) N = N - 1 REPEAT END ; ! SYMBOLS ! !----------------------------------------------------------------------- ! INTEGERFN LAYOUT(INTEGER A, B, LPPAGE) INTEGER L, I, THIS L P(1) = 205; ! header lines P(2) = 206 P(3) = 207 P(4) = 200 L = 4; ! number of lines so far ! IF A > 0 START IF A = 1 THEN P(5) = 201 ELSE P(5) = 202 P(6) = 200 L = 6 CYCLE I = 1, 1, A L = L + 1 P(L) = I REPEAT ! -> TIDY IF B = 0 ! THIS L = L THIS L = THIS L - LPPAGE WHILE THIS L > LPPAGE IF THIS L > LPPAGE - 4 C { (THIS L + 3 + B > LPPAGE %AND B < LPPAGE - 2) %C } START CYCLE I = 1, 1, LPPAGE - THIS L L = L + 1 P(L) = 200 REPEAT FINISH ELSE START L = L + 1 P(L) = 200 FINISH FINISH ! IF B > 0 START L = L + 1 IF B = 1 THEN P(L) = 203 ELSE P(L) = 204 L = L + 1 P(L) = 200 CYCLE I = 1, 1, B L = L + 1 P(L) = 100 + I REPEAT FINISH TIDY: THIS L = L THIS L = THIS L - LPPAGE WHILE THIS L > LPPAGE CYCLE I = 1, 1, LPPAGE - THIS L L = L + 1 P(L) = 200 REPEAT ! RESULT = L // LPPAGE END ; ! LAYOUT ! !----------------------------------------------------------------------- ! ROUTINE DISPLAY(RECORD (HF)NAME H, STRING (255)KEYS, RED KEYS, RECORD (REFF)ARRAYNAME REFS, RED REFS, INTEGER PAGE, MAXPAGE, LPPAGE, A) INTEGER I, J, L, WW, N STRING (63)WORK RECORD (REFF)NAME REF SWITCH SW(200:207) PRINTCHS(VDUS(1)); ! could do this a bit better for hardcopy devices PRINTSTRING(" References found") IF PAGE > 1 START SPACES(44) PRINTSTRING("/" . ITOS(PAGE)) FINISH NEWLINE SYMBOLS(72, '-'); NEWLINE ! I = (PAGE - 1) * LPPAGE + 1 J = I + LPPAGE - 1 CYCLE L = I, 1, J WW = P(L) -> SW(WW) IF WW >= 200 IF WW < 100 START N = WW REF == REFS(WW) FINISH ELSE START WW = WW - 100 N = WW + A REF == RED REFS(WW) FINISH WORK = ITOS(N) . " " LENGTH(WORK) = 4 WORK = WORK . REF_SECTION NAME . " " LENGTH(WORK) = LENGTH(WORK) & (-4) WORK = WORK . " . " WHILE LENGTH(WORK) < 40 LENGTH(WORK) = 40 W(WORK . H_TOPIC(REF_FILE NO)) -> NEXT SW(200): NEWLINE; -> NEXT SW(201): W("Reference to " . KEYS); -> NEXT SW(202): W("References to " . KEYS); -> NEXT SW(203): W("Reference to " . RED KEYS); -> NEXT SW(204): W("References to " . RED KEYS); -> NEXT SW(205): W("To examine a reference type its number and press 'return'. To return to") W("this page, type R and press 'return' in response to the View: prompt") W("(you may have to do this more than once). Q returns to command level.") SW(206): SW(207): NEXT: REPEAT IF PAGE < MAXPAGE C THEN W(START STANDOUT."...more".END STANDOUT) C ELSE W(START STANDOUT."End of section".END STANDOUT) PROMPT("Help: ") END ; ! DISPLAY ! !----------------------------------------------------------------------- ! ROUTINE MONITOR CALL(STRING (255)PARMS, INTEGER REFCOUNT) RECORD (MF) NAME M INTEGERNAME COUNT INTEGER BASE, MAX INTEGER FLAG, HOLDCOUNT RECORD (RF) RR RECORD (FRF) FR CONNECT(MONFILE, 11, 0, 0, RR, FLAG); ! Connect write shared RETURN UNLESS FLAG = 0 FINFO(MONFILE, 0, FR, FLAG) RETURN UNLESS FLAG = 0 MAX = (FR_SIZE - 36) // RECLENGTH; !Maximum of records it can hold BASE = RR_CONAD + 36 COUNT == INTEGER(RR_CONAD + RR_DATASTART) *INCT_(COUNT) *ST_HOLDCOUNT RETURN UNLESS 0 <= HOLDCOUNT <= MAX; ! FILE FULL ! M == RECORD(BASE + HOLDCOUNT * RECLENGTH) M_PDT = CURRENT PACKED DT M_REFERENCES = REFCOUNT M_USER = UINFS(1) M_CALL <- PARMS ! DISCONNECT(MONFILE, FLAG) END ; ! MONITOR CALL ! !----------------------------------------------------------------------- ! STRINGFN REDUCED(STRING (80)S) ! This FN attempts to reduce compound forms of words to ! more simple forms by removing common suffixes and ! truncating words to a meaningful length, ie. meaningful w.r.t. ! any common prefix that the word may have. The known suffixes ! and prefixes are normally no longer than four characters long ! and sometimes less and so they are held in a form that can be ! be used to exploit the full-word logical operator AND. ! Note that the order in which the suffixes are stored is ! very important and should not be altered. The prefixes are ! not affected by the order in which they are stored and thus ! can be added to as the need arrises, something that is quite ! likely to happen in a specialised environment. ! INTEGER I, WORD END, WE ADDR, OPTION, SADDR INTEGER TRUNCATION, WORD START, MINIMUM BYTEINTEGERNAME L STRING (80) ORIGINAL S ! ! MASKS FOR USE WITH THE SUFFIX OPTION VALUES ! CONSTBYTEINTEGER COMPLETED= 1,REMOVE = 2,DOUBLE CHECK = 4 CONSTINTEGER VOWEL TRUNC= 8 ! ! VARIOUS IMPORTANT CONST LENGTHS ! CONSTINTEGER VT MIN= 5 ; ! WORDS LESS THAN THIS DON'T HAVE VOWELS TRUNCATED ! !******************************************************************************** !* !* SPECIFICATION OF THE SUFFIXES - ORDER VERY IMPORTANT !* !******************************************************************************** ! CONSTINTEGER MAX SUFFIX= 22 CONSTBYTEINTEGERARRAY SUFFIX BYTES(0:11, 0:MAX SUFFIX)= C { } { S U F F I X M A S K LEN OPTION SPARE } 0 , 0 , 0 , 0 , x'00',x'00',x'00',x'00', 0, 1, 0, 0, 0 , 0 ,'L','Y', x'00',x'00',x'FF',x'FF', 2, 2, 0, 0, 'L','E','S','S', x'FF',x'FF',x'FF',x'FF', 4, 2, 0, 0, 'N','E','S','S', x'FF',x'FF',x'FF',x'FF', 4, 2, 0, 0, 0 , 0 ,'S','S', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 ,'I','E','S', x'00',x'FF',x'FF',x'FF', 3, 2, 0, 0, 0 , 0 ,'E','S', x'00',x'00',x'FF',x'FF', 2, 2, 0, 0, 0 , 0 , 0 ,'S', x'00',x'00',x'00',x'FF', 1, 2, 0, 0, 0 ,'I','O','N', x'00',x'FF',x'FF',x'FF', 3, 2, 0, 0, 0 , 0 ,'E','D', x'00',x'00',x'FF',x'FF', 2, 7, 0, 0, 0 ,'I','N','G', x'00',x'FF',x'FF',x'FF', 3, 7, 0, 0, 0 , 0 ,'A','Y', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 , 0 ,'E','Y', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 , 0 ,'I','Y', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 , 0 ,'O','Y', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 , 0 ,'U','Y', x'00',x'00',x'FF',x'FF', 2, 1, 0, 0, 0 , 0 , 0 ,'Y', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 ,'A', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 ,'E', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 ,'I', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 ,'O', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 ,'U', x'00',x'00',x'00',x'FF', 1, 9, 0, 0, 0 , 0 , 0 , 0, x'00',x'00',x'00',x'00', 0, 1, 0, 0 INTEGERARRAYNAME SUFFIX WORDS INTEGERARRAYFORMAT SW FORMAT(0:2, 0:MAX SUFFIX) ! !******************************************************************************** !* !* A SIMPLE SET OF SUFFIXES TO BE REMOVED IN THE EVENT OF THE !* FULL REDUCTION HAVING REDUCED A WORD TO LESS THAN THE !* MINIMUM SUITABLE BEARING IN MIND ANY PREFIX !* !******************************************************************************** ! CONSTINTEGER MAX SIMPLE= 6 CONSTBYTEINTEGERARRAY SIMPLE BYTES(0:11, 0:MAX SIMPLE)= C { } { S U F F I X M A S K LEN SPARE SPARE } 0 , 0 , 0 , 0 , x'00',x'00',x'00',x'00', 0, 0, 0, 0, 0 , 0 ,'L','Y', x'00',x'00',x'FF',x'FF', 2, 0, 0, 0, 0 ,'I','E','S', x'00',x'FF',x'FF',x'FF', 3, 0, 0, 0, 0 , 0 ,'E','S', x'00',x'00',x'FF',x'FF', 2, 0, 0, 0, 0 , 0 , 0 ,'S', x'00',x'00',x'00',x'FF', 1, 0, 0, 0, 0 , 0 , 0 ,'Y', x'00',x'00',x'00',x'FF', 1, 0, 0, 0, 0 , 0 , 0 , 0 , x'00',x'00',x'00',x'00', 0, 0, 0, 0 INTEGERARRAYNAME SIMPLE WORDS INTEGERARRAYFORMAT SIMPLE FORMAT(0:2, 0:MAX SIMPLE) ! !******************************************************************************** !* !* PREFIXES - ORDER NOT IMPORTANT - STORED IN ALPHABETICAL ORDER !* FOR LACK OF ANY BETTER IDEA. !* !******************************************************************************** ! CONSTINTEGER MAX PREFIX= 16 CONSTBYTEINTEGERARRAY PREFIX BYTES(0:11, 0:MAX PREFIX)= C { } { P R E F I X M A S K MIN TRUNC SPARE } 0 , 0 , 0 , 0 , x'00',x'00',x'00',x'00', 3, 5, 0, 0, 'A','R','C', 0 , x'FF',x'FF',x'FF',x'00', 5, 7, 0, 0, 'C','O','M', 0 , x'FF',x'FF',x'FF',x'00', 6, 7, 0, 0, 'C','O','N', 0 , x'FF',x'FF',x'FF',x'00', 6, 7, 0, 0, 'C','O','R','R', x'FF',x'FF',x'FF',x'FF', 6, 7, 0, 0, 'D','I','F','F', x'FF',x'FF',x'FF',x'FF', 7, 10, 0, 0, 'D','I','R','E', x'FF',x'FF',x'FF',x'FF', 8, 8, 0, 0, 'E','I','G', 0 , x'FF',x'FF',x'FF',x'00', 5, 7, 0, 0, 'G','R','A','P', x'FF',x'FF',x'FF',x'FF', 7, 9, 0, 0, 'I','N','T', 0 , x'FF',x'FF',x'FF',x'00', 5, 7, 0, 0, 'M','U','L','T', x'FF',x'FF',x'FF',x'FF', 6, 6, 0, 0, 'O','P','T', 0 , x'FF',x'FF',x'FF',x'00', 5, 5, 0, 0, 'P','R','O', 0 , x'FF',x'FF',x'FF',x'00', 5, 7, 0, 0, 'S','T','A', 0 , x'FF',x'FF',x'FF',x'00', 5, 7, 0, 0, 'S','T','R', 0 , x'FF',x'FF',x'FF',x'00', 6, 7, 0, 0, 'T','R','A','N', x'FF',x'FF',x'FF',x'FF', 6, 8, 0, 0, 0 , 0 , 0 , 0 , x'00',x'00',x'00',x'00', 3, 5, 0, 0 INTEGERARRAYNAME PREFIX WORDS INTEGERARRAYFORMAT PW FORMAT(0:2, 0:MAX PREFIX) ! ! OTHER PREFIXES THAT MIGHT NEED TO BE INCLUDED IN THE ABOVE TABLE ARE ! OPEN,CLOS(E),READ,WRIT(E),PRIN(T),COPY,OUT,IN ! GET,SET,SUB,NEW,OLD,LOG,ALG,PRE,DIS,UN,DE,RE ! !******************************************************************************** ! ! ORIGINAL S = S SADDR = ADDR(S) + 1 L == BYTEINTEGER(SADDR - 1) FOR I = SADDR, 1, SADDR + L - 1 CYCLE IF '0' <= BYTEINTEGER(I) <= '9' THENRESULT = S REPEAT SUFFIX WORDS == ARRAY(ADDR(SUFFIX BYTES(0, 0)), SW FORMAT) PREFIX WORDS == ARRAY(ADDR(PREFIX BYTES(0, 0)), PW FORMAT) SIMPLEWORDS == ARRAY(ADDR(SIMPLE BYTES(0, 0)), SIMPLE FORMAT) WE ADDR = ADDR(WORD END) ! MOVE(4, SADDR, ADDR(WORD START)) FOR I = 1, 1, MAX PREFIX CYCLE IF WORD START & PREFIX WORDS(1, I) = PREFIX WORDS(0, I) START TRUNCATION = PREFIX BYTES(9, I) MINIMUM = PREFIX BYTES(8, I) EXIT FINISH REPEAT ! CYCLE MOVE(4, SADDR + L - 4, WE ADDR) FOR I = 1, 1, MAX SUFFIX CYCLE IF WORD END & SUFFIX WORDS(1, I) = SUFFIX WORDS(0, I) THEN C OPTION = SUFFIX BYTES(9, I) ANDEXIT REPEAT ! IF OPTION & REMOVE > 0 START L = L - SUFFIX BYTES(8, I) IF L <= MINIMUM THENEXIT FINISH ! IF OPTION & DOUBLE CHECK > 0 START IF CHARNO(S, L - 1) = CHARNO(S, L) THEN L = L - 1 FINISH ! IF OPTION & VOWEL TRUNC > 0 START ! %IF L > VT MIN %THEN L = L - SUFFIX BYTES(8, I) FINISH ! IF OPTION & COMPLETED > 0 THENEXIT REPEAT ! IF L > TRUNCATION THEN L = TRUNCATION ! IF L < MINIMUM START ! MAIN REDUCTION HAS SHORTENED WORD TO SOMETNING ! LESS THAN USEFUL EG "SING" TO "S". THE ONLY ! THING TO DO NOW IS TO REINSTATE THE ORIGINAL WORD ! AND SIMPLY REMOVE PLURALS AND "LY"'S S = ORIGINAL S MOVE(4, SADDR + L - 4, WE ADDR) FOR I = 1, 1, MAX SIMPLE CYCLE IF WORD END & SIMPLE WORDS(1, I) = SIMPLE WORDS(0, I) THEN C L = L - SIMPLE BYTES(8, I) ANDEXIT REPEAT FINISH IF L < MINIMUM THEN S = ORIGINAL S ! RESULT = S ! END ; ! REDUCED ! !----------------------------------------------------------------------- ! INTEGERFN MODIFY(INTEGER F, MAX, INTEGERNAME N1, N2, RECORD (REFF)ARRAYNAME R1, R2) INTEGER I, J, I0, I1, FNO, OLD, N, NEWCOUNT I0 = 0 I1 = 0 IF N1 > 0 START ; ! locate old refs to the file CYCLE I = 1, 1, N1 FNO = R1(I)_FILENO I0 = I IF I0 = 0 AND FNO >= F I1 = I IF FNO = F EXIT IF FNO > F REPEAT FINISH I0 = N1 + 1 IF I0 = 0; ! where refs are or should be put OLD = 0 OLD = I1 - I0 + 1 IF I1 > 0; ! number of old refs ! -> DIFF UNLESS OLD = N2 I = I0 CYCLE J = 1, 1, OLD -> DIFF UNLESS R1(I)_SECTION NO = R2(J)_SECTION NO -> DIFF UNLESS R1(I)_SECTION NAME = R2(J)_SECTION NAME I = I + 1 REPEAT RESULT = 0; ! same number of refs with same values DIFF: J = N1 + N2 - OLD; ! new last N2 = 0 AND J = N1 - OLD IF J > MAX; ! most unlikely NEWCOUNT = J ! IF N2 < OLD START ; ! now have fewer so close the gap I = I1 J = I0 + N2 CYCLE I = I + 1 EXIT IF I > N1 R1(J) = R1(I) J = J + 1 REPEAT FINISH ! IF N2 > OLD AND I0 + OLD <= N1 START ; ! need (bigger) gap I = N1 N = N1 - I0 + 1 - OLD CYCLE R1(J) = R1(I) J = J - 1 I = I - 1 N = N - 1 REPEAT UNTIL N = 0 FINISH ! I = 0 J = I0 WHILE I < N2 CYCLE I = I + 1 R2(I)_FILENO = F R1(J) = R2(I) J = J + 1 REPEAT ! N1 = NEWCOUNT RESULT = 1; ! refs radically altered END ; ! MODIFY ! !----------------------------------------------------------------------- ! INTEGERFN CHANGED(RECORD (HF)NAME H0, INTEGER F) INTEGER HA, J, RC, RRC, RC0, RRC0 STRING (255)JUNK RECORD (HF)NAME H RECORD (REFF)ARRAY R, RR(1:MAXREFS) RC0 = REFCOUNT RRC0 = REDREFCOUNT RC = 0 RRC = 0 ! J = MAILSUPPORT("ERCC04@2972", H0_FILE(F) . " changed?") OUTFILE("T#EXTRACT", 1 << 17, 0, 0, HA, J) IF J = 0 START H == RECORD(HA) J = EXTRACT(H, H0_FILE(F)) RRC = FINDREFS(H, REDKEY, KEY, REDSTAR, STAR, RR, R, MAXREFS, KEYCOUNT, REDKEYFLAG, RC) IF J = 0 FINISH ! J = MODIFY(F, MAXREFS, REDREFCOUNT, RRC, REDREFS, RR) ! C MODIFY(F, MAXREFS, REFCOUNT, RC, REFS, R) RESULT = 0 IF J = 0; ! no apparent change ! RESULT = 1 IF RC0 = 1 > RRC0; ! there wasn't a menu on display W("File '" . H0_TOPIC(F) . "', which contained the reference, has been changed") IF REF COUNT = 0 = RED REF COUNT START W("and the reference no longer exists") RESULT = 2 FINISH ! W("Please press 'return' for a revised menu") PROMPT("Revision: ") RSTRG(JUNK) RESULT = 3 END ; ! CHANGED ! !----------------------------------------------------------------------- ! INTEGERFN DISPLAY REF(RECORD (HF)NAME H, RECORD (REFF)NAME REF, STRINGNAME RETURN) INTEGER F, J, DONE STRING (31)FILE RECORD (RF)R J = 0 F = REF_FILENO FILE = H_FILE(F) CONNECT(FILE, 1, 0, 0, R, J) IF J # 0 OR DTWORD(INTEGER(R_CONAD+20)) > DTEXTRACT START DONE = 0 J = 0 WHILE J < TOPMOD CYCLE DONE = 1 AND EXIT IF MODIFIED(J) = F; ! already done this file J = J + 1 REPEAT ! J = 0 J = CHANGED(H, F) IF DONE = 0 FINISH ZVIEW2(H_FILE(F) . "," . REF_SECTION NO, RETURN) IF J = 0 PROMPT("Help: ") RESULT = J; ! non zero if changed and ref not displayed END ; ! DISPLAY REF ! !----------------------------------------------------------------------- ! SYSTEMROUTINE ZHELP(STRING (255)EXTRACT, HELPINFO, KEYS) ! INTEGER J, PAGE, MAXPAGE, VDUI2, VDUI3, LPPAGE INTEGER A, B, L INTEGER MENU ON DISPLAY STRING (255)RED KEYS, WORK, K, KEY AS GIVEN STRING (255)BEFORE, AFTER, VDUS1 RECORD (RF)R RECORD (HF)NAME H CONNECT(EXTRACT, 1, 0, 0, R, J) RETURN UNLESS J = 0 H == RECORD(R_CONAD) DTEXTRACT = DTWORD(H_DATETIME) ! KEYS = BEFORE.AFTER WHILE KEYS -> BEFORE.(" ").AFTER; ! remove blanks UCTRANSLATE(ADDR(KEYS) + 1, LENGTH(KEYS)); ! upper case translate ! QUERY = NO IF LENGTH(KEYS) > 1 AND CHARNO(KEYS, LENGTH(KEYS)) = '?' START QUERY = YES LENGTH(KEYS) = LENGTH(KEYS) - 1 J = DSFI("", -1, 24, 0, ADDR(PTRNS0)); ! get initial values J = DSFI("", -1, 28, 0, ADDR(OCP0)) FINISH ! TOPIC FILE = 0 IF KEYS -> KEYS . ("/") .AFTER START CYCLE J = 1, 1, H_TOPFILE IF H_TOPIC(J) = AFTER START TOPIC FILE = J Q("Topic file: ".ITOS(TOPIC FILE)) EXIT FINISH REPEAT FINISH !----------------------------------------------------------------------- IF KEYS -> (".ALL") OR KEYS="" OR KEYS="?" OR KEYS="HELP" OR LENGTH(KEYS)>128 START CYCLE J = 1, 1, H_TOPFILE Q(H_FILE(J) . " - " . H_TOPIC(J)) REPEAT ZVIEW2(HELPINFO, AFTER) -> RETURN FINISH !----------------------------------------------------------------------- IF KEYS -> (",") START W("Commas (,) are not permitted in keys") W("To send output to a printer or a file, get to the section") W("you want, then type") W(" F<.LP>") W("or F<filename>") W("or F<filename/W> if the file already exists") W("or F<filename-MOD> to add to an existing file") SETFNAME(KEYS) SET RETURN CODE(202) RETURN FINISH ! !----------------------------------------------------------------------- ! Each key is examined to see if it can be 'reduced' ie ! some common suffix (and prefix?) removed. This is done ! if the length of the key is > 2 (excluding *'s) and does ! not have a trailing *. The reduced key - RED key - is ! then enclosed in *'s. RED KEY FLAG = NO RED KEYS = "" WORK = KEYS."&" KEY COUNT = 0 WHILE WORK -> KEY AS GIVEN.("&").WORK CYCLE KEY COUNT = KEY COUNT + 1 IF KEY COUNT > TOP KEY START W("Too many keys!!!") -> FAIL FINISH L = LENGTH(KEY AS GIVEN); ! examine each key A = 0 B = 0 IF L > 0 START A = 1 IF CHARNO(KEY AS GIVEN, 1) = '*' B = 1 IF CHARNO(KEY AS GIVEN, L) = '*' FINISH IF L - A - B < 2 START W("Keys must be at least 2 characters long") FAIL: SETFNAME(KEYS) SET RETURN CODE(202) RETURN FINISH BEFORE = KEY AS GIVEN BEFORE -> ("*") . BEFORE IF A = 1 L = L - A - B LENGTH(BEFORE) = L IF B = 1 K = BEFORE; ! original key K = K . "," IF B = 0 KEY(KEY COUNT) = K RED KEY(KEY COUNT) = K STAR(KEYCOUNT) = A REDSTAR(KEYCOUNT) = A ! REDKEYS = REDKEYS . "&" UNLESS REDKEYS = "" ! IF L > 2 AND B = 0 START ; ! make a 'reduced' version RED KEY FLAG = 1 K = REDUCED(BEFORE) REDKEY(KEYCOUNT) = K REDKEYS = REDKEYS . "*" . K . "*" REDSTAR(KEYCOUNT) = 1 FINISH ELSE REDKEYS = REDKEYS . KEY AS GIVEN REPEAT ! IF QUERY = YES START CYCLE J = 1, 1, KEY COUNT IF RED KEY FLAG = 1 START IF REDSTAR(J) = 0 THEN SPACE ELSE PRINTSYMBOL('*') PRINTSTRING(RED KEY(J)) SPACES(2) FINISH IF STAR(J) = 0 THEN SPACE ELSE PRINTSYMBOL('*') PRINTSTRING(KEY(J)) NEWLINE REPEAT FINISH ! !----------------------------------------------------------------------- RED REF COUNT = FINDREFS(H, RED KEY, KEY, REDSTAR, STAR, RED REFS, REFS, MAX REFS, KEY COUNT, RED KEY FLAG, REF COUNT) ! UNLESS TOPIC FILE = 0 START A = 0 J = 0 WHILE J < REF COUNT CYCLE J = J + 1 Q("sec: ".REFS(J)_SECTION NAME." file: ".ITOS(REFS(J)_FILENO)) IF REFS(J)_FILENO = TOPIC FILE START A = A + 1 REFS(A) = REFS(J) UNLESS A = J FINISH REPEAT REF COUNT = A ! A = 0 J = 0 WHILE J < RED REF COUNT CYCLE J = J + 1 IF RED REFS(J)_FILENO = TOPIC FILE START A = A + 1 RED REFS(A) = RED REFS(J) UNLESS A = J FINISH REPEAT RED REF COUNT = A FINISH ! -> NONE IF RED REF COUNT = 0 = REF COUNT ! -> TOO MANY IF REF COUNT > MAXREFS ! RED REF COUNT = 0 IF RED REF COUNT > MAX REFS ! -> TOO MANY IF REF COUNT = 0 = RED REF COUNT ! !----------------------------------------------------------------------- ! Now that we have finished processing the keys and refs ! monitor this successful call. MONITOR CALL(KEYS, REF COUNT + RED REF COUNT) !----------------------------------------------------------------------- ! ! REPEAT: -> NONE IF RED REF COUNT = 0 = REF COUNT ! IF REF COUNT = 1 > RED REF COUNT START J = DISPLAY REF(H, REFS(1), AFTER) -> RETURN IF J = 0 OR J = 2 -> REPEAT FINISH !----------------------------------------------------------------------- ! ! If more than one, construct a View like display of ! the references found. VDUI2 = 72; ! width VDUI3 = 0; ! lines per page, 0=hardcopy LPPAGE = 20; ! value to use for same VDUS1 = ""; ! clear screen sequence ! IF VDUI(1) > 0 START ; ! terminal type is set VDUI2 = VDUI(2) VDUI2 = VDUI2 - 1 IF VDUB(4) # 0 START STANDOUT = VDUS(17) END STANDOUT = VDUS(18) VDUI3 = VDUI(3) LPPAGE = VDUI3 - 4 IF VDUI3 > 0 LPPAGE = 20 IF LPPAGE > 20 VDUS1 = VDUS(1) . " " FINISH ! PAGE = 1 ! ! The LAYOUT procedure figures out how the references ! are to laid out on the page(s) in an attractive ! manner. MAXPAGE = LAYOUT(REF COUNT, RED REF COUNT, LPPAGE) Q("REFS ".ITOS(REFCOUNT)." REDREFS ".ITOS(REDREFCOUNT)) D: DISPLAY(H, KEYS, RED KEYS, REFS, RED REFS, PAGE, MAXPAGE, LPPAGE, REF COUNT) MENU ON DISPLAY = YES R: -> D IF MENU ON DISPLAY = NO RSTRG(AFTER) UNLESS AFTER = "" START AFTER -> (" ") . AFTER WHILE AFTER # "" AND CHARNO(AFTER, 1) = ' ' -> R IF AFTER = "" FINISH ! UCTRANSLATE(ADDR(AFTER)+1, LENGTH(AFTER)) UNLESS AFTER = "" ! IF AFTER = "Q" OR AFTER = "QUIT" START -> RETURN FINISH R1: IF AFTER = "-" START -> R IF PAGE = 1 PAGE = PAGE - 1 -> D FINISH ! IF AFTER = "" START PAGE = PAGE + 1 AND -> D IF PAGE < MAXPAGE J = 1 FINISH ELSE START J = PSTOI(AFTER) -> R UNLESS 1 <= J <= REF COUNT + RED REF COUNT FINISH ! IF J > REF COUNT START J = J - REF COUNT J = DISPLAY REF(H, RED REFS(J), AFTER) FINISH ELSE START J = DISPLAY REF(H, REFS(J), AFTER) FINISH MENU ON DISPLAY = NO -> REPEAT IF J = 3 -> RETURN IF J = 2 ! ! Ideally at this point, we would like to know if the user ! said Q to get out of VIEW and, if so, return. -> RETURN IF AFTER = "Q" -> D IF AFTER = "" -> R1 NONE: W("No references found") MONITOR CALL(KEYS, 0) -> RETURN TOO MANY: PRINTSTRING("Too many references found, ") W("please give more specific request") RETURN: SET RETURN CODE(0) END ; ! ZHELP ! ! ! EXTERNALROUTINE HELP(STRING (255)PARMS) STRING (255) SAVEMODE SAVEMODE = "" UNLESS QUERY MODE(2) = 0 C THEN SAVEMODE = MODESTR AND SETMODE("H=0") ZHELP("SUBSYS.EXTRACT", "SUBSYS.VD_CMNDS,K<HELP>", PARMS) SETMODE(SAVEMODE) UNLESS SAVEMODE = "" END ; ! HELP ! ! ! ENDOFFILE