More scanf cleanup.

Merge CT_CCL and CT_STRING handling before we add %m.

Also fix an accidental scanf/wscanf difference.

Add currently-disabled tests for questionable behavior noticed during
code review that isn't a regression, but should be fixed later.

Bug: http://b/68672236
Bug: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202240
Test: ran tests
Change-Id: I3eec9b7dfce84f63c68426406224822c52551d64
diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.c
index 1030a62..71cd49b 100644
--- a/libc/stdio/vfwscanf.c
+++ b/libc/stdio/vfwscanf.c
@@ -182,7 +182,7 @@
         if ((wi = __fgetwc_unlock(fp)) == WEOF) goto input_failure;
         if (wi != c) {
           __ungetwc(wi, fp);
-          goto input_failure;
+          goto match_failure;
         }
         nread++;
         continue;
@@ -402,28 +402,26 @@
         break;
 
       case CT_CCL:
-        /* scan a (nonempty) character class (sets NOSKIP) */
-        if (width == 0) width = (size_t)~0; /* `infinity' */
-        /* take only those things in the class */
+      case CT_STRING:
+        // CT_CCL: scan a (nonempty) character class (sets NOSKIP).
+        // CT_STRING: like CCL, but zero-length string OK, & no NOSKIP.
+        if (width == 0) width = (size_t)~0; // 'infinity'.
         if ((flags & SUPPRESS) && (flags & LONG)) {
           n = 0;
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && in_ccl(wi, ccl)) n++;
+          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) n++;
           if (wi != WEOF) __ungetwc(wi, fp);
-          if (n == 0) goto match_failure;
         } else if (flags & LONG) {
           p0 = p = va_arg(ap, wchar_t*);
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && in_ccl(wi, ccl))
+          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) {
             *p++ = (wchar_t)wi;
+          }
           if (wi != WEOF) __ungetwc(wi, fp);
           n = p - p0;
-          if (n == 0) goto match_failure;
-          *p = 0;
-          nassigned++;
         } else {
           if (!(flags & SUPPRESS)) mbp = va_arg(ap, char*);
           n = 0;
           memset(&mbs, 0, sizeof(mbs));
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width != 0 && in_ccl(wi, ccl)) {
+          while ((wi = __fgetwc_unlock(fp)) != WEOF && width != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) {
             if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) {
               nconv = wcrtomb(mbp, wi, &mbs);
               if (nconv == (size_t)-1) goto input_failure;
@@ -438,57 +436,20 @@
             n++;
           }
           if (wi != WEOF) __ungetwc(wi, fp);
-          if (n == 0) goto match_failure;
-          if (!(flags & SUPPRESS)) {
-            *mbp = 0;
-            nassigned++;
+        }
+        if (c == CT_CCL && n == 0) goto match_failure;
+        if (!(flags & SUPPRESS)) {
+          if (flags & LONG) {
+            *p = L'\0';
+          } else {
+            *mbp = '\0';
           }
+          ++nassigned;
         }
         nread += n;
         nconversions++;
         break;
 
-      case CT_STRING:
-        /* like CCL, but zero-length string OK, & no NOSKIP */
-        if (width == 0) width = (size_t)~0;
-        if ((flags & SUPPRESS) && (flags & LONG)) {
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && !iswspace(wi)) nread++;
-          if (wi != WEOF) __ungetwc(wi, fp);
-        } else if (flags & LONG) {
-          p0 = p = va_arg(ap, wchar_t*);
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && !iswspace(wi)) {
-            *p++ = (wchar_t)wi;
-            nread++;
-          }
-          if (wi != WEOF) __ungetwc(wi, fp);
-          *p = 0;
-          nassigned++;
-        } else {
-          if (!(flags & SUPPRESS)) mbp = va_arg(ap, char*);
-          memset(&mbs, 0, sizeof(mbs));
-          while ((wi = __fgetwc_unlock(fp)) != WEOF && width != 0 && !iswspace(wi)) {
-            if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) {
-              nconv = wcrtomb(mbp, wi, &mbs);
-              if (nconv == (size_t)-1) goto input_failure;
-            } else {
-              nconv = wcrtomb(mbbuf, wi, &mbs);
-              if (nconv == (size_t)-1) goto input_failure;
-              if (nconv > width) break;
-              if (!(flags & SUPPRESS)) memcpy(mbp, mbbuf, nconv);
-            }
-            if (!(flags & SUPPRESS)) mbp += nconv;
-            width -= nconv;
-            nread++;
-          }
-          if (wi != WEOF) __ungetwc(wi, fp);
-          if (!(flags & SUPPRESS)) {
-            *mbp = 0;
-            nassigned++;
-          }
-        }
-        nconversions++;
-        continue;
-
       case CT_INT:
         /* scan an integer as if by strtoimax/strtoumax */
         if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1)