From: Alan Modra Date: Wed, 1 Jan 2025 12:01:50 +0000 (+1030) Subject: PR 32507, PRIx64 in error messages on 32-bit mingw X-Git-Tag: binutils-2_44~301 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b38cf91f230bc3892ab9c3deb4f1b6639c657c47;p=thirdparty%2Fbinutils-gdb.git 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. --- diff --git a/bfd/bfd.c b/bfd/bfd.c index a0dd215e271..0e567ddeaea 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -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)