;++
;
; Program to display the length of every page in a file.
;
; By John Wilson.
;
; 12/03/95	JMBW	Created.
;
;--
	.radix	8
;
tab=	11
lf=	12
ff=	14
cr=	15
;
bufl=	32768d			;length of file input buffer
lbufl=	80d			;max line to store
;
code	segment
	assume	cs:code
	org	100h
;
start:	cld			;DF=0
	mov	si,80h		;pt at cmd line
	lodsb			;get length
	mov	di,si		;copy ptr
	mov	dx,di		;twice
	cbw			;ah=0
	mov	cx,ax		;copy
	jcxz	sk2
lp1:	lodsb			;get a char
	cmp	al,' '		;blank or ctrl char?
	jbe	sk1
	stosb			;save if not
sk1:	loop	lp1		;loop
sk2:	; cx=0 no matter how we got here, so input buf is empty
	cmp	di,dx		;have we moved?
	je	newpag		;no, use STDIN
	mov	[di],cl		;mark end
	mov	ax,3D00h	;func=open /RONLY
	int	21h
	jc	sk3
	mov	ds:handle,ax	;save handle
	jmp	short newpag
sk3:	mov	dx,offset operr	;pt at msg
die:	mov	ah,09h		;func=print
	int	21h
	mov	ax,4C01h	;func=punt
	int	21h
;+
;
; File read loop.
;
; si	ptr into BUF
; cx	# bytes left in BUF
;
;-
newpag:	; start new page
	mov	ds:nline,0	;init ctr
	mov	ds:last,0	;no prev non-null line
newlin:	; start new line
	mov	di,offset lbuf	;pt at line buffer
	jcxz	nl3		;input buf empty, go read data
nl1:	lodsb			;get a char
	cmp	al,lf		;eol?
	je	nl7
	cmp	al,ff		;eop?
	je	nl8
	; save char in case this is eof
	cmp	al,cr		;don't save CRs
	je	nl2
	cmp	di,offset lbuf+lbufl ;off end of buf?
	je	nl2		;yes, don't save
	stosb			;save char
nl2:	loop	nl1		;spin through buf
nl3:	; refill buffer
	mov	dx,offset buf	;pt at buffer
	mov	cx,bufl		;length
	mov	bx,ds:handle	;handle
	mov	ah,3Fh		;func=read
	int	21h
	jc	nl4
	mov	cx,ax		;copy length
	jcxz	nl5		;eof
	mov	si,dx		;point at data
	jmp	short nl1	;continue
nl4:	mov	dx,offset rderr	;read error
	jmp	short die
nl5: 	; eof
	test	ds:nline,-1	;was there a partial page?
	jz	nl6
	call	print		;yes, print its info
nl6:	int	20h
nl7:	; end of line
	dec	cx		;count the LF
	inc	ds:nline	;count the line
	sub	di,offset lbuf	;find length of line
	jz	newlin		;0, loop
	mov	ds:last,di	;save
	jmp	short newlin
nl8:	; end of page
	dec	cx		;count the FF
	sub	di,offset lbuf	;find length of line
	jz	nl9		;0, skip
	mov	ds:last,di	;save
	inc	ds:nline	;counts as a line
nl9:	call	print		;print info for this page
	jmp	short newpag	;start a new one
;+
;
; Print length of previous page, plus last non-blank line.
;
;-
print:	push	cx		;save
	mov	di,ds:last	;get length
	mov	bx,offset lbuf	;point at buf
	add	di,bx		;index out to end
	cmp	bx,di		;did we get anything?
	je	pr1		;no, so skip the ":<tab>"
	dec	bx		;back up
	dec	bx
	mov	word ptr [bx],':'+(tab*400) ;":<tab>"
pr1:	mov	ax,ds:nline	;get # lines
	mov	cx,10d		;divisor
pr2:	xor	dx,dx		;0-extend
	div	cx		;divide
	dec	bx		;back up
	or	dl,'0'		;make a digit
	mov	[bx],dl		;save it
	test	ax,ax		;anything left?
	jnz	pr2		;loop if so
	mov	dx,bx		;copy
	mov	ax,cr+(lf*400)	;add crlf
	stosw
	mov	cx,di		;get ptr to end
	sub	cx,dx		;find length
	mov	bx,0001h	;handle=STDOUT
	mov	ah,40h		;func=write
	int	21h
	pop	cx		;restore
	ret
;
operr	db	'?Error opening file',cr,lf,'$'
rderr	db	'?Read error',cr,lf,'$'
;
handle	dw	0000h		;handle (default=STDIN)
;
	db	5+1+1 dup(?)	;space for "65535:<tab>"
lbuf	db	lbufl+2 dup(?)	;output line buf (allow for cr, lf)
;
nline	dw	1 dup(?)	;# lines in page
last	dw	1 dup(?)	;length of last non-null line
;
buf	db	bufl dup(?)	;input buffer
;
code	ends
	end	start
