]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 32507, PRIx64 in error messages on 32-bit mingw
authorAlan Modra <amodra@gmail.com>
Wed, 1 Jan 2025 12:01:50 +0000 (22:31 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 1 Jan 2025 12:01:50 +0000 (22:31 +1030)
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.

bfd/bfd.c

index a0dd215e2717edf3e8219aa21f234a57205cf101..0e567ddeaea84c43dc7eeb2521ef5ee4ddb0fe1d 100644 (file)
--- 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)