[net.micro.cpm] Request for CP/M help on Find Next

rgt%a@LANL.ARPA (Richard Thomsen) (10/11/85)

	I need some help on using the CP/M Find First/Find Next commands.
I use the following routine to find the first file on the disk by using
the Find First CP/M command, then open the file and print the file name.
Then I close the file and use the same routine to find the next file.
On calling this routine, the ambigious file name is pointed to by reg HL,
and the last file found is pointed to by reg DE.  Reg A contains the value
zero on the first call, and 7 on successive calls.  I stepped through this
code with DDT, and everything seems proper, but the Find Next call always
returns with Reg A = 0FFH to indicate no files found.  But files exist!

	I got this code from _The CP/M Programmer's Handbook_ by Andy
Johnson-Laird, but it never finds the second or later files.  Another
version of code using this routine finds some, but not all, of the files
on the disk.  What am I doing wrong???

	I looked through the INSIDCPM.LBR, but they are not really doing
anything similar.  When I modify the program to not open the files that
were found, but just print the names, and also to not do the Find First
again, then it finds all the files.  But I need to open the files and
copy them, and this seems to screw up the Find Next!  Can anyone help?????


;++
;
;   TITLE:		GETNEXTF
;
;   TYPE:		Subroutine
;
;   ABSTRACT:
;
;	This subroutine gets the next file FCB from a possibly ambiguous file
;	name.  The actual FCB is stored in the destination FCB.
;
;
;   INPUTS:
;
;	Reg HL	--  Address of the possibly ambiguious file name FCB.
;	Reg DE	--  Address of FCB to contain the file name found
;	Reg A	--  File control byte.
;			Zero to return the first file name that matches
;			Non-zero to return the next file name that matches
;
;   OUTPUTS:
;
;	Carry	--  Exit status
;			Set	--  File not found
;			Clear	--  File name found and FCB set up
;
;   SIDE EFFECTS:
;
;	Address pointed to by reg DE is set to file name found.
;	DMA address is changed.
;
;   REGISTERS CHANGED:	A, B, C
;
;--
;
;   Define the data areas and values used by this subroutine
;
GNFFCBMOVSIZE	EQU	13		;Define size of FCB to be moved
GNFDIRBUF	DS	128		;Define buffer area for directory
;
;   Start of code  --  save the FCB addresses
;
GETNEXTF:
	PUSH	D		;Save destination FCB on stack
	PUSH	H		;Save source FCB on stack
	PUSH	PSW		;Save First/Next flag on stack
;
;   Set the DMA address to the directory buffer
;
	LXI	D,GNFDIRBUF	;Get address of directory buffer
	MVI	C,SETDMA	;Get code for set DMA
	CALL	BDOS		;Call BDOS to set the DMA address
;
;   DMA address set  --  see if first or next
;
	POP	PSW		;Restore First/Next flag
	ORA	A		;Check First/Next flag
	JNZ	GNFNEXT		;If next, use that call
;
;   Request is to get the first file name
;
	POP	D		;Get address of source file FCB for search
	PUSH	D		;And save it again
	MVI	C,SEARCHF	;Get code to search for first filename
	CALL	BDOS		;Call BDOS to perform search
	POP	H		;Restore address of source FCB
	POP	D		;Restore address of destination FCB
	CPI	0FFH		;See if file was found
	JZ	GNFFILENOTFND	;If not, then just exit with error
	JMP	GNFGETFCB	;Otherwise, get the FCB
;
;   Request is to get the next file name  --  search for next
;	First, the context of the file name must be restored by again
;	searching for the last one found.
;
GNFNEXT:
;
;   Request is to get the next file name  --  search for next
;	First, the context of the file name must be restored by again
;	searching for the last one found.
;
GNFNEXT:
	POP	H		;Recover address of source file name FCB
	POP	D		;Recover address of destination FCB
	PUSH	H		;Save them again, but in opposite order
	PUSH	D
	CALL	GNFZEROFILE	;Clear all but the name from the FCB
	POP	D		;Recover the destination FCB address
	PUSH	D		;And save it again
	MVI	C,SEARCHF	;Get code to search for the last file found
	CALL	BDOS		;And re-find that file

***   At this point, it finds the file again, as it should   ***

;
;   Now the FCB is set to what it was at the end of the last search.
;	Move the source FCB into the destination FCB and search for the next.
;
	POP	D		;Get the address of the destination FCB
	POP	H		;Get the address of the source FCB
	PUSH	D		;Save them again in the opposite order
	PUSH	H
	PUSH	D		;Save address of destination FCB again
	MVI	C,FCBSIZE	;Get the size of the FCB's
	CALL	MOVE		;Set the destination FCB to the source FCB
;
;   Now call the BDOS to search for the next occurance of the FCB
;
	POP	D		;Get address of destination FCB
	CALL	GNFZEROFILE	;And clear all but the name
	MVI	C,SEARCHN	;Get code to search for next file name
	CALL	BDOS		;Call the BDOS to do the search

***   At this point, it returns with Reg A = 0FFH, indicating no more files

	POP	H		;Restore the address of the source FCB
	POP	D		;Restore the address of the destination FCB
	CPI	0FFH		;See if file was found
	JZ	GNFFILENOTFND	;If not, then just exit with error
;
;
;   File was found  --  save the filename found in the save area for
;	next search
;
GNFGETFCB:
	PUSH	H		;Save the address of the source FCB
	PUSH	D		;Save the address of the destination FCB
	ADD	A		;Multiply return code by 32 to get offset
	ADD	A		;4
	ADD	A		;8
	ADD	A		;16
	ADD	A		;32
	LXI	H,GNFDIRBUF	;Get address of directory buffer
	MOV	E,A		;Put offset into reg E
	MVI	D,0		;Clear reg D to get 16-bit offset
	DAD	D		;Add to directory buffer
	POP	D		;Get address of destination FCB
	PUSH	D		;And save it again
	MVI	C,FCBSIZE	;Get size of entry to save
	CALL	MOVE		;Move name into save area
	POP	D		;Get the address of the destination FCB
	POP	H		;Get the address of the source FCB
	MOV	A,M		;Get the disk/user number from source
	STAX	D		;Store disk/user number in destination FCB
;
;   FCB now set to next disk  --  zero fill it for any disk commands
;
	PUSH	D		;Save the address of the destination FCB
	PUSH	H		;Save the address of the source FCB
	CALL	ZEROFCB		;Zero fill the FCB
	POP	H		;Restore the address of the source FCB
	POP	D		;Restore the address of the destination FCB
	XRA	A		;Clear carry to indicate success
	RET			;And return to caller
;
;   File not found  --  return error code to user
;
GNFFILENOTFND:
	STC			;Set carry to indicate error
	RET			;And return to caller
;
;   Clear the FCB except for the disk, file name, file type, and extent
;	Address of FCB is in reg DE.
;
GNFZEROFILE:
	LXI	H,13		;Bypass the file name and extent stored
	DAD	D		;Get the address of the part to clear
	MVI	C,36-13		;Get number of bytes to clear
GNFZEROFILELP:
	MVI	M,0		;Clear the byte
	INX	H		;Increment to next byte
	DCR	C		;Decrement count
	JNZ	GNFZEROFILELP	;Continue for all bytes
	RET			;Otherwise, return to caller
;

	Version 2.2 (I believe) of CP/M on a DEC Rainbow 100+.

						Richard Thomsen
						rgt@lanl

bridger@RAND-UNIX.ARPA (Bridger Mitchell) (10/11/85)

The cp/m 2.2 search first/search next functions must be used
with NO INTERVENING bdos or bios file i/o calls.  Search-next
proceeds from internal bdos pointers and the bios's directory
buffer contents; a close-function, for example, will change
both and a subsequent search-next will be proceeding from
the end of the directory.  It is ok to use selected other (non-file i/o)
calls between search function calls, e.g. print-character.

--bridger mitchell