diff options
author | Alan Modra <amodra@gmail.com> | 2025-01-01 22:31:50 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2025-01-01 22:31:50 +1030 |
commit | b38cf91f230bc3892ab9c3deb4f1b6639c657c47 (patch) | |
tree | 5cfd11814669a298c822cffe2eda3bc1ea1cad4c | |
parent | 5e04003fac2f15d18ec8c9167c139582fb897728 (diff) | |
download | binutils-b38cf91f230bc3892ab9c3deb4f1b6639c657c47.zip binutils-b38cf91f230bc3892ab9c3deb4f1b6639c657c47.tar.gz binutils-b38cf91f230bc3892ab9c3deb4f1b6639c657c47.tar.bz2 |
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.
-rw-r--r-- | bfd/bfd.c | 60 |
1 files changed, 51 insertions, 9 deletions
@@ -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) |