sscanf 格式化输入 的关键 VS2010\VC\crt\src\input.c

 VS2010\VC\crt\src\ctype.h


#define _ischartype_l(_Char, _Flag, _Locale)    ( ((_Locale)!=NULL && (((_locale_t)(_Locale))->locinfo->mb_cur_max) > 1) ? _isctype_l(_Char, (_Flag), _Locale) : _chvalidchk_l(_Char,_Flag,_Locale))
#define _isalpha_l(_Char, _Locale)      _ischartype_l(_Char, _ALPHA, _Locale)
#define _isupper_l(_Char, _Locale)      _ischartype_l(_Char, _UPPER, _Locale)
#define _islower_l(_Char, _Locale)      _ischartype_l(_Char, _LOWER, _Locale)
#define _isdigit_l(_Char, _Locale)      _ischartype_l(_Char, _DIGIT, _Locale)
#define _isxdigit_l(_Char, _Locale)     _ischartype_l(_Char, _HEX, _Locale)
#define _isspace_l(_Char, _Locale)      _ischartype_l(_Char, _SPACE, _Locale)
#define _ispunct_l(_Char, _Locale)      _ischartype_l(_Char, _PUNCT, _Locale)
#define _isalnum_l(_Char, _Locale)      _ischartype_l(_Char, _ALPHA|_DIGIT, _Locale)
#define _isprint_l(_Char, _Locale)      _ischartype_l(_Char, _BLANK|_PUNCT|_ALPHA|_DIGIT, _Locale)
#define _isgraph_l(_Char, _Locale)      _ischartype_l(_Char, _PUNCT|_ALPHA|_DIGIT, _Locale)
#define _iscntrl_l(_Char, _Locale)      _ischartype_l(_Char, _CONTROL, _Locale)


/***

*input.c - C formatted input, used by scanf, etc.
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*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 /* allow "%[a-z]"-style scansets */

#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>

#ifdef __cplusplus
extern "C"
{
#endif  /* __cplusplus */

#ifdef _SAFECRT_IMPL

#undef _malloc_crt
#undef _realloc_crt
#define _malloc_crt malloc
#define _realloc_crt realloc

/* Helpers for scanf_s. */
#ifdef _UNICODE
int __cdecl _stdin_winput_s(const wchar_t *_Format, va_list _ArgList)
#else  /* _UNICODE */
int __cdecl _stdin_input_s(const char *_Format, va_list _ArgList)
#endif  /* _UNICODE */
{
    int retval = -1;

    _lock(_STREAM_LOCKS + 0);
    __try {
        retval = __tinput_s(stdin, _Format, _ArgList);
    }
    __finally {
        _unlock(_STREAM_LOCKS + 0);
    }

    return retval;
}

#ifdef _UNICODE
int __cdecl _swinput_s(const wchar_t *_String, size_t _Count, const wchar_t *_Format, va_list _ArgList)
#else  /* _UNICODE */
int __cdecl _sinput_s(const char *_String, size_t _Count, const char *_Format, va_list _ArgList)
#endif  /* _UNICODE */
{
    FILE stream = { 0 };
    FILE *infile = &stream;
    int retval = -1;

    /* validation section */
    _VALIDATE_RETURN( (_String != NULL), EINVAL, -1);
    _VALIDATE_RETURN( (_Format != NULL), EINVAL, -1);
    _VALIDATE_RETURN(_Count <= (INT_MAX / sizeof(_TCHAR)), EINVAL, -1);

    infile->_flag = _IOREAD | _IOSTRG | _IOMYBUF;
    infile->_ptr = infile->_base = (char *) _String;
    infile->_cnt = (int)_Count * sizeof(_TCHAR);

    retval = __tinput_s(infile, _Format, _ArgList);

    return retval;
}

#endif  /* _SAFECRT_IMPL */

#ifdef _SAFECRT_IMPL
#define _FASSIGN(flag, argument, number, dec_point, locale) _safecrt_fassign((flag), (argument), (number), (dec_point))
#else  /* _SAFECRT_IMPL */
#define _FASSIGN(flag, argument, number, dec_point, locale) _fassign_l((flag), (argument), (number), (locale))
#endif  /* _SAFECRT_IMPL */

#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 _TINT __cdecl _hextodec(_TCHAR);
#ifdef CPRFLAG

#define INC()           (++charcount, _inc())
#define UN_INC(chr)     (--charcount, _un_inc(chr))
#define EAT_WHITE()     _whiteout(&charcount)

static _TINT __cdecl _inc(void);
static void __cdecl _un_inc(_TINT);
static _TINT __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 _TINT __cdecl _inc(FILE *);
static void __cdecl _un_inc(_TINT, FILE *);
static _TINT __cdecl _whiteout(int *, FILE *);

#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 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;
    CRT_WARNING_DISABLE_PUSH(22011, "Silence prefast about overflow/underflow");
    _ASSERTE(nFloatStrUsed<=(*pnFloatStrSz));
    if (nFloatStrUsed==(*pnFloatStrSz))
      {
        if ((*pFloatStr)==floatstring)
        {
            if (((*pFloatStr)=(_TCHAR *)_calloc_crt((*pnFloatStrSz),2*sizeof(_TCHAR)))==NULL)
            {
              return FALSE;
            }
            (*pmalloc_FloatStrFlag)=1;
            memcpy((*pFloatStr),floatstring,(*pnFloatStrSz)*sizeof(_TCHAR));
            (*pnFloatStrSz)*=2;
        }
        else
        {
            if ((tmpPointer=(_TCHAR *)_recalloc_crt((*pFloatStr), (*pnFloatStrSz),2*sizeof(_TCHAR)))==NULL)
            {
                return FALSE;
            }
            (*pFloatStr)=(_TCHAR *)(tmpPointer);
            (*pnFloatStrSz)*=2;
        }
    }
    CRT_WARNING_POP;
    return TRUE;
}


#ifdef CPRFLAG

/***
*int _cscanf(format, arglist) - read formatted input direct from console
*
*Purpose:
*   Reads formatted data like scanf, but uses console I/O functions.
*
*Entry:
*   char *format - format string to determine data formats
*   arglist - list of POINTERS to where to put data
*
*Exit:
*   returns number of successfully matched data items (from input)
*
*Exceptions:
*
*******************************************************************************/
#ifdef _SAFECRT_IMPL

#ifndef _SECURE_SCANF
static int __cdecl input(const _TUCHAR *, va_list);
#else  /* _SECURE_SCANF */
static int __cdecl input_s(const _TUCHAR *, va_list);
#endif  /* _SECURE_SCANF */

#ifndef _SECURE_SCANF
int __cdecl _tcscanf (const _TCHAR *format,...)
#else  /* _SECURE_SCANF */
int __cdecl _tcscanf_s (const _TCHAR *format,...)
#endif  /* _SECURE_SCANF */
{
    va_list arglist;

    va_start(arglist, format);

#ifndef _SECURE_SCANF
    return input(reinterpret_cast<const _TUCHAR*>(format), arglist);   /* get the input */
#else  /* _SECURE_SCANF */
    return input_s(reinterpret_cast<const _TUCHAR*>(format), arglist);   /* get the input */
#endif  /* _SECURE_SCANF */
}

#else  /* _SAFECRT_IMPL */

#ifndef _SECURE_SCANF
    #define _CPRSCANF   _tcscanf
    #define _CPRSCANF_L _tcscanf_l
    #define _CPRINPUT_L _cprinput_l
#else  /* _SECURE_SCANF */
    #define _CPRSCANF   _tcscanf_s
    #define _CPRSCANF_L _tcscanf_s_l
    #define _CPRINPUT_L _cprinput_s_l
#endif  /* _SECURE_SCANF */

static int __cdecl _CPRINPUT_L(const _TUCHAR *, _locale_t , va_list);

int __cdecl _CPRSCANF(const _TCHAR *format,...)
{
    va_list arglist;

    va_start(arglist, format);

    return _CPRINPUT_L(reinterpret_cast<const _TUCHAR*>(format), NULL, arglist);   /* get the input */
}

int __cdecl _CPRSCANF_L(const _TCHAR *format, _locale_t plocinfo, ...)
{
    va_list arglist;

    va_start(arglist, plocinfo);

    return _CPRINPUT_L(reinterpret_cast<const _TUCHAR*>(format), plocinfo, arglist);   /* get the input */
}

#undef _CPRSCANF
#undef _CPRSCANF_L
#undef _CPRINPUT_L

#endif  /* _SAFECRT_IMPL */

#endif  /* CPRFLAG */


#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:
*
*******************************************************************************/

#ifdef _SAFECRT_IMPL
    #define _INTRN_LOCALE_CONV( x ) localeconv()
#else  /* _SAFECRT_IMPL */
    inline const lconv* _INTRN_LOCALE_CONV( _LocaleUpdate& l )
    {
        return l.GetLocaleT()->locinfo->lconv;
    }
#endif  /* _SAFECRT_IMPL */

#ifdef _SAFECRT_IMPL
#ifdef CPRFLAG
#ifndef _SECURE_SCANF
        static int __cdecl input(const _TUCHAR* format, va_list arglist)
#else  /* _SECURE_SCANF */
        static int __cdecl input_s(const _TUCHAR* format, va_list arglist)
#endif  /* _SECURE_SCANF */
#else  /* CPRFLAG */
#ifndef _SECURE_SCANF
        int __cdecl __tinput (FILE* stream, const _TUCHAR* format, va_list arglist)
#else  /* _SECURE_SCANF */
        int __cdecl __tinput_s (FILE* stream, const _TUCHAR* format, va_list arglist)
#endif  /* _SECURE_SCANF */
#endif  /* CPRFLAG */
#else  /* _SAFECRT_IMPL */
#ifdef CPRFLAG
#ifndef _SECURE_SCANF
        static int __cdecl _cprinput_l(const _TUCHAR* format, _locale_t plocinfo, va_list arglist)
#else  /* _SECURE_SCANF */
        static int __cdecl _cprinput_s_l(const _TUCHAR* format, _locale_t plocinfo, va_list arglist)
#endif  /* _SECURE_SCANF */
#else  /* CPRFLAG */
#ifndef _SECURE_SCANF
        int __cdecl _tinput_l(FILE* stream, const _TUCHAR* format, _locale_t plocinfo, va_list arglist)
#else  /* _SECURE_SCANF */
        int __cdecl _tinput_s_l(FILE* stream, const _TUCHAR* format, _locale_t plocinfo, va_list arglist)
#endif  /* _SECURE_SCANF */
#endif  /* CPRFLAG */
#endif  /* _SAFECRT_IMPL */
{
    _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 */

    unsigned __int64 num64;             /* temp for 64-bit integers          */
    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         */
REG2 _TINT ch = 0;
    int charcount;                      /* total number of chars read        */
REG1 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 */
    int integer64;                      /* 1 for 64-bit integer, 0 otherwise */
    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);
#ifndef _UNICODE
    _VALIDATE_STREAM_ANSI_RETURN(stream, EINVAL, EOF);
#endif  /* _UNICODE */
#endif  /* CPRFLAG */

#ifndef _SAFECRT_IMPL
    _LocaleUpdate _loc_update(plocinfo);
#endif  /* _SAFECRT_IMPL */

    /*
    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 && _T('%') != *(format + 1)) {

            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;
            integer64 = 0;

            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;

                        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;

                        case _T('L') :
                        /*  ++longone;  */
                            ++longone;
                            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) {
                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)) {

                    arglist = arglistsave;

                    /* Reinitialize pointer to point to the array to which we write the input */
                    pointer = va_arg(arglist, void*);

                    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;
                                }
                                /* last could be 0xFF, so we handle it at the end of the for loop */
                                for (rngch = prevchar; rngch < last; ++rngch)
                                {
                                    table[rngch >> 3] |= 1 << (rngch & 7);
                                }
                                table[last >> 3] |= 1 << (last & 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) {
                                        char temp[2];
                                        temp[0] = (char) ch;
                                        if (isleadbyte((unsigned char)ch))
                                        {
                                            temp[1] = (char) INC();
                                        }
                                        wctemp = L'?';
#ifdef _SAFECRT_IMPL
                                        mbtowc(&wctemp, temp, MB_CUR_MAX);
#else  /* _SAFECRT_IMPL */
                                        _mbtowc_l(&wctemp,
                                                  temp,
                                                  _loc_update.GetLocaleT()->locinfo->mb_cur_max,
                                                  _loc_update.GetLocaleT());
#endif  /* _SAFECRT_IMPL */
                                        *(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 */
#ifdef _SAFECRT_IMPL
                                    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);
                                    }
#else  /* _SAFECRT_IMPL */
                                    if(wctomb_s(&temp,(char *)pointer, array_width, ch) == ERANGE) {
                                        /* We have exhausted the user's buffer */
                                        enomem = 1;
                                        break;
                                    }
#endif  /* _SAFECRT_IMPL */
                                    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 /*NULL*/;
                        }
                        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 ( 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 = (unsigned __int64 )(-(__int64)num64);
                        }
                        else {
                            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 (_T('F')==comchr) /* expected ':' in long pointer */
                            started = 0;

                        if (started)
                            if (!suppress) {

                                ++count;
assign_num:
                                if ( integer64 )
                                    *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64;
                                else
                                if (longone)
                                    *(long UNALIGNED *)pointer = (unsigned long)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
                        decimal=*_INTRN_LOCALE_CONV(_loc_update)->_W_decimal_point;
#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
                                {
                                    /* convert floatstring to char string */
                                    /* and do the conversion */
                                    size_t cfslength;
                                    char *cfloatstring;

                                    /*
                                     * Basically the code below assumes that the MULTI BYTE
                                     * Characters are at max 2 bytes. This is true for CRT
                                     * because currently we don't support UTF8.
                                     */
                                    cfslength =(size_t)(nFloatStrSz+1)*sizeof(wchar_t);

                                    if ((cfloatstring = (char *)_malloc_crt (cfslength)) == NULL)
                                        goto error_return;
                                    _ERRCHECK_EINVAL_ERANGE(wcstombs_s (NULL, cfloatstring, cfslength, pFloatStr, cfslength - 1));
                                    _FASSIGN( longone-1, (char*)pointer , cfloatstring, (char)decimal, _loc_update.GetLocaleT());
                                    _free_crt (cfloatstring);
                                }
#else  /* _UNICODE */
                                _FASSIGN( longone-1, (char*)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)
                            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 (_T('%') == *format && _T('%') == *(format + 1))
                {
                format++;
                }
            if ((int)*format++ != (int)(ch = INC()))
                {
                UN_INC(ch);
                goto error_return;
                }
#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 */
            }

#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 _TINT __cdecl _hextodec ( _TCHAR chr)
{
    return _ISDIGIT(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0');
}

#ifdef CPRFLAG

static _TINT __cdecl _inc(void)
{
    return (_gettche_nolock());
}

static void __cdecl _un_inc(_TINT chr)
{
    if (_TEOF != chr) {
        _ungettch_nolock(chr);
    }
}

static _TINT __cdecl _whiteout(REG1 int* counter)
{
    REG2 _TINT ch;

    do
    {
        ++*counter;
        ch = _inc();

        if (ch == _TEOF)
        {
            break;
        }
    }
    while(_istspace((_TUCHAR)ch));
    return ch;
}

#else  /* CPRFLAG */

static _TINT __cdecl _inc(FILE* fileptr)
{
    return (_gettc_nolock(fileptr));
}

static void __cdecl _un_inc(_TINT chr, FILE* fileptr)
{
    if (_TEOF != chr) {
        _ungettc_nolock(chr,fileptr);
    }
}

static _TINT __cdecl _whiteout(int* counter, FILE* fileptr)
{
    _TINT ch;

    do
    {
        ++*counter;
        ch = _inc(fileptr);

        if (ch == _TEOF)
        {
            break;
        }
    }
    while(_istspace((_TUCHAR)ch));
    return ch;
}

#endif  /* CPRFLAG */

#ifdef __cplusplus
} /* extern "C" */
#endif  /* __cplusplus */


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值