summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdio/vfscanf.c
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2008-04-14 21:14:55 +0000
committerJeff Johnston <jjohnstn@redhat.com>2008-04-14 21:14:55 +0000
commiteabd7de028075f106e1434bf9efd91a5fd32129f (patch)
tree0f40f0f7c842dbbdab04f15c7dcdcce5d964f290 /newlib/libc/stdio/vfscanf.c
parenta7b6c156deb51bc349193bafbf4e3d0a439e53f0 (diff)
downloadcygnal-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.c154
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;