1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 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 31 int _sfflsbuf(Sfio_t* f, int c) 32 #else 33 int _sfflsbuf(f,c) 34 Sfio_t* f; /* write out the buffered content of this stream */ 35 int 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