// LookupEntries:
//  Last modified by December 21, 1979  1:57 PM by Lyle Ramshaw,
//	Patched things so that a name appearing more than once in 
//	NameVec will be handled correctly.

// last edited October 4, 1977  10:49 AM by P. Deutsch
// Copyright Xerox Corporation 1979

//  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
	StripVersion
	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; numargs Na) = valof 
  
[LUE	
	test (Na ls 7) % (BufLen ls MinBufLen) 
	 ifso	// Allocate a local buffer
	[ BufLen = MinBufLen
	  Buf = BufLen
	  Dvec(LookupEntries, lv Buf)
	]
	 ifnot
	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 typ = dv>>DV.type
	    let elen = dv>>DV.length
	    unless (FilesOnly? typ ne dvTypeFile, typ eq dvTypeFree) do 
	    [LOOK
	      let len1 = (elen gr MinBufLen? MinBufLen, elen)	// Need to look at this much of the entry
	      if (dv+len1-endp) gr 0 then	// 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
	      let vn=StripVersion(Name)	//will append a "." if needed
	      if vn eq 0 then vn=1
	      let Len = Name>>STRING.length
	      let PrPtr = PrVec-lDV
	      for I = 0 to Cnt-1 do	// Loop through names
	      [ PrPtr = PrPtr+lDV	// Loop if already found higher version
	        if PrPtr!0 gr vn then loop
	        let tP = NameVec!I
	        if tP eq 0 then loop	// Skip this entry
	        let tLen = tP>>STRING.length
	        let d=tLen-Len
	        if (d ne 0) & (d ne -1) then loop // -1 if user didn't give "."
	        for J = 1 to tLen do
	          if ((Name>>STRING.char↑J xor tP>>STRING.char↑J)
	            & (not #40)) ne 0 then goto NOTEQ
	        // 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=vn		//Version we found
NOTEQ:
	      ]
	    ]LOOK
	    // Skip over the entry we just processed
	    test (dv+elen-endp) ls 0
	     ifso dv = dv+elen	// Entire entry is in the buffer
	     ifnot
	    [ for i = 1 to elen+dv-endp do Gets(S)	// Skip rest of entry
	      endp = Buf	// Used up the whole buffer
	      break	// Read some more
	    ]
	  ]ITEM repeat
	]FILL

	resultis NotFound
]LUE