Alexandre Julliard : ntdll: Load the case mapping table in the Unix library.

Alexandre Julliard julliard at winehq.org
Fri Jun 12 16:01:16 CDT 2020


Module: wine
Branch: master
Commit: 573be7e6023e73d736c341bdca1ee49594f56ee4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=573be7e6023e73d736c341bdca1ee49594f56ee4

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Jun 12 10:55:21 2020 +0200

ntdll: Load the case mapping table in the Unix library.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/env.c          | 103 ++++++++++++++++++++---------------------
 dlls/ntdll/unix/unix_private.h |  63 ++++++++++++++++++++++---
 2 files changed, 106 insertions(+), 60 deletions(-)

diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c
index c2674be2c6..8b37d3dcca 100644
--- a/dlls/ntdll/unix/env.c
+++ b/dlls/ntdll/unix/env.c
@@ -65,6 +65,8 @@ extern char **__wine_main_argv;
 extern char **__wine_main_environ;
 extern WCHAR **__wine_main_wargv;
 
+USHORT *uctable = NULL, *lctable = NULL;
+
 static int main_argc;
 static char **main_argv;
 static char **main_envp;
@@ -74,6 +76,36 @@ static CPTABLEINFO unix_table;
 static WCHAR system_locale[LOCALE_NAME_MAX_LENGTH];
 static WCHAR user_locale[LOCALE_NAME_MAX_LENGTH];
 
+static void *read_nls_file( const char *name )
+{
+    const char *dir = build_dir ? build_dir : data_dir;
+    struct stat st;
+    char *path;
+    void *data, *ret = NULL;
+    int fd;
+
+    if (!(path = malloc( strlen(dir) + 22 ))) return NULL;
+    sprintf( path, "%s/nls/%s.nls", dir, name );
+    if ((fd = open( path, O_RDONLY )) != -1)
+    {
+        fstat( fd, &st );
+        if ((data = malloc( st.st_size )) && st.st_size > 0x1000 &&
+            read( fd, data, st.st_size ) == st.st_size)
+        {
+            ret = data;
+        }
+        else
+        {
+            free( data );
+            data = NULL;
+        }
+        close( fd );
+    }
+    else ERR( "failed to load %s\n", path );
+    free( path );
+    return ret;
+}
+
 
 #ifdef __APPLE__
 
@@ -112,31 +144,7 @@ static struct norm_table *nfc_table;
 
 static void init_unix_codepage(void)
 {
-    const char *dir = build_dir ? build_dir : data_dir;
-    struct stat st;
-    char *name;
-    void *data;
-    int fd;
-
-    if (!(name = malloc( strlen(dir) + 17 ))) return;
-    sprintf( name, "%s/nls/normnfc.nls", dir );
-    if ((fd = open( name, O_RDONLY )) != -1)
-    {
-        fstat( fd, &st );
-        if ((data = malloc( st.st_size )) &&
-            st.st_size > 0x4000 &&
-            read( fd, data, st.st_size ) == st.st_size)
-        {
-            nfc_table = data;
-        }
-        else
-        {
-            free( data );
-        }
-        close( fd );
-    }
-    else ERR( "failed to load %s\n", name );
-    free( name );
+    nfc_table = read_nls_file( "normnfc" );
 }
 
 static int get_utf16( const WCHAR *src, unsigned int srclen, unsigned int *ch )
@@ -343,34 +351,6 @@ static const struct { const char *name; UINT cp; } charset_names[] =
     { "UTF8", CP_UTF8 }
 };
 
-static void load_unix_cptable( unsigned int cp )
-{
-    const char *dir = build_dir ? build_dir : data_dir;
-    struct stat st;
-    char *name;
-    void *data;
-    int fd;
-
-    if (!(name = malloc( strlen(dir) + 22 ))) return;
-    sprintf( name, "%s/nls/c_%03u.nls", dir, cp );
-    if ((fd = open( name, O_RDONLY )) != -1)
-    {
-        fstat( fd, &st );
-        if ((data = malloc( st.st_size )) && st.st_size > 0x10000 &&
-            read( fd, data, st.st_size ) == st.st_size)
-        {
-            RtlInitCodePageTable( data, &unix_table );
-        }
-        else
-        {
-            free( data );
-        }
-        close( fd );
-    }
-    else ERR( "failed to load %s\n", name );
-    free( name );
-}
-
 static void init_unix_codepage(void)
 {
     char charset_name[16];
@@ -396,7 +376,14 @@ static void init_unix_codepage(void)
         int res = strcmp( charset_names[pos].name, charset_name );
         if (!res)
         {
-            if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp );
+            if (charset_names[pos].cp != CP_UTF8)
+            {
+                char name[16];
+                void *data;
+
+                sprintf( name, "c_%03u", charset_names[pos].cp );
+                if ((data = read_nls_file( name ))) RtlInitCodePageTable( data, &unix_table );
+            }
             return;
         }
         if (res > 0) max = pos - 1;
@@ -797,9 +784,17 @@ static void init_locale(void)
  */
 void init_environment( int argc, char *argv[], char *envp[] )
 {
+    USHORT *case_table;
+
     init_unix_codepage();
     init_locale();
     set_process_name( argc, argv );
+
+    if ((case_table = read_nls_file( "l_intl" )))
+    {
+        uctable = case_table + 2;
+        lctable = case_table + case_table[1] + 2;
+    }
     __wine_main_argc = main_argc = argc;
     __wine_main_argv = main_argv = argv;
     __wine_main_wargv = main_wargv = build_wargv( argv );
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 1ef2111da1..b672321440 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -123,6 +123,8 @@ extern NTSTATUS CDECL fork_and_exec( const char *unix_name, const char *unix_dir
 extern const char *data_dir DECLSPEC_HIDDEN;
 extern const char *build_dir DECLSPEC_HIDDEN;
 extern const char *config_dir DECLSPEC_HIDDEN;
+extern USHORT *uctable DECLSPEC_HIDDEN;
+extern USHORT *lctable DECLSPEC_HIDDEN;
 extern unsigned int server_cpus DECLSPEC_HIDDEN;
 extern BOOL is_wow64 DECLSPEC_HIDDEN;
 extern HANDLE keyed_event DECLSPEC_HIDDEN;
@@ -212,6 +214,13 @@ static inline int ntdll_wcscmp( const WCHAR *str1, const WCHAR *str2 )
     return *str1 - *str2;
 }
 
+static inline int ntdll_wcsncmp( const WCHAR *str1, const WCHAR *str2, int n )
+{
+    if (n <= 0) return 0;
+    while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
+    return *str1 - *str2;
+}
+
 static inline WCHAR *ntdll_wcschr( const WCHAR *str, WCHAR ch )
 {
     do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
@@ -224,11 +233,53 @@ static inline WCHAR *ntdll_wcspbrk( const WCHAR *str, const WCHAR *accept )
     return NULL;
 }
 
-#define wcslen(str)     ntdll_wcslen(str)
-#define wcscpy(dst,src) ntdll_wcscpy(dst,src)
-#define wcscat(dst,src) ntdll_wcscat(dst,src)
-#define wcscmp(s1,s2)   ntdll_wcscmp(s1,s2)
-#define wcschr(str,ch)  ntdll_wcschr(str,ch)
-#define wcspbrk(str,ac) ntdll_wcspbrk(str,ac)
+static inline WCHAR ntdll_towupper( WCHAR ch )
+{
+    return ch + uctable[uctable[uctable[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)];
+}
+
+static inline WCHAR ntdll_towlower( WCHAR ch )
+{
+    return ch + lctable[lctable[lctable[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)];
+}
+
+static inline WCHAR *ntdll_wcsupr( WCHAR *str )
+{
+    WCHAR *ret;
+    for (ret = str; *str; str++) *str = ntdll_towupper(*str);
+    return ret;
+}
+
+static inline int ntdll_wcsicmp( const WCHAR *str1, const WCHAR *str2 )
+{
+    int ret;
+    for (;;)
+    {
+        if ((ret = ntdll_towupper( *str1 ) - ntdll_towupper( *str2 )) || !*str1) return ret;
+        str1++;
+        str2++;
+    }
+}
+
+static inline int ntdll_wcsnicmp( const WCHAR *str1, const WCHAR *str2, int n )
+{
+    int ret;
+    for (ret = 0; n > 0; n--, str1++, str2++)
+        if ((ret = ntdll_towupper(*str1) - ntdll_towupper(*str2)) || !*str1) break;
+    return ret;
+}
+
+#define wcslen(str)        ntdll_wcslen(str)
+#define wcscpy(dst,src)    ntdll_wcscpy(dst,src)
+#define wcscat(dst,src)    ntdll_wcscat(dst,src)
+#define wcscmp(s1,s2)      ntdll_wcscmp(s1,s2)
+#define wcsncmp(s1,s2,n)   ntdll_wcsncmp(s1,s2,n)
+#define wcschr(str,ch)     ntdll_wcschr(str,ch)
+#define wcspbrk(str,ac)    ntdll_wcspbrk(str,ac)
+#define wcsicmp(s1, s2)    ntdll_wcsicmp(s1,s2)
+#define wcsnicmp(s1, s2,n) ntdll_wcsnicmp(s1,s2,n)
+#define wcsupr(str)        ntdll_wcsupr(str)
+#define towupper(c)        ntdll_towupper(c)
+#define towlower(c)        ntdll_towlower(c)
 
 #endif /* __NTDLL_UNIX_PRIVATE_H */




More information about the wine-cvs mailing list