Improve setlocale() detection in Configure-ish files
authorKarl Williamson <khw@cpan.org>
Sun, 17 Feb 2019 05:12:41 +0000 (22:12 -0700)
committerKarl Williamson <khw@cpan.org>
Mon, 4 Mar 2019 20:01:37 +0000 (13:01 -0700)
This also now notes some behavior of setlocale

16 files changed:
Configure
Cross/config.sh-arm-linux
Cross/config.sh-arm-linux-n770
NetWare/config.wc
Porting/config.sh
config_h.SH
configure.com
metaconfig.h
plan9/config_sh.sample
symbian/config.sh
uconfig.h
uconfig.sh
uconfig64.sh
win32/config.ce
win32/config.gc
win32/config.vc

index 309a334..0c525c2 100755 (executable)
--- 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'
index 2410ca5..13a1427 100644 (file)
@@ -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'
index 6ad6445..d1e1c30 100644 (file)
@@ -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'
index c6b909a..9173c9d 100644 (file)
@@ -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'
index 6d38469..2a0532d 100644 (file)
@@ -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'
index 316c371..f26ed2f 100755 (executable)
@@ -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.
index 0140c5c..1f3e73c 100644 (file)
@@ -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 + "'"
index 8015862..73e0ab0 100644 (file)
@@ -26,4 +26,5 @@
  * I_WCTYPE
  * HAS_TOWLOWER
  * HAS_TOWUPPER
+ * SETLOCALE_ACCEPTS_ANY_LOCALE_NAME
  */
index c709967..78bc1da 100644 (file)
@@ -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'
index 655847a..8b3122b 100644 (file)
@@ -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'
index 9c0085b..92dba87 100644 (file)
--- a/uconfig.h
+++ b/uconfig.h
  */
 /*#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.
  */
 /*#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.
 #endif
 
 /* Generated from:
- * 5ad5aeb4fcee5fe869bed0368fc2430fdf0ad7011927820be7d0e6fa076334c5 config_h.SH
- * 2caca0ed689d83f195e6d1887fcf6a1702cceaa595de14be09580f91d06f5d62 uconfig.sh
+ * 2cc5c49f1266887de8224d2804aae6f80c43da0a62782d74866d5e828194698d config_h.SH
+ * d6d2fc8bf209b3d6db681ac0994a29a281afe35c3a96bb62079cb15b0605d035 uconfig.sh
  * ex: set ro: */
index 3367267..f55def4 100644 (file)
@@ -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'
index b6d3f82..bfc6049 100644 (file)
@@ -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'
index 8bf862a..d8eb67d 100644 (file)
@@ -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'
index d5697e3..66de52d 100644 (file)
@@ -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'
index 676f255..5ece804 100644 (file)
@@ -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'