summaryrefslogtreecommitdiff
path: root/src/pal/src/safecrt/input.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/safecrt/input.inl')
-rw-r--r--src/pal/src/safecrt/input.inl1314
1 files changed, 1314 insertions, 0 deletions
diff --git a/src/pal/src/safecrt/input.inl b/src/pal/src/safecrt/input.inl
new file mode 100644
index 0000000000..eaad174ff5
--- /dev/null
+++ b/src/pal/src/safecrt/input.inl
@@ -0,0 +1,1314 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/***
+*input.c - C formatted input, used by scanf, etc.
+*
+
+*
+*Purpose:
+* defines _input() to do formatted input; called from scanf(),
+* etc. functions. This module defines _cscanf() instead when
+* CPRFLAG is defined. The file cscanf.c defines that symbol
+* and then includes this file in order to implement _cscanf().
+*
+*Note:
+* this file is included in safecrt.lib build directly, plese refer
+* to safecrt_[w]input_s.c
+*
+*******************************************************************************/
+
+
+#define ALLOW_RANGE /* enable "%[a-z]"-style scansets */
+
+
+/* temporary work-around for compiler without 64-bit support */
+
+#ifndef _INTEGRAL_MAX_BITS
+#define _INTEGRAL_MAX_BITS 64
+#endif /* _INTEGRAL_MAX_BITS */
+
+// typedef __int64_t __int64;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define UNALIGNED
+
+#define _BEGIN_SECURE_CRT_DEPRECATION_DISABLE
+#define _END_SECURE_CRT_DEPRECATION_DISABLE
+
+#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */
+
+//#include <cruntime.h>
+//#include <stdio.h>
+//#include <ctype.h>
+//#include <cvt.h>
+//#include <conio.h>
+//#include <stdarg.h>
+//#include <string.h>
+//#include <internal.h>
+//#include <fltintrn.h>
+//#include <malloc.h>
+//#include <locale.h>
+//#include <mtdll.h>
+//#include <stdlib.h>
+//#include <setlocal.h>
+//#include <dbgint.h>
+
+//#ifndef _INC_INTERNAL_SAFECRT
+//#include <internal_securecrt.h>
+//#endif /* _INC_INTERNAL_SAFECRT */
+
+//#ifdef _MBCS
+//#undef _MBCS
+//#endif /* _MBCS */
+//#include <tchar.h>
+
+#define _MBTOWC(x,y,z) _minimal_chartowchar( x, y )
+
+#define _istspace(x) isspace((unsigned char)x)
+
+#define _malloc_crt PAL_malloc
+#define _realloc_crt PAL_realloc
+#define _free_crt PAL_free
+
+#define _FASSIGN(flag, argument, number, dec_point, locale) _safecrt_fassign((flag), (argument), (number))
+#define _WFASSIGN(flag, argument, number, dec_point, locale) _safecrt_wfassign((flag), (argument), (number))
+
+#if defined (UNICODE)
+#define ALLOC_TABLE 1
+#else /* defined (UNICODE) */
+#define ALLOC_TABLE 0
+#endif /* defined (UNICODE) */
+
+#define HEXTODEC(chr) _hextodec(chr)
+
+#define LEFT_BRACKET ('[' | ('a' - 'A')) /* 'lowercase' version */
+
+static int __cdecl _hextodec(_TCHAR);
+#ifdef CPRFLAG
+
+#define INC() (++charcount, _inc())
+#define UN_INC(chr) (--charcount, _un_inc(chr))
+#define EAT_WHITE() _whiteout(&charcount)
+
+static int __cdecl _inc(void);
+static void __cdecl _un_inc(int);
+static int __cdecl _whiteout(int *);
+
+#else /* CPRFLAG */
+
+#define INC() (++charcount, _inc(stream))
+#define UN_INC(chr) (--charcount, _un_inc(chr, stream))
+#define EAT_WHITE() _whiteout(&charcount, stream)
+
+static int __cdecl _inc(miniFILE *);
+static void __cdecl _un_inc(int, miniFILE *);
+static int __cdecl _whiteout(int *, miniFILE *);
+
+#endif /* CPRFLAG */
+
+#ifndef _UNICODE
+#define _ISDIGIT(chr) isdigit((unsigned char)chr)
+#define _ISXDIGIT(chr) isxdigit((unsigned char)chr)
+#else /* _UNICODE */
+#define _ISDIGIT(chr) ( !(chr & 0xff00) && isdigit( ((chr) & 0x00ff) ) )
+#define _ISXDIGIT(chr) ( !(chr & 0xff00) && isxdigit( ((chr) & 0x00ff) ) )
+#endif /* _UNICODE */
+
+#define MUL10(x) ( (((x)<<2) + (x))<<1 )
+
+
+#define LONGLONG_IS_INT64 1 /* 1 means long long is same as int64
+ 0 means long long is same as long */
+
+/***
+* int __check_float_string(size_t,size_t *, _TCHAR**, _TCHAR*, int*)
+*
+* Purpose:
+* Check if there is enough space insert onemore character in the given
+* block, if not then allocate more memory.
+*
+* Return:
+* FALSE if more memory needed and the reallocation failed.
+*
+*******************************************************************************/
+
+static int __check_float_string(size_t nFloatStrUsed,
+ size_t *pnFloatStrSz,
+ _TCHAR **pFloatStr,
+ _TCHAR *floatstring,
+ int *pmalloc_FloatStrFlag)
+{
+ void *tmpPointer;
+ _ASSERTE(nFloatStrUsed<=(*pnFloatStrSz));
+ if (nFloatStrUsed==(*pnFloatStrSz))
+ {
+ size_t newSize;
+
+ // Will (*pnFloatStrSz) * 2 * sizeof(_TCHAR) overflow?
+ if ( *pnFloatStrSz > (SIZE_T_MAX / 2 / sizeof(_TCHAR)))
+ {
+ return FALSE;
+ }
+
+ newSize = *pnFloatStrSz * 2 * sizeof(_TCHAR);
+
+ if ((*pFloatStr)==floatstring)
+ {
+ if (((*pFloatStr)=(_TCHAR *)_malloc_crt(newSize))==NULL)
+ {
+ return FALSE;
+ }
+
+ (*pmalloc_FloatStrFlag)=1;
+
+ memcpy((*pFloatStr),floatstring,(*pnFloatStrSz)*sizeof(_TCHAR));
+ (*pnFloatStrSz)*=2;
+ }
+ else
+ {
+ if ((tmpPointer=(_TCHAR *)_realloc_crt((*pFloatStr), newSize))==NULL)
+ {
+ return FALSE;
+ }
+ (*pFloatStr)=(_TCHAR *)(tmpPointer);
+ (*pnFloatStrSz)*=2;
+ }
+ }
+ return TRUE;
+}
+
+
+#define ASCII 32 /* # of bytes needed to hold 256 bits */
+
+#define SCAN_SHORT 0 /* also for FLOAT */
+#define SCAN_LONG 1 /* also for DOUBLE */
+#define SCAN_L_DOUBLE 2 /* only for LONG DOUBLE */
+
+#define SCAN_NEAR 0
+#define SCAN_FAR 1
+
+#ifndef _UNICODE
+#define TABLESIZE ASCII
+#else /* _UNICODE */
+#define TABLESIZE (ASCII * 256)
+#endif /* _UNICODE */
+
+
+/***
+*int _input(stream, format, arglist), static int input(format, arglist)
+*
+*Purpose:
+* get input items (data items or literal matches) from the input stream
+* and assign them if appropriate to the items thru the arglist. this
+* function is intended for internal library use only, not for the user
+*
+* The _input entry point is for the normal scanf() functions
+* The input entry point is used when compiling for _cscanf() [CPRFLAF
+* defined] and is a static function called only by _cscanf() -- reads from
+* console.
+*
+* This code also defines _input_s, which works differently for %c, %s & %[.
+* For these, _input_s first picks up the next argument from the variable
+* argument list & uses it as the maximum size of the character array pointed
+* to by the next argument in the list.
+*
+*Entry:
+* FILE *stream - file to read from
+* char *format - format string to determine the data to read
+* arglist - list of pointer to data items
+*
+*Exit:
+* returns number of items assigned and fills in data items
+* returns EOF if error or EOF found on stream before 1st data item matched
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+ #define _INTRN_LOCALE_CONV( x ) localeconv()
+
+#ifndef _UNICODE
+ int __cdecl __tinput_s (miniFILE* stream, const _TUCHAR* format, va_list arglist)
+#else
+ int __cdecl __twinput_s (miniFILE* stream, const _TUCHAR* format, va_list arglist)
+#endif /* _UNICODE */
+{
+ _TCHAR floatstring[_CVTBUFSIZE + 1];
+ _TCHAR *pFloatStr=floatstring;
+ size_t nFloatStrUsed=0;
+ size_t nFloatStrSz=sizeof(floatstring)/sizeof(floatstring[0]);
+ int malloc_FloatStrFlag=0;
+
+ unsigned long number; /* temp hold-value */
+#if ALLOC_TABLE
+ char *table = NULL; /* which chars allowed for %[] */
+ int malloc_flag = 0; /* is "table" allocated on the heap? */
+#else /* ALLOC_TABLE */
+ char AsciiTable[TABLESIZE];
+ char *table = AsciiTable;
+#endif /* ALLOC_TABLE */
+
+#if _INTEGRAL_MAX_BITS >= 64
+ uint64_t num64 = 0LL; /* temp for 64-bit integers */
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+ void *pointer=NULL; /* points to user data receptacle */
+ void *start; /* indicate non-empty string */
+
+
+#ifndef _UNICODE
+ wchar_t wctemp=L'\0';
+#endif /* _UNICODE */
+ _TUCHAR *scanptr; /* for building "table" data */
+ int ch = 0;
+ int charcount; /* total number of chars read */
+ int comchr; /* holds designator type */
+ int count; /* return value. # of assignments */
+
+ int started; /* indicate good number */
+ int width; /* width of field */
+ int widthset; /* user has specified width */
+#ifdef _SECURE_SCANF
+ size_t array_width = 0;
+ size_t original_array_width = 0;
+ int enomem = 0;
+ int format_error = FALSE;
+#endif /* _SECURE_SCANF */
+
+/* Neither coerceshort nor farone are need for the 386 */
+
+
+ char done_flag; /* general purpose loop monitor */
+ char longone; /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */
+#if _INTEGRAL_MAX_BITS >= 64
+ int integer64; /* 1 for 64-bit integer, 0 otherwise */
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+ signed char widechar; /* -1 = char, 0 = ????, 1 = wchar_t */
+ char reject; /* %[^ABC] instead of %[ABC] */
+ char negative; /* flag for '-' detected */
+ char suppress; /* don't assign anything */
+ char match; /* flag: !0 if any fields matched */
+ va_list arglistsave; /* save arglist value */
+
+ char fl_wchar_arg; /* flags wide char/string argument */
+
+ _TCHAR decimal;
+
+
+ _TUCHAR rngch;
+ _TUCHAR last;
+ _TUCHAR prevchar;
+ _TCHAR tch;
+
+ _VALIDATE_RETURN( (format != NULL), EINVAL, EOF);
+
+#ifndef CPRFLAG
+ _VALIDATE_RETURN( (stream != NULL), EINVAL, EOF);
+#endif /* CPRFLAG */
+
+ /*
+ count = # fields assigned
+ charcount = # chars read
+ match = flag indicating if any fields were matched
+
+ [Note that we need both count and match. For example, a field
+ may match a format but have assignments suppressed. In this case,
+ match will get set, but 'count' will still equal 0. We need to
+ distinguish 'match vs no-match' when terminating due to EOF.]
+ */
+
+ count = charcount = match = 0;
+
+ while (*format) {
+
+ if (_istspace((_TUCHAR)*format)) {
+
+ UN_INC(EAT_WHITE()); /* put first non-space char back */
+
+ do {
+ tch = *++format;
+ } while (_istspace((_TUCHAR)tch));
+
+ continue;
+
+ }
+
+ if (_T('%') == *format) {
+
+ number = 0;
+ prevchar = 0;
+ width = widthset = started = 0;
+#ifdef _SECURE_SCANF
+ original_array_width = array_width = 0;
+ enomem = 0;
+#endif /* _SECURE_SCANF */
+ fl_wchar_arg = done_flag = suppress = negative = reject = 0;
+ widechar = 0;
+
+ longone = 1;
+
+#if _INTEGRAL_MAX_BITS >= 64
+ integer64 = 0;
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+
+ while (!done_flag) {
+
+ comchr = *++format;
+ if (_ISDIGIT((_TUCHAR)comchr)) {
+ ++widthset;
+ width = MUL10(width) + (comchr - _T('0'));
+ } else
+ switch (comchr) {
+ case _T('F') :
+ case _T('N') : /* no way to push NEAR in large model */
+ break; /* NEAR is default in small model */
+ case _T('h') :
+ /* set longone to 0 */
+ --longone;
+ --widechar; /* set widechar = -1 */
+ break;
+
+#if _INTEGRAL_MAX_BITS >= 64
+ case _T('I'):
+ if ( (*(format + 1) == _T('6')) &&
+ (*(format + 2) == _T('4')) )
+ {
+ format += 2;
+ ++integer64;
+ num64 = 0;
+ break;
+ }
+ else if ( (*(format + 1) == _T('3')) &&
+ (*(format + 2) == _T('2')) )
+ {
+ format += 2;
+ break;
+ }
+ else if ( (*(format + 1) == _T('d')) ||
+ (*(format + 1) == _T('i')) ||
+ (*(format + 1) == _T('o')) ||
+ (*(format + 1) == _T('x')) ||
+ (*(format + 1) == _T('X')) )
+ {
+ if (sizeof(void*) == sizeof(__int64))
+ {
+ ++integer64;
+ num64 = 0;
+ }
+ break;
+ }
+ if (sizeof(void*) == sizeof(__int64))
+ {
+ ++integer64;
+ num64 = 0;
+ }
+ goto DEFAULT_LABEL;
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+
+ case _T('L') :
+ /* ++longone; */
+ ++longone;
+ break;
+
+ case _T('q'):
+ ++integer64;
+ num64 = 0;
+ break;
+
+ case _T('l') :
+ if (*(format + 1) == _T('l'))
+ {
+ ++format;
+#ifdef LONGLONG_IS_INT64
+ ++integer64;
+ num64 = 0;
+ break;
+#else /* LONGLONG_IS_INT64 */
+ ++longone;
+ /* NOBREAK */
+#endif /* LONGLONG_IS_INT64 */
+ }
+ else
+ {
+ ++longone;
+ /* NOBREAK */
+ }
+ case _T('w') :
+ ++widechar; /* set widechar = 1 */
+ break;
+
+ case _T('*') :
+ ++suppress;
+ break;
+
+ default:
+DEFAULT_LABEL:
+ ++done_flag;
+ break;
+ }
+ }
+
+ if (!suppress) {
+ va_copy(arglistsave, arglist);
+ pointer = va_arg(arglist,void *);
+ } else {
+ pointer = NULL; // doesn't matter what value we use here - we're only using it as a flag
+ }
+
+ done_flag = 0;
+
+ if (!widechar) { /* use case if not explicitly specified */
+ if ((*format == _T('S')) || (*format == _T('C')))
+#ifdef _UNICODE
+ --widechar;
+ else
+ ++widechar;
+#else /* _UNICODE */
+ ++widechar;
+ else
+ --widechar;
+#endif /* _UNICODE */
+ }
+
+ /* switch to lowercase to allow %E,%G, and to
+ keep the switch table small */
+
+ comchr = *format | (_T('a') - _T('A'));
+
+ if (_T('n') != comchr)
+ {
+ if (_T('c') != comchr && LEFT_BRACKET != comchr)
+ ch = EAT_WHITE();
+ else
+ ch = INC();
+ }
+
+ if (_T('n') != comchr)
+ {
+ if (_TEOF == ch)
+ goto error_return;
+ }
+
+ if (!widthset || width) {
+
+#ifdef _SECURE_SCANF
+ if(!suppress && (comchr == _T('c') || comchr == _T('s') || comchr == LEFT_BRACKET)) {
+
+ va_copy(arglist, arglistsave);
+
+ /* Reinitialize pointer to point to the array to which we write the input */
+ pointer = va_arg(arglist, void*);
+
+ va_copy(arglistsave, arglist);
+
+ /* Get the next argument - size of the array in characters */
+#ifdef _WIN64
+ original_array_width = array_width = (size_t)(va_arg(arglist, unsigned int));
+#else /* _WIN64 */
+ original_array_width = array_width = va_arg(arglist, size_t);
+#endif /* _WIN64 */
+
+ if(array_width < 1) {
+ if (widechar > 0)
+ *(wchar_t UNALIGNED *)pointer = L'\0';
+ else
+ *(char *)pointer = '\0';
+
+ errno = ENOMEM;
+
+ goto error_return;
+ }
+ }
+#endif /* _SECURE_SCANF */
+ switch(comchr) {
+
+ case _T('c'):
+ /* case _T('C'): */
+ if (!widthset) {
+ ++widthset;
+ ++width;
+ }
+ if (widechar > 0)
+ fl_wchar_arg++;
+ goto scanit;
+
+
+ case _T('s'):
+ /* case _T('S'): */
+ if(widechar > 0)
+ fl_wchar_arg++;
+ goto scanit;
+
+
+ case LEFT_BRACKET : /* scanset */
+ if (widechar>0)
+ fl_wchar_arg++;
+ scanptr = (_TUCHAR *)(++format);
+
+ if (_T('^') == *scanptr) {
+ ++scanptr;
+ --reject; /* set reject to 255 */
+ }
+
+ /* Allocate "table" on first %[] spec */
+#if ALLOC_TABLE
+ if (table == NULL) {
+ table = (char*)_malloc_crt(TABLESIZE);
+ if ( table == NULL)
+ goto error_return;
+ malloc_flag = 1;
+ }
+#endif /* ALLOC_TABLE */
+ memset(table, 0, TABLESIZE);
+
+
+ if (LEFT_BRACKET == comchr)
+ if (_T(']') == *scanptr) {
+ prevchar = _T(']');
+ ++scanptr;
+
+ table[ _T(']') >> 3] = 1 << (_T(']') & 7);
+
+ }
+
+ while (_T(']') != *scanptr) {
+
+ rngch = *scanptr++;
+
+ if (_T('-') != rngch ||
+ !prevchar || /* first char */
+ _T(']') == *scanptr) /* last char */
+
+ table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7);
+
+ else { /* handle a-z type set */
+
+ rngch = *scanptr++; /* get end of range */
+
+ if (prevchar < rngch) /* %[a-z] */
+ last = rngch;
+ else { /* %[z-a] */
+ last = prevchar;
+ prevchar = rngch;
+ }
+ for (rngch = prevchar; rngch <= last; ++rngch)
+ table[rngch >> 3] |= 1 << (rngch & 7);
+
+ prevchar = 0;
+
+ }
+ }
+
+
+ if (!*scanptr)
+ goto error_return; /* trunc'd format string */
+
+ /* scanset completed. Now read string */
+
+ if (LEFT_BRACKET == comchr)
+ format = scanptr;
+
+scanit:
+ start = pointer;
+
+ /*
+ * execute the format directive. that is, scan input
+ * characters until the directive is fulfilled, eof
+ * is reached, or a non-matching character is
+ * encountered.
+ *
+ * it is important not to get the next character
+ * unless that character needs to be tested! other-
+ * wise, reads from line-buffered devices (e.g.,
+ * scanf()) would require an extra, spurious, newline
+ * if the first newline completes the current format
+ * directive.
+ */
+ UN_INC(ch);
+
+#ifdef _SECURE_SCANF
+ /* One element is needed for '\0' for %s & %[ */
+ if(comchr != _T('c')) {
+ --array_width;
+ }
+#endif /* _SECURE_SCANF */
+ while ( !widthset || width-- ) {
+
+ ch = INC();
+ if (
+#ifndef CPRFLAG
+ (_TEOF != ch) &&
+#endif /* CPRFLAG */
+ // char conditions
+ ( ( comchr == _T('c')) ||
+ // string conditions !isspace()
+ ( ( comchr == _T('s') &&
+ (!(ch >= _T('\t') && ch <= _T('\r')) &&
+ ch != _T(' ')))) ||
+ // BRACKET conditions
+ ( (comchr == LEFT_BRACKET) &&
+ ((table[ch >> 3] ^ reject) & (1 << (ch & 7)))
+ )
+ )
+ )
+ {
+ if (!suppress) {
+#ifdef _SECURE_SCANF
+ if(!array_width) {
+ /* We have exhausted the user's buffer */
+
+ enomem = 1;
+ break;
+ }
+#endif /* _SECURE_SCANF */
+#ifndef _UNICODE
+ if (fl_wchar_arg) {
+ wctemp = L'?';
+ char temp[2];
+ temp[0] = (char) ch;
+#if 0 // we are not supporting multibyte input strings
+ if (isleadbyte((unsigned char)ch))
+ {
+ temp[1] = (char) INC();
+ }
+#endif /* 0 */
+ _MBTOWC(&wctemp, temp, MB_CUR_MAX);
+ *(wchar_t UNALIGNED *)pointer = wctemp;
+ /* just copy L'?' if mbtowc fails, errno is set by mbtowc */
+ pointer = (wchar_t *)pointer + 1;
+#ifdef _SECURE_SCANF
+ --array_width;
+#endif /* _SECURE_SCANF */
+ } else
+#else /* _UNICODE */
+ if (fl_wchar_arg) {
+ *(wchar_t UNALIGNED *)pointer = ch;
+ pointer = (wchar_t *)pointer + 1;
+#ifdef _SECURE_SCANF
+ --array_width;
+#endif /* _SECURE_SCANF */
+ } else
+#endif /* _UNICODE */
+ {
+#ifndef _UNICODE
+ *(char *)pointer = (char)ch;
+ pointer = (char *)pointer + 1;
+#ifdef _SECURE_SCANF
+ --array_width;
+#endif /* _SECURE_SCANF */
+#else /* _UNICODE */
+ int temp = 0;
+#ifndef _SECURE_SCANF
+ /* convert wide to multibyte */
+ if (_ERRCHECK_EINVAL_ERANGE(wctomb_s(&temp, (char *)pointer, MB_LEN_MAX, ch)) == 0)
+ {
+ /* do nothing if wctomb fails, errno will be set to EILSEQ */
+ pointer = (char *)pointer + temp;
+ }
+#else /* _SECURE_SCANF */
+ /* convert wide to multibyte */
+ if (array_width >= ((size_t)MB_CUR_MAX))
+ {
+_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
+ temp = wctomb((char *)pointer, ch);
+_END_SECURE_CRT_DEPRECATION_DISABLE
+ }
+ else
+ {
+ char tmpbuf[MB_LEN_MAX];
+_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
+ temp = wctomb(tmpbuf, ch);
+_END_SECURE_CRT_DEPRECATION_DISABLE
+ if (temp > 0 && ((size_t)temp) > array_width)
+ {
+ /* We have exhausted the user's buffer */
+ enomem = 1;
+ break;
+ }
+ memcpy(pointer, tmpbuf, temp);
+ }
+ if (temp > 0)
+ {
+ /* do nothing if wctomb fails, errno will be set to EILSEQ */
+ pointer = (char *)pointer + temp;
+ array_width -= temp;
+ }
+#endif /* _SECURE_SCANF */
+#endif /* _UNICODE */
+ }
+ } /* suppress */
+ else {
+ /* just indicate a match */
+ start = (_TCHAR *)start + 1;
+ }
+ }
+ else {
+ UN_INC(ch);
+ break;
+ }
+ }
+
+ /* make sure something has been matched and, if
+ assignment is not suppressed, null-terminate
+ output string if comchr != c */
+
+#ifdef _SECURE_SCANF
+ if(enomem) {
+ errno = ENOMEM;
+ /* In case of error, blank out the input buffer */
+ if (fl_wchar_arg)
+ {
+ _RESET_STRING(((wchar_t UNALIGNED *)start), original_array_width);
+ }
+ else
+ {
+ _RESET_STRING(((char *)start), original_array_width);
+ }
+
+ goto error_return;
+ }
+#endif /* _SECURE_SCANF */
+
+ if (start != pointer) {
+ if (!suppress) {
+ ++count;
+ if ('c' != comchr) /* null-terminate strings */
+ {
+ if (fl_wchar_arg)
+ {
+ *(wchar_t UNALIGNED *)pointer = L'\0';
+#ifdef _SECURE_SCANF
+ _FILL_STRING(((wchar_t UNALIGNED *)start), original_array_width,
+ ((wchar_t UNALIGNED *)pointer - (wchar_t UNALIGNED *)start + 1))
+#endif /* _SECURE_SCANF */
+ }
+ else
+ {
+ *(char *)pointer = '\0';
+#ifdef _SECURE_SCANF
+ _FILL_STRING(((char *)start), original_array_width,
+ ((char *)pointer - (char *)start + 1))
+#endif /* _SECURE_SCANF */
+ }
+ }
+ }
+ else
+ {
+ // supress set, do nothing
+ }
+ }
+ else
+ goto error_return;
+
+ break;
+
+ case _T('i') : /* could be d, o, or x */
+
+ comchr = _T('d'); /* use as default */
+
+ case _T('x'):
+
+ if (_T('-') == ch) {
+ ++negative;
+
+ goto x_incwidth;
+
+ } else if (_T('+') == ch) {
+x_incwidth:
+ if (!--width && widthset)
+ ++done_flag;
+ else
+ ch = INC();
+ }
+
+ if (_T('0') == ch) {
+
+ if (_T('x') == (_TCHAR)(ch = INC()) || _T('X') == (_TCHAR)ch) {
+ ch = INC();
+ if (widthset) {
+ width -= 2;
+ if (width < 1)
+ ++done_flag;
+ }
+ comchr = _T('x');
+ } else {
+ ++started;
+ if (_T('x') != comchr) {
+ if (widthset && !--width)
+ ++done_flag;
+ comchr = _T('o');
+ }
+ else {
+ /* scanning a hex number that starts */
+ /* with a 0. push back the character */
+ /* currently in ch and restore the 0 */
+ UN_INC(ch);
+ ch = _T('0');
+ }
+ }
+ }
+ goto getnum;
+
+ /* NOTREACHED */
+
+ case _T('p') :
+ /* force %hp to be treated as %p */
+ longone = 1;
+#ifdef _WIN64
+ /* force %p to be 64 bit in WIN64 */
+ ++integer64;
+ num64 = 0;
+#endif /* _WIN64 */
+ case _T('o') :
+ case _T('u') :
+ case _T('d') :
+
+ if (_T('-') == ch) {
+ ++negative;
+
+ goto d_incwidth;
+
+ } else if (_T('+') == ch) {
+d_incwidth:
+ if (!--width && widthset)
+ ++done_flag;
+ else
+ ch = INC();
+ }
+
+getnum:
+#if _INTEGRAL_MAX_BITS >= 64
+ if ( integer64 ) {
+
+ while (!done_flag) {
+
+ if (_T('x') == comchr || _T('p') == comchr)
+
+ if (_ISXDIGIT(ch)) {
+ num64 <<= 4;
+ ch = _hextodec(ch);
+ }
+ else
+ ++done_flag;
+
+ else if (_ISDIGIT(ch))
+
+ if (_T('o') == comchr)
+ if (_T('8') > ch)
+ num64 <<= 3;
+ else {
+ ++done_flag;
+ }
+ else /* _T('d') == comchr */
+ num64 = MUL10(num64);
+
+ else
+ ++done_flag;
+
+ if (!done_flag) {
+ ++started;
+ num64 += ch - _T('0');
+
+ if (widthset && !--width)
+ ++done_flag;
+ else
+ ch = INC();
+ } else
+ UN_INC(ch);
+
+ } /* end of WHILE loop */
+
+ if (negative)
+ num64 = (uint64_t )(-(__int64)num64);
+ }
+ else {
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+ while (!done_flag) {
+
+ if (_T('x') == comchr || _T('p') == comchr)
+
+ if (_ISXDIGIT(ch)) {
+ number = (number << 4);
+ ch = _hextodec(ch);
+ }
+ else
+ ++done_flag;
+
+ else if (_ISDIGIT(ch))
+
+ if (_T('o') == comchr)
+ if (_T('8') > ch)
+ number = (number << 3);
+ else {
+ ++done_flag;
+ }
+ else /* _T('d') == comchr */
+ number = MUL10(number);
+
+ else
+ ++done_flag;
+
+ if (!done_flag) {
+ ++started;
+ number += ch - _T('0');
+
+ if (widthset && !--width)
+ ++done_flag;
+ else
+ ch = INC();
+ } else
+ UN_INC(ch);
+
+ } /* end of WHILE loop */
+
+ if (negative)
+ number = (unsigned long)(-(long)number);
+#if _INTEGRAL_MAX_BITS >= 64
+ }
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+ if (_T('F')==comchr) /* expected ':' in long pointer */
+ started = 0;
+
+ if (started)
+ if (!suppress) {
+
+ ++count;
+assign_num:
+#if _INTEGRAL_MAX_BITS >= 64
+ if ( integer64 )
+ *(__int64 UNALIGNED *)pointer = ( uint64_t )num64;
+ else
+#endif /* _INTEGRAL_MAX_BITS >= 64 */
+ if (longone)
+ *(int UNALIGNED *)pointer = (unsigned int)number;
+ else
+ *(short UNALIGNED *)pointer = (unsigned short)number;
+
+ } else /*NULL*/;
+ else
+ goto error_return;
+
+ break;
+
+ case _T('n') : /* char count, don't inc return value */
+ number = charcount;
+ if(!suppress)
+ goto assign_num; /* found in number code above */
+ break;
+
+
+ case _T('e') :
+ /* case _T('E') : */
+ case _T('f') :
+ case _T('g') : /* scan a float */
+ /* case _T('G') : */
+ nFloatStrUsed=0;
+
+ if (_T('-') == ch) {
+ pFloatStr[nFloatStrUsed++] = _T('-');
+ goto f_incwidth;
+
+ } else if (_T('+') == ch) {
+f_incwidth:
+ --width;
+ ch = INC();
+ }
+
+ if (!widthset) /* must watch width */
+ width = -1;
+
+
+ /* now get integral part */
+
+ while (_ISDIGIT(ch) && width--) {
+ ++started;
+ pFloatStr[nFloatStrUsed++] = (char)ch;
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+ ch = INC();
+ }
+
+#ifdef _UNICODE
+ /* convert decimal point to wide-char */
+ /* if mbtowc fails (should never happen), we use L'.' */
+ decimal = L'.';
+ _MBTOWC(&decimal, _INTRN_LOCALE_CONV(_loc_update)->decimal_point, MB_CUR_MAX);
+#else /* _UNICODE */
+
+ decimal=*((_INTRN_LOCALE_CONV(_loc_update))->decimal_point);
+#endif /* _UNICODE */
+
+ /* now check for decimal */
+ if (decimal == (char)ch && width--) {
+ ch = INC();
+ pFloatStr[nFloatStrUsed++] = decimal;
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+
+ while (_ISDIGIT(ch) && width--) {
+ ++started;
+ pFloatStr[nFloatStrUsed++] = (_TCHAR)ch;
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+ ch = INC();
+ }
+ }
+
+ /* now check for exponent */
+
+ if (started && (_T('e') == ch || _T('E') == ch) && width--) {
+ pFloatStr[nFloatStrUsed++] = _T('e');
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+
+ if (_T('-') == (ch = INC())) {
+
+ pFloatStr[nFloatStrUsed++] = _T('-');
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+ goto f_incwidth2;
+
+ } else if (_T('+') == ch) {
+f_incwidth2:
+ if (!width--)
+ ++width;
+ else
+ ch = INC();
+ }
+
+
+ while (_ISDIGIT(ch) && width--) {
+ ++started;
+ pFloatStr[nFloatStrUsed++] = (_TCHAR)ch;
+ if (__check_float_string(nFloatStrUsed,
+ &nFloatStrSz,
+ &pFloatStr,
+ floatstring,
+ &malloc_FloatStrFlag
+ )==FALSE) {
+ goto error_return;
+ }
+ ch = INC();
+ }
+
+ }
+
+ UN_INC(ch);
+
+ if (started)
+ if (!suppress) {
+ ++count;
+ pFloatStr[nFloatStrUsed]= _T('\0');
+#ifdef _UNICODE
+ _WFASSIGN( longone-1, pointer, pFloatStr, (char)decimal, _loc_update.GetLocaleT());
+#else /* _UNICODE */
+ _FASSIGN( longone-1, pointer, pFloatStr, (char)decimal, _loc_update.GetLocaleT());
+#endif /* _UNICODE */
+ } else /*NULL */;
+ else
+ goto error_return;
+
+ break;
+
+
+ default: /* either found '%' or something else */
+
+ if ((int)*format != (int)ch) {
+ UN_INC(ch);
+#ifdef _SECURE_SCANF
+ /* error_return ASSERT's if format_error is true */
+ format_error = TRUE;
+#endif /* _SECURE_SCANF */
+ goto error_return;
+ }
+ else
+ match--; /* % found, compensate for inc below */
+
+ if (!suppress)
+ va_copy(arglist, arglistsave);
+
+ } /* SWITCH */
+
+ match++; /* matched a format field - set flag */
+
+ } /* WHILE (width) */
+
+ else { /* zero-width field in format string */
+ UN_INC(ch); /* check for input error */
+ goto error_return;
+ }
+
+ ++format; /* skip to next char */
+
+ } else /* ('%' != *format) */
+ {
+
+ if ((int)*format++ != (int)(ch = INC()))
+ {
+ UN_INC(ch);
+ goto error_return;
+ }
+#if 0 // we are not supporting multibyte input strings
+#ifndef _UNICODE
+ if (isleadbyte((unsigned char)ch))
+ {
+ int ch2;
+ if ((int)*format++ != (ch2=INC()))
+ {
+ UN_INC(ch2);
+ UN_INC(ch);
+ goto error_return;
+ }
+
+ --charcount; /* only count as one character read */
+ }
+#endif /* _UNICODE */
+#endif
+ }
+
+#ifndef CPRFLAG
+ if ( (_TEOF == ch) && ((*format != _T('%')) || (*(format + 1) != _T('n'))) )
+ break;
+#endif /* CPRFLAG */
+
+ } /* WHILE (*format) */
+
+error_return:
+#if ALLOC_TABLE
+ if (malloc_flag == 1)
+ {
+ _free_crt(table);
+ }
+#endif /* ALLOC_TABLE */
+ if (malloc_FloatStrFlag == 1)
+ {
+ _free_crt(pFloatStr);
+ }
+
+#ifndef CPRFLAG
+ if (_TEOF == ch)
+ /* If any fields were matched or assigned, return count */
+ return ( (count || match) ? count : EOF);
+ else
+#endif /* CPRFLAG */
+#ifdef _SECURE_SCANF
+ if(format_error == TRUE) {
+ _VALIDATE_RETURN( ("Invalid Input Format" && 0), EINVAL, count);
+ }
+#endif /* _SECURE_SCANF */
+ return count;
+
+}
+
+/* _hextodec() returns a value of 0-15 and expects a char 0-9, a-f, A-F */
+/* _inc() is the one place where we put the actual getc code. */
+/* _whiteout() returns the first non-blank character, as defined by isspace() */
+
+static int __cdecl _hextodec ( _TCHAR chr)
+{
+ return _ISDIGIT(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0');
+}
+
+#ifdef CPRFLAG
+
+static int __cdecl _inc(void)
+{
+ return (_gettche_nolock());
+}
+
+static void __cdecl _un_inc(int chr)
+{
+ if (_TEOF != chr) {
+ _ungettch_nolock(chr);
+ }
+}
+
+static int __cdecl _whiteout(REG1 int* counter)
+{
+ REG2 int ch;
+
+ do
+ {
+ ++*counter;
+ ch = _inc();
+
+ if (ch == _TEOF)
+ {
+ break;
+ }
+ }
+ while(_istspace((_TUCHAR)ch));
+ return ch;
+}
+
+#else /* CPRFLAG */
+
+static int __cdecl _inc(miniFILE* fileptr)
+{
+ return (_gettc_nolock(fileptr));
+}
+
+static void __cdecl _un_inc(int chr, miniFILE* fileptr)
+{
+ if (_TEOF != chr) {
+ _ungettc_nolock(chr,fileptr);
+ }
+}
+
+static int __cdecl _whiteout(int* counter, miniFILE* fileptr)
+{
+ int ch;
+
+ do
+ {
+ ++*counter;
+ ch = _inc(fileptr);
+
+ if (ch == _TEOF)
+ {
+ break;
+ }
+ }
+ while(_istspace((_TUCHAR)ch));
+ return ch;
+}
+
+#endif /* CPRFLAG */