ntdll: Reimplement the ctype functions to avoid depending on libc.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-29 10:42:28 +02:00
parent 716cf7d342
commit bc8745851e
2 changed files with 130 additions and 22 deletions

View File

@ -23,7 +23,6 @@
#include "config.h"
#include "wine/port.h"
#include <ctype.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
@ -31,9 +30,43 @@
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winternl.h"
/* same as wctypes except for TAB, which doesn't have C1_BLANK for some reason... */
static const unsigned short ctypes[257] =
{
/* -1 */
0x0000,
/* 00 */
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0028, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020,
/* 10 */
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
/* 20 */
0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 30 */
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 40 */
0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101,
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
/* 50 */
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 60 */
0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102,
0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
/* 70 */
0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020
};
/*********************************************************************
* memchr (NTDLL.@)
*/
@ -157,6 +190,7 @@ int __cdecl NTDLL_strncmp( const char *str1, const char *str2, size_t len )
/*********************************************************************
* strncpy (NTDLL.@)
*/
#undef strncpy
char * __cdecl NTDLL_strncpy( char *dst, const char *src, size_t len )
{
return strncpy( dst, src, len );
@ -355,7 +389,7 @@ int __cdecl NTDLL_toupper( int c )
*/
int __cdecl NTDLL_isalnum( int c )
{
return isalnum( c );
return ctypes[c + 1] & (C1_LOWER | C1_UPPER | C1_DIGIT);
}
@ -364,7 +398,7 @@ int __cdecl NTDLL_isalnum( int c )
*/
int __cdecl NTDLL_isalpha( int c )
{
return isalpha( c );
return ctypes[c + 1] & (C1_LOWER | C1_UPPER);
}
@ -373,7 +407,7 @@ int __cdecl NTDLL_isalpha( int c )
*/
int __cdecl NTDLL_iscntrl( int c )
{
return iscntrl( c );
return ctypes[c + 1] & C1_CNTRL;
}
@ -382,7 +416,7 @@ int __cdecl NTDLL_iscntrl( int c )
*/
int __cdecl NTDLL_isdigit( int c )
{
return isdigit( c );
return ctypes[c + 1] & C1_DIGIT;
}
@ -391,7 +425,7 @@ int __cdecl NTDLL_isdigit( int c )
*/
int __cdecl NTDLL_isgraph( int c )
{
return isgraph( c );
return ctypes[c + 1] & (C1_LOWER | C1_UPPER | C1_DIGIT | C1_PUNCT);
}
@ -400,7 +434,7 @@ int __cdecl NTDLL_isgraph( int c )
*/
int __cdecl NTDLL_islower( int c )
{
return islower( c );
return ctypes[c + 1] & C1_LOWER;
}
@ -409,7 +443,7 @@ int __cdecl NTDLL_islower( int c )
*/
int __cdecl NTDLL_isprint( int c )
{
return isprint( c );
return ctypes[c + 1] & (C1_LOWER | C1_UPPER | C1_DIGIT | C1_PUNCT | C1_BLANK);
}
@ -418,7 +452,7 @@ int __cdecl NTDLL_isprint( int c )
*/
int __cdecl NTDLL_ispunct( int c )
{
return ispunct( c );
return ctypes[c + 1] & C1_PUNCT;
}
@ -427,7 +461,7 @@ int __cdecl NTDLL_ispunct( int c )
*/
int __cdecl NTDLL_isspace( int c )
{
return isspace( c );
return ctypes[c + 1] & C1_SPACE;
}
@ -436,7 +470,7 @@ int __cdecl NTDLL_isspace( int c )
*/
int __cdecl NTDLL_isupper( int c )
{
return isupper( c );
return ctypes[c + 1] & C1_UPPER;
}
@ -445,7 +479,7 @@ int __cdecl NTDLL_isupper( int c )
*/
int __cdecl NTDLL_isxdigit( int c )
{
return isxdigit( c );
return ctypes[c + 1] & C1_XDIGIT;
}
@ -472,7 +506,7 @@ int CDECL NTDLL___toascii(int c)
*/
int CDECL NTDLL___iscsym(int c)
{
return (c < 127 && (isalnum(c) || c == '_'));
return (c < 127 && (NTDLL_isalnum(c) || c == '_'));
}
@ -481,7 +515,7 @@ int CDECL NTDLL___iscsym(int c)
*/
int CDECL NTDLL___iscsymf(int c)
{
return (c < 127 && (isalpha(c) || c == '_'));
return (c < 127 && (NTDLL_isalpha(c) || c == '_'));
}
@ -834,10 +868,10 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
while (*format)
{
if (isspace( *format ))
if (NTDLL_isspace( *format ))
{
/* skip whitespace */
while ((nch != '\0') && isspace( nch ))
while ((nch != '\0') && NTDLL_isspace( nch ))
nch = (consumed++, *str++);
}
else if (*format == '%')
@ -922,7 +956,7 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
BOOLEAN negative = FALSE;
BOOLEAN seendigit = FALSE;
/* skip initial whitespace */
while ((nch != '\0') && isspace( nch ))
while ((nch != '\0') && NTDLL_isspace( nch ))
nch = (consumed++, *str++);
/* get sign */
if (nch == '-' || nch == '+')
@ -1008,10 +1042,10 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
char *sptr_beg = sptr;
unsigned size = UINT_MAX;
/* skip initial whitespace */
while (nch != '\0' && isspace( nch ))
while (nch != '\0' && NTDLL_isspace( nch ))
nch = (consumed++, *str++);
/* read until whitespace */
while (width != 0 && nch != '\0' && !isspace( nch ))
while (width != 0 && nch != '\0' && !NTDLL_isspace( nch ))
{
if (!suppress)
{
@ -1037,10 +1071,10 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
WCHAR *sptr_beg = sptr;
unsigned size = UINT_MAX;
/* skip initial whitespace */
while (nch != '\0' && isspace( nch ))
while (nch != '\0' && NTDLL_isspace( nch ))
nch = (consumed++, *str++);
/* read until whitespace */
while (width != 0 && nch != '\0' && !isspace( nch ))
while (width != 0 && nch != '\0' && !NTDLL_isspace( nch ))
{
if (!suppress)
{
@ -1222,7 +1256,7 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
* of characters that must match the input. For example,
* to specify that a percent-sign character is to be input,
* use %%." */
while (nch != '\0' && isspace( nch ))
while (nch != '\0' && NTDLL_isspace( nch ))
nch = (consumed++, *str++);
if (nch == *format)
{

View File

@ -86,6 +86,18 @@ static int (__cdecl *piswlower)(WCHAR);
static int (__cdecl *piswspace)(WCHAR);
static int (__cdecl *piswxdigit)(WCHAR);
static int (__cdecl *pisalnum)(int);
static int (__cdecl *pisalpha)(int);
static int (__cdecl *piscntrl)(int);
static int (__cdecl *pisdigit)(int);
static int (__cdecl *pisgraph)(int);
static int (__cdecl *pislower)(int);
static int (__cdecl *pisprint)(int);
static int (__cdecl *pispunct)(int);
static int (__cdecl *pisspace)(int);
static int (__cdecl *pisupper)(int);
static int (__cdecl *pisxdigit)(int);
static void InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
@ -138,6 +150,17 @@ static void InitFunctionPtrs(void)
X(iswlower);
X(iswspace);
X(iswxdigit);
X(isalnum);
X(isalpha);
X(iscntrl);
X(isdigit);
X(isgraph);
X(islower);
X(isprint);
X(ispunct);
X(isspace);
X(isupper);
X(isxdigit);
#undef X
}
@ -1954,6 +1977,56 @@ static void test_wctype(void)
}
}
/* we could reuse wctypes except for TAB, which doesn't have C1_BLANK for some reason... */
static const unsigned short ctypes[256] =
{
/* 00 */
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0028, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020,
/* 10 */
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
/* 20 */
0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 30 */
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 40 */
0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101,
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
/* 50 */
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
/* 60 */
0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102,
0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
/* 70 */
0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020
};
static void test_ctype(void)
{
int i;
for (i = -1; i < 256; i++)
{
unsigned short type = (i >= 0 ? ctypes[i] : 0);
ok( pisalnum( i ) == (type & (C1_DIGIT|C1_LOWER|C1_UPPER)), "%u: wrong isalnum %x / %x\n", i, pisalnum(i), type );
ok( pisalpha( i ) == (type & (C1_LOWER|C1_UPPER)), "%u: wrong isalpha %x / %x\n", i, pisalpha(i), type );
ok( piscntrl( i ) == (type & C1_CNTRL), "%u: wrong iscntrl %x / %x\n", i, piscntrl( i ), type );
ok( pisdigit( i ) == (type & C1_DIGIT), "%u: wrong isdigit %x / %x\n", i, pisdigit( i ), type );
ok( pisgraph( i ) == (type & (C1_DIGIT|C1_PUNCT|C1_LOWER|C1_UPPER)), "%u: wrong isgraph %x / %x\n", i, pisgraph( i ), type );
ok( pislower( i ) == (type & C1_LOWER), "%u: wrong islower %x / %x\n", i, pislower( i ), type );
ok( pisprint( i ) == (type & (C1_DIGIT|C1_BLANK|C1_PUNCT|C1_LOWER|C1_UPPER)), "%u: wrong isprint %x / %x\n", i, pisprint( i ), type );
ok( pispunct( i ) == (type & C1_PUNCT), "%u: wrong ispunct %x / %x\n", i, pispunct( i ), type );
ok( pisspace( i ) == (type & C1_SPACE), "%u: wrong isspace %x / %x\n", i, pisspace( i ), type );
ok( pisupper( i ) == (type & C1_UPPER), "%u: wrong isupper %x / %x\n", i, pisupper( i ), type );
ok( pisxdigit( i ) == (type & C1_XDIGIT), "%u: wrong isxdigit %x / %x\n", i, pisxdigit( i ), type );
}
}
START_TEST(string)
{
InitFunctionPtrs();
@ -1984,4 +2057,5 @@ START_TEST(string)
test_wcsicmp();
test_sscanf();
test_wctype();
test_ctype();
}