diff options
-rw-r--r-- | ChangeLog | 49 | ||||
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | src/Makefile.am | 18 | ||||
-rw-r--r-- | src/errnos.in | 2 | ||||
-rw-r--r-- | src/gettext.h | 17 | ||||
-rw-r--r-- | src/gpg-error.c | 199 | ||||
-rw-r--r-- | src/gpg-error.def.in | 30 | ||||
-rw-r--r-- | src/init.c | 233 | ||||
-rw-r--r-- | src/init.h | 65 | ||||
-rw-r--r-- | src/mkstrtable.awk | 4 | ||||
-rw-r--r-- | src/w32-add.h | 24 | ||||
-rw-r--r-- | src/w32-gettext.c | 2092 | ||||
-rw-r--r-- | src/w32-gettext.h | 58 |
13 files changed, 1443 insertions, 1361 deletions
@@ -1,3 +1,52 @@ +2010-01-21 Werner Koch <wk@g10code.com> + + * src/mkstrtable.awk (END): Do not print PREFIX before + LAST_MSGSTR. + + * src/init.c (get_locale_dir): Rework to match what gnupg is doing. + (get_root_key, read_w32_registry_string): Remove. + * src/gpg-error.c (get_locale_dir): Replace by code from init.c + (get_root_key, read_w32_registry_string): Remove. + +2010-01-20 Werner Koch <wk@g10code.com> + + * src/init.c (gpg_err_init): Factor code out to .. + (real_init): .. new. + + * src/Makefile.am (gpg_error_SOURCES): Remove arch_sources. + (export_symbols): Do not prefix gpg-error-def with srcdir. + +2010-01-19 Werner Koch <wk@g10code.com> + + * src/init.c (DllMain): Call _w32_gettext_init. + (get_tls): Use it also for standard Windows. + (DllMain): Ditto. + (struct tls_space_s): Move to .. + (get_tls): Make global. + * src/init.h: .. New. + * src/gettext.h: Do not include w32-gettext.h. + * src/w32-gettext.c: Replace by version from GnuPG. + (my_nl_locale_name) [W32CE]: Do not use getenv. Use + GetSystemDefaultLCID. + (struct loaded_domain): Use uint16_t for NSTRINGS and MAPPED to + save space. + (load_domain): Check for too large MO files. + (utf8_to_wchar): Use gpg_err_set_errno. + (bindtextdomain): Rename to _gpg_w32_bindtextdomain. + (textdomain): Rename to _gpg_w32_textdomain. + (gettext): Rename to _gpg_w32_gettext. + (dgettext): Rename to _gpg_w32_dgettext. + (ngettext): Remove. + (gettext_localename): Rename to _gpg_w32_gettext_localename. + (gettext_select_utf8): Rename to _gpg_w32_gettext_use_utf8. + (_gpg_w32_bindtextdomain): Change to only register the directory. + Return the current directory if asked to. + (do_gettext): Add DOMAINNAME arg and take care of it. + * src/w32-add.h: New. + * src/w32-gettext.h: Remove. + * src/Makefile.am (extra-h.in): Process w32-add.h. + (arch_sources): Remove w32-gettext.h. + 2010-01-18 Werner Koch <wk@g10code.com> * src/init.c (wchar_to_utf8, utf8_to_wchar): New. @@ -76,6 +76,19 @@ b) If you don't have any a trusted version of GnuPG, you can attempt published via the announcement list and probably via Usenet. +Hints +----- + +To build for Windows you you may use the convenience command: + + ./autogen.sh --build-w32 + +which runs configure with suitable options. For WindowsCE the command +is: + + ./autogen.sh --build-w32ce + + Known Problems -------------- diff --git a/src/Makefile.am b/src/Makefile.am index d948021..7c5556c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,11 +38,10 @@ bin_SCRIPTS = gpg-error-config m4datadir = $(datadir)/aclocal m4data_DATA = gpg-error.m4 - EXTRA_DIST = mkstrtable.awk err-sources.h.in err-codes.h.in \ mkerrnos.awk errnos.in README \ mkerrcodes.awk mkerrcodes1.awk mkerrcodes2.awk mkerrcodes.c \ - mkheader.awk gpg-error.h.in mkw32errmap.c w32ce-add.h \ + mkheader.awk gpg-error.h.in mkw32errmap.c w32-add.h w32ce-add.h \ err-sources.h err-codes.h gpg-error-config.in gpg-error.m4 \ gpg-error.def.in versioninfo.rc.in @@ -58,7 +57,7 @@ CLEANFILES = err-sources.h err-codes.h code-to-errno.h code-from-errno.h \ extra-h.in $(tmp_files) if HAVE_W32_SYSTEM -arch_sources = w32-gettext.h w32-gettext.c +arch_sources = w32-gettext.c RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) $(CPPFLAGS) @@ -71,7 +70,7 @@ SUFFIXES = .rc .lo gpg_error_res = versioninfo.lo no_undefined = -no-undefined -export_symbols = -export-symbols $(srcdir)/gpg-error.def +export_symbols = -export-symbols gpg-error.def install-def-file: gpg-error.def $(INSTALL) gpg-error.def $(DESTDIR)$(libdir)/gpg-error.def @@ -100,7 +99,7 @@ libgpg_error_la_LDFLAGS = -version-info \ $(no_undefined) $(export_symbols) libgpg_error_la_SOURCES = gpg-error.h gettext.h $(arch_sources) \ - init.c strsource.c strerror.c code-to-errno.c code-from-errno.c + init.c init.h strsource.c strerror.c code-to-errno.c code-from-errno.c # Note that RCCOMPILE needs the same defines as ..._la_CPPFLAGS but # without the extra_cppflags because they may include am -idirafter @@ -108,7 +107,7 @@ libgpg_error_la_SOURCES = gpg-error.h gettext.h $(arch_sources) \ libgpg_error_la_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) libgpg_error_la_LIBADD = $(gpg_error_res) $(intllibs) -gpg_error_SOURCES = strsource-sym.c strerror-sym.c gpg-error.c $(arch_sources) +gpg_error_SOURCES = strsource-sym.c strerror-sym.c gpg-error.c gpg_error_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) gpg_error_LDADD = ./libgpg-error.la @LTLIBINTL@ @@ -175,10 +174,13 @@ errnos-sym.h: Makefile mkstrtable.awk errnos.in -v prefix=GPG_ERR_ -v namespace=errnos_ \ $(srcdir)/errnos.in >$@ -extra-h.in: Makefile w32ce-add.h +extra-h.in: Makefile w32-add.h w32ce-add.h -rm extra-h.in +if HAVE_W32_SYSTEM + cat $(srcdir)/w32-add.h >>extra-h.in +endif if HAVE_W32CE_SYSTEM - cat $(srcdir)/w32ce-add.h >extra-h.in + cat $(srcdir)/w32ce-add.h >>extra-h.in endif echo EOF >>extra-h.in diff --git a/src/errnos.in b/src/errnos.in index 1c703b8..0688047 100644 --- a/src/errnos.in +++ b/src/errnos.in @@ -169,4 +169,4 @@ 137 EUSERS 138 EWOULDBLOCK 139 EXDEV -140 EXFULL +140 EXFULL
\ No newline at end of file diff --git a/src/gettext.h b/src/gettext.h index 5adda46..aba29db 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -23,15 +23,14 @@ #if ENABLE_NLS #if HAVE_W32_SYSTEM -/* Redirect the gettext calls to an internal implementation on W32 - targets. */ -# include "w32-gettext.h" -#else -/* Get declarations of GNU message catalog functions. */ + /* We have a gettext implementation in gpg-error.h which get + included anyway. */ +#else /*!HAVE_W32_SYSTEM*/ + /* Get declarations of GNU message catalog functions. */ # include <libintl.h> -#endif +#endif /*!HAVE_W32_SYSTEM*/ -#else +#else /*!ENABLE_NLS*/ /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make @@ -61,7 +60,7 @@ # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) -#endif +#endif /*!ENABLE_NLS*/ /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time @@ -72,4 +71,6 @@ initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String + + #endif /* _LIBGETTEXT_H */ diff --git a/src/gpg-error.c b/src/gpg-error.c index 6cfe292..4b3c19a 100644 --- a/src/gpg-error.c +++ b/src/gpg-error.c @@ -66,17 +66,22 @@ i18n_init (void) { #ifdef ENABLE_NLS char *locale_dir; - -# ifdef HAVE_LC_MESSAGES + +#ifdef HAVE_LC_MESSAGES setlocale (LC_TIME, ""); setlocale (LC_MESSAGES, ""); -# else -# ifdef HAVE_W32_SYSTEM -# warning setlocal is missing -# else - setlocale (LC_ALL, "" ); -# endif +#else +# ifndef HAVE_W32_SYSTEM + setlocale (LC_ALL, "" ); # endif +#endif + + /* Note that for this program we would only need the textdomain call + because libgpg-error already initializes itself to its locale dir + (via gpg_err_init or a constructor). However this is only done + for the static standard locale and thus if the above setlocale + calls select a different locale the bindtext below will do + something else. */ locale_dir = get_locale_dir (); if (locale_dir) @@ -93,152 +98,54 @@ i18n_init (void) #include <windows.h> -static HKEY -get_root_key(const char *root) -{ - HKEY root_key; - - if( !root ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) - root_key = HKEY_CLASSES_ROOT; - else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) - root_key = HKEY_LOCAL_MACHINE; - else if( !strcmp( root, "HKEY_USERS" ) ) - root_key = HKEY_USERS; - else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) - root_key = HKEY_PERFORMANCE_DATA; - else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) - root_key = HKEY_CURRENT_CONFIG; - else - return NULL; - return root_key; -} -/**************** - * Return a string from the Win32 Registry or NULL in case of - * error. Caller must release the return value. A NULL for root - * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. - * NOTE: The value is allocated with a plain malloc() - use free() and not - * the usual xfree()!!! - */ static char * -read_w32_registry_string( const char *root, const char *dir, const char *name ) +get_locale_dir (void) { - HKEY root_key, key_handle; - DWORD n1, nbytes, type; - char *result = NULL; - - if ( !(root_key = get_root_key(root) ) ) - return NULL; - - if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) - { - if (root) - return NULL; /* no need for a RegClose, so return direct */ - /* It seems to be common practise to fall back to HKLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* still no need for a RegClose, so return direct */ - } - - nbytes = 1; - if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) { - if (root) - goto leave; - /* Try to fallback to HKLM also vor a missing value. */ - RegCloseKey (key_handle); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* Nope. */ - if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes)) - goto leave; - } - result = malloc( (n1=nbytes+1) ); - if( !result ) - goto leave; - if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) { - free(result); result = NULL; - goto leave; - } - result[nbytes] = 0; /* make sure it is really a string */ -#ifndef HAVE_W32CE_SYSTEM - if (type == REG_EXPAND_SZ && strchr (result, '%')) { - char *tmp; - - n1 += 1000; - tmp = malloc (n1+1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) { - free (tmp); - n1 = nbytes; - tmp = malloc (n1 + 1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) { - free (tmp); /* oops - truncated, better don't expand at all */ - goto leave; - } - tmp[nbytes] = 0; - free (result); - result = tmp; - } - else if (nbytes) { /* okay, reduce the length */ - tmp[nbytes] = 0; - free (result); - result = malloc (strlen (tmp)+1); - if (!result) - result = tmp; - else { - strcpy (result, tmp); - free (tmp); - } - } - else { /* error - don't expand */ - free (tmp); - } - } -#endif /*HAVE_W32CE_SYSTEM*/ - - leave: - RegCloseKey( key_handle ); - return result; -} - + static wchar_t moddir[MAX_PATH+5]; + char *result, *p; + int nbytes; -#define REGKEY "Software\\GNU\\GnuPG" + if (!GetModuleFileNameW (NULL, moddir, MAX_PATH)) + *moddir = 0; -static char * -get_locale_dir (void) -{ - char *instdir; - char *p; - char *dname; - - instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, - "Install Directory"); - if (!instdir) - return NULL; - - /* Build the key: "<instdir>/share/locale". */ #define SLDIR "\\share\\locale" - dname = malloc (strlen (instdir) + strlen (SLDIR) + 1); - if (!dname) + if (*moddir) { - free (instdir); - return NULL; + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL); + if (nbytes < 0) + return NULL; + + result = malloc (nbytes + strlen (SLDIR) + 1); + if (result) + { + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, + result, nbytes, NULL, NULL); + if (nbytes < 0) + { + free (result); + result = NULL; + } + else + { + p = strrchr (result, '\\'); + if (p) + *p = 0; + strcat (result, SLDIR); + } + } } - p = dname; - strcpy (p, instdir); - p += strlen (instdir); - strcpy (p, SLDIR); - - free (instdir); - - return dname; + else /* Use the old default value. */ + { + result = malloc (10 + strlen (SLDIR) + 1); + if (result) + { + strcpy (result, "c:\\gnupg"); + strcat (result, SLDIR); + } + } +#undef SLDIR + return result; } diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index dcf22ac..c563339 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -5,16 +5,24 @@ #include <config.h> EXPORTS - gpg_strerror @1 - gpg_strerror_r @2 - gpg_strsource @3 - gpg_err_code_from_errno @4 - gpg_err_code_to_errno @5 - gpg_err_init @6 - gpg_err_code_from_syserror @7 + gpg_strerror @1 + gpg_strerror_r @2 + gpg_strsource @3 + gpg_err_code_from_errno @4 + gpg_err_code_to_errno @5 + gpg_err_init @6 + gpg_err_code_from_syserror @7 + gpg_err_set_errno @8 #ifdef HAVE_W32CE_SYSTEM - _gpg_w32ce_strerror @8 - _gpg_w32ce_get_errno @9 + _gpg_w32ce_get_errno @9 + _gpg_w32ce_strerror @10 +#endif +#ifdef HAVE_W32_SYSTEM + _gpg_w32_bindtextdomain @11 + _gpg_w32_textdomain @12 + _gpg_w32_gettext @13 + _gpg_w32_dgettext @14 + _gpg_w32_dngettext @15 + _gpg_w32_gettext_localename @16 + _gpg_w32_gettext_use_utf8 @17 #endif - gpg_err_set_errno @10 - @@ -1,5 +1,5 @@ /* init.c - Initialize the GnuPG error library. - Copyright (C) 2005 g10 Code GmbH + Copyright (C) 2005, 2010 g10 Code GmbH This file is part of libgpg-error. @@ -14,9 +14,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with libgpg-error; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ #if HAVE_CONFIG_H #include <config.h> @@ -30,22 +29,13 @@ #include <gpg-error.h> #include "gettext.h" +#include "init.h" /* Locale directory support. */ #if HAVE_W32_SYSTEM -/* 119 bytes for an error message should be enough. With this size we - can assume that the allocation does not take up more than 128 bytes - per thread. */ -#define STRBUFFER_SIZE 120 - -/* The TLS space definition. */ -struct tls_space_s -{ - char strerror_buffer[STRBUFFER_SIZE]; -}; static int tls_index; /* Index for the TLS functions. */ static char *get_locale_dir (void); @@ -59,15 +49,13 @@ static void drop_locale_dir (char *locale_dir); #endif /*!HAVE_W32_SYSTEM*/ -/* Initialize the library. This function should be run early. */ -gpg_error_t -gpg_err_init (void) +static void +real_init (void) { #ifdef ENABLE_NLS char *locale_dir; /* We only have to bind our locale directory to our text domain. */ - locale_dir = get_locale_dir (); if (locale_dir) { @@ -75,7 +63,22 @@ gpg_err_init (void) drop_locale_dir (locale_dir); } #endif +} +/* Initialize the library. This function should be run early. */ +gpg_error_t +gpg_err_init (void) +{ +#ifdef HAVE_W32_SYSTEM + /* We always have a constructor and thus this function is called + automatically. Due to the way the C init code of mingw works, + the constructors are called before our DllMain function is + called. The problem with that is that the TLS has not been setup + and w32-gettext.c requires TLS. To solve this we do nothing here + but call the actual init code from our DllMain. */ +#else + real_init (); +#endif return 0; } @@ -146,164 +149,56 @@ utf8_to_wchar (const char *string) } - -static HKEY -get_root_key(const char *root) -{ - HKEY root_key; - - if( !root ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) - root_key = HKEY_CLASSES_ROOT; - else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) - root_key = HKEY_LOCAL_MACHINE; - else if( !strcmp( root, "HKEY_USERS" ) ) - root_key = HKEY_USERS; - else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) - root_key = HKEY_PERFORMANCE_DATA; - else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) - root_key = HKEY_CURRENT_CONFIG; - else - return NULL; - return root_key; -} - -/**************** - * Return a string from the Win32 Registry or NULL in case of - * error. Caller must release the return value. A NULL for root - * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. - * NOTE: The value is allocated with a plain malloc() - use free() and not - * the usual xfree()!!! - */ static char * -read_w32_registry_string( const char *root, const char *dir, const char *name ) +get_locale_dir (void) { - HKEY root_key, key_handle; - DWORD n1, nbytes, type; - char *result = NULL; + static wchar_t moddir[MAX_PATH+5]; + char *result, *p; + int nbytes; - if ( !(root_key = get_root_key(root) ) ) - return NULL; + if (!GetModuleFileNameW (NULL, moddir, MAX_PATH)) + *moddir = 0; - if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) - { - if (root) - return NULL; /* no need for a RegClose, so return direct */ - /* It seems to be common practise to fall back to HKLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* still no need for a RegClose, so return direct */ - } - - nbytes = 1; - if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) - { - if (root) - goto leave; - /* Try to fallback to HKLM also vor a missing value. */ - RegCloseKey (key_handle); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* Nope. */ - if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes)) - goto leave; - } - result = malloc ( (n1=nbytes+1) ); - if( !result ) - goto leave; - if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) - { - free(result); result = NULL; - goto leave; - } - result[nbytes] = 0; /* make sure it is really a string */ - -#ifndef HAVE_W32CE_SYSTEM /* W32CE has no environment variables. */ - if (type == REG_EXPAND_SZ && strchr (result, '%')) +#define SLDIR "\\share\\locale" + if (*moddir) { - char *tmp; + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL); + if (nbytes < 0) + return NULL; - n1 += 1000; - tmp = malloc (n1+1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) + result = malloc (nbytes + strlen (SLDIR) + 1); + if (result) { - free (tmp); - n1 = nbytes; - tmp = malloc (n1 + 1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, + result, nbytes, NULL, NULL); + if (nbytes < 0) { - free (tmp); /* oops - truncated, better don't expand at all */ - goto leave; + free (result); + result = NULL; + } + else + { + p = strrchr (result, '\\'); + if (p) + *p = 0; + strcat (result, SLDIR); } - tmp[nbytes] = 0; - free (result); - result = tmp; - } - else if (nbytes) /* okay, reduce the length */ - { - tmp[nbytes] = 0; - free (result); - result = malloc (strlen (tmp)+1); - if (!result) - result = tmp; - else { - strcpy (result, tmp); - free (tmp); - } } - else /* error - don't expand */ + } + else /* Use the old default value. */ + { + result = malloc (10 + strlen (SLDIR) + 1); + if (result) { - free (tmp); + strcpy (result, "c:\\gnupg"); + strcat (result, SLDIR); } - } -#endif /*HAVE_W32CE_SYSTEM*/ - - leave: - RegCloseKey( key_handle ); + } +#undef SLDIR return result; } -#define REGKEY "Software\\GNU\\GnuPG" - -static char * -get_locale_dir (void) -{ - char *instdir; - char *p; - char *dname; - - instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, - "Install Directory"); - if (!instdir) - return NULL; - - /* Build the key: "<instdir>/share/locale". */ -#define SLDIR "\\share\\locale" - dname = malloc (strlen (instdir) + strlen (SLDIR) + 1); - if (!dname) - { - free (instdir); - return NULL; - } - p = dname; - strcpy (p, instdir); - p += strlen (instdir); - strcpy (p, SLDIR); - - free (instdir); - - return dname; -} - - static void drop_locale_dir (char *locale_dir) { @@ -313,8 +208,7 @@ drop_locale_dir (char *locale_dir) /* Return the tls object. This function is guaranteed to return a valid non-NULL object. */ -#ifdef HAVE_W32CE_SYSTEM -static struct tls_space_s * +struct tls_space_s * get_tls (void) { struct tls_space_s *tls; @@ -330,12 +224,13 @@ get_tls (void) /* No way to continue - commit suicide. */ abort (); } + tls->gt_use_utf8 = 0; TlsSetValue (tls_index, tls); } return tls; } -#endif /*HAVE_W32CE_SYSTEM*/ + /* Return the value of the ERRNO variable. This needs to be a function so that we can have a per-thread ERRNO. This is used only @@ -397,10 +292,7 @@ gpg_err_set_errno (int err) } -/* Entry point called by the DLL loader. This is only used by - WindowsCE for now; we might eventually use TLS to implement a - thread safe strerror. */ -#ifdef HAVE_W32CE_SYSTEM +/* Entry point called by the DLL loader. */ int WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) { @@ -418,7 +310,12 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) tls = LocalAlloc (LPTR, sizeof *tls); if (!tls) return FALSE; + tls->gt_use_utf8 = 0; TlsSetValue (tls_index, tls); + if (reason == DLL_PROCESS_ATTACH) + { + real_init (); + } break; case DLL_THREAD_DETACH: @@ -440,7 +337,7 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) return TRUE; } -#endif /*HAVE_W32CE_SYSTEM*/ + #else /*!HAVE_W32_SYSTEM*/ diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000..0fa27be --- /dev/null +++ b/src/init.h @@ -0,0 +1,65 @@ +/* init.h - Declarations for init.c + Copyright (C) 2010 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INIT_H +#define INIT_H + +#if HAVE_W32_SYSTEM + +/* Forward declaration - defined in w32-gettext.c. */ +struct loaded_domain; + +/* An item for a linked list of loaded domains. */ +struct domainlist_s +{ + struct domainlist_s *next; + char *dname; /* Directory name for the mo file. */ + char *fname; /* File name for the MO file. */ + int load_failed; /* True if loading the domain failed. */ + struct loaded_domain *domain; /* NULL if not loaded. Never changed + once set to non-NULL. */ + char name[1]; /* Name of the domain. Never changed + once set. */ +}; + + + +/* 119 bytes for an error message should be enough. With this size we + can assume that the allocation does not take up more than 128 bytes + per thread. Note that this is only used for W32CE. */ +#define STRBUFFER_SIZE 120 + +/* The TLS space definition. */ +struct tls_space_s +{ + /* Flag used by w32-gettext. */ + int gt_use_utf8; + +#ifdef HAVE_W32CE_SYSTEM + char strerror_buffer[STRBUFFER_SIZE]; +#endif +}; + +/* Return the TLS. */ +struct tls_space_s *get_tls (void); + + +#endif /*HAVE_W32_SYSTEM*/ + +#endif /*INIT_H*/ diff --git a/src/mkstrtable.awk b/src/mkstrtable.awk index 8135ba7..d97e150 100644 --- a/src/mkstrtable.awk +++ b/src/mkstrtable.awk @@ -146,9 +146,9 @@ END { coded_msgs = msg; if (nogettext) - print " \"" prefix last_msgstr "\";"; + print " \"" last_msgstr "\";"; else - print " gettext_noop (\"" prefix last_msgstr "\");"; + print " gettext_noop (\"" last_msgstr "\");"; print ""; print "static const int " namespace "msgidx[] ="; print " {"; diff --git a/src/w32-add.h b/src/w32-add.h new file mode 100644 index 0000000..9bbf6b9 --- /dev/null +++ b/src/w32-add.h @@ -0,0 +1,24 @@ +## w32-add.h - Snippet to be be included into gpg-error.h. +## (Comments are indicated by a double hash mark) + +/* A lean gettext implementation based on GNU style mo files which are + required to be encoded in UTF-8. There is a limit on 65534 entries + to save some RAM. Only Germanic plural rules are supported. */ +const char *_gpg_w32_bindtextdomain (const char *domainname, + const char *dirname); +const char *_gpg_w32_textdomain (const char *domainname); +const char *_gpg_w32_gettext (const char *msgid); +const char *_gpg_w32_dgettext (const char *domainname, const char *msgid); +const char *_gpg_w32_dngettext (const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n); +const char *_gpg_w32_gettext_localename (void); +int _gpg_w32_gettext_use_utf8 (int value); + +#define bindtextdomain(a,b) _gpg_w32_bindtextdomain ((a), (b)) +#define textdomain(a) _gpg_w32_textdomain ((a)) +#define gettext(a) _gpg_w32_gettext ((a)) +#define dgettext(a,b) _gpg_w32_dgettext ((a), (b)) +#define ngettext(a,b,c) _gpg_w32_dngettext (NULL, (a), (b), (c)) +#define dngettext(a,b,c,d) _gpg_w32_dngettext ((a), (b), (c), (d)) +#define gettext_localname() _gpg_w32_gettext_localename () +#define gettext_use_utf8(a) _gpg_w32_gettext_use_utf8 (a) diff --git a/src/w32-gettext.c b/src/w32-gettext.c index 1b6eb3d..a35af1f 100644 --- a/src/w32-gettext.c +++ b/src/w32-gettext.c @@ -1,6 +1,6 @@ /* w32-gettext.h - A simple gettext implementation for Windows targets. - Copyright (C) 1995,1996,1997,1999,2005 Free Software Foundation, Inc. - Copyright (C) 2005 g10 Code GmbH + Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007, +2 2008, 2010 Free Software Foundation, Inc. This file is part of libgpg-error. @@ -15,13 +15,15 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with libgpg-error; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ #if HAVE_CONFIG_H #include <config.h> #endif +#if !defined (_WIN32) && !defined (__CYGWIN32__) +# error This module may only be build for Windows or Cygwin32 +#endif #include <stdlib.h> #include <stdio.h> @@ -31,16 +33,27 @@ #include <sys/types.h> #include <sys/stat.h> #include <stdint.h> +#ifndef HAVE_W32CE_SYSTEM +# include <locale.h> +#endif /*HAVE_W32CE_SYSTEM*/ +#include <windows.h> -#include <gpg-error.h> +#ifdef JNLIB_IN_JNLIB +#include "libjnlib-config.h" +#endif -#include "gettext.h" +#ifndef jnlib_malloc +# define jnlib_malloc(a) malloc ((a)) +# define jnlib_calloc(a,b) calloc ((a), (b)) +# define jnlib_free(a) free ((a)) +# define jnlib_xstrdup(a) not_used +#endif /*!jnlib_malloc*/ + +#include "init.h" - -/* localname.c from gettext. */ -/* Edit: Added a "static" to _nl_locale_name. Note that the category - argument is ignored on w32. */ + +/* localname.c from gettext BEGIN. */ /* Determine the current selected locale. Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. @@ -62,716 +75,543 @@ /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */ /* Win32 code written by Tor Lillqvist <tml@iki.fi>. */ +/* Renamed _nl_locale_name, removed unsed args, removed include files, + non-W32 code and changed comments <wk@gnupg.org>. */ -#ifdef HAVE_CONFIG_H -# include <config.h> +/* Mingw headers don't have latest language and sublanguage codes. */ +#ifndef LANG_AFRIKAANS +#define LANG_AFRIKAANS 0x36 #endif - -#include <stdlib.h> -#ifndef HAVE_W32CE_SYSTEM -# include <locale.h> +#ifndef LANG_ALBANIAN +#define LANG_ALBANIAN 0x1c #endif - -#ifdef HAVE_W32_SYSTEM -# include <windows.h> -/* List of language codes, sorted by value: - 0x01 LANG_ARABIC - 0x02 LANG_BULGARIAN - 0x03 LANG_CATALAN - 0x04 LANG_CHINESE - 0x05 LANG_CZECH - 0x06 LANG_DANISH - 0x07 LANG_GERMAN - 0x08 LANG_GREEK - 0x09 LANG_ENGLISH - 0x0a LANG_SPANISH - 0x0b LANG_FINNISH - 0x0c LANG_FRENCH - 0x0d LANG_HEBREW - 0x0e LANG_HUNGARIAN - 0x0f LANG_ICELANDIC - 0x10 LANG_ITALIAN - 0x11 LANG_JAPANESE - 0x12 LANG_KOREAN - 0x13 LANG_DUTCH - 0x14 LANG_NORWEGIAN - 0x15 LANG_POLISH - 0x16 LANG_PORTUGUESE - 0x17 LANG_RHAETO_ROMANCE - 0x18 LANG_ROMANIAN - 0x19 LANG_RUSSIAN - 0x1a LANG_CROATIAN == LANG_SERBIAN - 0x1b LANG_SLOVAK - 0x1c LANG_ALBANIAN - 0x1d LANG_SWEDISH - 0x1e LANG_THAI - 0x1f LANG_TURKISH - 0x20 LANG_URDU - 0x21 LANG_INDONESIAN - 0x22 LANG_UKRAINIAN - 0x23 LANG_BELARUSIAN - 0x24 LANG_SLOVENIAN - 0x25 LANG_ESTONIAN - 0x26 LANG_LATVIAN - 0x27 LANG_LITHUANIAN - 0x28 LANG_TAJIK - 0x29 LANG_FARSI - 0x2a LANG_VIETNAMESE - 0x2b LANG_ARMENIAN - 0x2c LANG_AZERI - 0x2d LANG_BASQUE - 0x2e LANG_SORBIAN - 0x2f LANG_MACEDONIAN - 0x30 LANG_SUTU - 0x31 LANG_TSONGA - 0x32 LANG_TSWANA - 0x33 LANG_VENDA - 0x34 LANG_XHOSA - 0x35 LANG_ZULU - 0x36 LANG_AFRIKAANS - 0x37 LANG_GEORGIAN - 0x38 LANG_FAEROESE - 0x39 LANG_HINDI - 0x3a LANG_MALTESE - 0x3b LANG_SAAMI - 0x3c LANG_GAELIC - 0x3d LANG_YIDDISH - 0x3e LANG_MALAY - 0x3f LANG_KAZAK - 0x40 LANG_KYRGYZ - 0x41 LANG_SWAHILI - 0x42 LANG_TURKMEN - 0x43 LANG_UZBEK - 0x44 LANG_TATAR - 0x45 LANG_BENGALI - 0x46 LANG_PUNJABI - 0x47 LANG_GUJARATI - 0x48 LANG_ORIYA - 0x49 LANG_TAMIL - 0x4a LANG_TELUGU - 0x4b LANG_KANNADA - 0x4c LANG_MALAYALAM - 0x4d LANG_ASSAMESE - 0x4e LANG_MARATHI - 0x4f LANG_SANSKRIT - 0x50 LANG_MONGOLIAN - 0x51 LANG_TIBETAN - 0x52 LANG_WELSH - 0x53 LANG_CAMBODIAN - 0x54 LANG_LAO - 0x55 LANG_BURMESE - 0x56 LANG_GALICIAN - 0x57 LANG_KONKANI - 0x58 LANG_MANIPURI - 0x59 LANG_SINDHI - 0x5a LANG_SYRIAC - 0x5b LANG_SINHALESE - 0x5c LANG_CHEROKEE - 0x5d LANG_INUKTITUT - 0x5e LANG_AMHARIC - 0x5f LANG_TAMAZIGHT - 0x60 LANG_KASHMIRI - 0x61 LANG_NEPALI - 0x62 LANG_FRISIAN - 0x63 LANG_PASHTO - 0x64 LANG_TAGALOG - 0x65 LANG_DIVEHI - 0x66 LANG_EDO - 0x67 LANG_FULFULDE - 0x68 LANG_HAUSA - 0x69 LANG_IBIBIO - 0x6a LANG_YORUBA - 0x70 LANG_IGBO - 0x71 LANG_KANURI - 0x72 LANG_OROMO - 0x73 LANG_TIGRINYA - 0x74 LANG_GUARANI - 0x75 LANG_HAWAIIAN - 0x76 LANG_LATIN - 0x77 LANG_SOMALI - 0x78 LANG_YI - 0x79 LANG_PAPIAMENTU -*/ -/* Mingw headers don't have latest language and sublanguage codes. */ -# ifndef LANG_AFRIKAANS -# define LANG_AFRIKAANS 0x36 -# endif -# ifndef LANG_ALBANIAN -# define LANG_ALBANIAN 0x1c -# endif -# ifndef LANG_AMHARIC -# define LANG_AMHARIC 0x5e -# endif -# ifndef LANG_ARABIC -# define LANG_ARABIC 0x01 -# endif -# ifndef LANG_ARMENIAN -# define LANG_ARMENIAN 0x2b -# endif -# ifndef LANG_ASSAMESE -# define LANG_ASSAMESE 0x4d -# endif -# ifndef LANG_AZERI -# define LANG_AZERI 0x2c -# endif -# ifndef LANG_BASQUE -# define LANG_BASQUE 0x2d -# endif -# ifndef LANG_BELARUSIAN -# define LANG_BELARUSIAN 0x23 -# endif -# ifndef LANG_BENGALI -# define LANG_BENGALI 0x45 -# endif -# ifndef LANG_BURMESE -# define LANG_BURMESE 0x55 -# endif -# ifndef LANG_CAMBODIAN -# define LANG_CAMBODIAN 0x53 -# endif -# ifndef LANG_CATALAN -# define LANG_CATALAN 0x03 -# endif -# ifndef LANG_CHEROKEE -# define LANG_CHEROKEE 0x5c -# endif -# ifndef LANG_DIVEHI -# define LANG_DIVEHI 0x65 -# endif -# ifndef LANG_EDO -# define LANG_EDO 0x66 -# endif -# ifndef LANG_ESTONIAN -# define LANG_ESTONIAN 0x25 -# endif -# ifndef LANG_FAEROESE -# define LANG_FAEROESE 0x38 -# endif -# ifndef LANG_FARSI -# define LANG_FARSI 0x29 -# endif -# ifndef LANG_FRISIAN -# define LANG_FRISIAN 0x62 -# endif -# ifndef LANG_FULFULDE -# define LANG_FULFULDE 0x67 -# endif -# ifndef LANG_GAELIC -# define LANG_GAELIC 0x3c -# endif -# ifndef LANG_GALICIAN -# define LANG_GALICIAN 0x56 -# endif -# ifndef LANG_GEORGIAN -# define LANG_GEORGIAN 0x37 -# endif -# ifndef LANG_GUARANI -# define LANG_GUARANI 0x74 -# endif -# ifndef LANG_GUJARATI -# define LANG_GUJARATI 0x47 -# endif -# ifndef LANG_HAUSA -# define LANG_HAUSA 0x68 -# endif -# ifndef LANG_HAWAIIAN -# define LANG_HAWAIIAN 0x75 -# endif -# ifndef LANG_HEBREW -# define LANG_HEBREW 0x0d -# endif -# ifndef LANG_HINDI -# define LANG_HINDI 0x39 -# endif -# ifndef LANG_IBIBIO -# define LANG_IBIBIO 0x69 -# endif -# ifndef LANG_IGBO -# define LANG_IGBO 0x70 -# endif -# ifndef LANG_INDONESIAN -# define LANG_INDONESIAN 0x21 -# endif -# ifndef LANG_INUKTITUT -# define LANG_INUKTITUT 0x5d -# endif -# ifndef LANG_KANNADA -# define LANG_KANNADA 0x4b -# endif -# ifndef LANG_KANURI -# define LANG_KANURI 0x71 -# endif -# ifndef LANG_KASHMIRI -# define LANG_KASHMIRI 0x60 -# endif -# ifndef LANG_KAZAK -# define LANG_KAZAK 0x3f -# endif -# ifndef LANG_KONKANI -# define LANG_KONKANI 0x57 -# endif -# ifndef LANG_KYRGYZ -# define LANG_KYRGYZ 0x40 -# endif -# ifndef LANG_LAO -# define LANG_LAO 0x54 -# endif -# ifndef LANG_LATIN -# define LANG_LATIN 0x76 -# endif -# ifndef LANG_LATVIAN -# define LANG_LATVIAN 0x26 -# endif -# ifndef LANG_LITHUANIAN -# define LANG_LITHUANIAN 0x27 -# endif -# ifndef LANG_MACEDONIAN -# define LANG_MACEDONIAN 0x2f -# endif -# ifndef LANG_MALAY -# define LANG_MALAY 0x3e -# endif -# ifndef LANG_MALAYALAM -# define LANG_MALAYALAM 0x4c -# endif -# ifndef LANG_MALTESE -# define LANG_MALTESE 0x3a -# endif -# ifndef LANG_MANIPURI -# define LANG_MANIPURI 0x58 -# endif -# ifndef LANG_MARATHI -# define LANG_MARATHI 0x4e -# endif -# ifndef LANG_MONGOLIAN -# define LANG_MONGOLIAN 0x50 -# endif -# ifndef LANG_NEPALI -# define LANG_NEPALI 0x61 -# endif -# ifndef LANG_ORIYA -# define LANG_ORIYA 0x48 -# endif -# ifndef LANG_OROMO -# define LANG_OROMO 0x72 -# endif -# ifndef LANG_PAPIAMENTU -# define LANG_PAPIAMENTU 0x79 -# endif -# ifndef LANG_PASHTO -# define LANG_PASHTO 0x63 -# endif -# ifndef LANG_PUNJABI -# define LANG_PUNJABI 0x46 -# endif -# ifndef LANG_RHAETO_ROMANCE -# define LANG_RHAETO_ROMANCE 0x17 -# endif -# ifndef LANG_SAAMI -# define LANG_SAAMI 0x3b -# endif -# ifndef LANG_SANSKRIT -# define LANG_SANSKRIT 0x4f -# endif -# ifndef LANG_SERBIAN -# define LANG_SERBIAN 0x1a -# endif -# ifndef LANG_SINDHI -# define LANG_SINDHI 0x59 -# endif -# ifndef LANG_SINHALESE -# define LANG_SINHALESE 0x5b -# endif -# ifndef LANG_SLOVAK -# define LANG_SLOVAK 0x1b -# endif -# ifndef LANG_SOMALI -# define LANG_SOMALI 0x77 -# endif -# ifndef LANG_SORBIAN -# define LANG_SORBIAN 0x2e -# endif -# ifndef LANG_SUTU -# define LANG_SUTU 0x30 -# endif -# ifndef LANG_SWAHILI -# define LANG_SWAHILI 0x41 -# endif -# ifndef LANG_SYRIAC -# define LANG_SYRIAC 0x5a -# endif -# ifndef LANG_TAGALOG -# define LANG_TAGALOG 0x64 -# endif -# ifndef LANG_TAJIK -# define LANG_TAJIK 0x28 -# endif -# ifndef LANG_TAMAZIGHT -# define LANG_TAMAZIGHT 0x5f -# endif -# ifndef LANG_TAMIL -# define LANG_TAMIL 0x49 -# endif -# ifndef LANG_TATAR -# define LANG_TATAR 0x44 -# endif -# ifndef LANG_TELUGU -# define LANG_TELUGU 0x4a -# endif -# ifndef LANG_THAI -# define LANG_THAI 0x1e -# endif -# ifndef LANG_TIBETAN -# define LANG_TIBETAN 0x51 -# endif -# ifndef LANG_TIGRINYA -# define LANG_TIGRINYA 0x73 -# endif -# ifndef LANG_TSONGA -# define LANG_TSONGA 0x31 -# endif -# ifndef LANG_TSWANA -# define LANG_TSWANA 0x32 -# endif -# ifndef LANG_TURKMEN -# define LANG_TURKMEN 0x42 -# endif -# ifndef LANG_UKRAINIAN -# define LANG_UKRAINIAN 0x22 -# endif -# ifndef LANG_URDU -# define LANG_URDU 0x20 -# endif -# ifndef LANG_UZBEK -# define LANG_UZBEK 0x43 -# endif -# ifndef LANG_VENDA -# define LANG_VENDA 0x33 -# endif -# ifndef LANG_VIETNAMESE -# define LANG_VIETNAMESE 0x2a -# endif -# ifndef LANG_WELSH -# define LANG_WELSH 0x52 -# endif -# ifndef LANG_XHOSA -# define LANG_XHOSA 0x34 -# endif -# ifndef LANG_YI -# define LANG_YI 0x78 -# endif -# ifndef LANG_YIDDISH -# define LANG_YIDDISH 0x3d -# endif -# ifndef LANG_YORUBA -# define LANG_YORUBA 0x6a -# endif -# ifndef LANG_ZULU -# define LANG_ZULU 0x35 -# endif -# ifndef SUBLANG_ARABIC_SAUDI_ARABIA -# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 -# endif -# ifndef SUBLANG_ARABIC_IRAQ -# define SUBLANG_ARABIC_IRAQ 0x02 -# endif -# ifndef SUBLANG_ARABIC_EGYPT -# define SUBLANG_ARABIC_EGYPT 0x03 -# endif -# ifndef SUBLANG_ARABIC_LIBYA -# define SUBLANG_ARABIC_LIBYA 0x04 -# endif -# ifndef SUBLANG_ARABIC_ALGERIA -# define SUBLANG_ARABIC_ALGERIA 0x05 -# endif -# ifndef SUBLANG_ARABIC_MOROCCO -# define SUBLANG_ARABIC_MOROCCO 0x06 -# endif -# ifndef SUBLANG_ARABIC_TUNISIA -# define SUBLANG_ARABIC_TUNISIA 0x07 -# endif -# ifndef SUBLANG_ARABIC_OMAN -# define SUBLANG_ARABIC_OMAN 0x08 -# endif -# ifndef SUBLANG_ARABIC_YEMEN -# define SUBLANG_ARABIC_YEMEN 0x09 -# endif -# ifndef SUBLANG_ARABIC_SYRIA -# define SUBLANG_ARABIC_SYRIA 0x0a -# endif -# ifndef SUBLANG_ARABIC_JORDAN -# define SUBLANG_ARABIC_JORDAN 0x0b -# endif -# ifndef SUBLANG_ARABIC_LEBANON -# define SUBLANG_ARABIC_LEBANON 0x0c -# endif -# ifndef SUBLANG_ARABIC_KUWAIT -# define SUBLANG_ARABIC_KUWAIT 0x0d -# endif -# ifndef SUBLANG_ARABIC_UAE -# define SUBLANG_ARABIC_UAE 0x0e -# endif -# ifndef SUBLANG_ARABIC_BAHRAIN -# define SUBLANG_ARABIC_BAHRAIN 0x0f -# endif -# ifndef SUBLANG_ARABIC_QATAR -# define SUBLANG_ARABIC_QATAR 0x10 -# endif -# ifndef SUBLANG_AZERI_LATIN -# define SUBLANG_AZERI_LATIN 0x01 -# endif -# ifndef SUBLANG_AZERI_CYRILLIC -# define SUBLANG_AZERI_CYRILLIC 0x02 -# endif -# ifndef SUBLANG_BENGALI_INDIA -# define SUBLANG_BENGALI_INDIA 0x01 -# endif -# ifndef SUBLANG_BENGALI_BANGLADESH -# define SUBLANG_BENGALI_BANGLADESH 0x02 -# endif -# ifndef SUBLANG_CHINESE_MACAU -# define SUBLANG_CHINESE_MACAU 0x05 -# endif -# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA -# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 -# endif -# ifndef SUBLANG_ENGLISH_JAMAICA -# define SUBLANG_ENGLISH_JAMAICA 0x08 -# endif -# ifndef SUBLANG_ENGLISH_CARIBBEAN -# define SUBLANG_ENGLISH_CARIBBEAN 0x09 -# endif -# ifndef SUBLANG_ENGLISH_BELIZE -# define SUBLANG_ENGLISH_BELIZE 0x0a -# endif -# ifndef SUBLANG_ENGLISH_TRINIDAD -# define SUBLANG_ENGLISH_TRINIDAD 0x0b -# endif -# ifndef SUBLANG_ENGLISH_ZIMBABWE -# define SUBLANG_ENGLISH_ZIMBABWE 0x0c -# endif -# ifndef SUBLANG_ENGLISH_PHILIPPINES -# define SUBLANG_ENGLISH_PHILIPPINES 0x0d -# endif -# ifndef SUBLANG_ENGLISH_INDONESIA -# define SUBLANG_ENGLISH_INDONESIA 0x0e -# endif -# ifndef SUBLANG_ENGLISH_HONGKONG -# define SUBLANG_ENGLISH_HONGKONG 0x0f -# endif -# ifndef SUBLANG_ENGLISH_INDIA -# define SUBLANG_ENGLISH_INDIA 0x10 -# endif -# ifndef SUBLANG_ENGLISH_MALAYSIA -# define SUBLANG_ENGLISH_MALAYSIA 0x11 -# endif -# ifndef SUBLANG_ENGLISH_SINGAPORE -# define SUBLANG_ENGLISH_SINGAPORE 0x12 -# endif -# ifndef SUBLANG_FRENCH_LUXEMBOURG -# define SUBLANG_FRENCH_LUXEMBOURG 0x05 -# endif -# ifndef SUBLANG_FRENCH_MONACO -# define SUBLANG_FRENCH_MONACO 0x06 -# endif -# ifndef SUBLANG_FRENCH_WESTINDIES -# define SUBLANG_FRENCH_WESTINDIES 0x07 -# endif -# ifndef SUBLANG_FRENCH_REUNION -# define SUBLANG_FRENCH_REUNION 0x08 -# endif -# ifndef SUBLANG_FRENCH_CONGO -# define SUBLANG_FRENCH_CONGO 0x09 -# endif -# ifndef SUBLANG_FRENCH_SENEGAL -# define SUBLANG_FRENCH_SENEGAL 0x0a -# endif -# ifndef SUBLANG_FRENCH_CAMEROON -# define SUBLANG_FRENCH_CAMEROON 0x0b -# endif -# ifndef SUBLANG_FRENCH_COTEDIVOIRE -# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c -# endif -# ifndef SUBLANG_FRENCH_MALI -# define SUBLANG_FRENCH_MALI 0x0d -# endif -# ifndef SUBLANG_FRENCH_MOROCCO -# define SUBLANG_FRENCH_MOROCCO 0x0e -# endif -# ifndef SUBLANG_FRENCH_HAITI -# define SUBLANG_FRENCH_HAITI 0x0f -# endif -# ifndef SUBLANG_GERMAN_LUXEMBOURG -# define SUBLANG_GERMAN_LUXEMBOURG 0x04 -# endif -# ifndef SUBLANG_GERMAN_LIECHTENSTEIN -# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 -# endif -# ifndef SUBLANG_KASHMIRI_INDIA -# define SUBLANG_KASHMIRI_INDIA 0x02 -# endif -# ifndef SUBLANG_MALAY_MALAYSIA -# define SUBLANG_MALAY_MALAYSIA 0x01 -# endif -# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM -# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 -# endif -# ifndef SUBLANG_NEPALI_INDIA -# define SUBLANG_NEPALI_INDIA 0x02 -# endif -# ifndef SUBLANG_PUNJABI_INDIA -# define SUBLANG_PUNJABI_INDIA 0x01 -# endif -# ifndef SUBLANG_ROMANIAN_ROMANIA -# define SUBLANG_ROMANIAN_ROMANIA 0x01 -# endif -# ifndef SUBLANG_SERBIAN_LATIN -# define SUBLANG_SERBIAN_LATIN 0x02 -# endif -# ifndef SUBLANG_SERBIAN_CYRILLIC -# define SUBLANG_SERBIAN_CYRILLIC 0x03 -# endif -# ifndef SUBLANG_SINDHI_INDIA -# define SUBLANG_SINDHI_INDIA 0x00 -# endif -# ifndef SUBLANG_SINDHI_PAKISTAN -# define SUBLANG_SINDHI_PAKISTAN 0x01 -# endif -# ifndef SUBLANG_SPANISH_GUATEMALA -# define SUBLANG_SPANISH_GUATEMALA 0x04 -# endif -# ifndef SUBLANG_SPANISH_COSTA_RICA -# define SUBLANG_SPANISH_COSTA_RICA 0x05 -# endif -# ifndef SUBLANG_SPANISH_PANAMA -# define SUBLANG_SPANISH_PANAMA 0x06 -# endif -# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC -# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 -# endif -# ifndef SUBLANG_SPANISH_VENEZUELA -# define SUBLANG_SPANISH_VENEZUELA 0x08 -# endif -# ifndef SUBLANG_SPANISH_COLOMBIA -# define SUBLANG_SPANISH_COLOMBIA 0x09 -# endif -# ifndef SUBLANG_SPANISH_PERU -# define SUBLANG_SPANISH_PERU 0x0a -# endif -# ifndef SUBLANG_SPANISH_ARGENTINA -# define SUBLANG_SPANISH_ARGENTINA 0x0b -# endif -# ifndef SUBLANG_SPANISH_ECUADOR -# define SUBLANG_SPANISH_ECUADOR 0x0c -# endif -# ifndef SUBLANG_SPANISH_CHILE -# define SUBLANG_SPANISH_CHILE 0x0d -# endif -# ifndef SUBLANG_SPANISH_URUGUAY -# define SUBLANG_SPANISH_URUGUAY 0x0e -# endif -# ifndef SUBLANG_SPANISH_PARAGUAY -# define SUBLANG_SPANISH_PARAGUAY 0x0f -# endif -# ifndef SUBLANG_SPANISH_BOLIVIA -# define SUBLANG_SPANISH_BOLIVIA 0x10 -# endif -# ifndef SUBLANG_SPANISH_EL_SALVADOR -# define SUBLANG_SPANISH_EL_SALVADOR 0x11 -# endif -# ifndef SUBLANG_SPANISH_HONDURAS -# define SUBLANG_SPANISH_HONDURAS 0x12 -# endif -# ifndef SUBLANG_SPANISH_NICARAGUA -# define SUBLANG_SPANISH_NICARAGUA 0x13 -# endif -# ifndef SUBLANG_SPANISH_PUERTO_RICO -# define SUBLANG_SPANISH_PUERTO_RICO 0x14 -# endif -# ifndef SUBLANG_SWEDISH_FINLAND -# define SUBLANG_SWEDISH_FINLAND 0x02 -# endif -# ifndef SUBLANG_TAMAZIGHT_ARABIC -# define SUBLANG_TAMAZIGHT_ARABIC 0x01 -# endif -# ifndef SUBLANG_TAMAZIGHT_LATIN -# define SUBLANG_TAMAZIGHT_LATIN 0x02 -# endif -# ifndef SUBLANG_TIGRINYA_ETHIOPIA -# define SUBLANG_TIGRINYA_ETHIOPIA 0x00 -# endif -# ifndef SUBLANG_TIGRINYA_ERITREA -# define SUBLANG_TIGRINYA_ERITREA 0x01 -# endif -# ifndef SUBLANG_URDU_PAKISTAN -# define SUBLANG_URDU_PAKISTAN 0x01 -# endif -# ifndef SUBLANG_URDU_INDIA -# define SUBLANG_URDU_INDIA 0x02 -# endif -# ifndef SUBLANG_UZBEK_LATIN -# define SUBLANG_UZBEK_LATIN 0x01 -# endif -# ifndef SUBLANG_UZBEK_CYRILLIC -# define SUBLANG_UZBEK_CYRILLIC 0x02 -# endif -#endif /* HAVE_W32_SYSTEM */ - -/* XPG3 defines the result of 'setlocale (category, NULL)' as: - "Directs 'setlocale()' to query 'category' and return the current - setting of 'local'." - However it does not specify the exact format. Neither do SUSV2 and - ISO C 99. So we can use this feature only on selected systems (e.g. - those using GNU C Library). */ -#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2) -# define HAVE_LOCALE_NULL -#endif - -/* Determine the current locale's name, and canonicalize it into XPG syntax - language[_territory[.codeset]][@modifier] - The codeset part in the result is not reliable; the locale_charset() - should be used for codeset information instead. - The result must not be freed; it is statically allocated. */ - +#ifndef LANG_AMHARIC +#define LANG_AMHARIC 0x5e +#endif +#ifndef LANG_ARABIC +#define LANG_ARABIC 0x01 +#endif +#ifndef LANG_ARMENIAN +#define LANG_ARMENIAN 0x2b +#endif +#ifndef LANG_ASSAMESE +#define LANG_ASSAMESE 0x4d +#endif +#ifndef LANG_AZERI +#define LANG_AZERI 0x2c +#endif +#ifndef LANG_BASQUE +#define LANG_BASQUE 0x2d +#endif +#ifndef LANG_BELARUSIAN +#define LANG_BELARUSIAN 0x23 +#endif +#ifndef LANG_BENGALI +#define LANG_BENGALI 0x45 +#endif +#ifndef LANG_BURMESE +#define LANG_BURMESE 0x55 +#endif +#ifndef LANG_CAMBODIAN +#define LANG_CAMBODIAN 0x53 +#endif +#ifndef LANG_CATALAN +#define LANG_CATALAN 0x03 +#endif +#ifndef LANG_CHEROKEE +#define LANG_CHEROKEE 0x5c +#endif +#ifndef LANG_DIVEHI +#define LANG_DIVEHI 0x65 +#endif +#ifndef LANG_EDO +#define LANG_EDO 0x66 +#endif +#ifndef LANG_ESTONIAN +#define LANG_ESTONIAN 0x25 +#endif +#ifndef LANG_FAEROESE +#define LANG_FAEROESE 0x38 +#endif +#ifndef LANG_FARSI +#define LANG_FARSI 0x29 +#endif +#ifndef LANG_FRISIAN +#define LANG_FRISIAN 0x62 +#endif +#ifndef LANG_FULFULDE +#define LANG_FULFULDE 0x67 +#endif +#ifndef LANG_GAELIC +#define LANG_GAELIC 0x3c +#endif +#ifndef LANG_GALICIAN +#define LANG_GALICIAN 0x56 +#endif +#ifndef LANG_GEORGIAN +#define LANG_GEORGIAN 0x37 +#endif +#ifndef LANG_GUARANI +#define LANG_GUARANI 0x74 +#endif +#ifndef LANG_GUJARATI +#define LANG_GUJARATI 0x47 +#endif +#ifndef LANG_HAUSA +#define LANG_HAUSA 0x68 +#endif +#ifndef LANG_HAWAIIAN +#define LANG_HAWAIIAN 0x75 +#endif +#ifndef LANG_HEBREW +#define LANG_HEBREW 0x0d +#endif +#ifndef LANG_HINDI +#define LANG_HINDI 0x39 +#endif +#ifndef LANG_IBIBIO +#define LANG_IBIBIO 0x69 +#endif +#ifndef LANG_IGBO +#define LANG_IGBO 0x70 +#endif +#ifndef LANG_INDONESIAN +#define LANG_INDONESIAN 0x21 +#endif +#ifndef LANG_INUKTITUT +#define LANG_INUKTITUT 0x5d +#endif +#ifndef LANG_KANNADA +#define LANG_KANNADA 0x4b +#endif +#ifndef LANG_KANURI +#define LANG_KANURI 0x71 +#endif +#ifndef LANG_KASHMIRI +#define LANG_KASHMIRI 0x60 +#endif +#ifndef LANG_KAZAK +#define LANG_KAZAK 0x3f +#endif +#ifndef LANG_KONKANI +#define LANG_KONKANI 0x57 +#endif +#ifndef LANG_KYRGYZ +#define LANG_KYRGYZ 0x40 +#endif +#ifndef LANG_LAO +#define LANG_LAO 0x54 +#endif +#ifndef LANG_LATIN +#define LANG_LATIN 0x76 +#endif +#ifndef LANG_LATVIAN +#define LANG_LATVIAN 0x26 +#endif +#ifndef LANG_LITHUANIAN +#define LANG_LITHUANIAN 0x27 +#endif +#ifndef LANG_MACEDONIAN +#define LANG_MACEDONIAN 0x2f +#endif +#ifndef LANG_MALAY +#define LANG_MALAY 0x3e +#endif +#ifndef LANG_MALAYALAM +#define LANG_MALAYALAM 0x4c +#endif +#ifndef LANG_MALTESE +#define LANG_MALTESE 0x3a +#endif +#ifndef LANG_MANIPURI +#define LANG_MANIPURI 0x58 +#endif +#ifndef LANG_MARATHI +#define LANG_MARATHI 0x4e +#endif +#ifndef LANG_MONGOLIAN +#define LANG_MONGOLIAN 0x50 +#endif +#ifndef LANG_NEPALI +#define LANG_NEPALI 0x61 +#endif +#ifndef LANG_ORIYA +#define LANG_ORIYA 0x48 +#endif +#ifndef LANG_OROMO +#define LANG_OROMO 0x72 +#endif +#ifndef LANG_PAPIAMENTU +#define LANG_PAPIAMENTU 0x79 +#endif +#ifndef LANG_PASHTO +#define LANG_PASHTO 0x63 +#endif +#ifndef LANG_PUNJABI +#define LANG_PUNJABI 0x46 +#endif +#ifndef LANG_RHAETO_ROMANCE +#define LANG_RHAETO_ROMANCE 0x17 +#endif +#ifndef LANG_SAAMI +#define LANG_SAAMI 0x3b +#endif +#ifndef LANG_SANSKRIT +#define LANG_SANSKRIT 0x4f +#endif +#ifndef LANG_SERBIAN +#define LANG_SERBIAN 0x1a +#endif +#ifndef LANG_SINDHI +#define LANG_SINDHI 0x59 +#endif +#ifndef LANG_SINHALESE +#define LANG_SINHALESE 0x5b +#endif +#ifndef LANG_SLOVAK +#define LANG_SLOVAK 0x1b +#endif +#ifndef LANG_SOMALI +#define LANG_SOMALI 0x77 +#endif +#ifndef LANG_SORBIAN +#define LANG_SORBIAN 0x2e +#endif +#ifndef LANG_SUTU +#define LANG_SUTU 0x30 +#endif +#ifndef LANG_SWAHILI +#define LANG_SWAHILI 0x41 +#endif +#ifndef LANG_SYRIAC +#define LANG_SYRIAC 0x5a +#endif +#ifndef LANG_TAGALOG +#define LANG_TAGALOG 0x64 +#endif +#ifndef LANG_TAJIK +#define LANG_TAJIK 0x28 +#endif +#ifndef LANG_TAMAZIGHT +#define LANG_TAMAZIGHT 0x5f +#endif +#ifndef LANG_TAMIL +#define LANG_TAMIL 0x49 +#endif +#ifndef LANG_TATAR +#define LANG_TATAR 0x44 +#endif +#ifndef LANG_TELUGU +#define LANG_TELUGU 0x4a +#endif +#ifndef LANG_THAI +#define LANG_THAI 0x1e +#endif +#ifndef LANG_TIBETAN +#define LANG_TIBETAN 0x51 +#endif +#ifndef LANG_TIGRINYA +#define LANG_TIGRINYA 0x73 +#endif +#ifndef LANG_TSONGA +#define LANG_TSONGA 0x31 +#endif +#ifndef LANG_TSWANA +#define LANG_TSWANA 0x32 +#endif +#ifndef LANG_TURKMEN +#define LANG_TURKMEN 0x42 +#endif +#ifndef LANG_UKRAINIAN +#define LANG_UKRAINIAN 0x22 +#endif +#ifndef LANG_URDU +#define LANG_URDU 0x20 +#endif +#ifndef LANG_UZBEK +#define LANG_UZBEK 0x43 +#endif +#ifndef LANG_VENDA +#define LANG_VENDA 0x33 +#endif +#ifndef LANG_VIETNAMESE +#define LANG_VIETNAMESE 0x2a +#endif +#ifndef LANG_WELSH +#define LANG_WELSH 0x52 +#endif +#ifndef LANG_XHOSA +#define LANG_XHOSA 0x34 +#endif +#ifndef LANG_YI +#define LANG_YI 0x78 +#endif +#ifndef LANG_YIDDISH +#define LANG_YIDDISH 0x3d +#endif +#ifndef LANG_YORUBA +#define LANG_YORUBA 0x6a +#endif +#ifndef LANG_ZULU +#define LANG_ZULU 0x35 +#endif +#ifndef SUBLANG_ARABIC_SAUDI_ARABIA +#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +#endif +#ifndef SUBLANG_ARABIC_IRAQ +#define SUBLANG_ARABIC_IRAQ 0x02 +#endif +#ifndef SUBLANG_ARABIC_EGYPT +#define SUBLANG_ARABIC_EGYPT 0x03 +#endif +#ifndef SUBLANG_ARABIC_LIBYA +#define SUBLANG_ARABIC_LIBYA 0x04 +#endif +#ifndef SUBLANG_ARABIC_ALGERIA +#define SUBLANG_ARABIC_ALGERIA 0x05 +#endif +#ifndef SUBLANG_ARABIC_MOROCCO +#define SUBLANG_ARABIC_MOROCCO 0x06 +#endif +#ifndef SUBLANG_ARABIC_TUNISIA +#define SUBLANG_ARABIC_TUNISIA 0x07 +#endif +#ifndef SUBLANG_ARABIC_OMAN +#define SUBLANG_ARABIC_OMAN 0x08 +#endif +#ifndef SUBLANG_ARABIC_YEMEN +#define SUBLANG_ARABIC_YEMEN 0x09 +#endif +#ifndef SUBLANG_ARABIC_SYRIA +#define SUBLANG_ARABIC_SYRIA 0x0a +#endif +#ifndef SUBLANG_ARABIC_JORDAN +#define SUBLANG_ARABIC_JORDAN 0x0b +#endif +#ifndef SUBLANG_ARABIC_LEBANON +#define SUBLANG_ARABIC_LEBANON 0x0c +#endif +#ifndef SUBLANG_ARABIC_KUWAIT +#define SUBLANG_ARABIC_KUWAIT 0x0d +#endif +#ifndef SUBLANG_ARABIC_UAE +#define SUBLANG_ARABIC_UAE 0x0e +#endif +#ifndef SUBLANG_ARABIC_BAHRAIN +#define SUBLANG_ARABIC_BAHRAIN 0x0f +#endif +#ifndef SUBLANG_ARABIC_QATAR +#define SUBLANG_ARABIC_QATAR 0x10 +#endif +#ifndef SUBLANG_AZERI_LATIN +#define SUBLANG_AZERI_LATIN 0x01 +#endif +#ifndef SUBLANG_AZERI_CYRILLIC +#define SUBLANG_AZERI_CYRILLIC 0x02 +#endif +#ifndef SUBLANG_BENGALI_INDIA +#define SUBLANG_BENGALI_INDIA 0x01 +#endif +#ifndef SUBLANG_BENGALI_BANGLADESH +#define SUBLANG_BENGALI_BANGLADESH 0x02 +#endif +#ifndef SUBLANG_CHINESE_MACAU +#define SUBLANG_CHINESE_MACAU 0x05 +#endif +#ifndef SUBLANG_ENGLISH_SOUTH_AFRICA +#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +#endif +#ifndef SUBLANG_ENGLISH_JAMAICA +#define SUBLANG_ENGLISH_JAMAICA 0x08 +#endif +#ifndef SUBLANG_ENGLISH_CARIBBEAN +#define SUBLANG_ENGLISH_CARIBBEAN 0x09 +#endif +#ifndef SUBLANG_ENGLISH_BELIZE +#define SUBLANG_ENGLISH_BELIZE 0x0a +#endif +#ifndef SUBLANG_ENGLISH_TRINIDAD +#define SUBLANG_ENGLISH_TRINIDAD 0x0b +#endif +#ifndef SUBLANG_ENGLISH_ZIMBABWE +#define SUBLANG_ENGLISH_ZIMBABWE 0x0c +#endif +#ifndef SUBLANG_ENGLISH_PHILIPPINES +#define SUBLANG_ENGLISH_PHILIPPINES 0x0d +#endif +#ifndef SUBLANG_ENGLISH_INDONESIA +#define SUBLANG_ENGLISH_INDONESIA 0x0e +#endif +#ifndef SUBLANG_ENGLISH_HONGKONG +#define SUBLANG_ENGLISH_HONGKONG 0x0f +#endif +#ifndef SUBLANG_ENGLISH_INDIA +#define SUBLANG_ENGLISH_INDIA 0x10 +#endif +#ifndef SUBLANG_ENGLISH_MALAYSIA +#define SUBLANG_ENGLISH_MALAYSIA 0x11 +#endif +#ifndef SUBLANG_ENGLISH_SINGAPORE +#define SUBLANG_ENGLISH_SINGAPORE 0x12 +#endif +#ifndef SUBLANG_FRENCH_LUXEMBOURG +#define SUBLANG_FRENCH_LUXEMBOURG 0x05 +#endif +#ifndef SUBLANG_FRENCH_MONACO +#define SUBLANG_FRENCH_MONACO 0x06 +#endif +#ifndef SUBLANG_FRENCH_WESTINDIES +#define SUBLANG_FRENCH_WESTINDIES 0x07 +#endif +#ifndef SUBLANG_FRENCH_REUNION +#define SUBLANG_FRENCH_REUNION 0x08 +#endif +#ifndef SUBLANG_FRENCH_CONGO +#define SUBLANG_FRENCH_CONGO 0x09 +#endif +#ifndef SUBLANG_FRENCH_SENEGAL +#define SUBLANG_FRENCH_SENEGAL 0x0a +#endif +#ifndef SUBLANG_FRENCH_CAMEROON +#define SUBLANG_FRENCH_CAMEROON 0x0b +#endif +#ifndef SUBLANG_FRENCH_COTEDIVOIRE +#define SUBLANG_FRENCH_COTEDIVOIRE 0x0c +#endif +#ifndef SUBLANG_FRENCH_MALI +#define SUBLANG_FRENCH_MALI 0x0d +#endif +#ifndef SUBLANG_FRENCH_MOROCCO +#define SUBLANG_FRENCH_MOROCCO 0x0e +#endif +#ifndef SUBLANG_FRENCH_HAITI +#define SUBLANG_FRENCH_HAITI 0x0f +#endif +#ifndef SUBLANG_GERMAN_LUXEMBOURG +#define SUBLANG_GERMAN_LUXEMBOURG 0x04 +#endif +#ifndef SUBLANG_GERMAN_LIECHTENSTEIN +#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +#endif +#ifndef SUBLANG_KASHMIRI_INDIA +#define SUBLANG_KASHMIRI_INDIA 0x02 +#endif +#ifndef SUBLANG_MALAY_MALAYSIA +#define SUBLANG_MALAY_MALAYSIA 0x01 +#endif +#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM +#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +#endif +#ifndef SUBLANG_NEPALI_INDIA +#define SUBLANG_NEPALI_INDIA 0x02 +#endif +#ifndef SUBLANG_PUNJABI_INDIA +#define SUBLANG_PUNJABI_INDIA 0x01 +#endif +#ifndef SUBLANG_ROMANIAN_ROMANIA +#define SUBLANG_ROMANIAN_ROMANIA 0x01 +#endif +#ifndef SUBLANG_SERBIAN_LATIN +#define SUBLANG_SERBIAN_LATIN 0x02 +#endif +#ifndef SUBLANG_SERBIAN_CYRILLIC +#define SUBLANG_SERBIAN_CYRILLIC 0x03 +#endif +#ifndef SUBLANG_SINDHI_INDIA +#define SUBLANG_SINDHI_INDIA 0x00 +#endif +#ifndef SUBLANG_SINDHI_PAKISTAN +#define SUBLANG_SINDHI_PAKISTAN 0x01 +#endif +#ifndef SUBLANG_SPANISH_GUATEMALA +#define SUBLANG_SPANISH_GUATEMALA 0x04 +#endif +#ifndef SUBLANG_SPANISH_COSTA_RICA +#define SUBLANG_SPANISH_COSTA_RICA 0x05 +#endif +#ifndef SUBLANG_SPANISH_PANAMA +#define SUBLANG_SPANISH_PANAMA 0x06 +#endif +#ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC +#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +#endif +#ifndef SUBLANG_SPANISH_VENEZUELA +#define SUBLANG_SPANISH_VENEZUELA 0x08 +#endif +#ifndef SUBLANG_SPANISH_COLOMBIA +#define SUBLANG_SPANISH_COLOMBIA 0x09 +#endif +#ifndef SUBLANG_SPANISH_PERU +#define SUBLANG_SPANISH_PERU 0x0a +#endif +#ifndef SUBLANG_SPANISH_ARGENTINA +#define SUBLANG_SPANISH_ARGENTINA 0x0b +#endif +#ifndef SUBLANG_SPANISH_ECUADOR +#define SUBLANG_SPANISH_ECUADOR 0x0c +#endif +#ifndef SUBLANG_SPANISH_CHILE +#define SUBLANG_SPANISH_CHILE 0x0d +#endif +#ifndef SUBLANG_SPANISH_URUGUAY +#define SUBLANG_SPANISH_URUGUAY 0x0e +#endif +#ifndef SUBLANG_SPANISH_PARAGUAY +#define SUBLANG_SPANISH_PARAGUAY 0x0f +#endif +#ifndef SUBLANG_SPANISH_BOLIVIA +#define SUBLANG_SPANISH_BOLIVIA 0x10 +#endif +#ifndef SUBLANG_SPANISH_EL_SALVADOR +#define SUBLANG_SPANISH_EL_SALVADOR 0x11 +#endif +#ifndef SUBLANG_SPANISH_HONDURAS +#define SUBLANG_SPANISH_HONDURAS 0x12 +#endif +#ifndef SUBLANG_SPANISH_NICARAGUA +#define SUBLANG_SPANISH_NICARAGUA 0x13 +#endif +#ifndef SUBLANG_SPANISH_PUERTO_RICO +#define SUBLANG_SPANISH_PUERTO_RICO 0x14 +#endif +#ifndef SUBLANG_SWEDISH_FINLAND +#define SUBLANG_SWEDISH_FINLAND 0x02 +#endif +#ifndef SUBLANG_TAMAZIGHT_ARABIC +#define SUBLANG_TAMAZIGHT_ARABIC 0x01 +#endif +#ifndef SUBLANG_TAMAZIGHT_LATIN +#define SUBLANG_TAMAZIGHT_LATIN 0x02 +#endif +#ifndef SUBLANG_TIGRINYA_ETHIOPIA +#define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +#endif +#ifndef SUBLANG_TIGRINYA_ERITREA +#define SUBLANG_TIGRINYA_ERITREA 0x01 +#endif +#ifndef SUBLANG_URDU_PAKISTAN +#define SUBLANG_URDU_PAKISTAN 0x01 +#endif +#ifndef SUBLANG_URDU_INDIA +#define SUBLANG_URDU_INDIA 0x02 +#endif +#ifndef SUBLANG_UZBEK_LATIN +#define SUBLANG_UZBEK_LATIN 0x01 +#endif +#ifndef SUBLANG_UZBEK_CYRILLIC +#define SUBLANG_UZBEK_CYRILLIC 0x02 +#endif + +/* Return an XPG style locale name + language[_territory[.codeset]][@modifier]. + Don't even bother determining the codeset; it's not useful in this + context, because message catalogs are not specific to a single + codeset. The result must not be freed; it is statically + allocated. */ static const char * -_nl_locale_name (int category, const char *categoryname) +my_nl_locale_name (const char *categoryname) { const char *retval; - -#ifndef HAVE_W32_SYSTEM - - /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. - On some systems this can be done by the 'setlocale' function itself. */ -# if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL - retval = setlocale (category, NULL); -# else - /* Setting of LC_ALL overwrites all other. */ - retval = getenv ("LC_ALL"); - if (retval == NULL || retval[0] == '\0') - { - /* Next comes the name of the desired category. */ - retval = getenv (categoryname); - if (retval == NULL || retval[0] == '\0') - { - /* Last possibility is the LANG environment variable. */ - retval = getenv ("LANG"); - if (retval == NULL || retval[0] == '\0') - /* We use C as the default domain. POSIX says this is - implementation defined. */ - retval = "C"; - } - } -# endif - - return retval; - -#else /* HAVE_W32_SYSTEM */ - - /* Return an XPG style locale name language[_territory][@modifier]. - Don't even bother determining the codeset; it's not useful in this - context, because message catalogs are not specific to a single - codeset. */ - LCID lcid; LANGID langid; int primary, sub; @@ -1178,19 +1018,16 @@ _nl_locale_name (int category, const char *categoryname) case LANG_ZULU: return "zu_ZA"; default: return "C"; } - -#endif /* HAVE_W32_SYSTEM */ } /* localname.c from gettext END. */ + + /* Support functions. */ -typedef uint32_t u32; -typedef unsigned long ulong; - -static __inline__ u32 -do_swap_u32 (u32 i) +static __inline__ uint32_t +do_swap_u32 (uint32_t i) { return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); } @@ -1204,26 +1041,25 @@ do_swap_u32 (u32 i) /* The so called `hashpjw' function by P.J. Weinberger [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, 1986, 1987 Bell Telephone Laboratories, Inc.] */ - -static __inline__ ulong +static __inline__ unsigned long hash_string( const char *str_param ) { - unsigned long int hval, g; - const char *str = str_param; - - hval = 0; - while (*str != '\0') + unsigned long int hval, g; + const char *str = str_param; + + hval = 0; + while (*str != '\0') { - hval <<= 4; - hval += (unsigned long int) *str++; - g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); - if (g != 0) + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) { hval ^= g >> (HASHWORDBITS - 8); hval ^= g; } } - return hval; + return hval; } @@ -1236,74 +1072,106 @@ hash_string( const char *str_param ) /* Revision number of the currently used .mo (binary) file format. */ #define MO_REVISION_NUMBER 0 + /* Header for binary .mo file format. */ struct mo_file_header { /* The magic number. */ - u32 magic; + uint32_t magic; /* The revision number of the file format. */ - u32 revision; + uint32_t revision; /* The number of strings pairs. */ - u32 nstrings; + uint32_t nstrings; /* Offset of table with start offsets of original strings. */ - u32 orig_tab_offset; + uint32_t orig_tab_offset; /* Offset of table with start offsets of translation strings. */ - u32 trans_tab_offset; + uint32_t trans_tab_offset; /* Size of hashing table. */ - u32 hash_tab_size; + uint32_t hash_tab_size; /* Offset of first hashing entry. */ - u32 hash_tab_offset; + uint32_t hash_tab_offset; }; + struct string_desc { /* Length of addressed string. */ - u32 length; + uint32_t length; /* Offset of string in file. */ - u32 offset; + uint32_t offset; }; struct overflow_space_s { struct overflow_space_s *next; - u32 idx; + uint32_t idx; + uint32_t length; char d[1]; }; struct loaded_domain { char *data; + char *data_native; /* Data mapped to the native version of the + string. (Allocated along with DATA). */ int must_swap; - u32 nstrings; - char *mapped; /* 0 = not yet mapped, 1 = mapped, - 2 = mapped to - overflow space */ + uint16_t nstrings; /* Number of strings. */ + uint16_t *mapped; /* Array of mapping indicators: + 0 := Not mapped (original utf8). + 1 := Mapped to native encoding in overflow space. + >=2 := Mapped to native encoding. The value + gives the length of the mapped string. + Because the terminating nul is included + in the length and an empty string is + not allowed, values are always > 1. */ struct overflow_space_s *overflow_space; struct string_desc *orig_tab; struct string_desc *trans_tab; - u32 hash_size; - u32 *hash_tab; + uint32_t hash_size; + uint32_t *hash_tab; }; + +/* The list of domains we we are aware of. This list is protected by + the criticla section DOMAINLIST_ACCESS_CS. */ +static struct domainlist_s *domainlist; + +/* A critical section to guard access to the domainlist. */ +static CRITICAL_SECTION domainlist_access_cs; + +/* The name of the current domain. This is a malloced string. This + is a gobal variable which is not thread-safe. */ +static char *current_domainname; + + +/* Constructor for this module. Called from DllMain. */ +static void module_init (void) __attribute__ ((__constructor__)); +static void +module_init (void) +{ + InitializeCriticalSection (&domainlist_access_cs); +} + + /* Free the domain data. */ static void free_domain (struct loaded_domain *domain) { struct overflow_space_s *os, *os2; - free (domain->data); - free (domain->mapped); + + jnlib_free (domain->data); + jnlib_free (domain->mapped); for (os = domain->overflow_space; os; os = os2) { os2 = os->next; - free (os); + jnlib_free (os); } - free (domain); + jnlib_free (domain); } -/* The gettext implementation; support functions. */ static struct loaded_domain * load_domain (const char *filename) { @@ -1317,9 +1185,9 @@ load_domain (const char *filename) fp = fopen (filename, "rb"); if (!fp) - return NULL; - - /* Determine the file size. */ + { + return NULL; + } if (fstat (fileno (fp), &st) || (size = (size_t) st.st_size) != st.st_size || size < sizeof (struct mo_file_header)) @@ -1328,7 +1196,7 @@ load_domain (const char *filename) return NULL; } - data = malloc (size); + data = (2*size <= size)? NULL : jnlib_malloc (2*size); if (!data) { fclose (fp); @@ -1343,7 +1211,7 @@ load_domain (const char *filename) if (nb < to_read) { fclose (fp); - free (data); + jnlib_free (data); return NULL; } read_ptr += nb; @@ -1357,205 +1225,186 @@ load_domain (const char *filename) if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED) { /* The magic number is wrong: not a message catalog file. */ - free (data); + jnlib_free (data); return NULL; } - domain = calloc (1, sizeof *domain); + domain = jnlib_calloc (1, sizeof *domain); if (!domain) { - free (data); + jnlib_free (data); return NULL; } domain->data = (char *) data; + domain->data_native = (char *) data + size; domain->must_swap = data->magic != MAGIC; /* Fill in the information about the available tables. */ switch (SWAPIT (domain->must_swap, data->revision)) { - case 0: - domain->nstrings = SWAPIT (domain->must_swap, data->nstrings); - domain->orig_tab = (struct string_desc *) - ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset)); - domain->trans_tab = (struct string_desc *) - ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset)); - domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size); - domain->hash_tab = (u32 *) - ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset)); + case MO_REVISION_NUMBER: + { + uint32_t nstrings; + + /* Because we use 16 bit values for the mapping array, we + can't support more that 65534 strings (65535 would be okay, + but it is often used as a special value). A PO file with + that many translations is very unlikely given that GnuPG + with its very large number of strings has only about 1600 + strings + variants. */ + nstrings = SWAPIT (domain->must_swap, data->nstrings); + if (nstrings > 65534) + goto bailout; + domain->nstrings = nstrings; + domain->orig_tab = (struct string_desc *) + ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset)); + domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size); + domain->hash_tab = (uint32_t *) + ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset)); + } break; - default: - /* This is an invalid revision. */ - free (data); - free (domain); - return NULL; + default: /* This is an invalid revision. */ + goto bailout; } /* Allocate an array to keep track of code page mappings. */ - domain->mapped = calloc (1, domain->nstrings); - if (!domain->mapped) - { - free (data); - free (domain); - return NULL; - } - - return domain; + domain->mapped = jnlib_calloc (domain->nstrings, sizeof *domain->mapped); + if (domain->mapped) + return domain; /* Okay. */ + + bailout: + jnlib_free (data); + jnlib_free (domain); + return NULL; } -/* Return a malloced string encoded in UTF-8 from the wide char input +/* Return a malloced wide char string from an UTF-8 encoded input string STRING. Caller must free this value. On failure returns - NULL; caller may use GetLastError to get the actual error number. - The result of calling this function with STRING set to NULL is not - defined. */ -static char * -wchar_to_native (const wchar_t *string) + NULL. The result of calling this function with STRING set to NULL + is not defined. */ +static wchar_t * +utf8_to_wchar (const char *string, size_t length, size_t *retlen) { int n; - char *result; + wchar_t *result; + size_t nbytes; - n = WideCharToMultiByte (CP_ACP, 0, string, -1, NULL, 0, NULL, NULL); - if (n < 0) + n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0); + if (n < 0 || (n+1) <= 0) return NULL; - result = malloc (n+1); + nbytes = (size_t)(n+1) * sizeof(*result); + if (nbytes / sizeof(*result) != (n+1)) + { + gpg_err_set_errno (ENOMEM); + return NULL; + } + result = jnlib_malloc (nbytes); if (!result) return NULL; - n = WideCharToMultiByte (CP_ACP, 0, string, -1, result, n, NULL, NULL); + n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n); if (n < 0) { - free (result); + jnlib_free (result); return NULL; } + *retlen = n; return result; } -/* Return a malloced wide char string from an UTF-8 encoded input +/* Return a malloced string encoded in UTF-8 from the wide char input string STRING. Caller must free this value. On failure returns - NULL; caller may use GetLastError to get the actual error number. - The result of calling this function with STRING set to NULL is not - defined. */ -static wchar_t * -utf8_to_wchar (const char *string) + NULL. The result of calling this function with STRING set to NULL + is not defined. */ +static char * +wchar_to_native (const wchar_t *string, size_t length, size_t *retlen) { int n; - wchar_t *result; + char *result; - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); - if (n < 0) + n = WideCharToMultiByte (CP_ACP, 0, string, length, NULL, 0, NULL, NULL); + if (n < 0 || (n+1) <= 0) return NULL; - result = malloc ((n+1) * sizeof *result); + result = jnlib_malloc (n+1); if (!result) return NULL; - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); + n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); if (n < 0) { - free (result); + jnlib_free (result); return NULL; } + *retlen = n; return result; } +/* Convert UTF8 to the native codepage. Caller must free the return value. */ static char * -utf8_to_native (const char *string) +utf8_to_native (const char *string, size_t length, size_t *retlen) { wchar_t *wstring; char *result; + size_t newlen; - wstring = utf8_to_wchar (string); - if (!wstring) - return NULL; - - result = wchar_to_native (wstring); - free (wstring); - - return result; -} - - -static const char* -get_string (struct loaded_domain *domain, u32 idx) -{ - struct overflow_space_s *os; - char *p; - - p = domain->data + SWAPIT (domain->must_swap, domain->trans_tab[idx].offset); - if (!domain->mapped[idx]) - { - size_t plen, buflen; - char *buf; - - domain->mapped[idx] = 1; - - plen = strlen (p); - buf = utf8_to_native (p); - buflen = strlen (buf); - if (buflen <= plen) - strcpy (p, buf); - else - { - /* There is not enough space for the translation - store it - in the overflow_space else and mark that in the mapped - array. Because we expect that this won't happen too - often, we use a simple linked list. */ - os = malloc (sizeof *os + buflen); - if (os) - { - os->idx = idx; - strcpy (os->d, buf); - os->next = domain->overflow_space; - domain->overflow_space = os; - p = os->d; - } - else - p = "ERROR in GETTEXT MALLOC"; - } - free (buf); - } - else if (domain->mapped[idx] == 2) + wstring = utf8_to_wchar (string, length, &newlen); + if (wstring) { - /* We need to get the string from the overflow_space. */ - for (os=domain->overflow_space; os; os = os->next) - if (os->idx == idx) - return (const char*) os->d; - p = "ERROR in GETTEXT\n"; + result = wchar_to_native (wstring, newlen, &newlen); + jnlib_free (wstring); } - return (const char*) p; + else + result = NULL; + *retlen = result? newlen : 0; + return result; } - -/* The domain we use. We only support one domain at this point. This - is why this implementation can not be shared. Bindtextdomain and - dgettext will simply cheat and always use this one domain. */ -static struct loaded_domain *the_domain; /* Specify that the DOMAINNAME message catalog will be found in DIRNAME rather than in the system locale data base. */ -char * -bindtextdomain (const char *domainname, const char *dirname) +const char * +_gpg_w32_bindtextdomain (const char *domainname, const char *dirname) { - struct loaded_domain *domain = NULL; const char *catval_full; char *catval; char *fname; + const char *retvalue; - /* DOMAINNAME is ignored. We only support one domain. */ + if (!dirname) + { + struct domainlist_s *dl; + + retvalue = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + retvalue = dl->dname; + break; + } + } + LeaveCriticalSection (&domainlist_access_cs); + return retvalue; + } /* DIRNAME is "$INSTALLDIR\share\locale". */ - /* First found out the category value. */ + /* First find out the category value. */ catval = NULL; - catval_full = _nl_locale_name (LC_MESSAGES, "LC_MESSAGES"); + catval_full = my_nl_locale_name ("LC_MESSAGES"); - /* Normally, we would have to loop over all returned locales, and + /* Normally we would have to loop over all returned locales and search for the right file. See gettext intl/dcigettext.c for all the gory details. Here, we only support the basic category, and ignore everything else. */ @@ -1563,7 +1412,7 @@ bindtextdomain (const char *domainname, const char *dirname) { char *p; - catval = malloc (strlen (catval_full) + 1); + catval = jnlib_malloc (strlen (catval_full) + 1); if (catval) { strcpy (catval, catval_full); @@ -1578,15 +1427,15 @@ bindtextdomain (const char *domainname, const char *dirname) /* Now build the filename string. The complete filename is this: DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo */ { - int len = strlen (dirname) + 1 + strlen (catval) + 13 - + strlen (domainname) + 3 + 1; + int len = (strlen (dirname) + 1 + strlen (catval) + 13 + + strlen (domainname) + 3 + 1); char *p; - fname = malloc (len); + fname = jnlib_malloc (len); if (!fname) { - free (catval); - return; + jnlib_free (catval); + return NULL; } p = fname; @@ -1602,74 +1451,294 @@ bindtextdomain (const char *domainname, const char *dirname) strcpy (p, ".mo"); } - domain = load_domain (fname); - free (catval); - free (fname); + jnlib_free (catval); - /* We should not be invoked twice, but this is how you would do - it if it happened. */ - if (the_domain) - free_domain (the_domain); - the_domain = domain; + /* Store the domain information in the domainlist. */ + { + struct domainlist_s *item, *dl; + char *rel_ptr1 = NULL; + char *rel_ptr2 = NULL; + + item = jnlib_calloc (1, sizeof *dl + strlen (domainname)); + if (!item) + { + jnlib_free (fname); + return NULL; + } + strcpy (item->name, domainname); + item->dname = jnlib_malloc (strlen (dirname) +1); + if(!item->dname) + { + jnlib_free (item); + jnlib_free (fname); + return NULL; + } + strcpy (item->dname, dirname); + retvalue = item->dname; - /* For historic reasoins we are not allowed to return a const char*. */ - return (char*)dirname; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + break; + if (!dl) /* First time called for this domainname. */ + { + item->fname = fname; + fname = NULL; + item->next = domainlist; + domainlist = item; + item = NULL; + } + else /* Update only. */ + { + rel_ptr1 = dl->fname; + dl->fname = fname; + fname = NULL; + rel_ptr2 = dl->dname; + dl->dname = item->dname; + item->dname = NULL; + } + } + LeaveCriticalSection (&domainlist_access_cs); + + jnlib_free (item); + jnlib_free (rel_ptr1); + jnlib_free (rel_ptr2); + } + + return retvalue; } -const char * -gettext (const char *msgid) + + +static const char * +get_plural (const char *data, size_t datalen, unsigned long nplural) +{ + const char *p; + int idx; + + /* We only support the Germanic rule. */ + idx = (nplural == 1? 0 : 1); + + for (; idx; idx--) + { + p = strchr (data, 0) + 1; + if (p >= data+datalen) + return "ERROR in GETTEXT (bad plural entry)"; + datalen -= (p-data); + data = p; + } + return data; +} + + +static const char* +get_string (struct loaded_domain *domain, uint32_t idx, + int use_plural, unsigned long nplural) +{ + struct tls_space_s *tls = get_tls (); + struct overflow_space_s *os; + const char *trans; /* Pointer to the translated entry. */ + size_t translen; /* Length of that entry. */ + + if (idx > 65534) + return "ERROR in GETTEXT (too many strings)"; + + if (tls->gt_use_utf8) + { + trans = (domain->data + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + translen = SWAPIT(domain->must_swap, domain->trans_tab[idx].length); + } + else if (!domain->mapped[idx]) + { + /* Not yet mapped. Map from utf-8 to native encoding now. */ + const char *p_utf8; + size_t plen_utf8, buflen; + char *buf; + + p_utf8 = (domain->data + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + plen_utf8 = SWAPIT(domain->must_swap, domain->trans_tab[idx].length); + + buf = utf8_to_native (p_utf8, plen_utf8, &buflen); + if (!buf) + { + trans = "ERROR in GETTEXT MALLOC"; + translen = 0; + } + else if (buflen <= plen_utf8 && buflen > 1) + { + /* Copy into the DATA_NATIVE area. */ + char *p_tmp; + + p_tmp = (domain->data_native + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + memcpy (p_tmp, buf, buflen); + domain->mapped[idx] = buflen; + trans = p_tmp; + translen = buflen; + } + else + { + /* There is not enough space for the translation (or for + whatever reason an empty string is used): Store it in the + overflow_space and mark that in the mapped array. + Because UTF-8 strings are in general shorter than the + Windows 2 byte encodings, we expect that this won't + happen too often (if at all) and thus we use a linked + list to manage this space. */ + os = jnlib_malloc (sizeof *os + buflen); + if (os) + { + os->idx = idx; + memcpy (os->d, buf, buflen); + os->length = buflen; + os->next = domain->overflow_space; + domain->overflow_space = os; + domain->mapped[idx] = 1; + trans = os->d; + translen = os->length; + } + else + { + trans = "ERROR in GETTEXT MALLOC"; + translen = 0; + } + } + jnlib_free (buf); + } + else if (domain->mapped[idx] == 1) + { + /* The translated string is in the overflow_space. */ + for (os=domain->overflow_space; os; os = os->next) + if (os->idx == idx) + break; + if (os) + { + trans = os->d; + translen = os->length; + } + else + { + trans = "ERROR in GETTEXT (overflow space)\n"; + translen = 0; + } + } + else + { + trans = (domain->data_native + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + translen = domain->mapped[idx]; + } + + if (use_plural && translen) + return get_plural (trans, translen, nplural); + else + return trans; +} + + +static const char * +do_gettext (const char *domainname, + const char *msgid, const char *msgid2, unsigned long nplural) { + struct domainlist_s *dl; struct loaded_domain *domain; - size_t act = 0; - size_t top, bottom; + int load_failed; + uint32_t top, bottom, nstr; + char *filename; + + if (!domainname) + domainname = current_domainname? current_domainname : ""; + + /* FIXME: The whole locking stuff is a bit questionable because + gettext does not claim to be thread-safe. We need to investigate + this further. */ + + load_failed = 0; + domain = NULL; + filename = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + load_failed = dl->load_failed; + domain = dl->domain; + break; + } + if (dl && !domain && !load_failed && dl->fname) + { + filename = jnlib_malloc (strlen (dl->fname) + 1); + if (filename) + strcpy (filename, dl->fname); + } + } + LeaveCriticalSection (&domainlist_access_cs); + if (!dl) + goto not_found; /* DOMAINNAME not bound. */ + if (filename) + { + /* No attempt so far to load the MO file. Try now. */ + int updated = 0; + + domain = load_domain (filename); + jnlib_free (filename); + filename = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + if (domain) + dl->domain = domain; + else + dl->load_failed = 1; + updated = 1; + break; + } + } + LeaveCriticalSection (&domainlist_access_cs); + if (!updated) + { + /* Ooops - lost the domain. */ + free_domain (domain); + domain = NULL; + } + } - if (!(domain = the_domain)) - goto not_found; + if (!domain) + goto not_found; /* No MO file. */ - /* Locate the MSGID and its translation. */ + /* First try to use the hash table. */ if (domain->hash_size > 2 && domain->hash_tab) { /* Use the hashing table. */ - u32 len = strlen (msgid); - u32 hash_val = hash_string (msgid); - u32 idx = hash_val % domain->hash_size; - u32 incr = 1 + (hash_val % (domain->hash_size - 2)); - u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); - - if (!nstr) - /* Hash table entry is empty. */ - goto not_found; - - if (SWAPIT (domain->must_swap, - domain->orig_tab[nstr - 1].length) == len - && !strcmp (msgid, - domain->data - + SWAPIT (domain->must_swap, - domain->orig_tab[nstr - 1].offset))) - return get_string (domain, nstr - 1); - - for(;;) - { - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; - - nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); - if (!nstr) - /* Hash table entry is empty. */ - goto not_found; - - if (SWAPIT (domain->must_swap, - domain->orig_tab[nstr - 1].length) == len - && !strcmp (msgid, - domain->data - + SWAPIT (domain->must_swap, - domain->orig_tab[nstr - 1].offset))) - return get_string (domain, nstr-1); - } - /* NOTREACHED */ + uint32_t len = strlen (msgid); + uint32_t hash_val = hash_string (msgid); + uint32_t idx = hash_val % domain->hash_size; + uint32_t incr = 1 + (hash_val % (domain->hash_size - 2)); + + while ( (nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx])) ) + { + nstr--; + if (nstr < domain->nstrings + && SWAPIT(domain->must_swap, + domain->orig_tab[nstr].length) >= len + && !strcmp (msgid, (domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[nstr].offset)))) + { + return get_string (domain, nstr, !!msgid2, nplural); + } + + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } } /* Now we try the default method: binary search in the sorted array @@ -1680,33 +1749,138 @@ gettext (const char *msgid) { int cmp_val; - act = (bottom + top) / 2; - cmp_val = strcmp(msgid, domain->data - + SWAPIT (domain->must_swap, - domain->orig_tab[act].offset)); + nstr = (bottom + top) / 2; + cmp_val = strcmp (msgid, (domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[nstr].offset))); if (cmp_val < 0) - top = act; + top = nstr; else if (cmp_val > 0) - bottom = act + 1; + bottom = nstr + 1; else - return get_string (domain, act); + { + return get_string (domain, nstr, !!msgid2, nplural); + } } - + not_found: - return msgid; + /* We use the standard Germanic rule if plural has been requested. */ + return msgid2? (nplural == 1? msgid : msgid2) : msgid; } -char * -textdomain (const char *domainname) +const char * +_gpg_w32_textdomain (const char *domainname) { - /* For now, support only one domain. */ - return (char*)domainname; + char *string; + + if (!domainname) + { + if (!current_domainname) + gpg_err_set_errno (0); + } + else + { + string = malloc (strlen (domainname) + 1); + if (!string) + return NULL; + strcpy (string, domainname); + current_domainname = string; + } + return current_domainname; } -char * -dgettext (const char *domainname, const char *msgid) + +/* A direct implementation of gettext instead of a macro calling + dngettext. This is so that the caller does not need to push dummy + values on the stack. The used domain is the first one registered + with bindtextdomain. */ +const char * +_gpg_w32_gettext (const char *msgid) { - /* For now, support only one domain. */ - return (char*)gettext (msgid); + return do_gettext (NULL, msgid, NULL, 0); +} + + +/* A direct implementation of dgettext instead of a macro calling + dngettext. This is so that the caller does not need to push dummy + values on the stack. */ +const char * +_gpg_w32_dgettext (const char *domainname, const char *msgid) +{ + return do_gettext (domainname, msgid, NULL, 0); +} + + +/* Our implementation of dngettext. This is the most genereic + function we have; a macro implements ngettext. */ +const char * +_gpg_w32_dngettext (const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n) +{ + /* We use the simple Germanic plural rule. */ + return do_gettext (domainname, msgid1, msgid2, n); +} + + +/* Return the locale name as used by gettext. The return value will + never be NULL. */ +const char * +_gpg_w32_gettext_localename (void) +{ + const char *s; + + s = my_nl_locale_name ("LC_MESSAGES"); + return s? s:""; +} + + +/* With a VALUE of 1 switch the gettext functions into utf8 mode. + That is the strings are returned without translation to the native + charset. A VALUE of 0 swicthes back to trnslated strings. A VALUE + of -1 returns the current value. */ +int +_gpg_w32_gettext_use_utf8 (int value) +{ + struct tls_space_s *tls = get_tls (); + int last = tls->gt_use_utf8; + if (value != -1) + tls->gt_use_utf8 = value; + return last; +} + + +#ifdef TEST +int +main (int argc, char **argv) +{ + const char atext1[] = + "Warning: You have entered an insecure passphrase.%%0A" + "A passphrase should be at least %u character long."; + const char atext2[] = + "Warning: You have entered an insecure passphrase.%%0A" + "A passphrase should be at least %u characters long."; + + if (argc) + { + argc--; + argv++; + } + + _gpg_err_w32_bindtextdomain ("gnupg2", "c:/programme/gnu/gnupg/share/locale"); + + printf ("locale is `%s'\n", _gpg_err_w32_gettext_localename ()); + fputs ("text with N=1:\n", stdout); + fputs (_gpg_err_w32_ngettext (atext1, atext2, 1), stdout); + fputs ("\n\ntext with N=2:\n", stdout); + fputs (_gpg_err_w32_ngettext (atext1, atext2, 2), stdout); + fputs ("\nready\n", stdout); + + return 0; } +/* + * Local Variables: + * compile-command: "i586-mingw32msvc-gcc -DTEST -Wall -g w32-gettext.c" + * End: + */ +#endif /*TEST*/ diff --git a/src/w32-gettext.h b/src/w32-gettext.h deleted file mode 100644 index ce69ffe..0000000 --- a/src/w32-gettext.h +++ /dev/null @@ -1,58 +0,0 @@ -/* w32-gettext.h - A simple gettext implementation for Windows targets. - Copyright (C) 2005 g10 Code GmbH - - This file is part of libgpg-error. - - libgpg-error is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - libgpg-error is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with libgpg-error; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if ENABLE_NLS - -#ifdef HAVE_W32CE_SYSTEM -# define LC_ALL 0 -#else -# include <locale.h> -#endif -#if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun)) -# define LC_MESSAGES 1729 -#endif - -/* If we build on w32, we will use our own simple gettext - implementation. For now, this is not a drop in replacement, so we - must cheat a bit and redirect all calls to the external gettext to - an internal implementation. We try to be as little invasive as - possible, so that the refactorization of the code occurs at logical - interfaces. - - Note that this function intimately knows the various definitions in - the target libintl.h and the local gettext.h file, from which it is - included. */ - -#define bindtextdomain _gpg_err_bindtextdomain -#define textdomain _gpg_err_textdomain -#define dgettext _gpg_err_dgettext -#define gettext _gpg_err_gettext - -/* Specify that the DOMAINNAME message catalog will be found - in DIRNAME rather than in the system locale data base. */ -char *bindtextdomain (const char *domainname, const char *dirname); - -const char *gettext (const char *msgid); - -char *textdomain (const char *domainname); - -char *dgettext (const char *domainname, const char *msgid); - -#endif /* ENABLE_NLS */ |