mescc: Support binutils 2.14: vfprint, vsprintf: %12.10d.
authorJan Nieuwenhuizen <janneke@gnu.org>
Wed, 20 Jun 2018 22:27:49 +0000 (00:27 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Wed, 20 Jun 2018 22:27:49 +0000 (00:27 +0200)
* lib/libc+tcc.c (vfprintf, vsprintf): Handle %12.10d.
* scaffold/tests/70-printf.c: Test it.

lib/libc+tcc.c
scaffold/tests/70-printf.c

index fc39c1a57d9a69e7491adfae0655d9c6c0c777a0..31364e21c5d9be68dd8eaafe27ba27b8dcddf07e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -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++;
index 653e212842238c38054fa4528558d9d13a3f78ff..4366b4478147739bdabf650a523fd1f1701e40a7 100644 (file)
@@ -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;
 }