aboutsummaryrefslogtreecommitdiff
path: root/stdio-common
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2021-09-23 11:16:02 +0200
committerFlorian Weimer <fweimer@redhat.com>2021-09-23 11:16:02 +0200
commit0a5e270bd16f2df5c72a1524c71b057e774a4942 (patch)
tree178587e017d7c090ade7eb56b8cd797809142422 /stdio-common
parent2849e2f53311b66853cb5159b64cba2bddbfb854 (diff)
downloadglibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.zip
glibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.tar.gz
glibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.tar.bz2
vfprintf: Handle floating-point cases outside of process_arg macro
A lot of the code is unique to the positional and non-positional code. Also unify the decimal and hexadecimal cases via the new helper function __printf_fp_spec.
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/vfprintf-internal.c186
1 files changed, 75 insertions, 111 deletions
diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c
index 3f3d1e1..8e31a96 100644
--- a/stdio-common/vfprintf-internal.c
+++ b/stdio-common/vfprintf-internal.c
@@ -342,6 +342,18 @@ outstring_converted_wide_string (FILE *s, const OTHER_CHAR_T *src, int prec,
return done;
}
+/* Calls __printf_fp or __printf_fphex based on the value of the
+ format specifier INFO->spec. */
+static inline int
+__printf_fp_spec (FILE *fp, const struct printf_info *info,
+ const void *const *args)
+{
+ if (info->spec == 'a' || info->spec == 'A')
+ return __printf_fphex (fp, info, args);
+ else
+ return __printf_fp (fp, info, args);
+}
+
/* For handling long_double and longlong we use the same flag. If
`long' and `long long' are effectively the same type define it to
zero. */
@@ -902,116 +914,6 @@ static const uint8_t jump_table[] =
break; \
} \
\
- LABEL (form_float): \
- { \
- /* Floating-point number. This is handled by printf_fp.c. */ \
- const void *ptr; \
- int function_done; \
- \
- if (fspec == NULL) \
- { \
- if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0)) \
- is_long_double = 0; \
- \
- struct printf_info info = { .prec = prec, \
- .width = width, \
- .spec = spec, \
- .is_long_double = is_long_double, \
- .is_short = is_short, \
- .is_long = is_long, \
- .alt = alt, \
- .space = space, \
- .left = left, \
- .showsign = showsign, \
- .group = group, \
- .pad = pad, \
- .extra = 0, \
- .i18n = use_outdigits, \
- .wide = sizeof (CHAR_T) != 1, \
- .is_binary128 = 0}; \
- \
- PARSE_FLOAT_VA_ARG_EXTENDED (info); \
- ptr = (const void *) &the_arg; \
- \
- function_done = __printf_fp (s, &info, &ptr); \
- } \
- else \
- { \
- ptr = (const void *) &args_value[fspec->data_arg]; \
- if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0)) \
- { \
- fspec->data_arg_type = PA_DOUBLE; \
- fspec->info.is_long_double = 0; \
- } \
- SETUP_FLOAT128_INFO (fspec->info); \
- \
- function_done = __printf_fp (s, &fspec->info, &ptr); \
- } \
- \
- if (function_done < 0) \
- { \
- /* Error in print handler; up to handler to set errno. */ \
- done = -1; \
- goto all_done; \
- } \
- \
- done_add (function_done); \
- } \
- break; \
- \
- LABEL (form_floathex): \
- { \
- /* Floating point number printed as hexadecimal number. */ \
- const void *ptr; \
- int function_done; \
- \
- if (fspec == NULL) \
- { \
- if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0)) \
- is_long_double = 0; \
- \
- struct printf_info info = { .prec = prec, \
- .width = width, \
- .spec = spec, \
- .is_long_double = is_long_double, \
- .is_short = is_short, \
- .is_long = is_long, \
- .alt = alt, \
- .space = space, \
- .left = left, \
- .showsign = showsign, \
- .group = group, \
- .pad = pad, \
- .extra = 0, \
- .wide = sizeof (CHAR_T) != 1, \
- .is_binary128 = 0}; \
- \
- PARSE_FLOAT_VA_ARG_EXTENDED (info); \
- ptr = (const void *) &the_arg; \
- \
- function_done = __printf_fphex (s, &info, &ptr); \
- } \
- else \
- { \
- ptr = (const void *) &args_value[fspec->data_arg]; \
- if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0)) \
- fspec->info.is_long_double = 0; \
- SETUP_FLOAT128_INFO (fspec->info); \
- \
- function_done = __printf_fphex (s, &fspec->info, &ptr); \
- } \
- \
- if (function_done < 0) \
- { \
- /* Error in print handler; up to handler to set errno. */ \
- done = -1; \
- goto all_done; \
- } \
- \
- done_add (function_done); \
- } \
- break; \
- \
LABEL (form_pointer): \
/* Generic pointer. */ \
{ \
@@ -1646,6 +1548,45 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
process_arg (((struct printf_spec *) NULL));
process_string_arg (((struct printf_spec *) NULL));
+ LABEL (form_float):
+ LABEL (form_floathex):
+ {
+ if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))
+ is_long_double = 0;
+
+ struct printf_info info =
+ {
+ .prec = prec,
+ .width = width,
+ .spec = spec,
+ .is_long_double = is_long_double,
+ .is_short = is_short,
+ .is_long = is_long,
+ .alt = alt,
+ .space = space,
+ .left = left,
+ .showsign = showsign,
+ .group = group,
+ .pad = pad,
+ .extra = 0,
+ .i18n = use_outdigits,
+ .wide = sizeof (CHAR_T) != 1,
+ .is_binary128 = 0
+ };
+
+ PARSE_FLOAT_VA_ARG_EXTENDED (info);
+ const void *ptr = &the_arg;
+
+ int function_done = __printf_fp_spec (s, &info, &ptr);
+ if (function_done < 0)
+ {
+ done = -1;
+ goto all_done;
+ }
+ done_add (function_done);
+ }
+ break;
+
LABEL (form_unknown):
if (spec == L_('\0'))
{
@@ -1901,7 +1842,6 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
unsigned long int word;
} number;
int base;
- union printf_arg the_arg;
CHAR_T *string; /* Pointer to argument string. */
/* Fill variables from values in struct. */
@@ -1996,6 +1936,30 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
process_arg ((&specs[nspecs_done]));
process_string_arg ((&specs[nspecs_done]));
+ LABEL (form_float):
+ LABEL (form_floathex):
+ {
+ const void *ptr
+ = (const void *) &args_value[specs[nspecs_done].data_arg];
+ if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))
+ {
+ specs[nspecs_done].data_arg_type = PA_DOUBLE;
+ specs[nspecs_done].info.is_long_double = 0;
+ }
+ SETUP_FLOAT128_INFO (specs[nspecs_done].info);
+
+ int function_done
+ = __printf_fp_spec (s, &specs[nspecs_done].info, &ptr);
+ if (function_done < 0)
+ {
+ /* Error in print handler; up to handler to set errno. */
+ done = -1;
+ goto all_done;
+ }
+ done_add (function_done);
+ }
+ break;
+
LABEL (form_unknown):
{
unsigned int i;