mac-rom/OS/HFS/BTMAINT2.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

1172 lines
33 KiB
Plaintext

;
; File: BTMAINT2.a
;
; Contains: These routines provide single-node BTree maintenance functions.
;
; Written by: Bill Bruffey
;
; Copyright: © 1984-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <4> 9/10/91 JSM Cleanup header.
; <3> 9/21/90 BG Removed <2>. 040s are behaving more reliably now.
; <2> 6/20/90 CCH Added some temporary NOPs to prevent pipeline problems in
; 68040's.
; <1.3> 5/4/89 KST Fixed a bug in GetMaxkey.
; 5/4/89 KSCT Fixed a bug in GetmaxKey, 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 LocBTCB from BTIntf to BTMaint2.
; 10/10/85 BB Added use of new MOVEQ equates for GetBlock and RelBlock. Added
; GetMaxKey subroutine and a call to it in BuildIRec. Did some
; minor code clean up.
; 9/26/85 BB Modified GetNode 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 Modified RelNode to handle a null node pointer and to call
; ChkNode.
; 9/23/85 BB Added ClrNode and a call to it in InitNode.
; 9/6/85 BB Fixed minor bugs in GetNodeSize and GetOffA.
; 8/29/85 BB Changed ChkNode to use a more efficient method for checking
; record offsets.
; 8/22/85 BB Added GetNode,RelNode, and ChkNode.
; 8/8/85 BB Modified GetOffset and InitNode for new node format.
; 7/31/85 BB Fixed bug in LocRec which was causing the "write" problem.
; 7/17/85 BB Added GetNodeSiz. Modified GetRecA to also return record size.
; 7/8/85 BB Modified GetLtSib/GetRtSib 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 InsertRec to return node number and record index of new
; record.
; 2/18/85 BB Modified LocRec 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 Added KeyCompare routine.
; 1/5/85 BB Changed CopyRec to LocRec to support return of key and data
; record pointers instead of copying that data.
; 1/5/85 BB Modified SearchNode to use external key compare routine.
; 10/1/84 BB Split off from BTmaint.
;
;__________________________________________________________________________________
;
; External
; Routines: BuildIRec - Builds an index record for a specified target node.
; ChkNode - Checks the validity of a node.
; ClrNode - Clears a node (to zero).
; DeleteRec - Deletes a record from a BTree node.
; GetMaxKey - Gets max key size rounded to word boundry.
; GetNode - Gets a BTree node from disk.
; GetNodeSiz - Gets the size of the data currently contained in a
; node (record data + offset overhead).
; GetLtSib - Gets left sibling node for a given BTree node.
; GetRtSib - Gets right sibling node for a given BTree node.
; GetOffset - Gets the record offset and the pointer to the offset
; word for a given record index.
; GetRecA - Gets the address of the record for a given record
; index.
; InitNode - Gets a cache buffer for a new node and initializes it to
; an empty state.
; InsertRec - Inserts a record into a BTree node.
; LocBTCB - Locates the BTCB for a BTree file.
; LocRec - Locates the key and data records for a specified
; BTree record.
; LocTPR - Locates the Tree Path Record (TPR) for a given tree
; level.
; MovOffLt - Move offsets left within a single node.
; MovOffRt - Move offsets right within a single node.
; MovRecLt - Move records left within a single node.
; MovRecRt - Move records right within a single node.
; RelNode - Releases the use of a node.
; SearchNode - Searches a BTree node for a specified key.
; UpdDRec - Updates the data portion of a BTree record.
; UpdIKey - Updates the key portion of an index record.
;
; Internal
; Subroutines: None.
;
;__________________________________________________________________________________
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
PRINT ON
PRINT NOGEN
BTMaint2 PROC EXPORT
EXPORT BuildIRec,ChkNode,ClrNode,DeleteRec
EXPORT GetMaxKey,GetNode,GetNodeSiz,GetLtSib,GetRtSib,GetOffset,GetRecA
EXPORT InitNode,InsertRec,LocBTCB,LocRec,LocTPR
EXPORT MovOffLt,MovOffRt,MovRecLt,MovRecRt
EXPORT RelNode,SearchNode,UpdDRec,UpdIKey
EXPORT vGetNode,vRelNode
IMPORT GetBlock,RelBlock
;__________________________________________________________________________________
;
; Routine: BuildIRec
;
; 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
;__________________________________________________________________________________
BuildIRec
MOVE.L D2,-(SP) ; save regs
MOVE.L D0,D2 ; save node number
CLR.W D0 ; locate 1st record
BSR GetRecA ; ...in node
MOVEA.L BTCVarPtr(A4),A1 ; locate record buffer
LEA BTVRecord(A1),A1 ;
JSR UpdIKey ; move in the key
BSR GetMaxKey ; 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 BuildIRec
;__________________________________________________________________________________
;
; Routine: ChkNode
;
; 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: GetNode
;__________________________________________________________________________________
ChkNode
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 FCBPLen(A2,D1.W),D0 ; PEOF / node size
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 GetOffset ;
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 ChkNode
;__________________________________________________________________________________
;
; Routine: ClrNode
;
; Function: Clears a node to all zeroes.
;
; Input: A0.L - pointer to node buffer
; A4.L - pointer to BTCB
;
; Output none
;
; Called by: BTDelete
;__________________________________________________________________________________
ClrNode
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 ClrNode <23Sep85>
;__________________________________________________________________________________
;
; Routine: DeleteRec
;
; 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
;__________________________________________________________________________________
DeleteRec
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 GetOffset ;
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 GetOffSet ;
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 MovRecLt ; 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 MovOffRt ; adjust the offsets
DRExit
MOVEM.L (SP)+,D2-D6/A2-A5 ; restore regs
RTS ; return
;__________________________________________________________________________________
;
; Routines: GetLtSib (Get Left Sibling)
; GetRtSib (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
;__________________________________________________________________________________
GetLtSib
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D3,-(A6) ; save registers
CLR.B D3 ; indicate GetLtSib
BRA.S GSRtSib1 ; use common code
GetRtSib
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D3,-(A6) ; save registers
MOVEQ #1,D3 ; indicate GetRtSib
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 GetNode ; 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 GetLtSib/GetRtSib
;__________________________________________________________________________________
;
; Routine: GetMaxKey
;
; 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
;__________________________________________________________________________________
GetMaxKey
MOVEQ #2,D0 ; key length = 1 <10Oct85>
; 2, include length byte <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 GetMaxKey <10Oct85>
;__________________________________________________________________________________
;
; Routine: GetNode
;
; 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
;__________________________________________________________________________________
GetNode
MOVE.L jGetNode,-(SP) ; jumptable entry for vGetNode <25Oct85>
RTS ; go there <25Oct85>
vGetNode ; 'vectored' GetNode routine <25Oct85>
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 GetBlock ; get the block
BNE.S GNExit ; didn't get it ->
MOVEA.L A0,A1 ; verify the node
BSR ChkNode ;
BEQ.S GNExit ; its ok -> <26Sep85>
MOVE.W D0,-(A6) ; save result code <26Sep85>
MOVEQ #kRBTrash,D1 ; set trash option <10Oct85> <26Sep85>
MOVEA.L BTCCQptr(A4),A1 ; ptr to cache queue <26Sep85>
JSR RelBlock ; release it <26Sep85>
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 GetNode
;__________________________________________________________________________________
;
; Routine: GetNodeSiz (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
;__________________________________________________________________________________
GetNodeSiz
MOVE.L D1,-(SP) ; save registers
MOVE.W NDNRecs(A1),D1 ; number of records in node
MOVE.W D1,D0 ; record data size
JSR GetOffset ; = 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 GetNodeSiz
;__________________________________________________________________________________
;
; Routine: GetOffset (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
;__________________________________________________________________________________
GetOffset
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: GetRecA (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
;__________________________________________________________________________________
GetRecA
MOVEM.L D1-D2,-(SP) ; save registers
MOVE.W D0,D1 ; D1 = record index
BSR.S GetOffSet ; 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 GetOffSet ;
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: InitNode
;
; 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
;__________________________________________________________________________________
InitNode
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 GetBlock ; get cache buffer
BNE.S INExit1 ; error ->
;
; initialize the node
;
BSR ClrNode ; 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 InitNode
;__________________________________________________________________________________
;
; Routine: InsertRec
;
; Function: Inserts a record into a BTree node.
;
; Input: A0.L - pointer to record
; A1.L - ptr(node buffer)
; D0.W - size of record
; 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,RotateLt,RotRecLt
;__________________________________________________________________________________
InsertRec
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 GetOffset ;
MOVE.W D0,D4 ; D4 = insert offset
MOVE.W NDNRecs(A1),D0 ; number of keys = last index
JSR GetOffSet ;
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 MovRecRt ; 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 MovOffLt ; 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 MovRecLt ; 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 InsertRec
;__________________________________________________________________________________
;
; Routine: LocBTCB (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
;__________________________________________________________________________________
LocBTCB
;
; locate BTCB for the file
;
MOVEA.L FCBSPtr,A4 ; start of FCBS
MOVEA.L FCBBTCBptr(A4,D0.W),A4 ; ptr(BTCB)
RTS ; exit LocBTCB
;__________________________________________________________________________________
;
; Routine: LocRec (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
;__________________________________________________________________________________
LocRec
MOVEM.L D0/D2-D3,-(SP) ; save registers
MOVE.W D1,D3 ; D3 = record index
MOVE.W D3,D0 ; locate
JSR GetRecA ; ...the record
MOVE.L A0,D2 ; D2 = ptr(record)
MOVE.W D3,D0 ; locate
ADDQ #1,D0 ;
JSR GetRecA ; ...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 LocRec
;__________________________________________________________________________________
;
; Routine: LocTPR (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)
;__________________________________________________________________________________
LocTPR
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: MovOffLt
;
; 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
;__________________________________________________________________________________
MovOffLt
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: MovOffRt
;
; 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
;__________________________________________________________________________________
MovOffRt
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: MovRecLt
;
; 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
;__________________________________________________________________________________
MovRecLt
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: MovRecRt
;
; 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
;__________________________________________________________________________________
MovRecRt
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: RelNode
;
; Function: Releases use of a BTree node obtained by GetNode.
; 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,TreeSearch
;__________________________________________________________________________________
RelNode
MOVE.L jRelNode,-(SP) ; jumptable entry for vRelNode <25Oct85>
RTS ; go there <25Oct85>
vRelNode ; 'vectored' RelNode routine <25Oct85>
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 ChkNode ; <21Sep85>
BEQ.S @1 ; ok -> <21Sep85>
_HFSDSErr ; *** HALT *** <24Sep85>
ENDIF
@1 JSR RelBlock ; release the block
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 RelNode
;__________________________________________________________________________________
;
; Routine: SearchNode
;
; 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,TreeSearch
;__________________________________________________________________________________
SearchNode
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 GetRecA ;
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 SearchNode
;__________________________________________________________________________________
;
; Routine: UpdDRec (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
;__________________________________________________________________________________
UpdDRec
MOVEM.L D0-D1/A0-A2,-(SP) ; save registers
MOVEA.L A0,A2 ; A2 = ptr(data record)
JSR LocRec ; 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 UpdDRec
;__________________________________________________________________________________
;
; Routine: UpdIKey (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
;__________________________________________________________________________________
UpdIKey
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)
MOVE.B (A0)+,D0 ; source key length
EXT.W D0 ;
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 UpdIKey
END