aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran/io')
-rw-r--r--libgfortran/io/read.c13
-rw-r--r--libgfortran/io/transfer128.c4
-rw-r--r--libgfortran/io/write_float.def54
3 files changed, 68 insertions, 3 deletions
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 21e7851..8e9d50d 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -186,7 +186,11 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
#if defined(HAVE_GFC_REAL_16)
# if defined(GFC_REAL_16_IS_FLOAT128)
case 16:
+# if defined(GFC_REAL_16_USE_IEC_60559)
+ *((GFC_REAL_16*) dest) = strtof128 (buffer, &endptr);
+# else
*((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
+# endif
break;
# elif defined(HAVE_STRTOLD)
case 16:
@@ -199,6 +203,8 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
case 17:
# if defined(POWER_IEEE128)
*((GFC_REAL_17*) dest) = __strtoieee128 (buffer, &endptr);
+# elif defined(GFC_REAL_17_USE_IEC_60559)
+ *((GFC_REAL_17*) dest) = strtof128 (buffer, &endptr);
# else
*((GFC_REAL_17*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
# endif
@@ -272,7 +278,14 @@ convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer,
#if defined(HAVE_GFC_REAL_16)
# if defined(GFC_REAL_16_IS_FLOAT128)
case 16:
+# if defined(GFC_REAL_16_USE_IEC_60559)
+ if (is_inf)
+ *((GFC_REAL_16*) dest) = plus ? __builtin_inff128 () : -__builtin_inff128 ();
+ else
+ *((GFC_REAL_16*) dest) = plus ? __builtin_nanf128 ("") : -__builtin_nanf128 ("");
+# else
*((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
+# endif
break;
# else
case 16:
diff --git a/libgfortran/io/transfer128.c b/libgfortran/io/transfer128.c
index 7372ad7..8f30730 100644
--- a/libgfortran/io/transfer128.c
+++ b/libgfortran/io/transfer128.c
@@ -65,7 +65,9 @@ export_proto(transfer_complex128_write);
write_float; the pointer assignment with USED attribute make sure
that there is a non-weakref dependence if the quadmath functions
are used. That avoids segfault when libquadmath is statically linked. */
-# if !defined(HAVE_GFC_REAL_17) || !defined(POWER_IEEE128)
+# if (defined(HAVE_GFC_REAL_17) && !defined(POWER_IEEE128) \
+ && !defined(GFC_REAL_17_USE_IEC_60559)) \
+ || (!defined(HAVE_GFC_REAL_17) && !defined(GFC_REAL_16_USE_IEC_60559))
static void __attribute__((used)) *tmp1 = strtoflt128;
static void __attribute__((used)) *tmp2 = quadmath_snprintf;
# endif
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 1f4be0d..a4d8493 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -837,18 +837,60 @@ snprintf (buffer, size, "%+-#.*e", (prec), (val))
#define DTOA2L(prec,val) \
snprintf (buffer, size, "%+-#.*Le", (prec), (val))
+#if defined(GFC_REAL_16_USE_IEC_60559) || defined(GFC_REAL_17_USE_IEC_60559)
+/* strfromf128 unfortunately doesn't allow +, - and # modifiers
+ nor .* (only allows .number). For +, work around it by adding
+ leading + manually for !signbit values. For - I don't see why
+ we need it, when we don't specify field minimum width.
+ For #, add . if it is missing. Assume size is at least 2. */
+static int
+gfor_strfromf128 (char *buffer, size_t size, int kind, int prec, _Float128 val)
+{
+ int ret, n = 0;
+ char fmt[sizeof (int) * 3 + 5];
+ snprintf (fmt, sizeof fmt, "%%.%d%c", prec, kind);
+ if (!__builtin_signbit (val))
+ {
+ n = 1;
+ buffer[0] = '+';
+ }
+ ret = strfromf128 (buffer + n, size - n, fmt, val) + n;
+ if ((size_t) ret < size - 1)
+ {
+ size_t s = strcspn (buffer, ".e");
+ if (buffer[s] != '.')
+ {
+ if (buffer[s] == '\0')
+ buffer[s + 1] = '\0';
+ else
+ memmove (buffer + s + 1, buffer + s, ret + 1 - s);
+ buffer[s] = '.';
+ ++ret;
+ }
+ }
+ return ret;
+}
+#endif
#if defined(HAVE_GFC_REAL_17)
# if defined(POWER_IEEE128)
# define DTOA2Q(prec,val) \
__snprintfieee128 (buffer, size, "%+-#.*Le", (prec), (val))
+# elif defined(GFC_REAL_17_USE_IEC_60559)
+# define DTOA2Q(prec,val) \
+gfor_strfromf128 (buffer, size, 'e', (prec), (val))
# else
# define DTOA2Q(prec,val) \
quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val))
# endif
#elif defined(GFC_REAL_16_IS_FLOAT128)
-# define DTOA2Q(prec,val) \
+# if defined(GFC_REAL_16_USE_IEC_60559)
+# define DTOA2Q(prec,val) \
+gfor_strfromf128 (buffer, size, 'e', (prec), (val))
+# else
+# define DTOA2Q(prec,val) \
quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val))
+# endif
#endif
#define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val)
@@ -865,13 +907,21 @@ snprintf (buffer, size, "%+-#.*Lf", (prec), (val))
# if defined(POWER_IEEE128)
# define FDTOA2Q(prec,val) \
__snprintfieee128 (buffer, size, "%+-#.*Lf", (prec), (val))
+# elif defined(GFC_REAL_17_USE_IEC_60559)
+# define FDTOA2Q(prec,val) \
+gfor_strfromf128 (buffer, size, 'f', (prec), (val))
# else
# define FDTOA2Q(prec,val) \
quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val))
# endif
#elif defined(GFC_REAL_16_IS_FLOAT128)
-# define FDTOA2Q(prec,val) \
+# if defined(GFC_REAL_16_USE_IEC_60559)
+# define FDTOA2Q(prec,val) \
+gfor_strfromf128 (buffer, size, 'f', (prec), (val))
+# else
+# define FDTOA2Q(prec,val) \
quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val))
+# endif
#endif