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
sfputr(Sfio_t * f,const char * s,int rc)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