summaryrefslogtreecommitdiff
path: root/m4/duplocale.m4
blob: 54349e920abba513b0331285a4d68ea240893fd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# duplocale.m4 serial 18
dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

AC_DEFUN([gl_FUNC_DUPLOCALE],
[
  AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
  AC_REQUIRE([AC_CANONICAL_HOST])
  AC_REQUIRE([gl_FUNC_SETLOCALE_NULL])
  gl_CHECK_FUNCS_ANDROID([duplocale], [[#include <locale.h>]])
  if test $ac_cv_func_duplocale = yes; then
    dnl Check against glibc bug where duplocale crashes.
    dnl See <https://sourceware.org/bugzilla/show_bug.cgi?id=10969>.
    dnl Also, on AIX 7.1, duplocale(LC_GLOBAL_LOCALE) returns (locale_t)0 with
    dnl errno set to EINVAL.
    dnl Also, on NetBSD 7.0, duplocale(LC_GLOBAL_LOCALE) returns a locale that
    dnl corresponds to the C locale.
    AC_REQUIRE([gl_LOCALE_H])
    if test $HAVE_LOCALE_T = 1; then
      AC_CHECK_FUNCS_ONCE([snprintf_l])
      gl_CHECK_FUNCS_ANDROID([nl_langinfo_l], [[#include <langinfo.h>]])
      AC_CACHE_CHECK([whether duplocale(LC_GLOBAL_LOCALE) works],
        [gl_cv_func_duplocale_works],
        [AC_RUN_IFELSE(
           [AC_LANG_SOURCE([[
#include <locale.h>
#if HAVE_XLOCALE_H
# include <xlocale.h>
#endif
#if HAVE_SNPRINTF_L
# include <stdio.h>
#endif
#if HAVE_NL_LANGINFO_L
# include <langinfo.h>
#endif
#include <string.h>
struct locale_dependent_values
{
  char numeric[100];
  char time[100];
};
int main ()
{
  struct locale_dependent_values expected_result;
  struct locale_dependent_values result;
  locale_t loc;
  setlocale (LC_ALL, "en_US.UTF-8");
  setlocale (LC_NUMERIC, "de_DE.UTF-8");
  setlocale (LC_TIME, "fr_FR.UTF-8");
#if HAVE_SNPRINTF_L
  snprintf (expected_result.numeric, sizeof (expected_result.numeric), "%g", 3.5);
#endif
#if HAVE_NL_LANGINFO_L
  strcpy (expected_result.time, nl_langinfo (MON_1));
#endif
  loc = duplocale (LC_GLOBAL_LOCALE);
  if (!loc)
    return 1;
#if HAVE_SNPRINTF_L
  snprintf_l (result.numeric, sizeof (result.numeric), loc, "%g", 3.5);
#endif
#if HAVE_NL_LANGINFO_L
  strcpy (result.time, nl_langinfo_l (MON_1, loc));
#endif
#if HAVE_SNPRINTF_L
  if (strcmp (result.numeric, expected_result.numeric) != 0)
    return 2;
#endif
#if HAVE_NL_LANGINFO_L
  if (strcmp (result.time, expected_result.time) != 0)
    return 3;
#endif
  freelocale (loc);
  return 0;
}]])],
           [gl_cv_func_duplocale_works=yes],
           [gl_cv_func_duplocale_works=no],
           [dnl Guess it works except on glibc < 2.12, uClibc, AIX, and NetBSD.
            case "$host_os" in
              aix* | netbsd*) gl_cv_func_duplocale_works="guessing no";;
              *-gnu* | gnu*)
                AC_EGREP_CPP([Unlucky], [
#include <features.h>
#ifdef __GNU_LIBRARY__
 #if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12)
  Unlucky GNU user
 #endif
#endif
#ifdef __UCLIBC__
 Unlucky user
#endif
                  ],
                  [gl_cv_func_duplocale_works="guessing no"],
                  [gl_cv_func_duplocale_works="guessing yes"])
                ;;
              *) gl_cv_func_duplocale_works="guessing yes";;
            esac
           ])
        ])
      case "$gl_cv_func_duplocale_works" in
        *no) REPLACE_DUPLOCALE=1 ;;
      esac
    else
      dnl In 2019, some versions of z/OS lack the locale_t type and have broken
      dnl newlocale, duplocale, freelocale functions. In this situation, we
      dnl cannot use nor override duplocale.
      HAVE_DUPLOCALE=0
    fi
  else
    HAVE_DUPLOCALE=0
    case "$gl_cv_onwards_func_duplocale" in
      future*) REPLACE_DUPLOCALE=1 ;;
    esac
  fi
  if test $REPLACE_DUPLOCALE = 1; then
    DUPLOCALE_LIB="$SETLOCALE_NULL_LIB"
  else
    DUPLOCALE_LIB=
  fi
  dnl DUPLOCALE_LIB is expected to be '-pthread' or '-lpthread' on AIX
  dnl with gcc or xlc, and empty otherwise.
  AC_SUBST([DUPLOCALE_LIB])
  dnl For backward compatibility.
  LIB_DUPLOCALE="$DUPLOCALE_LIB"
  AC_SUBST([LIB_DUPLOCALE])
])

# Prerequisites of lib/duplocale.c.
AC_DEFUN([gl_PREREQ_DUPLOCALE],
[
  :
])