/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:fputs.s 12.0$ */
/* $ACIS:fputs.s 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/stdio/RCS/fputs.s,v $ */

	.data
rcsid:	.asciz	"$Header:fputs.s 12.0$"
	.text

#define TMP	r0	/* Scatch register. */
#define S	r2	/* Same variable names as in C version, but uc. */
#define IOP	r3
#define UNBUFF	r4	/* UNBUFF is !0 if buffering is off. */
#define IOFLAG	r5
#define C	r10
#define IOP_CNT	r11	/* Keep iop_cnt local until flsbuf is called. */
#define IOP_PTR r12	/* Keep iop_ptr local until flsbuf is called. */
#define OLDSP	r13	/* Caller's stack pointer. */
#define BUFFER_SIZ	r14

#define NEWLINE	012

	/* Displacements of _iobuf fields */
#define FLAG	16
#define BSIZ	12
#define	BASE	8
#define	PTR	4
#define	CNT	0

#define FIRSTSVREG	r10
#define REGSVAREA	60 /* ARGSV(16)+LINKSV(20)+REGSV(64)-(FIRSTSVREG*4) */
#define LOCALBUF	1024	/* Local buffer size. */

	/* Defines copied from stdio.h */
#define _IOLBF	0200
#define _IONBF	04
#define EOF	-1
#define BUFSIZ	1024

.data
.align 2		/* Start data on word boundary. */
.globl	_fputs
	_fputs:	.long _.fputs
.text
.align 2		/* Start text on word boundary. */
.globl	_.fputs		/* fputs(s, iop) r2 s; r4 iop */
	_.fputs:
		stm	FIRSTSVREG,-REGSVAREA(sp)
		cas	OLDSP,sp,r0		/* Store caller's sp in r13 */
		ai	sp,sp,-REGSVAREA	/* Establish fgets' sp. */

				/* If iop is unbuffered, set up buffering */
		getha	IOFLAG,FLAG(IOP)	/* IOFLAG = iop->flag */
		nilz	UNBUFF,IOFLAG,_IONBF	/* UNBUFF=iop->flag&_IONBF */
		je	Lbegin
		ni	TMP,IOFLAG,0-5		/* iop->flag &= ~_IONBF */
		putha	TMP,FLAG(IOP)		/* Store iop->flag */
		ai	sp,sp,-LOCALBUF		/* Drop sp for local buffer */
		put	sp,BASE(IOP)		/* iop->base = LOCALBUF */
		put	sp,PTR(IOP)		/* iop->ptr = LOCALBUF */
		get	BUFFER_SIZ,$BUFSIZ	/* iop->ptr = BUFSIZ */
		put	BUFFER_SIZ,BSIZ(IOP)
	Lbegin:
		get	IOP_CNT,CNT(IOP)	/* load local iop->_cnt */
		get	IOP_PTR,PTR(IOP)	/* load local iop->_ptr */
		get	BUFFER_SIZ,BSIZ(IOP)	/* Get io bufsiz. */
						/* Only needed if LBF. */

	Lwhile_loop:			/* while(c = *s++) putc(c, iop); */
		lcs	C,0(S)			/* c = *s */
		cis	C,0			/* c == 0? */
		jeq	Lreturn
		inc	S,1
		si	IOP_CNT,IOP_CNT,1	/* --(iop)->cnt */
		jl	Lrest_putc		/* iop->cnt >= 0? */
				/* The simple part of putc: */
		inc	IOP_PTR,1		/* iop++ */
		bx	Lwhile_loop
		stc	C,-1(IOP_PTR)		/* *iop->ptr = c */

		/* Note:when line buf is on, _cnt is set to zero in flsbuf */
		/* and is decremented to -p->_bufsiz before flushing. */
	Lrest_putc:
		ci	IOFLAG,_IOLBF		/* Line buffering on? */
		jne	Lflush		/* No LBF, gotta flush buffer. */
		ai	TMP,BUFFER_SIZ,0
		a	TMP,IOP_CNT	/* -(p)->cnt < p->bufsiz? */
		jle	Lflush

				/* Line buffering is on: */
		inc	IOP_PTR,1		/* p->ptr++ */
		ci	C,NEWLINE		/* c=='\n'? */
		bnex	Lwhile_loop
		stc	C,-1(IOP_PTR)		/* iop->ptr = c */
		si	IOP_PTR,IOP_PTR,1     /* set to real ptr for flsbuf */
		
	Lflush:	/* buffer full, flush it or newline && linebuffer == on. */
		put	r2,-16(OLDSP)		/* Save arg words and tmps. */
		put	r3,-12(OLDSP)
		put	r4,-8(OLDSP)
		put	r5,-4(OLDSP)
		
		cas	r2,C,r0			/* flsbuf(iop) setup */
/* Comment:	cas	r3,IOP,r0		/* IOP already in r3. */
		get	r0,$__flsbuf
		balix	r15,_._flsbuf
				/* Update iop->ptr, flsbuf needs it. */
		put	IOP_PTR,PTR(IOP)
		
		ci	r2,EOF			/* EOF returned? */
		jeq	Lreally_return		/* EOF means error. */
				/* Restore arg words & tmps */
		get	r2,-16(OLDSP)
		get	r3,-12(OLDSP)
		get	r4,-8(OLDSP)
		get	r5,-4(OLDSP)

			/* If IOFLAG !0 then line buffering is on. */
		getha	IOFLAG,FLAG(IOP)	/* Get newly set io flag */
		nilz	IOFLAG,IOFLAG,_IOLBF	/* IOFLAG=iop->flag&_IOLBF */
		get	IOP_CNT,CNT(IOP)	/* Get new local iop->_cnt */
		get	BUFFER_SIZ,BSIZ(IOP)	/* Get buffer size. */
		bx	Lwhile_loop		/* get more chars */
		get	IOP_PTR,PTR(IOP)	/* Get new local iop->_ptr */

	Lreturn:				/* Return setup. */
		cis	UNBUFF,0		/* This stream unbuffered? */
		jeq	Lreally_return
	
				/* Stream unbuffered, reset the items done */
				/* just after entry to fputs. */
		cas	C,IOP,r0		/* Use reg C to save IOP. */
		cas	r2,IOP,r0		/* fflush(iop) set up. */
		get	r0,$_fflush
		balix	r15,_.fflush
		put	IOP_PTR,PTR(IOP)	/* fflush needs ptr. */

		ci	r2,EOF			/* fflush return error? */
		jeq	Lreally_return		/* Value added error check. */

		cas	IOP,C,r0		/* Restore iop. */
		getha	IOFLAG,FLAG(IOP)	/* Get iop->_flag */
		oi	IOFLAG,IOFLAG,_IONBF	/* Put the NBF bit back. */
		putha	IOFLAG,FLAG(IOP)	/* Put the flag back. */
		get	TMP,$0			/* tmpreg = 0 */
		put	TMP,BASE(IOP)		/* iop->_base = 0 */
		put	TMP,BSIZ(IOP)		/* iop->_bufsiz = 0 */
		get	IOP_CNT,$0		/* iop->_cnt = 0 */
		get	IOP_PTR,$0		/* iop->ptr = 0 */

			/* Assuming that r2 is != EOF at this point. */	
	Lreally_return:
		put	IOP_CNT,CNT(IOP)	/* Put local cnt back. */
		put	IOP_PTR,PTR(IOP)	/* Put local ptr back. */
		cas	sp,OLDSP,r0		/* Restore sp. */
		lm	FIRSTSVREG,-REGSVAREA(OLDSP)	
		br	r15

.short 0xdf07	/* Trace table marker. */
.short 0xdfa8	/* Trace table marker, (first gpr,flags) */
.short 0x2d00	/* trace table nparams, fp, local_offset */

.data
.globl	.oVncs
.set	.oVncs, 0
