mac-rom/OS/HFS/Extensions/BTreeMgr/BTreeMaint2.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

1176 lines
34 KiB
Plaintext

;
; File: BTreeMaint2.a
;
; Revision by: Kenny SC. Tung
;
; Copyright: © 1984-1990, 1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM1> 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 ¥
; <6> 8/3/90 KST Total number of nodes is calculated based on LEOF, not PEOF (in
; ExtChkNode).
; <5> 7/6/90 KST Fixing a bug in "ExtUpdIKey" which should not do EXT.W
; <4> 4/11/90 KST Code cleanup.
; <3> 4/11/90 KST Use ExtbtMaxDepth and related equates. <SM1>
; <2> 3/13/90 KST Adding for the first time.
; <1.1> 8/7/89 KST Code cleanup.
; <1.0> 6/14/89 KST New file added for the new implementation of BTreeMgr.
; <1.3> 5/4/89 KST Fixed a bug in ExtGetMaxkey.
; 5/4/89 KST Fixed a bug in ExtGetMaxkey, should add 2, not 1
; <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É
; 10/25/85 BB Added vectors for ROM versions.
; 10/22/85 BB Moved ExtLocBTCB from BTIntf to ExtBTMaint2.
; 10/10/85 BB Added use of new MOVEQ equates for GetBlock and RelBlock. Added
; ExtGetMaxkey subroutine and a call to it in ExtBuildIRec. Did some
; minor code clean up.
; 9/26/85 BB Modified ExtGetNode to release the cache block after detecting a
; bad BTree node.
; 9/24/85 PWD Changed '.Word $F042' to _TFSDSErr macro.
; 9/23/85 BB Added ExtClrNode and a call to it in ExtInitNode.
; 9/23/85 BB Modified ExtRelNode to handle a null node pointer and to call
; ExtChkNode.
; 9/6/85 BB Fixed minor bugs in ExtGetNodeSiz and GetOffA.
; 8/29/85 BB Changed ExtChkNode to use a more efficient method for checking
; record offsets.
; 8/22/85 BB Added ExtGetNode,ExtRelNode, and ExtChkNode.
; 8/8/85 BB Modified ExtGetOffset and ExtInitNode for new node format.
; 7/31/85 BB Fixed bug in ExtLocRec which was causing the "write" problem.
; 7/17/85 BB Added ExtGetNodeSiz. Modified ExtGetRecA to also return record size.
; 7/8/85 BB Modified ExtGetLtSib/ExtGetRtSib to use links to locate sibling nodes
; instead of using the TPT.
; 6/10/85 BB Cleaned up some.
; 3/15/85 BB Modified to use A6 stack.
; 3/11/85 BB Added extend BTree file stuff.
; 2/25/85 BB Modified ExtInsertRec to return node number and record index of new
; record.
; 2/18/85 BB Modified ExtLocRec to support variable length keys in leaf nodes.
; 2/13/85 BB Removed default KeyCompare routine
; 1/17/85 BB Removed use of BTree Global area (BTG).
; 1/5/85 BB Modified ExtSearchNode to use external key compare routine.
; 1/5/85 BB Added KeyCompare routine.
; 1/5/85 BB Changed CopyRec to ExtLocRec to support return of key and data
; record pointers instead of copying that data.
; 10/1/84 BB Split off from BTmaint.
;
; To Do:
;
;__________________________________________________________________________________
;
; FILE: ExtBTMaint2.text
;
; Function: These routines provide single-node BTree maintenance functions.
;
; External
; Routines: ExtBuildIRec - Builds an index record for a specified target node.
; ExtChkNode - Checks the validity of a node.
; ExtClrNode - Clears a node (to zero).
; ExtDeleteRec - Deletes a record from a BTree node.
; ExtGetMaxkey - Gets max key size rounded to word boundry.
; ExtGetNode - Gets a BTree node from disk.
; ExtGetNodeSiz - Gets the size of the data currently contained in a
; node (record data + offset overhead).
; ExtGetLtSib - Gets left sibling node for a given BTree node.
; ExtGetRtSib - Gets right sibling node for a given BTree node.
; ExtGetOffset - Gets the record offset and the pointer to the offset
; word for a given record index.
; ExtGetRecA - Gets the address of the record for a given record
; index.
; ExtInitNode - Gets a cache buffer for a new node and initializes it to
; an empty state.
; ExtInsertRec - Inserts a record into a BTree node.
; ExtLocBTCB - Locates the BTCB for a BTree file.
; ExtLocRec - Locates the key and data records for a specified
; BTree record.
; ExtLocTPR - Locates the Tree Path Record (TPR) for a given tree
; level.
; ExtMovOffLt - Move offsets left within a single node.
; ExtMovOffRt - Move offsets right within a single node.
; ExtMovRecLt - Move records left within a single node.
; ExtMovRecRt - Move records right within a single node.
; ExtRelNode - Releases the use of a node.
; ExtSearchNode - Searches a BTree node for a specified key.
; ExtUpdDRec - Updates the data portion of a BTree record.
; ExtUpdIKey - Updates the key portion of an index record.
;
; Internal
; Subroutines: None.
;
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'BtreeEqu.a'
INCLUDE 'BtreePrivate.a' ; Use ExtbtMaxDepth <11Apr90><SM1>
PRINT ON
PRINT NOGEN
ExtBTMaint2 PROC EXPORT
EXPORT ExtBuildIRec,ExtChkNode,ExtClrNode,ExtDeleteRec
EXPORT ExtGetMaxkey,ExtGetNode,ExtGetNodeSiz,ExtGetLtSib,ExtGetRtSib,ExtGetOffset,ExtGetRecA
EXPORT ExtInitNode,ExtInsertRec,ExtLocBTCB,ExtLocRec,ExtLocTPR
EXPORT ExtMovOffLt,ExtMovOffRt,ExtMovRecLt,ExtMovRecRt
EXPORT ExtRelNode,ExtSearchNode,ExtUpdDRec,ExtUpdIKey
IMPORT ExtGetBlock,ExtRelBlock ; <SM1>
;__________________________________________________________________________________
;
; Routine: ExtBuildIRec
;
; Function: Builds an index record for a specified target node. The
; record is built in the BTree buffer.
;
; Input: A1.L - ptr(target node buffer)
; D0.W - target node number
; A4.L - pointer to BTCB
;
; Output: A1.L - ptr(new index record) in BTree buffer
;
; Called by: BTInsert
;__________________________________________________________________________________
ExtBuildIRec
MOVE.L D2,-(SP) ; save regs
MOVE.L D0,D2 ; save node number
CLR.W D0 ; locate 1st record
BSR ExtGetRecA ; ...in node
MOVEA.L BTCVarPtr(A4),A1 ; locate record buffer
LEA ExtbtVRecord(A1),A1 ; <11Apr90><SM1>
JSR ExtUpdIKey ; move in the key
BSR ExtGetMaxkey ; node # offset = max key size <10Oct85>
MOVE.L D2,0(A1,D0.W) ; move in the node number <10Oct85>
MOVE.L (SP)+,D2 ; restore regs
RTS ; exit ExtBuildIRec
;__________________________________________________________________________________
;
; Routine: ExtChkNode
;
; Function: Checks the validity of a node.
;
; Input: A1.L - pointer to node buffer
; A4.L - pointer to BTCB
;
; Output D0.W - result code
; 0 - ok
; BTBadNode - bad node structure detected
;
; Called by: ExtGetNode
; <26Jul90> KSCT use LEOF to calculate total nodes.
;__________________________________________________________________________________
ExtChkNode
MOVEM.L D1-D2/A0-A2,-(SP) ; save registers
MOVE.W BTCRefNum(A4),D1 ; locate the FCB
MOVEA.L FCBSPtr,A2 ;
;
; check out the links
;
MOVE.L FCBEof(A2,D1.W),D0 ; LEOF / node size <26Jul90>
DIVU BTCNodeSize(A4),D0 ; = end node # + 1
MOVEQ #0,D1 ;
MOVE.W D0,D1 ; D1 = end node # + 1
CMP.L NDFlink(A1),D1 ; forward link within range?
BLS.S CNBadNode ; no, error ->
CMP.L NDBlink(A1),D1 ; backward link within range?
BLS.S CNBadNode ; no, error ->
;
; check node type
; note: valid node types are $FF (leaf node) to $02 (map node)
;
MOVE.B NDType(A1),D0 ; node type + 1
ADDQ.B #1,D0 ;
CMP.B #NDMapNode+1,D0 ; (node type +1) > (max type +1) ?
BHI.S CNBadNode ; yes, error ->
;
; check node height
;
MOVE.B NDNHeight(A1),D0 ; node height > tree depth?
CMP.B BTCDepth+1(A4),D0 ;
BHI.S CNBadNode ; yes, error ->
;
; check number of records
;
CNChkNRecs
MOVEQ #0,D1 ; D1 = node size
MOVE.W BTCNodeSize(A4),D1 ;
MOVEQ #-lenND,D0 ; max number of records
ADD.L D1,D0 ; = (node size - length of ND)
DIVU #6,D0 ; / (min record size + offset word)
CMP.W NDNRecs(A1),D0 ; record count within range?
BLO.S CNBadNode ; no, error ->
;
; check record offsets
;
CNChkOff
MOVE.W NDNRecs(A1),D1 ; loop index = # records
MOVE.W D1,D0 ; locate free space offset <29Aug85>
BSR ExtGetOffset ;
MOVEQ #2,D2 ; prime previous offset to <29Aug85>
ADD.L A0,D2 ; ptr(free space offset) + 2 <29Aug85>
SUB.L A1,D2 ; - ptr(node) <29Aug85>
@1 MOVE.W (A0)+,D0 ; get next offset <29Aug85>
BTST #0,D0 ; odd offset?
BNE.S CNBadNode ; yes, error ->
CMPI.W #LenND,D0 ; offset >= min ?
BLO.S CNBadNode ; no, error ->
CMP.W D2,D0 ; offset < previous ?
BHS.S CNBadNode ; no, error ->
MOVE.W D0,D2 ; previous offset = current offset
DBRA D1,@1 ; check next one ->
BRA.S CNExit ; all done ->
;
; clean up and exit
;
CNBadNode
MOVEQ #BTBadNode,D0 ; result = 'bad node' <14Oct85>
BRA.S CNExit1 ; exit ->
CNExit
CLR.W D0 ; result = 'ok'
CNExit1
MOVEM.L (SP)+,D1-D2/A0-A2 ; restore registers
TST.W D0 ; set up condition codes
RTS ; exit ExtChkNode
;__________________________________________________________________________________
;
; Routine: ExtClrNode
;
; Function: Clears a node to all zeroes.
;
; Input: A0.L - pointer to node buffer
; A4.L - pointer to BTCB
;
; Output none
;
; Called by: BTDelete
;__________________________________________________________________________________
ExtClrNode
MOVEM.L D0-D1/A0,-(SP) ; save registers <23Sep85>
MOVEQ #3,D1 ; loop index <10Oct85>
ADD.W BTCNodeSize(A4),D1 ; = node size <10Oct85>
LSR.W #2,D1 ; (in long words) <23Sep85>
SUBQ.W #1,D1 ; - 1 <23Sep85>
MOVEQ #0,D0 ; clear the node buffer <23Sep85>
@1 MOVE.L D0,(A0)+ ; <23Sep85>
DBRA D1,@1 ; <23Sep85>
MOVEM.L (SP)+,D0-D1/A0 ; restore registers <23Sep85>
RTS ; exit ExtClrNode <23Sep85>
;__________________________________________________________________________________
;
; Routine: ExtDeleteRec
;
; Function: Deletes a record from a BTree node.
;
; Input: A1.L - ptr(node buffer)
; D1.W - index of record to be deleted
; A4.L - pointer to BTCB
;
; Output: none
;
; Called by: BTDelete,RotRecLt
;__________________________________________________________________________________
ExtDeleteRec
MOVEM.L D2-D6/A2-A5,-(SP) ; save regs
;
; set up some common stuff
;
MOVE.W D1,D5 ; save delete index
MOVE.W D1,D0 ; get delete offset
JSR ExtGetOffset ;
MOVE.L A0,D6 ; ...D6 = ptr(delete offset)
MOVE.W D0,D4 ; ...D4 = delete offset
LEA -2(A0),A3 ; A3 = ptr(next offset)
MOVE.W (A3),D3 ; D3 = next offset
MOVE.W NDNRecs(A1),D0 ; get last offset
JSR ExtGetOffset ;
MOVE.L A0,A2 ; ...A2 = ptr(last offset)
MOVE.W D0,D2 ; ...D2 = last offset
;
; Compress remaining records
;
MOVE.L A1,A5 ; save ptr(node buffer)
LEA 0(A5,D3.W),A0 ; source = ptr(next record)
LEA 0(A5,D4.W),A1 ; dest = ptr(delete record)
MOVE.W D2,D0 ; count = last offset
SUB.W D3,D0 ; - next offset
JSR ExtMovRecLt ; move the records
SUB.W #1,NDNRecs(A5) ; decrement number of keys
;
; Adjust the offsets
;
MOVE.L A3,A0 ; source = ptr(next offset)
MOVE.L D6,A1 ; dest = ptr(delete offset)
MOVE.W NDNRecs(A5),D0 ; count = last index
SUB.W D5,D0 ; - delete index
MOVE.W D4,D1 ; delta = delete offset
SUB.W D3,D1 ; - next offset
JSR ExtMovOffRt ; adjust the offsets
DRExit
MOVEM.L (SP)+,D2-D6/A2-A5 ; restore regs
RTS ; return
;__________________________________________________________________________________
;
; Routines: ExtGetLtSib (Get Left Sibling)
; ExtGetRtSib (Get Right Sibling)
;
; Function: Gets the left or right sibling node for a given BTree node. The
; sibling nodes are located using the forward/backward node links.
;
; Input: A0.L - pointer to node buffer containing subject node
; A4.L - pointer to BTCB
;
; Output: A1.L - pointer to node buffer containing sibling node
; D1.L - node number of sibling node
; 0 - no sibling
; D0.W - result code
; 0 - ok
; -n - IO error
;__________________________________________________________________________________
ExtGetLtSib
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D3,-(A6) ; save registers
CLR.B D3 ; indicate ExtGetLtSib
BRA.S GSRtSib1 ; use common code
ExtGetRtSib
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D3,-(A6) ; save registers
MOVEQ #1,D3 ; indicate ExtGetRtSib
GSRtSib1
TST.B D3 ; getting left sibling ?
BNE.S @2 ; no ->
MOVE.L NDBlink(A0),D2 ; left sibling node number
BRA.S @3 ; ->
@2 MOVE.L NDFlink(A0),D2 ; right sibling node number
@3 BNE.S @5 ; we have the sibling ->
@4 CLR.L D1 ; indicate no sibling
BRA.S GSExit ; exit
@5 MOVEQ #0,D1 ; no GetBlock options <10Oct85>
BSR.S ExtGetNode ; get node from disk
BNE.S GSExit1 ; error ->
MOVE.L D2,D1 ; return the node number
MOVE.L A0,A1 ; ...and buffer address
GSExit
CLR.W D0 ; indicate no error
GSExit1
MOVEM.L (A6)+,D2-D3 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit ExtGetLtSib/ExtGetRtSib
;__________________________________________________________________________________
;
; Routine: ExtGetMaxkey
;
; Function: Gets maximum key size rounded to word boundry.
;
; Input: A4.L - pointer to BTCB
;
; Output D0.W - maximum key length
;
; Called by: BTInsert,BTDelete,BTGetRecord,BTSearch
;__________________________________________________________________________________
ExtGetMaxkey
MOVEQ #2,D0 ; key length = 1 <10Oct85>
; 2, include length byte <K.Tung 5/4/89>
ADD.W BTCKeyLen(A4),D0 ; + max key length <10Oct85>
LSR.W #1,D0 ; rounded down <10Oct85>
LSL.W #1,D0 ; <10Oct85>
RTS ; exit ExtGetMaxkey <10Oct85>
;__________________________________________________________________________________
;
; Routine: ExtGetNode
;
; Function: Gets an existing BTree node from disk and verifies it.
; Note: this is a temporary interface, it will change for the new
; cache.
;
; Input: D1.B - GetBlock option flags
; D2.L - node number of desired node
; A4.L - pointer to BTCB
;
; Output D0.W - result code
; 0 = ok
; -n = error
; A0.L - pointer to buffer containing node
;
; Called by: BTInsert,BTDelete,BTGetRecord,BTSearch
;__________________________________________________________________________________
ExtGetNode
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/A1,-(A6) ; save registers
MOVE.W BTCRefNum(A4),D0 ; file refnum
MOVEA.L BTCCQptr(A4),A1 ; ptr to cache queue
JSR ExtGetBlock ; get the block <SM1>
BNE.S GNExit ; didn't get it ->
MOVEA.L A0,A1 ; verify the node
BSR ExtChkNode ;
BEQ.S GNExit ; its ok -> <26Sep85>
MOVE.W D0,-(A6) ; save result code <26Sep85>
MOVEQ #kRBTrash,D1 ; set trash option <10Oct85>
MOVEA.L BTCCQptr(A4),A1 ; ptr to cache queue <26Sep85>
JSR ExtRelBlock ; release it <26Sep85><SM1>
MOVE.W (A6)+,D0 ; restore result code <26Sep85>
GNExit
MOVEM.L (A6)+,D1/A1 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit ExtGetNode
;__________________________________________________________________________________
;
; Routine: ExtGetNodeSiz (Get Node Size)
;
; Function: Gets the size of the data currently contained in a node
; (record data + offset overhead).
;
; Input: A1.L - pointer to node buffer
; A4.L - pointer to BTCB
;
; Output: D0.W - size of node data
;__________________________________________________________________________________
ExtGetNodeSiz
MOVE.L D1,-(SP) ; save registers
MOVE.W NDNRecs(A1),D1 ; number of records in node
MOVE.W D1,D0 ; record data size
JSR ExtGetOffset ; = free space offset
SUBI.W #lenND,D0 ; - length of ND <06Sep85>
LSL.W #1,D1 ; NRecs X 2 = overhead for offsets
ADD.W D1,D0 ; rec data size + offsets = node data size
MOVE.L (SP)+,D1 ; restore registers
RTS ; exit ExtGetNodeSiz
;__________________________________________________________________________________
;
; Routine: ExtGetOffset (Get Offset)
;
; Function: Gets the record offset and the pointer to the offset word
; for a given record index.
;
; Input: A1.L - pointer to node buffer
; D0.W - record index
; A4.L - pointer to BTCB
;
; Output: D0.W - record offset
; A0.L - address of offset word
;__________________________________________________________________________________
ExtGetOffset
BSR.S GetOffA ; get ptr(offset) first
MOVE.W (A0),D0 ; get the offset
RTS ; return
;
; GetOffA (Get Offset Address) subroutine
;
GetOffA
SUBA.L A0,A0 ; position to offset base + 2 <06Sep85>
MOVE.W BTCNodeSize(A4),A0 ; <06Sep85>
ADDA.L A1,A0 ; <06Sep85>
LSL.W #1,D0 ; index * 2 (bytes)
NEG.W D0 ; negative byte index
LEA -2(A0,D0.W),A0 ; ptr(offset) = (base - 2) + byte index
RTS ; return
;__________________________________________________________________________________
;
; Routine: ExtGetRecA (Get Record Address)
;
; Function: Gets the address and size of a BTree record given the record index.
;
; Input: A1.L - ptr(node buffer)
; D0.W - record index
; A4.L - pointer to BTCB
;
; Output: A0.L - record address
; D0.W - size of record
;__________________________________________________________________________________
ExtGetRecA
MOVEM.L D1-D2,-(SP) ; save registers
MOVE.W D0,D1 ; D1 = record index
BSR.S ExtGetOffset ; get offset of target record
MOVE.W D0,D2 ; D2 = target offset
MOVE.W D1,D0 ; get offset to next record
ADDQ.W #1,D0 ;
BSR.S ExtGetOffset ;
SUB.W D2,D0 ; size = next offset - target offset
LEA 0(A1,D2.W),A0 ; ptr(record) = base + offset
MOVEM.L (SP)+,D1-D2 ; restore registers
RTS ; return
;__________________________________________________________________________________
;
; Routine: ExtInitNode
;
; Function: Gets a cache buffer for a new node and initializes it to
; an empty state.
;
; Input: D1.L - node number of new node
; A4.L - pointer to BTCB
;
; Output D0.W - result code
; A0.L - ptr(cache buffer containing node)
;
; Called by: BTInsert
;__________________________________________________________________________________
ExtInitNode
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D2/A1,-(A6) ; save registers
;
; get cache buffer for new node
;
@1 MOVE.L D1,D2 ; node number
MOVE.W BTCRefNum(A4),D0 ; file refnum
MOVEQ #kGBnoread,D1 ; no-read option <10Oct85>
MOVEA.L BTCCQptr(A4),A1 ; cache queue ptr
JSR ExtGetBlock ; get cache buffer <SM1>
BNE.S INExit1 ; error ->
;
; initialize the node
;
BSR ExtClrNode ; clear the node first <23Sep85>
MOVE.W BTCNodeSize(A4),D2 ; D2 = node size
MOVE.W #lenND,-2(A0,D2.W) ; set free space offset
INExit
CLR.W D0 ; result = ok
INExit1
MOVEM.L (A6)+,D1-D2/A1 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit ExtInitNode
;__________________________________________________________________________________
;
; Routine: ExtInsertRec
;
; Function: Inserts a record into a BTree node.
;
; Input: A0.L - pointer to record (to insert)
; A1.L - ptr(node buffer)
; D0.W - size of record (data + key)
; D1.W - index of insert point
;
; Output: D0.W - result code
; 0 = ok
; -1 = won't fit
; A1.L - ptr(node buffer) containing new record
; D1.W - index of new record
;
; Called by: BTInsert,ExtRotateLt,RotRecLt
;__________________________________________________________________________________
ExtInsertRec
MOVEM.L D1-D7/A1-A5,-(SP) ; save regs
;
; set up some common stuff
;
MOVE.W D0,D7 ; save size of record
MOVE.W D1,D6 ; save insert index
MOVE.L A0,D5 ; save ptr to record
MOVE.W D1,D0 ; insert index
JSR ExtGetOffset ;
MOVE.W D0,D4 ; D4 = insert offset
MOVE.W NDNRecs(A1),D0 ; number of keys = last index
JSR ExtGetOffset ;
MOVE.L A0,A3 ; A3 = ptr(last offset)
MOVE.W D0,D3 ; D3 = last offset
;
; see if new record will fit
;
MOVE.L A3,D1 ; ptr(last offset)
CLR.L D0 ;
MOVE.W D3,D0 ; - (last offset + node base)
ADD.L A1,D0 ;
SUB.L D0,D1 ; = avail space
MOVEQ #2,D0 ; 2 + record size
ADD.W D7,D0 ; = required size
CMP.W D0,D1 ; enough space ?
BGE.S IRInsert ; yes ->
MOVEQ #-1,D0 ; indicate "won't fit"
BRA.S IRExit ; exit
;
; make hole for new record
;
IRInsert
MOVE.L A1,A5 ; A5 = ptr(node buffer)
LEA 0(A5,D4.W),A0 ; source = ptr(insert record)
LEA 0(A0,D7.W),A1 ; dest = source + size
MOVE.W D3,D0 ; last offset
SUB.W D4,D0 ; - insert offset = count
JSR ExtMovRecRt ; make hole for new record
;
; adjust offsets for moved records
;
MOVE.L A3,A0 ; source ptr = ptr to last offset
LEA -2(A0),A1 ; dest ptr = source ptr - 2
MOVE.W NDNRecs(A5),D0 ; offset count =
SUB.W D6,D0 ; last index - insert index
MOVE.W D7,D1 ; delta = record size
JSR ExtMovOffLt ; adjust offsets left
;
; move in the new record
;
MOVE.L D5,A0 ; source = ptr(record)
LEA 0(A5,D4.W),A1 ; dest = ptr(insert record)
MOVE.W D7,D0 ; count = record size
JSR ExtMovRecLt ; move record in
ADDQ.W #1,NDNRecs(A5) ; increment key count
CLR.W D0 ; result = ok
IRExit
MOVEM.L (SP)+,D1-D7/A1-A5 ; restore regs
TST.W D0 ; set condition codes
RTS ; exit ExtInsertRec
;__________________________________________________________________________________
;
; Routine: ExtLocBTCB (Locate BTree Control Block)
;
; Function: Locates the BTCB for a BTree file given the refnum.
;
; Input: D0.W - file refnum
;
; Output: A4.L - pointer to BTCB
;__________________________________________________________________________________
ExtLocBTCB
;
; locate BTCB for the file
;
MOVEA.L FCBSPtr,A4 ; start of FCBS
MOVEA.L FCBBTCBptr(A4,D0.W),A4 ; ptr(BTCB)
RTS ; exit ExtLocBTCB
;__________________________________________________________________________________
;
; Routine: ExtLocRec (Locate Record))
;
; Function: Locates the key and data record for a specified BTree record.
;
; Input: A1.L - ptr(node buffer)
; D1.W - record index
; A4.L - pointer to BTCB
;
; Output:
; A0.L - ptr(key)
; A1.L - ptr(data record)
; D1.W - size of record
;__________________________________________________________________________________
ExtLocRec
MOVEM.L D0/D2-D3,-(SP) ; save registers
MOVE.W D1,D3 ; D3 = record index
MOVE.W D3,D0 ; locate
JSR ExtGetRecA ; ...the record
MOVE.L A0,D2 ; D2 = ptr(record)
MOVE.W D3,D0 ; locate
ADDQ #1,D0 ;
JSR ExtGetRecA ; ...the next record
MOVE.L A0,D1 ; D1 = ptr(next record)
MOVEA.L D2,A0 ; ptr(key) = ptr(record)
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
SUB.L D2,D1 ; record size = ptr(next record)
SUB.L D0,D1 ; - ptr(record) - (adj key length)
MOVEA.L A0,A1 ; ptr(data record) = ptr(key)
ADDA.L D0,A1 ; + (adj key length)
MOVEM.L (SP)+,D0/D2-D3 ; restore registers
RTS ; exit ExtLocRec
;__________________________________________________________________________________
;
; Routine: ExtLocTPR (Locate Tree Path Record)
;
; Function: Locates the Tree Path Record (TPR) for a given tree level.
;
; Input: D0.W - tree level
; A4.L - pointer to BTCB
;
; Output: A0.L - ptr(TPR)
;__________________________________________________________________________________
ExtLocTPR
SUB.W #1,D0 ; offset
MULU #LenTPR,D0 ; ...from beg of table
MOVEA.L BTCVarPtr(A4),A0 ; ptr to BTree buffer
LEA BTVTPTable(A0,D0.L),A0 ; get ptr(TPR)
RTS
;__________________________________________________________________________________
;
; Routine: ExtMovOffLt
;
; Function: Move offsets left within a single node.
;
; Input: D0.W - number of offsets
; D1.W - delta amount to be added to each offset
; A0.L - pointer to source offset
; A1.L - pointer to destination offset
;
; Output: none
;__________________________________________________________________________________
ExtMovOffLt
MOVEM.L D0-D2/A0-A1,-(SP) ; save regs
@1 MOVE.W (A0)+,D2 ; *ptrDst++ = *ptrSrc++ + delta
ADD.W D1,D2
MOVE.W D2,(A1)+
DBF D0,@1
BRA.S MovOExit ; return
;__________________________________________________________________________________
;
; Routine: ExtMovOffRt
;
; Function: Move offsets right within a single node.
;
; Input: D0.W - number of offsets
; D1.W - delta amount to be added to each offset
; A0.L - pointer to source offset
; A1.L - pointer to destination offset
;
; Output: none
;__________________________________________________________________________________
ExtMovOffRt
MOVEM.L D0-D2/A0-A1,-(SP) ; save regs
CMPM.W (A0)+,(A1)+ ; preincrement A0, A1 for loop
@1 MOVE.W -(A0),D2 ; *ptrDst-- = *ptrSrc-- + delta
ADD.W D1,D2
MOVE.W D2,-(A1)
DBF D0,@1
MovOExit
MOVEM.L (SP)+,D0-D2/A0-A1 ; restore regs
RTS
;__________________________________________________________________________________
;
; Routine: ExtMovRecLt
;
; Function: Move records left within a single node.
;
; Input: D0.W - number of bytes to move
; A0.L - pointer to source
; A1.L - pointer to destination
;
; Output: none
;__________________________________________________________________________________
ExtMovRecLt
MOVEM.L D0-D1/A0-A1,-(SP) ; save regs
TST.W D0 ; test byte count
BLE.S MovlExit ; byte count <= 0
SUBQ.W #1,D0 ; adjust loop index
@1 MOVE.B (A0)+,(A1)+ ; move
DBRA D0,@1 ; ...it
MovlExit
MOVEM.L (SP)+,D0-D1/A0-A1 ; restore regs
RTS ; return
;__________________________________________________________________________________
;
; Routine: ExtMovRecRt
;
; Function: Move records right within a single node.
;
; Input: D0.W - number of bytes
; A0.L - pointer to source
; A1.L - pointer to destination
;
; Output: none
;__________________________________________________________________________________
ExtMovRecRt
MOVEM.L D0-D1/A0-A1,-(SP) ; save regs
TST.W D0
BLE.S MovrExit ; byte count <= 0
ADDA.W D0,A0 ; high-address of source block
ADDA.W D0,A1 ; high-address of dest block
SUBQ.W #1,D0 ; byte count - 1
@1 MOVE.B -(A0),-(A1) ; move
DBRA D0,@1 ; ...it
MovrExit
MOVEM.L (SP)+,D0-D1/A0-A1 ; restore regs
RTS ; return
;__________________________________________________________________________________
;
; Routine: ExtRelNode
;
; Function: Releases use of a BTree node obtained by ExtGetNode.
; Note: this is a temporary interface, it will change for the new
; cache.
;
; Input: A0.L - pointer to node buffer
; D1.B - RelBlock option flags
; A4.L - pointer to BTCB
;
; Output D0.W - result code
; 0 = ok
; -n = error
;
; Called by: BTInsert,BTDelete,BTGetRecord,BTSearch,ExtTreeSearch
;__________________________________________________________________________________
ExtRelNode
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVE.L A1,-(A6) ; save registers
MOVE.L A0,D0 ; have a node to release? <23Sep85>
BEQ.S @RNExit ; no -> <23Sep85>
IF HFSDebug THEN ; Only check when debugging <24Sep85>
TST.W NDNRecs(A0) ; empty node? <23Sep85>
BEQ.S @1 ; yes, skip node check <23Sep85>
MOVEA.L A0,A1 ; ***** check out the node ***** <21Sep85>
BSR ExtChkNode ; <21Sep85>
BEQ.S @1 ; ok -> <21Sep85>
_HFSDSErr ; *** HALT *** <24Sep85>
ENDIF
@1 JSR ExtRelBlock ; release the block <SM1>
@RNExit
MOVE.L (A6)+,A1 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit ExtRelNode
;__________________________________________________________________________________
;
; Routine: ExtSearchNode
;
; Function: Searches a BTree node for a specified key. A binary search
; algorithym is used.
;
; Input: A0.L - ptr(search key)
; A1.L - ptr(node buffer)
; A4.L - pointer to BTCB
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = record not found
; A1.L - ptr(node buffer)
; D1.W - index
; record index if found
; insert index if not found
;
; Called by: BTSearch,ExtTreeSearch
;__________________________________________________________________________________
ExtSearchNode
MOVEM.L D2-D5/A1-A3,-(SP) ; save regs
;
; set up some common stuff
;
MOVE.L A0,A3 ; A3 = ptr(search key)
MOVE.L A1,A2 ; A2 = ptr(node buffer)
MOVE.L BTCKeyCR(A4),D5 ; D5 = ptr(key compare routine)
;
; search node for key using a binary search
;
CLR.W D2 ; lower bnd = 0
MOVE.W NDNRecs(A2),D3 ; upper bnd = number of recs - 1
SUBQ.W #1,D3
CMP.W D3,D2 ; while lower bnd <= upper bnd
BGT.S SrchExit
SrchLoop
MOVE.W D2,D4 ; index = (upper+lower) / 2
ADD.W D3,D4 ;
LSR.W #1,D4 ; D4 = new index
MOVE.W D4,D0 ; get ptr(trial key)
MOVE.L A2,A1 ;
JSR ExtGetRecA ;
MOVE.L A0,A1 ; A1 = ptr(trial key)
MOVEA.L A3,A0 ; A0 = ptr(search key)
MOVE.L A4,-(SP) ; save A4
MOVEA.L D5,A4 ; A4 = ptr(key compare routine)
JSR (A4) ; compare the keys
MOVE.L (SP)+,A4 ; restore A4
TST.W D0 ; test result code
BEQ.S SrchEQ ; search key = trial key ->
BGT.S SrchGT ; search key > trial key ->
SrchLT ; search key < trial key
MOVE.W D4,D3 ; upper = index - 1
SUBQ.W #1,D3
CMP.W D3,D2 ; upper <= lower ?
BLE.S SrchLoop
BRA.S SrchExit
SrchEQ
CLR.W D0 ; result = FOUND
BRA.S SrchRet
SrchGT
MOVE.W D4,D2 ; lower = index + 1
ADDQ.W #1,D2
CMP.W D3,D2 ; lower <= upper ?
BLE.S SrchLoop
SrchExit
MOVE.W D2,D4 ; index = lower
MOVEQ #BTnotfound,D0 ; result = 'not found' <14Oct85>
;
; clean up and exit
;
SrchRet
MOVE.W D4,D1 ; return index in D1
MOVEM.L (SP)+,D2-D5/A1-A3 ; restore regs
TST.W D0 ; set up condition codes
RTS ; exit ExtSearchNode
;__________________________________________________________________________________
;
; Routine: ExtUpdDRec (Update Data Record)
;
; Function: Updates the data portion of a BTree record.
;
; Input: A0.L - ptr(data record)
; 0 = create a null record (cleared to zero)
; D0.W - size of data record
; A1.L - ptr(node buffer) containing BTree record
; D1.W - index of BTree record
; A4.L - pointer to BTCB
;
; Output: none
;__________________________________________________________________________________
ExtUpdDRec
MOVEM.L D0-D1/A0-A2,-(SP) ; save registers
MOVEA.L A0,A2 ; A2 = ptr(data record)
JSR ExtLocRec ; locate data position in BTree record
MOVE.L A2,D1 ; ptr(data record)
BEQ.S @2 ; ptr = 0, clear the record ->
MOVEA.L D1,A0 ; source = data record
EXT.L D0 ; move length = record size
_BlockMove ; move in the data record
BRA.S UDExit ; all done ->
@1 CLR.B (A1)+ ; clear the record
@2 DBRA D0,@1 ;
UDExit
MOVEM.L (SP)+,D0-D1/A0-A2 ; restore registers
RTS ; exit ExtUpdDRec
;__________________________________________________________________________________
;
; Routine: ExtUpdIKey (Update Index Key)
;
; Function: Updates the key portion of an index record. Variable
; length source keys are padded with $00 to obtain a fixed
; length index key.
;
; Input: A0.L - pointer to source key
; A1.L - pointer to index record key
; A4.L - pointer to BTCB
;
; Output: A1.L - pointer to updated index record key
;__________________________________________________________________________________
ExtUpdIKey
MOVEM.L D0-D1/A0-A2,-(SP) ; save regs
MOVEA.L A0,A2 ; save ptr(source key)
MOVE.W BTCKeyLen(A4),D1 ; get max key length
MOVE.B D1,(A1)+ ; stuff max key length
MOVEA.L A2,A0 ; ptr(source key)
MOVEQ #0,D0 ; fixing a bug here <06Jul90>
MOVE.B (A0)+,D0 ; source key length <06Jul90>
; EXT.W D0 ; this is bad for D0 >= $80 <06Jul90>
SUB.W D0,D1 ; max key length - source key length
BGE.S @2 ; length ok, decrement before testing ->
ADD.W D1,D0 ; source > max, use max length
BRA.S @2 ;
@1 MOVE.B (A0)+,(A1)+ ; copy next byte
@2 DBF D0,@1 ;
TST.W D1 ; need any null padding?
BLE.S @5 ; no ->
BRA.S @4 ; decrement before testing
@3 CLR.B (A1)+ ; clear next byte in key (null pad)
@4 DBF D1,@3
@5 MOVEM.L (SP)+,D0-D1/A0-A2 ; restore regs
RTS ; exit ExtUpdIKey
END