about summary refs log tree commit diff
path: root/stdio-common/vfprintf-internal.c
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/vfprintf-internal.c
parent2849e2f53311b66853cb5159b64cba2bddbfb854 (diff)
downloadglibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.tar.gz
glibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.tar.xz
glibc-0a5e270bd16f2df5c72a1524c71b057e774a4942.zip
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/vfprintf-internal.c')
-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 3f3d1e148a..8e31a964d1 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;