.TITLE KEYMNG .IDENT /1401.7/ ; ; ; ; WRITTEN BY RAY DI MARCO ; 14-JAN-81. ; ; ; VERSION 140181/07. ; ; ;----------------------------------------------------------------- ; ; THIS ROUTINE CONTAINS THE ROUTINES NEEDED TO MANAGE KEYS. THE ; ROUTINES ARE- ; ; KEY.NW FIND A SLOT FOR NEW RECORD/KEYS. IF A SLOT EXITS THE ; 'C' FLAG IS CLEAR ON RETURN AND R0 HOLDS THE RECORD ; NUMBER. ; ; KEY.OT WRITE OUT THE KEYS ASSOCIATED WITH RECORD 'R0', WHOSE ; CONTENTS ARE IN THE USER BUFFER. ; ; KEY.FD RETURN NUMBER OF RECORD WHOSE KEYS MATCH THOSE SPECIFIED ; BY THE USER IN R0. 'C' IS SET IFF THE RECORD COULD NOT ; BE FOUND. ; ; ALL REGISTERS OTHER THAN R0 ARE PRESERVED. ; ; .SBTTL MODIFICATIONS ; ; ; 27-JAN-81 DISPLAY NUMBER OF MATCHES WHEN USEDING KEY SEARCH MODE ; 28-JAN-81 INCLUDE EXTRA ENTRY IN 'GENKEY' TABLE '200$' FOR DATES ; 2-MAR-81 CHANGE REFRENCES TO 'FORM$$' TO USE '$$FORM' ; 13-MAR-81 IN 'KEY.FD' - IMPROVE SEARCHING (CHANGE 2000$-5000$) ; 11-SEP-81 'KEY.FD' - ALLOW RECORD NUMBER TO BE SPECIALLY SPECIFIED! ; 02-Apr-82 'KEY.FD' - correct logical error @4400$ ; ; ; ; ; ; .SBTTL DECLARATIONS ; ; .MCALL .PUSH,.POP ; STACKING ; ; .GLOBL KEY.NW,KEY.FD,KEY.OT ; ENTRIES ; .GLOBL FED.MD,FED.NW ; "FEDMNG" .GLOBL FRM.EF,FRM.BG,FRM.FG ; "FRMIO" .GLOBL TBLKUP ; "TBLKUP" .GLOBL FIL.DR,FIL.KR,FIL.KW ; "FILEIO" .GLOBL LOCFLD ; "LOCFLD" .GLOBL $$FORM ;; FORM DEFINITION FILE .GLOBL CNAFD4 ; "CNAF" .GLOBL ASCNUM ; ASCII -> NUMBER ; .PSECT CODE ; OPEN CODE SECTION ; ------ ---- ; ; ; .SBTTL MACRO - 'CMDTAB' ... CREATE A COMMAND TABLE ; ; ; ; THIS MACRO IS USED TO CREATE A COMMAND TABLE WHICH CAN BE USED ; BY 'TBLKUP' FOR COMMAND DECODING. TO USE IT DO THE FOLLOWING- ; ; CMDTAB NAME ; CREATE AND LABLE TABLE ; CMDENT COMMAND,ROUTINE ; COMMAND --> ROUTINE ; ....... ; CMDEND ; TERMINATE TABLE ; ; 'TBLKUP' IS CALLED WITH THE COMMAND STRING IN 'R0' AND THE TABLE ; ADDRESS (NAME) IN 'R1'. IT RETURNS WITH THE ROUTINE ADDRESS IN ; 2(R1) IF IT FINDS THE COMMAND IN THE TABLE. ; ; ; ; .MACRO CMDTAB TABLE TABLE: .MACRO CMDENT NAME,VAL1,VAL2=0,VAL3=0 .SAVE .PSECT MESSAGE ZZZZZ1 = . .ASCIZ /NAME/ .RESTORE .WORD ZZZZZ1,VAL1,VAL2,VAL3 .ENDM CMDENT ; .MACRO CMDEND .WORD 0,0,0,0 .MACRO CMDTAB .ENDM CMDTAB .MACRO CMDENT .ENDM CMDENT .ENDM CMDEND ; .ENDM CMDTAB ; ; ; ; .SBTTL MACRO - 'INPUT' ... INPUT A COMMAND ; ; ; THIS MACRO IS USED TO INPUT A COMMAND LINE. THE ADDRESS OF THE ; INPUT BUFFER IS RETURNED IN R0, AND IT IS TERMINATED BY A NULL. ; OPTIONAL PROMPT, STATUS AND ERROR MESSAGES CAN BE SPECIFIED. ; ; ; ; .MACRO INPUT BUFFER=IOM.BF,PROMPT,STATUS,ERROR .IF NB,ERROR .PUSH R0 MOV ERROR,R0 .GLOBL IOM.ER CALL IOM.ER .POP R0 .ENDC ; .IF NB,STATUS .PUSH R0 MOV STATUS,R0 .GLOBL IOM.ST CALL IOM.ST .POP R0 .ENDC ; .IF NB,PROMPT .PUSH R0 MOV PROMPT,R0 .GLOBL IOM.PT CALL IOM.PT .POP R0 .ENDC ; MOV BUFFER,R0 .IIF IDN,BUFFER,IOM.BF,.GLOBL IOM.BF .GLOBL IOM.IN CALL IOM.IN ; .ENDM INPUT ; ; ; ; ; ; ; ; .SBTTL MACRO - 'STATUS' ... DISPLAY STATUS MESSAGE ; ; ; .MACRO STATUS MESSAGE .IF NB,MESSAGE .PUSH R0 MOV MESSAGE,R0 .ENDC .GLOBL IOM.ST CALL IOM.ST .IIF NB,MESSAGE, .POP R0 .ENDM STATUS ; ; ; ; ; ; .SBTTL MACRO - 'ERROR' ... DISPLAY ERROR MESSAGE ; ; ; .MACRO ERROR MESSAGE .IF NB,MESSAGE .PUSH R0 MOV MESSAGE,R0 .ENDC .GLOBL IOM.ER CALL IOM.ER .IIF NB,MESSAGE, .POP R0 .ENDM ERROR ; ; ; ; ; ; .SBTTL ROUTINE - 'KEY.NW' ... FIND A NEW/UNUSED KEY RECORD ; ; ; SEACH THROUGH ALL KEY SLOTS TILL FIND ONE WHICH HAS FIRST WORD ; OF ZERO. ; ; KEY.NW: .PUSH MOV $$FORM,R1 ;; R1 --> FORM$$ MOV 14(R1),R1 ;; R1 == COUNT MOV #1,R2 ; RECORD NUMBER -> R2 100$: MOV R2,R0 ; RECORD NUMBER -> R0 CALL FIL.KR ; READ IN A KEY TST KEY$$B ; IS FIRST KEY 0? BEQ 200$ ; YES -> GOT IT -> EXIT INC R2 ; TRY NEXT SOB R1,100$ ; LOOP .POP ; RESTORE SEC ; SET FAILED RETURN ; EXIT ; 200$: .POP ; RESTORE CLC ; CLEAR FAIL RETURN ; EXIT ; ; ; ; .SBTTL ROUTINE - 'KEY.OT' ... OUTPUT KEYS ; ; ; HAVE TO OUTPUT KEYS FOR RECORD 'R0'. GENERATE KEYS FROM DATA ; HELD IN FORM RECORD AND THEN WRITE OUT CONTENTS OF KEY BUFFER. ; ; ; ; KEY.OT: MOV $$FORM,R5 ;; GEN KEYS FROM FORM CALL GENKEY ; GENERATE KEYS MOV R0,KEY$$B ; SAVE KEY NUMBER CALL FIL.KW ; OUTPUT KEYS RETURN ; EXIT ; ; ; ; ; ; .SBTTL ROUTINE - 'KEY.FD' ... LOCATE RECORD VIA KEY ; ; ; ; THIS ROUTINE IS CALLED TO LOCATE A SPECIFIC RECORD IN THE DATA FILE ; VIA ITS KEYS. ; ; ; IDENTIFY OURSELVES AND USE 'KEY FORM' TO INPUT KEYS FOR ; RECORD WE ARE LOOKING FOR. ; ; KEY.FD: .PUSH ; SAVE TSTB (R0) ;; END OF INPUT STRING? BEQ 7$ ;; YES -> SKIP MOV R0,R1 ;; STRING -> R1 CALL ASCNUM ;; NUMBER -> R0 TST R0 ;; NUMBER = 0? BEQ 7$ ;; YES -> SKIP MOV $$FORM,R1 ;; R1 --> FDT MOV 14(R1),R1 ;; R1 == NUMBER OF ENTRIES CMP R0,R1 ;; LEGAL RECORD SPECIFIED? BHI 7$ ;; NO -> SKIP CALL FIL.KR ;; GET KEYS TST KEY$$B ;; RECORD IN USE? BNE 700$ ;; YES -> ACCEPT AS MATCH!!! ; 7$: STATUS #6000$ ; IDENTIFY STATE BIS #4,FED.MD ; EXIT IMMEDIATE FLAG SET MOV $$FORM,R5 ;; ARG -> R5 ADD #30,R5 ;; R5 --> ARG CALL FED.NW ; ENTER DATA ; ; ; ; SEARCH TILL FIND A NON-ZERO KEY. IF ALL KEYS ARE ZERO ; ABORT OPERATION. IF FIND A NON-ZERO KEY GOTO 2000$. ; ; CALL GENKEY ; GENEARTE KEYS MOV #KEY$$B+2,R4 ; R4 --> KEY BUFFER MOV #15.,R3 ; R3 = COUNTER 10$: TST (R4)+ ; GOT A <>0 KEY BNE 2000$ ; GOT A KEY -> 2000$ SOB R3,10$ ; LOOP BR 1000$ ; FAILED -> EXIT ; ; ; SUCESSFUL EXIT POINT. ; ; 700$: .POP ; RESTORE CLC ; SET OK FLAG RETURN ; HOME ; ; ; ERROR/FAILED EXIT POINT. ; ; 1000$: ERROR #6002$ ; TELL FAILED .POP ; RESTORE SEC ; SET NO-GO RETURN ; HOME ; ; ; ; ; ; ; SEE IF HAVE 1 WORD (DATE/NUMBER) OR A MULTI-BYTE (ASCII) ; KEY FIELD. IF A 1 WORD TYPE, THEN USE ROUTINE AT '3000$'. ; IF ASCII TYPE FIELD, USE ROUTINE '4000$' FOR SEARCH. ; ; ; 2000$: MOV -(R4),R3 ; KEY VALUE -> R3 MOV R4,R5 ; R5 HOLDS KEYS ADDRESS IN KEY$$B SUB #KEY$$B+2,R4 ; R4 HOLDS KEY NUMBER*2 .REPT 4 ; FIND KEYS RDT ENTRY OFFSET ... ASL R4 ; ... NOTE 40 OCTAL BYTES ... .ENDR ; ... PER RDT ENTRY MOV $$FORM,R1 ;; R1 --> FORM$$ ADD 30+2(R1),R4 ;; R4 --> RDT ENTRY FOR KEY MOV (R4),R2 ; ENTRY TYPE -> R2 BIC #^C377,R2 ; DISCARD FLAGS CMP R2,#3 ; TYPES 0/1/2 ARE ASCII FIELDS BLO 4000$ ; ASCII TYPE -> 4000$ ; ; ; ; ; ; NUMERIC/DATE TYPE KEY. IN THIS CASE THE CONTENTS OF THE ; KEY INDEX FILE ONLY HAVE TO BE SEARCHED. IN PASS 1, SCAN ; THROUGH KEY FILE, LATCHING LAST FOUND MATCH, AND COUNTING ; NUMBER OF MATCHS. NOTE SCAN FROM LAST TO FIRST. ; ; ; ; ; 3000$: CLR MATCH ; NO MATCHS CLR MATCH+2 ; NO MATCHS MOV R3,R4 ; R4 == VALUE TO MATCH MOV $$FORM,R0 ; R0 --> FORM$$ MOV 14(R0),R0 ; R0 = NUMBER OF ENTRIES 3100$: CALL FIL.KR ; ACCESS KEYS CMP (R5),R4 ; MATCH? BNE 3130$ ; NO -> SKIP MOV R0,MATCH ; SAVE MATCH NUMBER INC MATCH+2 ; UP NUMBER OF MATCHS 3130$: SOB R0,3100$ ; LOOP ; ; ; ; IF NONE OR ONE MATCHS EXIT NOW. IF MORE THAN ONE MATCH ; HAVE TO INDIVIDUALLY DISPLAY THEM. ; ; MOV MATCH,R0 ; MATCH NUMBER -> R0 BEQ 3777$ ; NO MATCH -> 3777$ CMP MATCH+2,#1 ; ONLY 1 MATCH? BEQ 3776$ ; YES -> OK ; ; ; ; ; ; NUMERIC/DATE KEY SEARCH, PHASE 2. HAVE MORE THAN ONE MATCHING ; RECORD. WE MUST THEREFORE DISPLAY THEM ONE AT A TIME, AND ; ASK THE OPERATOR TO SELECT THE ONE HE REQUIRES. ; ; ; ; MOV MATCH,R0 ; START AT FIRST MATCH 3300$: CALL FIL.KR ; READ IN KEY CMP (R5),R4 ; MATCH? BNE 3430$ ; NO MATCH -> 3430$ CALL 5000$ ; IS THIS WHAT WE ARE LOOKING FOR BGT 3776$ ; YES ACCEPT BLT 1000$ ; ABORT -> 3777$ 3430$: INC R0 ; TRY NEXT RECORD BR 3300$ ; LOOP ; 3776$: JMP 700$ ; ACCEPT 3777$: JMP 1000$ ; ABORT ; ; ; ; ; ; ; UNFORTUNATELY, THE KEY IS AN ASCII TYPE ONE. IN THIS ; CASE, THE KEY WAS HASHED TO A 1 WORD QUANTITY. IN THIS ; CASE IF WE FIND A MATCH WHEN SCANNING THE KEY FILE, WE ; MUST ALSO CHECK THE ACTUAL RECORD TO ENSURE THAT WE ; HAVE A TRUE MATCH. ; ; ; ; 4000$: MOV 4(R4),R3 ; R3=OFFSET TO KEY FIELD FROM 'KEYADD' MOV 22(R4),R1 ; R1 --> NAME OF KEY MOV $$FORM,R0 ; R0 --> FORM$$ CALL LOCFLD ; LOCATE ENTRY FOR FIELD BCS 1000$ ; CANNOT LOCATE -> ERROR MOV 4(R1),R2 ; R2 =OFFSET TO FIELD FROM 'RECADD' MOV 2(R1),R1 ; R1 = SIZE (BYTES) OF FIELD ADD (R0),R2 ; R2=ADDRESS OF FIELD ADD 30(R0),R3 ; R3=ADDRESS OF KEY FIELD CLR MATCH ; NO MATCHS CLR MATCH+2 ; NO MATCHS MOV (R5),R4 ; R4 = VALUE SEARCHING FOR ; MOV 14(R0),R0 ; R0 = NUMBER OF ENTRIES 4100$: CALL FIL.KR ; ACCESS KEYS CMP (R5),R4 ; MATCH? BNE 4140$ ; NO -> SKIP .PUSH ; SAVE CALL FIL.DR ; READ IN RECORD 4110$: CMPB (R2)+,(R3)+ ; MATCH? BNE 4120$ ; NO -> SKIP SOB R1,4110$ ; LOOP MOV R0,MATCH ; SAVE MATCH NUMBER INC MATCH+2 ; UP NUMBER OF MATCHS 4120$: .POP ; RESTORE 4140$: SOB R0,4100$ ; LOOP ; ; ; IF NO OR ONE MATCHS TERMINATE HERE. ; ; MOV MATCH,R0 ; MATCH NUMBER -> R0 BEQ 1000$ ; NO MATCH -> 1000$ CMP MATCH+2,#1 ; ONLY 1 MATCH? BEQ 4776$ ; YES -> OK ; ; ; ; ; ; MORE THAN ONE MATCH. DISPLAY EACH ONE TO ALLOW ; OPERATOR TO SELECT THE ONE HE REQUIRES. ; ; ; ; MOV MATCH,R0 ; START AT FIRST MATCH 4400$: CALL FIL.KR ; READ IN KEY CMP (R5),R4 ; MATCH? BNE 4440$ ; NO MATCH -> 4440$ .PUSH ; SAVE CALL FIL.DR ; READ IN DATA 4410$: CMPB (R2)+,(R3)+ ; MATCH? BNE 4420$ ; NO -> SKIP SOB R1,4410$ ; LOOP .POP ; RESTORE CALL 5000$ ; IS THIS WHAT WE ARE LOOKING FOR BGT 4776$ ; YES ACCEPT BLT 4777$ ; ABORT -> 4777$ BR 4440$ ; NEXT 4420$: .POP ;; RESTORE 4440$: INC R0 ; TRY NEXT RECORD BR 4400$ ; LOOP ; 4776$: JMP 700$ ; ACCEPT 4777$: JMP 1000$ ; ABORT ; ; ; ; ; ; ; AT ENTRY, R0 HOLDS NUMBER OF POSSIBLE MATCHING RECORD. ; DISPLAY RECORD, AND REQUEST OPERATOR TO INDICATE IF ; IT IS TO BE ACCEPTED. RETURN WITH ; ; 'Z' SET IF TO TRY NEXT ONE ; 'N' SET IF TO ABORT ; ; ; ; 5000$: .PUSH ; SAVE MOV R0,R2 ; RECORD NUMBER -> R2 CALL FIL.DR ; ENTER DATA MOV $$FORM,R0 ;; POINT TO RECORD MOV (R0),R5 ; BUFFER -> R5 CALL FRM.EF ; CLEAR FORM CALL FRM.BG ; DISPLAY BG CALL FRM.FG ; DISPLAY FG ; CLR R0 ; FORMAT CONTROL MOV #60012$,R1 ; BUFFER ADDRESS CALL CNAFD4 ; TO ASCII MOV #60011$,R1 ; R1 --> BUFFER MOV MATCH+2,R2 ; NUMBER MATCHS -> R2 DEC R2 ; R2 = REMAINING MATCHS CALL CNAFD4 ; NUMBER MATCHS -> ASCII ; 5040$: INPUT ,PROMPT=#6001$,STATUS=#6000$ ; SEE IF FOUND RIGHT FORM MOV #7000$,R1 ; TABLE ADDRESS -> R1 CALL TBLKUP ; DO A TABLE LOOKUP BCS 5040$ ; ILLEGAL COMMAND -> LOOP MOV 2(R1),MATCH+4 ; TYPE -> MATCH+4 .POP ; RESTORE ; TST MATCH+4 ; WAS ANSWER YES? BGT 5100$ ; YES -> ACCEPT BLT 5200$ ; NO -> ABORT DEC MATCH+2 ; DOWN COUNTER BEQ 5200$ ; NO MORE MATCHS -> ABORT SEZ ; SET 'NEXT' FLAG 5100$: RETURN ; HOME ; 5200$: SEN ; SET FAIL FLAG RETURN ; HOME ; ; ; ; ; MESSAGES FOR 'KEY.FD' ; ; ; .NLIST BIN .ENABL LC 6000$: .ASCII /"KEYMNG" - Record Locating Mode (via Keyed Index)/<200> 6001$: .ASCII /COMMANDS ARE - Accept ABort Next/ .ASCII / (REMAINING MATCHES=/ 60011$: .ASCII /XXXX RECORD=/ 60012$: .ASCII /XXXX)/<200> 6002$: .ASCII /? HELP ? - Cannot Locate Specified Record/<200> .DSABLE LC .EVEN .LIST BIN ; ; ; ; ; COMMAND DECODE TABLE FOR 'CKY.FD' ; ; CMDTAB 7000$ CMDENT ,0 CMDENT ,1 CMDENT ,-1 CMDEND ; ; MATCH: .WORD 0,0,0,0 ; USED FOR 'APPROX SEARCH' ; ; ; ; .SBTTL ROUTINE - 'GENKEY' ... GENERATE KEYS ; ; ; THIS ROUTINE SEARCHS THROGH THE FORM WHOSE HEADER IS PASSED OVER ; IN 'R5', AND TRANSLATES ENTRIES WHICH MATCH THOSE IN THE 'KEY' ; FORM DESCRIPTOR TO ONE WORD KEY VALUES, WHICH IT STORES IN THE ; 'KEY$$B' BUFFER. THE ROUTINE WILL GENERATE A MAXIMUM OF 15 ; KEY WORDS, AND WILL NOT MODIFY THE FIRST WORD IN THE BUFFER. ; ; ; GENKEY: .PUSH ; SAVE MOV #KEY$$B,R0 ; BUFFER MOV #16.,R1 ; COUNT 10$: CLR (R0)+ ; ERASE SOB R1,10$ ; LOOP ; MOV $$FORM,R3 ;; R3 -> FORM$$ MOV 30+2(R3),R4 ;; R4 --> KEY RDT MOV 30+4(R3),R2 ;; R2 = NUM ENTRIES BEQ 100$ ; NO KEYS -> SKIP MOV #KEY$$B+2,R3 ; R3 --> DESTINATION CMP R2,#15. ; TOO MANY KEYS? BLOS 40$ ; NO -> OK MOV #15.,R2 ; MAKE RIGHT ; 40$: MOV 22(R4),R1 ; FIELD NAME STRING -> R1 MOV R5,R0 ; R0 --> RDT TO SEARCH CALL LOCFLD ; LOCATE FDT BCS 60$ ; FAILED -> 60$ MOV (R1),R0 ; FIELD TYPE -> R0 BIC #^C377,R0 ; DISCARD FLAGS ADD R0,R0 ; 2*TYPE -> R0 CALL @200$(R0) ; DISPATCH 60$: ADD #40,R4 ; NEXT KEY ADD #2,R3 ; POINT NEXT DESTINATION SOB R2,40$ ; LOOP ; 100$: .POP ; RESTORE RETURN ; HOME ; ; 200$: .WORD ..ASC,..ASC,..ASC,..NUM ; DISPATCH TABLE (INDEX VIA TYPE) .WORD ..NUM ;; DATE DISPATCH ; ; ; ; ; ; THIS KEY FIELD IS A NUMBER. ; ; ..NUM: MOV 4(R1),R0 ; OFFSET -> R0 ADD (R5),R0 ; ABSOLUTE ADDRESS OF ENTRY MOVB (R0)+,(R3) ; SAVE ... MOVB (R0)+,1(R3) ; ... KEY RETURN ; HOME ; ; ; ; ; THIS ROUTINE GENERATES A 1 WORD KEY FOR ; AN ASCII FIELD. ; ; ..ASC: .PUSH ; SAVE MOV 4(R1),R0 ; OFFSET -> R0 ADD (R5),R0 ; ABSOLUTE MOV 2(R1),R2 ; COUNTER CLR R4 ; ZERO ACCUMULATOR 10$: MOVB (R0)+,R1 ; BYTE -> R1 SUB #40,R1 ; RELATIVE TO ' ' BLOS 20$ ; SKIP BLANKS ADD R1,R4 ; ACCUMULATE ROL R4 ; MUL RESULT BY 2 20$: SOB R2,10$ ; LOOP MOV R4,(R3) ; SAVE KEY .POP ; RESTORE RETURN ; HOME ; ; ; ; ; .SBTTL BUFFER - 'KEY$$B' ... USER KEY BUFFER ; ; ; KEY$$B::.BLKW 16. ; ; .END