; ; ; FNDKEY ; ; FNDKEY - DATABASE SEARCH ROUTINE ; ; ROUTINE NAME: FNDKEY ; ; PURPOSE: FNDKEY finds the next database key that matches ; your pattern and opens it for reading, writing, or ; modifying. ; ; CALLABLE: From FORTRAN or MACRO ; ; PARAMETERS: From FORTRAN: ; CALL FNDKEY(ROOT[,PATT][,KEY][,VAL][,ERR]) ; or ; ERR=FNDKEY(ROOT[,PATT][,KEY][,VAL][,ERR]) ; ; ROOT The data buffer initalized by BLDHDR or OPENBF ; that is used by all database routines to store ; temporary variables and I/O buffers in. ; PATT A simple pattern to search for in the database. ; This "pattern" is a string of characters with ; backslash (\) characters as "wild card" char- ; acters. The pattern is assumed to be the same ; length as the scan section of the keys being ; searched for, but if it is prematurely terminated ; by a NUL, the remaining characters of the pattern ; are assumed to be backslashes. ; KEY A buffer for fndkey to return the actual string ; that your pattern matched. This buffer MUST be ; large enough for the whole scan section of a key ; to fit into, or you will get very strange results ; from your fortran programs. ; VAL A buffer for storing the data section of a key in. ; Again, this buffer MUST be large enough to hold ; the complete data section of a key. ; ERR A word that the status of the search is returned ; in. Possible error values are: ; ERR= +n means successfull return. ; ERR= 0 means there were no keys that matched. ; ERR= -1 means there are no more keys that match. ; ERR= -100 means you called FNDKEY with a bad ROOT ; parameter. ; ; PARAMETERS: From a MACRO program: ; R5 Points to a FORTRAN like parameter list, essen- ; tially the same as FORTRAN would have produced. ; R4 Points to the ROOT buffer. The FORTRAN parameter ; list must have all the parameters, including a ; slot for the root buffer, but it need not also ; have the ROOT pointer. ; R0 The error return is also returned here. ; B$READKEY Is the entrypoint for the MACRO section of ; FNDKEY. You can call via the FNDKEY entrypoint, ; and the routine will initalize R4 for you. This ; is rarely done because code for checking the root ; block is also executed in this entrypoint. ; ; ROUTINES USED: B$ACTIVATE B$GETNEXT B$GETKEY $CMPS ; ; EXAMPLE: ; CALL FNDKEY(ROOT,'TI',,,ERR) ; IF (FNDKEY(ROOT,PATTRN) .LE. 0) GOTO 999 ; CALL FNDKEY(ROOT,,KEY,,ERR) ; from MACRO: ; .PSECT DATA ; PLIST: .WORD 4 ;4 ARGUMENTS ; .WORD ROOT ;POINTER TO ROOT BLOCK ; .WORD -1 ;NUL PATT PARAMETER ; .WORD KEY ;BUFFER FOR KEY ; .WORD VAL ;BUFFER FOR DATA ; KEY: .BLKB 56 ; VAL: .BLKB 14 ; .PSECT ; MOV PLIST,R5 ;INITALIZE THE ARG LIST ; MOV ROOT,R4 ;INITALIZE THE ROOT POINTER ; JSR PC,B$READKEY ;CALL FNDKEY ; TST R0 ;CHECK ERR RETURN ; BLE ERROR ;ERR WAS = 0 ; ; AUTHOR: Mike Higgins ; ; SOURCE LANGUAGE: MACRO11 with SUPERMAC ; ; OBJECT MODULE NAME: FNDKEY ; ; LIBRARY: [60,100]DATABASE ; ; MAINTENANCE: See Mike Higgins ; ; .TITLE FNDKEY BIO-FILE KEY SEARCH ROUTINE ;PARAMETER ASSIGNMENTS ROOTV=2 PATT=4 KEY=6 VAL=10 ERR=12 .MCALL SUPER SUPER ;REGESTER ASSIGNMENTS ROOT=R4 BUF=R3 LEVEL=R2 TEM=R1 TEM2=R0 PROCEDURE FNDKEY LET ROOT := ROOTV(R5) ;GET POINTER TO ROOT BLOCK IF DB.BLT(ROOT) NE #"RT ;IS THIS REALLY A ROOT BLOCK FORET #-100.,ERR ;NO! SOMETHING IS WRONG RETURN END ;ENTRYPOINT FOR CALLING FROM MACRO B$READKEY:: LET LEVEL := RT.PCL(ROOT) IF #FL.ACT OFF.IN LV.FLG(LEVEL) ;IS THIS LEVEL ACTIVE YET? SCALL B$ACTIVATE ;NO, ACTIVATE IT ON.ERROR FORET #0,ERR ;THERE ARE O KEYS AT THIS LEVEL RETURN END ELSE LET BUF := LV.PCE(LEVEL) + LV.LEN(LEVEL) ;IF THIS LEVEL IS ALREADY ACTIVE, ;SKIP TO THE NEXT KEY END REPEAT: IF BUF GT RT.LLA(ROOT) ;ARE THERE ANY MORE KEYS IN THIS BLOCK? SCALL B$GETNEXT ;NO, THEN GET NEXT BLOCK ON.ERROR ;WOOPS, NO MORE BLOCKS LET LV.FLG(LEVEL) := . OFF.BY #FL.ACT ;DO AN EFFECTIVE RESET IF #FL.FKY SET.IN LV.FLG(LEVEL) ;DID I FIND ANY KEYS FOR THIS PATTERN? FORET #-1,ERR ;YES, LET FORTRAN KNOW ;AND CLEAR THE BIT FOR THE NEXT SEARCH LET LV.FLG(LEVEL) := . OFF.BY #FL.FKY RETURN ELSE FORET #0,ERR ;NO, RETURN COMPLETE FAILURE WARNING RETURN END END END ;CONTROL PASSES HERE WHEN THERE IS ;A KEY LEFT IN THE CURRENT BLOCK IF (BUF) EQ #0 ;IS THIS KEY DELETED? LET BUF := BUF + LV.LEN(LEVEL) ;THEN SKIP TO THE NEXT ONE GOTO REPEAT END ;CONTROL PASSES HERE WHEN THERE ;IS A KEY THAT IS NOT DELETED LET LV.PCE(LEVEL) := BUF ;POINT THE "CURRENT ELEMENT" AT THIS ONE IF (R5) GE #PATT/2 ;IS THERE A PATTERN PARAMETER? LET TEM := PATT(R5) ;YES, GET THE ADDRESS IF TEM NE #-1 ;IS IT A NUL PARAMETER? LET TEM2 := LV.SCN(LEVEL) ;NO, GET THE LENGTH IF RESULT IS GT ;DOES THIS LEVEL HAVE SCAN SECTIONS? THRU TEM2 ;YES, DO THE COMPARE IFB (TEM) EQ #0 THEN GOTO EQUIV ;NUL IN PATT MEANS ALL BACKSLASHES IFB (TEM) NE #'\ ;WILD CARD CHARACTER MATCH IFB (TEM)+ NE (BUF)+ ;DO THEY MATCH? ;NO, SKIP TO THE NEXT ONE LET BUF := LV.PCE(LEVEL) + LV.LEN(LEVEL) GOTO REPEAT END ELSE TSTB (TEM)+ ;SKIP OVER WILD CARD SECTIONS TSTB (BUF)+ END END END END EQUIV: ;IF YOU GET HERE, THEY MUST BE EQUAL SCALL B$GETKEY ;RETURN THE KEY AND VAL PARAMETERS END ;SET THE FOUND KEY FLAG LET LV.FLG(LEVEL) := . SET.BY #FL.FKY ENDPROCEDURE FNDKEY .END