📄 input.c
字号:
/***
*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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -