;FIND.ASM
;
;       06/23/79
;ORIGINALLY WRITTEN BY WARD CHRISTENSEN
;       01/27/80
;PUT IN CTL-C BREAK
;       02/27/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.
;       03/18/80
;MAKE "_" MATCH A TAB; MAKE "|" AN "OR"
;AS IN: FIND B:*.ASM _IN_|_OUT_
;       ----------------
;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
TAB     EQU     9
;
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/18/80'
       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
;
       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
       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     CONST   ;TEST FOR ABORT
       ORA     A
       JNZ     CHREXIT ;ABORT REQUESTED
;
;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:
;<<INIT DMA ADDR, FCB>>
CPM STDMA,80H
XRA A ! STA FCBEXT ! STA FCBRNO
;<<IF FIRST TIME>>
LDA MFFLG1 ! ORA A ! JNZ MFN01
;  <<TURN OFF 1ST TIME SW>>
MVI A,1 ! STA MFFLG1
;  <<SAVE THE REQUESTED NAME>>
MOVE FCB,MFREQ,12 ;SAVE ORIG REQ
LDA FCB ! STA MFCUR ;SAVE DISK IN CURR FCB
;  <<SRCHF REQ NAME>>
MOVE MFREQ,FCB,12
CPM SRCHF,FCB
;<<ELSE>>
JMP MFN02
MFN01:
;  <<SRCHF CURR NAME>>
MOVE MFCUR,FCB,12
CPM SRCHF,FCB
;  <<SRCHN REQ NAME>>
MOVE MFREQ,FCB,12
CPM SRCHN,FCB
;<<ENDIF>>
MFN02:
;<<RETURN CARRY IF NOT FOUND>>
INR A ! STC ! RZ
;<<MOVE NAME FOUND TO CURR>>
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
;<<MOVE NAME FOUND TO FCB>>
POP H ! MOVE ,FCB+1,11
;<<SETUP FCB>>
XRA A ! STA FCBEXT
;<<RETURN>>
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 CPM     RDCON
       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      100     ;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
PRINT   EQU     9
RDCONBF EQU     10
CONST   EQU     11
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