1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

ldbl-128ibm-compat: Add strfmon_l with IEEE long double format

Similarly to what has been done for printf-like functions, more
specifically to the internal implementation in __vfprintf_internal, this
patch extends __vstrfmon_l_internal to deal with long double values with
binary128 format (as a third format option and reusing the float128
implementation).

Tested for powerpc64le, powerpc64, x86_64, and with build-many-glibcs.

Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
This commit is contained in:
Rajalakshmi Srinivasaraghavan
2018-06-28 15:17:42 +05:30
committed by Gabriel F. T. Gomes
parent 5d39f37b26
commit 66fa30828a
6 changed files with 113 additions and 4 deletions

View File

@ -15,5 +15,6 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
same format as double, in which case the flag should be set to one, same format as double, in which case the flag should be set to one,
or as another format, otherwise. */ or as another format, otherwise. */
#define STRFMON_LDBL_IS_DBL 0x0001 #define STRFMON_LDBL_IS_DBL 0x0001
#define STRFMON_LDBL_USES_FLOAT128 0x0002
#endif #endif

View File

@ -29,6 +29,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../locale/localeinfo.h" #include "../locale/localeinfo.h"
#include <bits/floatn.h>
#define out_char(Ch) \ #define out_char(Ch) \
@ -96,6 +97,9 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
{ {
double dbl; double dbl;
long double ldbl; long double ldbl;
#if __HAVE_DISTINCT_FLOAT128
_Float128 f128;
#endif
} }
fpnum; fpnum;
int int_format; int int_format;
@ -106,6 +110,7 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
int group; int group;
char pad; char pad;
int is_long_double; int is_long_double;
int is_binary128;
int p_sign_posn; int p_sign_posn;
int n_sign_posn; int n_sign_posn;
int sign_posn; int sign_posn;
@ -150,6 +155,7 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
group = 1; /* Print digits grouped. */ group = 1; /* Print digits grouped. */
pad = ' '; /* Fill character is <SP>. */ pad = ' '; /* Fill character is <SP>. */
is_long_double = 0; /* Double argument by default. */ is_long_double = 0; /* Double argument by default. */
is_binary128 = 0; /* Long double argument by default. */
p_sign_posn = -2; /* This indicates whether the */ p_sign_posn = -2; /* This indicates whether the */
n_sign_posn = -2; /* '(' flag is given. */ n_sign_posn = -2; /* '(' flag is given. */
width = -1; /* No width specified so far. */ width = -1; /* No width specified so far. */
@ -270,6 +276,10 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
++fmt; ++fmt;
if (__glibc_likely ((flags & STRFMON_LDBL_IS_DBL) == 0)) if (__glibc_likely ((flags & STRFMON_LDBL_IS_DBL) == 0))
is_long_double = 1; is_long_double = 1;
#if __HAVE_DISTINCT_FLOAT128
if (__glibc_likely ((flags & STRFMON_LDBL_USES_FLOAT128) != 0))
is_binary128 = is_long_double;
#endif
} }
/* Handle format specifier. */ /* Handle format specifier. */
@ -324,10 +334,22 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
/* Now it's time to get the value. */ /* Now it's time to get the value. */
if (is_long_double == 1) if (is_long_double == 1)
{ {
fpnum.ldbl = va_arg (ap, long double); #if __HAVE_DISTINCT_FLOAT128
is_negative = fpnum.ldbl < 0; if (is_binary128 == 1)
if (is_negative) {
fpnum.ldbl = -fpnum.ldbl; fpnum.f128 = va_arg (ap, _Float128);
is_negative = fpnum.f128 < 0;
if (is_negative)
fpnum.f128 = -fpnum.f128;
}
else
#endif
{
fpnum.ldbl = va_arg (ap, long double);
is_negative = fpnum.ldbl < 0;
if (is_negative)
fpnum.ldbl = -fpnum.ldbl;
}
} }
else else
{ {
@ -517,6 +539,7 @@ __vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
info.width = left_prec + (right_prec ? (right_prec + 1) : 0); info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
info.spec = 'f'; info.spec = 'f';
info.is_long_double = is_long_double; info.is_long_double = is_long_double;
info.is_binary128 = is_binary128;
info.group = group; info.group = group;
info.pad = pad; info.pad = pad;
info.extra = 1; /* This means use values from LC_MONETARY. */ info.extra = 1; /* This means use values from LC_MONETARY. */

View File

@ -214,6 +214,18 @@ CFLAGS-test-syslog-chk-ieee128.c += -mfloat128 -mabi=ieeelongdouble -Wno-psabi
CFLAGS-test-syslog-chk-ibm128.c += -mabi=ibmlongdouble -Wno-psabi CFLAGS-test-syslog-chk-ibm128.c += -mabi=ibmlongdouble -Wno-psabi
endif endif
ifeq ($(subdir),stdlib)
ldbl-extra-routines += strfmon strfmon_l
# Printing long double values with IEEE binary128 format reuses part
# of the internal float128 implementation (__printf_fp, __printf_fphex,
# and __float128 variables and union members). Thus, the compilation of
# the following files, must have -mfloat128 passed to the compiler.
# Also, guarantee that they are compiled in IBM long double mode.
CFLAGS-strfmon.c += -mfloat128 -mabi=ibmlongdouble
CFLAGS-strfmon_l.c += -mfloat128 -mabi=ibmlongdouble
endif
# Add IEEE binary128 files as make targets. # Add IEEE binary128 files as make targets.
routines += $(foreach r,$(ldbl-extra-routines),ieee128-$(r)) routines += $(foreach r,$(ldbl-extra-routines),ieee128-$(r))

View File

@ -205,5 +205,8 @@ libc {
__errorieee128; __errorieee128;
__error_at_lineieee128; __error_at_lineieee128;
__strfmonieee128;
__strfmon_lieee128;
} }
} }

View File

@ -0,0 +1,35 @@
/* Wrapper for strfmon. IEEE128 version.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <monetary.h>
#include <stdarg.h>
#include <locale/localeinfo.h>
ssize_t
___ieee128_strfmon (char *s, size_t maxsize, const char *format, ...)
{
va_list ap;
ssize_t res;
va_start (ap, format);
res = __vstrfmon_l_internal (s, maxsize, _NL_CURRENT_LOCALE,
format, ap, STRFMON_LDBL_USES_FLOAT128);
va_end (ap);
return res;
}
weak_alias (___ieee128_strfmon, __strfmonieee128)

View File

@ -0,0 +1,35 @@
/* Wrapper for strfmon_l. IEEE128 version.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <monetary.h>
#include <stdarg.h>
#include <locale/localeinfo.h>
ssize_t
___ieee128_strfmon_l (char *s, size_t maxsize, locale_t loc, const char *format, ...)
{
va_list ap;
ssize_t res;
va_start (ap, format);
res = __vstrfmon_l_internal (s, maxsize, loc,
format, ap, STRFMON_LDBL_USES_FLOAT128);
va_end (ap);
return res;
}
weak_alias (___ieee128_strfmon_l, __strfmon_lieee128)