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 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 /* Put out a null-terminated string 25 ** 26 ** Written by Kiem-Phong Vo. 27 */ 28 #if __STD_C 29 ssize_t sfputr(Sfio_t* f, const char* s, int rc) 30 #else 31 ssize_t sfputr(f,s,rc) 32 Sfio_t* f; /* write to this stream */ 33 char* s; /* string to write */ 34 int rc; /* record separator. */ 35 #endif 36 { 37 ssize_t p, n, w, sn; 38 uchar *ps; 39 char *ss; 40 SFMTXDECL(f); 41 42 SFMTXENTER(f,-1); 43 44 if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) 45 SFMTXRETURN(f, -1); 46 47 SFLOCK(f,0); 48 49 f->val = sn = -1; ss = (char*)s; 50 for(w = 0; (*s || rc >= 0); ) 51 { /* need to communicate string size to exception handler */ 52 if((f->flags&SF_STRING) && f->next >= f->endb ) 53 { sn = sn < 0 ? strlen(s) : (sn - (s-ss)); 54 ss = (char*)s; /* save current checkpoint */ 55 f->val = sn + (rc >= 0 ? 1 : 0); /* space requirement */ 56 f->bits |= SF_PUTR; /* tell sfflsbuf to use f->val */ 57 } 58 59 SFWPEEK(f,ps,p); 60 f->bits &= ~SF_PUTR; /* remove any trace of this */ 61 62 if(p < 0 ) /* something not right about buffering */ 63 break; 64 65 if(p == 0 || (f->flags&SF_WHOLE) ) 66 { n = sn < 0 ? strlen(s) : sn - (s-ss); 67 if(p >= (n + (rc < 0 ? 0 : 1)) ) 68 { /* buffer can hold everything */ 69 if(n > 0) 70 { memcpy(ps, s, n); 71 ps += n; 72 w += n; 73 } 74 if(rc >= 0) 75 { *ps++ = rc; 76 w += 1; 77 } 78 f->next = ps; 79 } 80 else 81 { /* create a reserve buffer to hold data */ 82 Sfrsrv_t* rsrv; 83 84 p = n + (rc >= 0 ? 1 : 0); 85 if(!(rsrv = _sfrsrv(f, p)) ) 86 n = 0; 87 else 88 { if(n > 0) 89 memcpy(rsrv->data, s, n); 90 if(rc >= 0) 91 rsrv->data[n] = rc; 92 if((n = SFWRITE(f,rsrv->data,p)) < 0 ) 93 n = 0; 94 } 95 96 w += n; 97 } 98 break; 99 } 100 101 if(*s == 0) 102 { *ps++ = rc; 103 f->next = ps; 104 w += 1; 105 break; 106 } 107 108 #if _lib_memccpy && !__ia64 /* these guys may never get it right */ 109 if((ps = (uchar*)memccpy(ps,s,'\0',p)) != NIL(uchar*)) 110 ps -= 1; 111 else ps = f->next+p; 112 s += ps - f->next; 113 #else 114 for(; p > 0; --p, ++ps, ++s) 115 if((*ps = *s) == 0) 116 break; 117 #endif 118 w += ps - f->next; 119 f->next = ps; 120 } 121 122 /* sync unseekable shared streams */ 123 if(f->extent < 0 && (f->flags&SF_SHARE) ) 124 (void)SFFLSBUF(f,-1); 125 126 /* check for line buffering */ 127 else if((f->flags&SF_LINE) && !(f->flags&SF_STRING) && (n = f->next-f->data) > 0) 128 { if(n > w) 129 n = w; 130 f->next -= n; 131 (void)SFWRITE(f,(Void_t*)f->next,n); 132 } 133 134 SFOPEN(f,0); 135 SFMTXRETURN(f, w); 136 } 137