mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-25 09:30:50 +00:00
1172 lines
33 KiB
Plaintext
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
|
|
|
|
|