summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdio/nano-vfscanf_i.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdio/nano-vfscanf_i.c')
-rw-r--r--newlib/libc/stdio/nano-vfscanf_i.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/newlib/libc/stdio/nano-vfscanf_i.c b/newlib/libc/stdio/nano-vfscanf_i.c
new file mode 100644
index 000000000..aba74b0d8
--- /dev/null
+++ b/newlib/libc/stdio/nano-vfscanf_i.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2012-2014 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <newlib.h>
+#include <ctype.h>
+#include <wctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include "local.h"
+#include "../stdlib/local.h"
+
+#include "nano-vfscanf_local.h"
+
+int
+_scanf_chars (struct _reent *rptr,
+ struct _scan_data_t *pdata,
+ FILE *fp, va_list *ap)
+{
+ int n;
+ char *p;
+
+ if (pdata->width == 0)
+ pdata->width = (pdata->code == CT_CHAR) ? 1 : (size_t)~0;
+
+ n = 0;
+ if ((pdata->flags & SUPPRESS) == 0)
+ p = GET_ARG (N, *ap, char *);
+
+ /* It's impossible to have EOF when we get here. */
+ while ((pdata->code == CT_CHAR)
+ || (pdata->code == CT_CCL && pdata->ccltab[*fp->_p])
+ || (pdata->code == CT_STRING && !isspace (*fp->_p)))
+ {
+ n++;
+ if ((pdata->flags & SUPPRESS) == 0)
+ *p++ = *fp->_p;
+
+ fp->_r--, fp->_p++;
+ if (--pdata->width == 0)
+ break;
+
+ if ((fp->_r <= 0 && pdata->pfn_refill (rptr, fp)))
+ break;
+ }
+ /* For CT_CHAR, it is impossible to have input_failure(n == 0) here.
+ For CT_CCL, it is impossible to have input_failure here.
+ For CT_STRING, it is possible to have empty string. */
+ if (n == 0 && pdata->code == CT_CCL)
+ return MATCH_FAILURE;
+
+ if ((pdata->flags & SUPPRESS) == 0)
+ {
+ pdata->nassigned++;
+ if (pdata->code != CT_CHAR)
+ *p = 0;
+ }
+ pdata->nread += n;
+ return 0;
+}
+int
+_scanf_i (struct _reent *rptr,
+ struct _scan_data_t *pdata,
+ FILE *fp, va_list *ap)
+{
+#define CCFN_PARAMS _PARAMS((struct _reent *, const char *, char **, int))
+ /* Conversion function (strtol/strtoul). */
+ u_long (*ccfn)CCFN_PARAMS=0;
+ char *p;
+ int n;
+ char *xdigits = "A-Fa-f8901234567]";
+ char *prefix_chars[3] = {"+-", "00", "xX"};
+
+ /* Scan an integer as if by strtol/strtoul. */
+ unsigned width_left = 0;
+ int skips = 0;
+
+ ccfn = (pdata->code == CT_INT) ? (u_long (*)CCFN_PARAMS)_strtol_r : _strtoul_r;
+#ifdef hardway
+ if (pdata->width == 0 || pdata->width > BUF - 1)
+#else
+ /* size_t is unsigned, hence this optimisation. */
+ if (pdata->width - 1 > BUF - 2)
+#endif
+ {
+ width_left = pdata->width - (BUF - 1);
+ pdata->width = BUF - 1;
+ }
+ p = pdata->buf;
+ pdata->flags |= NDIGITS | NZDIGITS | NNZDIGITS;
+
+ /* Process [sign] [0] [xX] prefixes sequently. */
+ for (n = 0; n < 3; n++)
+ {
+ if (!memchr (prefix_chars[n], *fp->_p, 2))
+ continue;
+
+ if (n == 1)
+ {
+ if (pdata->base == 0)
+ {
+ pdata->base = 8;
+ pdata->flags |= PFXOK;
+ }
+ pdata->flags &= ~(NZDIGITS | NDIGITS);
+ }
+ else if (n == 2)
+ {
+ if ((pdata->flags & (PFXOK | NZDIGITS)) != PFXOK)
+ continue;
+ pdata->base = 16;
+
+ /* We must reset the NZDIGITS and NDIGITS
+ flags that would have been unset by seeing
+ the zero that preceded the X or x.
+
+ ??? It seems unnecessary to reset the NZDIGITS. */
+ pdata->flags |= NDIGITS;
+ }
+ if (pdata->width-- > 0)
+ {
+ *p++ = *fp->_p++;
+ fp->_r--;
+ if ((fp->_r <= 0 && pdata->pfn_refill (rptr, fp)))
+ goto match_end;
+ }
+ }
+
+ if (pdata->base == 0)
+ pdata->base = 10;
+
+ /* The check is un-necessary if xdigits points to exactly the string:
+ "A-Fa-f8901234567]". The code is kept only for reading's sake. */
+#if 0
+ if (pdata->base != 16)
+#endif
+ xdigits = xdigits + 16 - pdata->base;
+
+ /* Initilize ccltab according to pdata->base. */
+ __sccl (pdata->ccltab, (unsigned char *) xdigits);
+ for (; pdata->width; pdata->width--)
+ {
+ n = *fp->_p;
+ if (pdata->ccltab[n] == 0)
+ break;
+ else if (n == '0' && (pdata->flags & NNZDIGITS))
+ {
+ ++skips;
+ if (width_left)
+ {
+ width_left--;
+ pdata->width++;
+ }
+ goto skip;
+ }
+ pdata->flags &= ~(NDIGITS | NNZDIGITS);
+ /* Char is legal: store it and look at the next. */
+ *p++ = *fp->_p;
+skip:
+ if (--fp->_r > 0)
+ fp->_p++;
+ else if (pdata->pfn_refill (rptr, fp))
+ /* "EOF". */
+ break;
+ }
+ /* If we had only a sign, it is no good; push back the sign.
+ If the number ends in `x', it was [sign] '0' 'x', so push back
+ the x and treat it as [sign] '0'.
+ Use of ungetc here and below assumes ASCII encoding; we are only
+ pushing back 7-bit characters, so casting to unsigned char is
+ not necessary. */
+match_end:
+ if (pdata->flags & NDIGITS)
+ {
+ if (p > pdata->buf)
+ pdata->pfn_ungetc (rptr, *--p, fp); /* "[-+xX]". */
+
+ if (p == pdata->buf)
+ return MATCH_FAILURE;
+ }
+ if ((pdata->flags & SUPPRESS) == 0)
+ {
+ u_long ul;
+ *p = 0;
+ ul = (*ccfn) (rptr, pdata->buf, (char **) NULL, pdata->base);
+ if (pdata->flags & POINTER)
+ *GET_ARG (N, *ap, void **) = (void *) (uintptr_t) ul;
+ else if (pdata->flags & SHORT)
+ *GET_ARG (N, *ap, short *) = ul;
+ else if (pdata->flags & LONG)
+ *GET_ARG (N, *ap, long *) = ul;
+ else
+ *GET_ARG (N, *ap, int *) = ul;
+
+ pdata->nassigned++;
+ }
+ pdata->nread += p - pdata->buf + skips;
+ return 0;
+}
+