KLIST
This utility attempts to combine the functionality of the "LIST.ITEM", "SEARCH", "COUNT" command and "SELECT" commans. It has been developed and enhanced for a 7 years now and is an invaluable aid to day to day development and system administration tasks in a Universe environment. Any bugs can be reported to me at [email protected]. There is a preamble that gives users an idea of the functions available, as well as a '-HELP' option. Compile and catalog the code and at TCL enter: KLIST -H to see what options are available. The lastest (5th December, 2014) version is the last before I retire. It has the following extra functions added to it: 1. Use of '...' in file, record and string masks. 2. Use of PERL regular expressions (requires REGEXP UVBasic function) in string searches. 3. Expansion of values in fields and subvalues in values on a global and individual field/value basis. 4. Conversion of internal dates to external format on a global and individual field/value/subvalue basis. 5. Display of specific fields only 6. Prompts for missing command line parameters (UVAccount, File, Record masks)
The code:
* -*- mode:unibasic -*-
********************************************************************************
* Programme - KLIST
*
* Version 4.0
*
* Author - Ken Ford Date - 7th March, 2008
*
* Description -
* This programme lists selected records or optionally fields withing records
* optionally expanding selected values and subvalues and optionally converting
* potential internal dates. Records can be selected by record mask within file
* mask, optionally within Universe account. A string mask can be used to narrow
* down which records to list, and matching fields only within a record can be
* listed. Universe Retrieve phrases can be used in place of record masks as well.
* Also, a record count or keys only can be listed.
* This programme optionally combines the functionality of the following
* Universe commands:
* SELECT
* COUNT
* LIST.ITEM
* SEARCH
* ED
* COMO
* GET.LIST
*
* Modifications -
* 16/3/08 Added '-V' option.
* 26/3/08 Added '-M' option
* 27/3/08 Changed '-Q' option to consider Q-pointer references only if
* F-pointer reference returns no record VOC item file ID.
* 28/3/08 Use '-M' option with string-mask to print
* only lines containing a match. Enable placing of options either
* before or after masking arguments.
* 17/4/08 Default file selection to F-pointer references, considering Q-pointer
* references only if no F-pointer match/es; force consideration of
* pointer references if '-Q' present; limit to F-pointer references
* if '-F' present.
* 3/7/08 Allow REC.RESPONSE to be the name of a &SAVEDLIST& record of keys.
* 12/12/08 Added '-Dn[,n]' option to convert dates to external format.
* 24/12/08 Enhanced '-V' option so that if ',S' is appended, sub-values are
* also expanded.
* 20/5/09 Enabled running on active select list if file is in current account
* 8/12/09 Introduced '-COMO' command line option to capture output in a COMO
* file 'KLIST.COMO'
* 25/5/11 Restructured code; fixed bug in string matching; new argument '-nn'
* to limit no. of records to list.
* 2/6/14 New option '-NO.ERR' to supress error messages.
* 27/11/14 New option '-F' or '-A' to print specific fields/attributes;
* Revised option '-V[,S]' to enable expanding values in specific
* fields and subvalues in specific values;
* Revised option '-D' to enable specifying fields, values and subvalues
* for potential date conversion;
* Prevented listing of empty values and subvalues where appropriate;
* New option '-RE' to enable search string in PERL RE form
*
********************************************************************************
*
PROMPT ''
PRINT '[KLIST v4.1 5/12/2014]'
DEFFUN REGEXP(STRING.OBJ,RE) ;* Define UVBasic function
IF INDEX(@SENTENCE,'-DEBUG',1) THEN DEBUG.ON = @TRUE ELSE DEBUG.ON = @FALSE
*
GOSUB INITIALISATION
*
GOSUB GET.OPTIONS
*
ACCOUNT.CNT = DCOUNT(ACCOUNT,@FM)
FOR I = 1 TO ACCOUNT.CNT
GOSUB PROCESS.UV.ACCOUNT ; * Process Universe Account
NEXT I
*
GOSUB FINALISATION
*
STOP
*
*================================================================================
*
PROCESS.UV.ACCOUNT:
*
* Processing of all (or default) Universe account/s instances.
*
CMD = ''
EXPR = ''
IF PAUSE THEN
PRINTLINE = 'Account: ':ACCOUNT<I>'30L':' <Enter>(=Continue)[[/END]](=Stop) : '
GOSUB PRINT.LINE
INPUT RESPONSE
IF RESPONSE = 'END' THEN STOP
END
*---- Check that Universe account exists.
UV.ACCOUNT = RAISE(TRANS('UV.ACCOUNT',ACCOUNT<I>,-1,'X'))
EXEC 'SH -c "ls -d ':UV.ACCOUNT<11>:'"' CAPTURING OUTPUT
IF INDEX(OUTPUT,'does not exist',1) THEN
PRINT 'Universe Account ':ACCOUNT<I>:' does not exist'
RETURN
END
HUSH ON
EXEC 'SET.FILE ':ACCOUNT<I>:' VOC ':VOC.PTR CAPTURING OUTPUT
HUSH OFF
IF DICT.FILE THEN
FILE.RESPONSE = FIELD(FILE.RESPONSE,' ',2)
IF FILE.RESPONSE = '_' THEN FILE.RESPONSE = '' ; *@@@@#KF-081006
END
DICT = ''
*---- Determine which files to consider within the Universe account.
BEGIN CASE
CASE FILE.RESPONSE = 'A' OR FILE.RESPONSE = 'ALL' OR FILE.RESPONSE = ''
IF FPTR.ONLY THEN EXPR = ' WITH F1 LIKE F...' ELSE
IF QPTR.ONLY THEN EXPR = ' WITH F1 LIKE Q...' ELSE
EXPR = ' WITH F1 LIKE F... OR WITH F1 LIKE Q...'
END
END
CMD = 'SELECT ':VOC.PTR:EXPR
HUSH ON
EXEC CMD CAPTURING OUTPUT
HUSH OFF
CASE TRANS(VOC.PTR,FILE.RESPONSE,0,'X')
PTR.TYPE = TRANS(VOC.PTR,FILE.RESPONSE,1,'X')[1,1]
IF PTR.TYPE MATCHES 'F':@VM:'Q' THEN
IF QPTR.ONLY THEN
IF (PTR.TYPE = 'Q') THEN
FILE = FILE.RESPONSE
END ELSE FILE = ''
END
IF FPTR.ONLY THEN
IF (PTR.TYPE = 'F') THEN
FILE = FILE.RESPONSE
END ELSE FILE = ''
END
FILE = FILE.RESPONSE
END ELSE
PRINT "'":FILE.RESPONSE:"' is not a file or file pointer"
RETURN
END
CASE 1
IF INDEX(FILE.RESPONSE,'...',1) THEN
CMD = 'SELECT ':VOC.PTR:' LIKE ':FILE.RESPONSE
END ELSE
CMD = 'SELECT ':VOC.PTR:' = "':FILE.RESPONSE:'"'
END
IF FPTR.ONLY THEN EXPR = 'SELECT ':VOC.PTR:' WITH F1 LIKE F...' ELSE
IF QPTR.ONLY THEN EXPR = 'SELECT ':VOC.PTR:' WITH F1 LIKE Q...' ELSE
EXPR = 'SELECT ':VOC.PTR:' WITH F1 LIKE F... OR WITH F1 LIKE Q...'
END
END
CMD = EXPR:@FM:CMD
HUSH ON
EXEC CMD CAPTURING OUTPUT
HUSH OFF
END CASE
IF CMD THEN
FILE = ''
LOOP WHILE READNEXT ID DO
FILE<-1> = ID
REPEAT
END
FILE.CNT = DCOUNT(FILE,@FM)
IF FILE.CNT = 0 THEN
PRINTLINE = 'No File matches file-mask "':FILE.RESPONSE:'" in Account ':ACCOUNT<I>
GOSUB PRINT.LINE
END
SAVE.LIST = 1
*
FOR J = 1 TO FILE.CNT
GOSUB PROCESS.FILE.IN.ACCOUNT ; * Process File within Account
NEXT J
*
RETURN
*
*--------------------------------------------------------------------------------
*
PROCESS.FILE.IN.ACCOUNT:
*
* Processing of all selected file instances within a Universe account
*
*---- Filter out object code files.
IF FIELD(FILE<J>,'.',DCOUNT(FILE<J>,'.')) = 'O' THEN RETURN
EXEC 'SET.FILE ':ACCOUNT<I>:' ':FILE<J>:' ':FILE.PTR CAPTURING OUTPUT
IF DICT.FILE THEN
DICT = 'DICT '
END ELSE
DICT = ''
END
FILE.HDR.PRINTED = 0
OPEN FILE.PTR TO FILE.FV ELSE
IF NOT(NO.ERROR) THEN PRINT 'Could not access file ':FILE<J>:' in Account ':ACCOUNT<I>
HUSH ON
EXEC 'DELETE VOC ':FILE.PTR
HUSH OFF
RETURN
END
IF FILEINFO(FILE.FV,3) = 4 THEN
IF LEN(DICT) THEN RETURN
DIR.FILE = 1
END ELSE
DIR.FILE = 0
END
CLOSE FILE.FV
IF TRANS(VOC.PTR,FILE<J>,1,'X')[1,1] = 'Q' THEN QPTR = 1 ELSE QPTR = 0
RECORD = ''
RECORD.SAVED = ''
CMD = ''
* --- Determine which records to consider within a file in a Universe account.
IF SAMPLE THEN SAMPLE = 'SAMPLE ':SAMPLE ELSE SAMPLE = ''
BEGIN CASE
CASE REC.RESPONSE = 'A' OR REC.RESPONSE = 'ALL' OR REC.RESPONSE = '' OR REC.RESPONSE = '...'
IF SORT.KEYS THEN CMD = 'SSELECT ':DICT:FILE.PTR
ELSE CMD = 'SELECT ':DICT:FILE.PTR
CASE NOT(INDEX(REC.RESPONSE,'[',1)) AND NOT(INDEX(REC.RESPONSE,']',1)) AND NOT(INDEX(REC.RESPONSE,'...',1)) AND TRANS(DICT:FILE.PTR,REC.RESPONSE,0,'X')
CMD = 'SELECT ':DICT:FILE.PTR:' "':REC.RESPONSE:'"'
CASE FIELD(REC.RESPONSE,' ',1) MATCHES 'WITH':@VM:'LIKE'
STRING.RESPONSE = REC.RESPONSE
REC.RESPONSE = '...'
CMD = 'SELECT ':DICT:FILE.PTR:' LIKE "':REC.RESPONSE:'"'
CASE 1
IF NOT(RECORD.LIST) THEN
IF NOT(TRANS('&SAVEDLISTS&',REC.RESPONSE,0,'X')) THEN
IF SORT.KEYS THEN CMD = 'SSELECT ':DICT:FILE.PTR:' LIKE "':REC.RESPONSE:'"'
ELSE CMD = 'SELECT ':DICT:FILE.PTR:' LIKE "':REC.RESPONSE:'"'
END ELSE
RECORD.LIST = 1
CMD = 'GET.LIST ':REC.RESPONSE
END
END ELSE
CMD = 'GET.LIST ':LIST.NAME
END
END CASE
IF STRING.RESPONSE AND NOT(RE.MATCHING) THEN
BEGIN CASE
CASE FIELD(STRING.RESPONSE,' ',1) = 'WITH'
CMD := ' AND ':STRING.RESPONSE
CASE FIELD(STRING.RESPONSE,' ',1) = 'LIKE'
CMD := ' AND WITH EVAL "@RECORD" ':STRING.RESPONSE
CASE NOT(INDEX(STRING.RESPONSE,'...',1))
IF STRING.RESPONSE MATCHES '...[...':@VM:'...]...' THEN
CMD := ' WITH EVAL "@RECORD" = "':STRING.RESPONSE:'"'
STRING.RESPONSE = TRIM(TRIM(STRING.RESPONSE,'[','L'),']','T')
END ELSE
CMD := ' WITH EVAL "@RECORD" = "[':STRING.RESPONSE:']"'
END
CASE INDEX(STRING.RESPONSE,'...',1)
CMD := ' WITH EVAL "@RECORD" LIKE ':STRING.RESPONSE
END CASE
END
CMD := ' ':SAMPLE
EXEC CMD CAPTURING OUTPUT
IF NOT(OUTPUT MATCHES "...record(s)...selected...to...") AND NOT(NO.ERROR) THEN
PRINT 'Error selecting records from file ':FILE<J>:' : '
FOR OUTPUT.INX = 1 TO DCOUNT(OUTPUT,@FM)
IF OUTPUT<OUTPUT.INX> ELSE CONTINUE
PRINT OUTPUT<OUTPUT.INX>
NEXT OUTPUT.INX
END
K.MAX = @SELECTED
IF COUNT.RECS THEN
PRINTLINE = "Records matching record-mask and/or string-mask in file ":DICT:FILE<J>:" : ":K.MAX
GOSUB PRINT.LINE
RETURN
END
IF @SELECTED > 0 THEN
RECS.PRINTED = 0
IF K.MAX > 10 THEN WARN.USER = 1 ELSE WARN.USER = 0
*---------- Process Records in File within Account
FOR K = 1 TO K.MAX
READNEXT ID ELSE EXIT
RECORD<-1> = ID
*------------- Process records in groups of 10 to save waiting time.
IF NOT(MOD(K,10)) THEN
GOSUB LIST.RECORD.GROUP ; * List records within file within account.
RECORD = ''
END
NEXT K
IF LEN(RECORD) THEN
GOSUB LIST.RECORD.GROUP
END
PRINT ''
PRINTLINE = 'Records listed in file ':DICT:FILE<J>:' : ':K.MAX
GOSUB PRINT.LINE
IF LIST.NAME THEN EXEC 'DELETE.LIST ':LIST.NAME
END
*
RETURN
*
*--------------------------------------------------------------------------------
*
LIST.RECORD.GROUP:
*
* Processing a group of 10 or fewer records within a file within a Universe account
*
RECORD.CNT = DCOUNT(RECORD,@FM)
IF RECORD.CNT = 0 THEN
PRINTLINE = "No Record matches record-mask and/or string-mask in a/c ":ACCOUNT<I>
GOSUB PRINT.LINE
END
LAST.SAVEDLIST = ''
IF KEYS.ONLY THEN
OUTPUT = RECORD
RECORD.CNT = 1
END
FOR L = 1 TO RECORD.CNT
GOSUB LIST.RECORD
NEXT L
RETURN
*
*--------------------------------------------------------------------------------
*
LIST.RECORD:
*
* Listing a record within a file within a Universe account.
*
IF NOT(FILE.HDR.PRINTED) THEN
IF QPTR THEN QPTR = '(Q-pointer)' ELSE QPTR = ''
PRINTLINE = ''
GOSUB PRINT.LINE
PRINTLINE = 'Account: ':ACCOUNT<I>:' - File: ':DICT:FILE<J>:' ':QPTR
GOSUB PRINT.LINE
IF KEYS.ONLY THEN
PRINTLINE = ''
GOSUB PRINT.LINE
END
LAST.SAVEDLIST = ACCOUNT<I>:@FM:DICT:FILE<J>
FILE.HDR.PRINTED = 1
END
REC.HDR.PRINTED = @FALSE
IF NOT(KEYS.ONLY) THEN
RECORD.PTR = RECORD<L>
CMD = 'LIST.ITEM ':DICT:FILE.PTR:' "':RECORD.PTR:'" NOPAGE COL.HDR.SUPP'
IF COMO AND COMO.ON THEN
COMO.ON = @FALSE
HUSH ON
EXEC 'COMO OFF'
EXEC 'SH -c "cat \&COMO\&[[/KLIST]].PART.COMO >> \&COMO\&[[/KLIST]].COMO"'
EXEC 'DELETE &COMO& KLIST.PART.COMO'
HUSH OFF
END
EXEC CMD CAPTURING OUTPUT
IF COMO THEN
COMO.ON = @TRUE
HUSH ON
EXEC 'COMO ON KLIST.PART.COMO'
HUSH OFF
END
IF (STRING.RESPONSE = '') THEN
OUTPUT = OUTPUT[INDEX(OUTPUT,DICT:FILE.PTR,1),99999]
OUTPUT = CHANGE(OUTPUT,DICT:FILE.PTR,DICT:FILE<J>,-1)
END ELSE
IF RE.MATCHING THEN
*------------- Check for a match on a PERL regular expression within the record.
STRING.OBJ = CHANGE(FIELD(OUTPUT,@FM,2,999),@FM,'')
IF LEN(STRING.OBJ) < 257 THEN
IF RE[1,1] MATCHES "'":@VM:'"' THEN
RE = RE[2,LEN(RE)-2]
END
RESPONSE = REGEXP(STRING.OBJ,RE)
IF TEST THEN
PRINT RESPONSE<1>
PRINT RESPONSE<2>
END
IF NOT(RESPONSE<1>) THEN RETURN
END
END
END
RECORD.SAVED := @FM:RECORD<L>
END
LINE.CNT = DCOUNT(OUTPUT,@FM)
IF DICT.FILE AND OUTPUT<5> = '001 I' THEN I.TYPE = @TRUE ELSE I.TYPE = @FALSE
FOR M = 1 TO LINE.CNT
IF I.TYPE AND M > 13 THEN RETURN
GOSUB PROCESS.LINE ;* Process each line in the record listing output.
NEXT M
*
RETURN
*
*--------------------------------------------------------------------------------
*
PROCESS.LINE:
*
* Processing a line within listing of a record within a file within a Universe account.
*
IF KEYS.ONLY THEN
RECORD.PTR = OUTPUT<M>
PRINTLINE = OUTPUT<M>
GOSUB PRINT.LINE
END ELSE
IF OUTPUT<M> = '' THEN RETURN
LINE.IN.SCREEN.OUTPUT = MOD(M,@CRTHIGH)
IF LINE.IN.SCREEN.OUTPUT = 1 THEN RETURN
IF INDEX(OUTPUT<M>,'LIST.ITEM ',1) THEN RETURN
IF INDEX(OUTPUT<M-1>:OUTPUT<M>,' PAGE ',1) THEN RETURN
IF TRIM(OUTPUT<M>) = RECORD.PTR THEN
REC.HDR = 'Record: ':OUTPUT<M>
RETURN
END
*------- Check for a match within the current output line on either a specified string,
* or if supplied, a PERL regulare expression.
IF NOT(FULL.ITEM) THEN
IF RE.MATCHING THEN
IF NOT(REGEXP(OUTPUT<M>,RE)<1>) THEN RETURN
END ELSE
IF LEN(STRING.RESPONSE) THEN
IF NOT(OUTPUT<M> MATCHES '...':STRING.RESPONSE:'...') THEN RETURN
END
END
END
*------- Combine split lines in output from LIST.ITEM
N = 1
LOOP WHILE NOT((M+N) > LINE.CNT) DO
IF OUTPUT<M+N>[1,4] = ' ' THEN
OUTPUT<M> := TRIM(OUTPUT<M+N>)
N += 1
END ELSE EXIT
REPEAT
LINE = OUTPUT<M>
M += (N-1)
OUTPUT.FIELD.NO = TRIM(FIELD(LINE,' ',1),'0','L')
LINE = LINE[5,999]
*------- Check whether field is to be printed or not.
PRINT.FIELD = @FALSE
IF LEN(FIELDS) THEN
RECORD.POS = 0
LOCATE(OUTPUT.FIELD.NO, FIELDS; RECORD.POS) THEN
PRINT.FIELD = @TRUE
END
END ELSE
PRINT.FIELD = @TRUE
END
IF PRINT.FIELD THEN
IF NOT(REC.HDR.PRINTED) THEN
REC.HDR.PRINTED = @TRUE
PRINTLINE = ''
GOSUB PRINT.LINE
PRINTLINE = REC.HDR
GOSUB PRINT.LINE
RECS.PRINTED += 1
END
IF DATE.CONV THEN
*------------- Check each subvalue within each value within the current output line.
CONVERSIONS = @FALSE
MV.MAX = DCOUNT(LINE<1>,@VM)
IF MV.MAX = 0 THEN
TRY.DATE = LINE<1>
IF LEN(TRY.DATE) THEN GOSUB TRY.CONVERTING
END ELSE
FOR MV.INX = 1 TO MV.MAX
THIS.VAL = LINE<1,MV.INX>
SV.MAX = DCOUNT(THIS.VAL<1,1>,@SM)
IF SV.MAX = 0 THEN
TRY.DATE = THIS.VAL
IF LEN(TRY.DATE) THEN GOSUB TRY.CONVERTING
END ELSE
FOR SV.INX = 1 TO SV.MAX
TRY.DATE = THIS.VAL<1,1,SV.INX>
IF LEN(TRY.DATE) THEN GOSUB TRY.CONVERTING
NEXT SV.INX
END
NEXT MV.INX
END
IF CONVERSIONS THEN OUTPUT<M> = OUTPUT<M>[1,4]:LINE
END
*
IF LEN(EXP.MVS) AND (INDEX(LINE,@VM,1) OR INDEX(LINE,@SM,1)) THEN
*------------- Field is multivalued, so check whether expansion of values is required or not.
EXPAND.MV = @FALSE
MV.FIELD.POS = 0
LOCATE(OUTPUT.FIELD.NO, EXP.MVS; MV.FIELD.POS) THEN
EXPAND.MV = @TRUE
END ELSE
IF EXP.MVS<1> = 0 THEN
EXPAND.MV = @TRUE
MV.FIELD.POS = 1
END
END
IF EXPAND.MV THEN
GOSUB EXPAND.MVS
END ELSE
IF LEN(LINE) > 0 THEN
PRINTLINE = OUTPUT.FIELD.NO"R%3":' ':LINE
GOSUB PRINT.LINE
END
END
END ELSE
IF LEN(LINE) > 0 THEN
PRINTLINE = OUTPUT.FIELD.NO"R%3":' ':LINE
GOSUB PRINT.LINE
END
END
END ELSE PRINT.FIELD = @FALSE
END
*
RETURN
*
*--------------------------------------------------------------------------------
*
TRY.CONVERTING:
*
* If the value in the field looks like an internal date and if it is, convert it.
*
IF NUM(TRY.DATE) THEN
IF INT(TRY.DATE) AND (TRY.DATE > 9999) AND (TRY.DATE < 20000) THEN
*---------- See if this date is to be date-converted
FOR CONV.INX = 1 TO CONV.SPECIFIERS
IF (CONV.FIELDS<CONV.INX> = 0) OR (CONV.FIELDS<CONV.INX> = OUTPUT.FIELD.NO) THEN
IF (CONV.MVS<CONV.INX> = 0) OR (CONV.MVS<CONV.INX> = MV.INX) THEN
IF (CONV.SVS<CONV.INX> = 0) OR (CONV.SVS<CONV.INX> = SV.INX) THEN
EXT.DATE = OCONV(TRY.DATE,'D4')
IF ICONV(EXT.DATE,'D4') = TRY.DATE THEN
LINE<1,MV.INX,SV.INX> = EXT.DATE
CONVERSIONS = @TRUE
END
END
END
END
NEXT CONV.INX
END
END
*
RETURN
*
*--------------------------------------------------------------------------------
*
EXPAND.MVS:
*
* Expand multivalues in a field in a record in a file within a Universe account
*
MV.MIN = 1
MV.MAX = DCOUNT(LINE,@VM)
FOR MV.INX = MV.MIN TO MV.MAX
IF (MV.MAX > 1 OR INDEX(LINE,@SM,1)) AND MV.INX = 1 THEN ; * Allow for sub-valued single multivalue field.
PRINTLINE = OUTPUT.FIELD.NO"R%3":' Multivalues:'
GOSUB PRINT.LINE
END
CURRENT.MV = LINE<1,MV.INX>
IF LEN(EXP.SVS) AND INDEX(CURRENT.MV,@SM,1) THEN
*---------- Value contains subvalues, so check whether expansion of subvalues is required or not.
EXPAND.SV = @FALSE
SV.VALUE.POS = 0
LOCATE(MV.INX, EXP.SVS<MV.FIELD.POS>; SV.VALUE.POS) THEN
EXPAND.SV = @TRUE
END ELSE
IF EXP.SVS<MV.FIELD.POS> = 0 THEN
EXPAND.SV = @TRUE
SV.VALUE.POS = 1
END
END
IF EXPAND.SV THEN
SV.MIN = 1
SV.MAX = DCOUNT(CURRENT.MV,@SM)
FOR SV.INX = SV.MIN TO SV.MAX
IF SV.MAX > 1 AND SV.INX = 1 THEN
PRINTLINE = SPACES(4):MV.INX"3R%3":' Subvalues:'
GOSUB PRINT.LINE
END
CURRENT.SV = CURRENT.MV<1,1,SV.INX>
IF LEN(CURRENT.SV) THEN
PRINTLINE = SPACES(8):SV.INX"3R%3":' ':CURRENT.SV
GOSUB PRINT.LINE
END
NEXT SV.INX
END ELSE
IF LEN(CURRENT.MV) THEN
PRINTLINE = SPACES(4):MV.INX"3R%3":' ':CURRENT.MV
GOSUB PRINT.LINE
END
END
END ELSE
IF LEN(CURRENT.MV) THEN
PRINTLINE = SPACES(4):MV.INX"3R%3":' ':CURRENT.MV
GOSUB PRINT.LINE
END
END
NEXT MV.INX
RETURN
*
*--------------------------------------------------------------------------------
*
PRINT.LINE:
*
* Print a line of output
*
IF COMO AND NOT(COMO.ON) THEN
COMO.ON = @TRUE
HUSH ON
EXEC 'COMO ON KLIST.PART.COMO'
HUSH OFF
END
IF (LINES.PRINTED > (@CRTHIGH-3)) AND NOT(NOSTOP) THEN
PRINT
PRINT 'Continue? Y(es)=default[[/N]](oStop)[[/Q]](uit)[[/END]] ... : ':
INPUT RESPONSE
BEGIN CASE
CASE UPCASE(RESPONSE) = 'END' OR UPCASE(RESPONSE) = 'Q'
PRINT
STOP
CASE UPCASE(RESPONSE) = 'N'
NOSTOP = 1
IF WARN.USER THEN
PRINT 'There are ':(K.MAX-RECS.PRINTED):' more records to go. List them ALL? (Y[[/N]]=default) : ':
INPUT RESPONSE
IF UPCASE(RESPONSE)[1,1] # 'Y' THEN NOSTOP = 0
END
CASE 1
NULL
END CASE
PRINT 'Account: ':ACCOUNT<I>:' - File: ':DICT:FILE<J>:' ':QPTR:' - Record: ':RECORD.PTR:' (continued ... )'
PRINT
LINES.PRINTED = 2
END
PRINT PRINTLINE
LINES.PRINTED += 1
RETURN
*
*--------------------------------------------------------------------------------
*
INITIALISATION:
*
IF INDEX(@SENTENCE,'-H',1) THEN
PRINT 'KLIST [<A/c-mask>] [<File-mask> <Record-mask>] [<String-mask>][<Options>]'
PRINT 'Options - '
PRINT " -An or -Fn List Attribute[[/Field]] 'n' only. Note: Multiple fields can be"
PRINT ' specified delimited by ";"'
PRINT ' -C[OUNT] Count of records in a file'
PRINT " -D[f][,[v][,[s]]]"
PRINT " Convert date/s in attributes/fields, values and subvalues."
PRINT ' Note: A optional field no., optional value no., and an'
PRINT ' optional subvalue no. can be included with a comma delimiter.'
PRINT " Multiple 'D,,' instances are permitted, delimited by ';'"
PRINT ' -E[D] Execute Line Editor using items selected from last used file'
PRINT ' Note: Last selection is in saved list KLIST.<Unix-login-id>'
PRINT ' -K[EYS] Keys to records only are listed.'
PRINT ' -M[ATCHES] Matching lines only in records selected are listed.'
PRINT ' -N[OSTOP] Eliminate Header and End-of-Screen pause.'
PRINT ' -RE List only lines in records matching a PERL Regular Expression.'
PRINT ' -S[ORT] Sort by record ID'
PRINT ' -V[f][,S[v]] Expand Values in attributes/fields (and optionally Subvalues'
PRINT ' in values)'
PRINT " Note: A Field[[/Attribute]] no. can follow 'V' to limit expansions."
PRINT " A Value no. can follow 'S' to limit expansions."
PRINT " Multiple 'V,S' instances are permitted delimited by ';'."
PRINT ''
PRINT 'Press <Enter> to continue ...':
INPUT RESPONSE
PRINT " -n List a sample of 'n' records only."
PRINT ''
PRINT 'Less commonly used Options -'
PRINT ' -COMO Capture output to KLIST.COMO command output file'
PRINT ' -F[PTRS] Include only files referenced by F-pointers'
PRINT ' -NO.ERR Eliminate messages about file access restrictions'
PRINT ' -P[AUSE] Pause at each A/c header'
PRINT ' -Q[PTRS] Include only files referenced by Q-pointers'
PRINT ''
PRINT 'Note: A command line mask item containing one or more spaces requires'
PRINT " the whole mask item to be quoted. "
PRINT " E.g. 'WITH EVAL ":'"@RECORD<48,1>"':' # ""':"'"
PRINT ' Dictionary item names can be used in field listing expressions.'
PRINT " Either '[' and/or ']' masks OR '...' masks can be used."
PRINT ''
PRINT " A/c-mask 'A'|'' = All Accounts / Default = Current Account"
PRINT " File-mask '' = All files in an Account / '[',']' and '...' allowed"
PRINT " Record-mask ''|null = All records in file in Account / 'WITH' clause allowed"
PRINT " String-mask '[',']' and '...' allowed / 'WITH' clause allowed / PERL Regular"
PRINT " Expression[[/Record]]-selection-phrase based on field content"
PRINT ''
PRINT 'Press <Enter> to continue ...':
INPUT RESPONSE
PRINT ' Examples :'
PRINT " KLIST FMC.CON... ...FTRIG... -N -V,S -COMO"
PRINT " Captures in KLIST.COMO a list of all records with keys containing 'FTRIG'"
PRINT " in all files with names containing 'FMC.CON' in the current Account, with"
PRINT " expansion of all values and subvalues in multivalued fields"
PRINT " KLIST FMC.TEST DICT APP.INDEX -N -K -S"
PRINT " List keys only in sorted order in the dictionary of file APP.INDEX in the"
PRINT " Account FMC.TEST."
PRINT " KLIST TRAN ...S9... -A17 -V,S -N -5"
PRINT " List 5 samples of records with keys containing 'S9' in the TRAN file, "
PRINT " displaying Attribute 17 only, expanding all values and subvalues"
PRINT " KLIST VOC LOGIN '(kford)' -RE"
PRINT " List lines in the 'LOGIN' record in the 'VOC' file in the current Account"
PRINT " that match the PERL regular expression string mask."
PRINT " KLIST TRAN ...S9... -V,S -N -2 -D17,2,1"
PRINT " List 2 samples of records with keys containing 'S9' in the TRAN file, "
PRINT " displaying all fields, expanding all values and subvalues, and converting"
PRINT " the date (if it is one) in field/attribute 17, value 2, subvalue 1."
STOP
END
IF TRANS('VOC','UV.ACCOUNT',0,'X') = '' THEN
HUSH ON
DATA 'Q'
DATA 'UV'
DATA 'UV.ACCOUNT'
DATA ''
DATA 'FI'
EXEC 'ED VOC UV.ACCOUNT'
HUSH OFF
END
AC.RESPONSE = ''
ACCOUNT = ''
ARG = ''
ARGS = ''
CMD.LINE = CHANGE(@SENTENCE,' ',@FM)
COMO = @FALSE
COMO.ON = @FALSE
COUNT.RECS = 0
DATE.CONV = 0
DICT.FILE = 0
EDIT.LIST = 0
ELT.CNT = 0
EXP.MVS = ''
EXP.SVS = ''
EXPECT.RE = @FALSE
FIELDS = ''
FILE = ''
FILE.PTR = 'KLIST.FILE'
FILE.RESPONSE = ''
FPTR.ONLY = 0
FULL.ITEM = 1
ITEM = 1
KEYS.ONLY = 0
LAST.SAVEDLIST = ''
LEFTOVERS = ''
LINE = ''
LINES.PER.PAGE = @CRTHIGH
LINES.PRINTED = 0
LIST.NAME = ''
NO.ERROR = @FALSE
NOSTOP = 0
PAUSE = 0
QPTR.ONLY = 0
RE = ''
RE.MATCHING = @FALSE
REC.HDR = ''
REC.HDR.PRINTED = @FALSE
REC.RESPONSE = ''
RECORD = ''
RECORD.LIST = 0
RECORD.SAVED = ''
RECS.PRINTED = 0
SAMPLE = 0
SAVE.LIST = 0
SORT.KEYS = 0
SPECIFIC.FIELDS = ''
STRING.RESPONSE = ''
SVAL.POS = 0
TEST = 0
VAL.POS = 0
VOC.PTR = 'KLIST.VOC'
WARN.USER = 0
RETURN
*
*--------------------------------------------------------------------------------
*
GET.OPTIONS:
*
LOOP
REMOVE ELT FROM CMD.LINE SETTING DELIM
ELT.CNT += 1
IF ELT = 'RUN' OR ELT = 'RAID' THEN
REMOVE ELT FROM CMD.LINE SETTING DELIM
ELT.CNT += 1
CONTINUE
END
IF ELT[1,5] = 'KLIST' THEN CONTINUE
IF NOT(ELT) THEN
IF NOT(DELIM) THEN EXIT
ELSE CONTINUE
END
*------- Parse command line options.
BEGIN CASE
CASE ELT[1,2] = '-A' ;* List specific attribute(s)/field(s) only
FIELDS = CHANGE(ELT[3,99],';',@FM)
CASE ELT[1,5] = '-COMO' ;* Capture to a command output file
COMO = @TRUE
HUSH ON
EXEC 'DELETE &COMO& KLIST.COMO'
HUSH OFF
CASE ELT[1,2] = '-C' ;* Count of records in a file
COUNT.RECS = 1
CASE ELT[1,2] = '-D' ;* Convert dates to external format
DATE.CONV = @TRUE
*---------- Create arrays of field, value and subvalue positions for data conversion
* Note: '0' means convert all fields/values/subvalues; null means no conversion
*
* Examples:
* '-D1;2,1;2,2,;3;4'
* This produces 3 arrays internally, thus:
* Field array - 1:@FM:2:@FM:2:@FM:3:@FM:4
* Value array - 0:@FM:1:@FM:2:@FM:0:@FM:0
* [[SubValue]] array - 0:@FM:0:@FM:0;@FM:0:@FM:0
* This is interpreted to mean:
* Date convert internal dates in field 1 (all values and subvalues, if any)
* internal dates in field 2, value 1
* field 2, value 2 (all subvalues, if any)
* field 3 (all values and subvalues, if any)
* field 4 (all values and subvalues, if any)
CONV.FIELDS = ''
CONV.MVS = ''
CONV.SVS = ''
SETS = CHANGE(ELT[3,99],';',@FM)
LOOP REMOVE SUBELT FROM SETS SETTING ELT.DELIM
IF LEN(SUBELT) THEN
FIELD.POS = FIELD(SUBELT,',',1)
IF LEN(FIELD.POS) THEN
CONV.FIELDS<-1> = FIELD.POS
END ELSE
CONV.FIELDS<-1> = 0
END
VAL.POS = FIELD(SUBELT,',',2)
IF LEN(VAL.POS) THEN
CONV.MVS<-1> = VAL.POS
END ELSE
CONV.MVS<-1> = 0
END
SVAL.POS = FIELD(SUBELT,',',3)
IF LEN(SVAL.POS) THEN
CONV.SVS<-1> = SVAL.POS
END ELSE
CONV.SVS<-1> = 0
END
END
WHILE ELT.DELIM DO
REPEAT
IF NOT(LEN(CONV.FIELDS)) THEN
CONV.FIELDS = 0
CONV.MVS = 0
CONV.SVS = 0
END
CONV.SPECIFIERS = DCOUNT(CONV.FIELDS,@FM)
CASE ELT[1,2] = '-E' ;* Edit the listed records
EDIT.LIST = 1
CASE ELT[1,5] = '-FPTR' ;* List only files with 'F' pointers
FPTR.ONLY = 1
CASE ELT[1,2] = '-F' ;* List specific field(s)/attribute(s) only
FIELDS = CHANGE(ELT[3,99],';',@FM)
CASE ELT[1,2] = '-K' ;* List only keys in a file
KEYS.ONLY = 1
CASE ELT[1,2] = '-M' ;* List only lines in record that match string
FULL.ITEM = 0
CASE ELT[1,7] = '-NO.ERR' ;* No errors listed
NO.ERROR = @TRUE
CASE ELT[1,2] = '-N' ;* No stopping after a screen of output
NOSTOP = 1
EXEC 'TERM ,9999' CAPTURING OUTPUT
CASE ELT[1,2] = '-P' ;* Pause on change of Universe account
PAUSE = 1
CASE ELT[1,5] = '-QPTR' ;* List only files with 'Q' pointers
QPTR.ONLY = 1
CASE ELT[1,3] = '-RE' ;* Search records using a PERL regular expression
RE.MATCHING = @TRUE
FULL.ITEM = @FALSE
CASE ELT[1,2] = '-S' ;* Sort listed output by record key
SORT.KEYS = 1
CASE ELT[1,2] = '-T' ;* Testing (debug) mode
TEST = 1
DEBUG
CASE ELT[1,2] = '-V' ;* Expand values withing fields
*
* '-V' specifys which field or fields are to have values and optionally
* subvalues displayed'
* Valid variants of the '-V' option:
* '-V' means expand all multivalued fields
* '-Vn' means expand multivalued field "n" only
* '-V,S' means expand all multivalued fields and all subvalued
* values in each field
* '-Vn,S' means expand multivalued field "n" only and all subvalued
* values in that field
* '-Vn,Sp' means expand multivalued field "n" only and subvalues
* in value "p" of the field
* '-V,Sp' means expand all multivalued fields and subvalues in
* value "p" of each field
* '-Vn[,S[p]];q[,S[r]] ... ;[x[,S[y]]'
* represents a semi-colon delimited list of specific fields
* with optional value and subvalue expansion
* Examples:
* '-V' means expand all values in all fields.
* '-V5' means expand all values in multivalued field 5 only.
* '-V,S' means expand all values in all multivalued fields and
* all subvalued values in each such field.
* '-V5,S' means expand all values in multivalued field 5 only and
* all subvalued values in that field.
* '-V5,S5' means expand multivalued field 5 only and subvalues in
* value 5 in that field.
* '-V5,S;7;9,S;12,S4'
* means expand multivalued fields 5, 7, 9 & 12, and
* all subvalues in all values in fields 5 & 9, and subvalues
* in value 4 if field 12.
*
* Note: It is valid to have multiple "-Vn" options, so the last example could be
* expressed as '-V5,S -V7 -V9,S -V12,S4'
*
*---------- Create arrays of value and subvalue positions for expansion
* Note: '0' indicates expand all values/subvalues; null indicates no expansion
SETS = CHANGE(ELT[3,99],';',@FM)
LOOP REMOVE SUBELT FROM SETS SETTING ELT.DELIM
IF LEN(SUBELT) THEN
VAL.POS = FIELD(SUBELT,',',1)
IF LEN(VAL.POS) THEN
EXP.MVS<-1> = VAL.POS
END ELSE
EXP.MVS<-1> = 0
END
SVAL.POS = FIELD(SUBELT,',',2)
IF LEN(SVAL.POS) THEN
SVAL.POS = FIELD(SVAL.POS,'S',2)
IF LEN(SVAL.POS) THEN
EXP.SVS<-1> = SVAL.POS
END ELSE
EXP.SVS<-1> = 0
END
END ELSE
EXP.SVS<-1> = @FM
END
END ELSE
EXP.MVS<-1> = 0
EXP.SVS<-1> = @FM
END
WHILE ELT.DELIM DO
REPEAT
CASE ELT[1,1] = '-' AND ELT[2,99] MATCHES "0N" ;* List a sample of 'n' records
SAMPLE = ELT[2,99]
CASE 1
ARGS := ELT:' '
END CASE
WHILE DELIM DO
REPEAT
CHAR.CNT = LEN(ARGS)
*---- If there is an active select list of record IDs, save it for use later.
IF SYSTEM(11) THEN
RECORDS = ''
EOI = @FALSE
LOOP
READNEXT ID ELSE EOI = @TRUE
WHILE NOT(EOI) DO
IF NOT(LEN(ID)) THEN EXIT
RECORDS<-1> = ID
REPEAT
IF LEN(RECORDS) THEN
LIST.NAME = 'KLIST.LIST.':DATE():'.':FIELD(TIME(),'.',1)
OPEN '&SAVEDLISTS&' TO SAVEDLISTS.FV THEN
WRITE RECORDS ON SAVEDLISTS.FV, LIST.NAME
END
RECORD.LIST = 1
END
END
*---- Process positional arguments from command line.
SELECT.EXPR = ''
REGEXPR = ''
ARG.CNT = 0
LOOP
ARG.CNT += 1
ARG = FIELD(ARGS,' ',ARG.CNT)
WHILE LEN(ARG) DO
IF ARG[1,1] = '"' OR ARG[1,1] = "'" THEN
ARG.DELIM = ARG[1,1]
ARG = FIELD(ARGS,ARG.DELIM,2)
ARG.CNT += COUNT(ARG,' ')
END
BEGIN CASE
CASE AC.RESPONSE = ''
BEGIN CASE
*----------- Are all Universe Accounts to be checked?
CASE ARG MATCHES 'ALL':@VM:'[]' OR ARG = '...' OR ARG = '""' OR ARG = "''"
AC.RESPONSE = 'ALL'
*----------- Is there a Universe A/c name mask in ARG?
CASE INDEX(ARG,'...',1) OR INDEX(ARG,'[',1) OR INDEX(ARG,']',1)
AC.RESPONSE = ARG
* ---------- Is there a Universe A/c with its name in ARG?
CASE TRANS('UV.ACCOUNT',ARG,0,'X') = ARG
AC.RESPONSE = ARG
*----------- Is the Universe A/c not provided and there a file dictionary specified?
CASE ARG = 'DICT'
AC.RESPONSE = @WHO
DICT.FILE = @TRUE
*----------- Is the Universe A/c not provided and there a file with its name in ARG?
CASE TRANS('VOC',ARG,0,'X') = ARG
AC.RESPONSE = @WHO
FILE.RESPONSE = ARG
CASE 1
AC.RESPONSE = '_'
END CASE
CASE FILE.RESPONSE = ''
BEGIN CASE
*----------- Are all files in the current Universe A/c to be checked?
CASE ARG MATCHES 'ALL':@VM:'[]'OR ARG = '...' OR ARG = '""' OR ARG = "''"
FILE.RESPONSE = 'ALL'
*----------- Is there a file dictionary specified in ARG?
CASE ARG = 'DICT'
DICT.FILE = @TRUE
*----------- Is there a file in the current Universe A/c with its name in ARG?
CASE TRANS('VOC',ARG,0,'X') = ARG
FILE.RESPONSE = ARG
*----------- Is there a name mask for the file/s to be check in the current Universe A/c?
CASE INDEX(ARG,'...',1) OR INDEX(ARG,'[',1) OR INDEX(ARG,']',1)
FILE.RESPONSE = ARG
CASE 1
FILE.RESPONSE = '_'
END CASE
CASE REC.RESPONSE = ''
BEGIN CASE
CASE INDEX(ARG,'...',1) OR INDEX(ARG,'[',1) OR INDEX(ARG,']',1)
REC.RESPONSE = ARG
CASE ARG MATCHES "'WITH":@VM:'"WITH'
SELECT.EXPR = ARG
CASE LEN(SELECT.EXPR)
SELECT.EXPR := ARG
IF ARG[LEN(ARG),1] MATCHES "'":@VM:'"' THEN
REC.RESPONSE = SELECT.EXPR
END
CASE 1
REC.RESPONSE = ARG
END CASE
CASE STRING.RESPONSE = ''
BEGIN CASE
CASE RE.MATCHING
IF LEN(REGEXPR) THEN
REGEXPR := ' ':ARG
IF ARG[LEN(ARG),1] MATCHES "'":@VM:'"' THEN
STRING.RESPONSE = REGEXPR
END
END ELSE
REGEXPR = ARG
END
CASE INDEX(ARG,'...',1) OR INDEX(ARG,'[',1) OR INDEX(ARG,']',1)
STRING.RESPONSE = ARG
CASE ARG MATCHES "'WITH":@VM:'"WITH'
SELECT.EXPR = ARG
CASE LEN(SELECT.EXPR)
SELECT.EXPR := ' ':ARG
IF ARG[LEN(ARG),1] MATCHES "'":@VM:'"' THEN
STRING.RESPONSE = SELECT.EXPR
END
CASE 1
REC.RESPONSE = ARG
END CASE
CASE 1
LEFTOVERS = ARG
END CASE
REPEAT
IF AC.RESPONSE = '' THEN AC.RESPONSE = '_'
IF DICT.FILE THEN
FILE.RESPONSE = 'DICT ':FILE.RESPONSE
END
IF AC.RESPONSE = '_' THEN
IF NOT(LEN(FILE.RESPONSE)) THEN
VALID.AC = @FALSE
LOOP WHILE NOT(VALID.AC) DO
PRINT 'Account(s)? A(ll)|Name-mask|A/c-name|""(=All)|':"''(=All)|Null(=Current)[[/END]] : ":
INPUT AC.RESPONSE
VALID.AC = @TRUE
BEGIN CASE
CASE AC.RESPONSE = ''
AC.RESPONSE = @WHO
CASE AC.RESPONSE MATCHES 'ALL':@VM:'A':@VM:'[]' OR AC.RESPONSE = '""' OR AC.RESPONSE = "''" OR AC.RESPONSE = '...'
AC.RESPONSE = 'ALL'
CASE TRANS('UV.ACCOUNT',AC.RESPONSE,0,'X') = AC.RESPONSE
AC.RESPONSE = AC.RESPONSE
CASE AC.RESPONSE = 'END'
PRINT 'KLIST stopped.'
STOP
CASE 1
PRINT 'Invalid Account response.'
VALID.AC = @FALSE
END CASE
REPEAT
END
END
BEGIN CASE
CASE AC.RESPONSE = 'ALL'
CMD = 'SELECT UV.ACCOUNT'
* HUSH ON
EXEC CMD CAPTURING OUTPUT
* HUSH OFF
CASE INDEX(AC.RESPONSE,'...',1) OR INDEX(AC.RESPONSE,'[',1) OR INDEX(AC.RESPONSE,']',1)
CMD = 'SELECT UV.ACCOUNT = "':AC.RESPONSE:'"'
EXEC CMD CAPTURING OUTPUT
IF INDEX(OUTPUT,@FM:'0 record',1) THEN
ACCOUNT = @WHO
IF TEST THEN
PRINT "First argument (":AC.RESPONSE:") is not a Universe A/c - defaulting to Current A/c - ":ACCOUNT
PRINT
END
IF AC.RESPONSE = 'DICT' THEN
AC.RESPONSE := ' ':FILE.RESPONSE
FILE.RESPONSE = REC.RESPONSE
REC.RESPONSE = STRING.RESPONSE
STRING.RESPONSE = ''
END
STRING.RESPONSE = REC.RESPONSE
REC.RESPONSE = FILE.RESPONSE
FILE.RESPONSE = AC.RESPONSE
AC.RESPONSE = ''
END
CASE 1
ACCOUNT = AC.RESPONSE
@SELECTED = 0
END CASE
IF SYSTEM(11) THEN
FOR I = 1 TO @SELECTED
READNEXT ID ELSE EXIT
ACCOUNT<-1> = ID
NEXT I
END
IF ACCOUNT = '' THEN
PRINT 'No Universe A/c matches account-mask (':AC.RESPONSE:')'
STOP
END
IF FILE.RESPONSE # '' THEN
IF FILE.RESPONSE = '_' THEN
FILE.RESPONSE = ''
END
END ELSE
PRINT 'File(s)? (A)ll(=default)/<string-expression>/<filename>[[/END]] : ':
INPUT FILE.RESPONSE
FILE.RESPONSE = UPCASE(FILE.RESPONSE)
IF FILE.RESPONSE = 'END' THEN
PRINT
STOP
END
END
IF REC.RESPONSE # '' THEN
IF REC.RESPONSE = '_' THEN
REC.RESPONSE = ''
END
END ELSE
IF RECORD.LIST THEN
REC.RESPONSE = LIST.NAME
END ELSE
IF ARG = '' AND NOT(KEYS.ONLY) THEN
PRINT 'Record ID(s)? (A)ll(=default)/<string-expression>/<record-ID[[/END]] : ':
INPUT REC.RESPONSE
REC.RESPONSE = UPCASE(REC.RESPONSE)
IF REC.RESPONSE = 'END' THEN
PRINT
STOP
END
END ELSE
REC.RESPONSE = 'A'
END
END
END
IF STRING.RESPONSE # '' THEN
IF STRING.RESPONSE = '_' THEN
STRING.RESPONSE = ''
END
END
RETURN
*
*--------------------------------------------------------------------------------
*
FINALISATION:
*
PRINT
IF TEST THEN PRINT 'Cleaning up temporary VOC items ...'
HUSH ON
EXEC 'DELETE VOC ':VOC.PTR
HUSH OFF
IF SAVE.LIST THEN
K.MAX = DCOUNT(RECORD.SAVED,@FM)
IF K.MAX > 1 THEN
PRINT 'Saved ':K.MAX-1:' (selected) keys from last selected file (':LAST.SAVEDLIST<2>:' in a/c ':LAST.SAVEDLIST<1>:') in KLIST.':@ACCOUNT:' ...'
HUSH ON
EXEC 'DELETE &SAVEDLISTS& KLIST.':@ACCOUNT
DATA ''
FOR K = 2 TO K.MAX
DATA 'I ':RECORD.SAVED<K>
NEXT K
DATA 'FI'
EXEC 'ED &SAVEDLISTS& KLIST.':@ACCOUNT
HUSH OFF
IF EDIT.LIST THEN
DATA 'ED ':DICT:FILE.PTR
EXEC 'GET.LIST KLIST.':@ACCOUNT
END
END
END
HUSH ON
EXEC 'DELETE VOC ':FILE.PTR
EXEC 'TERM ,':LINES.PER.PAGE
HUSH OFF
CLEARSELECT
IF COMO AND COMO.ON THEN
COMO.ON = @FALSE
HUSH ON
EXEC 'COMO OFF'
EXEC 'SH -c "cat \&COMO\&[[/KLIST]].PART.COMO >> \&COMO\&[[/KLIST]].COMO"'
EXEC 'DELETE &COMO& KLIST.PART.COMO'
HUSH OFF
END
*
RETURN
*
*--------------------------------------------------------------------------------
*
END
*
*================================================================================