forked from KolibriOS/kolibrios
set default newlib dir's structure
git-svn-id: svn://kolibrios.org@4874 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
267
contrib/sdk/sources/newlib/libc/stdio/fvwrite.c
Normal file
267
contrib/sdk/sources/newlib/libc/stdio/fvwrite.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
/* No user fns here. Pesch 15apr92. */
|
||||
|
||||
#include <_ansi.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "local.h"
|
||||
#include "fvwrite.h"
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define COPY(n) _CAST_VOID memmove ((_PTR) fp->_p, (_PTR) p, (size_t) (n))
|
||||
|
||||
#define GETIOV(extra_work) \
|
||||
while (len == 0) \
|
||||
{ \
|
||||
extra_work; \
|
||||
p = iov->iov_base; \
|
||||
len = iov->iov_len; \
|
||||
iov++; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Write some memory regions. Return zero on success, EOF on error.
|
||||
*
|
||||
* This routine is large and unsightly, but most of the ugliness due
|
||||
* to the three different kinds of output buffering is handled here.
|
||||
*/
|
||||
|
||||
int
|
||||
_DEFUN(__sfvwrite_r, (ptr, fp, uio),
|
||||
struct _reent *ptr _AND
|
||||
register FILE *fp _AND
|
||||
register struct __suio *uio)
|
||||
{
|
||||
register size_t len;
|
||||
register _CONST char *p = NULL;
|
||||
register struct __siov *iov;
|
||||
register int w, s;
|
||||
char *nl;
|
||||
int nlknown, nldist;
|
||||
|
||||
if ((len = uio->uio_resid) == 0)
|
||||
return 0;
|
||||
|
||||
/* make sure we can write */
|
||||
if (cantwrite (ptr, fp))
|
||||
return EOF;
|
||||
|
||||
iov = uio->uio_iov;
|
||||
len = 0;
|
||||
|
||||
#ifdef __SCLE
|
||||
if (fp->_flags & __SCLE) /* text mode */
|
||||
{
|
||||
do
|
||||
{
|
||||
GETIOV (;);
|
||||
while (len > 0)
|
||||
{
|
||||
if (putc (*p, fp) == EOF)
|
||||
return EOF;
|
||||
p++;
|
||||
len--;
|
||||
uio->uio_resid--;
|
||||
}
|
||||
}
|
||||
while (uio->uio_resid > 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fp->_flags & __SNBF)
|
||||
{
|
||||
/*
|
||||
* Unbuffered: write up to BUFSIZ bytes at a time.
|
||||
*/
|
||||
do
|
||||
{
|
||||
GETIOV (;);
|
||||
w = fp->_write (ptr, fp->_cookie, p, MIN (len, BUFSIZ));
|
||||
if (w <= 0)
|
||||
goto err;
|
||||
p += w;
|
||||
len -= w;
|
||||
}
|
||||
while ((uio->uio_resid -= w) != 0);
|
||||
}
|
||||
else if ((fp->_flags & __SLBF) == 0)
|
||||
{
|
||||
/*
|
||||
* Fully buffered: fill partially full buffer, if any,
|
||||
* and then flush. If there is no partial buffer, write
|
||||
* one _bf._size byte chunk directly (without copying).
|
||||
*
|
||||
* String output is a special case: write as many bytes
|
||||
* as fit, but pretend we wrote everything. This makes
|
||||
* snprintf() return the number of bytes needed, rather
|
||||
* than the number used, and avoids its write function
|
||||
* (so that the write function can be invalid). If
|
||||
* we are dealing with the asprintf routines, we will
|
||||
* dynamically increase the buffer size as needed.
|
||||
*/
|
||||
do
|
||||
{
|
||||
GETIOV (;);
|
||||
w = fp->_w;
|
||||
if (fp->_flags & __SSTR)
|
||||
{
|
||||
if (len >= w && fp->_flags & (__SMBF | __SOPT))
|
||||
{ /* must be asprintf family */
|
||||
unsigned char *str;
|
||||
int curpos = (fp->_p - fp->_bf._base);
|
||||
/* Choose a geometric growth factor to avoid
|
||||
quadratic realloc behavior, but use a rate less
|
||||
than (1+sqrt(5))/2 to accomodate malloc
|
||||
overhead. asprintf EXPECTS us to overallocate, so
|
||||
that it can add a trailing \0 without
|
||||
reallocating. The new allocation should thus be
|
||||
max(prev_size*1.5, curpos+len+1). */
|
||||
int newsize = fp->_bf._size * 3 / 2;
|
||||
if (newsize < curpos + len + 1)
|
||||
newsize = curpos + len + 1;
|
||||
if (fp->_flags & __SOPT)
|
||||
{
|
||||
/* asnprintf leaves original buffer alone. */
|
||||
str = (unsigned char *)_malloc_r (ptr, newsize);
|
||||
if (!str)
|
||||
{
|
||||
ptr->_errno = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
memcpy (str, fp->_bf._base, curpos);
|
||||
fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
|
||||
newsize);
|
||||
if (!str)
|
||||
{
|
||||
/* Free buffer which is no longer used. */
|
||||
_free_r (ptr, fp->_bf._base);
|
||||
/* Ensure correct errno, even if free changed it. */
|
||||
ptr->_errno = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
fp->_bf._base = str;
|
||||
fp->_p = str + curpos;
|
||||
fp->_bf._size = newsize;
|
||||
w = len;
|
||||
fp->_w = newsize - curpos;
|
||||
}
|
||||
if (len < w)
|
||||
w = len;
|
||||
COPY (w); /* copy MIN(fp->_w,len), */
|
||||
fp->_w -= w;
|
||||
fp->_p += w;
|
||||
w = len; /* but pretend copied all */
|
||||
}
|
||||
else if (fp->_p > fp->_bf._base && len > w)
|
||||
{
|
||||
/* fill and flush */
|
||||
COPY (w);
|
||||
/* fp->_w -= w; *//* unneeded */
|
||||
fp->_p += w;
|
||||
if (_fflush_r (ptr, fp))
|
||||
goto err;
|
||||
}
|
||||
else if (len >= (w = fp->_bf._size))
|
||||
{
|
||||
/* write directly */
|
||||
w = fp->_write (ptr, fp->_cookie, p, w);
|
||||
if (w <= 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fill and done */
|
||||
w = len;
|
||||
COPY (w);
|
||||
fp->_w -= w;
|
||||
fp->_p += w;
|
||||
}
|
||||
p += w;
|
||||
len -= w;
|
||||
}
|
||||
while ((uio->uio_resid -= w) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Line buffered: like fully buffered, but we
|
||||
* must check for newlines. Compute the distance
|
||||
* to the first newline (including the newline),
|
||||
* or `infinity' if there is none, then pretend
|
||||
* that the amount to write is MIN(len,nldist).
|
||||
*/
|
||||
nlknown = 0;
|
||||
nldist = 0;
|
||||
do
|
||||
{
|
||||
GETIOV (nlknown = 0);
|
||||
if (!nlknown)
|
||||
{
|
||||
nl = memchr ((_PTR) p, '\n', len);
|
||||
nldist = nl ? nl + 1 - p : len + 1;
|
||||
nlknown = 1;
|
||||
}
|
||||
s = MIN (len, nldist);
|
||||
w = fp->_w + fp->_bf._size;
|
||||
if (fp->_p > fp->_bf._base && s > w)
|
||||
{
|
||||
COPY (w);
|
||||
/* fp->_w -= w; */
|
||||
fp->_p += w;
|
||||
if (_fflush_r (ptr, fp))
|
||||
goto err;
|
||||
}
|
||||
else if (s >= (w = fp->_bf._size))
|
||||
{
|
||||
w = fp->_write (ptr, fp->_cookie, p, w);
|
||||
if (w <= 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = s;
|
||||
COPY (w);
|
||||
fp->_w -= w;
|
||||
fp->_p += w;
|
||||
}
|
||||
if ((nldist -= w) == 0)
|
||||
{
|
||||
/* copied the newline: flush and forget */
|
||||
if (_fflush_r (ptr, fp))
|
||||
goto err;
|
||||
nlknown = 0;
|
||||
}
|
||||
p += w;
|
||||
len -= w;
|
||||
}
|
||||
while ((uio->uio_resid -= w) != 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
fp->_flags |= __SERR;
|
||||
return EOF;
|
||||
}
|
Reference in New Issue
Block a user