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