;FIND.ASM ; ;03/Aug/82 ADDED DETECT OF CONTROL X TO SKIP TO NEXT FILE ; AFTER DISASSEMBLING A VERSION OF FIND DATED ; 8/Nov/80 (FOR WHICH I DIDN'T HAVE THE SOURCE) ; AND FINDING THAT FEATURE IMPLEMENTED. Bill Bolton ; ;01/Aug/82 DOING "FIND *.* [any garbage string]" ON AN RCPM ; SYSTEM WOULD GIVE A DIRECTORY OF ALL FILES ON THE ; DISK, INCLUDING TAGGED AND SYSTEM FILES WHICH MAY ; HAVE BEEN INTENDED TO BE "INVISIBLE". ADDED FILE ; TYPE AND ATTRIBUTE CHECKING FROM "DISPLAY" TO ; PREVENT THIS HAPPENING. FILES WITH TYPE "ALL" ; (WHICH I USE FOR CATALOGUES) WILL BE SCANNED NO ; MATTER WHAT ATTRIBUTES ARE SET. THIS ALLOWS THE ; CATALOGUES TO BE "FIND"ed AND "DISPLAY"ed BUT NOT ; "TYPE"ed OR "XMODEM"ed. IMPLEMENTED FOR CONDITIONAL ; ASSEMBLY. ALSO CHANGED ABORT TO ONLY RESPOND TO ; CONTROL-C OR CONTROL-K TO ELIMINATE PROBLEMS ON ; REMOTE SYSTEMS WITH SUPRIOUS CHARACTERS OFF THE LINE ; PREMATURELY ABORTING A "FIND". CHANGED THE ABORT CHECK ; TO DIRECT CONSOLE INPUT (BDOS 6) SO THE A CP/M VERSION ; NUMBER CHECK WAS ADDED. Bill Bolton ; ;18/Mar/80 MAKE "_" MATCH A TAB; MAKE "|" AN "OR" ; AS IN: FIND B:*.ASM _IN_|_OUT_ ; ;27/Feb/80 TRANSLATE FILE READ CHARS TO UPPER CASE ; SO CASE DOESN'T MATTER IN FILE CONTENTS. ; ALSO PUT IN "JUST IN CASE" TEST FOR LINE ; LONGER THAN 128. ; ;27/Jan/80 PUT IN CTL-C BREAK ; ;23/Jun/79 ORIGINALLY WRITTEN BY WARD CHRISTENSEN ; ---------------- ;USED TO DO A CHARACTER STRING SEARCH ;OF ONE OR MORE FILES. ANY ASCII STRING ;MAY BE SEARCHED FOR. CASE DOESN'T MATTER. ; ;COMMAND FORMAT: ; ; FIND FILENAME STRING ; ;FILENAME MAY BE AMBIGUOUS, ; E.G. *.ASM OR CBBS*.ASM ; ;"_" IN STRING WILL MATCH A TAB. ; CR EQU 0DH LF EQU 0AH EOF EQU 1AH CNTRLC EQU 3 TAB EQU 9 CNTRLK EQU 11 CNTRLS EQU 19 CNTRLX EQU 24 ; FALSE EQU 0 TRUE EQU NOT FALSE ; RCPM EQU TRUE ;True for restricted filetype search ; MF SET 0 ;SHOW MOVE NOT REQUESTED CF SET 0 ;SHOW COMP NOT REQUESTED ; ;(FROM EQU8.LIB...) ;DEFINE SOME MACROS TO MAKE THINGS EASIER ; ;DEFINE DATA MOVE MACRO: MOVE from,to,length ; from may be addr, or quoted string ; MOVE MACRO ?F,?T,?L IF NOT NUL ?F IRPC ?C,?F ?Q SET '&?C&?C' ;;TEST FOR QUOTE EXITM ENDM IF ?Q EQ '''' LOCAL ?B,?Z CALL ?Z ?B DB ?F ?Z POP H ;GET FROM LXI B,?Z-?B ;GET LEN ELSE LXI H,?F ENDIF ENDIF IF NOT NUL ?T LXI D,?T ENDIF IF NOT NUL ?L LXI B,?L ENDIF CALL MOVER MF SET -1 ;;SHOW EXPANSION ENDM ;COMPARE MACRO COMP MACRO ?F,?T,?L IF NOT NUL ?F IRPC ?C,?F ?Q SET '&?C&?C' ;;TEST FOR QUOTE EXITM ENDM IF ?Q EQ '''' LOCAL ?B,?Z CALL ?Z ?B DB ?F ?Z POP H ;GET FROM LXI B,?Z-?B ;GET LEN ELSE LXI H,?F ENDIF ENDIF IF NOT NUL ?T LXI D,?T ENDIF IF NOT NUL ?L LXI B,?L ENDIF IF NOT NUL ?I LOCAL ?B,?Z CALL ?Z ?B DB ?I ?Z POP D ;GET TO LXI B,?Z-?B ENDIF CALL COMPR CF SET -1 ;;SHOW EXPANSION ENDM ; ;DEFINE CP/M MACRO - CPM FNC,PARM ; CPM MACRO ?F,?P PUSH B PUSH D PUSH H IF NOT NUL ?F MVI C,?F ENDIF IF NOT NUL ?P LXI D,?P ENDIF CALL BDOS POP H POP D POP B ENDM ; ORG 100H CALL START DB 'FIND.COM ' DB '03/Aug/82' DB 0DH,0AH,'$' START POP D ;GET ID MVI C,PRINT CALL BDOS ;PRINT ID ; ;INIT LOCAL STACK ; LXI H,0 DAD SP SHLD STACK LXI SP,STACK ; ;START OF PROGRAM EXECUTION ; CPM VERSION MOV A,L ;A <---- VERSION NUMBER CPI 20H JNC CHECK$NAME CALL ERXIT DB '++ CP/M Version 2.0 or later is required to run FIND$' ; CHECK$NAME: LDA FCB+1 CPI ' ' JNZ GETSTR CALL ERXIT DB '++NO FILE NAME++$' ; ;FIND START OF STRING IN TBUFF ; GETSTR LXI D,80H ;DE=TBUFF LDAX D ;LENGTH MOV C,A ;SAVE LENGTH MVI B,0 ;SETUP BC FOR MOVE INX D ;PAST LENGTH MOV L,A ;L=LENGTH MVI H,0 ;HL=LENGTH DAD D ;HL=LAST CHAR MVI M,0 ;STORE END DELIM ; ;SCAN FOR START OF STRING ; XCHG ;START TO HL SCAN INX H ;TO NEXT CHAR MOV A,M ;LOOK FOR ' ' ORA A ;END? JZ BADSTR ;..YES, BAD CPI ' ' JNZ SCAN ;NOT AT ' ' INX H ;TO STRING ; MOVE ,STRING, ;HL = FROM, BC=LENGTH NEXTFL CALL MFNAME ;GET NEXT JC EXIT CPM OPEN,FCB INR A JZ EXIT IF RCPM ; ;Check for .ALL file, which can always be scanned ; ALLCHK: LDA FCB+11 CPI 'L' ;WAS LAST CHAR AN 'L'? JNZ CKFIL ;IF NOT, TRY NEXT TEST LDA FCB+10 ;CHK NEXT ANI 07FH ;Forget attributes for this test CPI 'L' ;AN 'L'? JNZ CKFIL ;IF NOT, TRY NEXT TEST LDA FCB+9 ;WAS 'L', CHK NEXT CHAR ANI 07FH ;Forget attributes for this test CPI 'A' ; 'A' AS IN '.ALL'? JZ OK$SCAN ;YES, GO SCAN IT ; ;Check for file protected by CP/M 2.x f2' attribute ; CKFIL: LDA FCB+2 ;POINT TO TAG FILE ATTR ANI 80H ;IS IT TAGGED? JZ CKFIL2 ;IF NOT, CONTINUE ; PROXIT: JMP NEXTFL ;SEE IF ANOTHER ; CKFIL2: LDA FCB+10 ;POINT TO SYS FILE ATTR ANI 80H ;IS IT SYS? JNZ PROXIT ;SYS file, can't print it ; ;Check for .COM file, which can't be scanned ; LDA FCB+11 CPI 'M' ;WAS LAST CHAR AN 'M'? JNZ OBJCHK ;IF NOT, CHK FOR '.OBJ' TYPE LDA FCB+10 ANI 7FH ;STRIP CP/M 2.x ATTR CPI 'O' ;AN 'O'? JNZ OK$SCAN ;IF NOT IT'S OK TO SCAN LDA FCB+9 ANI 7FH ;STRIP CP/M 2.x ATTR CPI 'C' ;'C' AS IN '.COM'? JNZ OK$SCAN ;IF NOT, IT'S OK TO SCAN JMP NEXTFL ;MORE TO PRINT? ; ;Check for .OBJ file, which can't be scanned ; OBJCHK: CPI 'J' ;WAS LAST CHAR AN 'J' ? JNZ OK$SCAN ;IF NOT, OK TO SCAN LDA FCB+10 ;MIGHT BE '.OBJ', CHK NEXT CHR ANI 7FH ;STRIP CP/M 2.x ATTR CPI 'B' ;IS IT A 'B'? JNZ OK$SCAN ;IF NOT, SCAN LDA FCB+9 ;WAS, CHK FIRST CHAR ANI 7FH ;STRIP CP/M 2.x ATTR CPI 'O' ;'O' AS IN '.OBJ'? JNZ OK$SCAN ;IF NOT, SCAN THE FILE, IF SO JMP NEXTFL ;MORE TO SCAN? ENDIF ;RCPM ; OK$SCAN: MOVE ' 0',LINENO MOVE FCB+1,FNAME,8 MOVE FCB+9,FNAME+9,3 CALL ILPRT DB '----> FILE ' FNAME DB 'XXXXXXXX.XXX' DB CR,LF,0 LXI H,0 SHLD EFCBCT ;ZERO COUNT ; ;BUMP ASCII LINE # ; NEXTLN LXI H,LINENO+3 NEXTADD MOV A,M ;GET DIGIT ORI '0' ;MAKE ASCII INR A MOV M,A CPI '9'+1 ;CARRY? JNZ NEXTNC MVI M,'0' DCX H JMP NEXTADD ; NEXTNC LXI H,LINE MVI B,0FFH ;SO LONG LINE WON'T BLOW NEXTLC INR B JM LONG ;TOO LONG A LINE PUSH B PUSH H LXI H,EFCB CALL RDBYTE POP H POP B MOV M,A INX H CPI EOF JZ NEXTFL ;NEXT FILE CPI LF JNZ NEXTLC JMP EOL ; ;GOT A LONG LINE - STICK CRLF IN MIDDLE ; LONG MVI M,0DH INX H MVI M,0AH EOL CPM DIRECT,0FFH ;TEST FOR USER COMMAND ORA A CNZ CHREXIT ;PARSE COMMAND JC NEXTFL ; ;READ IN A LINE, NOW SCAN FOR THE STRING ; LXI H,STRING ORLINE SHLD STRPTR LXI H,LINE NEXTST XCHG LHLD STRPTR XCHG PUSH H NEXTC LDAX D CPI '_' JNZ NOTAB MVI A,TAB NOTAB INX D ORA A ;END OF STRING? JZ MATCHED CPI '|' JZ MATCHED ;FIRST PART MOV C,M ;FOR LOWER CASE TEST CMP M INX H JZ NEXTC MOV B,A ;SAVE CHAR MOV A,C ;GET CHAR CPI 61H ;LOWER? JC NOTEQ ;NO, SO NO MATCH CPI 7BH JNC NOTEQ ANI 5FH ;MAKE UPPER CASE CMP B JZ NEXTC ;MATCHED NOTEQ POP H ;RESTORE ADDR INX H MOV A,M CPI CR JNZ NEXTST ; ;IF AN "OR" (|) IS IN THE LINE, SCAN FOR IT ; LHLD STRPTR FINDOR MOV A,M INX H CPI '|' JZ ORLINE ORA A JNZ FINDOR JMP NEXTLN ; ;GOT MATCH, PRINT IT ; MATCHED POP H ;KILL STACKED ADDR CALL ILPRT LINENO DB ' ',TAB,0 ; LXI H,LINE MATCHLP MOV A,M MOV E,A CPM WRCON MOV A,M INX H CPI LF JNZ MATCHLP JMP NEXTLN ; ;INLINE PRINT - CALL ILPRT FOLLOWED BY MSG, ;WHICH ENDS IN A: 0 ; ILPRT XTHL ;GET MSG ADDR, SAVE HL ILPLP MOV E,M CPM WRCON INX H MOV A,M ORA A ;END? JNZ ILPLP XTHL RET ; BADSTR CALL ERXIT DB '++BAD STRING++$' ; ;FOLLOWING FROM 'EQU8.LIB'----> ; ;MOVE, COMPARE SUBROUTINES ; IF MF ;MACRO EXPANSION FLAG SET? ; MOVER MOV A,M STAX D INX H INX D DCX B MOV A,B ORA C JNZ MOVER RET ENDIF ; IF CF ;MACRO EXPANSION FLAG SET? COMPR LDAX D CMP M RNZ INX D INX H DCX B MOV A,B ORA C JNZ COMPR RET ENDIF ; ; FROM EQU8.LIB: AS OF 05/06/79 ; ;RDBYTE, HL POINTS TO EXTENDED FCB: ; ; 2 BYTE BUFFER ADDR ; 2 BYTE "BYTES LEFT" (INIT TO 0) ; 1 BYTE BUFFER SIZE (IN PAGES) ; 2 BYTE FCB ADDRESS ; RDBYTE MOV E,M INX H MOV D,M ;GET BUFFER ADDR INX H MOV C,M INX H MOV B,M ;BC = BYTES LEFT MOV A,B ;GET COUNT ORA C JNZ RDBNORD ;NO READ ; INX H ;TO BUFFER SIZE MOV A,M ;GET COUNT ADD A ;MULTIPLY BY 2 MOV B,A ;SECTOR COUNT IN B INX H ;TO FCB PUSH H ;SAVE FCB POINTER MOV A,M ;GET.. INX H ;..FCB.. MOV H,M ;..ADDR.. MOV L,A ;..TO HL ; RDBLP MVI A,1AH ;GET EOF CHAR STAX D ;SAVE IN CASE EOF PUSH D ;SAVE DMA ADDR PUSH H ;SAVE FCB ADDR CPM STDMA ;SET DMA ADDR POP D ;GET FCB CPM READ ORA A POP H ;HL=DMA, DE=FCB JNZ RDBRET ;GOT EOF MOV A,L ADI 80H ;TO NEXT BUFF MOV L,A MOV A,H ACI 0 MOV H,A XCHG ;DMA TO DE, FCB TO HL DCR B ;MORE SECTORS? JNZ RDBLP ;YES, MORE RDBRET POP H ;GET FCB POINTER DCX H ;TO LENGTH MOV A,M ;GET LENGTH DCX H ;TO COUNT MOV M,A ;SET PAGE COUNT DCX H ;TO LO COUNT DCX H ;TO HI FCB DCX H ;TO EFCB START JMP RDBYTE ;LOOP THRU AGAIN ; RDBNORD INX H ;TO LENGTH MOV A,M ;GET LENGTH (PAGES) XCHG ;BUFF TO HL ADD H MOV H,A ;HL = END OF BUFF MOV A,L SUB C MOV L,A MOV A,H SBB B MOV H,A ;HL = DATA POINTER MOV A,M ;GET BYTE XCHG ;EFCB BACK TO HL CPI 1AH ;EOF? RZ ;YES, LEAVE POINTERS DCX B ;DECR COUNT DCX H ;BACK TO "BYTES LEFT" MOV M,B DCX H MOV M,C ;STORE BACK COUNT RET ; ;SAMPLE EFCB: ; ;EFCB DW BUFF ;BUFFER ADDR ; DW 0 ;BYTES LEFT ; DB 20 ;BUFFER SIZE (IN PAGES) ; DW FCB ;FCB ADDRESS ; ; MUST BE ASSEMBLED BY "MAC" ; ;MULTI-FILE ACCESS SUBROUTINE. ALLOWS PROCESSING ;OF MULTIPLE FILES (I.E. *.ASM) FROM DISK. THIS ;ROUTINE BUILDS THE PROPER NAME IN THE FCB EACH ;TIME IT IS CALLED. THIS COMMAND WOULD BE USED ;IN SUCH PROGRAMS AS MODEM TRANSFER, TAPE SAVE, ;ETC IN WHICH YOU WANT TO PROCESS SINGLE OR ;MULTIPLE FILES. ; ;JUST CALL "MFNAME" (Multiple File NAME) AND THE FCB ;WILL BE SET UP WITH THE NEXT NAME, READY TO ;DO NORMAL PROCESSING (OPEN, READ, ETC.) ; ;CARRY IS SET IF NO MORE NAMES CAN BE FOUND ; ;------------------------------------------------ ; ; MULTI-FILE ACCESS SUBROUTINE ; ;THE ROUTINE IS COMMENTED IN PSEUDO CODE, ;EACH PSEUDO CODE STATEMENT IS IN <<...>> ; MFNAME: ;<> CPM STDMA,80H XRA A ! STA FCBEXT ! STA FCBRNO ;<> LDA MFFLG1 ! ORA A ! JNZ MFN01 ; <> MVI A,1 ! STA MFFLG1 ; <> MOVE FCB,MFREQ,12 ;SAVE ORIG REQ LDA FCB ! STA MFCUR ;SAVE DISK IN CURR FCB ; <> MOVE MFREQ,FCB,12 CPM SRCHF,FCB ;<> JMP MFN02 MFN01: ; <> MOVE MFCUR,FCB,12 CPM SRCHF,FCB ; <> MOVE MFREQ,FCB,12 CPM SRCHN,FCB ;<> MFN02: ;<> INR A ! STC ! RZ ;<> DCR A ! ANI 3 ! ADD A ADD A ! ADD A ! ADD A ! ADD A ADI 81H ! MOV L,A ! MVI H,0 PUSH H ;SAVE NAME POINTER MOVE ,MFCUR+1,11 ;<> POP H ! MOVE ,FCB+1,11 ;<> XRA A ! STA FCBEXT ;<> RET ; ;MULTI-FILE ACCESS WORK AREA ; MFFLG1 DB 0 ;1ST TIME SW MFREQ DS 12 ;REQ NAME MFCUR DS 12 ;CURR NAME ;------------------------------------------------ ; ;EXIT, READING CHAR WHICH WAS TYPED TO INTERRUPT ; CHREXIT: CPI CNTRLC ;ABORT? JZ ABORT CPI CNTRLK ;ABORT? JZ ABORT CPI CNTRLX ;SKIP TO NEXT FILE? STC RZ CPI CNTRLS ;PAUSE? JZ PLOOP ORA A ;RESET CARRY FLAG RET ; PLOOP: CPM DIRECT,0FFH ORA A JZ PLOOP JMP CHREXIT ; ABORT: CALL MSGEXIT DB CR,LF,'++ABORT++$' ; ;EXIT WITH ERROR MESSAGE ; MSGEXIT EQU $ ;EXIT W/"INFORMATIONAL" MSG ERXIT POP D ;GET MSG MVI C,PRINT CALL BDOS ; ;EXIT, RESTORING STACK AND RETURN ; EXIT LHLD STACK SPHL RET ;TO CCP ; EFCB DW BUFF ;BUFFER ADDR EFCBCT DW 0 ;BYTES LEFT DB 20 ;BUFFER SIZE (IN PAGES) DW FCB ;FCB ADDRESS ; STRING DS 30 ;WHAT TO SEARCH FOR DS 200 ;STACK AREA STACK DS 2 STRPTR DS 2 ;POINTER FOR "|" SCAN LINE DS 133 BUFF EQU $ ;DISK READ BUFER ; ;BDOS/CBIOS EQUATES (VERSION 8) ; RDCON EQU 1 WRCON EQU 2 DIRECT EQU 6 PRINT EQU 9 RDCONBF EQU 10 CONST EQU 11 VERSION EQU 12 OPEN EQU 15 CLOSE EQU 16 SRCHF EQU 17 SRCHN EQU 18 ERASE EQU 19 READ EQU 20 WRITE EQU 21 MAKE EQU 22 REN EQU 23 STDMA EQU 26 BDOS EQU 5 FCB EQU 5CH FCB2 EQU 6CH FCBEXT EQU FCB+12 FCBRNO EQU FCB+32