diff --git a/ChangeLog b/ChangeLog index b72f89c5a..adefd49ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,15 @@ 2010-02-26 Werner Koch + * gl/mkdtemp.c (__set_errno) [W32CE]: Use gpg_err_set_errno. + * gl/setenv.c (__set_errno) [W32CE]: Ditto. + * gl/unsetenv.c (__set_errno) [W32CE]: Ditto. + * configure.ac (HAVE_W32CE_SYSTEM): New ac_define and am_conditional. - * autogen.sh: New option --build-w32ce. + (signal.h, getenv): Check for them. + + * autogen.sh: New option --build-w32ce. Remove obsolete option + --without-included-gettext. 2009-12-08 Werner Koch @@ -412,7 +419,7 @@ 2006-09-18 Werner Koch Released 1.9.23. - + * configure.ac (--enable-agent-only): Donot build tools and doc (--disable-tools,--disable-doc): New. * Makefile.am (SUBDIRS): Allow to conditional build tools and doc. @@ -421,7 +428,7 @@ Replaced all call gpg_error_from_errno(errno) by gpg_error_from_syserror(). - + * configure.ac: Build gpg by default. (GNUPG_SYS_SO_PEERCRED): Removed. @@ -436,7 +443,7 @@ 2006-09-06 Werner Koch * configure.ac: Define _ASSUAN_ONLY_GPG_ERRORS. Require Assuan - 0.9 and libgpg-error 1.4 + 0.9 and libgpg-error 1.4. 2006-08-31 Werner Koch @@ -478,7 +485,7 @@ 2006-07-03 Werner Koch - * configure.ac: Test for ksba_dn_teststr. + * configure.ac: Test for ksba_dn_teststr. 2006-06-30 Werner Koch @@ -486,7 +493,7 @@ * Makefile.am (SUBDIRS): Include keyserver/. * configure.ac: Include keyserver/. (FAKE_CURL, GPGKEYS_CURL): New. - + 2006-06-20 Werner Koch Released 1.9.21. @@ -540,7 +547,7 @@ 2005-08-01 Werner Koch Released 1.9.18. - + * configure.ac: Require libksba 0.9.12 to match new features in gpgsm. 2005-06-20 Werner Koch @@ -577,7 +584,7 @@ 2005-04-21 Werner Koch Released 1.9.16. - + * configure.ac: Do not build gpg by default. 2005-04-20 Werner Koch @@ -592,7 +599,7 @@ 2005-04-15 Marcus Brinkmann * configure.ac: Check for /usr/bin/shred and define SHRED. - + * configure.ac: Add --enable-symcryptrun, disabled by default. Define automake variable BUILD_SYMCRYPTRUN. Check for openpty -lutil, define LIBUTIL_LIBS. @@ -635,8 +642,8 @@ 2004-12-20 Werner Koch * configure.ac: Add PATHSEP_C and PATHSEP_S. For W32 let all - directories default to c:/gnupg. Require libassuan 0.6.9. - + directories default to c:/gnupg. Require libassuan 0.6.9. + 2004-12-18 Werner Koch * configure.ac (AH_BOTTOM): Define EXEEXT_S. @@ -666,7 +673,7 @@ * configure.ac: Replace strsep. Replaced use of "target" by "host". - + 2004-10-22 Werner Koch Released 1.9.12. @@ -689,7 +696,7 @@ * configure.ac: Build Makefile for tests/pkits. New option --with-pkits-tests. - + 2004-08-05 Werner Koch * configure.ac: Changed tests for libusb to also suuport the @@ -754,7 +761,7 @@ 2004-03-06 Werner Koch Released 1.9.6. - + * configure.ac: Check the Libgcrypt API. 2004-02-25 Werner Koch @@ -842,7 +849,7 @@ 2003-11-17 Werner Koch Release 1.9.2. - + * configure.ac: Requires now libassuan 0.6.1. 2003-10-31 Werner Koch @@ -858,12 +865,12 @@ 2003-10-01 Werner Koch - * configure.ac (AH_BOTTOM): Define GNUPG_MAJOR_VERSION. + * configure.ac (AH_BOTTOM): Define GNUPG_MAJOR_VERSION. 2003-09-23 Werner Koch Merged most of David Shaw's changes in 1.3 since 2003-06-03. - + * configure.ac: Drop all TIGER/192 support. (uint64_t): Check for UINT64_C to go along with uint64_t. (getaddrinfo): Check for it. @@ -877,7 +884,7 @@ 2003-09-06 Werner Koch Released 1.9.1. - + * configure.ac: Require newer versions of some libraries. 2003-09-02 Werner Koch @@ -898,9 +905,9 @@ 2003-08-05 Werner Koch Released 1.9.0. - + * configure.ac (GNUPG_DEFAULT_HONMEDIR): Changed back to ~/.gnupg. - + 2003-07-31 Werner Koch * Makefile.am (DISTCLEANFILES): Add g10defs.h @@ -923,7 +930,7 @@ * configure.ac: Build a limited version of scdaemon if libopensc is not available. - + * configure.ac (ALL_LINUGAS): Removed. * Makefile.am (ACLOCAL_AMFLAGS): New. @@ -945,10 +952,10 @@ 2003-01-09 Werner Koch - * configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool. + * configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool. (NEED_KSBA_VERSION): Does now require 0.4.6. - * README: Noted where to find gpg-protect-tool. + * README: Noted where to find gpg-protect-tool. 2002-10-31 Neal H. Walfield @@ -1004,7 +1011,7 @@ 2002-08-10 Werner Koch Released 0.3.10. - + * configure.ac (NEED_LIBKSBA_VERSION): Require 0.4.4. Add support for gettext. @@ -1015,7 +1022,7 @@ 2002-07-01 Werner Koch Released 0.3.9. - + * README: Short note on how to export in pkcs-12 format. 2002-06-29 Werner Koch @@ -1032,7 +1039,7 @@ 2002-06-25 Werner Koch Released 0.3.8. - + * configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.1.8. 2002-06-12 Werner Koch @@ -1050,7 +1057,7 @@ 2002-05-14 Werner Koch * doc/: New - * configure.ac, Makefile.am: Added doc/ + * configure.ac, Makefile.am: Added doc/. 2002-05-03 Werner Koch @@ -1067,9 +1074,9 @@ 2002-04-15 Werner Koch Released 0.3.5. - + * NEWS: Started to describe release notes. - + * configure.ac (NEED_LIBKSBA_VERSION, NEED_LIBGCRYPT_VERSION): Defined 2002-04-01 Werner Koch @@ -1154,9 +1161,9 @@ * configure.ac (HAVE_JNLIB_LOGGING): always define it. - - Copyright 2001, 2002, 2003, 2004, 2005, 2006, - 2007 Free Software Foundation, Inc. + + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007. + 2010 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without @@ -1165,5 +1172,5 @@ This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, to the extent permitted by law; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - + diff --git a/NEWS b/NEWS index 2fcf9fa16..a81215c1e 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ Noteworthy changes in version 2.1.x (under development) * New and changed passphrases are now created with an iteration count requiring about 100ms of CPU work. + * Ported to Windows CE. + Noteworthy changes in version 2.0.13 (2009-09-04) ------------------------------------------------- diff --git a/autogen.sh b/autogen.sh index 86552ee0d..2edbababb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -123,8 +123,7 @@ if [ "$myhost" = "w32" ]; then --with-zlib=${w32root} \ --with-regex=${w32root} \ --with-pth-prefix=${w32root} \ - --with-adns=${w32root} \ - --without-included-gettext "$@" + --with-adns=${w32root} "$@" rc=$? exit $rc fi diff --git a/configure.ac b/configure.ac index 7ac5ec05a..abb26cfd5 100644 --- a/configure.ac +++ b/configure.ac @@ -918,6 +918,9 @@ AC_SUBST(GPGKEYS_MAILTO) # Construct a printable name of the OS # case "${host}" in + *-mingw32ce*) + PRINTABLE_OS_NAME="W32CE" + ;; *-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; @@ -1089,9 +1092,11 @@ AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include ]) # # These are needed by libjnlib - fixme: we should use a jnlib.m4 # Note: We already checked pwd.h. -AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol]) -AC_CHECK_FUNCS([memrchr isascii timegm getrusage setrlimit stat setlocale]) -AC_CHECK_FUNCS([flockfile funlockfile fopencookie funopen getpwnam getpwuid]) +AC_CHECK_HEADERS([signal.h]) +AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \ + memrchr isascii timegm getrusage setrlimit stat setlocale \ + flockfile funlockfile fopencookie funopen getpwnam getpwuid \ + getenv ]) # # gnulib checks diff --git a/gl/Makefile.am b/gl/Makefile.am index 59667db7b..5c1d7c47b 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -29,6 +29,10 @@ MAINTAINERCLEANFILES = AM_CPPFLAGS = +if HAVE_W32CE_SYSTEM +AM_CFLAGS = $(GPG_ERROR_CFLAGS) +endif + ## begin gnulib module alloca-opt BUILT_SOURCES += $(ALLOCA_H) diff --git a/gl/mkdtemp.c b/gl/mkdtemp.c index 4cf86a0cc..e3abb11fd 100644 --- a/gl/mkdtemp.c +++ b/gl/mkdtemp.c @@ -23,7 +23,12 @@ #include #ifndef __set_errno -# define __set_errno(Val) errno = (Val) +# ifdef HAVE_W32CE_SYSTEM +# include +# define __set_errno(Val) gpg_err_set_errno ((Val)) +# else +# define __set_errno(Val) errno = (Val) +# endif #endif #include diff --git a/gl/setenv.c b/gl/setenv.c index 7c03d62b4..a7483966a 100644 --- a/gl/setenv.c +++ b/gl/setenv.c @@ -21,7 +21,12 @@ #include #ifndef __set_errno -# define __set_errno(ev) ((errno) = (ev)) +# ifdef HAVE_W32CE_SYSTEM +# include +# define __set_errno(ev) gpg_err_set_errno ((ev)) +# else +# define __set_errno(ev) ((errno) = (ev)) +# endif #endif #include diff --git a/gl/unsetenv.c b/gl/unsetenv.c index 76b707cad..222d7fc67 100644 --- a/gl/unsetenv.c +++ b/gl/unsetenv.c @@ -18,7 +18,12 @@ #include #if !_LIBC -# define __set_errno(ev) ((errno) = (ev)) +# ifdef HAVE_W32CE_SYSTEM +# include +# define __set_errno(ev) gpg_err_set_errno ((ev)) +# else +# define __set_errno(ev) ((errno) = (ev)) +# endif #endif #include diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 54984930d..5a9e7072d 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,44 @@ +2010-02-26 Werner Koch + + * t-timestuff.c: New. + + * dynload.h (dlopen, dlsym) [W32CE]: Map to wchar_t. + + * mischelp.c (_jnlib_free): New. + (same_file_p) [W32CE]: Map to wchar_t. + + * utf8conv.c (set_native_charset) [W32CE]: Do not use + GetConsoleOutputCP. + (wchar_to_utf8, utf8_to_wchar) [W32]: New. + + * Makefile.am (t_jnlib_ldadd) [W32CE]: Add gpg-error. + + * t-support.h (getenv) [HAVE_GETENV]: Add getenv stub. + [W32CE]: Include gpg-error.h + * t-support.c (gpg_err_code_from_errno) + (gpg_err_code_from_syserror) [GPG_ERROR_H]: Do not build. + + * t-stringhelp.c (gethome) [!HAVE_GETPWUID]: Keep result of getenv. + + * dotlock.c [!HAVE_SIGNAL_H]: Don't include signal.h. + (create_dotlock) [W32CE]: Map filename top wchar_t. + + * libjnlib-config.h [USE_SIMPLE_GETTEXT]: Include gpg-error.h and + remove w32help.h. + (jnlib_set_errno): New. Use it everywhere to set ERRNO. + (getenv) [!HAVE_GETENV]: New. + (getpid) [W32E]: New. + + * stringhelp.c (get_pwdir) [!HAVE_PWD_H]: Mark unused args. + (w32_strerror) [W32CE]: Use a simple implementation. + + * w32help.h [USE_SIMPLE_GETTEXT]: Remove all definitions; we are + now using the gpg-error included implementation. + * w32-gettext.c: Remove. + + * mischelp.c (same_file_p): Fix bug in case the second file can't + be opened. + 2009-10-19 Werner Koch * strlist.c (add_to_strlist_try): New. @@ -696,10 +737,10 @@ Mon Jan 24 13:04:28 CET 2000 Werner Koch *********************************************************** * Please note that JNLIB is maintained as part of GnuPG. * * You may find it source-copied in other packages. * - *********************************************************** - - Copyright 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + *********************************************************** + + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2010 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index c6d0b3a85..a0da872aa 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -1,6 +1,6 @@ # Makefile for the JNLIB part of GnuPG -# Copyright (C) 1999, 2000, 2001, 2004, -# 2006 Feee Software Soundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2004, 2006, +# 2010 Feee Software Soundation, Inc. # # This file is part of JNLIB. # @@ -44,7 +44,7 @@ libjnlib_a_SOURCES = \ types.h mischelp.c mischelp.h dynload.h w32help.h if HAVE_W32_SYSTEM -libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h w32-gettext.c +libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h endif @@ -60,11 +60,19 @@ endif # defines replacements for the actual used memory allocation functions # so that there is no dependency on libgcrypt. # -module_tests = t-stringhelp +module_tests = t-stringhelp t-timestuff t_jnlib_src = t-support.c t-support.h t_jnlib_ldadd = libjnlib.a $(LIBINTL) $(LIBICONV) +# For W32 we need libgpg-error because it provides gettext. +if HAVE_W32_SYSTEM +t_jnlib_ldadd += $(GPG_ERROR_LIBS) +endif t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src) t_stringhelp_LDADD = $(t_jnlib_ldadd) +t_timestuff_SOURCES = t-timestuff.c $(t_jnlib_src) +t_timestuff_LDADD = $(t_jnlib_ldadd) + + diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index bf179bee4..0d5a7bce9 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -35,11 +35,14 @@ #include #include #include -#include +#ifdef HAVE_SIGNAL_H +# include +#endif #include "libjnlib-config.h" #include "stringhelp.h" #include "dotlock.h" +#include "utf8conv.h" #if !defined(DIRSEP_C) && !defined(EXTSEP_C) \ && !defined(DIRSEP_S) && !defined(EXTSEP_S) @@ -222,7 +225,7 @@ create_dotlock (const char *file_to_lock) do { - errno = 0; + jnlib_set_errno (0); fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); } @@ -301,10 +304,23 @@ create_dotlock (const char *file_to_lock) would not stop as expected but spin til until Windows crashes. Our solution is to keep the lock file open; that does not harm. */ - h->lockhd = CreateFile (h->lockname, - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, 0, NULL); + { +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wname = utf8_to_wchar (h->lockname); + + h->lockhd = INVALID_HANDLE_VALUE; + if (wname) + h->lockhd = CreateFile (wname, +#else + h->lockhd = CreateFile (h->lockname, +#endif + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, 0, NULL); +#ifdef HAVE_W32CE_SYSTEM + jnlib_free (wname); +#endif + } if (h->lockhd == INVALID_HANDLE_VALUE) { log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1)); @@ -613,7 +629,7 @@ read_lockfile (dotlock_t h, int *same_node ) h->lockname, strerror(errno) ); if (buffer != buffer_space) jnlib_free (buffer); - errno = e; /* Need to return ERRNO here. */ + jnlib_set_errno (e); /* Need to return ERRNO here. */ return -1; } @@ -630,7 +646,7 @@ read_lockfile (dotlock_t h, int *same_node ) close (fd); if (buffer != buffer_space) jnlib_free (buffer); - errno = 0; /* Do not return an inappropriate ERRNO. */ + jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */ return -1; } p += res; @@ -644,7 +660,7 @@ read_lockfile (dotlock_t h, int *same_node ) log_info ("invalid size of lockfile `%s'", h->lockname ); if (buffer != buffer_space) jnlib_free (buffer); - errno = 0; /* Better don't return an inappropriate ERRNO. */ + jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */ return -1; } @@ -660,7 +676,7 @@ read_lockfile (dotlock_t h, int *same_node ) log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname ); if (buffer != buffer_space) jnlib_free (buffer); - errno = 0; + jnlib_set_errno (0); return -1; } diff --git a/jnlib/dynload.h b/jnlib/dynload.h index 54774650d..0c8a3bbaa 100644 --- a/jnlib/dynload.h +++ b/jnlib/dynload.h @@ -1,5 +1,5 @@ /* dynload.h - Wrapper functions for run-time dynamic loading - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2010 Free Software Foundation, Inc. * * This file is part of JNLIB. * @@ -24,13 +24,21 @@ # include #else # include - +# include "utf8conv.h" +# include "mischelp.h" # define RTLD_LAZY 0 static inline void * -dlopen (const char * name, int flag) +dlopen (const char *name, int flag) { - void * hd = LoadLibrary (name); + void *hd; +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wname = utf8_to_wchar (name); + hd = wname? LoadLibrary (wname) : NULL; + _jnlib_free (wname); +#else + hd = LoadLibrary (name); +#endif (void)flag; return hd; } @@ -40,7 +48,13 @@ dlsym (void *hd, const char *sym) { if (hd && sym) { - void * fnc = GetProcAddress (hd, sym); +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wsym = utf8_to_wchar (sym); + void *fnc = wsym? GetProcAddress (hd, wsym) : NULL; + _jnlib_free (wsym); +#else + void *fnc = GetProcAddress (hd, sym); +#endif if (!fnc) return NULL; return fnc; @@ -53,7 +67,7 @@ static inline const char * dlerror (void) { static char buf[32]; - sprintf (buf, "ec=%lu", GetLastError ()); + snprintf (buf, sizeof buf, "ec=%lu", GetLastError ()); return buf; } diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index 5c6144286..621e89feb 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -39,7 +39,7 @@ /* Gettext stuff */ #ifdef USE_SIMPLE_GETTEXT -# include "w32help.h" +# include # define _(a) gettext (a) # define N_(a) (a) @@ -80,5 +80,20 @@ #define jnlib_log_fatal log_fatal #define jnlib_log_bug log_bug +/* Wrapper to set ERRNO. */ +#ifdef HAVE_W32CE_SYSTEM +# define jnlib_set_errno(e) gpg_err_set_errno ((e)) +#else +# define jnlib_set_errno(e) do { errno = (e); } while (0) +#endif + +/* Dummy replacement for getenv. */ +#ifndef HAVE_GETENV +#define getenv(a) (NULL) +#endif + +#ifdef HAVE_W32CE_SYSTEM +#define getpid() GetCurrentProcessId () +#endif #endif /*LIBJNUTIL_CONFIG_H*/ diff --git a/jnlib/mischelp.c b/jnlib/mischelp.c index f7df5c154..e06be21f2 100644 --- a/jnlib/mischelp.c +++ b/jnlib/mischelp.c @@ -29,12 +29,24 @@ # include # include #endif /*!HAVE_W32_SYSTEM*/ +#include #include "libjnlib-config.h" #include "stringhelp.h" +#include "utf8conv.h" #include "mischelp.h" +/* Because we can't use our jnlib_free macro in inline functions we + provide this wrapper. */ +void +_jnlib_free (void *p) +{ + if (p) + jnlib_free (p); +} + + /* Check whether the files NAME1 and NAME2 are identical. This is for example achieved by comparing the inode numbers of the files. */ int @@ -50,14 +62,36 @@ same_file_p (const char *name1, const char *name2) #ifdef HAVE_W32_SYSTEM HANDLE file1, file2; BY_HANDLE_FILE_INFORMATION info1, info2; - + +#ifdef HAVE_W32CE_SYSTEM + { + wchar_t *wname = utf8_to_wchar (name1); + if (wname) + file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + else + file1 = INVALID_HANDLE_VALUE; + jnlib_free (wname); + } +#else file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); +#endif if (file1 == INVALID_HANDLE_VALUE) yes = 0; /* If we can't open the file, it is not the same. */ else { +#ifdef HAVE_W32CE_SYSTEM + { + wchar_t *wname = utf8_to_wchar (name2); + if (wname) + file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + else + file2 = INVALID_HANDLE_VALUE; + jnlib_free (wname); + } +#else file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - if (file1 == INVALID_HANDLE_VALUE) +#endif + if (file2 == INVALID_HANDLE_VALUE) yes = 0; /* If we can't open the file, it is not the same. */ else { @@ -87,7 +121,7 @@ same_file_p (const char *name1, const char *name2) and get back a time_t. It differs from mktime() in that it handles the case where the struct tm is UTC and the local environment isn't. - Note, that this replacement implementaion is not thread-safe! + Note, that this replacement implementation might not be thread-safe! Some BSDs don't handle the putenv("foo") case properly, so we use unsetenv if the platform has it to remove environment variables. @@ -96,6 +130,35 @@ same_file_p (const char *name1, const char *name2) time_t timegm (struct tm *tm) { +#ifdef HAVE_W32_SYSTEM + /* This one is thread safe. */ + SYSTEMTIME st; + FILETIME ft; + unsigned long long cnsecs; + + st.wYear = tm->tm_year + 1900; + st.wMonth = tm->tm_mon + 1; + st.wDay = tm->tm_mday; + st.wHour = tm->tm_hour; + st.wMinute = tm->tm_min; + st.wSecond = tm->tm_sec; + st.wMilliseconds = 0; /* Not available. */ + st.wDayOfWeek = 0; /* Ignored. */ + + /* System time is UTC thus the conversion is pretty easy. */ + if (!SystemTimeToFileTime (&st, &ft)) + { + jnlib_set_errno (EINVAL); + return (time_t)(-1); + } + + cnsecs = (((unsigned long long)ft.dwHighDateTime << 32) + | ft.dwLowDateTime); + cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */ + return (time_t)(cnsecs / 10000000ULL); + +#else /* (Non thread safe implementation!) */ + time_t answer; char *zone; @@ -128,6 +191,7 @@ timegm (struct tm *tm) tzset(); return answer; +#endif } #endif /*!HAVE_TIMEGM*/ diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h index e478354d1..52781e12f 100644 --- a/jnlib/mischelp.h +++ b/jnlib/mischelp.h @@ -22,6 +22,10 @@ #define LIBJNLIB_MISCHHELP_H +/* Because we can't use the internal jnlib_free macro in inline + functions we provide a wrapper fucntion as well. */ +void _jnlib_free (void *p); + /* Check whether the files NAME1 and NAME2 are identical. This is for example achieved by comparing the inode numbers of the files. */ int same_file_p (const char *name1, const char *name2); diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 3173ebc15..36f96b8ff 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -346,6 +346,10 @@ get_pwdir (int xmode, const char *name) else result = jnlib_strdup (pwd->pw_dir); } +#else /*!HAVE_PWD_H*/ + /* No support at all. */ + (void)xmode; + (void)name; #endif /*HAVE_PWD_H*/ return result; } @@ -369,7 +373,7 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr) { if (xmode) BUG (); - errno = EINVAL; + jnlib_set_errno (EINVAL); return NULL; } argc++; @@ -738,9 +742,15 @@ w32_strerror (int ec) if (ec == -1) ec = (int)GetLastError (); +#ifdef HAVE_W32CE_SYSTEM + /* There is only a wchar_t FormatMessage. It does not make much + sense to play the conversion game; we print only the code. */ + snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ()); +#else FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), strerr, DIM (strerr)-1, NULL); +#endif return strerr; } #endif /*HAVE_W32_SYSTEM*/ @@ -1076,7 +1086,7 @@ do_strconcat (const char *s1, va_list arg_ptr) needed += strlen (argv[argc]); if (argc >= DIM (argv)-1) { - errno = EINVAL; + jnlib_set_errno (EINVAL); return NULL; } argc++; diff --git a/jnlib/t-stringhelp.c b/jnlib/t-stringhelp.c index 02041d35e..0c921b03d 100644 --- a/jnlib/t-stringhelp.c +++ b/jnlib/t-stringhelp.c @@ -43,9 +43,9 @@ gethome (void) { char *home = getenv("HOME"); -#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H) if(home) home_buffer = xstrdup (home); +#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H) else { struct passwd *pwd; diff --git a/jnlib/t-support.c b/jnlib/t-support.c index d8eba3b59..bf05c4c06 100644 --- a/jnlib/t-support.c +++ b/jnlib/t-support.c @@ -120,6 +120,7 @@ gcry_free (void *a) require functions called from these inline fucntions. Although we do not use gpg-error, gpg-error.h may get included via gcrypt.h if it happens to be used used in libjnlib-config.h. */ +#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ int gpg_err_code_from_errno (int err) { @@ -127,17 +128,20 @@ gpg_err_code_from_errno (int err) assert (!"stub function"); return -1; } +#endif /*GPG_ERROR_H*/ /* Retrieve the error code directly from the ERRNO variable. This returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ +#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ int gpg_err_code_from_syserror (void) { assert (!"stub function"); return -1; } +#endif /*GPG_ERROR_H*/ diff --git a/jnlib/t-support.h b/jnlib/t-support.h index 52701741b..2dfbc0990 100644 --- a/jnlib/t-support.h +++ b/jnlib/t-support.h @@ -24,7 +24,17 @@ #error The regression tests should not include with gcrypt.h #endif -/* Repalcement prototypes. */ +#ifdef HAVE_W32CE_SYSTEM +#include /* Defines strerror. */ +#endif + + +#ifndef HAVE_GETENV +# define getenv(a) (NULL) +#endif + + +/* Replacement prototypes. */ void *gcry_xmalloc (size_t n); void *gcry_xcalloc (size_t n, size_t m); void *gcry_xrealloc (void *a, size_t n); diff --git a/jnlib/t-timestuff.c b/jnlib/t-timestuff.c new file mode 100644 index 000000000..46816765d --- /dev/null +++ b/jnlib/t-timestuff.c @@ -0,0 +1,145 @@ +/* t-timestuff.c - Regression tests for time functions + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB 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 3 of + * the License, or (at your option) any later version. + * + * JNLIB 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include "mischelp.h" + +#include "t-support.h" + + +static int +cmp_time_s (struct tm *a, struct tm *b) +{ + if (a->tm_year != b->tm_year + || a->tm_mon != b->tm_mon + || a->tm_mday != b->tm_mday + || a->tm_hour != b->tm_hour + || a->tm_min != b->tm_min + || a->tm_sec != b->tm_sec + || a->tm_wday != b->tm_wday + || a->tm_yday != b->tm_yday + || !a->tm_isdst != !b->tm_isdst) + return -1; + return 0; +} + + + +static void +test_timegm (void) +{ + static struct { + int year, mon, mday, hour, min, sec; + } tvalues[] = { + { -1 }, + { -2, 1 }, + { -2, 2 }, + { -2, 86399 }, + { -2, 86400 }, + { -2, 0x7ffffffe }, + { -2, 0x7fffffff }, + /* Note: Because we use mktime below we can only start with the + day after Epoch. */ + { 1970, 1, 2, 0, 0 , 1}, + { 1970, 1, 2, 0, 0 , 2}, + { 1970, 1, 2, 12, 0 , 0}, + { 1970, 1, 2, 23, 59 , 59}, + { 1999, 12, 31, 23, 59 , 59}, + { 2000, 1, 1, 0, 0, 0}, + { 2000, 1, 1, 0, 0, 1}, + { 2010, 12, 31, 23, 59 , 59}, + { 2010, 1, 1, 0, 0, 0}, + { 2010, 1, 1, 0, 0, 1}, + /* The date below is about the last time mktime works in CET on + Windows XP; this is a somewhat strange because 32 bit Unices + will happily work along for another month until they reach the + end of all ticks on 20380119T031408 (unless Uli takes + compassion on us and changes time_t to a u64). */ + { 2037, 12, 18, 23, 59, 59} + + }; + int tidx; + time_t now, atime, counter; + struct tm tbuf, tbuf2, *tp; + + counter = 0; + for (tidx=0; tidx < DIM (tvalues); tidx++) + { + if (tvalues[tidx].year == -1) + { + now = time (NULL); + } + else if (tvalues[tidx].year == -2) + { + now = tvalues[tidx].mon; + } + else + { + memset (&tbuf, 0, sizeof tbuf); + tbuf.tm_year = tvalues[tidx].year - 1900; + tbuf.tm_mon = tvalues[tidx].mon; + tbuf.tm_mday = tvalues[tidx].mday; + tbuf.tm_hour = tvalues[tidx].hour; + tbuf.tm_min = tvalues[tidx].min; + tbuf.tm_sec = tvalues[tidx].sec; + now = mktime (&tbuf); + } + if (now == (time_t)(-1)) + fail (tidx); + + tp = gmtime (&now); + if (!tp) + fail (tidx); + tbuf = *tp; + tbuf2 = tbuf; + atime = timegm (&tbuf); + if (atime == (time_t)(-1)) + fail (tidx); + if (atime != now) + fail (tidx); + + tp = gmtime (&atime); + if (!tp) + fail (tidx); + if (cmp_time_s (tp, &tbuf)) + fail (tidx); + if (cmp_time_s (tp, &tbuf2)) + fail (tidx); + } +} + + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + test_timegm (); + + return 0; +} + diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c index fee4dc6a5..6cbe4e92c 100644 --- a/jnlib/utf8conv.c +++ b/jnlib/utf8conv.c @@ -1,6 +1,6 @@ /* utf8conf.c - UTF8 character set conversion - * Copyright (C) 1994, 1998, 1999, 2000, 2001, - * 2003, 2006, 2008 Free Software Foundation, Inc. + * Copyright (C) 1994, 1998, 1999, 2000, 2001, 2003, 2006, + * 2008, 2010 Free Software Foundation, Inc. * * This file is part of JNLIB. * @@ -50,12 +50,12 @@ static int use_iconv; /* iconv comversion fucntions required. */ #ifdef HAVE_W32_SYSTEM typedef void *iconv_t; #ifndef ICONV_CONST -#define ICONV_CONST const +#define ICONV_CONST #endif static iconv_t (* __stdcall iconv_open) (const char *tocode, const char *fromcode); static size_t (* __stdcall iconv) (iconv_t cd, - const char **inbuf, size_t *inbytesleft, + char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); static int (* __stdcall iconv_close) (iconv_t cd); @@ -166,8 +166,10 @@ set_native_charset (const char *newset) different one for console input. Not sure how to cope with that. If the console Code page is not known we fall back to the system code page. */ +#ifndef HAVE_W32CE_SYSTEM cpno = GetConsoleOutputCP (); if (!cpno) +#endif cpno = GetACP (); sprintf (codepage, "CP%u", cpno ); /* Resolve alias. We use a long string string and not the usual @@ -736,3 +738,76 @@ jnlib_iconv_close (jnlib_iconv_t cd) return iconv_close ((iconv_t)cd); } + + +#ifdef HAVE_W32_SYSTEM +/* Return a malloced string encoded in UTF-8 from the wide char input + string STRING. Caller must free this value. Returns NULL and sets + ERRNO on failure. Calling this function with STRING set to NULL is + not defined. */ +char * +wchar_to_utf8 (const wchar_t *string) +{ + int n; + char *result; + + n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL); + if (n < 0) + { + jnlib_set_errno (EINVAL); + return NULL; + } + + result = jnlib_malloc (n+1); + if (!result) + return NULL; + + n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL); + if (n < 0) + { + jnlib_free (result); + jnlib_set_errno (EINVAL); + result = NULL; + } + return result; +} + + +/* Return a malloced wide char string from an UTF-8 encoded input + string STRING. Caller must free this value. Returns NULL and sets + ERRNO on failure. Calling this function with STRING set to NULL is + not defined. */ +wchar_t * +utf8_to_wchar (const char *string) +{ + int n; + size_t nbytes; + wchar_t *result; + + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); + if (n < 0) + { + jnlib_set_errno (EINVAL); + return NULL; + } + + nbytes = (size_t)(n+1) * sizeof(*result); + if (nbytes / sizeof(*result) != (n+1)) + { + jnlib_set_errno (ENOMEM); + return NULL; + } + result = malloc (nbytes); + if (!result) + return NULL; + + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); + if (n < 0) + { + free (result); + jnlib_set_errno (EINVAL); + result = NULL; + } + return result; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/jnlib/utf8conv.h b/jnlib/utf8conv.h index e800f81da..28dd450dd 100644 --- a/jnlib/utf8conv.h +++ b/jnlib/utf8conv.h @@ -36,6 +36,10 @@ size_t jnlib_iconv (jnlib_iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); int jnlib_iconv_close (jnlib_iconv_t cd); +#ifdef HAVE_W32_SYSTEM +char *wchar_to_utf8 (const wchar_t *string); +wchar_t *utf8_to_wchar (const char *string); +#endif /*HAVE_W32_SYSTEM*/ #endif /*LIBJNLIB_UTF8CONF_H*/ diff --git a/jnlib/w32-afunix.c b/jnlib/w32-afunix.c index 63653941e..579621491 100644 --- a/jnlib/w32-afunix.c +++ b/jnlib/w32-afunix.c @@ -51,14 +51,15 @@ read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) fclose (fp); if (!nread) { - errno = ENOFILE; +#warning remove this file + jnlib_set_errno (EIO); return -1; } buffer[nread] = 0; aval = atoi (buffer); if (aval < 1 || aval > 65535) { - errno = EINVAL; + jnlib_set_errno (EINVAL); return -1; } *port = (unsigned int)aval; @@ -66,7 +67,7 @@ read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) ; if (*p != '\n' || nread != 17) { - errno = EINVAL; + jnlib_set_errno (EINVAL); return -1; } p++; nread--; @@ -126,7 +127,7 @@ _w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen) ret = send (sockfd, nonce, 16, 0); if (ret >= 0 && ret != 16) { - errno = EIO; + jnlib_set_errno (EIO); ret = -1; } } diff --git a/jnlib/w32-gettext.c b/jnlib/w32-gettext.c deleted file mode 100644 index 3060a96e2..000000000 --- a/jnlib/w32-gettext.c +++ /dev/null @@ -1,1710 +0,0 @@ -/* w32-gettext.h - A simple gettext implementation for Windows targets. - Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007, - 2008, 2010 Free Software Foundation, Inc. - - This program 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. - - This program 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 . - */ - -#if HAVE_CONFIG_H -#include -#endif -#if !defined (_WIN32) && !defined (__CYGWIN32__) -# error This module may only be build for Windows or Cygwin32 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef JNLIB_IN_JNLIB -#include "libjnlib-config.h" -#endif - -#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) my_xstrdup(a) -#endif /*!jnlib_malloc*/ - - - -/* localname.c from gettext BEGIN. */ - -/* Determine the current selected locale. - Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -/* Written by Ulrich Drepper , 1995. */ -/* Win32 code written by Tor Lillqvist . */ -/* Renamed _nl_locale_name, removed unsed args, removed include files, - non-W32 code and changed comments . */ - -/* 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 - -/* 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 * -my_nl_locale_name (const char *categoryname) -{ - const char *retval; - LCID lcid; - LANGID langid; - int primary, sub; - - /* Let the user override the system settings through environment - variables, as on POSIX systems. */ -#ifndef HAVE_W32CE_SYSTEM - retval = getenv ("LC_ALL"); - if (retval != NULL && retval[0] != '\0') - return retval; - retval = getenv (categoryname); - if (retval != NULL && retval[0] != '\0') - return retval; - retval = getenv ("LANG"); - if (retval != NULL && retval[0] != '\0') - return retval; -#endif /*!HAVE_W32CE_SYSTEM*/ - - /* Use native Win32 API locale ID. */ -#ifdef HAVE_W32CE_SYSTEM - lcid = GetSystemDefaultLCID (); -#else - lcid = GetThreadLocale (); -#endif - - /* Strip off the sorting rules, keep only the language part. */ - langid = LANGIDFROMLCID (lcid); - - /* Split into language and territory part. */ - primary = PRIMARYLANGID (langid); - sub = SUBLANGID (langid); - - /* Dispatch on language. - See also http://www.unicode.org/unicode/onlinedat/languages.html . - For details about languages, see http://www.ethnologue.com/ . */ - switch (primary) - { - case LANG_AFRIKAANS: return "af_ZA"; - case LANG_ALBANIAN: return "sq_AL"; - case LANG_AMHARIC: return "am_ET"; - case LANG_ARABIC: - switch (sub) - { - case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; - case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; - case SUBLANG_ARABIC_EGYPT: return "ar_EG"; - case SUBLANG_ARABIC_LIBYA: return "ar_LY"; - case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; - case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; - case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; - case SUBLANG_ARABIC_OMAN: return "ar_OM"; - case SUBLANG_ARABIC_YEMEN: return "ar_YE"; - case SUBLANG_ARABIC_SYRIA: return "ar_SY"; - case SUBLANG_ARABIC_JORDAN: return "ar_JO"; - case SUBLANG_ARABIC_LEBANON: return "ar_LB"; - case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; - case SUBLANG_ARABIC_UAE: return "ar_AE"; - case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; - case SUBLANG_ARABIC_QATAR: return "ar_QA"; - } - return "ar"; - case LANG_ARMENIAN: return "hy_AM"; - case LANG_ASSAMESE: return "as_IN"; - case LANG_AZERI: - switch (sub) - { - /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ - case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; - case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; - } - return "az"; - case LANG_BASQUE: - return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ - case LANG_BELARUSIAN: return "be_BY"; - case LANG_BENGALI: - switch (sub) - { - case SUBLANG_BENGALI_INDIA: return "bn_IN"; - case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; - } - return "bn"; - case LANG_BULGARIAN: return "bg_BG"; - case LANG_BURMESE: return "my_MM"; - case LANG_CAMBODIAN: return "km_KH"; - case LANG_CATALAN: return "ca_ES"; - case LANG_CHEROKEE: return "chr_US"; - case LANG_CHINESE: - switch (sub) - { - case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW"; - case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN"; - case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; - case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; - case SUBLANG_CHINESE_MACAU: return "zh_MO"; - } - return "zh"; - case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN - * What used to be called Serbo-Croatian - * should really now be two separate - * languages because of political reasons. - * (Says tml, who knows nothing about Serbian - * or Croatian.) - * (I can feel those flames coming already.) - */ - switch (sub) - { - case SUBLANG_DEFAULT: return "hr_HR"; - case SUBLANG_SERBIAN_LATIN: return "sr_CS"; - case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; - } - return "hr"; - case LANG_CZECH: return "cs_CZ"; - case LANG_DANISH: return "da_DK"; - case LANG_DIVEHI: return "div_MV"; - case LANG_DUTCH: - switch (sub) - { - case SUBLANG_DUTCH: return "nl_NL"; - case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; - } - return "nl"; - case LANG_EDO: return "bin_NG"; - case LANG_ENGLISH: - switch (sub) - { - /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought - * English was the language spoken in England. - * Oh well. - */ - case SUBLANG_ENGLISH_US: return "en_US"; - case SUBLANG_ENGLISH_UK: return "en_GB"; - case SUBLANG_ENGLISH_AUS: return "en_AU"; - case SUBLANG_ENGLISH_CAN: return "en_CA"; - case SUBLANG_ENGLISH_NZ: return "en_NZ"; - case SUBLANG_ENGLISH_EIRE: return "en_IE"; - case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; - case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; - case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ - case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; - case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; - case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; - case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; - case SUBLANG_ENGLISH_INDONESIA: return "en_ID"; - case SUBLANG_ENGLISH_HONGKONG: return "en_HK"; - case SUBLANG_ENGLISH_INDIA: return "en_IN"; - case SUBLANG_ENGLISH_MALAYSIA: return "en_MY"; - case SUBLANG_ENGLISH_SINGAPORE: return "en_SG"; - } - return "en"; - case LANG_ESTONIAN: return "et_EE"; - case LANG_FAEROESE: return "fo_FO"; - case LANG_FARSI: return "fa_IR"; - case LANG_FINNISH: return "fi_FI"; - case LANG_FRENCH: - switch (sub) - { - case SUBLANG_FRENCH: return "fr_FR"; - case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE"; - case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; - case SUBLANG_FRENCH_SWISS: return "fr_CH"; - case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; - case SUBLANG_FRENCH_MONACO: return "fr_MC"; - case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */ - case SUBLANG_FRENCH_REUNION: return "fr_RE"; - case SUBLANG_FRENCH_CONGO: return "fr_CG"; - case SUBLANG_FRENCH_SENEGAL: return "fr_SN"; - case SUBLANG_FRENCH_CAMEROON: return "fr_CM"; - case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI"; - case SUBLANG_FRENCH_MALI: return "fr_ML"; - case SUBLANG_FRENCH_MOROCCO: return "fr_MA"; - case SUBLANG_FRENCH_HAITI: return "fr_HT"; - } - return "fr"; - case LANG_FRISIAN: return "fy_NL"; - case LANG_FULFULDE: return "ful_NG"; - case LANG_GAELIC: - switch (sub) - { - case 0x01: /* SCOTTISH */ return "gd_GB"; - case 0x02: /* IRISH */ return "ga_IE"; - } - return "C"; - case LANG_GALICIAN: return "gl_ES"; - case LANG_GEORGIAN: return "ka_GE"; - case LANG_GERMAN: - switch (sub) - { - case SUBLANG_GERMAN: return "de_DE"; - case SUBLANG_GERMAN_SWISS: return "de_CH"; - case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; - case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; - case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; - } - return "de"; - case LANG_GREEK: return "el_GR"; - case LANG_GUARANI: return "gn_PY"; - case LANG_GUJARATI: return "gu_IN"; - case LANG_HAUSA: return "ha_NG"; - case LANG_HAWAIIAN: - /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) - or Hawaii Creole English ("cpe_US", 600000 speakers)? */ - return "cpe_US"; - case LANG_HEBREW: return "he_IL"; - case LANG_HINDI: return "hi_IN"; - case LANG_HUNGARIAN: return "hu_HU"; - case LANG_IBIBIO: return "nic_NG"; - case LANG_ICELANDIC: return "is_IS"; - case LANG_IGBO: return "ibo_NG"; - case LANG_INDONESIAN: return "id_ID"; - case LANG_INUKTITUT: return "iu_CA"; - case LANG_ITALIAN: - switch (sub) - { - case SUBLANG_ITALIAN: return "it_IT"; - case SUBLANG_ITALIAN_SWISS: return "it_CH"; - } - return "it"; - case LANG_JAPANESE: return "ja_JP"; - case LANG_KANNADA: return "kn_IN"; - case LANG_KANURI: return "kau_NG"; - case LANG_KASHMIRI: - switch (sub) - { - case SUBLANG_DEFAULT: return "ks_PK"; - case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; - } - return "ks"; - case LANG_KAZAK: return "kk_KZ"; - case LANG_KONKANI: - /* FIXME: Adjust this when such locales appear on Unix. */ - return "kok_IN"; - case LANG_KOREAN: return "ko_KR"; - case LANG_KYRGYZ: return "ky_KG"; - case LANG_LAO: return "lo_LA"; - case LANG_LATIN: return "la_VA"; - case LANG_LATVIAN: return "lv_LV"; - case LANG_LITHUANIAN: return "lt_LT"; - case LANG_MACEDONIAN: return "mk_MK"; - case LANG_MALAY: - switch (sub) - { - case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; - case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; - } - return "ms"; - case LANG_MALAYALAM: return "ml_IN"; - case LANG_MALTESE: return "mt_MT"; - case LANG_MANIPURI: - /* FIXME: Adjust this when such locales appear on Unix. */ - return "mni_IN"; - case LANG_MARATHI: return "mr_IN"; - case LANG_MONGOLIAN: - return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ - case LANG_NEPALI: - switch (sub) - { - case SUBLANG_DEFAULT: return "ne_NP"; - case SUBLANG_NEPALI_INDIA: return "ne_IN"; - } - return "ne"; - case LANG_NORWEGIAN: - switch (sub) - { - case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO"; - case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; - } - return "no"; - case LANG_ORIYA: return "or_IN"; - case LANG_OROMO: return "om_ET"; - case LANG_PAPIAMENTU: return "pap_AN"; - case LANG_PASHTO: - return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ - case LANG_POLISH: return "pl_PL"; - case LANG_PORTUGUESE: - switch (sub) - { - case SUBLANG_PORTUGUESE: return "pt_PT"; - /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. - Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ - case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; - } - return "pt"; - case LANG_PUNJABI: - switch (sub) - { - case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ - } - return "pa"; - case LANG_RHAETO_ROMANCE: return "rm_CH"; - case LANG_ROMANIAN: - switch (sub) - { - case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; - } - return "ro"; - case LANG_RUSSIAN: - return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ - case LANG_SAAMI: /* actually Northern Sami */ return "se_NO"; - case LANG_SANSKRIT: return "sa_IN"; - case LANG_SINDHI: - switch (sub) - { - case SUBLANG_SINDHI_INDIA: return "sd_IN"; - case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; - } - return "sd"; - case LANG_SINHALESE: return "si_LK"; - case LANG_SLOVAK: return "sk_SK"; - case LANG_SLOVENIAN: return "sl_SI"; - case LANG_SOMALI: return "so_SO"; - case LANG_SORBIAN: - /* FIXME: Adjust this when such locales appear on Unix. */ - return "wen_DE"; - case LANG_SPANISH: - switch (sub) - { - case SUBLANG_SPANISH: return "es_ES"; - case SUBLANG_SPANISH_MEXICAN: return "es_MX"; - case SUBLANG_SPANISH_MODERN: - return "es_ES@modern"; /* not seen on Unix */ - case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; - case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; - case SUBLANG_SPANISH_PANAMA: return "es_PA"; - case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; - case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; - case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; - case SUBLANG_SPANISH_PERU: return "es_PE"; - case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; - case SUBLANG_SPANISH_ECUADOR: return "es_EC"; - case SUBLANG_SPANISH_CHILE: return "es_CL"; - case SUBLANG_SPANISH_URUGUAY: return "es_UY"; - case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; - case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; - case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; - case SUBLANG_SPANISH_HONDURAS: return "es_HN"; - case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; - case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; - } - return "es"; - case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ - case LANG_SWAHILI: return "sw_KE"; - case LANG_SWEDISH: - switch (sub) - { - case SUBLANG_DEFAULT: return "sv_SE"; - case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; - } - return "sv"; - case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */ - case LANG_TAGALOG: return "tl_PH"; - case LANG_TAJIK: return "tg_TJ"; - case LANG_TAMAZIGHT: - switch (sub) - { - /* FIXME: Adjust this when Tamazight locales appear on Unix. */ - case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; - case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin"; - } - return "ber_MA"; - case LANG_TAMIL: - return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ - case LANG_TATAR: return "tt_RU"; - case LANG_TELUGU: return "te_IN"; - case LANG_THAI: return "th_TH"; - case LANG_TIBETAN: return "bo_CN"; - case LANG_TIGRINYA: - switch (sub) - { - case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; - case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; - } - return "ti"; - case LANG_TSONGA: return "ts_ZA"; - case LANG_TSWANA: return "tn_BW"; - case LANG_TURKISH: return "tr_TR"; - case LANG_TURKMEN: return "tk_TM"; - case LANG_UKRAINIAN: return "uk_UA"; - case LANG_URDU: - switch (sub) - { - case SUBLANG_URDU_PAKISTAN: return "ur_PK"; - case SUBLANG_URDU_INDIA: return "ur_IN"; - } - return "ur"; - case LANG_UZBEK: - switch (sub) - { - case SUBLANG_UZBEK_LATIN: return "uz_UZ"; - case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; - } - return "uz"; - case LANG_VENDA: - /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code - "ve" or not. - http://www.loc.gov/standards/iso639-2/englangn.html has it, but - http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't, */ - return "ven_ZA"; /* or "ve_ZA"? */ - case LANG_VIETNAMESE: return "vi_VN"; - case LANG_WELSH: return "cy_GB"; - case LANG_XHOSA: return "xh_ZA"; - case LANG_YI: return "sit_CN"; - case LANG_YIDDISH: return "yi_IL"; - case LANG_YORUBA: return "yo_NG"; - case LANG_ZULU: return "zu_ZA"; - default: return "C"; - } -} - -/* localname.c from gettext END. */ - - - -/* Support functions. */ - -static __inline__ uint32_t -do_swap_u32 (uint32_t i) -{ - return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); -} - -#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data)) - - -/* We assume to have `unsigned long int' value with at least 32 bits. */ -#define HASHWORDBITS 32 - -/* 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__ unsigned long -hash_string( const char *str_param ) -{ - 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 ^= g >> (HASHWORDBITS - 8); - hval ^= g; - } - } - return hval; -} - -/* static char * */ -/* my_xstrdup (const char *s) */ -/* { */ -/* size_t n = strlen (s) + 1; */ -/* char *p = jnlib_malloc (n); */ -/* if (!p) */ -/* abort (); */ -/* strcpy (p, s); */ -/* return p; */ -/* } */ - - - -/* Generic message catalog and gettext stuff. */ - -/* The magic number of the GNU message catalog format. */ -#define MAGIC 0x950412de -#define MAGIC_SWAPPED 0xde120495 - -/* 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. */ - uint32_t magic; - /* The revision number of the file format. */ - uint32_t revision; - /* The number of strings pairs. */ - uint32_t nstrings; - /* Offset of table with start offsets of original strings. */ - uint32_t orig_tab_offset; - /* Offset of table with start offsets of translation strings. */ - uint32_t trans_tab_offset; - /* Size of hashing table. */ - uint32_t hash_tab_size; - /* Offset of first hashing entry. */ - uint32_t hash_tab_offset; -}; - - -struct string_desc -{ - /* Length of addressed string. */ - uint32_t length; - /* Offset of string in file. */ - uint32_t offset; -}; - - -struct overflow_space_s -{ - struct overflow_space_s *next; - 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; - uint32_t nstrings; /* Number of strings. */ - uint32_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; - uint32_t hash_size; - uint32_t *hash_tab; -}; - - -/* 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; - -/* Global flag to switch gettext into an utf8 mode. */ -static int want_utf8; - - - -/* Free the domain data. */ -static void -free_domain (struct loaded_domain *domain) -{ - struct overflow_space_s *os, *os2; - - jnlib_free (domain->data); - jnlib_free (domain->mapped); - for (os = domain->overflow_space; os; os = os2) - { - os2 = os->next; - jnlib_free (os); - } - jnlib_free (domain); -} - - -static struct loaded_domain * -load_domain (const char *filename) -{ - FILE *fp; - size_t size; - struct stat st; - struct mo_file_header *data = NULL; - struct loaded_domain *domain = NULL; - size_t to_read; - char *read_ptr; - - fp = fopen (filename, "rb"); - if (!fp) - return NULL; - - /* Determine the file size. */ - if (fstat (fileno (fp), &st) - || (size = (size_t) st.st_size) != st.st_size - || size < sizeof (struct mo_file_header)) - { - fclose (fp); - return NULL; - } - - data = (2*size <= size)? NULL : jnlib_malloc (2*size); - if (!data) - { - fclose (fp); - return NULL; - } - - to_read = size; - read_ptr = (char *) data; - do - { - long int nb = fread (read_ptr, 1, to_read, fp); - if (nb < to_read) - { - fclose (fp); - jnlib_free (data); - return NULL; - } - read_ptr += nb; - to_read -= nb; - } - while (to_read > 0); - fclose (fp); - - /* Using the magic number we can test whether it really is a message - catalog file. */ - if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED) - { - /* The magic number is wrong: not a message catalog file. */ - jnlib_free (data); - return NULL; - } - - domain = jnlib_calloc (1, sizeof *domain); - if (!domain) - { - 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 MO_REVISION_NUMBER: - 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 = (uint32_t *) - ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset)); - break; - - default: - /* This is an invalid revision. */ - jnlib_free (data); - jnlib_free (domain); - return NULL; - } - - /* Allocate an array to keep track of code page mappings. */ - domain->mapped = jnlib_calloc (domain->nstrings, sizeof *domain->mapped); - if (!domain->mapped) - { - jnlib_free (data); - jnlib_free (domain); - return NULL; - } - - return domain; -} - - -/* Return a malloced wide char string from an UTF-8 encoded input - string STRING. Caller must free this value. On failure returns - 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; - wchar_t *result; - size_t nbytes; - - n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0); - if (n < 0 || (n+1) <= 0) - return NULL; - - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - { - errno = ENOMEM; - return NULL; - } - result = jnlib_malloc (nbytes); - if (!result) - return NULL; - - n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n); - if (n < 0) - { - jnlib_free (result); - return NULL; - } - *retlen = n; - return result; -} - - -/* Return a malloced string encoded in UTF-8 from the wide char input - string STRING. Caller must free this value. On failure returns - 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; - char *result; - - n = WideCharToMultiByte (CP_ACP, 0, string, length, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - return NULL; - - result = jnlib_malloc (n+1); - if (!result) - return NULL; - - n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); - if (n < 0) - { - 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, size_t length, size_t *retlen) -{ - wchar_t *wstring; - char *result; - size_t newlen; - - wstring = utf8_to_wchar (string, length, &newlen); - if (wstring) - { - result = wchar_to_native (wstring, newlen, &newlen); - jnlib_free (wstring); - } - else - result = NULL; - *retlen = result? newlen : 0; - return result; -} - - - - -/* 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) -{ - struct loaded_domain *domain = NULL; - const char *catval_full; - char *catval; - char *fname; - - /* DOMAINNAME is ignored. We only support one domain. */ - - /* DIRNAME is "$INSTALLDIR\share\locale". */ - - /* First find out the category value. */ - catval = NULL; - catval_full = my_nl_locale_name ("LC_MESSAGES"); - - /* 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. */ - if (catval_full) - { - char *p; - - catval = jnlib_malloc (strlen (catval_full) + 1); - if (catval) - { - strcpy (catval, catval_full); - p = strchr (catval, '_'); - if (p) - *p = '\0'; - } - } - if (!catval) - return NULL; - - /* 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); - char *p; - - fname = jnlib_malloc (len); - if (!fname) - { - jnlib_free (catval); - return NULL; - } - - p = fname; - strcpy (p, dirname); - p += strlen (dirname); - *(p++) = '\\'; - strcpy (p, catval); - p += strlen (catval); - strcpy (p, "\\LC_MESSAGES\\"); - p += 13; - strcpy (p, domainname); - p += strlen (domainname); - strcpy (p, ".mo"); - } - - domain = load_domain (fname); - jnlib_free (catval); - jnlib_free (fname); - - /* 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; - - /* For historic reasons we are not allowed to return a const char*. */ - return (char*)dirname; -} - - - - -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 overflow_space_s *os; - const char *trans; /* Pointer to the translated entry. */ - size_t translen; /* Length of that entry. */ - - if (want_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 *msgid, const char *msgid2, unsigned long nplural) -{ - struct loaded_domain *domain; - uint32_t top, bottom, nstr; - - if (!(domain = the_domain)) - goto not_found; - - /* First try to use the hash table. */ - if (domain->hash_size > 2 && domain->hash_tab) - { - /* Use the hashing table. */ - 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 - of messages. */ - bottom = 0; - top = domain->nstrings; - while (bottom < top) - { - int cmp_val; - - nstr = (bottom + top) / 2; - cmp_val = strcmp (msgid, (domain->data - + SWAPIT(domain->must_swap, - domain->orig_tab[nstr].offset))); - if (cmp_val < 0) - top = nstr; - else if (cmp_val > 0) - bottom = nstr + 1; - else - return get_string (domain, nstr, !!msgid2, nplural); - } - - not_found: - /* We use the standard Germanic rule if plural has been requested. */ - return msgid2? (nplural == 1? msgid : msgid2) : msgid; -} - - -char * -textdomain (const char *domainname) -{ - /* For now, support only one domain. */ - return (char*)domainname; -} - - -const char * -gettext (const char *msgid) -{ - return do_gettext (msgid, NULL, 0); -} - -char * -dgettext (const char *domainname, const char *msgid) -{ - (void)domainname; - - /* For now, support only one domain. */ - return (char*)do_gettext (msgid, NULL, 0); -} - -const char * -ngettext (const char *msgid1, const char *msgid2, unsigned long int n) -{ - /* We use the simple Germanic plural rule. */ - return do_gettext (msgid1, msgid2, n); -} - - -/* Return the locale name as used by gettext. The return value will - never be NULL. */ -const char * -gettext_localename (void) -{ - const char *s; - - s = my_nl_locale_name ("LC_MESSAGES"); - return s? s:""; -} - -void -gettext_select_utf8 (int value) -{ - want_utf8 = value; -} - - -#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++; - } - - bindtextdomain ("gnupg2", "c:/programme/gnu/gnupg/share/locale"); - - printf ("locale is `%s'\n", gettext_localename ()); - fputs ("text with N=1:\n", stdout); - fputs (ngettext (atext1, atext2, 1), stdout); - fputs ("\n\ntext with N=2:\n", stdout); - fputs (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/jnlib/w32help.h b/jnlib/w32help.h index c503ad28a..518d4251c 100644 --- a/jnlib/w32help.h +++ b/jnlib/w32help.h @@ -27,15 +27,6 @@ char *read_w32_registry_string (const char *root, int write_w32_registry_string (const char *root, const char *dir, const char *name, const char *value); -#ifdef USE_SIMPLE_GETTEXT -char *bindtextdomain (const char *domainname, const char *dirname); -const char *gettext (const char *msgid ); -const char *ngettext (const char *msgid1, const char *msgid2, - unsigned long int n); -const char *gettext_localename (void); -void gettext_select_utf8 (int value); -#endif /*USE_SIMPLE_GETTEXT*/ - #endif /*HAVE_W32_SYSTEM*/ #endif /*LIBJNLIB_MISCHELP_H*/