********************************************************************
; PRINTF REPLACEMENT ROUTINES
********************************************************************
; Written by Stone, SST, 1993 Email c9107253@mystra.newcastle.edu.au
; All source public domain of course
;
; BUGS: must use %ld & %lc instead of %d & %c due to long word
; passing
;
********************************************************************

;	MODULE  RawDoFmtGlue
	OPT		o+			;optimize
	OPT		l+			;link

	xdef		_fpf		;fprintf replacement: output, string, args...
	xdef		_spf		;sprintf replacement: outstring, maxn, string, args...
	xref		_DOSBase	;relative to A4!

	include "dh0:stone/dazsys/macros.i"
	include "dh0:stone/dazsys/xrefs"
	

********************************************************************
_fpf ; call with output, string, args, ...
*********************************************************************
; DO A FORMATTED PRINT SIMILAR TO fprintf EXCEPT USE EXEC RawDoFmt FOR SMALLNESS!
; NUMBER OF CHARACTERS ACTUALLY PRINTED IS RETURNED IN D0
BUFSIZE = 120
				rsset		0
pf_msgbuf		rs.b	BUFSIZE						;MUST be first! (and divi by 4)
pf_DOSBase		rs.l	1							;need this for printing!
pf_stringpos	rs.w	1							;current position
pf_totprint		rs.w	1							;total printed
pf_badoutput	rs.b	1							;output was bad
pf_pad			rs.b	3
pf_noofvars		rs.l	0
pf_stacked		rs.l	14
pf_return		rs.l	1
; CALLER MUST SUPPLY THE FOLLOWING ON THE STACK
pf_output		rs.l	1							;output file
pf_string		rs.l	1							;format
pf_stream		rs.l	0							;start of the stream
; also: a4 should point at global variable table with _DOSBase defined
*********************************************************************
		movem.l		d1-d7/a0-a6,-(sp)
		lea			(0-pf_noofvars)(sp),sp
		moveq		#0,d0							;for return
		if.l		not,pf_output(sp),_fpf_thatsall	;NULL file?
		move.l		_DOSBase(a4),pf_DOSBase(sp)		;get the DOSBase
		move.l		sp,a3							;a3 <== base of data
		clr.b		pf_badoutput(sp)
		clr.w		pf_stringpos(sp)				;buf pos
		clr.w		pf_totprint(sp)					;for return
		move.l		pf_string(sp),a0
		lea			pf_stream(sp),a1
		lea			P_DoChar(pc),a2					;call this each char
		LVOEXEC		RawDoFmt
		move.w		pf_totprint(sp),d0
		ext.l		d0								;return d0 (long)
_fpf_thatsall:
		lea			pf_noofvars(sp),sp
		movem.l		(sp)+,d1-d7/a0-a6
		rts
; a3 pf_variable table, d0 character to add to the buffer
P_DoChar
		move.w		d1,-(sp)
		move.w		pf_stringpos(a3),d1
		move.b		d0,(a3,d1.w)
		if			eq,p_dc_dit
		addq.w		#1,pf_totprint(a3)
		addq.w		#1,d1
		if.w		d1,lt,#BUFSIZE,p_dc_ok
p_dc_dit
		bsr.s		P_dump
		moveq		#0,d1
p_dc_ok	move.w		d1,pf_stringpos(a3)
		move.w		(sp)+,d1
		rts
; Pass with d1 as the length to print, a3 with the pf_variable table
P_dump	movem.l		d0-d7/a0-a6,-(sp)
		if.b		pf_badoutput(a3),pdump_nomore
		moveq		#0,d3
		move.w		d1,d3							;d3 <== length
		beq.s		pdump_nomore
		move.l		a3,d2							;d2 <== buffer
		move.l		pf_output(a3),d1				;d1 <== file handle
		LVO			pf_DOSBase(a3),Write
		tst.w		d0
		seq.b		pf_badoutput(a3)				;didn't write anything?
pdump_nomore:
		movem.l		(sp)+,d0-d7/a0-a6
		rts

*********************************************************************
_spf ; outstring, (long)maxlen, string, args, ...
*********************************************************************
				rsset		0
sf_stringpos	rs.w	1							;current position
sf_pad			rs.w	1
sf_noofvars		rs.l	0
sf_stacked		rs.l	14
sf_return		rs.l	1
; CALLER MUST SUPPLY THE FOLLOWING ON THE STACK
sf_outbuf		rs.l	1							;output buffer
sf_pad2			rs.w	1
sf_maxlen		rs.w	1							;0 or less = unlimited
sf_string		rs.l	1							;format
sf_stream		rs.l	0							;start of the stream
*********************************************************************
		movem.l		d1-d7/a0-a6,-(sp)
		subq.l		#sf_noofvars,sp
		move.l		sp,a3							;a3 <== base of data
		subq.w		#1,sf_maxlen(a3)				;compensate
		clr.w		sf_stringpos(a3)				;buf pos
		move.l		sf_string(a3),a0
		move.l		a0,d7
		beq.s		_spf_nomore						;NULL string?
		lea			sf_stream(a3),a1
		lea			S_DoChar(pc),a2					;call this each char
		LVOEXEC		RawDoFmt
		move.w		sf_stringpos(a3),d0
		move.l		sf_outbuf(a3),a0				;Terminate with '\0'
		clr.b		(a0,d0.w)
		ext.l		d0								;return d0 (long)
_spf_nomore:
		addq.l		#sf_noofvars,sp
		movem.l		(sp)+,d1-d7/a0-a6
		rts
; a3 sf_variable table, d0 character to add to the buffer
S_DoChar
		movem.l		a0/d1,-(sp)
		move.w		sf_stringpos(a3),d1
		if.w		d1,eq,sf_maxlen(a3),s_nomor		;stop at len-1
		move.l		sf_outbuf(a3),a0
		if.b		not,d0,s_nomor					;write '\0' in later
		addq.w		#1,sf_stringpos(a3)
		move.b		d0,(a0,d1.w)
s_nomor	movem.l		(sp)+,a0/d1
 		rts
