1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#include	"sfhdr.h"
23
24/*	Write a buffer out to a file descriptor or
25**	extending a buffer for a SF_STRING stream.
26**
27**	Written by Kiem-Phong Vo
28*/
29
30#if __STD_C
31int _sfflsbuf(Sfio_t* f, int c)
32#else
33int _sfflsbuf(f,c)
34Sfio_t*	f;	/* write out the buffered content of this stream */
35int	c;	/* if c>=0, c is also written out */
36#endif
37{
38	ssize_t		n, w, written;
39	uchar*		data;
40	uchar		outc;
41	int		local, isall;
42	int		inpc = c;
43	SFMTXDECL(f); /* declare a local stream variable for multithreading */
44
45	SFMTXENTER(f,-1);
46
47	GETLOCAL(f,local);
48
49	for(written = 0;; f->mode &= ~SF_LOCK)
50	{	/* check stream mode */
51		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
52			SFMTXRETURN(f, -1);
53		SFLOCK(f,local);
54
55		/* current data extent */
56		n = f->next - (data = f->data);
57
58		if(n == (f->endb-data) && (f->flags&SF_STRING))
59		{	/* extend string stream buffer */
60			(void)SFWR(f,data,1,f->disc);
61
62			/* !(f->flags&SF_STRING) is required because exception
63			   handlers may turn a string stream to a file stream */
64			if(f->next < f->endb || !(f->flags&SF_STRING) )
65				n = f->next - (data = f->data);
66			else
67			{	SFOPEN(f,local);
68				SFMTXRETURN(f, -1);
69			}
70		}
71
72		if(c >= 0)
73		{	/* write into buffer */
74			if(n < (f->endb - (data = f->data)))
75			{	*f->next++ = c;
76				if(c == '\n' &&
77				   (f->flags&SF_LINE) && !(f->flags&SF_STRING))
78				{	c = -1;
79					n += 1;
80				}
81				else	break;
82			}
83			else if(n == 0)
84			{	/* unbuffered io */
85				outc = (uchar)c;
86				data = &outc;
87				c = -1;
88				n = 1;
89			}
90		}
91
92		if(n == 0 || (f->flags&SF_STRING))
93			break;
94
95		isall = SFISALL(f,isall);
96		if((w = SFWR(f,data,n,f->disc)) > 0)
97		{	if((n -= w) > 0) /* save unwritten data, then resume */
98				memcpy((char*)f->data,(char*)data+w,n);
99			written += w;
100			f->next = f->data+n;
101			if(c < 0 && (!isall || n == 0))
102				break;
103		}
104		else if(w == 0)
105		{	if(written > 0) /* some buffer was cleared */
106				break; /* do normal exit below */
107			else /* nothing was done, returning failure */
108			{	SFOPEN(f,local);
109				SFMTXRETURN(f, -1);
110			}
111		}
112		else /* w < 0 means SF_EDISC or SF_ESTACK in sfwr() */
113		{	if(c < 0) /* back to the calling write operation */
114				break;
115			else	continue; /* try again to write out c */
116		}
117	}
118
119	SFOPEN(f,local);
120
121	if(inpc < 0)
122		inpc = f->endb-f->next;
123
124	SFMTXRETURN(f,inpc);
125}
126