* 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.
This commit is contained in:
Corinna Vinschen 2009-07-20 15:44:55 +00:00
parent cb8ee36ae8
commit 20fc2f4936
5 changed files with 71 additions and 6 deletions

View File

@ -1,3 +1,19 @@
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.

View File

@ -24,6 +24,7 @@ details. */
#define pwrite __FOO_pwrite
#include "winsup.h"
#include "winnls.h"
#include "miscfuncs.h"
#include <sys/stat.h>
#include <sys/vfs.h> /* needed for statfs */
@ -36,6 +37,7 @@ details. */
#include <sys/uio.h>
#include <ctype.h>
#include <locale.h>
#include <wchar.h>
#include <unistd.h>
#include <sys/wait.h>
#include <rpc.h>
@ -4031,32 +4033,61 @@ unlinkat (int dirfd, const char *pathname, int flags)
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;
}

View File

@ -28,6 +28,11 @@ extern mbtowc_f __ascii_mbtowc;
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 *);

View File

@ -56,6 +56,7 @@ wincaps wincap_unknown __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_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -94,6 +95,7 @@ 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)) = {
@ -132,6 +134,7 @@ 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)) = {
@ -170,6 +173,7 @@ 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)) = {
@ -208,6 +212,7 @@ 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)) = {
@ -246,6 +251,7 @@ 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)) = {
@ -284,6 +290,7 @@ 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)) = {
@ -322,6 +329,7 @@ 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)) = {
@ -360,6 +368,7 @@ 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)) = {
@ -398,6 +407,7 @@ 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)) = {
@ -436,6 +446,7 @@ 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));

View File

@ -48,6 +48,7 @@ struct wincaps
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
@ -102,6 +103,7 @@ public:
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
};