diff options
author | Peter S. Mazinger <ps.m@gmx.net> | 2006-02-13 07:36:40 +0000 |
---|---|---|
committer | Peter S. Mazinger <ps.m@gmx.net> | 2006-02-13 07:36:40 +0000 |
commit | caed8420ef5be27f4b6e2b07a39e21642e6d1ceb (patch) | |
tree | 965f11d1f2103eeda2d09448bbbcbc1848a37855 /libc/stdio/scanf.c | |
parent | 5ba9a00a29564ec74925f9acbba7753b004facf0 (diff) |
More renames for IMA
Diffstat (limited to 'libc/stdio/scanf.c')
-rw-r--r-- | libc/stdio/scanf.c | 2268 |
1 files changed, 0 insertions, 2268 deletions
diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c deleted file mode 100644 index df78e7ad3..000000000 --- a/libc/stdio/scanf.c +++ /dev/null @@ -1,2268 +0,0 @@ -/* Copyright (C) 2002-2004 Manuel Novoa III - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Aug 1, 2003 - * New *scanf implementation with lots of bug fixes and *wscanf support. - * Also now optionally supports hexadecimal float notation, positional - * args, and glibc locale-specific digit grouping. Should now be - * standards compliant. - * - * Aug 18, 2003 - * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error, - * even when just starting a new mb char. - * Bug fix: wscanf would incorrectly unget in certain situations. - * - * Sep 5, 2003 - * Bug fix: store flag wasn't respected if no positional args. - * Implement vs{n}scanf for the non-buffered stdio no-wchar case. - * - * Sep 13, 2003 - * Bug fix: Fix a problem reported by Atsushi Nemoto <anemo@mba.ocn.ne.jp> - * for environments where long and long long are the same. - * - * Sep 21, 2003 - * Ugh... EOF handling by scanf was completely broken. :-( Regretably, - * I got my mind fixed in one mode and didn't comply with the standards. - * Things should be fixed now, but comparision testing is difficult when - * glibc's scanf is broken and they stubbornly refuse to even acknowledge - * that it is... even when confronted by specific examples from the C99 - * standards and from an official C standard defect report. - */ - -#define _ISOC99_SOURCE /* for LLONG_MAX primarily... */ -#include <features.h> -#include "_stdio.h" -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <stdarg.h> -#include <stdint.h> -#include <errno.h> -#include <printf.h> - -#ifdef __UCLIBC_HAS_WCHAR__ -#include <bits/uClibc_uwchar.h> -#include <wchar.h> -#include <wctype.h> -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#include <langinfo.h> -#include <locale.h> - -#include <assert.h> -#include <limits.h> - -#ifdef __UCLIBC_HAS_THREADS__ -#include <stdio_ext.h> -#include <pthread.h> -#endif /* __UCLIBC_HAS_THREADS__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ -#include <float.h> -#include <bits/uClibc_fpmax.h> -#endif /* __UCLIBC_HAS_FLOATS__ */ - -libc_hidden_proto(memcmp) -libc_hidden_proto(memset) -libc_hidden_proto(strcpy) -libc_hidden_proto(strlen) -libc_hidden_proto(ungetc) -libc_hidden_proto(vfscanf) -libc_hidden_proto(vsscanf) -libc_hidden_proto(fclose) -libc_hidden_proto(getc_unlocked) -libc_hidden_proto(__fgetc_unlocked) -#ifdef __UCLIBC_HAS_WCHAR__ -libc_hidden_proto(wcslen) -libc_hidden_proto(vfwscanf) -libc_hidden_proto(vswscanf) -libc_hidden_proto(mbsrtowcs) -libc_hidden_proto(mbrtowc) -libc_hidden_proto(wcrtomb) -libc_hidden_proto(ungetwc) -libc_hidden_proto(iswspace) -libc_hidden_proto(fgetwc_unlocked) -#endif -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -#else -#ifdef __UCLIBC_HAS_LOCALE__ -libc_hidden_proto(__global_locale) -#endif -libc_hidden_proto(__ctype_b) -#endif - -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#ifdef L_vfscanf -/* only emit this once */ -#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented! -#endif -#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#endif - -#undef __STDIO_HAS_VSSCANF -#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) -#define __STDIO_HAS_VSSCANF 1 - -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) -typedef struct { - FILE f; - unsigned char *bufread; /* pointer to 1 past end of buffer */ - unsigned char *bufpos; -} __FILE_vsscanf; -#endif - -#endif - -extern void _store_inttype(void *dest, int desttype, uintmax_t val); - -#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) - -extern unsigned long long -_stdlib_strto_ll(register const char * __restrict str, - char ** __restrict endptr, int base, int sflag); -#if (ULLONG_MAX == UINTMAX_MAX) -#define STRTOUIM(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf) -#endif - -#else /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ - -extern unsigned long -_stdlib_strto_l(register const char * __restrict str, - char ** __restrict endptr, int base, int sflag); - -#if (ULONG_MAX == UINTMAX_MAX) -#define STRTOUIM(s,e,b,sf) _stdlib_strto_l(s,e,b,sf) -#endif - -#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ - -#ifndef STRTOUIM -#error STRTOUIM conversion function is undefined! -#endif - -/**********************************************************************/ - -/* The standards require EOF < 0. */ -#if EOF >= CHAR_MIN -#define __isdigit_char_or_EOF(C) __isdigit_char((C)) -#else -#define __isdigit_char_or_EOF(C) __isdigit_int((C)) -#endif - -/**********************************************************************/ -#ifdef L_fscanf - -libc_hidden_proto(fscanf) -int fscanf(FILE * __restrict stream, const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vfscanf(stream, format, arg); - va_end(arg); - - return rv; -} -libc_hidden_def(fscanf) - -#endif -/**********************************************************************/ -#ifdef L_scanf - -int scanf(const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vfscanf(stdin, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_sscanf - -#ifdef __STDIO_HAS_VSSCANF - -libc_hidden_proto(sscanf) -int sscanf(const char * __restrict str, const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vsscanf(str, format, arg); - va_end(arg); - - return rv; -} -libc_hidden_def(sscanf) - -#else /* __STDIO_HAS_VSSCANF */ -#warning Skipping sscanf since no vsscanf! -#endif /* __STDIO_HAS_VSSCANF */ - -#endif -/**********************************************************************/ -#ifdef L_vscanf - -libc_hidden_proto(vscanf) -int vscanf(const char * __restrict format, va_list arg) -{ - return vfscanf(stdin, format, arg); -} -libc_hidden_def(vscanf) - -#endif -/**********************************************************************/ -#ifdef L_vsscanf - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning WISHLIST: Implement vsscanf for non-buf and no custom stream case. -#endif /* __UCLIBC_MJN3_ONLY__ */ - -#ifdef __STDIO_BUFFERS - -int vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - FILE f; - -/* __STDIO_STREAM_RESET_GCS(&f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.__cookie = &(f.__filedes); - f.__gcs.read = NULL; - f.__gcs.write = NULL; - f.__gcs.seek = NULL; - f.__gcs.close = NULL; -#endif - - f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES; - f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); - -#ifdef __UCLIBC_HAS_WCHAR__ - f.__ungot_width[0] = 0; -#endif -#ifdef __STDIO_MBSTATE - __INIT_MBSTATE(&(f.__state)); -#endif - -#ifdef __UCLIBC_HAS_THREADS__ - f.__user_locking = 1; /* Set user locking. */ - __stdio_init_mutex(&f.__lock); -#endif - f.__nextopen = NULL; - - /* Set these last since __bufgetc initialization depends on - * __user_locking and only gets set if user locking is on. */ - f.__bufstart = - f.__bufpos = (unsigned char *) ((void *) sp); - f.__bufread = - f.__bufend = f.__bufstart + strlen(sp); - __STDIO_STREAM_ENABLE_GETC(&f); - __STDIO_STREAM_DISABLE_PUTC(&f); - - return vfscanf(&f, fmt, ap); -} -libc_hidden_def(vsscanf) - -#elif !defined(__UCLIBC_HAS_WCHAR__) - -int vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - __FILE_vsscanf f; - - f.bufpos = (unsigned char *) ((void *) sp); - f.bufread = f.bufpos + strlen(sp); - -/* __STDIO_STREAM_RESET_GCS(&f.f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.f.__cookie = &(f.f.__filedes); - f.f.__gcs.read = NULL; - f.f.__gcs.write = NULL; - f.f.__gcs.seek = NULL; - f.f.__gcs.close = NULL; -#endif - - f.f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB; - f.f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); - -/* #ifdef __UCLIBC_HAS_WCHAR__ */ -/* f.f.__ungot_width[0] = 0; */ -/* #endif */ -#ifdef __STDIO_MBSTATE -#error __STDIO_MBSTATE is defined! -/* __INIT_MBSTATE(&(f.f.__state)); */ -#endif - -#ifdef __UCLIBC_HAS_THREADS__ - f.f.__user_locking = 1; /* Set user locking. */ - __stdio_init_mutex(&f.f.__lock); -#endif - f.f.__nextopen = NULL; - - return vfscanf(&f.f, fmt, ap); -} -libc_hidden_def(vsscanf) - -#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) - -int vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - FILE *f; - int rv = EOF; - - if ((f = fmemopen((char *)sp, strlen(sp), "r")) != NULL) { - rv = vfscanf(f, fmt, ap); - fclose(f); - } - - return rv; -} -libc_hidden_def(vsscanf) - -#else -#warning Skipping vsscanf since no buffering, no custom streams, and wchar enabled! -#ifdef __STDIO_HAS_VSSCANF -#error WHOA! __STDIO_HAS_VSSCANF is defined! -#endif -#endif - -#endif -/**********************************************************************/ -#ifdef L_fwscanf - -int fwscanf(FILE * __restrict stream, const wchar_t * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vfwscanf(stream, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_wscanf - -int wscanf(const wchar_t * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vfwscanf(stdin, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_swscanf - -#ifdef __STDIO_BUFFERS - -int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, - ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = vswscanf(str, format, arg); - va_end(arg); - - return rv; -} -#else /* __STDIO_BUFFERS */ -#warning Skipping swscanf since no buffering! -#endif /* __STDIO_BUFFERS */ - -#endif -/**********************************************************************/ -#ifdef L_vwscanf - -int vwscanf(const wchar_t * __restrict format, va_list arg) -{ - return vfwscanf(stdin, format, arg); -} - -#endif -/**********************************************************************/ -#ifdef L_vswscanf - -#ifdef __STDIO_BUFFERS - -int vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, - va_list arg) -{ - FILE f; - - f.__bufstart = - f.__bufpos = (char *) str; - f.__bufread = - f.__bufend = (char *)(str + wcslen(str)); - __STDIO_STREAM_DISABLE_GETC(&f); - __STDIO_STREAM_DISABLE_PUTC(&f); - -/* __STDIO_STREAM_RESET_GCS(&f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.__cookie = &(f.__filedes); - f.__gcs.read = NULL; - f.__gcs.write = NULL; - f.__gcs.seek = NULL; - f.__gcs.close = NULL; -#endif - - f.__filedes = __STDIO_STREAM_FAKE_VSWSCANF_FILEDES; - f.__modeflags = (__FLAG_WIDE|__FLAG_READONLY|__FLAG_READING); - -#ifdef __UCLIBC_HAS_WCHAR__ - f.__ungot_width[0] = 0; -#endif /* __UCLIBC_HAS_WCHAR__ */ -#ifdef __STDIO_MBSTATE - __INIT_MBSTATE(&(f.__state)); -#endif /* __STDIO_MBSTATE */ - -#ifdef __UCLIBC_HAS_THREADS__ - f.__user_locking = 1; /* Set user locking. */ - __stdio_init_mutex(&f.__lock); -#endif - f.__nextopen = NULL; - - return vfwscanf(&f, format, arg); -} -libc_hidden_def(vswscanf) -#else /* __STDIO_BUFFERS */ -#warning Skipping vswscanf since no buffering! -#endif /* __STDIO_BUFFERS */ - -#endif -/**********************************************************************/ -/**********************************************************************/ - - - -/* float layout 0123456789012345678901 repeat n for "l[" */ -#define SPEC_CHARS "npxXoudifFeEgGaACSncs[" -/* npxXoudif eEgG CS cs[ */ - -/* NOTE: Ordering is important! In particular, CONV_LEFTBRACKET - * must immediately precede CONV_c. */ - -enum { - CONV_n = 0, - CONV_p, - CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, - CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, - CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket, - CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */ -}; - -#ifdef __UCLIBC_HAS_FLOATS__ -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -#else -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10 } -#endif -#else /* __UCLIBC_HAS_FLOATS__ */ -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0 } -#endif /* __UCLIBC_HAS_FLOATS__ */ - -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfscanf -/* emit once */ -#warning CONSIDER: Add a '0' flag to eat 0 padding when grouping? -#endif -#endif /* __UCLIBC_MJN3_ONLY__ */ - -#define SPEC_FLAGS "*'I" - -enum { - FLAG_SURPRESS = 0x10, /* MUST BE 1ST!! See DO_FLAGS. */ - FLAG_THOUSANDS = 0x20, - FLAG_I18N = 0x40, /* only works for d, i, u */ - FLAG_MALLOC = 0x80, /* only works for s, S, and [ (and l[)*/ -}; - - -#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ - CONV_C, CONV_LEFTBRACKET, \ - CONV_c, CONV_leftbracket } - -/* Note: We treat L and ll as synonymous... for ints and floats. */ - -#define SPEC_ALLOWED_FLAGS { \ - /* n */ (0x0f|FLAG_SURPRESS), \ - /* p */ ( 0|FLAG_SURPRESS), \ - /* oxXudi */ (0x0f|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ - /* fFeEgGaA */ (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ - /* C */ ( 0|FLAG_SURPRESS), \ - /* S and l[ */ ( 0|FLAG_SURPRESS|FLAG_MALLOC), \ - /* c */ (0x04|FLAG_SURPRESS), \ - /* s and [ */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \ -} - - -/**********************************************************************/ -/* - * In order to ease translation to what arginfo and _print_info._flags expect, - * we map: 0:int 1:char 2:longlong 4:long 8:short - * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) - */ - -/* TODO -- Fix the table below to take into account stdint.h. */ -/* #ifndef LLONG_MAX */ -/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ -/* #else */ -/* #if LLONG_MAX != INTMAX_MAX */ -/* #error fix QUAL_CHARS intmax_t entry 'j'! */ -/* #endif */ -/* #endif */ - -#ifdef PDS -#error PDS already defined! -#endif -#ifdef SS -#error SS already defined! -#endif -#ifdef IMS -#error IMS already defined! -#endif - -#if PTRDIFF_MAX == INT_MAX -#define PDS 0 -#elif PTRDIFF_MAX == LONG_MAX -#define PDS 4 -#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) -#define PDS 8 -#else -#error fix QUAL_CHARS ptrdiff_t entry 't'! -#endif - -#if SIZE_MAX == UINT_MAX -#define SS 0 -#elif SIZE_MAX == ULONG_MAX -#define SS 4 -#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) -#define SS 8 -#else -#error fix QUAL_CHARS size_t entries 'z', 'Z'! -#endif - -#if INTMAX_MAX == INT_MAX -#define IMS 0 -#elif INTMAX_MAX == LONG_MAX -#define IMS 4 -#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) -#define IMS 8 -#else -#error fix QUAL_CHARS ptrdiff_t entry 't'! -#endif - -#define QUAL_CHARS { \ - /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int q:long_long */ \ - 'h', 'l', 'L', 'j', 'z', 't', 'q', 0, \ - 2, 4, 8, IMS, SS, PDS, 8, 0, /* TODO -- fix!!! */\ - 1, 8 } - - -/**********************************************************************/ - -#ifdef L_vfwscanf -#if WINT_MIN > EOF -#error Unfortunately, we currently need wint_t to be able to store EOF. Sorry. -#endif -#define W_EOF WEOF -#define Wint wint_t -#define Wchar wchar_t -#define Wuchar __uwchar_t -#define ISSPACE(C) iswspace((C)) -#define VFSCANF vfwscanf -#define GETC(SC) (SC)->sc_getc((SC)) -#else -typedef unsigned char __uchar_t; -#define W_EOF EOF -#define Wint int -#define Wchar char -#define Wuchar __uchar_t -#define ISSPACE(C) isspace((C)) -#define VFSCANF vfscanf -#ifdef __UCLIBC_HAS_WCHAR__ -#define GETC(SC) (SC)->sc_getc((SC)) -#else /* __UCLIBC_HAS_WCHAR__ */ -#define GETC(SC) getc_unlocked((SC)->fp) -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif - -struct scan_cookie { - Wint cc; - Wint ungot_char; - FILE *fp; - int nread; - int width; - -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t app_ungot; /* Match FILE struct member type. */ - unsigned char ungot_wchar_width; -#else /* __UCLIBC_HAS_WCHAR__ */ - unsigned char app_ungot; /* Match FILE struct member type. */ -#endif /* __UCLIBC_HAS_WCHAR__ */ - - char ungot_flag; - -#ifdef __UCLIBC_HAS_WCHAR__ - char ungot_wflag; /* vfwscanf */ - char mb_fail; /* vfscanf */ - mbstate_t mbstate; /* vfscanf */ - wint_t wc; - wint_t ungot_wchar; /* to support __scan_getc */ - int (*sc_getc)(struct scan_cookie *); -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - const char *grouping; - const unsigned char *thousands_sep; - int tslen; -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t thousands_sep_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ - const unsigned char *decpt; - int decpt_len; -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t decpt_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ - const unsigned char *fake_decpt; -#endif /* __UCLIBC_HAS_FLOATS__ */ - -}; - -typedef struct { -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) -#if NL_ARGMAX > 10 -#warning NL_ARGMAX > 10, and space is allocated on the stack for positional args. -#endif - void *pos_args[NL_ARGMAX]; - int num_pos_args; /* Must start at -1. */ - int cur_pos_arg; -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - void *cur_ptr; - const unsigned char *fmt; - int cnt, dataargtype, conv_num, max_width; - unsigned char store, flags; -} psfs_t; /* parse scanf format state */ - - -/**********************************************************************/ -/**********************************************************************/ - -extern void __init_scan_cookie(register struct scan_cookie *sc, - register FILE *fp) attribute_hidden; -extern int __scan_getc(register struct scan_cookie *sc) attribute_hidden; -extern void __scan_ungetc(register struct scan_cookie *sc) attribute_hidden; - -#ifdef __UCLIBC_HAS_FLOATS__ -extern int __scan_strtold(long double *ld, struct scan_cookie *sc); -#endif /* __UCLIBC_HAS_FLOATS__ */ - -extern int __psfs_parse_spec(psfs_t *psfs) attribute_hidden; -extern int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) attribute_hidden; - -/**********************************************************************/ -#ifdef L___scan_cookie - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Remove dependence on decpt_str and fake_decpt in stub locale mode. -#endif -#ifndef __UCLIBC_HAS_LOCALE__ -static const char decpt_str[] = "."; -#endif - -void attribute_hidden __init_scan_cookie(register struct scan_cookie *sc, - register FILE *fp) -{ - sc->fp = fp; - sc->nread = 0; - sc->ungot_flag = 0; - sc->app_ungot = ((fp->__modeflags & __FLAG_UNGOT) ? fp->__ungot[1] : 0); -#ifdef __UCLIBC_HAS_WCHAR__ - sc->ungot_wflag = 0; /* vfwscanf */ - sc->mb_fail = 0; -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (*(sc->grouping = __UCLIBC_CURLOCALE_DATA.grouping)) { - sc->thousands_sep = __UCLIBC_CURLOCALE_DATA.thousands_sep; - sc->tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; -#ifdef __UCLIBC_HAS_WCHAR__ - sc->thousands_sep_wc = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ - } -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ -#ifdef __UCLIBC_HAS_LOCALE__ - sc->decpt = __UCLIBC_CURLOCALE_DATA.decimal_point; - sc->decpt_len = __UCLIBC_CURLOCALE_DATA.decimal_point_len; -#else /* __UCLIBC_HAS_LOCALE__ */ - sc->fake_decpt = sc->decpt = decpt_str; - sc->decpt_len = 1; -#endif /* __UCLIBC_HAS_LOCALE__ */ -#ifdef __UCLIBC_HAS_WCHAR__ -#ifdef __UCLIBC_HAS_LOCALE__ - sc->decpt_wc = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; -#else - sc->decpt_wc = '.'; -#endif -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif /* __UCLIBC_HAS_FLOATS__ */ - -} - -int attribute_hidden __scan_getc(register struct scan_cookie *sc) -{ - int c; - -#ifdef __UCLIBC_HAS_WCHAR__ - assert(!sc->mb_fail); -#endif /* __UCLIBC_HAS_WCHAR__ */ - - sc->cc = EOF; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - if (sc->ungot_flag == 0) { -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) - if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { - c = GETC(sc); - } else { - __FILE_vsscanf *fv = (__FILE_vsscanf *)(sc->fp); - if (fv->bufpos < fv->bufread) { - c = *fv->bufpos++; - } else { - c = EOF; - sc->fp->__modeflags |= __FLAG_EOF; - } - } - if (c == EOF) { - sc->ungot_flag |= 2; - return -1; - } -#else - if ((c = GETC(sc)) == EOF) { - sc->ungot_flag |= 2; - return -1; - } -#endif - sc->ungot_char = c; - } else { - assert(sc->ungot_flag == 1); - sc->ungot_flag = 0; - } - - ++sc->nread; - return sc->cc = sc->ungot_char; -} - -void attribute_hidden __scan_ungetc(register struct scan_cookie *sc) -{ - ++sc->width; - if (sc->ungot_flag == 2) { /* last was EOF */ - sc->ungot_flag = 0; - sc->cc = sc->ungot_char; - } else if (sc->ungot_flag == 0) { - sc->ungot_flag = 1; - --sc->nread; - } else { - assert(0); - } -} - -#endif -/**********************************************************************/ -#ifdef L___psfs_parse_spec - -#ifdef SPEC_FLAGS -static const unsigned char spec_flags[] = SPEC_FLAGS; -#endif /* SPEC_FLAGS */ -static const unsigned char spec_chars[] = SPEC_CHARS; -static const unsigned char qual_chars[] = QUAL_CHARS; -static const unsigned char spec_ranges[] = SPEC_RANGES; -static const unsigned short spec_allowed[] = SPEC_ALLOWED_FLAGS; - -int attribute_hidden __psfs_parse_spec(register psfs_t *psfs) -{ - const unsigned char *p; - const unsigned char *fmt0 = psfs->fmt; - int i; -#ifdef SPEC_FLAGS - int j; -#endif -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - unsigned char fail = 0; - - i = 0; /* Do this here to avoid a warning. */ - - if (!__isdigit_char(*psfs->fmt)) { /* Not a positional arg. */ - fail = 1; - goto DO_FLAGS; - } - - /* parse the positional arg (or width) value */ - do { - if (i <= ((INT_MAX - 9)/10)) { - i = (i * 10) + (*psfs->fmt++ - '0'); - } - } while (__isdigit_char(*psfs->fmt)); - - if (*psfs->fmt != '$') { /* This is a max field width. */ - if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ - goto ERROR_EINVAL; - } - psfs->max_width = i; - psfs->num_pos_args = -2; - goto DO_QUALIFIER; - } - ++psfs->fmt; /* Advance past '$'. */ -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - -#if defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) - DO_FLAGS: -#endif /* defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) */ -#ifdef SPEC_FLAGS - p = spec_flags; - j = FLAG_SURPRESS; - do { - if (*p == *psfs->fmt) { - ++psfs->fmt; - psfs->flags |= j; - goto DO_FLAGS; - } - j += j; - } while (*++p); - - if (psfs->flags & FLAG_SURPRESS) { /* Suppress assignment. */ - psfs->store = 0; - goto DO_WIDTH; - } -#else /* SPEC_FLAGS */ - if (*psfs->fmt == '*') { /* Suppress assignment. */ - ++psfs->fmt; - psfs->store = 0; - goto DO_WIDTH; - } -#endif /* SPEC_FLAGS */ - - -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - if (fail) { - /* Must be a non-positional arg */ - if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ - goto ERROR_EINVAL; - } - psfs->num_pos_args = -2; - } else { - if ((psfs->num_pos_args == -2) || (((unsigned int)(--i)) >= NL_ARGMAX)) { - /* Already saw a non-pos arg or (0-based) num too large. */ - goto ERROR_EINVAL; - } - psfs->cur_pos_arg = i; - } -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - - DO_WIDTH: - for (i = 0 ; __isdigit_char(*psfs->fmt) ; ) { - if (i <= ((INT_MAX - 9)/10)) { - i = (i * 10) + (*psfs->fmt++ - '0'); - psfs->max_width = i; - } - } - -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - DO_QUALIFIER: -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - p = qual_chars; - do { - if (*psfs->fmt == *p) { - ++psfs->fmt; - break; - } - } while (*++p); - if ((p - qual_chars < 2) && (*psfs->fmt == *p)) { - p += ((sizeof(qual_chars)-2) / 2); - ++psfs->fmt; - } - psfs->dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should we validate that psfs->max_width > 0 in __psfs_parse_spec()? It would avoid whitespace consumption... -#warning CONSIDER: Should INT_MAX be a valid width (%c/%C)? See __psfs_parse_spec(). -#endif /* __UCLIBC_MJN3_ONLY__ */ - - p = spec_chars; - do { - if (*psfs->fmt == *p) { - int p_m_spec_chars = p - spec_chars; - -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#error implement gnu a flag - if ((*p == 'a') - && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's')) - ) { /* Assumes ascii for 's' and 'S' test. */ - psfs->flags |= FLAG_MALLOC; - ++psfs->fmt; - ++p; - continue; /* The related conversions follow 'a'. */ - } -#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ - - for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {} - if (((psfs->dataargtype >> 8) | psfs->flags) - & ~spec_allowed[(int)(p - spec_ranges)] - ) { - goto ERROR_EINVAL; - } - - if ((p_m_spec_chars >= CONV_c) - && (psfs->dataargtype & PA_FLAG_LONG)) { - p_m_spec_chars -= 3; /* lc -> C, ls -> S, l[ -> ?? */ - } - - psfs->conv_num = p_m_spec_chars; - return psfs->fmt - fmt0; - } - if (!*++p) { - ERROR_EINVAL: - __set_errno(EINVAL); - return -1; - } - } while(1); - - assert(0); -} - -#endif -/**********************************************************************/ -#if defined(L_vfscanf) || defined(L_vfwscanf) - -#ifdef __UCLIBC_HAS_WCHAR__ -#ifdef L_vfscanf -static int sc_getc(register struct scan_cookie *sc) -{ - return (getc_unlocked)(sc->fp); /* Disable the macro. */ -} - -static int scan_getwc(register struct scan_cookie *sc) -{ - size_t r; - int width; - wchar_t wc[1]; - char b[1]; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - width = sc->width; /* Preserve width. */ - sc->width = INT_MAX; /* MB_CUR_MAX can invoke a function. */ - - assert(!sc->mb_fail); - - r = (size_t)(-3); - while (__scan_getc(sc) >= 0) { - *b = sc->cc; - - r = mbrtowc(wc, b, 1, &sc->mbstate); - if (((ssize_t) r) >= 0) { /* Successful completion of a wc. */ - sc->wc = *wc; - goto SUCCESS; - } else if (r == ((size_t) -2)) { - /* Potentially valid but incomplete. */ - continue; - } - break; - } - - if (r == ((size_t)(-3))) { /* EOF or ERROR on first read */ - sc->wc = WEOF; - r = (size_t)(-1); - } else { - /* If we reach here, either r == ((size_t)-1) and - * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) - * and stream is in an error state or at EOF with a - * partially complete wchar. */ - __set_errno(EILSEQ); /* In case of incomplete conversion. */ - sc->mb_fail = 1; - } - - SUCCESS: - sc->width = width; /* Restore width. */ - - return (int)((ssize_t) r); -} - -#endif /* L_vfscanf */ - -#ifdef L_vfwscanf - -/* This gets called by __scan_getc. __scan_getc is called by vfwscanf - * when the next wide char is expected to be valid ascii (digits). - */ -static int sc_getc(register struct scan_cookie *sc) -{ - wint_t wc; - - if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { - if (sc->fp->__bufpos < sc->fp->__bufend) { - wc = *((wchar_t *)(sc->fp->__bufpos)); - sc->fp->__bufpos += sizeof(wchar_t); - } else { - sc->fp->__modeflags |= __FLAG_EOF; - return EOF; - } - } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { - return EOF; - } - - sc->ungot_wflag = 1; - sc->ungot_wchar = wc; - sc->ungot_wchar_width = sc->fp->__ungot_width[0]; - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (wc == sc->thousands_sep_wc) { - wc = ','; - } else -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ -#ifdef __UCLIBC_HAS_FLOATS__ - if (wc == sc->decpt_wc) { - wc = '.'; - } else -#endif /* __UCLIBC_HAS_FLOATS__ */ - if (!__isascii(wc)) { - wc = '?'; - } - sc->wc = sc->ungot_char = wc; - - return (int) wc; -} - -static int scan_getwc(register struct scan_cookie *sc) -{ - wint_t wc; - - sc->wc = WEOF; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - if (sc->ungot_flag == 0) { - if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { - if (sc->fp->__bufpos < sc->fp->__bufend) { - wc = *((wchar_t *)(sc->fp->__bufpos)); - sc->fp->__bufpos += sizeof(wchar_t); - } else { - sc->ungot_flag |= 2; - return -1; - } - } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { - sc->ungot_flag |= 2; - return -1; - } - sc->ungot_wflag = 1; - sc->ungot_char = wc; - sc->ungot_wchar_width = sc->fp->__ungot_width[0]; - } else { - assert(sc->ungot_flag == 1); - sc->ungot_flag = 0; - } - - ++sc->nread; - sc->wc = sc->ungot_char; - - return 0; -} - - -#endif /* L_vfwscanf */ -#endif /* __UCLIBC_HAS_WCHAR__ */ - -static __inline void kill_scan_cookie(register struct scan_cookie *sc) -{ -#ifdef L_vfscanf - - if (sc->ungot_flag & 1) { -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) - if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { - ungetc(sc->ungot_char, sc->fp); - } -#else - ungetc(sc->ungot_char, sc->fp); -#endif - /* Deal with distiction between user and scanf ungots. */ - if (sc->nread == 0) { /* Only one char was read... app ungot? */ - sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ - } else { - sc->fp->__ungot[1] = 0; - } - } - -#else - - if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1) - && !__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp) - && (sc->fp->__state.__mask == 0) - ) { - ungetwc(sc->ungot_char, sc->fp); - /* Deal with distiction between user and scanf ungots. */ - if (sc->nread == 0) { /* Only one char was read... app ungot? */ - sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ - } else { - sc->fp->__ungot[1] = 0; - } - sc->fp->__ungot_width[1] = sc->ungot_wchar_width; - } - -#endif -} - -#ifdef L_vfwscanf -#ifdef __UCLIBC_HAS_FLOATS__ -static const char fake_decpt_str[] = "."; -#endif -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ -static const char fake_thousands_sep_str[] = ","; -#endif -#endif /* L_vfwscanf */ - - -int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) -{ - const Wuchar *fmt; - unsigned char *b; - - -#ifdef L_vfwscanf - wchar_t wbuf[1]; - wchar_t *wb; -#endif /* L_vfwscanf */ - -#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) || !defined(L_vfscanf) - mbstate_t mbstate; -#endif |