1 #include <newlib.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7
8 int
__ssputs(FILE * fp,const char * buf,size_t len)9 __ssputs (
10 FILE *fp,
11 const char *buf,
12 size_t len)
13 {
14 register unsigned int w;
15
16 w = (unsigned int) fp->_w;
17 if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
18 /* must be asprintf family */
19 unsigned char *str;
20 int curpos = (fp->_p - fp->_bf._base);
21 /* Choose a geometric growth factor to avoid
22 * quadratic realloc behavior, but use a rate less
23 * than (1+sqrt(5))/2 to accomodate malloc
24 * overhead. asprintf EXPECTS us to overallocate, so
25 * that it can add a trailing \0 without
26 * reallocating. The new allocation should thus be
27 * max(prev_size*1.5, curpos+len+1). */
28 unsigned int newsize = fp->_bf._size * 3 / 2;
29 if (newsize < curpos + len + 1)
30 newsize = curpos + len + 1;
31 if (fp->_flags & __SOPT)
32 {
33 /* asnprintf leaves original buffer alone. */
34 str = (unsigned char *)malloc (newsize);
35 if (!str)
36 goto err;
37 memcpy (str, fp->_bf._base, curpos);
38 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
39 }
40 else
41 {
42 str = (unsigned char *)realloc (fp->_bf._base,
43 newsize);
44 if (!str) {
45 /* Free unneeded buffer. */
46 free (fp->_bf._base);
47 goto err;
48 }
49 }
50 fp->_bf._base = str;
51 fp->_p = str + curpos;
52 fp->_bf._size = newsize;
53 w = len;
54 fp->_w = newsize - curpos;
55 }
56 if (len < w)
57 w = len;
58 memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
59 fp->_w -= w;
60 fp->_p += w;
61
62 return 0;
63
64 err:
65 _REENT_ERRNO(ptr) = ENOMEM;
66 fp->_flags |= __SERR;
67 return EOF;
68 }
69