Date : Fri, 11 Oct 1985 09:56:24 mdt
From : Richard Thomsen <rgt%a@LANL.ARPA>
Subject: Request for CP/M help on Find Next
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