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