; DirScanA.asm -- Scan directory buffer quickly
; Copyright Xerox Corporation 1979
; Last modified July 12, 1979  9:56 AM by Taft

.ent ScanDirBuffer

.srel

ScanDirBuffer: .ScanDirBuffer

.nrel

; ScanDirBuffer(ptr, endPtr, sdb)
; Scans memory in the region [ptr..endPtr) looking at directory entries,
; and returns a pointer to some "interesting" directory entry.
; It is assumed that endPtr-ptr le 2000B.
; sdb is a ScanDirBuffer state structure:
; structure SDB: [
;   name word		// -> name string, which must be all upper-case
;   length word		// number of words to check in the name string
;   ignoreFree word	// true to skip free blocks, false to stop on each
;   scratch word 5	// scratch area used by ScanDirBuffer
;   ]
; An interesting entry is one that:
; (1) is of dvTypeFile and matches name;
; (2) is of dvTypeFree and ignoreFree is false;
; (3) is not of dvTypeFile or dvTypeFree; or
; (4) extends to or beyond endPtr.

; structure of SDB:
name = 0
length = 1
ignoreFree = 2
frame = 3
endPtr = 4
nextPtr = 5
tempName = 6
tempLength = 7

lDV = 6

.ScanDirBuffer:
	sta 3 1 2
	lda 3 3 2		; ac3← sdb
	sta 2 frame 3		; save frame in sdb
	sta 0 nextPtr 3		; save ptr
	sta 1 endPtr 3		; save endPtr

; Examine next directory entry.
; First, extract length and examine type.
nextDV:	lda 2 nextPtr 3		; get ptr to directory entry
nextD1:	lda 0 0 2
	lda 1 c2000		; dvTypeFile = 1
	subz 1 0 snc		; if dvTypeFile, type bits become zero
	 jmp freeDV		; dvTypeFree = 0 (the only type < 1)
; If type was other than dvTypeFile then ac0 is now ge 2000B.
; Hence the following test is not needed.
;	sltu 0 1
;	 jmp exit		; not dvTypeFile, exit

; Check for entry extending beyond end of buffer
	add 2 0			; ac0← ptr+length
	lda 1 endPtr 3		; endPtr
	sltu 0 1
	 jmp exit		; extends to or beyond end, exit
	sta 0 nextPtr 3		; pointer to next directory entry

; Compare first word of name (length and first character).
; Most mismatches should occur at this point.
	lda 0 lDV 2		; get word from entry
	lda 1 c177737		; capitalize first character
	and 1 0
	lda 1 @name 3		; get word from name
	sub 1 0 szr
	 jmp nextDV		; did not match, advance to next entry

; First word matched.  Now prepare to check the rest of the name.
	lda 0 name 3		; set up name pointer and length in temps
	sta 0 tempName 3
	lda 0 length 3
	sta 0 tempLength 3
	jmp ecomp

comp:	inc 2 2			; advance directory entry pointer
	isz tempName 3		; advance name pointer
	lda 0 lDV 2		; get word from entry
	lda 1 c157737		; capitalize letters
	and 1 0
	lda 1 @tempName 3	; get word from name
	sub 1 0 szr
	 jmp nextDV		; did not match, advance to next entry
ecomp:	dsz tempLength 3	; decrement and test word count
	 jmp comp		; continue

; Name matched entirely.  Return pointer to directory entry.
	lda 0 length 3		; number of words we checked
	sub 0 2			; reset ptr to start of dir entry
	inc 2 2
	jmp exit

; Here for free entry.  Return it only if ignoreFree is false
freeDV:	add 1 0			; restore length
	lda 1 ignoreFree 3
	snz 1 1
	 jmp exit
	add 0 2			; ac2← ptr+length
	lda 1 endPtr 3		; endPtr
	sgeu 2 1
	 jmp nextD1		; not at end yet, advance to next entry
	sub 0 2			; restore ptr

; Here to exit.  ac2 has pointer to directory entry, ac3 to sdb.
exit:	mov 2 0			; return ptr
	lda 2 frame 3		; recover frame
	lda 3 1 2
	jmp 1 3

c177737: 177737
c157737: 157737
c2000:	2000

.end