// LookupEntries:
// last edited 4 December 1977 by E. Fiala

//  Look up a collection of names in a directory.
//  S is the directory (a disk stream), which gets reset.
//  NameVec is a vector of Cnt strings:
//      zeros in NameVec are ignored.
//  PrVec is a vector of lDV*Cnt words into which the directory
//      entries (without the name) are read.
//  If FilesOnly, only looks at dvTypeFile entries.
//  Buf, if supplied, is a buffer of size BufLen

//  Returns number of names not found (hopefully 0).
//  Those names will have 0 in the first word of their PrVec entries.
  
get "AltoFileSys.d"

external [
		// Defined here
	LookupEntries

		// OS
	Resets; Gets; Endofs
	Dvec
	MoveBlock
	ReadBlock
	Usc
	Zero
	]

manifest [
	MinBufLen = lDV+lSTRING	// Minimum buffer size
	MaxBufLen = #77777	// Maximum buffer size to avoid Usc
	]

let LookupEntries(S, NameVec, PrVec, Cnt, FilesOnly, Buf, BufLen) = valof 
[LUE	
	let typDV = FilesOnly ? dvTypeFile,dvTypeFree
	if Usc(BufLen, MaxBufLen) gr 0 then BufLen = MaxBufLen

	let NotFound = 0		// Number of names not found yet
	for i = 0 to Cnt-1 do
	  if NameVec!i ne 0 then NotFound = NotFound+1
	Zero(PrVec,lDV*Cnt)	// Clear DV's
	Resets(S) 
	let endp = Buf	// End of valid info in buffer

	until Endofs(S) do
	[FILL
	  endp = ReadBlock(S,endp,Buf+BufLen-endp)+endp	// Fill buffer
	  let dv = Buf
	  [ITEM
	    let elen = dv + dv>>DV.length
	    unless dv>>DV.type ne typDV do 
	    [LOOK
	      if (elen-endp) gr 0 do	// Whole entry isn't in buffer
	      [ MoveBlock(Buf, dv, endp-dv)
	        endp = endp+Buf-dv	// Move end pointer down
	        break			// Let FILL read some more
	      ]
	      let Name = dv+lDV		// Fabricate pointer to name in DV
//Append a "." if necessary
	      let nlen = Name>>STRING.length
	      if Name>>STRING.char↑nlen ne $. then
	      [	Name>>STRING.length = nlen+1
		Name>>STRING.char↑(nlen+1) = $.
	      ]
MDIloop:      for I = 0 to Cnt-1 do	// Loop through names
	      [ let tP = NameVec!I
//If tLen-Len eq -1 then user didn't give "."
//Upper case match first char at same time
		if ((Name!0 - tP!0) & 177337B) ne 0 then loop
	        let tLen,PrPtr = tP>>STRING.length,nil
	        if ((Name>>STRING.char↑tLen - tP>>STRING.char↑tLen)
	            & 337B) ne 0 then loop
	        for J = 1 to ((tLen-1) rshift 1) do
		  if ((Name!J - tP!J) & 157737B) ne 0 then goto NOTEQ
		PrPtr = PrVec+(I*lDV)
	        // If Len ne tLen, the extra character must be
	        // a final ".", so the comparison is successful
	        if PrPtr!0 eq 0 then NotFound = NotFound-1
	        MoveBlock(PrPtr, dv, lDV)
	        PrPtr!0=1
	        break
NOTEQ:
	      ]
	    ]LOOK
// Skip over the entry we just processed
	    test (elen-endp) < 0
	    ifso dv = elen
	    ifnot
	    [ for i = 1 to elen-endp do Gets(S)
	      endp = Buf; break		// Read some more
	    ]
	  ]ITEM repeat
	]FILL

	resultis NotFound
]LUE