* wincap.cc: Implement above element throughout.
* wchar.h (__sjis_mbtowc): Declare.
(__eucjp_mbtowc): Ditto.
(__gbk_mbtowc): Ditto.
(__kr_mbtowc): Ditto.
(__big5_mbtowc): Ditto.
* syscalls.cc (internal_setlocale): Convert to char * function.
Return parameter by default. Return NULL if request to use a
charset can't be satisfied due to missing codepage support in the
underlying OS. Fix comment.
(setlocale): Store original locale. Restore to original locale if
internal_setlocale returns NULL.
+2009-07-20 Corinna Vinschen <corinna@vinschen.de>
+
+ * wincap.h (wincaps::has_always_all_codepages): New element.
+ * wincap.cc: Implement above element throughout.
+ * wchar.h (__sjis_mbtowc): Declare.
+ (__eucjp_mbtowc): Ditto.
+ (__gbk_mbtowc): Ditto.
+ (__kr_mbtowc): Ditto.
+ (__big5_mbtowc): Ditto.
+ * syscalls.cc (internal_setlocale): Convert to char * function.
+ Return parameter by default. Return NULL if request to use a
+ charset can't be satisfied due to missing codepage support in the
+ underlying OS. Fix comment.
+ (setlocale): Store original locale. Restore to original locale if
+ internal_setlocale returns NULL.
+
2009-07-20 Corinna Vinschen <corinna@vinschen.de>
* fork.cc (fork): Create local tmp_pathbuf. Explain why.
#define pwrite __FOO_pwrite
#include "winsup.h"
+#include "winnls.h"
#include "miscfuncs.h"
#include <sys/stat.h>
#include <sys/vfs.h> /* needed for statfs */
#include <sys/uio.h>
#include <ctype.h>
#include <locale.h>
+#include <wchar.h>
#include <unistd.h>
#include <sys/wait.h>
#include <rpc.h>
return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path);
}
-static void
-internal_setlocale ()
+static char *
+internal_setlocale (char *ret)
{
- if (*cygheap->locale.charset == 'A')
+ if (*__locale_charset () == 'A')
{
cygheap->locale.mbtowc = __utf8_mbtowc;
cygheap->locale.wctomb = __utf8_wctomb;
}
else
{
+ if (!wincap.has_always_all_codepages ())
+ {
+ /* Prior to Windows Vista, many codepages are not installed by
+ default, or can be deinstalled. The following codepages require
+ that the respective conversion tables are installed into the OS.
+ So we check if they are installed and if not, setlocale should
+ fail. */
+ CPINFO cpi;
+ UINT cp = 0;
+ if (__mbtowc == __sjis_mbtowc)
+ cp = 932;
+ else if (__mbtowc == __eucjp_mbtowc)
+ cp = 20932;
+ else if (__mbtowc == __gbk_mbtowc)
+ cp = 963;
+ else if (__mbtowc == __kr_mbtowc)
+ cp = 949;
+ else if (__mbtowc == __big5_mbtowc)
+ cp = 950;
+ if (cp && !GetCPInfo (cp, &cpi)
+ && GetLastError () == ERROR_INVALID_PARAMETER)
+ return NULL;
+ }
cygheap->locale.mbtowc = __mbtowc;
cygheap->locale.wctomb = __wctomb;
}
strcpy (cygheap->locale.charset, __locale_charset ());
/* Each setlocale potentially changes the multibyte representation
- of the CWD. Therefore we have to rest the CWD's posix path and
+ of the CWD. Therefore we have to reset the CWD's posix path and
reevaluate the next time it's used. */
/* FIXME: Other buffered paths might be affected as well. */
cygheap->cwd.reset_posix ();
+ return ret;
}
extern "C" char *
setlocale (int category, const char *locale)
{
+ char old[(LC_MESSAGES + 1) * (ENCODING_LEN + 1/*"/"*/ + 1)];
+ if (locale && (category == LC_ALL || category == LC_CTYPE)
+ && !wincap.has_always_all_codepages ())
+ stpcpy (old, _setlocale_r (_REENT, category, NULL));
char *ret = _setlocale_r (_REENT, category, locale);
- if (ret && locale && (category == LC_ALL || category == LC_CTYPE))
- internal_setlocale ();
+ if (ret && locale && (category == LC_ALL || category == LC_CTYPE)
+ && !(ret = internal_setlocale (ret)))
+ _setlocale_r (_REENT, category, old);
return ret;
}
extern mbtowc_f __utf8_mbtowc;
extern mbtowc_f __iso_mbtowc;
extern mbtowc_f __cp_mbtowc;
+extern mbtowc_f __sjis_mbtowc;
+extern mbtowc_f __eucjp_mbtowc;
+extern mbtowc_f __gbk_mbtowc;
+extern mbtowc_f __kr_mbtowc;
+extern mbtowc_f __big5_mbtowc;
typedef int wctomb_f (struct _reent *, char *, wchar_t, const char *,
mbstate_t *);
has_broken_udf:false,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:false,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:false,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:true,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:false,
has_console_handle_problem:false,
has_broken_alloc_console:false,
+ has_always_all_codepages:true,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_udf:false,
has_console_handle_problem:true,
has_broken_alloc_console:true,
+ has_always_all_codepages:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
unsigned has_broken_udf : 1;
unsigned has_console_handle_problem : 1;
unsigned has_broken_alloc_console : 1;
+ unsigned has_always_all_codepages : 1;
};
class wincapc
bool IMPLEMENT (has_broken_udf)
bool IMPLEMENT (has_console_handle_problem)
bool IMPLEMENT (has_broken_alloc_console)
+ bool IMPLEMENT (has_always_all_codepages)
#undef IMPLEMENT
};