aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/transfer.c
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2014-11-10 02:17:16 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2014-11-10 02:17:16 +0200
commit9cbecd06be8bba398595990b0ecb4156d4a19aad (patch)
tree632705719333408c765e7eddf68dc9b1418b8854 /libgfortran/io/transfer.c
parentf8df4b4e2b524b2f35fe93dd935c175c495a7fd0 (diff)
downloadgcc-9cbecd06be8bba398595990b0ecb4156d4a19aad.zip
gcc-9cbecd06be8bba398595990b0ecb4156d4a19aad.tar.gz
gcc-9cbecd06be8bba398595990b0ecb4156d4a19aad.tar.bz2
PR 47007 and 61847 Locale failures in libgfortran.
2014-11-10 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/47007 PR libfortran/61847 * config.h.in: Regenerated. * configure: Regenerated. * configure.ac (AC_CHECK_HEADERS_ONCE): Check for xlocale.h. (AC_CHECK_FUNCS_ONCE): Check for newlocale, freelocale, uselocale, strerror_l. * io/io.h (locale.h): Include. (xlocale.h): Include if present. (c_locale): New variable. (old_locale): New variable. (old_locale_ctr): New variable. (old_locale_lock): New variable. (st_parameter_dt): Add old_locale member. * io/transfer.c (data_transfer_init): Set locale to "C" if doing formatted transfer. (finalize_transfer): Reset locale to previous. * io/unit.c (c_locale): New variable. (old_locale): New variable. (old_locale_ctr): New variable. (old_locale_lock): New variable. (init_units): Init c_locale, init old_locale_lock. (close_units): Free c_locale. * runtime/error.c (locale.h): Include. (xlocale.h): Include if present. (gf_strerror): Use strerror_l if available. Reset locale to LC_GLOBAL_LOCALE for strerror_r branch. 2014-11-10 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/47007 PR libfortran/61847 * gfortran.texi: Add note about locale issues to thread-safety section. From-SVN: r217273
Diffstat (limited to 'libgfortran/io/transfer.c')
-rw-r--r--libgfortran/io/transfer.c55
1 files changed, 43 insertions, 12 deletions
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index dc1b6f4..87b8c05 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2870,13 +2870,27 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
dtp->u.p.current_unit->read_bad = 1;
}
- /* Start the data transfer if we are doing a formatted transfer. */
- if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
- && ((cf & (IOPARM_DT_LIST_FORMAT | IOPARM_DT_HAS_NAMELIST_NAME)) == 0)
- && dtp->u.p.ionml == NULL)
- formatted_transfer (dtp, 0, NULL, 0, 0, 1);
+ if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
+ {
+#ifdef HAVE_USELOCALE
+ dtp->u.p.old_locale = uselocale (c_locale);
+#else
+ __gthread_mutex_lock (&old_locale_lock);
+ if (!old_locale_ctr++)
+ {
+ old_locale = setlocale (LC_NUMERIC, NULL);
+ setlocale (LC_NUMERIC, "C");
+ }
+ __gthread_mutex_unlock (&old_locale_lock);
+#endif
+ /* Start the data transfer if we are doing a formatted transfer. */
+ if ((cf & (IOPARM_DT_LIST_FORMAT | IOPARM_DT_HAS_NAMELIST_NAME)) == 0
+ && dtp->u.p.ionml == NULL)
+ formatted_transfer (dtp, 0, NULL, 0, 0, 1);
+ }
}
+
/* Initialize an array_loop_spec given the array descriptor. The function
returns the index of the last element of the array, and also returns
starting record, where the first I/O goes to (necessary in case of
@@ -3531,14 +3545,14 @@ finalize_transfer (st_parameter_dt *dtp)
if (dtp->u.p.eor_condition)
{
generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return;
+ goto done;
}
if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
{
if (dtp->u.p.current_unit && current_mode (dtp) == UNFORMATTED_SEQUENTIAL)
dtp->u.p.current_unit->current_record = 0;
- return;
+ goto done;
}
if ((dtp->u.p.ionml != NULL)
@@ -3552,12 +3566,12 @@ finalize_transfer (st_parameter_dt *dtp)
dtp->u.p.transfer = NULL;
if (dtp->u.p.current_unit == NULL)
- return;
+ goto done;
if ((cf & IOPARM_DT_LIST_FORMAT) != 0 && dtp->u.p.mode == READING)
{
finish_list_read (dtp);
- return;
+ goto done;
}
if (dtp->u.p.mode == WRITING)
@@ -3570,7 +3584,7 @@ finalize_transfer (st_parameter_dt *dtp)
&& dtp->u.p.advance_status != ADVANCE_NO)
next_record (dtp, 1);
- return;
+ goto done;
}
dtp->u.p.current_unit->current_record = 0;
@@ -3579,7 +3593,7 @@ finalize_transfer (st_parameter_dt *dtp)
{
fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
dtp->u.p.seen_dollar = 0;
- return;
+ goto done;
}
/* For non-advancing I/O, save the current maximum position for use in the
@@ -3591,7 +3605,7 @@ finalize_transfer (st_parameter_dt *dtp)
dtp->u.p.current_unit->saved_pos =
dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
- return;
+ goto done;
}
else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
&& dtp->u.p.mode == WRITING && !is_internal_unit (dtp))
@@ -3600,6 +3614,23 @@ finalize_transfer (st_parameter_dt *dtp)
dtp->u.p.current_unit->saved_pos = 0;
next_record (dtp, 1);
+
+ done:
+#ifdef HAVE_USELOCALE
+ if (dtp->u.p.old_locale != (locale_t) 0)
+ {
+ uselocale (dtp->u.p.old_locale);
+ dtp->u.p.old_locale = (locale_t) 0;
+ }
+#else
+ __gthread_mutex_lock (&old_locale_lock);
+ if (!--old_locale_ctr)
+ {
+ setlocale (LC_NUMERIC, old_locale);
+ old_locale = NULL;
+ }
+ __gthread_mutex_unlock (&old_locale_lock);
+#endif
}
/* Transfer function for IOLENGTH. It doesn't actually do any