
	include	exec/memory.i
	include dos/dos.i
	include	libraries/execxref.i
	include	libraries/dosxref.i

	include	include/macros.i


	mc68000				; snma option.

true	equ	1
false	equ	0
case	equ	true		; case sensitive search??

	structure	datas,0
		aptr	dosbase

		long	filehandle
		aptr	filebuffer
		long	filelength

		aptr	messagebuffer
		long	counter

		long	temp

		label	datas_sizeof



buffersize	equ	16*1024		; use 16 kb buffer
messagebuflen	equ	1024

	section	code,code

	clr.b	-1(a0,d0)
	move.l	a0,a5

	move.l	#datas_sizeof,d0
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	move.l	4,a6
	call	AllocMem
	move.l	d0,a4
	tst.l	d0
	beq	cleanup

	move.l	#messagebuflen,d0
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	call	AllocMem
	move.l	d0,messagebuffer(a4)
	beq	cleanup

	openlib	dos,0,cleanup

	bsr	parse			; parse commandline 
	tst.l	d0
	beq	g_c0
	lea	error3(pc),a0
	bsr	printclimsg
	lea	error1(pc),a0
	bsr	printclimsg
	bra	cleanup


g_c0	move.l	a5,d1
	move.l	a3,a5
	move.l	#MODE_OLDFILE,d2
	move.l	dosbase(a4),a6
	call	Open
	move.l	d0,filehandle(a4)
	bne	g_c1
	lea	error3(pc),a0
	bsr	printclimsg
	lea	error2(pc),a0
	bsr	printclimsg
	bra	cleanup

g_c1	move.l	d0,d1
	moveq	#0,d2
	move.l	#OFFSET_END,d3
	call	Seek
	move.l	filehandle(a4),d1
	moveq	#0,d2
	move.l	#OFFSET_BEGINNING,d3
	call	Seek
	move.l	d0,filelength(a4)


	move.l	#buffersize,d0
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	move.l	4,a6
	call	AllocMem
	move.l	d0,filebuffer(a4)
	beq	cleanup

	moveq	#0,d6
grep_loop
	move.l	filehandle(a4),d1
	move.l	filebuffer(a4),d2
	move.l	#buffersize,d3
	move.l	dosbase(a4),a6
	call	Read
	add.l	d0,d6
	tst.l	d0
	beq	statistics
	move.l	d0,d5
	move.l	d0,d7


	move.l	filebuffer(a4),a0	; in this loop we check if the requested
grep_loop3				; string was there.
	move.l	a5,a3
grep_loop2
	tst.b	(a3)
	bne	g_testchar
	bsr	printline
g_testchar
	subq.l	#1,d5
	bmi	g_readmore

	move.l	d5,d0
	divu.w	#350,d0
	and.l	#$ffff,d0
	bne	g_noct
	moveq	#0,d0			; check for ctrl+c once in every 350
	moveq	#0,d1			; times
	bset	#12,d1			; SIGBIT_CTRLC
	move.l	4,a6
	push	a0
	call	SetSignal
	pull	a0
	btst	#12,d0			; SIGBIT_CTRLC
	bne	statistics

g_noct	ifne	case
	move.b	(a3)+,d0
	beq	grep_loop3
	move.b	(a0)+,d1
	bsr	lowerthem
	cmp.b	d0,d1
	else
	cmpm.b	(a3)+,(a0)+
	endc
	beq	grep_loop2
	bra	grep_loop3

g_readmore
	move.l	filelength(A4),d4
	cmp.l	d4,d6
	bmi	grep_loop


;	***********************************************************************

statistics
	lea	message(pc),a0
	move.l	a5,-(sp)
	move.l	counter(a4),-(sp)
	move.l	sp,a1
	lea	pcp(pc),a2
	move.l	messagebuffer(A4),a3
	move.l	4,a6
	call	RawDoFmt
	add.l	#8,sp
	move.l	messagebuffer(a4),a0
	bsr	printclimsg


cleanup	move.l	filehandle(A4),d1
	beq	_100
	move.l	dosbase(a4),a6
	call	Close

_100	move.l	4,a6
	move.l	filebuffer(a4),d0
	beq	_101
	move.l	d0,a1
	move.l	#buffersize,d0
	call	FreeMem

_101	move.l	messagebuffer(a4),d0
	beq	_102
	move.l	d0,a1
	move.l	#messagebuflen,d0
	call	FreeMem

_102	closlib	dos

	move.l	a4,d0
	beq	_999
	move.l	d0,a1
	move.l	#datas_sizeof,d0
	call	FreeMem

_999	moveq	#0,d0
	rts

pcp	move.b	d0,(a3)+
	rts

;	***********************************************************************

parse	move.l	a5,a3
	cmp.b	#34,(a3)
	bne	parse_findspace

	adda.l	#1,a5
	adda.l	#1,a3
p_lp1	tst.b	(a3)
	beq	p_error
	cmp.b	#34,(a3)+
	bne	p_lp1

	move.b	#0,-1(a3)
p_lp2	tst.b	(a3)
	beq	p_error
	cmp.b	#" ",(a3)+
	beq	p_lp2
	suba.l	#1,a3

	moveq	#0,d0
	rts

parse_findspace
	tst.b	(a3)
	beq	p_error
	cmp.b	#" ",(a3)+
	bne	parse_findspace

	move.b	#0,-1(a3)
p_lp3	tst.b	(a3)
	beq	p_error
	cmp.b	#" ",(a3)+
	beq	p_lp3
	suba.l	#1,a3

	moveq	#0,d0
	rts

p_error	moveq	#-1,d0
	rts

;	***********************************************************************

	ifne	case
lowerthem
	and.w	#$ff,d0		; make letters lowercase.
	and.w	#$ff,d1		; This makes string searcher case sensitive.

	cmp.w	#"A",d0		; touch only capital letters
	bmi	lt_no1
	cmp.w	#"Z"+1,d0
	bpl	lt_no1
	bset	#5,d0		; lower it

lt_no1	cmp.w	#"A",d1
	bmi	lt_no2
	cmp.w	#"Z"+1,d1
	bpl	lt_no2
	bset	#5,d1

lt_no2	rts
	endc

;	***********************************************************************

printclimsg
	push	all
	move.l	a0,a5

	move.l	dosbase(A4),a6
	call	Output
	move.l	d0,d1

	move.l	a5,a0
	moveq	#0,d3
p_lp	addq.l	#1,d3
	tst.b	(a0)+
	bne	p_lp
	subq.l	#1,d3

	move.l	a5,d2
	call	Write
	pull	all
	rts

;	***********************************************************************

printline
	push	all

	move.l	#0,temp(a4)

	move.l	d6,d4
	sub.l	d5,d4
	sub.l	#200,d4
	bpl	pl_pos
	move.l	d7,d4
	sub.l	d5,d4
	bra	pl_pos1

pl_pos	move.l	#200,d4			; go back in the file to make sure
	move.l	d5,d7			; that the whole line is in the
	add.l	#200,d7			; memory at the same time.

pl_pos1	neg.l	d7

pl_cont	move.l	filehandle(a4),d1
	move.l	d7,d2
	move.l	#OFFSET_CURRENT,d3
	move.l	dosbase(a4),a6
	call	Seek

	add.l	#400,d7
	neg.l	d7
	bpl	pl_neq
	moveq	#0,d7

pl_neq	move.l	#400,d0			; the line should fit in 400 bytes.
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	move.l	4,a6
	call	AllocMem
	move.l	d0,d6
	beq	printline_exit

	move.l	filehandle(a4),d1
	move.l	d0,d2
	move.l	#400,d3			; read it and..
	move.l	dosbase(a4),a6
	call	Read

	move.l	d6,a0
	add.l	d4,a0
	move.l	a0,d5
	subq.l	#1,a0
pl_lp1	cmp.b	#32,(a0)	; 1st search backwards to find the start
	bmi	found		; of the line.
	suba.l	#1,a0
	subq.l	#1,d4
	beq	found
	bra	pl_lp1
found	adda.l	#1,a0
	move.l	a0,a1
	moveq	#0,d3
pl_lp2	addq.l	#1,d3			; calculate the length of the string.
	cmp.b	#32,(a1)+
	bpl	pl_lp2

pl_c0	move.l	a1,temp(A4)	; this is the value we need substract from
	sub.l	d5,temp(a4)	; the search loop counter.
	subq.l	#1,temp(A4)

	push	a0/d3
	call	Output
	pull	a0/d3			; and print it to cli window.
	move.l	d0,d1
	move.l	a0,d2
	call	Write

	add.l	#1,counter(a4)

	move.l	d6,a1
	move.l	#400,d0
	move.l	4,a6
	call	FreeMem

printline_exit
	move.l	filehandle(a4),d1	; return the file pointer to where
	move.l	d7,d2			; it was before.
	beq	printline_nomovement
	move.l	#OFFSET_CURRENT,d3
	move.l	dosbase(A4),a6
	call	Seek

printline_nomovement
	pull	all
	sub.l	temp(a4),d5		; continue search from the end of
	add.l	temp(A4),a0		; the printed line.
	move.l	a5,a3
	rts

;	***********************************************************************

dosname	dc.b	'dos.library',0
error1	dc.b	'** Parse error!!',10,0
error2	dc.b	'** Unable to open file!',10,0
error3	dc.b	'USAGE: Grep FileName SearchString',10,0
message	dc.b	10,'Found %ld occuriences of string:',10
	dc.b	' [1m%s0m',10,0
	even
