in printf, use ferror macro rather than directly inspecting flags bit
[musl] / src / stdio / vfwprintf.c
index e87ad42..1878411 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stddef.h>
+#include <stdlib.h>
 #include <wchar.h>
 #include <inttypes.h>
 
@@ -52,6 +53,8 @@ static const unsigned char states[]['z'-'A'+1] = {
        }, { /* 1: l-prefixed */
                S('d') = LONG, S('i') = LONG,
                S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+               S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
+               S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
                S('c') = INT, S('s') = PTR, S('n') = PTR,
                S('l') = LLPRE,
        }, { /* 2: ll-prefixed */
@@ -122,7 +125,13 @@ static void pop_arg(union arg *arg, int type, va_list *ap)
 
 static void out(FILE *f, const wchar_t *s, size_t l)
 {
-       while (l-- && !(f->flags & F_ERR)) fputwc(*s++, f);
+       while (l-- && !ferror(f)) fputwc(*s++, f);
+}
+
+static void pad(FILE *f, int n, int fl)
+{
+       if ((fl & LEFT_ADJ) || !n || ferror(f)) return;
+       fprintf(f, "%*s", n, "");
 }
 
 static int getint(wchar_t **s) {
@@ -239,6 +248,10 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
                }
 
                if (!f) continue;
+
+               /* Do not process any new directives once in error state. */
+               if (ferror(f)) return -1;
+
                t = s[-1];
                if (ps && (t&15)==3) t&=~32;
 
@@ -255,12 +268,12 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
                        }
                        continue;
                case 'c':
-                       fputwc(btowc(arg.i), f);
-                       l = 1;
-                       continue;
                case 'C':
-                       fputwc(arg.i, f);
-                       l = 1;
+                       if (w<1) w=1;
+                       pad(f, w-1, fl);
+                       out(f, &(wchar_t){t=='C' ? arg.i : btowc(arg.i)}, 1);
+                       pad(f, w-1, fl^LEFT_ADJ);
+                       l = w;
                        continue;
                case 'S':
                        a = arg.p;
@@ -268,9 +281,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
                        if (p<0 && *z) goto overflow;
                        p = z-a;
                        if (w<p) w=p;
-                       if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+                       pad(f, w-p, fl);
                        out(f, a, p);
-                       if ((fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+                       pad(f, w-p, fl^LEFT_ADJ);
                        l=w;
                        continue;
                case 'm':
@@ -283,14 +296,14 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
                        if (p<0 && *bs) goto overflow;
                        p=l;
                        if (w<p) w=p;
-                       if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+                       pad(f, w-p, fl);
                        bs = arg.p;
                        while (l--) {
                                i=mbtowc(&wc, bs, MB_LEN_MAX);
                                bs+=i;
-                               fputwc(wc, f);
+                               out(f, &wc, 1);
                        }
-                       if ((fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+                       pad(f, w-p, fl^LEFT_ADJ);
                        l=w;
                        continue;
                }
@@ -351,7 +364,7 @@ int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
        olderr = f->flags & F_ERR;
        f->flags &= ~F_ERR;
        ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type);
-       if (f->flags & F_ERR) ret = -1;
+       if (ferror(f)) ret = -1;
        f->flags |= olderr;
        FUNLOCK(f);
        va_end(ap2);