PR 32507, PRIx64 in error messages on 32-bit mingw

People, including me, had forgotten that the bfd_error_handler just
handled standard printf format strings, not MSC %I64 and suchlike.
Using PRIx64 and similar in errors does not work if the host compiler
headers define those formats as the Microsoft %I64 variety.  (We
handled %ll OK, editing it to %I64 on such hosts.)

	PR 32507
	* bfd.c (_bfd_doprnt, _bfd_doprnt_scan): Handle %I64 and %I32
	in input strings if the host defines PRId64 as "I64d".
	Edit %ll to %I64 on detecting PRId64 as "I64d" rather than on
	a preprocessor define.
This commit is contained in:
Alan Modra 2025-01-01 22:31:50 +10:30
parent 5e04003fac
commit b38cf91f23

View File

@ -1090,8 +1090,14 @@ _bfd_doprnt (bfd_print_callback print, void *stream, const char *format,
ptr += 2;
}
/* There is a clash between Microsoft's non-standard I64
and I32 integer length modifiers and glibc's
non-standard I flag. */
const char *printf_flag_chars
= sizeof PRId64 == sizeof "I64d" ? "-+ #0'" : "-+ #0'I";
/* Move past flags. */
while (strchr ("-+ #0'I", *ptr))
while (strchr (printf_flag_chars, *ptr))
*sptr++ = *ptr++;
if (*ptr == '*')
@ -1141,6 +1147,22 @@ _bfd_doprnt (bfd_print_callback print, void *stream, const char *format,
while (ISDIGIT (*ptr))
*sptr++ = *ptr++;
}
if (sizeof PRId64 == sizeof "I64d" && *ptr =='I')
{
if (ptr[1] == '6' && ptr[2] == '4')
{
wide_width = 3;
*sptr++ = *ptr++;
*sptr++ = *ptr++;
*sptr++ = *ptr++;
}
else if (ptr[1] == '3' && ptr[2] == '2')
{
*sptr++ = *ptr++;
*sptr++ = *ptr++;
*sptr++ = *ptr++;
}
}
while (strchr ("hlL", *ptr))
{
switch (*ptr)
@ -1192,14 +1214,17 @@ _bfd_doprnt (bfd_print_callback print, void *stream, const char *format,
PRINT_TYPE (long, l);
break;
case 2:
if (sizeof PRId64 == sizeof "I64d")
{
/* Convert any %ll to %I64. */
sptr[-3] = 'I';
sptr[-2] = '6';
sptr[-1] = '4';
*sptr++ = ptr[-1];
*sptr = '\0';
}
/* Fall through. */
default:
#if defined (__MSVCRT__)
sptr[-3] = 'I';
sptr[-2] = '6';
sptr[-1] = '4';
*sptr++ = ptr[-1];
*sptr = '\0';
#endif
PRINT_TYPE (long long, ll);
break;
}
@ -1322,8 +1347,14 @@ _bfd_doprnt_scan (const char *format, va_list ap, union _bfd_doprnt_args *args)
ptr += 2;
}
/* There is a clash between Microsoft's non-standard I64
and I32 integer length modifiers and glibc's
non-standard I flag. */
const char *printf_flag_chars
= sizeof PRId64 == sizeof "I64d" ? "-+ #0'" : "-+ #0'I";
/* Move past flags. */
while (strchr ("-+ #0'I", *ptr))
while (strchr (printf_flag_chars, *ptr))
ptr++;
if (*ptr == '*')
@ -1372,6 +1403,17 @@ _bfd_doprnt_scan (const char *format, va_list ap, union _bfd_doprnt_args *args)
while (ISDIGIT (*ptr))
ptr++;
}
if (sizeof PRId64 == sizeof "I64d" && *ptr =='I')
{
if (ptr[1] == '6' && ptr[2] == '4')
{
wide_width = 3;
ptr += 3;
}
else if (ptr[1] == '3' && ptr[2] == '2')
ptr += 3;
}
while (strchr ("hlL", *ptr))
{
switch (*ptr)