

;	----------------------------------------------------------
;	Reassembly of FIND.COM, which was originally extracted
;	from the CBBS(R) package available from Ward Christensen
;	and Randy Suess. However, considerable rearrangement has
;	taken place, most notably the following:
;	    <no file name> results in a screen of information
;	    the search pattern may be a regular expression
;	    label+line number as an alternative to line number.
;	    instance count reported, both per file and globally
;	To achieve compatibility with MicroShell the vertical bar
;	was replaced by exclamation point; all syntactic elements
;	are defined by equ's and may be redefined. LABEL!PATTERN
;	is checked for balanced parentheses and non-null arguments
;	to forestall the most common failure modes. Had MicroShell
;	not been available, an option to direct the output to some
;	disk file would probably have been included. This is the
;	Intel 8086 version, transformed with TRANS86 and revised.
;
;		    FYNDE.ASN   Copyright (C) 1982
;		    Universidad Autonoma de Puebla
;
;	[Harold V. McIntosh, 20 December 1982]
;	----------------------------------------------------------

HT	equ	09H		;horizontal tab
LF	equ	0AH		;line feed
CR	equ	0DH		;carriage return

;	Delimiters for the command line

LSQ	equ	'['		;begin alternative list
RSQ	equ	']'		;end alternative list
LBR	equ	'{'		;begin iterated expression
RBR	equ	'}'		;end iterated expression
ORR	equ	'!'		;separate alternatives

;	Representatives of characters or classes.

TAB	equ	'_'		;substitute for tab
QUE	equ	'?'		;represent any byte
ALF	equ	'@'		;represent any alphanumeric

bdos	equ	224		;CP/M interrupt to BDOS

ksiz	equ	40		;records in IN buffer
isiz	equ	ksiz*128	;bytes in IN buffer

	org	100H

X0100:	ld	al,005DH	;file name
	cmp	al,#' '
	jnz	X0143
	ld	bx,#M1
	call	mssg
exit:	ld	dl,#00
	ld	cl,#00
	int	bdos

X0143:	ld	bx,#M2
	call	mssg
	ld	ah,#12
	ld	dx,#005CH
	ld	bx,#file
	call	miuc
	stob	#00,enth
	ld	bx,#0080H	;CP/M's sector buffer
	ld	dl,[bx]
	mov	cl,dl
	ld	dh,#00
	xchg	bx,dx
	inc	dx
	add	bx,dx
	stob	#00,[bx]
	xchg	bx,dx
X0152:	inc	bx
	dec	cl
	cmpb	[bx],#00
	jnz	:G2
	jmp	X029C
:G2	cmpb	[bx],#' '
	jnz	X0152
	inc	bx
	call	bala		;check balance of [], {}.
	call	nula		;check for null alternatives
	ld	dx,#patt	;command line pattern
	call	muve
	ld	ah,#4
	ld	dx,#lzer
	ld	bx,#dtot
	call	miuc
	sto	#0000,lapo
	ld	bx,#patt	;command line pattern
	sto	bx,papo
	call	next
	or	al,al
	jz	scan
	sto	bx,papo
	sto	#patt,lapo

;	Scan the directory for file names.

scan:	ld	cl,#26		;(1A) set DMA address
	ld	dx,#0080H	;CPM's sector buffer
	int	bdos		; - B D O S -
	ld	cl,#17		;(11) search once
	ld	dx,#file
	int	bdos		; - B D O S -
	incb	enth
	ld	cl,enth
fnth:	inc	al
	jz	done		;we're all done
	dec	cl
	jz	this
	push	cx
	ld	cl,#18		;(12) search again
	ld	dx,#file
	int	bdos		; - B D O S -
	pop	cx
	jmp	fnth

;	We're all done so output summary, then exit.

done:	ld	bx,#dtot
	call	mssg
	jmp	exit

;	A prospective file has been located

this:	dec	al
	and	al,#03
	add	al,al
	add	al,al
	add	al,al
	add	al,al
	add	al,al
	add	al,#81H
	mov	dl,al
	ld	dh,#00
	ld	ah,#12
	ld	bx,#005DH
	call	miuc
	ld	cl,#15		;(0F) open file
	ld	dx,#005CH	;CP/M's FCB
	int	bdos		; - B D O S -
	inc	al
	jnz	:G6
	jmp	exit		;quit [without message]
:G6	sto	#00,007CH	;block pointer

	ld	ah,#4
	ld	dx,#lzer
	ld	bx,#ftot
	call	miuc
	ld	ah,#4
	ld	dx,#lzer
	ld	bx,#lnum	;'line number'
	call	miuc
	ld	ah,#8
	ld	dx,#005DH	;file name
	ld	bx,#fnam	;'file name'
	call	miuc
	ld	ah,#3
	ld	dx,#0065H	;extension
	ld	bx,#fext	;'file extension'
	call	miuc
	ld	bx,#fhed
	call	mssg		;message to console
	ld	ax,#0620H	;six spaces
	ld	bx,#llbl
	call	fiuc

X01C2:	sto	#0000,ictr
X01C8:	ld	bx,#lnum+3	;increment l.c.
	call	inco
	ld	bx,#lbuf	;line buffer
	ld	ch,#0FFH	;limit on line length
X01E0:	inc	ch
	js	X01FD
	push	cx
	push	bx
	call	inch		;char from big bffr to line bffr
	pop	bx
	pop	cx
	sto	al,[bx]
	inc	bx
	cmp	al,#1AH
	jnz	X01E8
	ld	bx,#ftot
	call	mssg
	jmp	scan
X01E8:	cmp	al,#LF
	jnz	X01E0
	jmp	X0202

X01FD:	stob	#CR,[bx]
	inc	bx
	stob	#LF,[bx]
	inc	bx

;	Check console for termination request, which may
;	be generated by pressing any key. Clear out the
;	requesting character before leaving.

X0202:	stob	#00,[bx]	;guarantee right hand fence
	ld	cl,#11		;(0B) console status
	int	bdos		; - B D O S -
	or	al,al
	jz	culi		;scan the current line
	ld	cl,#1		;(01) read console
	int	bdos		; - B D O S -
	ld	bx,#M4		;"search terminated"
	call	mssg
	jmp	exit

;	Scan the current line.
;	First, see if it is labelled.

culi:	ld	dx,lapo
	or	dx,dx
	jz	X0217		;no label requested
	ld	bx,#lbuf
	call	chek
	jnz	X0217		;label not found
	push	bx
	ld	ax,#0620H
	ld	bx,#llbl
	call	fiuc
	pop	bx
	ld	dx,#llbl+5
	ld	ah,#6
didl:	dec	bx
	ld	al,[bx]
	cmp	al,#HT		;ignore tabs in text
	jz	didl
	cmp	al,#' '		;quit at head of line
	jc	dido
	xchg	bx,dx
	sto	al,[bx]
	xchg	bx,dx
	dec	dx
	dec	ah
	jnz	didl
dido:	ld	ah,#4
	ld	dx,#lzer
	ld	bx,#lnum
	call	miuc

;	Now look for the pattern

X0217:	ld	bx,#lbuf	;line buffer
X021A:	ld	dx,papo		;pattern pointer
	push	bx
	call	chek
	pop	bx
	jz	X0263
	inc	bx
	cmpb	[bx],#CR
	jnz	X021A
	jmp	X01C8		;increment l.c. at X026A

;	This line contains the pattern.

X0263:	ld	bx,#llbl	;line label
	call	mssg		;mssg to console
	ld	bx,#lbuf	;line buffer
	call	mssg		;mssg to console
	ld	bx,#ftot+3
	call	inco
	ld	bx,#dtot+3
	call	inco
	jmp	X01C8		;increment l.c. at X026A

;	Increment an ASCII counter

inco:	orb	[bx],#30H
	incb	[bx]
	cmpb	[bx],#':'
	jnz	incr
	stob	#'0',[bx]
	dec	bx
	jmp	inco
incr:	ret

;	Memory to console

mssg:	ld	dl,[bx]
	inc	bx
	push	bx
	ld	cl,#2		;(02) write console
	int	bdos		; - B D O S -
	pop	bx
	cmpb	[bx],#00
	jnz	mssg
	ret

X029C:	ld	bx,#M3		;"bad pattern"
	call	mssg
	jmp	exit

;	Move a character from the big buffer to the line
;	buffer, replenishing the big buffer when it is
;	exhausted.

inch:	cmp	ictr,#0000
	jnz	incc
	call	indi
incc:	dec	ictr
	ld	bx,iptr
	ld	al,[bx]
	cmp	al,#1AH
	jz	inrr
	inc	iptr
inrr:	ret

indi:	ld	al,#ksiz
	sto	#isiz,ictr
	sto	#ibuf,iptr
	ld	dx,iptr
indd:	push	dx
	push	ax
	ld	cl,#26		;(1A) set DMA address
	int	bdos		; -B D O S -
	ld	dx,#005CH	;CP/M's FCB
	ld	cl,#20		;(14) read one record
	int	bdos		; - B D O S -
	or	al,al
	jnz	inee
	pop	ax
	pop	dx
	dec	al
	jz	inss
	add	dx,#0080H
	jmp	indd

inee:	pop	ax
	pop	dx
	sto	#1AH,[bx]
inss:	ret

;	Advance to next alternative

nexr:	ret
nexx:	ld	bx,[bx]
next:	ld	al,[bx]
	or	al,al
	jz	nexr
	inc	bx
	call	enda
	jz	nexr
	call	begb
	jz	nexx
	jmp	next

fiuc:	sto	al,[bx]
	inc	bx
	dec	ah
	jnz	fiuc
	ret

miuc:	xchg	bx,dx
	ld	al,[bx]
	xchg	bx,dx
	sto	al,[bx]
	inc	dx
	inc	bx
	dec	ah
	jnz	miuc
	ret

;	Move and semi-compile the command line.

muve:	ld	al,[bx]
	cmp	al,#TAB
	jnz	munt
	ld	al,#HT
munt:	xchg	bx,dx
	sto	al,[bx]
	xchg	bx,dx
	inc	bx
	inc	dx
	cmp	al,#RBR
	jz	murb
	cmp	al,#RSQ
	jz	murb
	cmp	al,#LBR
	jz	mulb
	cmp	al,#LSQ
	jz	mulb
must:	dec	cl
	jnz	muve
	ret

murb:	mov	ax,bx
	pop	bx
	sto	dx,[bx]
	mov	bx,ax
	jmp	must

mulb:	push	dx
	inc	dx
	inc	dx
	jmp	must

;	Check balance of []'s and {}'s.

bala:	push	bx
	push	cx
	ld	cx,#0101H
balb:	ld	al,[bx]
	inc	bx
	cmp	al,#LSQ
	jnz	balc
	inc	ch
	jmp	balb
balc:	cmp	al,#RSQ
	jnz	bald
	dec	ch
	jz	balx
	jmp	balb
bald:	cmp	al,#LBR
	jnz	bale
	inc	cl
	jmp	balb
bale:	cmp	al,#RBR
	jnz	balf
	dec	cl
	jz	balx
	jmp	balb
balf:	or	al,al
	jnz	balb
	mov	al,cl
	cmp	al,#01
	jnz	balx
	mov	al,ch
	cmp	al,#01
	pop	cx
	pop	bx
	jz	balr
balx:	ld	bx,#M3		;"bad pattern"
	call	mssg
	jmp	exit		;PDL unbalanced but doesn't matter
balr:	ret

;	Check for termination of alternative.

enda:	cmp	al,#ORR
	jz	endr
	cmp	al,#RSQ
	jz	endr
	cmp	al,#RBR
	jz	endr
	or	al,al
endr:	ret

;	Check for beginning of alternative.

bega:	cmp	al,#ORR
	jz	begr
begb:	cmp	al,#LSQ
	jz	begr
	cmp	al,#LBR
begr:	ret

;	Check for null alternative.

nula:	push	bx
	call	nulb
	pop	bx
nulr:	ret
nulb:	ld	al,[bx]
	inc	bx
	or	al,al
	jz	nulr
	call	bega
	jnz	nulb
	ld	al,[bx]
	call	enda
	jnz	nulb
	jmp	balx

;	Check for given expression.

chek:	ld	ah,[bx]
	xchg	bx,dx
	ld	al,[bx]
	xchg	bx,dx
	inc	dx
	call	enda
	jz	chre
	cmp	ah,#CR
	jz	chno
	cmp	al,#LBR
	jnz	:G41
	jmp	chlb
:G41	cmp	al,#LSQ
	jnz	:G42
	jmp	chsq
:G42	inc	bx
	cmp	al,#QUE
	jz	chek
	cmp	al,#ALF
	jz	chal
	cmp	al,ah
	jz	chek
	cmp	ah,#'a'
	jc	chno
	cmp	ah,#'{'
	jnc	chno
	and	ah,#05FH
	cmp	al,ah
	jz	chek
chno:	or	al,#0FFH
chre:	ret

;	Check alphanumeric.

chal:	cmp	ah,#'0'
	jc	chno
	cmp	ah,#':'
	jc	chek
	cmp	ah,#'A'
	jc	chno
	cmp	ah,#'['
	jc	chek
	cmp	ah,#'a'
	jc	chno
	cmp	ah,#'{'
	jc	chek
	jmp	chno

;	Check list of alternatives.

chsq:	push	sqxx
	push	sqaa
	push	sqzz
	sto	bx,sqxx
	xchg	bx,dx
	ld	dx,[bx]
	inc	bx
	inc	bx
	sto	bx,sqaa
	xchg	bx,dx
	sto	bx,sqzz
chaa:	ld	bx,sqxx
	call	chek
	jz	chff
chbb:	ld	bx,sqaa		;fail so find next alternative
chcc:	call	next
	cmp	al,#RSQ
	jz	chdd		;no more alternatives, so fail
	cmp	al,#ORR
	jnz	chcc
	sto	bx,sqaa
	xchg	bx,dx
	jmp	chaa		;try next alternative
chdd:	ld	bx,sqxx
	or	al,#0FFH
chee:	pop	sqzz
	pop	sqaa
	pop	sqxx
	ret
chff:	ld	dx,sqzz		;good alternative, try rest
	call	chek
	jz	chee
	jmp	chbb

;	Check iterative pattern.

chlb:	push	text
	push	texx
	push	rest
	push	rept
	push	repp
	sto	bx,text
	sto	bx,texx
	xchg	bx,dx
	ld	dx,[bx]
	inc	bx
	inc	bx
	sto	bx,rept
	sto	bx,repp
	sto	dx,rest
chlc:	ld	dx,rest
	ld	bx,text
	call	chek		;check rest
	jz	chzz
chii:	ld	dx,rept		;rest failed
	ld	bx,text		;keep same text
	call	chek		;try out the repeater
	jnz	choo
	sto	bx,text		;repeater worked, record progress
	ld	bx,repp		;start alternatives over again
	sto	bx,rept
	jmp	chlc
choo:	ld	bx,rept		;repeater failed, try next
chxx:	call	next
	cmp	al,#RBR
	jz	chyy		;this was the last, quit
	cmp	al,#ORR
	jnz	chxx
	sto	bx,rept
	jmp	chii
chyy:	ld	bx,texx
	or	al,#00		;emphasize the RBR
chzz:	pop	repp
	pop	rept
	pop	rest
	pop	texx
	pop	text
	ret

M1:	db	'The command line',CR,LF
	db	'     FYNDE D:FILE.EXT EXPRESSION',CR,LF
	db	'will search through all instances of FILE.EXT',CR,LF
	db	'(which may be an ambiguous reference) on disk D',CR,LF
	db	'to find lines containing EXPRESSION. Such lines',CR,LF
	db	'will be presented on the console preceded by a',CR,LF
	db	'line number, and classified by file. EXPRESSION',CR,LF
	db	'may have the form LABEL!PATTERN or simply the',CR,LF
	db	'form PATTERN. Both may contain:',CR,LF
	db	'     [p1!p2!...!pn]  alternative strings',CR,LF
	db	'     {p1!p2!...!pn}  repeated alternatives',CR,LF
	db	'     ? any single character',CR,LF
	db	'     @ for any alphanumeric: a-z, A-Z, 0-9',CR,LF
	db	'     _ in place of horizontal tab',CR,LF
	db	'When a label is present, lines will be numbered',CR,LF
	db	'relative to the label.  Example: X{?}:![call!ret]',CR,LF
	db	'will list calls and returns relative to labels',CR,LF
	db	'like X0100: or X33:. LABEL begins in column 1,',CR,LF
	db	'PATTERN can begin in any column.',CR,LF,00

M2:	db	'FYNDE.CMD 12/20/82 ICUAP',CR,LF,00

M3:	db	'-- Bad Pattern --',00

M4:	db	CR,LF,'-- Search Terminated --',00

enth:	ds	1
file:	db	'DFilenameEXT',00
	ds	19

sqxx:	ds	2
sqaa:	ds	2
sqzz:	ds	2
text:	ds	2
texx:	ds	2
rest:	ds	2
rept:	ds	2
repp:	ds	2

patt:	ds	256		;command line pattern
X0492:	ds	2		;end of stack
lapo:	ds	2		;label pointer
papo:	ds	2		;pattern pointer
fhed:	db	'~~~~~~> File '
fnam:	db	'xxxxxxxx.'	;filename
fext:	db	'xxx',CR,LF,00	;file extension
llbl:	db	'      +'
lnum:	db	'         ',00
lzer:	db	'   0'
ftot:	db	'      lines found',CR,LF,00
dtot:	db	'      instances throughout the disk',CR,LF,00
	db	00		;fence for line buffer
lbuf:	ds	85H		;line buffer
ictr:	ds	2
iptr:	ds	2
ibuf:	ds	isiz
fini:	ds	0

	END
