diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2008-04-14 21:14:55 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2008-04-14 21:14:55 +0000 |
commit | eabd7de028075f106e1434bf9efd91a5fd32129f (patch) | |
tree | 0f40f0f7c842dbbdab04f15c7dcdcce5d964f290 /newlib/libc/stdio/vfscanf.c | |
parent | a7b6c156deb51bc349193bafbf4e3d0a439e53f0 (diff) | |
download | cygnal-eabd7de028075f106e1434bf9efd91a5fd32129f.tar.gz cygnal-eabd7de028075f106e1434bf9efd91a5fd32129f.tar.bz2 cygnal-eabd7de028075f106e1434bf9efd91a5fd32129f.zip |
2008-04-14 Jeff Johnston <jjohnstn@redhat.com>
* libc/stdio/Makefile.am: Build vfprintf.c and vfscanf.c with
-DSTRING_ONLY defined with and without -DINTEGER_ONLY defined
to build special versions for sprintf/sscanf family functions.
* libc/stdio/Makefile.in: Regenerated.
* libc/stdio/vfprintf.c[STRING_ONLY][INTEGER_ONLY](_VFPRINTF_R):
Redefine to be _svfiprintf_r which is optimized to work with siprintf
family of functions (i.e. no I/O) and does not support floating-point.
[STRING_ONLY][!INTEGER_ONLY](_VFPRINTF_R): Redefine to be
_svfprintf_r which is optimized to work with sprintf family of
functions and not use I/O.
[STRING_ONLY](__sprint_r): New string only version of static function.
designed to work with sprintf family of functions.
* libc/stdio/vfscanf.c[STRING_ONLY][INTEGER_ONLY](_SVFSCANF_R):
Redefine to be _ssvfiscanf_r which is optimized to work with siscanf
family of functions (i.e. no I/O) and no float-point support.
[STRING_ONLY][!INTEGER_ONLY](_SVFSCANF_R): Redefine to be
__ssvfscanf_r which is optimized to work with sscanf family of
functions and does not require I/O functions.
* libc/stdio/asprintf.c: Call _svfprintf_r instead of _vfprintf_r.
* libc/stdio/snprintf.c: Ditto.
* libc/stdio/sprintf.c: Ditto.
* libc/stdio/vasnprintf.c: Ditto.
* libc/stdio/vasprintf.c: Ditto.
* libc/stdio/siprintf.c: Call _svfiprintf_r instead of _vfiprintf_r.
* libc/stdio/sniprintf.c: Ditto.
* libc/stdio/vasiprintf.c: Ditto.
* libc/stdio/vsiprintf.c: Ditto.
* libc/stdio/vsniprintf.c: Ditto.
* libc/stdio/vsprintf.c: Ditto.
* libc/stdio/local.h: Add prototypes for _svfprintf_r, _svfiprintf_r,
_ssvfscanf_r, and _ssvfiscanf_r.
* libc/stdio/sscanf.c: Call _ssvfscanf_r instead of _svfscanf_r.
* libc/stdio/vsscanf.c: Ditto.
* libc/stdio/siscanf.c: Call _ssvfiscanf_r instead of _svfiscanf_r.
* libc/stdio/vsiscanf.c: Ditto.
Diffstat (limited to 'newlib/libc/stdio/vfscanf.c')
-rw-r--r-- | newlib/libc/stdio/vfscanf.c | 154 |
1 files changed, 151 insertions, 3 deletions
diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index 68b55f426..f56681eaa 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -121,17 +121,35 @@ Supporting OS subroutines required: #define VFSCANF vfiscanf #define _VFSCANF_R _vfiscanf_r #define __SVFSCANF __svfiscanf -#define __SVFSCANF_R __svfiscanf_r +#ifdef STRING_ONLY +# define __SVFSCANF_R __ssvfiscanf_r +#else +# define __SVFSCANF_R __svfiscanf_r +#endif #else #define VFSCANF vfscanf #define _VFSCANF_R _vfscanf_r #define __SVFSCANF __svfscanf -#define __SVFSCANF_R __svfscanf_r +#ifdef STRING_ONLY +# define __SVFSCANF_R __ssvfscanf_r +#else +# define __SVFSCANF_R __svfscanf_r +#endif #ifndef NO_FLOATING_POINT #define FLOATING_POINT #endif #endif +#ifdef STRING_ONLY +#undef _flockfile +#undef _funlockfile +#define _flockfile(x) {} +#define _funlockfile(x) {} +#define _ungetc_r _sungetc_r +#define __srefill_r __ssrefill_r +#define _fread_r _sfread_r +#endif + #ifdef FLOATING_POINT #include <math.h> #include <float.h> @@ -234,6 +252,8 @@ typedef unsigned long long u_long_long; #define BufferEmpty (fp->_r <= 0 && __srefill_r(rptr, fp)) +#ifndef STRING_ONLY + #ifndef _REENT_ONLY int @@ -267,7 +287,135 @@ _DEFUN(_VFSCANF_R, (data, fp, fmt, ap), CHECK_INIT(data, fp); return __SVFSCANF_R (data, fp, fmt, ap); } +#endif /* !STRING_ONLY */ + +#ifdef STRING_ONLY +/* When dealing with the sscanf family, we don't want to use the + * regular ungetc which will drag in file I/O items we don't need. + * So, we create our own trimmed-down version. */ +static int +_DEFUN(_sungetc_r, (data, fp, ch), + struct _reent *data _AND + int c _AND + register FILE *fp) +{ + if (c == EOF) + return (EOF); + /* After ungetc, we won't be at eof anymore */ + fp->_flags &= ~__SEOF; + c = (unsigned char) c; + + /* + * If we are in the middle of ungetc'ing, just continue. + * This may require expanding the current ungetc buffer. + */ + + if (HASUB (fp)) + { + if (fp->_r >= fp->_ub._size && __submore (data, fp)) + { + return EOF; + } + *--fp->_p = c; + fp->_r++; + return c; + } + + /* + * If we can handle this by simply backing up, do so, + * but never replace the original character. + * (This makes sscanf() work when scanning `const' data.) + */ + + if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c) + { + fp->_p--; + fp->_r++; + return c; + } + + /* + * Create an ungetc buffer. + * Initially, we will use the `reserve' buffer. + */ + + fp->_ur = fp->_r; + fp->_up = fp->_p; + fp->_ub._base = fp->_ubuf; + fp->_ub._size = sizeof (fp->_ubuf); + fp->_ubuf[sizeof (fp->_ubuf) - 1] = c; + fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1]; + fp->_r = 1; + return c; +} + +/* String only version of __srefill_r for sscanf family. */ +static int +_DEFUN(__ssrefill_r, (ptr, fp), + struct _reent * ptr _AND + register FILE * fp) +{ + /* + * Our only hope of further input is the ungetc buffer. + * If there is anything in that buffer to read, return. + */ + if (HASUB (fp)) + { + FREEUB (ptr, fp); + if ((fp->_r = fp->_ur) != 0) + { + fp->_p = fp->_up; + return 0; + } + } + + /* Otherwise we are out of character input. */ + fp->_p = fp->_bf._base; + fp->_r = 0; + fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ + fp->_flags |= __SEOF; + return EOF; +} + +static size_t +_DEFUN(_sfread_r, (ptr, buf, size, count, fp), + struct _reent * ptr _AND + _PTR buf _AND + size_t size _AND + size_t count _AND + FILE * fp) +{ + register size_t resid; + register char *p; + register int r; + size_t total; + + if ((resid = count * size) == 0) + return 0; + + total = resid; + p = buf; + + while (resid > (r = fp->_r)) + { + _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r); + fp->_p += r; + fp->_r = 0; + p += r; + resid -= r; + if (__ssrefill_r (ptr, fp)) + { + /* no more input: return partial result */ + return (total - resid) / size; + } + } + _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid); + fp->_r -= resid; + fp->_p += resid; + return count; +} +#endif /* STRING_ONLY */ int _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), @@ -741,7 +889,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), } else { - size_t r = fread ((_PTR) GET_ARG (N, ap, char *), 1, width, fp); + size_t r = _fread_r (rptr, (_PTR) GET_ARG (N, ap, char *), 1, width, fp); if (r == 0) goto input_failure; |