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/vfscanf.c b/libc/stdio/vfscanf.c
index 887b435..c9e4385 100644
--- a/libc/stdio/vfscanf.c
+++ b/libc/stdio/vfscanf.c
@@ -324,10 +324,7 @@
         /* scan arbitrary characters (sets NOSKIP) */
         if (width == 0) width = 1;
         if (flags & LONG) {
-          if ((flags & SUPPRESS) == 0)
-            wcp = va_arg(ap, wchar_t*);
-          else
-            wcp = NULL;
+          wcp = ((flags & SUPPRESS) == 0) ? va_arg(ap, wchar_t*) : NULL;
           n = 0;
           while (width != 0) {
             if (n == (int)MB_CUR_MAX) {
@@ -388,20 +385,17 @@
         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 & LONG) {
           wchar_t twc;
-          int nchars;
+          int nchars = 0;
 
-          if ((flags & SUPPRESS) == 0)
-            wcp = va_arg(ap, wchar_t*);
-          else
-            wcp = &twc;
+          wcp = (flags & SUPPRESS) == 0 ? va_arg(ap, wchar_t*) : &twc;
           n = 0;
-          nchars = 0;
-          while (width != 0) {
+          while ((c == CT_CCL || !isspace(*fp->_p)) && width != 0) {
             if (n == (int)MB_CUR_MAX) {
               fp->_flags |= __SERR;
               goto input_failure;
@@ -417,7 +411,7 @@
             }
             if (nconv == 0) *wcp = L'\0';
             if (nconv != (size_t)-2) {
-              if (wctob(*wcp) != EOF && !ccltab[wctob(*wcp)]) {
+              if ((c == CT_CCL && wctob(*wcp) != EOF && !ccltab[wctob(*wcp)]) || (c == CT_STRING && iswspace(*wcp))) {
                 while (n != 0) {
                   n--;
                   ungetc(buf[n], fp);
@@ -438,121 +432,46 @@
               break;
             }
           }
-          if (n != 0) {
+          if (c == CT_CCL && n != 0) {
             fp->_flags |= __SERR;
             goto input_failure;
           }
           n = nchars;
-          if (n == 0) goto match_failure;
-          if (!(flags & SUPPRESS)) {
-            *wcp = L'\0';
-            nassigned++;
-          }
-        } else
-            /* take only those things in the class */
-            if (flags & SUPPRESS) {
+        } else if (flags & SUPPRESS) {
           n = 0;
-          while (ccltab[*fp->_p]) {
+          while ((c == CT_CCL && ccltab[*fp->_p]) || (c == CT_STRING && !isspace(*fp->_p))) {
             n++, fp->_r--, fp->_p++;
             if (--width == 0) break;
             if (fp->_r <= 0 && __srefill(fp)) {
-              if (n == 0) goto input_failure;
+              if (c == CT_CCL && n == 0) goto input_failure;
               break;
             }
           }
-          if (n == 0) goto match_failure;
         } else {
           p0 = p = va_arg(ap, char*);
-          while (ccltab[*fp->_p]) {
+          while ((c == CT_CCL && ccltab[*fp->_p]) || (c == CT_STRING && !isspace(*fp->_p))) {
             fp->_r--;
             *p++ = *fp->_p++;
             if (--width == 0) break;
             if (fp->_r <= 0 && __srefill(fp)) {
-              if (p == p0) goto input_failure;
+              if (c == CT_CCL && p == p0) goto input_failure;
               break;
             }
           }
           n = p - p0;
-          if (n == 0) goto match_failure;
-          *p = '\0';
-          nassigned++;
+        }
+        if (c == CT_CCL && n == 0) goto match_failure;
+        if (!(flags & SUPPRESS)) {
+          if (flags & LONG) {
+            *wcp = L'\0';
+          } else {
+            *p = '\0';
+          }
+          ++nassigned;
         }
         nread += n;
         break;
 
-      case CT_STRING:
-        /* like CCL, but zero-length string OK, & no NOSKIP */
-        if (width == 0) width = (size_t)~0;
-        if (flags & LONG) {
-          wchar_t twc;
-
-          if ((flags & SUPPRESS) == 0)
-            wcp = va_arg(ap, wchar_t*);
-          else
-            wcp = &twc;
-          n = 0;
-          while (!isspace(*fp->_p) && width != 0) {
-            if (n == (int)MB_CUR_MAX) {
-              fp->_flags |= __SERR;
-              goto input_failure;
-            }
-            buf[n++] = *fp->_p;
-            fp->_p++;
-            fp->_r--;
-            memset(&mbs, 0, sizeof(mbs));
-            nconv = mbrtowc(wcp, buf, n, &mbs);
-            if (nconv == (size_t)-1) {
-              fp->_flags |= __SERR;
-              goto input_failure;
-            }
-            if (nconv == 0) *wcp = L'\0';
-            if (nconv != (size_t)-2) {
-              if (iswspace(*wcp)) {
-                while (n != 0) {
-                  n--;
-                  ungetc(buf[n], fp);
-                }
-                break;
-              }
-              nread += n;
-              width--;
-              if (!(flags & SUPPRESS)) wcp++;
-              n = 0;
-            }
-            if (fp->_r <= 0 && __srefill(fp)) {
-              if (n != 0) {
-                fp->_flags |= __SERR;
-                goto input_failure;
-              }
-              break;
-            }
-          }
-          if (!(flags & SUPPRESS)) {
-            *wcp = L'\0';
-            nassigned++;
-          }
-        } else if (flags & SUPPRESS) {
-          n = 0;
-          while (!isspace(*fp->_p)) {
-            n++, fp->_r--, fp->_p++;
-            if (--width == 0) break;
-            if (fp->_r <= 0 && __srefill(fp)) break;
-          }
-          nread += n;
-        } else {
-          p0 = p = va_arg(ap, char*);
-          while (!isspace(*fp->_p)) {
-            fp->_r--;
-            *p++ = *fp->_p++;
-            if (--width == 0) break;
-            if (fp->_r <= 0 && __srefill(fp)) break;
-          }
-          *p = '\0';
-          nread += p - p0;
-          nassigned++;
-        }
-        continue;
-
       case CT_INT:
         /* scan an integer as if by strtoimax/strtoumax */
 #ifdef hardway