summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2019-02-16 22:12:41 -0700
committerKarl Williamson <khw@cpan.org>2019-03-04 13:01:37 -0700
commit2e3ef32f4acc106de6ae8170099f09a36d4ef490 (patch)
tree1182ba2bcee9a62e52f350e618dcdf86680da670
parent0806cdda2789ca6394976d1ff3e65dd59bcb8d1b (diff)
downloadperl-2e3ef32f4acc106de6ae8170099f09a36d4ef490.tar.gz
Improve setlocale() detection in Configure-ish files
This also now notes some behavior of setlocale
-rwxr-xr-xConfigure181
-rw-r--r--Cross/config.sh-arm-linux1
-rw-r--r--Cross/config.sh-arm-linux-n7701
-rw-r--r--NetWare/config.wc1
-rw-r--r--Porting/config.sh1
-rwxr-xr-xconfig_h.SH17
-rw-r--r--configure.com2
-rw-r--r--metaconfig.h1
-rw-r--r--plan9/config_sh.sample1
-rw-r--r--symbian/config.sh1
-rw-r--r--uconfig.h21
-rw-r--r--uconfig.sh1
-rw-r--r--uconfig64.sh1
-rw-r--r--win32/config.ce1
-rw-r--r--win32/config.gc1
-rw-r--r--win32/config.vc1
16 files changed, 215 insertions, 18 deletions
diff --git a/Configure b/Configure
index 309a3340b3..0c525c22f2 100755
--- a/Configure
+++ b/Configure
@@ -762,7 +762,9 @@ d_sethostent_r=''
sethostent_r_proto=''
d_setitimer=''
d_setlinebuf=''
+d_has_C_UTF8=''
d_setlocale=''
+d_setlocale_accepts_any_locale_name=''
d_setlocale_r=''
setlocale_r_proto=''
d_setnent=''
@@ -17787,10 +17789,6 @@ eval $inlibc
set setlinebuf d_setlinebuf
eval $inlibc
-: see if setlocale exists
-set setlocale d_setlocale
-eval $inlibc
-
: see if locale.h is available
set locale.h i_locale
eval $inhdr
@@ -17803,6 +17801,179 @@ eval $inhdr
set towupper d_towupper
eval $inlibc
+: check for setlocale function and behavior
+$cat <<EOM
+
+Checking to see if you have setlocale() and its behavior
+EOM
+$cat >try.c <<EOCP
+#$i_stdlib I_STDLIB
+#ifdef I_STDLIB
+# include <stdlib.h>
+#endif
+#include <string.h>
+#$i_locale I_LOCALE
+#ifdef I_LOCALE
+# include <locale.h>
+#endif
+#$i_wctype I_WCTYPE
+#ifdef I_WCTYPE
+# include <wctype.h>
+#endif
+
+int main() {
+ const char * invalid_name = "\a"; /* This is really invalid! */
+ int accepts_any_locale_name = 0;
+ int has_C_UTF8 = 0;
+ unsigned char bad_setlocale = 255;
+
+ /* If LC_CTYPE isn't defined the compilation will fail, and locales will be
+ * disabled. It's hard to imagine an instance where meaningful locale
+ * handling could be done without LC_CTYPE */
+ const char * name = setlocale(LC_CTYPE, "C");
+
+ if (name == NULL || strcmp(name, "C") != 0) {
+ exit(bad_setlocale);
+ }
+
+ name = setlocale(LC_CTYPE, invalid_name);
+ if (name != NULL) {
+
+ /* Let it pass if it accepts the name but gives back one of the C
+ * locales */
+ if (strcmp(name, "C") != 0 && strcmp(name, "C.UTF-8") != 0) {
+ accepts_any_locale_name = 1;
+ }
+ }
+
+ name = setlocale(LC_CTYPE, "C.UTF-8");
+ if (name != NULL) {
+ unsigned char y_with_diaeresis = ('A' == 193) ? 0xDF : 0xFF;
+
+#$d_towupper HAS_TOWUPPER
+#ifdef HAS_TOWUPPER
+
+ /* We assume that if the machine doesn't have the C99 towupper, it
+ * doesn't have C.UTF-8, even if we successfully changed locales to
+ * include it. This seems safer even on platforms that didn't accept
+ * the really invalid name */
+
+ if (towupper(y_with_diaeresis) == 0x178) {
+ has_C_UTF8 = 1;
+ }
+
+#endif
+
+ }
+
+#if 0
+
+ /* Currently unused code to determine if LC_ALL with disparate values uses
+ * category=value pairs or positional, and to determine the separator
+ * between the categories. We could add code so that if the separator were
+ * > '9', we subtract 10; similarly for 'Z' and 'z', and then just about
+ * every possible ASCII separator would fit in the 5 bits available in the
+ * exit code. This would not be true in EBCDIC. And then if LC_ALL is
+ * positional, we probably would want to know the order of the categories.
+ * Using a file between the C program and the shell script would really be
+ * require to do that */
+#ifdef LC_ALL
+
+ unsigned char min_separator = ' ' - 1;
+ unsigned char separator = min_separator;
+ int uses_name_value_pair_names = 0;
+
+ name = setlocale(LC_ALL, "C");
+ if (name == NULL || strcmp(name, "C") != 0) {
+ exit(bad_setlocale);
+ }
+
+ if (has_C_UTF8) {
+ char * pos;
+
+ name = setlocale(LC_CTYPE, "C.UTF-8");
+ if (name == NULL) {
+ exit(bad_setlocale);
+ }
+ name = setlocale(LC_ALL, NULL);
+ if (name == NULL) {
+ exit(bad_setlocale);
+ }
+
+ pos = strstr(name, "LC_CTYPE=C.UTF-8");
+ if (pos != NULL) {
+ uses_name_value_pair_names = 1;
+ if (pos == name) {
+ separator = name[sizeof("LC_CTYPE=C.UTF-8") - 1];
+ }
+ else {
+ separator = *(pos - 1);
+ }
+ }
+ else {
+ pos = strstr(name, "C.UTF-8");
+ if (pos == NULL) {
+ /* bad */
+ }
+ else if (pos == name) {
+ separator = name[sizeof("C.UTF-8") - 1];
+ }
+ else {
+ separator = *(pos - 1);
+ }
+ }
+ }
+
+#endif
+#endif
+
+ exit( 0 /* (separator - min_separator) << 3
+ | uses_name_value_pair_names << 2
+ */
+ | has_C_UTF8 << 1
+ | accepts_any_locale_name);
+
+}
+EOCP
+set try
+if eval $compile; then
+ echo "Your system has setlocale()..." >&4
+ $run ./try
+ case $? in
+ 0) echo "and it seems sane" >&4
+ d_setlocale="$define"
+ d_setlocale_accepts_any_locale_name="$undef"
+ d_has_C_UTF8="false"
+ ;;
+ 1) echo "and it seems sane, but accepts any locale name as valid" >&4
+ d_setlocale="$define"
+ d_setlocale_accepts_any_locale_name="$define"
+ d_has_C_UTF8="false"
+ ;;
+ 2) echo "and it seems sane" >&4
+ d_setlocale="$define"
+ d_setlocale_accepts_any_locale_name="$undef"
+ d_has_C_UTF8="true"
+ ;;
+ 3) echo "and it seems sane, but accepts any locale name as valid" >&4
+ d_setlocale="$define"
+ d_setlocale_accepts_any_locale_name="$define"
+ d_has_C_UTF8="true"
+ ;;
+ *) echo "but it doesn't seem to work, so we won't use it." >&4
+ d_setlocale="$undef"
+ d_setlocale_accepts_any_locale_name="$undef"
+ d_has_C_UTF8="false"
+ ;;
+ esac
+else
+ echo "your system does not have setlocale()" >&4
+ d_setlocale="$undef"
+ d_setlocale_accepts_any_locale_name="$undef"
+ d_has_C_UTF8="false"
+fi
+$rm_try
+
: see if setlocale_r exists
set setlocale_r d_setlocale_r
eval $inlibc
@@ -24055,6 +24226,7 @@ d_gmtime64='$d_gmtime64'
d_gmtime_r='$d_gmtime_r'
d_gnulibc='$d_gnulibc'
d_grpasswd='$d_grpasswd'
+d_has_C_UTF8='$d_has_C_UTF8'
d_hasmntopt='$d_hasmntopt'
d_htonl='$d_htonl'
d_hypot='$d_hypot'
@@ -24242,6 +24414,7 @@ d_sethostent_r='$d_sethostent_r'
d_setitimer='$d_setitimer'
d_setlinebuf='$d_setlinebuf'
d_setlocale='$d_setlocale'
+d_setlocale_accepts_any_locale_name='$d_setlocale_accepts_any_locale_name'
d_setlocale_r='$d_setlocale_r'
d_setnent='$d_setnent'
d_setnetent_r='$d_setnetent_r'
diff --git a/Cross/config.sh-arm-linux b/Cross/config.sh-arm-linux
index 2410ca5836..13a1427381 100644
--- a/Cross/config.sh-arm-linux
+++ b/Cross/config.sh-arm-linux
@@ -492,6 +492,7 @@ d_sethostent_r='undef'
d_setitimer='define'
d_setlinebuf='define'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='define'
d_setnetent_r='undef'
diff --git a/Cross/config.sh-arm-linux-n770 b/Cross/config.sh-arm-linux-n770
index 6ad6445020..d1e1c30070 100644
--- a/Cross/config.sh-arm-linux-n770
+++ b/Cross/config.sh-arm-linux-n770
@@ -491,6 +491,7 @@ d_sethostent_r='undef'
d_setitimer='define'
d_setlinebuf='define'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='define'
d_setnetent_r='undef'
diff --git a/NetWare/config.wc b/NetWare/config.wc
index c6b909aa1d..9173c9de0f 100644
--- a/NetWare/config.wc
+++ b/NetWare/config.wc
@@ -481,6 +481,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/Porting/config.sh b/Porting/config.sh
index 6d38469c32..2a0532df52 100644
--- a/Porting/config.sh
+++ b/Porting/config.sh
@@ -507,6 +507,7 @@ d_sethostent_r='undef'
d_setitimer='define'
d_setlinebuf='define'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='define'
d_setnetent_r='undef'
diff --git a/config_h.SH b/config_h.SH
index 316c3718c2..f26ed2f3bb 100755
--- a/config_h.SH
+++ b/config_h.SH
@@ -439,12 +439,6 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
*/
#$d_setlinebuf HAS_SETLINEBUF /**/
-/* HAS_SETLOCALE:
- * This symbol, if defined, indicates that the setlocale routine is
- * available to handle locale-specific ctype implementations.
- */
-#$d_setlocale HAS_SETLOCALE /**/
-
/* HAS_SETPGID:
* This symbol, if defined, indicates that the setpgid(pid, gpid)
* routine is available to set process group ID.
@@ -3266,6 +3260,17 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
*/
#$d_setitimer HAS_SETITIMER /**/
+/* HAS_SETLOCALE:
+ * This symbol, if defined, indicates that the setlocale routine is
+ * available to handle locale-specific ctype implementations.
+ */
+/* SETLOCALE_ACCEPTS_ANY_LOCALE_NAME:
+ * This symbol, if defined, indicates that the setlocale routine is
+ * available and it accepts any input locale name as valid.
+ */
+#$d_setlocale HAS_SETLOCALE /**/
+#$d_setlocale_accepts_any_locale_name SETLOCALE_ACCEPTS_ANY_LOCALE_NAME /**/
+
/* HAS_SETPROCTITLE:
* This symbol, if defined, indicates that the setproctitle routine is
* available to set process title.
diff --git a/configure.com b/configure.com
index 0140c5cdec..1f3e73c681 100644
--- a/configure.com
+++ b/configure.com
@@ -5438,6 +5438,7 @@ $ d_mbtowc="define"
$ d_mktime="define"
$ d_nl_langinfo="define"
$ d_setlocale="define"
+$ d_setlocale_accepts_any_locale_name="undef"
$ d_stdiobase="define"
$ d_stdio_cnt_lval="define"
$ d_stdio_ptr_lval="define"
@@ -6312,6 +6313,7 @@ $ WC "d_sethent='" + d_sethent + "'"
$ WC "d_setitimer='" + d_setitimer + "'"
$ WC "d_setlinebuf='undef'"
$ WC "d_setlocale='" + d_setlocale + "'"
+$ WC "d_setlocale_accepts_any_locale_name='" + d_setlocale_accepts_any_locale_name + "'"
$ WC "d_setnent='" + d_setnent + "'"
$ WC "d_setpent='" + d_setpent + "'"
$ WC "d_setpgid='" + d_setpgid + "'"
diff --git a/metaconfig.h b/metaconfig.h
index 801586243b..73e0ab0257 100644
--- a/metaconfig.h
+++ b/metaconfig.h
@@ -26,4 +26,5 @@
* I_WCTYPE
* HAS_TOWLOWER
* HAS_TOWUPPER
+ * SETLOCALE_ACCEPTS_ANY_LOCALE_NAME
*/
diff --git a/plan9/config_sh.sample b/plan9/config_sh.sample
index c709967081..78bc1daf03 100644
--- a/plan9/config_sh.sample
+++ b/plan9/config_sh.sample
@@ -492,6 +492,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='define'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/symbian/config.sh b/symbian/config.sh
index 655847a5cf..8b3122b286 100644
--- a/symbian/config.sh
+++ b/symbian/config.sh
@@ -439,6 +439,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='undef'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/uconfig.h b/uconfig.h
index 9c0085be35..92dba8709c 100644
--- a/uconfig.h
+++ b/uconfig.h
@@ -404,12 +404,6 @@
*/
/*#define HAS_SETLINEBUF / **/
-/* HAS_SETLOCALE:
- * This symbol, if defined, indicates that the setlocale routine is
- * available to handle locale-specific ctype implementations.
- */
-/*#define HAS_SETLOCALE / **/
-
/* HAS_SETPGID:
* This symbol, if defined, indicates that the setpgid(pid, gpid)
* routine is available to set process group ID.
@@ -3231,6 +3225,17 @@
*/
/*#define HAS_SETITIMER / **/
+/* HAS_SETLOCALE:
+ * This symbol, if defined, indicates that the setlocale routine is
+ * available to handle locale-specific ctype implementations.
+ */
+/* SETLOCALE_ACCEPTS_ANY_LOCALE_NAME:
+ * This symbol, if defined, indicates that the setlocale routine is
+ * available and it accepts any input locale name as valid.
+ */
+/*#define HAS_SETLOCALE / **/
+/*#define SETLOCALE_ACCEPTS_ANY_LOCALE_NAME / **/
+
/* HAS_SETPROCTITLE:
* This symbol, if defined, indicates that the setproctitle routine is
* available to set process title.
@@ -5236,6 +5241,6 @@
#endif
/* Generated from:
- * 5ad5aeb4fcee5fe869bed0368fc2430fdf0ad7011927820be7d0e6fa076334c5 config_h.SH
- * 2caca0ed689d83f195e6d1887fcf6a1702cceaa595de14be09580f91d06f5d62 uconfig.sh
+ * 2cc5c49f1266887de8224d2804aae6f80c43da0a62782d74866d5e828194698d config_h.SH
+ * d6d2fc8bf209b3d6db681ac0994a29a281afe35c3a96bb62079cb15b0605d035 uconfig.sh
* ex: set ro: */
diff --git a/uconfig.sh b/uconfig.sh
index 3367267a41..f55def4255 100644
--- a/uconfig.sh
+++ b/uconfig.sh
@@ -432,6 +432,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='undef'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/uconfig64.sh b/uconfig64.sh
index b6d3f8230e..bfc6049b74 100644
--- a/uconfig64.sh
+++ b/uconfig64.sh
@@ -432,6 +432,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='undef'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/win32/config.ce b/win32/config.ce
index 8bf862a502..d8eb67d17b 100644
--- a/win32/config.ce
+++ b/win32/config.ce
@@ -479,6 +479,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/win32/config.gc b/win32/config.gc
index d5697e35f4..66de52d7c0 100644
--- a/win32/config.gc
+++ b/win32/config.gc
@@ -480,6 +480,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'
diff --git a/win32/config.vc b/win32/config.vc
index 676f25506e..5ece80459a 100644
--- a/win32/config.vc
+++ b/win32/config.vc
@@ -480,6 +480,7 @@ d_sethostent_r='undef'
d_setitimer='undef'
d_setlinebuf='undef'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='undef'
d_setnetent_r='undef'