4
0
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:
Corinna Vinschen 2010-01-24 12:29:49 +00:00
parent 88116ad22e
commit 57c7e05ea7
4 changed files with 121 additions and 139 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}