mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-18 12:29:32 +08:00
* nlsfuncs.cc (check_codepage): Move from syscalls.cc here.
(internal_setlocale): Ditto. (initial_setlocale): Ditto. (setlocale): Ditto. * strfuncs.cc (__sjis_wctomb): Revert previous patch. (__sjis_mbtowc): Ditto. * syscalls.cc: Move setlocale-related functions to nlsfuncs.cc.
This commit is contained in:
parent
88116ad22e
commit
57c7e05ea7
@ -1,3 +1,13 @@
|
||||
2010-01-24 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* nlsfuncs.cc (check_codepage): Move from syscalls.cc here.
|
||||
(internal_setlocale): Ditto.
|
||||
(initial_setlocale): Ditto.
|
||||
(setlocale): Ditto.
|
||||
* strfuncs.cc (__sjis_wctomb): Revert previous patch.
|
||||
(__sjis_mbtowc): Ditto.
|
||||
* syscalls.cc: Move setlocale-related functions to nlsfuncs.cc.
|
||||
|
||||
2010-01-23 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* strfuncs.cc (__sjis_wctomb): Special handling for characters which
|
||||
|
@ -9,8 +9,9 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <stdlib.h>
|
||||
#include <winnls.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
#include "path.h"
|
||||
#include "fhandler.h"
|
||||
@ -762,3 +763,110 @@ __set_charset_from_locale (const char *locale, char *charset)
|
||||
strcpy (charset, "ISO-8859-15");
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
check_codepage (char *ret)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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. */
|
||||
/* FIXME: It could be necessary to convert the entire environment,
|
||||
not just PATH. */
|
||||
tmp_pathbuf tp;
|
||||
char *path = getenv ("PATH");
|
||||
wchar_t *w_path = NULL, *w_cwd;
|
||||
|
||||
debug_printf ("Cygwin charset changed from %s to %s",
|
||||
cygheap->locale.charset, __locale_charset ());
|
||||
/* Fetch PATH and CWD and convert to wchar_t in previous charset. */
|
||||
if (path && *path) /* $PATH can be potentially unset. */
|
||||
{
|
||||
w_path = tp.w_get ();
|
||||
sys_mbstowcs (w_path, 32768, path);
|
||||
}
|
||||
w_cwd = tp.w_get ();
|
||||
cwdstuff::cwd_lock.acquire ();
|
||||
sys_mbstowcs (w_cwd, 32768, cygheap->cwd.get_posix ());
|
||||
/* Set charset for internal conversion functions. */
|
||||
if (*__locale_charset () == 'A'/*SCII*/)
|
||||
{
|
||||
cygheap->locale.mbtowc = __utf8_mbtowc;
|
||||
cygheap->locale.wctomb = __utf8_wctomb;
|
||||
}
|
||||
else
|
||||
{
|
||||
cygheap->locale.mbtowc = __mbtowc;
|
||||
cygheap->locale.wctomb = __wctomb;
|
||||
}
|
||||
strcpy (cygheap->locale.charset, __locale_charset ());
|
||||
/* Restore CWD and PATH in new charset. */
|
||||
cygheap->cwd.reset_posix (w_cwd);
|
||||
cwdstuff::cwd_lock.release ();
|
||||
if (w_path)
|
||||
{
|
||||
char *c_path = tp.c_get ();
|
||||
sys_wcstombs (c_path, 32768, w_path);
|
||||
setenv ("PATH", c_path, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from dll_crt0_1, before fetching the command line from Windows.
|
||||
Set the internal charset according to the environment locale settings.
|
||||
Check if a required codepage is available, and only switch internal
|
||||
charset if so.
|
||||
Make sure to reset the application locale to "C" per POSIX. */
|
||||
void
|
||||
initial_setlocale ()
|
||||
{
|
||||
char *ret = _setlocale_r (_REENT, LC_CTYPE, "");
|
||||
if (ret && check_codepage (ret)
|
||||
&& strcmp (cygheap->locale.charset, __locale_charset ()) != 0)
|
||||
internal_setlocale ();
|
||||
}
|
||||
|
||||
/* Like newlib's setlocale, but additionally check if the charset needs
|
||||
OS support and the required codepage is actually installed. If codepage
|
||||
is not available, revert to previous locale and return NULL. For details
|
||||
about codepage availability, see the comment in check_codepage() above. */
|
||||
extern "C" char *
|
||||
setlocale (int category, const char *locale)
|
||||
{
|
||||
char old[(LC_MESSAGES + 1) * (ENCODING_LEN + 1/*"/"*/ + 1)];
|
||||
if (locale && !wincap.has_always_all_codepages ())
|
||||
stpcpy (old, _setlocale_r (_REENT, category, NULL));
|
||||
char *ret = _setlocale_r (_REENT, category, locale);
|
||||
if (ret && locale && !(ret = check_codepage (ret)))
|
||||
_setlocale_r (_REENT, category, old);
|
||||
return ret;
|
||||
}
|
||||
|
@ -108,23 +108,6 @@ extern "C" int
|
||||
__sjis_wctomb (struct _reent *r, char *s, wchar_t wchar, const char *charset,
|
||||
mbstate_t *state)
|
||||
{
|
||||
if (*charset == 'S')
|
||||
{
|
||||
/* SJIS is not exactly CP932. Two ASCII code points are converted
|
||||
differently. */
|
||||
if (wchar == L'\x00a5') /* SJIS has Yen sign in place of Backslash */
|
||||
{
|
||||
if (s)
|
||||
*s = '\x5c';
|
||||
return 1;
|
||||
}
|
||||
else if (wchar == L'\x203e') /* SJIS has Overline in place of Tilde */
|
||||
{
|
||||
if (s)
|
||||
*s = '\x7e';
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return __db_wctomb (r,s, wchar, 932);
|
||||
}
|
||||
|
||||
@ -252,17 +235,7 @@ extern "C" int
|
||||
__sjis_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n,
|
||||
const char *charset, mbstate_t *state)
|
||||
{
|
||||
int ret = __db_mbtowc (r, pwc, s, n, 932, state);
|
||||
if (*charset == 'S' && pwc && ret == 1)
|
||||
{
|
||||
/* CP932 is not exactly SJIS. Two ASCII code points are converted
|
||||
differently. */
|
||||
if (*s == '\x5c') /* SJIS has Yen sign in place of Backslash */
|
||||
*pwc = L'\x00a5';
|
||||
else if (*s == '\x7e') /* SJIS has Overline in place of Tilde */
|
||||
*pwc = L'\x203e';
|
||||
}
|
||||
return ret;
|
||||
return __db_mbtowc (r, pwc, s, n, 932, state);
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
|
@ -24,7 +24,7 @@ details. */
|
||||
#define pwrite __FOO_pwrite
|
||||
|
||||
#include "winsup.h"
|
||||
#include "winnls.h"
|
||||
#include <winnls.h>
|
||||
#include "miscfuncs.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vfs.h> /* needed for statfs */
|
||||
@ -36,8 +36,6 @@ details. */
|
||||
#include <utmpx.h>
|
||||
#include <sys/uio.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <rpc.h>
|
||||
@ -4292,110 +4290,3 @@ unlinkat (int dirfd, const char *pathname, int flags)
|
||||
return -1;
|
||||
return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path);
|
||||
}
|
||||
|
||||
static char *
|
||||
check_codepage (char *ret)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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. */
|
||||
/* FIXME: It could be necessary to convert the entire environment,
|
||||
not just PATH. */
|
||||
tmp_pathbuf tp;
|
||||
char *path = getenv ("PATH");
|
||||
wchar_t *w_path = NULL, *w_cwd;
|
||||
|
||||
debug_printf ("Cygwin charset changed from %s to %s",
|
||||
cygheap->locale.charset, __locale_charset ());
|
||||
/* Fetch PATH and CWD and convert to wchar_t in previous charset. */
|
||||
if (path && *path) /* $PATH can be potentially unset. */
|
||||
{
|
||||
w_path = tp.w_get ();
|
||||
sys_mbstowcs (w_path, 32768, path);
|
||||
}
|
||||
w_cwd = tp.w_get ();
|
||||
cwdstuff::cwd_lock.acquire ();
|
||||
sys_mbstowcs (w_cwd, 32768, cygheap->cwd.get_posix ());
|
||||
/* Set charset for internal conversion functions. */
|
||||
if (*__locale_charset () == 'A'/*SCII*/)
|
||||
{
|
||||
cygheap->locale.mbtowc = __utf8_mbtowc;
|
||||
cygheap->locale.wctomb = __utf8_wctomb;
|
||||
}
|
||||
else
|
||||
{
|
||||
cygheap->locale.mbtowc = __mbtowc;
|
||||
cygheap->locale.wctomb = __wctomb;
|
||||
}
|
||||
strcpy (cygheap->locale.charset, __locale_charset ());
|
||||
/* Restore CWD and PATH in new charset. */
|
||||
cygheap->cwd.reset_posix (w_cwd);
|
||||
cwdstuff::cwd_lock.release ();
|
||||
if (w_path)
|
||||
{
|
||||
char *c_path = tp.c_get ();
|
||||
sys_wcstombs (c_path, 32768, w_path);
|
||||
setenv ("PATH", c_path, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from dll_crt0_1, before fetching the command line from Windows.
|
||||
Set the internal charset according to the environment locale settings.
|
||||
Check if a required codepage is available, and only switch internal
|
||||
charset if so.
|
||||
Make sure to reset the application locale to "C" per POSIX. */
|
||||
void
|
||||
initial_setlocale ()
|
||||
{
|
||||
char *ret = _setlocale_r (_REENT, LC_CTYPE, "");
|
||||
if (ret && check_codepage (ret)
|
||||
&& strcmp (cygheap->locale.charset, __locale_charset ()) != 0)
|
||||
internal_setlocale ();
|
||||
}
|
||||
|
||||
/* Like newlib's setlocale, but additionally check if the charset needs
|
||||
OS support and the required codepage is actually installed. If codepage
|
||||
is not available, revert to previous locale and return NULL. For details
|
||||
about codepage availability, see the comment in check_codepage() above. */
|
||||
extern "C" char *
|
||||
setlocale (int category, const char *locale)
|
||||
{
|
||||
char old[(LC_MESSAGES + 1) * (ENCODING_LEN + 1/*"/"*/ + 1)];
|
||||
if (locale && !wincap.has_always_all_codepages ())
|
||||
stpcpy (old, _setlocale_r (_REENT, category, NULL));
|
||||
char *ret = _setlocale_r (_REENT, category, locale);
|
||||
if (ret && locale && !(ret = check_codepage (ret)))
|
||||
_setlocale_r (_REENT, category, old);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user