While we have `configure' checks for the individual POSIX 2008 extended
locale functions we refer to and use to guard the respective call sites,
we only verify the presence of `newlocale' for our global feature enable
check. Consequently compilation fails for targets like NetBSD that only
have partial support for POSIX 2008 locale features and in particular
lack the `uselocale' function:
.../libgfortran/io/transfer.c: In function 'data_transfer_init_worker':
.../libgfortran/io/transfer.c:3416:30: error:
'old_locale_lock' undeclared (first use in this function)
3416 | __gthread_mutex_lock (&old_locale_lock);
| ^~~~~~~~~~~~~~~
.../libgfortran/io/transfer.c:3416:30: note: each undeclared identifier is reported only once for each function it appears in
.../libgfortran/io/transfer.c:3417:12: error:
'old_locale_ctr' undeclared (first use in this function)
3417 | if (!old_locale_ctr++)
| ^~~~~~~~~~~~~~
.../libgfortran/io/transfer.c:3419:11: error:
'old_locale' undeclared (first use in this function); did you mean 'c_locale'?
3419 | old_locale = setlocale (LC_NUMERIC, NULL);
| ^~~~~~~~~~
| c_locale
.../libgfortran/io/transfer.c: In function 'finalize_transfer':
.../libgfortran/io/transfer.c:4253:26: error:
'old_locale_lock' undeclared (first use in this function)
4253 | __gthread_mutex_lock (&old_locale_lock);
| ^~~~~~~~~~~~~~~
.../libgfortran/io/transfer.c:4254:10: error:
'old_locale_ctr' undeclared (first use in this function)
4254 | if (!--old_locale_ctr)
| ^~~~~~~~~~~~~~
.../libgfortran/io/transfer.c:4256:30: error:
'old_locale' undeclared (first use in this function); did you mean 'c_locale'?
4256 | setlocale (LC_NUMERIC, old_locale);
| ^~~~~~~~~~
| c_locale
make[3]: *** [Makefile:6221: transfer.lo] Error 1
Only enable the use of POSIX 2008 extended locale features then when all
the three functions required are present, removing said build errors.
libgfortran/
* io/io.h [HAVE_NEWLOCALE]: Also check for HAVE_FREELOCALE and
HAVE_USELOCALE.
[HAVE_FREELOCALE && HAVE_NEWLOCALE && HAVE_USELOCALE]
(HAVE_POSIX_2008_LOCALE): New macro.
(st_parameter_dt) [HAVE_NEWLOCALE]: Check for
HAVE_POSIX_2008_LOCALE instead.
* io/transfer.c (data_transfer_init_worker, finalize_transfer)
[HAVE_USELOCALE]: Check for HAVE_POSIX_2008_LOCALE instead.
* io/unit.c [HAVE_NEWLOCALE]: Likewise.
(init_units) [HAVE_NEWLOCALE]: Likewise.
(close_units) [HAVE_FREELOCALE]: Likewise.
* runtime/error.c (gf_strerror) [HAVE_USELOCALE]: Likewise.
typedef struct fnode fnode;
struct gfc_unit;
typedef struct fnode fnode;
struct gfc_unit;
-#ifdef HAVE_NEWLOCALE
-/* We have POSIX 2008 extended locale stuff. */
+#if defined (HAVE_FREELOCALE) && defined (HAVE_NEWLOCALE) \
+ && defined (HAVE_USELOCALE)
+/* We have POSIX 2008 extended locale stuff. We only choose to use it
+ if all the functions required are present as some systems, e.g. NetBSD
+ do not have `uselocale'. */
+#define HAVE_POSIX_2008_LOCALE
extern locale_t c_locale;
internal_proto(c_locale);
#else
extern locale_t c_locale;
internal_proto(c_locale);
#else
char *line_buffer;
struct format_data *fmt;
namelist_info *ionml;
char *line_buffer;
struct format_data *fmt;
namelist_info *ionml;
+#ifdef HAVE_POSIX_2008_LOCALE
locale_t old_locale;
#endif
/* Current position within the look-ahead line buffer. */
locale_t old_locale;
#endif
/* Current position within the look-ahead line buffer. */
if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
{
if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
{
+#ifdef HAVE_POSIX_2008_LOCALE
dtp->u.p.old_locale = uselocale (c_locale);
#else
__gthread_mutex_lock (&old_locale_lock);
dtp->u.p.old_locale = uselocale (c_locale);
#else
__gthread_mutex_lock (&old_locale_lock);
+#ifdef HAVE_POSIX_2008_LOCALE
if (dtp->u.p.old_locale != (locale_t) 0)
{
uselocale (dtp->u.p.old_locale);
if (dtp->u.p.old_locale != (locale_t) 0)
{
uselocale (dtp->u.p.old_locale);
static char stderr_name[] = "stderr";
static char stderr_name[] = "stderr";
+#ifdef HAVE_POSIX_2008_LOCALE
locale_t c_locale;
#else
/* If we don't have POSIX 2008 per-thread locales, we need to use the
locale_t c_locale;
#else
/* If we don't have POSIX 2008 per-thread locales, we need to use the
+#ifdef HAVE_POSIX_2008_LOCALE
c_locale = newlocale (0, "C", 0);
#else
#ifndef __GTHREAD_MUTEX_INIT
c_locale = newlocale (0, "C", 0);
#else
#ifndef __GTHREAD_MUTEX_INIT
+#ifdef HAVE_POSIX_2008_LOCALE
freelocale (c_locale);
#endif
}
freelocale (c_locale);
#endif
}
p = strerror (errnum);
return p;
#elif defined(HAVE_STRERROR_R)
p = strerror (errnum);
return p;
#elif defined(HAVE_STRERROR_R)
+#ifdef HAVE_POSIX_2008_LOCALE
/* Some targets (Darwin at least) have the POSIX 2008 extended
locale functions, but not strerror_l. So reset the per-thread
locale here. */
/* Some targets (Darwin at least) have the POSIX 2008 extended
locale functions, but not strerror_l. So reset the per-thread
locale here. */