summaryrefslogtreecommitdiff
path: root/usr/src/lib/libast/common/sfio/sfflsbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libast/common/sfio/sfflsbuf.c')
-rw-r--r--usr/src/lib/libast/common/sfio/sfflsbuf.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/sfio/sfflsbuf.c b/usr/src/lib/libast/common/sfio/sfflsbuf.c
new file mode 100644
index 0000000000..fb7dc3b61d
--- /dev/null
+++ b/usr/src/lib/libast/common/sfio/sfflsbuf.c
@@ -0,0 +1,116 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write a buffer out to a file descriptor or
+** extending a buffer for a SF_STRING stream.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfflsbuf(reg Sfio_t* f, reg int c)
+#else
+int _sfflsbuf(f,c)
+reg Sfio_t* f; /* write out the buffered content of this stream */
+reg int c; /* if c>=0, c is also written out */
+#endif
+{
+ reg ssize_t n, w;
+ reg uchar* data;
+ uchar outc;
+ reg int local, isall;
+ int inpc = c;
+
+ SFMTXSTART(f,-1);
+
+ GETLOCAL(f,local);
+
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,local);
+
+ /* current data extent */
+ n = f->next - (data = f->data);
+
+ if(n == (f->endb-data) && (f->flags&SF_STRING))
+ { /* extend string stream buffer */
+ (void)SFWR(f,data,1,f->disc);
+
+ /* !(f->flags&SF_STRING) is required because exception
+ handlers may turn a string stream to a file stream */
+ if(f->next < f->endb || !(f->flags&SF_STRING) )
+ n = f->next - (data = f->data);
+ else
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ }
+
+ if(c >= 0)
+ { /* write into buffer */
+ if(n < (f->endb - (data = f->data)))
+ { *f->next++ = c;
+ if(c == '\n' &&
+ (f->flags&SF_LINE) && !(f->flags&SF_STRING))
+ { c = -1;
+ n += 1;
+ }
+ else break;
+ }
+ else if(n == 0)
+ { /* unbuffered io */
+ outc = (uchar)c;
+ data = &outc;
+ c = -1;
+ n = 1;
+ }
+ }
+
+ if(n == 0 || (f->flags&SF_STRING))
+ break;
+
+ isall = SFISALL(f,isall);
+ if((w = SFWR(f,data,n,f->disc)) > 0)
+ { if((n -= w) > 0) /* save unwritten data, then resume */
+ memcpy((char*)f->data,(char*)data+w,n);
+ f->next = f->data+n;
+ if(c < 0 && (!isall || n == 0))
+ break;
+ }
+ else if(w == 0)
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ else if(c < 0)
+ break;
+ }
+
+ SFOPEN(f,local);
+
+ if(inpc < 0)
+ inpc = f->endb-f->next;
+
+ SFMTXRETURN(f,inpc);
+}