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