*
* SEARCH: Global file search for text or binary strings
*
* Copyright 1983-2005 Dave Dunfield
* All rights reserved.
*
* DIRECTORY STRUCTURE
	ORG	0
DPREFIX	RMB	8
DNAME	RMB	8
DTYPE	RMB	3
DDADR	RMB	2
DRADR	RMB	2
DATTR	RMB	1
* FILE ATTRIBUTES
RPERM	EQU	%10000000
WPERM	EQU	%01000000
EPERM	EQU	%00100000
DPERM	EQU	%00010000
*
DIRLOC	EQU	0		DIRECTORY STARTS HERE
*
	ORG	OSUTIL		UTILITY SPACE
SEARCH	CMPA	#'?'		QUERY REQUEST?	
	BNE	QUAL		NO, LOOK FOR QUALIFIERS
	SSR	25
	FCC	'Use: SEARCH[/BINARY/CASE/HEX/TOTAL]'
	FCCZ	' <filespec> <search string>'
	RTS
* PERFORM SEARCH
* PARSE FOR COMMAND QUALIFIERS
QUAL	LDA	,Y		GET CHAR FROM COMMAND LINE
	CMPA	#'/'		IS IT A QUALIFIER?
	BNE	MAIN		NO, DO PGM
	LEAX	QTABLE,PCR	POINT TO QUALIFIER TABLE
	SSR	18		LOOK IT UP
	CMPB	#QMAX		IS IT IN RANGE
	BHS	QERR		IF SO, IT'S INVALID
	LEAX	QFLAGS,PCR	POINT TO QUALIFIER FLAGS
	CLR	B,X		SET THE FLAG
	BRA	QUAL		LOOK FOR ANOTHER QUALIFIER
QERR	SSR	24		DISPLAY MESSAGE
	FCCZ	/Invalid qualifier: '/
	LDA	,Y+		GET CHARACTER
DSQU1	SSR	33		DISPLAY
	LDA	,Y+		GET NEXT CHAR
	BEQ	GOABO		NULL IS DELIMITER
	CMPA	#'/'		START OF ANOTHER QUALIFIER?
	BEQ	GOABO		IF SO, QUIT
	CMPA	#' '		SPACE?
	BEQ	GOABO		IF SO, QUIT
	CMPA	#$0D		END OF LINE?
	BNE	DSQU1		NO, KEEP DUMPING
GOABO	SSR	25		DISPLAY MESSAGE
	FCB	$27,0		CHARACTERS TO DISPLAY
	LDA	#1		INVALID OPERAND RETURN CODE
	LBRA	ABORT		GIVE UP
* MAIN PROGRAM
MAIN	SSR	9		GET PATTERN
	LBNE	ABORT		BAD, GIVE UP
	LDA	-1,X		GET DRIVE
	SSR	76		Select this drive
	LDU	#BUFFER		POINT TO BUFFER
	CLR	BUFSIZ		BUFFER SIZE INDICATOR
	TST	HEX		IS STRING HEX
	BNE	STRIN		NO, INPUT A STRING
* INPUT HEX BYTES TO SEARCH FOR
HEXIN	SSR	7		GET HEX NUMBER
	LBNE	ABORT		INVALID, QUIT
	TFR	X,D		COPY
	STB	,U+		SAVE IT
	INC	BUFSIZ		ADVANCE SIZE
	SSR	4		MORE OPERANDS?
	BNE	HEXIN		GET NEXT OPERAND
	BRA	GOTOP		WE HAVE OEPRAND
* INPUT A STRING VALUE
STRIN	SSR	4		GET VALUE
	BEQ	BADSTR		ITS BAD
	LEAY	1,Y		SKIP IT
	STA	TEMP		SAVE
	CMPA	,Y		NULL STRING?
	BEQ	BADSTR		ITS BAD
STR1	LDA	,Y+		GET CHAR FROM STRING
	BEQ	BADSTR		ITS BAD
	CMPA	TEMP		ARE WE AT END?
	BEQ	GOTOP		WE HAVE IT
	INC	BUFSIZ		ADVANCE
	STA	,U+		SAVE
	CMPA	#$0D		CR?
	BNE	STR1		NO, ITS OK
* STRING OPERAND IS INVALID
BADSTR	SSR	43		INVALID OPERAND MESSAGE
	LBRA	ABORT		GO HOME
* WE HAVE SEARCH OPERAND
GOTOP	LDD	#DIRLOC		DIRECTORY STARTS HERE
SCAND	STD	SECTOR		SAVE DIRECTORY SECTOR
	LDX	#DIRBUF		POINT TO FREE SPACE
	SSR	92		READ DISK
	LBNE	ABORT		DISK ERROR
SCAND1	SSR	19		DOES THIS ONE MATCH?
	BEQ	SCANF		IF SO, SCAN THE FILE
NXTDIR	LEAX	32,X		SKIP TO NEXT
	CMPX	#DIRBUF+512	BEYOND END?
	BLO	SCAND1		NO, WE ARE OK
	LDD	SECTOR		GET SECTOR NUMBER
	SSR	77		GET NEXT SECTOR
	BNE	SCAND		CONTINUE IF MORE
	LDD	FMATCH		DID ANY FILES MATCH?
	BEQ	NOMAT		NO, ERROR
	CMPD	#1		SEARCHED ONLY ONE
	BEQ	SEREND		IF SO, NO GRAND TOTAL
	SSR	24		DISPLAY MSG
	FCCZ	'Searched '
	SSR	26		DISPLAY
	SSR	24		DISPLAY MSG
	FCCZ	 ' files, for a total of '
	LDD	GMATCH		GET GRAND TOTAL MATCHES
	SSR	26		DISPLAY
	SSR	25		DISPLLY MESSAGE
	FCCZ	' matches.'	
SEREND	CLRA			ZERO RETURN CODE
	BRA	ABORT		QUIT
NOMAT	SSR	44		FILE NOT FOUND
ABORT	SSR	0		GO HOME
* MATCHING FILE WAS FOUND, SEARCH IT
SCANF	PSHS	X		SAVE POINTER INTO ENTRY
	LDD	FMATCH		FILE MATCH,
	ADDD	#1		INCREMENT
	STD	FMATCH		RESAVE
	SSR	24		DISPLAY MESSAGE
	FCCZ	'Scanning file: '
	SSR	31		DISPLAY
	LDA	DATTR,X		GET ATTRIBUTES
	BITA	#RPERM		CAN WE READ
	BNE	PROTOK
	SSR	25
	FCCZ	' - Protection violation'
	LBRA	NXTDIR		GET NEXT
PROTOK	SSR	22		NEW LINE
	CLRA
	CLRB
	STD	BYTCT		SAVE BYTE COUNT
	STD	NMATCH		SAVE NUMBER OF MATCHES
	INCB
	STD	LINCT		CURRENT LINE COUNTER
* READ SECTORS FROM FILE, AND SCAN THEM
	LDD	DDADR,X		GET DISK ADDRESS
SCSEC	STD	FSEC		SAVE
	LDX	#WRKBUF		POINT TO WORK BUFFER
	STX	WRKPTR		SAVE POINTER
	SSR	92		READ SECTOR
	BNE	ABORT		INVALID
* SCAN 1K SECTOR(X) FOR CONTENTS OF BUFFER
	LDY	#BUFF1		POINT TO BUFFER
	LDB	BUFSIZ		GET BUFFER SIZE
* FILL COMPARE BUFFER FROM FILE
SCAN1	BSR	RDFIL		READ FILE
	STA	,Y+		SAVE IN BUFFER
	DECB			REDUCE COUNT
	BNE	SCAN1		CONTINUE
* COMPARE COMPARE BUFFER WITH FILE CONTENTS
SCAN2	LDX	#BUFFER		POINT TO BUFFER
	LDY	#BUFF1		POINT TO OTHER BUFFER
	LDB	BUFSIZ		GET BUFFER SIZE
SCAN3	LDA	,X+		GET CHAR FROM BUFFER
	CMPA	,Y+		COMPARE WITH OTHER
	BNE	SCAN4		NO MATCH
	DECB			REDUCE COUNT
	BNE	SCAN3		KEEP LOOKING
* STRING WAS FOUND
	LDD	NMATCH		GET NUMBER OF MATCHES
	ADDD	#1		ADVANCE
	STD	NMATCH		RESAVE
	LDA	TOTAL		IS IT TOTAL ONLY?
	BEQ	SCAN4		YES, DON'T DISPLAY
	LDA	BINARY		BINARY ONLY?
	BEQ	BINDI		IF DSO, DISPLAY OFFSET ONLY
	SSR	24		DISPLAY MSG
	FCCZ	'Line: '
	LDD	LINCT		GET LINE COUNTER
	SSR	26		DISPLAY
	SSR	24		DISPLAY MSG
	FCCZ	', '
BINDI	SSR	24
	FCCZ	'Offset: '
	LDB	BUFSIZ		GET BUFFER SIZE
	CLRA			ZERO HIGH
	PSHS	A,B		SAVE
	LDD	BYTCT		GET BYTE COUNT
	SUBD	,S		CONVERT
	STD	,S		SAVE
	SSR	26		DISPLAY
	SSR	24		DISPLAY MESSAGE
	FCCZ	' ($'
	PULS	A,B		RESTORE
	SSR	27		DISPLAY
	SSR	25		DISPLAY MESSAGE
	FCCZ	')'
SCAN4	LDX	#BUFF1		POINT TO COMPARE BUFFER
	LDB	BUFSIZ		GET SIZE
SCAN5	LDA	1,X		GET CHAR
	STA	,X+		RESAVE
	DECB			REDUCE COUNT
	BNE	SCAN5		CONTINUE
	BSR	RDFIL		READ A CHAR
	STA	-1,X		SAVE
	BRA	SCAN2		CONTINUE
*
* RDFILE
*
RDFIL	PSHS	B,X		SAVE REG
	LDD	BYTCT		GET BYTE COUNT
	ADDD	#1		ADVANCE
	STD	BYTCT		RESAVE
	LDX	WRKPTR		GET POINTER
	CMPX	#WRKBUF+512	ADVANCE
	BLO	RDFOK		OK
	LDD	FSEC		GET FILE SECTOR
	SSR	77		NEW SECTOR?
	BEQ	FILEOF		END OF FILE
	LDX	#WRKBUF		SET IT UP
	STD	FSEC		RESAVE
	SSR	92		READ DISK
	LBNE	ABORT		BAD
RDFOK	LDA	,X+		GET CHAR
	BPL	RDFO1		NORMAL
	LDB	BINARY		ARE WE TREATING AS BINARY
	BNE	FILEOF		NO, END OF FILE
RDFO1	STX	WRKPTR		RESAVE POINTER
	CMPA	#$0D		NEW LINE?
	BNE	RDF1		NO
	LDX	LINCT		GET LINE COUNT
	LEAX	1,X		ADVANCE
	STX	LINCT		RESAVE
RDF1	LDB	CASE		IS LOWER CASE CONVERT ENABLED?
	BNE	RDF2		NO, SKIP IT
	CMPA	#$61		LOWER CASE?
	BLO	RDF2		NO, DON'T CONVERT
	CMPA	#$7A		LOWER CASE?
	BHI	RDF2		NO, DON'T CONVERT
	ANDA	#$5F		CONVERT TO UPPER CASE
RDF2	PULS	B,X,PC
FILEOF	LEAS	5,S		SKIP SAVED X AND PC
	SSR	24		DISPLAY MESSAGE
	FCCZ	'Total of '
	LDD	NMATCH		GET NUMBER OF MATCHES
	SSR	26		DISPLAY IN DECIMAL
	SSR	25		DISPLAY MESSAGE
	FCCZ	' matches were found.'
	LDD	GMATCH		GET GRAND MATCH TOTAL
	ADDD	NMATCH		ADD IN THIS MATCHES
	STD	GMATCH		SAVE
	PULS	X		RESTORE POINTER
	LBRA	NXTDIR
* STRINGS
QTABLE	FCB	$82
	FCC	'/HEX'		HEX INPUT
	FCB	$82
	FCC	'/BINARY'	BINARY INPUT FILE
	FCB	$82
	FCC	'/TOTAL'	TOTAL MATCHES ONLY
	FCB	$82
	FCC	'/CASE'		CASE CONVERSION
	FCB	$80
QMAX	EQU	4
*
QFLAGS	EQU	*
HEX	FCB	$FF		HEX INPUT STRING
BINARY	FCB	$FF		BINARY INPUT FILE
TOTAL	FCB	$FF		DISPLAY TOTALS ONLY
CASE	FCB	$FF		FORCE CASE CONVERSIONS
*
* LOCAL STORAGE
*
FMATCH	FDB	0
GMATCH	FDB	0
TEMP	RMB	2
SECTOR	RMB	2
FSEC	RMB	2
BUFSIZ	RMB	1
WRKPTR	RMB	2
NMATCH	RMB	2
LINCT	RMB	2
BYTCT	RMB	2
BUFFER	RMB	80
BUFF1	RMB	80
DIRBUF	RMB	512
WRKBUF	RMB	512
