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