From 57c7e05ea70448bbfe5685871bc047494cb60e8a Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sun, 24 Jan 2010 12:29:49 +0000 Subject: * 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. --- winsup/cygwin/ChangeLog | 10 +++++ winsup/cygwin/nlsfuncs.cc | 110 ++++++++++++++++++++++++++++++++++++++++++++- winsup/cygwin/strfuncs.cc | 29 +----------- winsup/cygwin/syscalls.cc | 111 +--------------------------------------------- 4 files changed, 121 insertions(+), 139 deletions(-) (limited to 'winsup/cygwin') diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 68bf818a6..1c948011c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2010-01-24 Corinna Vinschen + + * 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 * strfuncs.cc (__sjis_wctomb): Special handling for characters which diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc index 9467858c5..0cdac6792 100644 --- a/winsup/cygwin/nlsfuncs.cc +++ b/winsup/cygwin/nlsfuncs.cc @@ -9,8 +9,9 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" -#include #include +#include +#include #include #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; +} diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc index 181cdb25b..6d9f4a232 100644 --- a/winsup/cygwin/strfuncs.cc +++ b/winsup/cygwin/strfuncs.cc @@ -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 diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 6adb941ad..d105f4e82 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -24,7 +24,7 @@ details. */ #define pwrite __FOO_pwrite #include "winsup.h" -#include "winnls.h" +#include #include "miscfuncs.h" #include #include /* needed for statfs */ @@ -36,8 +36,6 @@ details. */ #include #include #include -#include -#include #include #include #include @@ -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; -} -- cgit v1.2.3