; ; ; OPENB ; ; OPENBF- OPEN A DATABASE FILE ; ; ROUTINE NAME: OPENBF ; ; PURPOSE: To open an existing database file, or to create a ; new file initalized by BLDHDR. ; ; CALLABLE: By FORTRAN only: ; CALL OPENBF(ROOT,NAME,LUN,MODE[,ERR]) ; or ; ERR=OPENBF(ROOT,NAME,LUN,MODE[,ERR]) ; ; PARAMETERS: ; ROOT The core buffer for storing the root block and all ; I/O buffers for each level. ROOT must be dimenti- ; oned to 512*NRLEVS+512 bytes, where NRLEVS is the ; number of levels in the files structure. ; NAME A string containing the file specifier for the da- ; tabase file you wish to open. Name must be termi- ; nated with a NUL. The default device ; is BD:, the default file type is '.BDB'., and the ; default UIC is the uic that the program is running ; under. ; LUN The FORTRAN Logical Unit Number that you wish to ; open the file under ; MODE The mode that the file is to be opened under: ; MODE=0 Means shared LUN. The same file can be ; opened under more than one in core ROOT buffer ; with the same lun. This allows you to do two sets ; of file manipulations on the same database file. ; In other words, keep two (or more) pointers into ; the file at the expence of two or more core ROOT ; buffers. ; MODE=1 Means read only. ; MODE=2 Read and write. ; MODE=3 Read, write and create (must have called ; BLDHDR) ; MODE=4 Forces creation of new file (must have called ; BLDHDR). ; ; ERR Error return value. Returns -100 for missing ; BLDHDR call or corrupted database file, 0 means ; success, all other negative error returns are FCS ; error codes. See the RSX11M Pocket Reference for ; a complete list of FCS I/O error codes. ; ; ROUTINES USED: $FCHNL, OPEN$ macro ; ; EXAMPLE: ; CALL OPENBF(ROOT,'DP:[60,200]DICT',8,1) ; or ; INTEGER OPENBF ; IF (OPENBF(DBUF,STRING,DLUN,8,2) ; ; AUTHOR: PETE Linhard, with mods by Mike Higgins ; ; SOURCE LANGUAGE: MACRO11 with SUPERMAC ; ; OBJECT MODULE NAME: OPENBF ; ; LIBRARY: [60,100]DATABASE ; ; MAINTENANCE: See mike Higgins ; ; .MCALL SUPER,FDBK$R,OPEN$,READ$,OPEN$U,OPEN$W,CLOSE$,FDOF$L .MCALL WAIT$,NMBLK$,QIOW$S,FHDOF$ FDOF$L FHDOF$ DEF$L SUPER ; ; DEFINE PARAMETERS ROOT=2 NAME=4 LUN=6 MODE=10 ERR=12 ; ; DEFINE FILE ACCESS MODES ; M.SHR=0 M.RO=1 M.RW=2 M.RWC=3 M.NEW=4 ; PROCEDURE OPENBF ;(ROOT,NAME,LUN,MODE[,ERR]) ; ; ; FIND THE FORTRAN FDB ; LET R2 := @LUN(R5) ;GET THE LUN NUMBER LET R3 := @#$OTSV SCALL $FCHNL ;FCHNL RETURNS THE FORTRAN FDB ADDRESS LET R0 := . + #14 ;MINUS 14 BYTES FOR FORTRAN JUNK LET R3 := @MODE(R5) ;GET MODE PARAMETER IF R3 EQ #M.SHR THEN JUMPTO OPENED ;IF THE MODE IS SHARE, THE FILE MUST ;ALREADY BE OPENED, AND OPENBF DOES ;NOT HAVE TO DO THAT AGAIN LET R1 := NAME(R5) ;FIRST PARSE THE FILE NAME LET R2 := #DSDS SCALL PFILE ; ;NEXT BUILD FILE ACCESS BYTE ; LET R2 := #FA.SHR ;SHARE TO FCS MEANS OTHER PEOPLE ;CAN READ THIS FILE WHILE I READ OR ;WRITE IT ; ;FORCE CREATION BIT IF R3 EQ #M.NEW THEN LET R2 := . SET.BY #FA.CRE IF R3 EQ #M.RO ;READ ONLY? LET R2 := . SET.BY #FO.RD ;YES, TELL FCS ABOUT IT ELSE LET R2 := . SET.BY #FO.UPD ;NO, OPEN FOR UPDATE END ; ; SET THE DON'T LOCK BIT IN THE FDB ; THIS WILL DISALLOW ANY DATABASE FILE FROM BEING LOCKED ; FOR ANY REASON FROM NOW ON. UNFORTUNATELY, FILES CREATED ; BY OLDER VERSIONS OF OPENBF CAN STILL BECOME LOCKED. ; ; LET F.ACTL(R0) := . SET.BY #FA.DLK ; NOTE: THE PREVIOUS LINE WAS COMMENTED OUT BECAUSE ; IT CRASHED ANY DATABASE PROGRAM THAT CONTAINED IT ; ;OPEN THE FILE LET FLAG := #0 OP:OPEN$ R0,R2,@LUN(R5),#DSDS,#DFNB,#FD.RWM,,#DB.SIZE ON.ERROR IF FLAG EQ #0 LET FLAG := FLAG +1 ;IF THERE WAS NO SUCH FILE, AND THE ;MODE WAS READ WRITE CREATE, (3) ;THE OPEN IS ATTEMPTED AGAIN IN ;CREATE MODE IF R3 EQ #M.RWC ANDB F.ERR(R0) EQ #IE.NSF LET R2 := . SET.BY #FA.CRE ;SET THE CREATE BIT FOR OPEN LET R3 := #M.NEW ;SET THE MODE PARAMETER TO "NEW" GOTO OP ;AND TRY THE OPEN AGAIN END IFB F.ERR(R0) EQ #IE.CLO LET R1 := R0 + #F.FNB CALL .FIND LET R4 := ROOT(R5) LET RAD := R4 QIOW$S #IO.RAT,@LUN(R5),#1,,,, LET R4 := R4 + #H.UCHA LET (R4) :B= (R4) OFF.BY #UC.DLK LET WAD := R4 QIOW$S #IO.WAT,@LUN(R5),#1,,#IOERR,, IFB IOERR LT #0 LET R1 :B= IOERR JUMPTO OPERR END PUTLINE JOBLOG,#LOCKED,#ENL-STL JUMPTO OP END END JUMPTO FILERR END OPENED: ; ;THE FILE OPENED SUCCESFULLY, SO ; SET UP THE ROOT BLOCK ; LET R1 := ROOT(R5) IF R3 NE #M.NEW ;IS THIS AN ALREADY EXISTING FILE?? ;YES, READ IN THE FIRST BLOCK READ$ R0,R1,,#BKVB,,#IOERR,,FILERR WAIT$ R0 IFB F.ERR(R0) LT #0 THEN JUMPTO FILERR ;GIVE UP ON ROOT BLOCK FAILURE ; ;**********THIS BLOCK OF CODE ADDED BY MIKE HIGGINS TO ASSURE THAT ;**********THE ROOT BLOCK IS CLEANED UP PROPERLY, EVEN WHEN THE ;**********FILE IS NOT CLOSED BY CLOSBF. ; ;DEFINE THE REGESTERS THE WAY THAT I LIKE THEM RT=R4 BUF=R3 LEVEL=R2 TEM=R1 PUSH RT,BUF,LEVEL,TEM ;PUSH PETE'S REGESTERS SAFELY AWAY LET RT := 2(R5) ;GET POINTER TO ROOT LET RT.LEV(RT) := #1 ;INITALIZE LEVEL NUMBER LET BUF := RT + #DB.SIZE ;POINTER TO CURRENT BUFFER LET RT.BUF(RT) := BUF LET RT.PCE(RT) := RT ;POINTER TO CURRENT ELEMENT LET LEVEL := RT + #LV.1ST+LV.SIZE ;STACK POINTER LET RT.LLA(RT) := BUF + LV.LLK(LEVEL) ;LAST LEGAL KEY ADDRS LET RT.PCL(RT) := LEVEL ;STORE STACK POINTER IN ROOT LET TEM := RT.NLV(RT) ;LOOP FOR THE MAXIMUM NUMBER OF LEVELS THRU TEM ;MARK THIS LEVEL AS INACTIVE AND ;UNMODIFIED LET LV.FLG(LEVEL) := . OFF.BY #FL.ACT!FL.MOD LET LV.PCB(LEVEL) := #0 ;CLEAR THE I/O BUFFER BLOCK NUMBER LET LV.PCE(LEVEL) := BUF ;CURRENT KEY IS THE BEGENING OF BLOCK LET LEVEL := LEVEL + #LV.SIZE ;INC TO NEXT STACK ELEMENT LET BUF := BUF + #DB.SIZE ;INC TO NEXT BUFFER END POP TEM,LEVEL,BUF,RT ;RESTORE PETE'S REGESTERS IF #FL.COR SET.IN RT.FLG(R1) PUTLINE JOBLOG,#CORRUPT,#CLEN END ; ;************END OF MIKES MODS ; END ;WHETHER THE FILE WAS NEW OR OLD, CHECK ;TO SEE IF THE ROOT BLOCK WAS INITALIZED ;CORRECTLY FOR A DATABASE FILE IF DB.BLT(R1) NE #"RT ;ROOT BLOCKS HAVE #"RT STORED IN THEM LET R1 :B= #-100. ;ERROR -100 MEANS BAD ROOT BLOCK GOTO OPERR END IF R3 GT #M.RO ;IF THE FILE IS OPENED FOR WRITE, LET RT.AGE(R1) := . + #1 ;THEN INCRIMENT THE AGE ;AND SET THE MODIFY BIT AND THE ;WRITE PERMISSION BITS IN THE ;ROOT BLOCK LET RT.FLG(R1) := . SET.BY #FL.WRT!FL.MOD END LET RT.FDB(R1) := R0 ;STORE THE FDB AWAY IN THE ROOT ;FOR OTHER BDB ROUTINES TO USE ; RETURN A ZERO ERROR PARAM IF NO ERROR LET R0 := #0 ;IF THERE IS AN ERR ARG, RETURN IT THERE ALSO IFB (R5) GE #5 AND ERR(R5) NE #-1 LET @ERR(R5) := R0 END RETURN ; ; PARSE FILENAME INTO DS DS ; ; R1=POINTER TO STERING TERMINATED BY A ZERO BYTE ; R2=DATA SET DESCRIPTOR ; ; RESTORES R3 AND R4 ; PFILE: PUSH R3,R4 ; ; ; FIRST CLEAR THE DSDS ; FOR R3 := #0 TO #12 BY #2 THEN LET DSDS(R3) := #0 WHILEB (R1) NE #0 ;WHILE THE STRING DOESN'T HAVE A NUL LET R3 := R1 LET R4 := #0 BEGIN SCAN REPEAT IFB (R1) EQ #': ;COLON TERMINATES A DEVICE LET (R2) := R4 + #1 LET 2(R2) := R3 LET R1 := R1 + #1 LEAVE SCAN END IFB (R1) EQ #'] ;RGT BRACKET TERMINATES A UIC LET 4(R2) := R4 + #1 LET 6(R2) := R3 LET R1 := R1 + #1 LEAVE SCAN END LET R1 := R1 + #1 LET R4 := R4 + #1 UNTILB (R1) EQ #0 END END LET 10(R2) := R4 LET 12(R2) := R3 ; RESTORE REGS POP R4,R3 RETURN ; ; FILE ERROR ; FILERR: LET R1 :B= F.ERR(R0) OPERR: LET R0 := R1 ;IF THERE IS AN ERR ARGUMENT, RETURN THE ;ERROR CODE THERE ALSO IFB (R5) GE #5 AND ERR(R5) NE #-1 LET @ERR(R5) := R1 END RETURN DSDS: .BLKW 6 DFNB: NMBLK$ ,BDB,,BD,0 BKVB: .WORD 0 .WORD 1 IOPTR:: .WORD 0,0 IOERR:: .WORD 0,0 FLAG: .WORD 0 RATT: .BYTE -12,1 RAD: .WORD 0 .WORD 0 WATT: .BYTE 3,1 WAD: .WORD 0 .WORD 0 STL=. LOCKED: .BYTE 40,10 .ASCII /****** FILE WAS LOCKED!!! ******/ ENL=. TEM=. CORRUPT: .BYTE 40,10 .ASCII /****** FILE MAY BE CORRUPTED!!! ******/ CLEN=.-TEM .END