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/*	Put out a null-terminated string
25**
26**	Written by Kiem-Phong Vo.
27*/
28#if __STD_C
29ssize_t sfputr(Sfio_t* f, const char* s, int rc)
30#else
31ssize_t sfputr(f,s,rc)
32Sfio_t*		f;	/* write to this stream	*/
33char*		s;	/* string to write	*/
34int		rc;	/* record separator.	*/
35#endif
36{
37	reg ssize_t	p, n, w;
38	reg uchar*	ps;
39	SFMTXDECL(f);
40
41	SFMTXENTER(f,-1);
42
43	if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
44		SFMTXRETURN(f, -1);
45
46	SFLOCK(f,0);
47
48	for(w = 0; (*s || rc >= 0); )
49	{	if(SFWPEEK(f,ps,p) < 0)
50			break;
51
52		if(p == 0 || (f->flags&SF_WHOLE) )
53		{	n = strlen(s);
54			if(p >= (n + (rc < 0 ? 0 : 1)) )
55			{	/* buffer can hold everything */
56				if(n > 0)
57				{	memcpy(ps, s, n);
58					ps += n;
59					w += n;
60				}
61				if(rc >= 0)
62				{	*ps++ = rc;
63					w += 1;
64				}
65				f->next = ps;
66			}
67			else
68			{	/* create a reserve buffer to hold data */
69				Sfrsrv_t*	rsrv;
70
71				p = n + (rc >= 0 ? 1 : 0);
72				if(!(rsrv = _sfrsrv(f, p)) )
73					n = 0;
74				else
75				{	if(n > 0)
76						memcpy(rsrv->data, s, n);
77					if(rc >= 0)
78						rsrv->data[n] = rc;
79					if((n = SFWRITE(f,rsrv->data,p)) < 0 )
80						n = 0;
81				}
82
83				w += n;
84			}
85			break;
86		}
87
88		if(*s == 0)
89		{	*ps++ = rc;
90			f->next = ps;
91			w += 1;
92			break;
93		}
94
95#if _lib_memccpy && !__ia64 /* these guys may never get it right */
96		if((ps = (uchar*)memccpy(ps,s,'\0',p)) != NIL(uchar*))
97			ps -= 1;
98		else	ps  = f->next+p;
99		s += ps - f->next;
100#else
101		for(; p > 0; --p, ++ps, ++s)
102			if((*ps = *s) == 0)
103				break;
104#endif
105		w += ps - f->next;
106		f->next = ps;
107	}
108
109	/* sync unseekable shared streams */
110	if(f->extent < 0 && (f->flags&SF_SHARE) )
111		(void)SFFLSBUF(f,-1);
112
113	/* check for line buffering */
114	else if((f->flags&SF_LINE) && !(f->flags&SF_STRING) && (n = f->next-f->data) > 0)
115	{	if(n > w)
116			n = w;
117		f->next -= n;
118		(void)SFWRITE(f,(Void_t*)f->next,n);
119	}
120
121	SFOPEN(f,0);
122	SFMTXRETURN(f, w);
123}
124