supermario/base/SuperMarioProj.1994-02-09/OS/HFS/BTSVCS.a

1430 lines
43 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: BTSVCS.a
;
; Contains: These routines provide service functions used to access
; and maintain a BTree file.
;
; Copyright: © 1984-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM2> 10/30/92 PN #1046897 Roll in FileMgrPatches.a to BTOpen to set up write
; count in BTOpen
; <SM1> 4/1/92 kc Rolled in FixBTFlush,BTInsertPatch and BTDeletePatch
; from FileMgrPatches.a.
; • Pre-SuperMario comments follow •
; <2> 9/10/91 JSM Add a header.
; <1.3> 5/4/89 KST Fixed a bug in BTDelete, MOVE.W should be MOVE.L
; 5/4/89 KSCT Fixed a bug in BTDelete, MOVE should be a long, not word
; <1.2> 3/2/89 DNF removed references to forROM, HFS now builds identically for ram
; or rom
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <•1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
; <1.0> 2/11/88 BBM Adding file for the first time into EASE…
; 9/25/86 BB Updated to use new MPW equate files.
; 1/20/86 BB Fixed bug on CalBTVars, did not include space for a node pointer
; in the index record size calculation (not patched in ROm75).
; 12/18/85 BB BTInsert now checks for errors returned from InitNode (not
; patched in ROm75).
; 11/20/85 BB Fixed update depth bug in BTDelete (ROM75 patch). Fixed GetNode
; error return bug in BTDelete (ROM75 patch).
; 10/25/85 BB Added vectors for ROM versions.
; 10/22/85 BB Moved BTClose, BTFlush, and BTOpen to BTsvcs from BtIntf.
; 10/21/85 BB Fixed bug in BTGetRecord which was trying to release a node it
; didn't have after getting an IO error.
; 10/14/85 BB Added use of new MOVEQ error equates.
; 10/10/85 BB Fixed BTDelete and BtInsert to use MarkBlock instead of always
; releasing nodes as "dirty". Added use of new MOVEQ equates for
; GetBlock,RelBlock, and FlushCache. Did some minor code clean up.
; 10/9/85 BB Fixed bug in calulation of the size of BTree variables.
; 9/23/85 BB Modified BTInsert to not check for a null node pointer before
; calling RelNode. RelNode now checks for it.
; 9/23/85 BB Modified BTDelete to call ClrNode for nodes being freed.
; 9/3/85 BB Fixed bug in Btdelete that was releasing parent nodes as dirty.
; 8/29/85 BB Fixed bug in BTInsert that was releasing a node twice.
; 8/9/85 BB Added code to maintain leaf record count and 1st and last node
; numbers.
; 8/6/85 BB Updated to use equates for index and leaf node types.
; 7/10/85 BB Removed calls to BTFlush. This is now done by CM and FXM.
; 7/8/85 BB Modified BTInsert and BTDelete to maintain links for index nodes
; and to use the new GetLtSib/GetRtSib interface.
; 6/10/85 BB Added BTSetUP and BTCleanup subroutines.
; 6/5/85 BB Removed use of BTVars for temporary storage of data records.
; 5/30/85 BB Modified BTGetRecord to set up default node and index markers
; for BTree underflow/overflow conditions.
; 5/24/85 BB Added call to BTFlush after an insert or delete.
; 5/24/85 BB Modified all routines to selectively clear BTCB flags.
; 4/21/85 BB Modified BTGetRecord to update current node and record index
; marks after each successful call.
; 3/15/85 BB Modified to use A6 stack.
; 3/11/85 BB Added extend BTree file stuff.
; 2/26/85 BB Finished adding hints.
; 2/21/85 BB Added use of hints.
; 2/18/85 BB Modified to support variable length keys in leaf nodes.
; 2/12/85 BB Added save/restore for scratch registers
; 1/17/85 BB Removed use of BTree Global area (BTG).
; 1/5/85 BB Modified to return pointers to key and data record for BTSearch
; and BTGetRecord. BTDelete also modified to no longer return
; deleted record.
; 1/1/85 BB Modified BTOpen to set up address of external key-compare
; routine (currently "KeyCompare") in BTCB.
; 10/10/84 BB Modified for BTree files.
; 9/27/84 BB New today.
;
;__________________________________________________________________________________
;
; External
; Routines: BTClose - Closes a BTree file.
; BTDelete - Deletes a record from a BTree file given the key.
; BTFlush - Flushes a BTree file.
; BTGetRecord - Gets the next/previous record from a BTree file.
; BTInsert - Inserts a record into a BTree file given the key
; and data record.
; BTOpen - Opens a BTree file.
; BTSearch - Searches a BTree file for a record given the key.
; BTUpdate - Marks the cache buffer containing the specified
; BTree node as updated (dirty).
; Internal
; Subroutines: BTCleanUp - Cleans up after a BTree service call.
; BTSetUp - Sets up for a BTree service call.
; CalBTVars - Calculates the size of the BTree Variable storage
; area (BTVars).
;
;__________________________________________________________________________________
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
Include 'FileMgrPrivate.a'
PRINT ON
PRINT NOGEN
BTSvcs PROC EXPORT
EXPORT BTClose,BTDelete,BTFlush,BTGetRecord,BTInsert,BTOpen,BTSearch
EXPORT BTUpdate
EXPORT vBTClose,vBTDelete,vBTFlush,vBTGetRecord,vBTInsert,vBTOpen
EXPORT vBTSearch,vBTUpdate
IMPORT AllocNode,ExtBTFile,FreeNode
IMPORT BuildIRec,DeleteRec,GetLtSib,GetMaxKey,GetOffset,GetRecA,GetRtSib
IMPORT InitNode,InsertRec,KeyCompare,LocRec,LocTPR,SearchNode
IMPORT UpdDRec,UpdIKey
IMPORT RotateLt,SplitLt,TreeSearch
IMPORT LocBTCB
IMPORT ClrNode,GetNode,RelNode
IMPORT FlushCache,GetBlock,MarkBlock,InitCache,RelBlock
;__________________________________________________________________________________
;
; Routine: BTClose
;
; Function: Closes a BTree file. The BTree Header (BTH) is updated and the
; cache is flushed and trashed for the specified file. The BTCB
; memory is also released.
;
; Input: D0.W - file refnum
;
; Output: D0.W - result code
; 0 = ok
; -n = IO error
;
;__________________________________________________________________________________
BTClose
MOVE.L jBTClose,-(SP) ; jumptable entry for vBTClose <25Oct85>
RTS ; go there <25Oct85>
vBTClose ; 'vectored' BTClose routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D4/A0-A4,-(A6) ; save regs
MOVE.W D0,D3 ; D3 = file refnum
MOVE.W D3,D0 ; locate the BTCB
JSR LocBTCB ;
;
; flush the BTCB and cache buffers for the file
;
JSR BTFlush ; Flush everything first
BNE.S BCExit ; error ->
;
; trash any cache buffers for the file
;
MOVE.W D3,D0 ; file refnum
MOVEQ #kFCTrash,D1 ; set 'trash' option <14Oct85>
MOVEA.L BTCCQptr(A4),A1 ; cache queue ptr
JSR FlushCache ; trash the cache for this file
BNE.S BCExit ; error ->
;
; release BTCB memory
;
MOVEA.L A4,A0 ; release the BTCB
_DisposPtr ;
MOVEA.L FCBSPtr,A4 ; clear BTCB ptr
CLR.L FCBBTCBptr(A4,D3.W) ; ... in FCB
CLR.W D0 ; result = 'ok'
BCExit
MOVEM.L (A6)+,D1-D4/A0-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTClose
;__________________________________________________________________________________
;
; Routine: BTDelete
;
; Function: Deletes a record from a BTree file given the key.
;
; Input: A0.L - address of key
; D0.W - file refnum
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = record not found
; other = error
;__________________________________________________________________________________
BTDelete
MOVE.L jBTDelete,-(SP) ; jumptable entry for vBTDelete <25Oct85>
RTS ; go there <25Oct85>
vBTDelete ; 'vectored' BTDelete routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D5/A0-A4,-(A6) ; save regs
;
; initialize some things
;
BSR BTSetUp ; set up common stuff
CLR.L BTCNodeM(A4) ; invalidate current node mark
SUBA.L A2,A2 ; ...no left node buffer
SUBA.L A3,A3 ; ...no right node buffer
;
; search tree for key
;
JSR TreeSearch ; search for key
MOVEA.L A1,A3 ; A3 = ptr(node buffer)
BNE BDExit1 ; didn't find it ->
MOVE.W D1,D5 ; D5 = record index
;
; delete record from node
;
BDDelete
MOVEA.L A3,A1 ; ptr(node buffer)
MOVE.W D5,D1 ; record index
JSR DeleteRec ; delete it
;; <SM1> FM rolled in for SuperMario…
;; No error checking here, so I assume the file has changed. <8/16/89 KSCT>
ADDQ.L #1,BTCWcount(A4) ; bump write count <8/16/89 KSCT>
MOVEA.L A3,A0 ; ptr(node buffer) <10Oct85>
JSR MarkBlock ; mark it dirty <10Oct85>
TST.W D5 ; delete 1st record ?
BNE.S @1 ; no ->
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required
@1 CMPI.B #NDLeafNode,NDType(A3) ; at leaf level?
BNE.S BDRemove ; no ->
SUB.L #1,BTCNRecs(A4) ; decrement number of leaf records
;
; unlink the node if the last record was deleted
;
BDRemove
TST.W NDNRecs(A3) ; node empty ?
BGT.S BDNxtLev ; no ->
MOVEA.L A3,A0 ; ptr(node buffer)
JSR GetLtSib ; get left sibling node
BNE BDExit1 ; error ->
TST.L D1 ; is there a left sibling ?
BEQ.S @1 ; no ->
MOVE.L NDFlink(A3),NDFlink(A1) ; update forward link
MOVEQ #kRBdirty,D1 ; release <10Oct85>
MOVEA.L A1,A0 ;
JSR RelNode ; ...left node buffer
@1 MOVEA.L A3,A0 ; ptr(node buffer)
JSR GetRtSib ; get right sibling node
BNE BDExit1 ; error ->
TST.L D1 ; is there a right sibling ?
BEQ.S BDUpdPtrs ; no ->
MOVE.L NDBlink(A3),NDBlink(A1) ; update backward link
MOVEQ #kRBdirty,D1 ; release <10Oct85>
MOVEA.L A1,A0 ;
JSR RelNode ; ...right node buffer
;
; update 1st and last node pointers
;
BDUpdPtrs
CMPI.B #NDLeafNode,NDType(A3) ; at leaf level?
BNE.S BDFree ; no ->
TST.L NDBLink(A3) ; backward link = 0?
BNE.S @1 ; no ->
MOVE.L NDFlink(A3),BTCFNode(A4) ; yes, update 1st node number
@1 TST.L NDFLink(A3) ; forward link = 0?
BNE.S BDFree ; no ->
MOVE.L NDBlink(A3),BTCLNode(A4) ; yes, update last node number
;
; free the empty node
;
BDFree
MOVEA.L A3,A0 ; clear the empty node <23Sep85>
JSR ClrNode ; <23Sep85>
MOVEQ #kRBdirty,D1 ; release <10Oct85>
JSR RelNode ; ...node buffer
SUBA.L A3,A3 ; indicate no buffer
MOVE.W BTCLevel(A4),D0 ; locate
JSR LocTPR ; ...TPR
MOVE.L TPRNodeN(A0),D1 ; free
MOVE.W BTCRefNum(A4),D0 ;
JSR FreeNode ; ...the disk node
BSET #BTCDelIRec,BTCFlags(A4) ; indicate index record delete
BCLR #BTCKeyUpd,BTCFlags(A4) ; ...and no key update
;
; move to next level
;
BDNxtLev
SUB.W #1,BTCLevel(A4) ; bump to next level up
BEQ.S BDRoot ; up to root level ->
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ? <03Sep85>
BNE.S @1 ; yes -> <03Sep85>
BTST #BTCDelIRec,BTCFlags(A4) ; index record delete required ? <03Sep85>
BEQ BDExit ; no, all done -> <03Sep85>
@1 MOVE.W BTCLevel(A4),D0 ; locate TPR
JSR LocTPR ; for this level
MOVE.W TPRRIndx(A0),D5 ; D5 = parent record index
MOVE.L TPRNodeN(A0),D2 ; D2 = parent node number
MOVEQ #0,D1 ; get parent node <10Oct85>
JSR GetNode ;
BNE BDExit1 ; error -> <20Nov85>
MOVEA.L A0,A2 ; A2 = ptr(parent node buffer)
;
; update parent key
;
BDUpdKey
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
BEQ.S @1 ; no ->
MOVE.W D5,D0 ; locate
MOVEA.L A2,A1 ;
JSR GetRecA ; ...parent index record
MOVE.L A0,-(SP) ; ...and save it
MOVE.L A3,A1 ; locate 1st key
CLR.W D0 ;
JSR GetRecA ; ...in node
MOVEA.L (SP)+,A1 ; ptr(parent index record)
JSR UpdIKey ; update the key
MOVEA.L A2,A0 ; ptr(parent node buffer) <10Oct85>
JSR MarkBlock ; mark it dirty <10Oct85>
TST.W D5 ; update to 1st key in node ?
BEQ.S @1 ; yes, leave flag set ->
BCLR #BTCKeyUpd,BTCFlags(A4) ; don't need to update next level
@1 MOVEQ #0,D1 ; release child <10Oct85>
MOVE.L A3,A0 ;
JSR RelNode ; ...node buffer
MOVEA.L A2,A3 ; new child node = parent node
MOVE.L D2,D3 ; should be a long, not word <5/4/89>
;
; check if done
;
BCLR #BTCDelIRec,BTCFlags(A4) ; indx rec delete required ? <03Sep85>
BEQ.S @2 ; no ->
BRA BDDelete ; delete parent index record ->
@2 BTST #BTCKeyUpd,BTCFlags(A4) ; another key update required ?
BNE.S BDNxtLev ; yes ->
BRA.S BDExit ; no, all done ->
;
; up to the root, check for an empty tree
;
BDRoot
MOVE.L A3,D0 ; root node released?
BNE.S BDUpdDepth ; no ->
CLR.W BTCDepth(A4) ; set tree to empty state
CLR.L BTCRoot(A4) ;
BRA.S BDExit ; exit ->
;
; update tree depth
;
BDUpdDepth
CMPI.W #1,NDNRecs(A3) ; check # of records left in root
BGT.S BDExit ; > 1, all done ->
TST.B NDType(A3) ; index node ?
BNE.S BDExit ; no, all done ->
SUBQ.W #1,BTCDepth(A4) ; decrement tree depth
MOVEQ #0,D1 ; locate key and data for 1st record <10Oct85>
MOVEA.L A3,A1 ;
JSR LocRec ; ... in node <10Oct85>
MOVE.L (A1),BTCRoot(A4) ; new root = child node <10Oct85>
;
; release the previous root node
;
MOVEA.L A3,A0 ; clear the node buffer <23Sep85>
JSR ClrNode ; <23Sep85>
MOVEQ #kRBdirty,D1 ; release the <10Oct85>
JSR RelNode ; ...node buffer
SUBA.L A3,A3 ; indicate no buffer
MOVE.L D3,D1 ; free
MOVE.W BTCRefNum(A4),D0 ;
JSR FreeNode ; ...the node
; <20Nov85>
; get new root node and check if depth can be reduced again <20Nov85>
; <20Nov85>
MOVE.L BTCRoot(A4),D3 ; D3 = new root node # <20Nov85>
MOVE.L D3,D2 ; get the new root node <20Nov85>
MOVEQ #0,D1 ; <20Nov85>
JSR GetNode ; <20Nov85>
BNE.S BDExit1 ; error -> <20Nov85>
MOVEA.L A0,A3 ; A3 = ptr to node buffer <20Nov85>
BRA.S BDUpdDepth ; check out new root -> <20Nov85>
;
; release last node and exit
;
BDExit
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
CLR.W D0 ; result = ok
BDExit1
MOVE.W D0,-(A6) ; save result code
MOVEA.L A3,A0 ; ptr(node buffer) <23Sep85>
MOVEQ #0,D1 ; <10Oct85>
JSR RelNode ; release it
MOVE.W (A6)+,D0 ; restore result code
BSR BTCleanUP ; clean up
MOVEM.L (A6)+,D1-D5/A0-A4 ; restore regs <29Aug85>
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTDelete
;__________________________________________________________________________________
;
; Routine: BTFlush
;
; Function: Flushes a BTree file. The BTree Header (BTH) is updated and the
; cache is flushed for the specified file.
;
; Input: D0.W - file refnum
;
; Output: D0.W - result code
; 0 = ok
; -n = IO error
;__________________________________________________________________________________
;
; <SM1> FM Rolled in a fix to make sure that we return noErr (FixBTFlush)
; when exiting due to an offline volume!
BTFlush
MOVE.L jBTFlush,-(SP) ; jumptable entry for vBTFlush <25Oct85>
RTS ; go there <25Oct85>
vBTFlush ; 'vectored' BTFlush routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D4/A0-A4,-(A6) ; save regs
MOVE.W D0,D3 ; D3 = file refnum
MOVEA.L FCBsPtr,A1 ; point into FCB array
MOVEA.L FCBVPtr(A1,D3.W),A2 ; point to VCB
TST.W VCBDrvNum(A2) ; volume offline?
BEQ.S BFExitNoErr ; <SM1> FM yes, nothing could have changed ->
JSR LocBTCB ; locate the BTCB
BCLR #BTCdirty,BTCFlags(A4) ; is the BTCB dirty?
BEQ.S BFFlush ; no, just flush cache ->
;
; get BTH from disk
;
MOVEQ #0,D1 ; no options <14Oct85>
MOVEQ #0,D2 ; BTH is disk block 0
JSR GetNode ; get disk block
BNE.S BFExit ; couldn't get it ->
MOVEA.L A0,A3 ; A3 = cache buffer ptr
;
; update BTH from BTCB info
;
MOVE.W #LenMemBTH-1,D0 ; loop index
LEA BTCDepth(A4),A0 ; ptr(source)
LEA lenND(A3),A1 ; ptr(destination)
@4 MOVE.B (A0)+,(A1)+ ; move it
DBRA D0,@4 ; ...in
;
; release cache buffer
;
MOVEQ #kRBdirty,D1 ; release 'dirty' <14Oct85>
MOVEA.L A3,A0 ; cache buffer ptr
JSR RelNode ; release it
BNE.S BFExit ; error ->
;
; flush the cache for this file
;
BFFlush
MOVE.W D3,D0 ; file refnum
MOVEQ #0,D1 ; no FlushCache options <14Oct85>
MOVEA.L BTCCQptr(A4),A1 ; cache queue ptr
JSR FlushCache ; flush it
; BNE.S BFExit ; error -> <25Sep86>
;
; clean up and exit
;
BFExitNoErr MOVEQ #0,D0 ; <SM1> FM clear d0 if there was no err!
BFExit
MOVEM.L (A6)+,D1-D4/A0-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTFlush
;__________________________________________________________________________________
;
; Routine: BTGetRecord
;
; Function: Gets a record from a BTree file. Any previous, current,
; or next record relative to the last BTSearch or BTGetRecord
; operation may be obtained.
;
; Input: D0.W - refnum
; D1.W - selection code
; -n = previous record
; 0 = current record
; +n = next record
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = record not found
; other = error
; A0.L - pointer to key
; A1.L - pointer to data record
; D1.W - size of data record
; D2.L - BTree hint
;__________________________________________________________________________________
BTGetRecord
MOVE.L jBTGetRecord,-(SP) ; jumptable entry for vBTGetRecord <25Oct85>
RTS ; go there <25Oct85>
vBTGetRecord ; 'vectored' BTGetRecord routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D3-D5/A2-A4,-(A6) ; save regs
;
; initialize some things
;
BSR BTSetUp ; set up common stuff
MOVE.W D1,D5 ; D5 = selection code
SUBA.L A3,A3 ; indicate no node buffer
;
; set up starting position in BTree
;
MOVE.W BTCIndexM(A4),D4 ; current index mark
MOVE.L BTCNodeM(A4),D3 ; current node mark
BNE.S @1 ; valid node number ->
MOVEQ #BTnotfound,D0 ; set return code <14Oct85>
BRA.S GRExit1 ; exit ->
@1 ADD.W D5,D4 ; adjust index
;
; locate the record relative to the starting position
;
GRLocate
BSR.S GRGetNode ; get the node
BNE.S GRExit1 ; error ->
@1 TST.W D4 ; check index bounds
BLT.S @3 ; < 0, get previous node ->
MOVE.W NDNRecs(A3),D1 ;
CMP.W D1,D4 ;
BLT.S GRGotIt ; < #recs, got it ->
MOVE.L NDFlink(A3),D0 ; get next node number
BEQ.S @2 ; don't have one ->
MOVE.L D0,D3 ; D3 = next node number
SUB.W D1,D4 ; adjust index
BRA.S GRLocate ; try next node
@2 MOVE.W D1,D4 ; new index mark = index of last record
SUBQ.W #1,D4 ;
BRA.S @5 ; use common exit ->
@3 MOVE.L NDBlink(A3),D0 ; get previous node number
BEQ.S @4 ; don't have one ->
MOVE.L D0,D3 ; D3 = previous node number
BSR.S GRGetNode ; get the previous node
BNE.S GRExit1 ; error ->
ADD.W NDNRecs(A3),D4 ; adjust index
BRA.S @1 ; check bounds again ->
@4 MOVEQ #0,D4 ; new index mark = index of first record
@5 MOVE.L D3,BTCNodeM(A4) ; new node mark
MOVE.W D4,BTCIndexM(A4) ; new index mark
MOVEQ #BTnotfound,D0 ; set return code <14Oct85>
BRA.S GRExit1 ; exit ->
;
; found the record, set up pointers to key and data
;
GRGotIt
MOVE.W D4,D1 ; record index
MOVEA.L A3,A1 ; ptr(node buffer)
JSR LocRec ; locate key and data record
MOVE.L D3,BTCNodeM(A4) ; update current node
MOVE.W D4,BTCIndexM(A4) ; ...and index markers
;
; release node buffer and exit
;
GRExit
CLR.W D0 ; result = ok
GRExit1
MOVEM.L D0-D1/A0-A1,-(A6) ; save return stuff
BSR.S GRRelNode ; release node buffer
MOVEM.L (A6)+,D0-D1/A0-A1 ; restore return stuff
MOVE.L D3,D2 ; hint = node number
BSR BTCleanUP ; clean up
MOVEM.L (A6)+,D3-D5/A2-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTGetRecord
;
; GRGetNode subroutine - releases current node and gets the next node.
; A3.L = ptr(current node buffer)
; D3.L = next node number
;
GRGetNode
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
BSR.S GRRelNode ; release current node
MOVEQ #0,D1 ; no GetBlock options <10Oct85>
MOVE.L D3,D2 ; node number
JSR GetNode ; get the node
BNE.S @1 ; error -> <21Oct85>
MOVEA.L A0,A3 ; A3 = ptr(next node buffer)
@1 MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit GRGetNode
;
; GRRelNode subroutine - releases current node buffer.
; A3.L = ptr(current node buffer)
;
GRRelNode
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
MOVEA.L A3,A0 ; ptr(node buffer) <23Sep85>
JSR RelNode ; release the node
SUBA.L A3,A3 ; indicate no node buffer
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit GRRelNode
;__________________________________________________________________________________
;
; Routine: BTInsert
;
; Function: Inserts a record into a BTree file given the
; record key and data.
;
; Input: A0.L - address of key
; A1.L - address of record data
; D0.W - file refnum
; D1.W - size of record
;
; Output: D0.W - result code
; 0 = ok
; BTexists = key already exists
; other = error
; D2.L - BTree hint
;__________________________________________________________________________________
BTInsert
MOVE.L jBTInsert,-(SP) ; jumptable entry for vBTInsert <25Oct85>
RTS ; go there <25Oct85>
vBTInsert ; 'vectored' BTInsert routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/D3-D7/A0-A4,-(A6) ; save registers
JSR LocBTCB ; locate BTCB
MOVE.L A1,D7 ; D7 = ptr(record)
MOVE.W D1,D6 ; D6 = size of record
MOVE.L A0,D5 ; D5 = ptr(key)
;
; make sure there is enough file space for a worst case split
;
MOVEQ #1,D3 ; required space (in nodes) =
ADD.W BTCDepth(A4),D3 ; tree depth + 1
CMP.L BTCFree(A4),D3 ; enough space?
BLE.S BIInit ; yes ->
@1 JSR ExtBTFile ; extend the file
BNE BIExit2 ; couldn't do it ->
CMP.L BTCFree(A4),D3 ; enough space now?
BGT.S @1 ; no ->
;
; initialize some things
;
BIInit
MOVE.W BTCRefNum(A4),D0 ; set up common stuff
BSR BTSetUp ;
MOVEM.L D6/D7,-(A6) ;save input record size and ptr
MOVEQ #0,D4 ; indicate no parent node buffer <29Aug85>
SUBA.L A2,A2 ; ...no left node buffer
SUBA.L A3,A3 ; ...no right node buffer
CLR.L BTCNodeM(A4) ; invalidate current node mark
;
; build BTree record consisting of input key with a junk data record
;
MOVEA.L BTCVarPtr(A4),A1 ; dest = record buffer
LEA BTVRecord(A1),A1 ;
MOVEA.L D5,A0 ; source = input key
MOVEQ #0,D0 ; get key length
MOVE.B (A0),D0 ;
ADDQ.L #2,D0 ; include length byte
LSR.L #1,D0 ;
LSL.L #1,D0 ; ...and adjust to word boundry
ADD.W D0,D6 ; total size = key size + data size
_BlockMove ; move in the key
ADDQ.W #1,D6 ; adjust total size to word boundry
LSR.W #1,D6 ;
LSL.W #1,D6 ;
MOVE.L A1,D7 ; D7 = ptr(Btree record)
;
; search tree for key
;
BISearch
JSR TreeSearch ; search for key
MOVEA.L A1,A3 ; A3 = ptr(right node buffer)
BNE.S @1 ; key not found or error ->
MOVEQ #BTexists,D0 ; error, it already exists <14Oct85>
BRA BIExit1 ; exit ->
@1 CMP.W #BTnotfound,D0 ; key not found ?
BNE BIExit1 ; no, must be IO error ->
MOVE.L D2,D3 ; D3 = right node number
MOVE.W D1,D5 ; D5 = insert index
;
; if tree is empty, add 1st leaf node
;
TST.W BTCLevel(A4) ; tree empty ?
BGT.S BIInsert ; no ->
MOVE.W BTCRefNum(A4),D0 ; file refnum
JSR AllocNode ; allocate the node
BNE BIExit1 ; error ->
MOVE.L D1,D3 ; D3 = new node number
JSR InitNode ; get an initialized node
BNE BIExit1 ; error -> <18Dec85>
MOVEA.L A0,A3 ; A3 = ptr(new root node)
MOVE.B #NDLeafNode,NDType(A3) ; type = leaf node
MOVEQ #1,D0 ; node height = 1
MOVE.B D0,NDNHeight(A3) ;
MOVE.W D0,BTCDepth(A4) ; tree depth = 1
MOVE.L D3,BTCRoot(A4) ; new root node number
MOVE.L D3,BTCFNode(A4) ; 1st and last node pointers
MOVE.L D3,BTCLNode(A4) ;
MOVE.W #1,BTCLevel(A4) ; current level = 1
;
; try a simple insert first
;
BIInsert
MOVEA.L D7,A0 ; ptr(record)
MOVE.W D6,D0 ; record size
MOVEA.L A3,A1 ; ptr(node buffer)
MOVE.W D5,D1 ; insert index
JSR InsertRec ; try to insert it
BNE.S BIRotate ; didn't make it ->
TST.W D5 ; insert a new 1st record ?
BNE.S BIInsDone ; no, insert complete ->
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required
BRA.S BIInsDone ; insert complete ->
;
; insert didn't work, try rotation into left sibling node
;
BIRotate
MOVEA.L A3,A0 ; ptr(node buffer)
JSR GetLtSib ; get left sibling node
BNE BIExit1 ; error ->
TST.L D1 ; is there a left sibling ?
BEQ.S BISplit ; no ->
MOVE.L D1,D2 ; D2 = left node number
MOVEA.L A1,A2 ; A2 = ptr(left node buffer)
MOVEA.L D7,A0 ; ptr(record)
MOVE.W D6,D0 ; record size
MOVE.W D5,D1 ; insert index
JSR RotateLt ; try rotating left
BNE.S BISplit ; didn't make it ->
BRA.S BISplit1 ; use common code -> <10Oct85>
;
; rotate didn't work, got to split
;
BISplit MOVEA.L D7,A0 ; ptr(record)
MOVE.W D6,D0 ; record size
MOVE.W D5,D1 ; insert index
JSR SplitLt ; split left
BEQ.S @1 ; ok ->
MOVEQ #BTnoFit,D0 ; result = 'no fit' <14Oct85>
BRA BIExit1 ; exit ->
@1 BSET #BTCNewIRec,BTCFlags(A4) ; indicate new index record required <10Oct85>
BISplit1 ;<10Oct85>
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required <10Oct85>
MOVE.W D1,D5 ; D5 = new record index <10Oct85>
MOVEA.L A2,A0 ; mark the left node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
;
; completed the record insert, clean up
;
BIInsDone
;; <SM1> FM
;; if we get to here the file has changed, even we exit with error from <SM1>
;; here on. <8/16/89 KSCT> <SM1>
ADDQ.L #1,BTCWcount(A4) ; bump write count <8/16/89 KSCT> <SM1>
MOVEA.L A3,A0 ; mark the right node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
CMPI.B #NDleafNode,NDType(A1) ; leaf level?
BNE.S BICkDone ; no ->
MOVEM.L (A6),A0/D0 ; get input record ptr and size
JSR UpdDRec ; replace the junk data record
ADD.L #1,BTCNRecs(A4) ; bump leaf record count
MOVE.W D5,BTCIndexM(A4) ; save index marker
MOVE.L D3,D0 ; assume right node number
CMPA.L A3,A1 ; is new record in right node?
BEQ.S @1 ; yes ->
MOVE.L D2,D0 ; no, use left node number
@1 MOVE.L D0,BTCNodeM(A4) ; save node marker
;
; Check if all done
;
BICkDone
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
BNE.S BINxtLev ; yes, move to next level ->
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
BEQ BIExit ; no, all done ->
;
; move to next level
;
BINxtLev
SUB.W #1,BTCLevel(A4) ; bump to next level up
BEQ BIRoot ; up to root level ->
MOVE.W BTCLevel(A4),D0 ; locate TPR
JSR LocTPR ; for this level
MOVE.W TPRRIndx(A0),D5 ; D5 = parent record index
MOVE.L TPRNodeN(A0),D3 ; D3 = parent node number
MOVE.L D2,-(A6) ; save D2
MOVEQ #0,D1 ; get parent node <10Oct85>
MOVE.L D3,D2 ;
JSR GetNode ;
BNE BIExit1 ; error ->
MOVE.L A0,D4 ; D4 = ptr(parent node buffer)
MOVE.L (A6)+,D2 ; restore D2
;
; update parent key
;
BIUpdKey
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
BEQ.S @1 ; no ->
MOVE.W D5,D0 ; locate
MOVEA.L D4,A1 ;
JSR GetRecA ; ...parent index record
MOVE.L A0,-(SP) ; ...and save it
MOVEA.L A3,A1 ; locate 1st key
CLR.W D0 ;
JSR GetRecA ; ...in right node
MOVEA.L (SP)+,A1 ; ptr(parent index record)
JSR UpdIKey ; update the key
MOVEA.L D4,A0 ; mark the parent node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
TST.W D5 ; update to 1st key in node ?
BEQ.S @1 ; yes, leave flag set ->
BCLR #BTCKeyUpd,BTCFlags(A4) ; don't need to update next level
@1 MOVEQ #0,D1 ; release <10Oct85>
MOVEA.L A3,A0 ;
JSR RelNode ; ... right node buffer
MOVEA.L D4,A3 ; parent is new right node
MOVEQ #0,D4 ; indicate no parent node buffer <29Aug85>
;
; build new index record pointing at new left node
;
BINewRec
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
BEQ.S @1 ; no ->
MOVEA.L A2,A1 ; left node
MOVE.L D2,D0 ; left node number
JSR BuildIRec ; build index record
@1 MOVEQ #0,D1 ; release <10Oct85>
MOVEA.L A2,A0 ;
JSR RelNode ; ... left node buffer
SUBA.L A2,A2 ; indicate no left node
;
; set up for insert of new index record
;
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
BEQ BICkDone ; no, check if done ->
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
LEA BTVRecord(A0),A0 ;
MOVE.L A0,D7 ; D7 = ptr to new record
JSR GetMaxKey ; max key length + 4 <10Oct85>
ADDQ.W #4,D0 ; = size of index record <10Oct85>
MOVE.W D0,D6 ; D6 = size of new record <10Oct85>
BCLR #BTCNewIRec,BTCFlags(A4) ; clear new index rec flag
BRA BIInsert ; insert new index record ->
;
; we updated the root, must add a level if it was split
;
BIRoot
BTST #BTCNewIRec,BTCFlags(A4) ; was root node split ?
BEQ.S BIExit ; no, all done ->
;
; set up a new root index node
;
MOVE.W BTCRefNum(A4),D0 ; volume refnum
JSR AllocNode ; allocate the node
BNE.S BIExit1 ; error ->
MOVE.L D1,D3 ; D3 = new root node number
MOVE.L D3,D1 ; new node number
JSR InitNode ; get an initialized node
BNE.S BIExit1 ; error -> <18Dec85>
MOVE.L A0,D4 ; D4 = ptr(new root node buffer)
MOVE.B #NDIndxNode,NDType(A0) ; type = index node
MOVEQ #1,D0 ; node height
ADD.W BTCDepth(A4),D0 ; = previous depth +1
MOVE.B D0,NDNHeight(A0) ;
;
; add index record for left node
;
MOVEA.L A2,A1 ; build index record
MOVE.L D2,D0 ;
JSR BuildIRec ; ...for left node
JSR GetMaxKey ; max key length + 4 <10Oct85>
ADDQ.W #4,D0 ; = size of index record <10Oct85>
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
LEA BTVRecord(A0),A0 ;
MOVEA.L D4,A1 ; ptr(root node buffer)
CLR.W D1 ; insert index = 0
JSR InsertRec ; insert it
;
; add index record for right node (previous root)
;
MOVE.W #1,D0 ; get node number
JSR LocTPR ;
MOVE.L TPRNodeN(A0),D0 ; ...of previous root
MOVEA.L A3,A1 ; ptr(node buffer)
JSR BuildIRec ; build index record
JSR GetMaxKey ; max key length + 4 <10Oct85>
ADDQ.W #4,D0 ; = size of index record <10Oct85>
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
LEA BTVRecord(A0),A0 ;
MOVEA.L D4,A1 ; ptr(root node buffer)
MOVE.W #1,D1 ; insert index = 1
JSR InsertRec ; insert it
MOVEA.L D4,A0 ; mark the new root node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
;
; update BTCB
;
ADD.W #1,BTCDepth(A4) ; add a level
MOVE.L D3,BTCRoot(A4) ; new root node number
;
; clean up and exit
;
BIExit
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
CLR.W D0 ; result = ok
BIExit1
MOVE.W D0,-(A6) ; save result code
MOVEA.L A2,A0 ; ptr(left node buffer) <23Sep85>
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
JSR RelNode ; release it
MOVEA.L A3,A0 ; ptr(right node buffer) <23Sep85>
JSR RelNode ; release it
MOVEA.L D4,A0 ; ptr(parent node buffer) <23Sep85>
JSR RelNode ; release it
MOVE.W (A6)+,D0 ; restore result code
MOVE.L BTCNodeM(A4),D2 ; return hint (node number)
CLR.L BTCNodeM(A4) ; invalidate current record markers
BSR BTCleanUP ; clean up
ADDQ.L #8,A6 ; deallocate saved stuff
BIExit2
MOVEM.L (A6)+,D1/D3-D7/A0-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTInsert
;__________________________________________________________________________________
;
; Routine: BTOpen
;
; Function: Opens a BTree file. The data fork for the specified file
; must be already open. A BTCB for the file is allocated and
; initialized. The BTH info is read from disk and copied into the
; BTCB.
;
; Input: D0.W - file refnum
; A0.L - pointer to key compare routine
; A1.L - pointer to cache queue
;
; Output: D0.W - result code
; 0 = ok
; -n = FS Open error
; BTnoBTCB = no available BTCB
;__________________________________________________________________________________
BTOpen
MOVE.L jBTOpen,-(SP) ; jumptable entry for vBTOpen <25Oct85>
RTS ; go there <25Oct85>
vBTOpen ; 'vectored' BTOpen routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D5/A0-A4,-(A6) ; save regs
MOVE.W D0,D3 ; D3 = file refnum
MOVE.L A0,D4 ; D4 = ptr(key compare routine)
MOVE.L A1,D5 ; D5 = cache queue ptr
;
; allocate and initialize a BTCB
;
MOVE.L #lenBTCB,D0 ; allocate space for BTCB
_NewPtr ,SYS,CLEAR ;
BNE BOExit1 ; couldn't get it ->
MOVEA.L A0,A4 ; A4 = BTCB ptr
MOVEA.L FCBSPtr,A3 ; A3 = start of FCB array
MOVE.L A4,FCBBTCBptr(A3,D3.W) ; set BTCB ptr in FCB
MOVE.W D3,BTCRefNum(A4) ; set refnum
MOVE.L D4,BTCKeyCR(A4) ; set ptr(key compare routine)
MOVE.L D5,BTCCQptr(A4) ; set ptr to cache queue
;
; get BTH from disk
;
MOVE.W D3,D0 ; file refnum
MOVEA.L D5,A1 ; cache queue ptr
MOVEQ #0,D1 ; no GetBlock options <14Oct85>
MOVEQ #0,D2 ; BTH is block 0
JSR GetBlock ; get the block
BNE.S BOExit1 ; couldn't get it ->
MOVEA.L A0,A2 ; A2 = cache buffer ptr
;
; make sure the BTree header node is ok
;
BOChkHdr
LEA lenND(A2),A0 ; A0 = ptr to BTH
MOVE.W BTHNodeSize(A0),D0 ; node size
BEQ.S BOBadHdr ; node size = 0, error ->
MOVE.W D0,D1 ;
ANDI.W #$1FF,D1 ;
BNE.S BOBadHdr ; node size not 512 multiple, error ->
MOVE.L FCBPLen(A3,D3.W),D2 ; physical length
DIVU D0,D2 ; physical length / node size
SWAP D2 ; = # of nodes
CLR.W D2 ;
SWAP D2 ;
CMP.L BTHNNodes(A0),D2 ; same # as in BTH?
BNE.S BOBadHdr ; no, error ->
CMP.L BTHFree(A0),D2 ; free count < # of nodes?
BLO.S BOBadHdr ; no, error ->
SUBQ.L #1,D2 ; D2 = max node #
CMPI.B #BTMaxDepth,BTHDepth(A0) ; tree depth <= max?
BHI.S BOBadHdr ; no, error ->
CMP.L BTHRoot(A0),D2 ; root node # <= max?
BLO.S BOBadHdr ; no error ->
CMP.L BTHFNode(A0),D2 ; 1st leaf node # <= max?
BLO.S BOBadHdr ; no error ->
CMP.L BTHLNode(A0),D2 ; last node # <= max?
BHS.S BOCpyBTH ; yes ->
BOBadHdr
MOVEQ #BTBadHdr,D0 ; result = 'bad header node' <14Oct85>
BRA.S BOExit ; ->
;
; copy BTH into BTCB
;
BOCpyBTH
MOVE.W #LenMemBTH-1,D0 ; loop index
LEA lenND(A2),A0 ; ptr(source)
LEA BTCDepth(A4),A1 ; ptr(dest)
@1 MOVE.B (A0)+,(A1)+ ; move it
DBRA D0,@1 ; ...in
MOVE.L #WCSigLong,BTCWcount(A4) ; set write count <PN>
CLR.W D0 ; result = 'ok'
;
; release header block and exit
;
BOExit
MOVE.W D0,-(A6) ; save result code
MOVEA.L D5,A1 ; cache queue ptr
MOVEQ #0,D1 ; release 'clean' <14Oct85>
MOVEA.L A2,A0 ; cache buffer ptr
JSR RelBlock ; release it
BEQ.S @1 ; ok ->
MOVE.W D0,(A6) ; replace previous result code
@1 MOVE.W (A6)+,D0 ; restore result code
BOExit1
MOVEM.L (A6)+,D1-D5/A0-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTOpen
;__________________________________________________________________________________
;
; Routine: BTSearch
;
; Function: Searches a BTree file for a record given the key. If a hint is
; given, the BTree node identified by that hint is obtained and
; searched first. Then, if the record is not found, a normal tree
; search is performed.
;
; Input: A0.L - pointer to key
; D0.W - file refnum
; D2.L - BTree hint
; 0 = no hint
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = record not found
; other = error
; A0.L - pointer to key
; A1.L - pointer to data record
; D1.W - size of data record
; D2.L - new BTree hint
;__________________________________________________________________________________
BTSearch
MOVE.L jBTSearch,-(SP) ; jumptable entry for vBTSearch <25Oct85>
RTS ; go there <25Oct85>
vBTSearch ; 'vectored' BTSearch routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D3-D7/A2-A4,-(A6) ; save regs
;
; initialize some things
;
BSR BTSetUp ; set up common stuff
MOVEA.L A0,A3 ; A3 = ptr to key
SUBA.L A2,A2 ; indicate no node buffer
;
; go directly to the leaf node if hint is given
;
TST.L D2 ; hint given?
BEQ.S BSTSrch ; no, do tree search ->
MOVEQ #0,D1 ; get target node <10Oct85>
JSR GetNode ;
BNE.S BSExit ; error ->
MOVEA.L A0,A2 ; A2 = ptr(node buffer)
CMPI.B #NDLeafNode,NDType(A0) ; leaf node?
BNE.S @1 ; no ->
TST.W NDNRecs(A0) ; node empty?
BLE.S @1 ; yes ->
MOVEA.L A3,A0 ; search node for key
MOVEA.L A2,A1 ;
JSR SearchNode ;
BEQ.S BSTSrch1 ; found it ->
@1 MOVEA.L A2,A0 ; release node buffer
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
JSR RelNode ;
BNE.S BSExit ; error ->
;
; search tree for key
;
BSTSrch
MOVEA.L A3,A0 ; ptr to key
JSR TreeSearch ; search tree for key
MOVEA.L A1,A2 ; A2 = ptr(node buffer)
BEQ.S BSTSrch1 ; key found ->
CMP.W #BTnotfound,D0 ; key not found error ?
BNE.S BSExit1 ; no, must be IO error ->
BSTSrch1 MOVE.W D1,D5 ; D5 = record index
MOVE.W D0,-(A6) ; save search result
;
; update current markers in BTCB
;
MOVE.L D2,BTCNodeM(A4) ; update current node mark
MOVE.W D5,BTCIndexM(A4) ; ... and record index mark
;
; set up pointers to key and data record
;
TST.W (A6) ; record found?
BNE.S BSExit ; no ->
MOVE.W D5,D0 ; record index
MOVEA.L A2,A1 ; ptr(node buffer)
JSR LocRec ; locate the record
;
; release node buffer and exit
;
BSExit
MOVEM.L D1-D2/A0-A1,-(A6) ; save return stuff
MOVEA.L A2,A0 ; ptr(node buffer) <23Sep85>
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
JSR RelNode ; release it
MOVEM.L (A6)+,D1-D2/A0-A1 ; restore return stuff
MOVE.W (A6)+,D0 ; restore search result
BSExit1
BSR.S BTCleanUP ; clean up
MOVEM.L (A6)+,D3-D7/A2-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTSearch
;__________________________________________________________________________________
;
; Routine: BTUpdate
;
; Function: Marks a buffer containing the specified BTree node as being
; updated (dirty).
;
; Input: D0.L - file refnum
; D2.L - BTree hint (node number of dirty node)
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = node not found
; other = IO error
;__________________________________________________________________________________
BTUpdate
MOVE.L jBTUpdate,-(SP) ; jumptable entry for vBTUpdate <25Oct85>
RTS ; go there <25Oct85>
vBTUpdate ; 'vectored' BTUpdate routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/A0-A1/A4,-(A6) ; save regs
JSR LocBTCB ; locate BTCB
MOVEQ #kGBexist,D1 ; indicate existing cache block <10Oct85>
JSR GetNode ; get the node
BNE.S BUExit ; error ->
MOVEQ #kRBdirty,D1 ; indicate dirty buffer
JSR RelNode ; release the node
BNE.S BUExit ; error ->
CLR.W D0 ; indicate no error
BUExit
MOVEM.L (A6)+,D1/A0-A1/A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit BTUpdate
;__________________________________________________________________________________
;
; Internal Subroutines
;__________________________________________________________________________________
;__________________________________________________________________________________
;
; Subroutine: BTCleanUp (BTree Clean Up)
;
; Function: Cleans up after a BTree service call. Space for the BTree
; variable storage area (BTVars) is released and the pointer to
; BTVars in the BTCB is cleared.
;
; Input: A4.L - pointer to BTCB
;
; Output: none
;__________________________________________________________________________________
BTCleanUp
MOVE.L D0,-(SP) ; save registers
BSR.S CalBTVars ; calculate size of BTVars
ADDA.L D0,A6 ; remove BTVars from A6 stack
CLR.L BTCVarPtr(A4) ; clear pointer in BTCB
MOVE.L (SP)+,D0 ; restore registers
RTS ; exit BTCleanUp
;__________________________________________________________________________________
;
; Subroutine: BTSetUp (BTree Set Up)
;
; Function: Sets up for a BTree service call. The BTCB is located and space
; for the BTree variable storage area (BTVars) is allocated on the
; A6 stack. A pointer to BTVars is saved in the BTCB. All call-
; specific status flags in the BTCB are also cleared.
;
; Input: D0.W - file refnum
;
; Output: A4.L - pointer to BTCB
;__________________________________________________________________________________
BTSetUp
MOVE.L D0,-(SP) ; save registers
JSR LocBTCB ; locate the BTCB
BSR.S CalBTVars ; calculate size of BTVars
SUBA.L D0,A6 ; allocate space on A6 stack
MOVE.L A6,BTCVarPtr(A4) ; save pointer in BTCB
BCLR #BTCNewIRec,BTCFlags(A4) ; clear status flags
BCLR #BTCDelIRec,BTCFlags(A4) ;
BCLR #BTCKeyUpd,BTCFlags(A4) ;
MOVE.L (SP)+,D0 ; restore registers
RTS ; exit BTSetUp
;__________________________________________________________________________________
;
; Subroutine: CalBTVars (Calculate size of BTVars)
;
; Function: Calculates the size of the BTree variable storage area (BTVars).
;
; Input: A4.L - pointer to BTCB
;
; Output: D0.L - size of BTVars
;__________________________________________________________________________________
CalBTVars
JSR GetMaxKey ; get max key size <10Oct85>
ADDI.W #lenTPT+4,D0 ; size of BTVars = length of TPT <20Jan86>
RTS ; exit CalBTVars
END