	ALWAYS	30JAN4	SEARCH	<SEARCH VIRTUAL MEMORY>
	.MCALL	DIR$,CALLR
;************************************************************************
;*									*
;*	MODULE: SEARCH							*
;*									*
;*	FUNCTION: SEARCH AN AREA OF VIRTUAL MEMORY FOR A VALUE		*
;*									*
;*	INPUT PARAMETERS:						*
;*									*
;*	R0 POINTS TO THE COMMAND LINE IN PROCESS			*
;*									*
;*	OUTPUT PARAMETERS:						*
;*									*
;*	R0 POINTS JUST BEYOND COMMAND LINE				*
;*									*
;*	DESTROYS: R1,R2,R3,R4						*
;*									*
;*	AUTHOR: KEVIN ANGLEY						*
;*									*
;*	DATE: 27-JUL-82							*
;*									*
;*	REVISED BY: CHRIS DORAN, SIRA LTD.				*
;*									*
;*	DATE: JAN-84							*
;*									*
;*	MODIFICATIONS:							*
;*		Support STEP option.					*
;*		Allow specification of single ASCII character ('char)	*
;*		  or character pair ("charchar) as search key.		*
;*		Put FOR key, only used here, into this module, for	*
;*		  overlaid code efficiency.				*
;*		Show match count at end.				*
;*		Add FOR NOT xx/xxxx option, finding non-matches.	*
;*		Return cs on error, cc if all OK.			*
;*									*
;************************************************************************

SEARCH::
	CALL	FROMTH		; GET FROM ADDR IN R1, THRU ADDR IN R2
				;  AND COUNT IN R3
	BCS	255$		;  CS: NOT SUCCESSFUL, TAKE ERROR EXIT
	MOV	R1,R2		; SAVE FROM ADDRESS IN R2 - DON'T NEED THRU
	GETKEY	FOR		; COLLECT "FOR" KEYWORD
	BEQ	10$		;  EQ: YES - GO PROCESS
	OUTPUT	MSK		; OUTPUT "MISSING KEYWORD"
	BR	255$		;  AND TAKE ERROR EXIT
10$:
	CLRB	NOMATCH		; Default to match
	GETKEY	NOT		; but if NOT option set
	BNE	11$
	COMB	NOMATCH		; want to find mis-matches instead
11$:	CLR	MATCHES		; Clear match counter
	CMPB	@%0,#'"		; Double-byte?
	BNE	15$		; No, must be hex number
	INC	%0		; Yes, skip "
	MOVB	(%0)+,%1	; Get the low (first) byte
	BEQ	12$		; (Must be one)
	MOVB	(%0)+,%4	; Get hi (second)
	BNE	20$		; Do a full word search
12$:	OUTPUT	HCE		; "(Hex) conversion error"
	BR	255$		; if no second byte	
15$:
	CALL	GETHAS		; Get two hex digits or 'char
				; VALUE NOW IN LOW BYTE OF R1
	BCS	255$		;  CS: TAKE ERROR EXIT
	MOVB	R1,R4		; SAVE HIGH BYTE OR ONLY BYTE
	TSTB	(R0)		; CHECK FOR EOLN
	BEQ	30$		;  EQ: MUST BE A BYTE SEARCH
	CALL	GETHX2		; GET LOW BYTE INTO R1
	BCS	255$		;  CS: HEX CONVERSION ERROR

20$:				; WORD SEARCH
	CMPB	R1,MEMORY(R2)	; MUST MATCH LOW BYTE
	BNE	23$		;  NE: NO MATCH
	CMP	R2,#MEMHIGH	; CAN'T MATCH IF ALREADY AT TOP BYTE
	BEQ	25$		;  EQ: YES - DON'T ATTEMPT MATCH
	CMPB	R4,MEMORY+1(R2)	; COMPARE HIGH BYTE
	BNE	23$		;  NE: NO MATCH
	CALL	SERMCH		; Display matching address if NOT NOMATCH
	BR	25$		; Get next address
23$:	CALL	SERNOM		; Display non-matching address if NOMATCH
25$:
	ADD	STEP,R2		; NEXT VIRTUAL ADDRESS
	SOB	R3,20$		; KEEP LOOKING IN ANY CASE
	BR	250$		; UNTIL DONE, THEN EXIT

30$:
	CMPB	R4,MEMORY(R2)	; BYTE MATCH?
	BNE	33$		;  NE: NO
	CALL	SERMCH		; Display address if NOT NOMATCH
	BR	35$
33$:	CALL	SERNOM		; Display address if NOMATCH
35$:
	ADD	STEP,R2		; NEXT VIRTUAL ADDRESS
	SOB	R3,30$		; KEEP LOOKING IN ANY CASE

250$:				; NORMAL EXIT
	PUSH	%0		; Save command line pointer
	MOV	#MFO+1,%0	; Address message: "nnnn mis-matches found"
	MOV	MATCHES,%1	; Fetch count
	CALL	PUTHX4		; Put in in hex
	POP	%0		; Restore command line pointer
.IF DF R$$T11
	MOV	#177777,IS	; Assume match, so remove "mis-"
	MOV	#177777,.M
.IFF
	CLR	IS		; Assume match, so remove "mis-"
	CLR	.M
.IFTF
	TSTB	NOMATCH		; But if looking for no-matches,
	BEQ	251$
	MOV	#"is,IS		; Put it back
	MOV	#"-m,.M		; (Actually, "is-m", to use word ops)
251$:	MOV	#"es,ES		; Assume not 1, so say "match-es"
	DEC	MATCHES		; But if count was 1
	BNE	252$
.IFT
	MOV	#177777,ES	; make it "match" instead
.IFF
	CLR	ES		; make it "match" instead
.ENDC
252$:	OUTPUT	MFO		; Show matches found
	CLC			; Success

255$:				; ERROR EXIT
	CALLR	EXTRA		; PURGE COMMAND LINE OF SUPERFLUOUS JUNK
				;  AND RETURN FROM THERE
	.PAGE
	.SBTTL	SERMCH/SERNOM - DISPLAY MATCHING/NON-MATCHING ADDRESS

; Match found. Display address if NOMATCH flag clear.
SERMCH:	TSTB	NOMATCH		; Displaying matches?
	BEQ	SERDIS		; Yes, do so
	RETURN			; No, just return

; Non-match found. Display address if NOMATCH flag set.
SERNOM:	TSTB	NOMATCH		; Displaying non-matches?
	BEQ	SERRET		; No, just return
SERDIS:
	CALL	$SAVAL		; SAVE R0-R5 (CO-ROUTINE)
	MOV	#ADR+1,R0	; FILL IN ADDRESS BUFFER
	CALL	UNOFFSET	; UNOFFSET R2 INTO R3/R4
	MOV	R3,R1		; PREPARE FOR OUTPUT
	MOV	R4,R2
	CALL	PUTHXJ		; PUT INTO BUFFER
	OUTPUT	ADR		; OUTPUT THE ADDRESS
	INC	MATCHES		; Count match
SERRET:	RETURN			; RESTORE REGS AND EXIT

	.PSECT	PURE	RO,D

	KEY	FOR
	KEY	NOT
	.EVEN

	.PSECT	DATA	RW,D

NOMATCH:	.BLKB		; Match/nomatch flag
; NOTE: "is-m" and "es" of message must be on word boundaries.
	.ODD
	DEFM	MFO	<0000 mis-matches found>
IS=MFO+7.
.M=MFO+9.
ES=MFO+15.
	.EVEN
MATCHES:	.BLKW		; Match counter

	.END
