1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#include "sfhdr.h"
1N/A
1N/A/* Write a buffer out to a file descriptor or
1N/A** extending a buffer for a SF_STRING stream.
1N/A**
1N/A** Written by Kiem-Phong Vo
1N/A*/
1N/A
1N/A#if __STD_C
1N/Aint _sfflsbuf(Sfio_t* f, int c)
1N/A#else
1N/Aint _sfflsbuf(f,c)
1N/ASfio_t* f; /* write out the buffered content of this stream */
1N/Aint c; /* if c>=0, c is also written out */
1N/A#endif
1N/A{
1N/A ssize_t n, w, written;
1N/A uchar* data;
1N/A uchar outc;
1N/A int local, isall;
1N/A int inpc = c;
1N/A SFMTXDECL(f); /* declare a local stream variable for multithreading */
1N/A
1N/A SFMTXENTER(f,-1);
1N/A
1N/A GETLOCAL(f,local);
1N/A
1N/A for(written = 0;; f->mode &= ~SF_LOCK)
1N/A { /* check stream mode */
1N/A if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
1N/A SFMTXRETURN(f, -1);
1N/A SFLOCK(f,local);
1N/A
1N/A /* current data extent */
1N/A n = f->next - (data = f->data);
1N/A
1N/A if(n == (f->endb-data) && (f->flags&SF_STRING))
1N/A { /* extend string stream buffer */
1N/A (void)SFWR(f,data,1,f->disc);
1N/A
1N/A /* !(f->flags&SF_STRING) is required because exception
1N/A handlers may turn a string stream to a file stream */
1N/A if(f->next < f->endb || !(f->flags&SF_STRING) )
1N/A n = f->next - (data = f->data);
1N/A else
1N/A { SFOPEN(f,local);
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A }
1N/A
1N/A if(c >= 0)
1N/A { /* write into buffer */
1N/A if(n < (f->endb - (data = f->data)))
1N/A { *f->next++ = c;
1N/A if(c == '\n' &&
1N/A (f->flags&SF_LINE) && !(f->flags&SF_STRING))
1N/A { c = -1;
1N/A n += 1;
1N/A }
1N/A else break;
1N/A }
1N/A else if(n == 0)
1N/A { /* unbuffered io */
1N/A outc = (uchar)c;
1N/A data = &outc;
1N/A c = -1;
1N/A n = 1;
1N/A }
1N/A }
1N/A
1N/A if(n == 0 || (f->flags&SF_STRING))
1N/A break;
1N/A
1N/A isall = SFISALL(f,isall);
1N/A if((w = SFWR(f,data,n,f->disc)) > 0)
1N/A { if((n -= w) > 0) /* save unwritten data, then resume */
1N/A memcpy((char*)f->data,(char*)data+w,n);
1N/A written += w;
1N/A f->next = f->data+n;
1N/A if(c < 0 && (!isall || n == 0))
1N/A break;
1N/A }
1N/A else if(w == 0)
1N/A { if(written > 0) /* some buffer was cleared */
1N/A break; /* do normal exit below */
1N/A else /* nothing was done, returning failure */
1N/A { SFOPEN(f,local);
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A }
1N/A else /* w < 0 means SF_EDISC or SF_ESTACK in sfwr() */
1N/A { if(c < 0) /* back to the calling write operation */
1N/A break;
1N/A else continue; /* try again to write out c */
1N/A }
1N/A }
1N/A
1N/A SFOPEN(f,local);
1N/A
1N/A if(inpc < 0)
1N/A inpc = f->endb-f->next;
1N/A
1N/A SFMTXRETURN(f,inpc);
1N/A}