.TITLE FINDER ... DBSMNG CUSP to find and print entries in SFL files .IDENT /071182/ .ENABL LC ; ; ; Written by Ray Di Marco ; 7-Dec-82 ; ; ; ;---------------------------------------------------------------------------- ; ; This module contains the code for the FINDER program; the program is used ; to print all SFL file entries that match a specified target. ; ; The program is a supped up version of NUMBER, the special program contained ; in the PHONES demo database, and like NUMBER, is a stripped down version ; of INSPECT. (The code that allows database records to be displayed and ; printed has been removed.) ; ; To use FINDER the user must load a SFL file with the desired (ascii) data; ; this data must then be sorted with SORTER. FINDER can then be used to ; type on the user's screen all entries in the SFL file that match a ; given target string. FINDER automatocally terminates whenever a ; only is typed when it requests a target string. The program, unlike ; other CUSPs, includes VT100 specific code. ; .SBTTL Declarations .ENABL LC ; ; .MCALL .PRINT,.EXIT,.TTYOUT ; used for error handling .MCALL .GTLIN ; Input .MCALL .PUSH,.POP ; Stacking ; .GLOBL CON.EX,CON.ST,CON.CI ; CONIO .GLOBL SFLINT,SFLPSN,SFLINP,SFLINC,SFLPAR,SFLNME; SRTFIO ; .PSECT CODE ; open code ; ====== ==== ; ; .SBTTL Macro Definitions ; .MACRO PRINT STR=R0 .GLOBL CON.LO MOV STR,R0 CALL CON.LO .ENDM PRINT ; .MACRO GTLIN BUF=R0,STR .IF NB,STR .GLOBL CON.LO MOV STR,R0 CALL CON.LO .ENDC MOV BUF,R0 .GLOBL CON.LI CALL CON.LI .ENDM GTLIN ; .MACRO FATAL STR,?A,?B .PRINT #'B .EXIT B': .ASCIZ |FINDER-fatal-'STR'| .EVEN .ENDM FATAL ; .SBTTL INITIALIZATION SECTION ; ; Initialize TTY interface and get name of file ; START: CALL CON.ST ; initialize TTY interface PRINT #7000$ ; identify self GTLIN #SFLNME,#7100$ ; get name of 'SFL' file CALL SFLINT ; initialize sort file ; ; Insure have a valid index file ; CMP SFLPAR,#3 ; minimum record size = 3 BLO 6000$ ; to small -> abort CMP SFLINT+2,#2 ; need at least 2 records BLOS 6100$ ; not enough -> abort JMP RESTRT ; enter loop ; ; Error traps ; 6000$: FATAL 6100$: FATAL ; .NLIST BIN 7000$: .ASCIZ /FINDER RDM101282/ 7100$: .ASCII / Sorted Index File: /<200> .EVEN .LIST BIN .SBTTL Main Loop Code ; ; Prompt for target ; RESTRT: GTLIN #..TARG,#PROMPT ; prompt MOV #..TARG,R0 ; R0 -> line buffer ; ; Exit if only entered ; CMPB (R0),#0 ; any input BNE 100$ ; no --> skip JMP CON.EX ; yes -> quit ; ; Work out target size ; 100$: TSTB (R0)+ ; at EOS? BNE 100$ ; no -> loop SUB #..TARG+1,R0 ; R0 = target size BEQ RESTRT ; no -> reprompt MOV R0,TARSIZ ; save size ; ; Convert LC to UC ; MOV #..TARG,R1 ; R1 -> TARGET 200$: CMPB (R1)+,#140 ; LC character? BLO 240$ ; no -> skip BICB #40,-1(R1) ; convert UC 240$: SOB R0,200$ ; loop till all done ; ; ; perform a binary seach of index file to find best match. ; use R4 as step size and R3 as pointer ; MOV SFLPAR+2,R4 ; R4 = number of entries CALL 5000$ ; R4 = R4 / 2 MOV R4,R3 ; R3 = starting entry 2000$: CMP R3,SFLPAR+2 ; in range? BLOS 2010$ ; yes -> skip MOV SFLPAR+2,R3 ; force into range 2010$: MOV R3,R0 ; R0 = next entry to search CALL SFLPSN ; position on entry R0 CALL 5000$ ; R4 = step size BEQ 2400$ ; out of steps -> done ADD R4,R3 ; assume going to step up CALL 5400$ ; compare TAR to REC BHI 2000$ ; TAR > REC -> step up SUB R4,R3 ; we are not stepping up ... SUB R4,R3 ; ... we are stepping down BGT 2000$ ; loop not wrapped arround MOV #1,R3 ; don't allow wrap arround BR 2000$ ; loop ; ; insure that R3 points to a valid entry ; 2400$: CMP R3,#1 ; at first entry? BHI 2440$ ; no -> skip MOV #2,R3 ; force to second 2440$: DEC R3 ; skip back 1 record ; ; ; print all matching entries (20 at a time) ; MOV #20.,R4 ; R4 = line counter DEC R3 ; preloop fudge 2500$: INC R3 ; try next record CMP R3,SFLPAR+2 ; all done? BHI RESTRT ; yes -> terminate MOV R3,R0 ; R0 = match area CALL SFLPSN ; position file CALL 5400$ ; compare TAR with REC BLO RESTRT ; TAR < REC -> terminate BHI 2500$ ; TAR > REC -> loop ; MOV R3,R0 ; R0 = match area CALL SFLPSN ; position file MOV #..RECN,R0 ; R0 -> buffer MOV SFLPAR,R1 ; R1 = number bytes to read CALL SFLINP ; input record CLRB ..RECN(R1) ; terminate DEC R4 ; one more line gone BNE 3000$ ; skip if not all used ; .PRINT #MORE ; see CALL CON.CI ; if more CMP R0,#40 ; output is BNE 3700$ ; wanted MOV #19.,R4 ; reset line counter ; 3000$: .PRINT #HEADER ; print header .PRINT #..INDX ; print entry .PRINT #TRAILR ; print trailer BR 2500$ ; loop 3700$: JMP RESTRT ; ; ; R4 = R4/2 used to calculate new step-size ; 5000$: CMP R4,#1 ; last step = 1? BEQ 5040$ ; yes -> skip INC R4 ; R4 = number+1 5040$: ASR R4 ; R4 = number/2 rounded up BIC #100000,R4 ; ensure sign bit clear RETURN ; bye ; ; CMP TAR,ENT used to compare target with entry @R3 ; 5400$: CALL SFLINC ; discard first byte CALL SFLINC ; discard second byte MOV TARSIZ,R2 ; R2 = record size MOV #..TARG,R1 ; R1 = TARGET 5600$: CALL SFLINC ; R0 = next input character CMPB (R1)+,R0 ; comp TAR to REC byte BNE 5700$ ; skip no match SOB R2,5600$ ; loop if matched 5700$: RETURN ; all done ; .SBTTL Data Structures ; ; TARSIZ: .WORD 0 ; target size ..TARG: .BLKB 200 ; Target to be found ..RECN: .WORD 0 ..INDX: .BLKB 200 ; index PROMPT: .ASCII <15><12>/Target: /<200> HEADER: .ASCII <33>|[0;1;4m|<200> TRAILR: .ASCII <33>|[0m|<200> NFOUND: .ASCIZ /no match!/ MORE: .ASCII <15><12> .ASCII /press for rest of data, or for new TARGET/ .ASCII <15><200> ; .END START