1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #include	"sfhdr.h"
23da2e3ebdSchin 
24da2e3ebdSchin /*	Write a buffer out to a file descriptor or
25da2e3ebdSchin **	extending a buffer for a SF_STRING stream.
26da2e3ebdSchin **
27da2e3ebdSchin **	Written by Kiem-Phong Vo
28da2e3ebdSchin */
29da2e3ebdSchin 
30da2e3ebdSchin #if __STD_C
_sfflsbuf(Sfio_t * f,int c)317c2fbfb3SApril Chin int _sfflsbuf(Sfio_t* f, int c)
32da2e3ebdSchin #else
33da2e3ebdSchin int _sfflsbuf(f,c)
347c2fbfb3SApril Chin Sfio_t*	f;	/* write out the buffered content of this stream */
357c2fbfb3SApril Chin int	c;	/* if c>=0, c is also written out */
36da2e3ebdSchin #endif
37da2e3ebdSchin {
3834f9b3eeSRoland Mainz 	ssize_t		n, w, written;
397c2fbfb3SApril Chin 	uchar*		data;
40da2e3ebdSchin 	uchar		outc;
417c2fbfb3SApril Chin 	int		local, isall;
42da2e3ebdSchin 	int		inpc = c;
4334f9b3eeSRoland Mainz 	SFMTXDECL(f); /* declare a local stream variable for multithreading */
44da2e3ebdSchin 
457c2fbfb3SApril Chin 	SFMTXENTER(f,-1);
46da2e3ebdSchin 
47da2e3ebdSchin 	GETLOCAL(f,local);
48da2e3ebdSchin 
4934f9b3eeSRoland Mainz 	for(written = 0;; f->mode &= ~SF_LOCK)
50da2e3ebdSchin 	{	/* check stream mode */
51da2e3ebdSchin 		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
52da2e3ebdSchin 			SFMTXRETURN(f, -1);
53da2e3ebdSchin 		SFLOCK(f,local);
54da2e3ebdSchin 
55da2e3ebdSchin 		/* current data extent */
56da2e3ebdSchin 		n = f->next - (data = f->data);
57da2e3ebdSchin 
58da2e3ebdSchin 		if(n == (f->endb-data) && (f->flags&SF_STRING))
59*b30d1939SAndy Fiddaman 		{	/* call sfwr() to extend string buffer and process events */
60*b30d1939SAndy Fiddaman 			w = ((f->bits&SF_PUTR) && f->val > 0) ? f->val : 1;
61*b30d1939SAndy Fiddaman 			(void)SFWR(f, data, w, f->disc);
62da2e3ebdSchin 
63da2e3ebdSchin 			/* !(f->flags&SF_STRING) is required because exception
64da2e3ebdSchin 			   handlers may turn a string stream to a file stream */
65da2e3ebdSchin 			if(f->next < f->endb || !(f->flags&SF_STRING) )
66da2e3ebdSchin 				n = f->next - (data = f->data);
67da2e3ebdSchin 			else
68da2e3ebdSchin 			{	SFOPEN(f,local);
69da2e3ebdSchin 				SFMTXRETURN(f, -1);
70da2e3ebdSchin 			}
71da2e3ebdSchin 		}
72da2e3ebdSchin 
73da2e3ebdSchin 		if(c >= 0)
74da2e3ebdSchin 		{	/* write into buffer */
75da2e3ebdSchin 			if(n < (f->endb - (data = f->data)))
76da2e3ebdSchin 			{	*f->next++ = c;
77da2e3ebdSchin 				if(c == '\n' &&
78da2e3ebdSchin 				   (f->flags&SF_LINE) && !(f->flags&SF_STRING))
79da2e3ebdSchin 				{	c = -1;
80da2e3ebdSchin 					n += 1;
81da2e3ebdSchin 				}
82da2e3ebdSchin 				else	break;
83da2e3ebdSchin 			}
84da2e3ebdSchin 			else if(n == 0)
85da2e3ebdSchin 			{	/* unbuffered io */
86da2e3ebdSchin 				outc = (uchar)c;
87da2e3ebdSchin 				data = &outc;
88da2e3ebdSchin 				c = -1;
89da2e3ebdSchin 				n = 1;
90da2e3ebdSchin 			}
91da2e3ebdSchin 		}
92da2e3ebdSchin 
93da2e3ebdSchin 		if(n == 0 || (f->flags&SF_STRING))
94da2e3ebdSchin 			break;
95da2e3ebdSchin 
96da2e3ebdSchin 		isall = SFISALL(f,isall);
97da2e3ebdSchin 		if((w = SFWR(f,data,n,f->disc)) > 0)
98da2e3ebdSchin 		{	if((n -= w) > 0) /* save unwritten data, then resume */
99da2e3ebdSchin 				memcpy((char*)f->data,(char*)data+w,n);
10034f9b3eeSRoland Mainz 			written += w;
101da2e3ebdSchin 			f->next = f->data+n;
102da2e3ebdSchin 			if(c < 0 && (!isall || n == 0))
103da2e3ebdSchin 				break;
104da2e3ebdSchin 		}
105da2e3ebdSchin 		else if(w == 0)
10634f9b3eeSRoland Mainz 		{	if(written > 0) /* some buffer was cleared */
10734f9b3eeSRoland Mainz 				break; /* do normal exit below */
10834f9b3eeSRoland Mainz 			else /* nothing was done, returning failure */
10934f9b3eeSRoland Mainz 			{	SFOPEN(f,local);
11034f9b3eeSRoland Mainz 				SFMTXRETURN(f, -1);
11134f9b3eeSRoland Mainz 			}
11234f9b3eeSRoland Mainz 		}
11334f9b3eeSRoland Mainz 		else /* w < 0 means SF_EDISC or SF_ESTACK in sfwr() */
11434f9b3eeSRoland Mainz 		{	if(c < 0) /* back to the calling write operation */
11534f9b3eeSRoland Mainz 				break;
11634f9b3eeSRoland Mainz 			else	continue; /* try again to write out c */
117da2e3ebdSchin 		}
118da2e3ebdSchin 	}
119da2e3ebdSchin 
120da2e3ebdSchin 	SFOPEN(f,local);
121da2e3ebdSchin 
122da2e3ebdSchin 	if(inpc < 0)
123da2e3ebdSchin 		inpc = f->endb-f->next;
124da2e3ebdSchin 
125da2e3ebdSchin 	SFMTXRETURN(f,inpc);
126da2e3ebdSchin }
127