summary refs log tree commit diff
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:19:20 +0200
commit475b0b92e079c67ea8a25ec05fe0b17fdd935e12 (patch)
tree9b72489f5b138165d704fc4bbbf2e432fbe084bc /stdio-common
parent0a5e270bd16f2df5c72a1524c71b057e774a4942 (diff)
downloadglibc-475b0b92e079c67ea8a25ec05fe0b17fdd935e12.tar.gz
glibc-475b0b92e079c67ea8a25ec05fe0b17fdd935e12.tar.xz
glibc-475b0b92e079c67ea8a25ec05fe0b17fdd935e12.zip
vfprintf: Unify argument handling in process_arg
Instead of checking a pointer argument for NULL, use helper macros
defined differently in the non-positional and positional cases.
This avoids frequent conditional checks and a GCC 12 warning
about comparing pointers against NULL which cannot be NULL.
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/vfprintf-internal.c206
1 files changed, 89 insertions, 117 deletions
diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c
index 8e31a964d1..415f038141 100644
--- a/stdio-common/vfprintf-internal.c
+++ b/stdio-common/vfprintf-internal.c
@@ -650,8 +650,9 @@ static const uint8_t jump_table[] =
       REF (form_unknown)        /* for 'I' */				      \
     }
 
-
-#define process_arg(fspec)						      \
+/* Before invoking this macro, process_arg_int etc. macros have to be
+   defined to extract one argument of the appropriate type.  */
+#define process_arg()						              \
       /* Start real work.  We know about all flags and modifiers and	      \
 	 now process the wanted format specifier.  */			      \
     LABEL (form_percent):						      \
@@ -665,13 +666,7 @@ static const uint8_t jump_table[] =
 									      \
       if (is_longlong)							      \
 	{								      \
-	  long long int signed_number;					      \
-									      \
-	  if (fspec == NULL)						      \
-	    signed_number = va_arg (ap, long long int);			      \
-	  else								      \
-	    signed_number = args_value[fspec->data_arg].pa_long_long_int;     \
-									      \
+	  long long int signed_number = process_arg_long_long_int ();	      \
 	  is_negative = signed_number < 0;				      \
 	  number.longlong = is_negative ? (- signed_number) : signed_number;  \
 									      \
@@ -680,29 +675,14 @@ static const uint8_t jump_table[] =
       else								      \
 	{								      \
 	  long int signed_number;					      \
-									      \
-	  if (fspec == NULL)						      \
-	    {								      \
-	      if (is_long_num)						      \
-		signed_number = va_arg (ap, long int);			      \
-	      else if (is_char)						      \
-		signed_number = (signed char) va_arg (ap, unsigned int);      \
-	      else if (!is_short)					      \
-		signed_number = va_arg (ap, int);			      \
-	      else							      \
-		signed_number = (short int) va_arg (ap, unsigned int);	      \
-	    }								      \
+	  if (is_long_num)						      \
+	    signed_number = process_arg_long_int ();			      \
+	  else if (is_char)						      \
+	    signed_number = (signed char) process_arg_unsigned_int ();	      \
+	  else if (!is_short)						      \
+	    signed_number = process_arg_int ();				      \
 	  else								      \
-	    if (is_long_num)						      \
-	      signed_number = args_value[fspec->data_arg].pa_long_int;	      \
-	    else if (is_char)						      \
-	      signed_number = (signed char)				      \
-		args_value[fspec->data_arg].pa_u_int;			      \
-	    else if (!is_short)						      \
-	      signed_number = args_value[fspec->data_arg].pa_int;	      \
-	    else							      \
-	      signed_number = (short int)				      \
-		args_value[fspec->data_arg].pa_u_int;			      \
+	    signed_number = (short int) process_arg_unsigned_int ();	      \
 									      \
 	  is_negative = signed_number < 0;				      \
 	  number.word = is_negative ? (- signed_number) : signed_number;      \
@@ -737,10 +717,7 @@ static const uint8_t jump_table[] =
 									      \
       if (is_longlong)							      \
 	{								      \
-	  if (fspec == NULL)						      \
-	    number.longlong = va_arg (ap, unsigned long long int);	      \
-	  else								      \
-	    number.longlong = args_value[fspec->data_arg].pa_u_long_long_int; \
+	  number.longlong = process_arg_unsigned_long_long_int ();	      \
 									      \
 	LABEL (longlong_number):					      \
 	  if (prec < 0)							      \
@@ -776,28 +753,14 @@ static const uint8_t jump_table[] =
 	}								      \
       else								      \
 	{								      \
-	  if (fspec == NULL)						      \
-	    {								      \
-	      if (is_long_num)						      \
-		number.word = va_arg (ap, unsigned long int);		      \
-	      else if (is_char)						      \
-		number.word = (unsigned char) va_arg (ap, unsigned int);      \
-	      else if (!is_short)					      \
-		number.word = va_arg (ap, unsigned int);		      \
-	      else							      \
-		number.word = (unsigned short int) va_arg (ap, unsigned int); \
-	    }								      \
+	  if (is_long_num)						      \
+	    number.word = process_arg_unsigned_long_int ();		      \
+	  else if (is_char)						      \
+	    number.word = (unsigned char) process_arg_unsigned_int ();	      \
+	  else if (!is_short)						      \
+	    number.word = process_arg_unsigned_int ();			      \
 	  else								      \
-	    if (is_long_num)						      \
-	      number.word = args_value[fspec->data_arg].pa_u_long_int;	      \
-	    else if (is_char)						      \
-	      number.word = (unsigned char)				      \
-		args_value[fspec->data_arg].pa_u_int;			      \
-	    else if (!is_short)						      \
-	      number.word = args_value[fspec->data_arg].pa_u_int;	      \
-	    else							      \
-	      number.word = (unsigned short int)			      \
-		args_value[fspec->data_arg].pa_u_int;			      \
+	    number.word = (unsigned short int) process_arg_unsigned_int ();   \
 									      \
 	LABEL (number):							      \
 	  if (prec < 0)							      \
@@ -917,11 +880,7 @@ static const uint8_t jump_table[] =
     LABEL (form_pointer):						      \
       /* Generic pointer.  */						      \
       {									      \
-	const void *ptr;						      \
-	if (fspec == NULL)						      \
-	  ptr = va_arg (ap, void *);					      \
-	else								      \
-	  ptr = args_value[fspec->data_arg].pa_pointer;			      \
+	const void *ptr = process_arg_pointer ();			      \
 	if (ptr != NULL)						      \
 	  {								      \
 	    /* If the pointer is not NULL, write it as a %#x spec.  */	      \
@@ -962,30 +921,17 @@ static const uint8_t jump_table[] =
 	    __libc_fatal ("*** %n in writable segment detected ***\n");	      \
 	}								      \
       /* Answer the count of characters written.  */			      \
-      if (fspec == NULL)						      \
-	{								      \
-	  if (is_longlong)						      \
-	    *(long long int *) va_arg (ap, void *) = done;		      \
-	  else if (is_long_num)						      \
-	    *(long int *) va_arg (ap, void *) = done;			      \
-	  else if (is_char)						      \
-	    *(char *) va_arg (ap, void *) = done;			      \
-	  else if (!is_short)						      \
-	    *(int *) va_arg (ap, void *) = done;			      \
-	  else								      \
-	    *(short int *) va_arg (ap, void *) = done;			      \
-	}								      \
+      void *ptrptr = process_arg_pointer ();				      \
+      if (is_longlong)							      \
+	*(long long int *) ptrptr = done;				      \
+      else if (is_long_num)						      \
+	*(long int *) ptrptr = done;					      \
+      else if (is_char)							      \
+	*(char *) ptrptr = done;					      \
+      else if (!is_short)						      \
+	*(int *) ptrptr = done;						      \
       else								      \
-	if (is_longlong)						      \
-	  *(long long int *) args_value[fspec->data_arg].pa_pointer = done;   \
-	else if (is_long_num)						      \
-	  *(long int *) args_value[fspec->data_arg].pa_pointer = done;	      \
-	else if (is_char)						      \
-	  *(char *) args_value[fspec->data_arg].pa_pointer = done;	      \
-	else if (!is_short)						      \
-	  *(int *) args_value[fspec->data_arg].pa_pointer = done;	      \
-	else								      \
-	  *(short int *) args_value[fspec->data_arg].pa_pointer = done;	      \
+	*(short int *) ptrptr = done;					      \
       break;								      \
 									      \
     LABEL (form_strerror):						      \
@@ -997,7 +943,7 @@ static const uint8_t jump_table[] =
       goto LABEL (print_string)
 
 #ifdef COMPILE_WPRINTF
-# define process_string_arg(fspec) \
+# define process_string_arg()						      \
     LABEL (form_character):						      \
       /* Character.  */							      \
       if (is_long)							      \
@@ -1005,11 +951,7 @@ static const uint8_t jump_table[] =
       --width;	/* Account for the character itself.  */		      \
       if (!left)							      \
 	PAD (L' ');							      \
-      if (fspec == NULL)						      \
-	outchar (__btowc ((unsigned char) va_arg (ap, int))); /* Promoted. */ \
-      else								      \
-	outchar (__btowc ((unsigned char)				      \
-			  args_value[fspec->data_arg].pa_int));		      \
+      outchar (__btowc ((unsigned char) process_arg_int ())); /* Promoted. */ \
       if (left)								      \
 	PAD (L' ');							      \
       break;								      \
@@ -1020,10 +962,7 @@ static const uint8_t jump_table[] =
 	--width;							      \
 	if (!left)							      \
 	  PAD (L' ');							      \
-	if (fspec == NULL)						      \
-	  outchar (va_arg (ap, wchar_t));				      \
-	else								      \
-	  outchar (args_value[fspec->data_arg].pa_wchar);		      \
+	outchar (process_arg_wchar_t ());				      \
 	if (left)							      \
 	  PAD (L' ');							      \
       }									      \
@@ -1035,10 +974,7 @@ static const uint8_t jump_table[] =
 									      \
 	/* The string argument could in fact be `char *' or `wchar_t *'.      \
 	   But this should not make a difference here.  */		      \
-	if (fspec == NULL)						      \
-	  string = (CHAR_T *) va_arg (ap, const wchar_t *);		      \
-	else								      \
-	  string = (CHAR_T *) args_value[fspec->data_arg].pa_wstring;	      \
+	string = (CHAR_T *) process_arg_wstring ();			      \
 									      \
 	/* Entry point for printing other strings.  */			      \
       LABEL (print_string):						      \
@@ -1090,7 +1026,7 @@ static const uint8_t jump_table[] =
       }									      \
       break;
 #else
-# define process_string_arg(fspec) \
+# define process_string_arg()						      \
     LABEL (form_character):						      \
       /* Character.  */							      \
       if (is_long)							      \
@@ -1098,10 +1034,7 @@ static const uint8_t jump_table[] =
       --width;	/* Account for the character itself.  */		      \
       if (!left)							      \
 	PAD (' ');							      \
-      if (fspec == NULL)						      \
-	outchar ((unsigned char) va_arg (ap, int)); /* Promoted.  */	      \
-      else								      \
-	outchar ((unsigned char) args_value[fspec->data_arg].pa_int);	      \
+      outchar ((unsigned char) process_arg_int ()); /* Promoted.  */	      \
       if (left)								      \
 	PAD (' ');							      \
       break;								      \
@@ -1114,9 +1047,7 @@ static const uint8_t jump_table[] =
 	size_t len;							      \
 									      \
 	memset (&mbstate, '\0', sizeof (mbstate_t));			      \
-	len = __wcrtomb (buf, (fspec == NULL ? va_arg (ap, wchar_t)	      \
-			       : args_value[fspec->data_arg].pa_wchar),	      \
-			 &mbstate);					      \
+	len = __wcrtomb (buf, process_arg_wchar_t (), &mbstate);	      \
 	if (len == (size_t) -1)						      \
 	  {								      \
 	    /* Something went wrong during the conversion.  Bail out.  */     \
@@ -1138,10 +1069,7 @@ static const uint8_t jump_table[] =
 									      \
 	/* The string argument could in fact be `char *' or `wchar_t *'.      \
 	   But this should not make a difference here.  */		      \
-	if (fspec == NULL)						      \
-	  string = (char *) va_arg (ap, const char *);			      \
-	else								      \
-	  string = (char *) args_value[fspec->data_arg].pa_string;	      \
+	string = (char *) process_arg_string ();			      \
 									      \
 	/* Entry point for printing other strings.  */			      \
       LABEL (print_string):						      \
@@ -1322,7 +1250,6 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
       STEP0_3_TABLE;
       STEP4_TABLE;
 
-      union printf_arg *args_value;	/* This is not used here but ... */
       int is_negative;	/* Flag for negative number.  */
       union
       {
@@ -1337,7 +1264,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
       int left = 0;	/* Left-justify output.  */
       int showsign = 0;	/* Always begin with plus or minus sign.  */
       int group = 0;	/* Print numbers according grouping rules.  */
-      int is_long_double = 0; /* Argument is long double/ long long int.  */
+      /* Argument is long double/long long int.  Only used if
+	 double/long double or long int/long long int are distinct.  */
+      int is_long_double __attribute__ ((unused)) = 0;
       int is_short = 0;	/* Argument is short int.  */
       int is_long = 0;	/* Argument is long int.  */
       int is_char = 0;	/* Argument is promoted (unsigned) char.  */
@@ -1545,8 +1474,28 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
       /* Process current format.  */
       while (1)
 	{
-	  process_arg (((struct printf_spec *) NULL));
-	  process_string_arg (((struct printf_spec *) NULL));
+#define process_arg_int() va_arg (ap, int)
+#define process_arg_long_int() va_arg (ap, long int)
+#define process_arg_long_long_int() va_arg (ap, long long int)
+#define process_arg_pointer() va_arg (ap, void *)
+#define process_arg_string() va_arg (ap, const char *)
+#define process_arg_unsigned_int() va_arg (ap, unsigned int)
+#define process_arg_unsigned_long_int() va_arg (ap, unsigned long int)
+#define process_arg_unsigned_long_long_int() va_arg (ap, unsigned long long int)
+#define process_arg_wchar_t() va_arg (ap, wchar_t)
+#define process_arg_wstring() va_arg (ap, const wchar_t *)
+	  process_arg ();
+	  process_string_arg ();
+#undef process_arg_int
+#undef process_arg_long_int
+#undef process_arg_long_long_int
+#undef process_arg_pointer
+#undef process_arg_string
+#undef process_arg_unsigned_int
+#undef process_arg_unsigned_long_int
+#undef process_arg_unsigned_long_long_int
+#undef process_arg_wchar_t
+#undef process_arg_wstring
 
 	LABEL (form_float):
 	LABEL (form_floathex):
@@ -1850,7 +1799,8 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
       int left = specs[nspecs_done].info.left;
       int showsign = specs[nspecs_done].info.showsign;
       int group = specs[nspecs_done].info.group;
-      int is_long_double = specs[nspecs_done].info.is_long_double;
+      int is_long_double __attribute__ ((unused))
+	= specs[nspecs_done].info.is_long_double;
       int is_short = specs[nspecs_done].info.is_short;
       int is_char = specs[nspecs_done].info.is_char;
       int is_long = specs[nspecs_done].info.is_long;
@@ -1933,8 +1883,30 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
 
 	  JUMP (spec, step4_jumps);
 
-	  process_arg ((&specs[nspecs_done]));
-	  process_string_arg ((&specs[nspecs_done]));
+#define process_arg_data args_value[specs[nspecs_done].data_arg]
+#define process_arg_int() process_arg_data.pa_int
+#define process_arg_long_int() process_arg_data.pa_long_int
+#define process_arg_long_long_int() process_arg_data.pa_long_long_int
+#define process_arg_pointer() process_arg_data.pa_pointer
+#define process_arg_string() process_arg_data.pa_string
+#define process_arg_unsigned_int() process_arg_data.pa_u_int
+#define process_arg_unsigned_long_int() process_arg_data.pa_u_long_int
+#define process_arg_unsigned_long_long_int() process_arg_data.pa_u_long_long_int
+#define process_arg_wchar_t() process_arg_data.pa_wchar
+#define process_arg_wstring() process_arg_data.pa_wstring
+	  process_arg ();
+	  process_string_arg ();
+#undef process_arg_data
+#undef process_arg_int
+#undef process_arg_long_int
+#undef process_arg_long_long_int
+#undef process_arg_pointer
+#undef process_arg_string
+#undef process_arg_unsigned_int
+#undef process_arg_unsigned_long_int
+#undef process_arg_unsigned_long_long_int
+#undef process_arg_wchar_t
+#undef process_arg_wstring
 
 	  LABEL (form_float):
 	  LABEL (form_floathex):