home *** CD-ROM | disk | FTP | other *** search
- ' This SUBprocedure provides the interface between Spectra Publishing's
- ' PowerBASIC 2.00 compiler and Novell's BTRIEVE file system on PCDOS/MSDOS
- ' machines.
-
- ' In order to use the SUB, include its source code in your program with the
- ' $INCLUDE metastatement: $INCLUDE "POWERBBT.BAS"
-
- ' Each time you wish to perform a BTRIEVE operation, use the CALL statement
- ' to call the SUB with the following parameters:
-
- ' CALL BTRV(OPERATION%, RETSTATUS%, FCBPOSBLOCK$, DATABUFFER$, _
- ' DATABUFLEN%, KEYBUFFER$, KEYNUMBER%)
-
- ' where: OPERATION% is the BTRIEVE operation code for the desired function.
- ' RETSTATUS% is a BTRIEVE status code returned after the desired
- ' function is attempted.
- ' FCBPOSBLOCK$ is a 128-byte data area containing file control block
- ' (FCB) and position information which must not be changed by
- ' your program.
- ' DATABUFFER$ is a data buffer used to specify special information
- ' such as file specifications, key characteristics, etc. Its
- ' structure will be defined by your program with a FIELD
- ' statement.
- ' DATABUFLEN% is the length of the data buffer, DATABUFFER$.
- ' KEYBUFFER$ is the key buffer.
- ' KEYNUMBER% is the key number to be processed.
-
- ' Important note: The BTRV routine resets the currently-active PowerBASIC
- ' data segment to the default data segment (by executing a DEF SEG state-
- ' ment with no argument). If you set a different segment with DEF SEG in
- ' your main program and then call BTRV, you will need to execute your DEF
- ' SEG statement again (after the call), if you wish to continue using your
- ' segment as PowerBASIC's data segment; otherwise, the default data segment
- ' will be active when BTRV returns to your main program.
-
-
- sub BTRV(Operation%, RetStatus%, FCBPosBlock$, DataBuffer$, DataBufLen%, _
- KeyBuffer$, KeyNumber%)
-
- static VersionDetermined%, BMULTIPresent%, BMULTIProcessID%
- local CriticalErrorVec$ 'holds critical error handler vector
-
- dim ParamBlock%(0:13) 'local array holds 14-word parameter block
-
- %AX = 1 : %BX = 2 : %DX = 4 : %DS = 8 'register equates for use with REG
-
- 'parameter positions within ParamBlock% array
- %DBOfst = 0 : %DBSeg = 1 : %DBLength = 2 : %PosOfst = 3 : %PosSeg = 4
- %FCBOfst = 5 : %FCBSeg = 6 : %OpCode = 7 : %KBOfst = 8 : %KBSeg = 9
- %KeyInfo = 10: %StatOfst = 11 : %StatSeg = 12 : %IfaceID = 13
-
- %FCBPosSize = 128 '128 = correct size for FCB + position info
- %FCBPosLenErr = 23 'status code returned if size exceeded
- %NoBTRIEVEErr = 20 'status code returned if BTRIEVE not loaded
-
-
- 'First, swap critical error handler and check for presence of BTRIEVE
-
- def seg = 0 'use segment zero (DOS INT vectors)
- CriticalErrorVec$ = peek$(&h90,4) 'get critical error handler vector
- poke$ &h90, peek$(&h51A,4) 'tell DOS to handle errors
-
- 'if INT 7B offset = 33 hex, BTRIEVE handler
- if peeki(&h7B * 4) = &h33 then ' has been loaded
- if VersionDetermined% = 0 then 'DOS version has yet to be determined
- incr VersionDetermined% 'set flag since we're determining now
- reg %AX, &h3000 'use DOS function 30 hex to get the
- call interrupt &h21 ' DOS version number in register AX
- if (reg(%AX) AND &h00FF) >= 3 then 'we have DOS 3.00 or above
- reg %AX, &hAB00 'so check to see if BMULTI loaded
- call interrupt &h2F
- if (reg(%AX) AND &h00FF) = 77 then
- BMULTIPresent% = 1 'it is loaded, so flag it
- else
- BMULTIPresent% = 0 'otherwise set flag to zero
- end if
- end if
- end if
- else 'BTRIEVE handler isn't loaded, so warn user
- RetStatus% = %NoBTRIEVEErr
- poke$ &h90, CriticalErrorVec$ 'restore critical error handler
- def seg 'and PB default data segment
- exit sub 'then quit
- end if
-
- if len(FCBPosBlock$) < %FCBPosSize then 'make sure the passed FCBPosBlock$
- RetStatus% = %FCBPosLenErr ' is long enough to hold FCB and
- ' position info -- quit if not
- poke$ &h90, CriticalErrorVec$ 'restore critical error handler
- def seg 'and PB default data segment
- exit sub
- end if
-
-
- 'Now set up 14-word parameter block for the BTRIEVE interrupt
-
- ParamBlock%(%DBOfst) = cvi(mkl$(strptr(DataBuffer$))) 'offset and segment
- ParamBlock%(%DBSeg) = cvi(mkl$(strseg(DataBuffer$))) 'of data buffer
-
- ParamBlock%(%DBLength) = DataBufLen% 'data buffer length
-
- ParamBlock%(%FCBOfst) = cvi(mkl$(strptr(FCBPosBlock$))) 'offset and segment
- ParamBlock%(%FCBSeg) = cvi(mkl$(strseg(FCBPosBlock$))) 'of FCB block
-
- ParamBlock%(%PosOfst) = ParamBlock%(%FCBOfst) + 38 'offset and segment
- ParamBlock%(%PosSeg) = ParamBlock%(%FCBSeg) 'of position block
-
- ParamBlock%(%OpCode) = Operation% 'BTRIEVE operation code
-
- ParamBlock%(%KBOfst) = cvi(mkl$(strptr(KeyBuffer$))) 'offset and segment
- ParamBlock%(%KBSeg) = cvi(mkl$(strseg(KeyBuffer$))) 'of key buffer
-
- ParamBlock%(%KeyInfo) = len(KeyBuffer$)+(KeyNumber%*256) 'key info word
-
- ParamBlock%(%StatOfst) = cvi(mkl$(varptr(RetStatus%))) 'offset and segment
- ParamBlock%(%StatSeg) = cvi(mkl$(varseg(RetStatus%))) 'of status variable
-
- ParamBlock%(%IfaceID) = &h6176 'interface ID
-
-
- 'Now do the interrupt with DS:DX pointing to the parameter block
-
- reg %DX, varptr(ParamBlock%(0))
- reg %DS, varseg(ParamBlock%(0))
-
- if BMULTIPresent% = 0 then 'BMULTI not present, so use INT 7B
- call interrupt &h7B
- else
- do 'use BMULTI to do it
- if BMULTIProcessID% = 0 then 'get process ID if haven't yet
- reg %AX, &hAB01
- else
- reg %AX, &hAB02 'here if we have process ID -- need
- reg %BX, BMULTIProcessID% ' to set it now
- end if
- call interrupt &h2F 'invoke BMULTI
- if (reg(%AX) AND &h00FF) = 0 then exit loop 'go on if done processing
- reg %AX, &h0200 'otherwise allow task
- call interrupt &h7F ' switch and try request
- loop ' again
- if BMULTIProcessID% = 0 then BMULTIProcessID% = reg(%BX) 'assign proc ID
- end if
-
- DataBufLen% = ParamBlock%(%DBLength) 'pass new data buffer length back
-
-
- 'Now restore critical error handler vector and PB's default data segment
-
- poke$ &h90, CriticalErrorVec$
- def seg
-
- end sub