* cygheap.cc (cygheap_init): Default locale.charset to "UTF-8".

* dcrt0.cc (dll_crt0_1): Call setlocale (LC_CTYPE, "") here, just
	before resetting application locale to "C".
	* environ.cc (environ_init): Drop code setting locale here.
	* syscalls.cc (check_codepage): Break out check for required codepage
	from internal_setlocale.
	(internal_setlocale): Just convert CWD and $PATH from old charset to
	new charset and set internal charset.
	(setlocale): Change accordingly.  Don't require LC_ALL or LC_CTYPE to
	store old locale value.  Always call internal_setlocale if charset
	changed due to locale environment changes.
This commit is contained in:
Corinna Vinschen
2009-09-28 10:43:49 +00:00
parent a58d484bcf
commit d856640e1c
5 changed files with 76 additions and 67 deletions

View File

@@ -4151,69 +4151,79 @@ unlinkat (int dirfd, const char *pathname, int flags)
}
static char *
internal_setlocale (char *ret)
check_codepage (char *ret)
{
tmp_pathbuf tp;
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 = 936;
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;
}
return ret;
}
/* Each setlocale potentially changes the multibyte representation
of the CWD. Therefore we have to reevaluate the CWD's posix path and
store in the new charset. */
static void
internal_setlocale ()
{
/* Each setlocale from the environment potentially changes the
multibyte representation of the CWD. Therefore we have to
reevaluate the CWD's posix path and store in the new charset.
Same for the PATH environment variable. */
/* FIXME: Other buffered paths might be affected as well. */
wchar_t *w_cwd = tp.w_get ();
tmp_pathbuf tp;
wchar_t *w_path, *w_cwd;
debug_printf ("Cygwin charset changed from %s to %s",
cygheap->locale.charset, __locale_charset ());
/* Fetch CWD and PATH and convert to wchar_t in previous charset. */
w_path = tp.w_get ();
sys_mbstowcs (w_path, 32768, getenv ("PATH"));
w_cwd = tp.w_get ();
cwdstuff::cwd_lock.acquire ();
sys_mbstowcs (w_cwd, 32768, cygheap->cwd.get_posix ());
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 = 936;
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;
}
/* Set charset for internal conversion functions. */
cygheap->locale.mbtowc = __mbtowc;
cygheap->locale.wctomb = __wctomb;
strcpy (cygheap->locale.charset, __locale_charset ());
/* See above. */
/* Restore CWD and PATH in new charset. */
cygheap->cwd.reset_posix (w_cwd);
cwdstuff::cwd_lock.release ();
return ret;
char *c_path = tp.c_get ();
sys_wcstombs (c_path, 32768, w_path);
setenv ("PATH", c_path, 1);
}
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 ())
if (locale && !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)
&& !(ret = internal_setlocale (ret)))
_setlocale_r (_REENT, category, old);
if (ret && locale)
{
if (!(ret = check_codepage (ret)))
_setlocale_r (_REENT, category, old);
else if (!*locale && strcmp (cygheap->locale.charset,
__locale_charset ()) != 0)
internal_setlocale ();
}
return ret;
}