From 2551eef9533e746c9092340b0edd271e8e717571 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Thu, 21 Jun 2018 00:27:49 +0200 Subject: [PATCH] mescc: Support binutils 2.14: vfprint, vsprintf: %12.10d. * lib/libc+tcc.c (vfprintf, vsprintf): Handle %12.10d. * scaffold/tests/70-printf.c: Test it. --- lib/libc+tcc.c | 177 +++++++++++++++++++++++++------------ scaffold/tests/70-printf.c | 11 +++ 2 files changed, 133 insertions(+), 55 deletions(-) diff --git a/lib/libc+tcc.c b/lib/libc+tcc.c index fc39c1a5..31364e21 100644 --- a/lib/libc+tcc.c +++ b/lib/libc+tcc.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -679,7 +680,7 @@ vfprintf (FILE* f, char const* format, va_list ap) p++; char c = *p; int left_p = 0; - int precision_p = 0; + int precision = -1; int width = -1; if (c == 'l') c = *++p; @@ -688,11 +689,6 @@ vfprintf (FILE* f, char const* format, va_list ap) left_p = 1; c = *++p; } - if (c == '.') - { - precision_p = 1; - c = *++p; - } char pad = ' '; if (c == '0') { @@ -709,6 +705,20 @@ vfprintf (FILE* f, char const* format, va_list ap) width = va_arg (ap, int); c = *++p; } + if (c == '.') + { + c = *++p; + if (c >= '0' && c <= '9') + { + precision = abtoi (&p, 10); + c = *p; + } + else if (c == '*') + { + precision = va_arg (ap, int); + c = *++p; + } + } if (c == 'l') c = *++p; switch (c) @@ -729,23 +739,35 @@ vfprintf (FILE* f, char const* format, va_list ap) char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X'); if (c == 'X') strupr (s); - if (!precision_p && width >= 0) - width = width - strlen (s); - if (!left_p && !precision_p) - while (!precision_p && width-- > 0) - { - fputc (pad, f); - count++; - } + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + fputc (pad, f); + count++; + } + while (precision > length) + { + fputc ('0', f); + precision--; + width--; + count++; + } + } while (*s) { - if (precision_p && width-- == 0) + if (precision-- <= 0) break; + width--; fputc (*s++, f); count++; } - while (!precision_p && width-- > 0) + while (width > 0) { + width--; fputc (pad, f); count++; } @@ -754,23 +776,35 @@ vfprintf (FILE* f, char const* format, va_list ap) case 's': { char *s = va_arg (ap, char *); - if (!precision_p && width >= 0) - width = width - strlen (s); - if (!left_p && !precision_p) - while (!precision_p && width-- > 0) - { - fputc (pad, f); - count++; - } + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + fputc (pad, f); + count++; + } + while (precision > length) + { + fputc (' ', f); + precision--; + width--; + count++; + } + } while (*s) { - if (precision_p && width-- == 0) + if (precision-- <= 0) break; + width--; fputc (*s++, f); count++; } - while (!precision_p && width-- > 0) + while (width > 0) { + width--; fputc (pad, f); count++; } @@ -784,7 +818,7 @@ vfprintf (FILE* f, char const* format, va_list ap) } default: { - eputs ("vfprintf: not supported: %"); + eputs ("vfprintf: not supported: %:"); eputc (c); eputs ("\n"); p++; @@ -841,7 +875,7 @@ vsscanf (char const *s, char const *template, va_list ap) } default: { - eputs ("vsscanf: not supported: %"); + eputs ("vsscanf: not supported: %:"); eputc (c); eputs ("\n"); t++; @@ -870,7 +904,7 @@ vsprintf (char *str, char const* format, va_list ap) p++; char c = *p; int left_p = 0; - int precision_p = 0; + int precision = -1; int width = -1; if (c == 'l') c = *++p; @@ -879,11 +913,6 @@ vsprintf (char *str, char const* format, va_list ap) left_p = 1; c = *++p; } - if (c == '.') - { - precision_p = 1; - c = *++p; - } char pad = ' '; if (c == '0') { @@ -900,6 +929,20 @@ vsprintf (char *str, char const* format, va_list ap) width = va_arg (ap, int); c = *++p; } + if (c == '.') + { + c = *++p; + if (c >= '0' && c <= '9') + { + precision = abtoi (&p, 10); + c = *p; + } + else if (c == '*') + { + precision = va_arg (ap, int); + c = *++p; + } + } if (c == 'l') c = *++p; switch (c) @@ -920,23 +963,35 @@ vsprintf (char *str, char const* format, va_list ap) char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X'); if (c == 'X') strupr (s); - if (!precision_p && width >= 0) - width = width - strlen (s); - if (!left_p && !precision_p) - while (!precision_p && width-- > 0) - { - *str++ = pad; - count++; - } + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + *str++ = pad; + count++; + } + while (precision > length) + { + *str++ = '0'; + precision--; + width--; + count++; + } + } while (*s) { - if (precision_p && width-- == 0) + if (precision-- <= 0) break; + width--; *str++ = *s++; count++; } - while (!precision_p && width-- > 0) + while (width > 0) { + width--; *str++ = pad; count++; } @@ -945,23 +1000,35 @@ vsprintf (char *str, char const* format, va_list ap) case 's': { char *s = va_arg (ap, char *); - if (!precision_p && width >= 0) - width = width - strlen (s); - if (!left_p && !precision_p) - while (!precision_p && width-- > 0) - { - *str++ = pad; - count++; - } + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + *str++ = pad; + count++; + } + while (width > length) + { + *str++ = ' '; + precision--; + width--; + count++; + } + } while (*s) { - if (precision_p && width-- == 0) + if (precision-- <= 0) break; + width--; *str++ = *s++; count++; } - while (!precision_p && width-- > 0) + while (width > 0) { + width--; *str++ = pad; count++; } @@ -975,7 +1042,7 @@ vsprintf (char *str, char const* format, va_list ap) } default: { - eputs ("vsprintf: not supported: %"); + eputs ("vsprintf: not supported: %:"); eputc (c); eputs ("\n"); p++; diff --git a/scaffold/tests/70-printf.c b/scaffold/tests/70-printf.c index 653e2128..4366b447 100644 --- a/scaffold/tests/70-printf.c +++ b/scaffold/tests/70-printf.c @@ -135,9 +135,11 @@ test () return 19; int n; +#if !__x86_64__ fprintf (stderr, "foo bar\n%n", &n); if (n != 8) return 20; +#endif sprintf (buf, "foo%nbar\n", &n); eputs ("buf="); eputs (buf); eputs ("\n"); @@ -146,5 +148,14 @@ test () if (n != 3) return 22; +#if !__x86_64__ + fprintf (stdout, "%12.8d\n", 12345); +#endif + + sprintf (buf, "%12.8d\n", 12345); + eputs ("buf="); eputs (buf); eputs ("\n"); + if (strcmp (buf, " 00012345\n")) + return 23; + return 0; }