; ; Hacks to match MacOS (most recent first): ; ; 8/3/92 Re-routed the unused function ExtBTUpdate through the trap table. ; 9/2/94 SuperMario ROM source dump (header preserved below) ; ; ; File: BTreeSvcs.a ; ; Contains: These routines provide service functions used to access ; and maintain a BTree file. ; ; Modified for Sys7.0 B*tree Manager by Kenny SC. Tung ; ; Copyright: © 1984-1992 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 4/1/92 kc Changed the name prefex used to distinguish ; routines used by the external B-Tree manager ; from the versions used by the File System. ; • Pre-SuperMario comments follow • ; <13> 9/16/91 JSM Cleanup header. ; <12> 2/21/91 KST dnf, #83596: Do not check for volume offline. ; <11> 11/12/90 dnf include FileMgrPrivateEqu.a ; <10> 9/27/90 KST Documentation changes only. ; <9> 8/3/90 KST ExtBTFlush should't call FlushCache directly. It will call FS's ; flushfile only if D5 flag is set now. ; <8> 4/11/90 KST Use ExtBTMaxDepth and related equates. ; <7> 4/5/90 KST make btDebug symbol default to 0. ; <6> 4/4/90 KST BTInsert didn't check for MaxDepth limit and returns no error. ; <5> 2/22/90 KST Documentation change and cleanup. ; <4> 2/16/90 KST Take out debugger code. ; <3> 2/16/90 KST Adding ExtGetUpdateHdr, ExtUpdateHdr routines for "RelMap" change. ; <2> 2/12/90 KST Adding documentation for BTInsert using new buffer scheme. ; 9/27/89 KSCT It used to use cache queue ptr from BTCCQptr(A4).now we pass ; SysCtlCPtr in BTFlush. The code will run on 7.0 without ; RamCAche. ; 8/31/89 KSCT We can't mark block before Updating the leaf record because of ; the new buffer scheme, not cache ; 8/29/89 KSCT Fixed 2 bugs in BTSearch. It branches to the wrong label ; (BSExit). This will causing a crash if the node hint is bad or ; the node is bad. ; 5/4/89 KSCT Fixed a bug in BTDelete, MOVE should be a long, not word. ; 4/11/89 KSCT Fixing a serious bug that B*Tree grows without checking the ; depth limit. ; 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 ExtInitNode (not ; patched in ROm75). ; 11/20/85 BB Fixed update depth bug in BTDelete (ROM75 patch). Fixed ExtGetNode ; 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 ExtBTSvcs 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. ; 10/1/85 LAK Changed to .Include TFSEqu for cache, BTree equates. ; 9/23/85 BB Modified BTDelete to call ExtClrNode for nodes being freed. ; 9/23/85 BB Modified BTInsert to not check for a null node pointer before ; calling ExtRelNode. ExtRelNode now checks for it. ; 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 ExtGetLtSib/ExtGetRtSib 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. ; ExtBTUpdate - 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 'BtreeEqu.a' INCLUDE 'BtreePrivate.a' ; Use ExtBTMaxDepth <11Apr90> include 'FileMgrPrivate.a' PRINT ON PRINT NOGEN IF &trim(&type('btDebug')) = 'UNDEFINED' THEN btDebug EQU 0 ENDIF ExtBTSvcs PROC EXPORT EXPORT ExtBTClose,ExtBTDelete,ExtBTFlush,ExtBTGetRecord,ExtBTInsert,ExtBTSearch ; EXPORT ExtBTUpdate Export ExtGetUpdateHdr, ExtUpdateHdr ; <16Feb90> IMPORT ExtAllocNode,ExtExtBTFile,ExtFreeNode IMPORT ExtBuildIRec,ExtDeleteRec,ExtGetLtSib,ExtGetMaxkey,ExtGetRecA,ExtGetRtSib IMPORT ExtInitNode,ExtInsertRec,ExtLocRec,ExtLocTPR,ExtSearchNode IMPORT ExtUpdDRec,ExtUpdIKey, ExtLocBTCB IMPORT ExtRotateLt,ExtSplitLT,ExtTreeSearch IMPORT ExtClrNode,ExtGetNode,ExtRelNode IMPORT ExtMarkBlock, ExtWriteBlock, ExtDoAOCRWF ; ;__________________________________________________________________________________ ; ; 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. ; Note: ExtBTFlush only flushes buffers to FS DiskCache not to disk. ; Input: D0.W - file refnum ; ; Output: D0.W - result code ; 0 = ok ; -n = IO error ; 25Sep89 KSCT Don't call FlushCache, it is called in ExtBTFlush. ;__________________________________________________________________________________ ExtBTClose ; 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.W D3,D0 ; locate the BTCB JSR ExtLocBTCB ; ; ; flush the BTCB and cache buffers for the file MOVEQ #0,D5 ; clear flag so that it will not flush fs cache JSR ExtBTFlush ; Flush everything first BNE.S BCExit ; error -> ; release BTCB memory ; @2 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-D5/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 ;__________________________________________________________________________________ ExtBTDelete ; ; 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 ExtTreeSearch ; 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 ExtDeleteRec ; delete it MOVEA.L A3,A0 ; ptr(node buffer) <10Oct85> JSR ExtMarkBlock ; 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 ExtGetLtSib ; 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 ExtRelNode ; ...left node buffer @1 MOVEA.L A3,A0 ; ptr(node buffer) JSR ExtGetRtSib ; 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 ExtRelNode ; ...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 ExtClrNode ; <23Sep85> MOVEQ #kRBdirty,D1 ; release <10Oct85> JSR ExtRelNode ; ...node buffer SUBA.L A3,A3 ; indicate no buffer MOVE.W BTCLevel(A4),D0 ; locate JSR ExtLocTPR ; ...TPR MOVE.L TPRNodeN(A0),D1 ; free MOVE.W BTCRefNum(A4),D0 ; JSR ExtFreeNode ; ...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 ExtLocTPR ; 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 ExtGetNode ; 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 ExtGetRecA ; ...parent index record MOVE.L A0,-(SP) ; ...and save it MOVE.L A3,A1 ; locate 1st key CLR.W D0 ; JSR ExtGetRecA ; ...in node MOVEA.L (SP)+,A1 ; ptr(parent index record) JSR ExtUpdIKey ; update the key MOVEA.L A2,A0 ; ptr(parent node buffer) <10Oct85> JSR ExtMarkBlock ; write it back <20Feb90> 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 ExtRelNode ; ...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 ExtLocRec ; ... 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 ExtClrNode ; <23Sep85> MOVEQ #kRBdirty,D1 ; release the <10Oct85> JSR ExtRelNode ; ...node buffer SUBA.L A3,A3 ; indicate no buffer MOVE.L D3,D1 ; free MOVE.W BTCRefNum(A4),D0 ; JSR ExtFreeNode ; ...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 ExtGetNode ; <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 ExtRelNode ; 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 ; A4.L - BTCB ; D5.B - Write flag, If set then flush file system cache. ; Output: D0.W - result code ; 0 = ok ; -n = IO error ; 30Jul90 KST Flush B*Tree private cache buffers for the specific file. ; Only call FlushCache if D5 flag is set. ;__________________________________________________________________________________ ExtBTFlush ; '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 ; we have the BTCB already ; JSR ExtLocBTCB ; locate the BTCB BCLR #BTCdirty,BTCFlags(A4) ; is the BTCB dirty? BEQ.S BFFlush ; no, just flush cache -> BSR.S ExtGetUpdateHdr ; get BTH from disk in A3 and update it BNE.S BFExit ; can't get it <2/16/90> ; release cache buffer MOVEQ #kRBdirty,D1 ; release 'dirty' <14Oct85> MOVEA.L A3,A0 ; cache buffer ptr JSR ExtRelNode ; release it BNE.S BFExit ; error -> ; ; flush the private cache buffers for the B*Tree manager, don't call FlushCache. ; Note: this is a delayed write if D5 is not set. <01Aug90> BFFlush MOVEA.L BTCCQptr(A4),A3 ; ptr to cache queue <30Jul90> MOVE.W btQBSize(A3),D4 ; D4=INIT B*Tree buffer size <30Jul90> LEA btQBStart(A3),A3 ; A3=first buffer <30Jul90> MOVEQ #btBufferN,D1 ; number of private buffers <30Jul90> SUBQ #1,D1 ; for dbring <30Jul90> @flushLoop CMP.W btBHRefNum(A3),D3 ; same file? <30Jul90> BNE.S @4 ; no <30Jul90> BCLR #CBHdirty,btBHFlags(A3) ; buffer dirty? <30Jul90> BEQ.S @4 ; no <30Jul90> ;; buffer dirty, so write it to FS, A4 trashed here. <30Jul90> MOVEA.L A3,A4 ; A4 = ptr(buffer header) <30Jul90> JSR ExtWriteBlock ; write block to FS <30Jul90> @4 ADDA.W D4,A3 ; next buffer <30Jul90> ADDA.W #lenBTBH,A3 ; ... and skip header <30Jul90> DBRA D1,@flushLoop ; continue <30Jul90> TST.B D5 ; flush fs cache? <01Aug90> BEQ.S @BFRet ; no, all done <01Aug90> ;; here, call file system's flushcache <01Aug90> MOVEa.L FSVarsPtr,A1 ; <01Aug90> MOVEA.L fsVars.btMgr(A1),A1 ; <01Aug90> MOVEA.L btVParam(A1),A0 ; A0 = BT Param <01Aug90> MOVE.W D3,ioRefNum(A0) ; file refnum <01Aug90> MOVEQ #DoFlushFile,D1 ; indicate this is FlushFile <01Aug90> BSR ExtDoAOCRWF ; flush cache <01Aug90> BNE.S BFExit ; error <01Aug90> @BFRet MOVEQ #0,D0 ; no error <01Aug90> ; clean up and exit ; 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 ; __________________________________________________________________________ ; Function: get BTH from disk and update it from BTCB info ; Input: A4.L - BTCB <2/16/90> ; Output: D0=0 if read header and then A3.L = header buffer ptr ; Trashes: D0, D1, D2, A0, A1, A3 ; __________________________________________________________________________ ExtGetUpdateHdr MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEQ #0,D1 ; no options MOVEQ #0,D2 ; BTH is disk block 0 JSR ExtGetNode ; get disk block BNE.S @6 ; couldn't get it -> MOVEA.L A0,A3 ; A3 = cache buffer ptr BSR.S ExtUpdateHdr @6 MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit BTFlush ; __________________________________________________________________________ ; Function: update BTH from BTCB info. This routine is SYNC. ; Input: A4.L = BTCB, A3.L = header buffer ptr. ; Output: D0=0 <2/16/90> ; Trashes: D0, A0, A1 ; __________________________________________________________________________ ExtUpdateHdr 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 MOVEQ #0,D0 RTS ;__________________________________________________________________________________ ; ; 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 ;__________________________________________________________________________________ ExtBTGetRecord ; ; 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 ExtLocRec ; 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 ExtGetNode ; 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 ExtRelNode ; 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 DATA record ; D2.L - actual data size (in number of nodes) <23Feb90> ; Output: D0.W - result code ; 0 = ok ; BTexists = key already exists ; other = error ; D2.L - BTree hint ;__________________________________________________________________________________ ExtBTInsert ; ; 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 ExtLocBTCB ; 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 ; In supporting the new special data record, no code needs to be changed at this lower ; level (the data record (A1) and size (D1) are representing the special record, not the ; actual data), except in allocating more disk space for the data. <23Feb90> 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 ExtExtBTFile ; 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 ExtBTVRecord(A1),A1 ; maxDepth changed <11Apr90> 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 ExtTreeSearch ; 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 ExtAllocNode ; allocate the node BNE BIExit1 ; error -> MOVE.L D1,D3 ; D3 = new node number JSR ExtInitNode ; 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 ExtInsertRec ; 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 ExtGetLtSib ; 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 ExtRotateLt ; try rotating left, and insert the record 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 ExtSplitLT ; 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> ;; another problem with the new buffer scheme using ExtMarkBlock;<9/6/89> ;; A1.L=ptr(node buffer) containing new record ;<9/6/89> CMPA.L A2,A1 ; new record in left node? ;<9/6/89> BNE.S @4 ; no ;<9/6/89> CMPI.B #NDleafNode,NDType(A1) ; leaf level? ;<9/6/89> BNE.S @4 ; no, -> ;<9/6/89> ;; before we marking the leaf, update the data ;<9/6/89> MOVEM.L (A6),A0/D0 ; get input record ptr and size ;<9/6/89> JSR ExtUpdDRec ; replace the junk data record ;<9/6/89> @4 MOVEA.L A2,A0 ; mark the left node dirty <10Oct85> JSR ExtMarkBlock ; write it back <20Feb90> ; ; completed the record insert, clean up ; BIInsDone ;; We can't mark block before Updating the leaf record: <8/31/89> ;; (because ExtMarkBlock is now writing block to cache) CMPI.B #NDleafNode,NDType(A1) ; leaf level? <8/31/89> BEQ.S @0 ; yes, -> <8/31/89> MOVEA.L A3,A0 ; no, not leaf <8/31/89> JSR ExtMarkBlock ; write it back <20Feb90> BRA.S BICkDone ; all done if not leaf <8/31/89> @0 MOVEM.L (A6),A0/D0 ; get input record ptr and size <8/31/89> JSR ExtUpdDRec ; replace the junk data record <8/31/89> MOVEA.L A3,A0 ; update and then mark it <8/31/89> JSR ExtMarkBlock ; write it back <20Feb90> 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 ExtLocTPR ; 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 (node hint) MOVEQ #0,D1 ; get parent node <10Oct85> MOVE.L D3,D2 ; JSR ExtGetNode ; BNE BIExit1 ; error -> D2 on a6 ????? 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 ExtGetRecA ; ...parent index record MOVE.L A0,-(SP) ; ...and save it MOVEA.L A3,A1 ; locate 1st key CLR.W D0 ; JSR ExtGetRecA ; ...in right node MOVEA.L (SP)+,A1 ; ptr(parent index record) JSR ExtUpdIKey ; update the key MOVEA.L D4,A0 ; mark the parent node dirty <10Oct85> JSR ExtMarkBlock ; write it back <20Feb90> 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 ExtRelNode ; ... 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 ExtBuildIRec ; build index record @1 MOVEQ #0,D1 ; release <10Oct85> MOVEA.L A2,A0 ; JSR ExtRelNode ; ... 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 ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90> MOVE.L A0,D7 ; D7 = ptr to new record JSR ExtGetMaxkey ; 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 BIExit ; no, all done -> ; ; set up a new root index node ; MOVE.W BTCDepth(A4),D0 ; check tree depth <04Apr90> CMPI #ExtBTMaxDepth,D0 ; is this the limit? <11Apr90> BNE.S @0 ; no <04Apr90> IF btDebug THEN _debugger ; fatal error <04Apr90> ENDIF MOVE.W #btDepthErr,D0 ; punt on <04Apr90> BRA.S BIExit1 ; error -> <04Apr90> @0 MOVE.W BTCRefNum(A4),D0 ; volume refnum JSR ExtAllocNode ; allocate the node BNE.S BIExit1 ; error -> MOVE.L D1,D3 ; D3 = new root node number MOVE.L D3,D1 ; new node number JSR ExtInitNode ; 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 ExtBuildIRec ; ...for left node JSR ExtGetMaxkey ; max key length + 4 <10Oct85> ADDQ.W #4,D0 ; = size of index record <10Oct85> MOVEA.L BTCVarPtr(A4),A0 ; locate new index record LEA ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90> MOVEA.L D4,A1 ; ptr(root node buffer) CLR.W D1 ; insert index = 0 JSR ExtInsertRec ; insert it ; ; add index record for right node (previous root) ; MOVE.W #1,D0 ; get node number JSR ExtLocTPR ; MOVE.L TPRNodeN(A0),D0 ; ...of previous root MOVEA.L A3,A1 ; ptr(node buffer) JSR ExtBuildIRec ; build index record JSR ExtGetMaxkey ; max key length + 4 <10Oct85> ADDQ.W #4,D0 ; = size of index record <10Oct85> MOVEA.L BTCVarPtr(A4),A0 ; locate new index record LEA ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90> MOVEA.L D4,A1 ; ptr(root node buffer) MOVE.W #1,D1 ; insert index = 1 JSR ExtInsertRec ; insert it MOVEA.L D4,A0 ; mark the new root node dirty <10Oct85> JSR ExtMarkBlock ; write it back <20Feb90> ; ; 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 ExtRelNode ; release it MOVEA.L A3,A0 ; ptr(right node buffer) <23Sep85> JSR ExtRelNode ; release it MOVEA.L D4,A0 ; ptr(parent node buffer) <23Sep85> JSR ExtRelNode ; 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: 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 ;__________________________________________________________________________________ ExtBTSearch ; ; 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 ExtGetNode ; BNE.S BSExit1 ; error -> <07Sep89> ; this node has been released <07Sep89> 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 ExtSearchNode ; BEQ.S BSTSrch1 ; found it -> @1 MOVEA.L A2,A0 ; release node buffer MOVEQ #0,D1 ; no RelBlock options <10Oct85> JSR ExtRelNode ; BNE.S BSExit1 ; error -> <07Sep89> ; ; search tree for key ; BSTSrch MOVEA.L A3,A0 ; ptr to key JSR ExtTreeSearch ; 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 ExtLocRec ; 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 ExtRelNode ; 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: ExtBTUpdate ; ; 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 ;__________________________________________________________________________________ ExtBTUpdate MOVE.L jBTUpdate,-(SP) ; jumptable entry for vBTUpdate <25Oct85> RTS ; go there <25Oct85> vExtBTUpdate ; MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEM.L D1/A0-A1/A4,-(A6) ; save regs JSR ExtLocBTCB ; locate BTCB MOVEQ #kGBexist,D1 ; indicate existing cache block <10Oct85> JSR ExtGetNode ; get the node BNE.S BUExit ; error -> MOVEQ #kRBdirty,D1 ; indicate dirty buffer JSR ExtRelNode ; 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 ExtBTUpdate ;__________________________________________________________________________________ ; ; 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 ExtLocBTCB ; 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 ExtGetMaxkey ; get max key size <10Oct85> ADDI.W #ExtlenTPT+4,D0 ; size of BTVars = length of TPT <11Apr90> RTS ; exit CalBTVars END