Use inline ctype functions for ato*/strto* and scanf.

This also let us remove the `unsigned char` casts, since we define our
inlines to work for all values.

Before:

  Benchmark                      Time           CPU Iterations
  -------------------------------------------------------------
  BM_inttypes_strtoimax        112 ns        112 ns    6222193
  BM_inttypes_strtoumax        104 ns        104 ns    6725010
  BM_stdlib_strtol             113 ns        113 ns    6195861
  BM_stdlib_strtoll            113 ns        113 ns    6195633
  BM_stdlib_strtoul            105 ns        105 ns    6691394
  BM_stdlib_strtoull           105 ns        105 ns    6690695

  BM_stdio_scanf_d                    504 ns        503 ns    1385224
  BM_stdio_scanf_maps                1900 ns       1898 ns     369260
  BM_stdio_scanf_maps_baseline       1030 ns       1030 ns     678832
  BM_stdio_scanf_s                    433 ns        432 ns    1619086

After:

  BM_inttypes_strtoimax         91 ns         91 ns    7718194
  BM_inttypes_strtoumax         82 ns         82 ns    8508052
  BM_stdlib_strtol              92 ns         92 ns    7674694
  BM_stdlib_strtoll             91 ns         91 ns    7639228
  BM_stdlib_strtoul             83 ns         82 ns    8500304
  BM_stdlib_strtoull            82 ns         82 ns    8504929

  BM_stdio_scanf_d                    465 ns        465 ns    1507891
  BM_stdio_scanf_maps                1836 ns       1836 ns     381082
  BM_stdio_scanf_maps_baseline        846 ns        845 ns     830881
  BM_stdio_scanf_s                    419 ns        419 ns    1671979

Bug: N/A
Test: ran tests, benchmarks
Change-Id: I44681daf16c4328b060770cf11fc0633157c427f
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index f83a317..f4c8c5f 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -27,12 +27,13 @@
  * SUCH DAMAGE.
  */
 
-#include <ctype.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdlib.h>
 
+#include <private/bionic_ctype.h>
+
 template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
   // Ensure that base is between 2 and 36 inclusive, or the special value of 0.
   if (base < 0 || base == 1 || base > 36) {
@@ -47,8 +48,8 @@
   const char* s = nptr;
   int c;
   do {
-    c = static_cast<unsigned char>(*s++);
-  } while (isspace(c));
+    c = *s++;
+  } while (IsSpace(c));
   int neg;
   if (c == '-') {
     neg = 1;
@@ -58,7 +59,7 @@
     if (c == '+') c = *s++;
   }
   if ((base == 0 || base == 16) && c == '0' &&
-      (*s == 'x' || *s == 'X') && isxdigit(static_cast<unsigned char>(s[1]))) {
+      (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
     c = s[1];
     s += 2;
     base = 16;
@@ -92,11 +93,11 @@
   // Set `any` if any digits consumed; make it negative to indicate overflow.
   int any = 0;
   T acc = 0;
-  for (; ; c = static_cast<unsigned char>(*s++)) {
-    if (isdigit(c)) {
+  for (; ; c = *s++) {
+    if (IsDigit(c)) {
       c -= '0';
-    } else if (isalpha(c)) {
-      c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+    } else if (IsAlpha(c)) {
+      c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
     } else {
       break;
     }
@@ -138,8 +139,8 @@
   const char* s = nptr;
   int c;
   do {
-    c = static_cast<unsigned char>(*s++);
-  } while (isspace(c));
+    c = *s++;
+  } while (IsSpace(c));
   int neg;
   if (c == '-') {
     neg = 1;
@@ -149,7 +150,7 @@
     if (c == '+') c = *s++;
   }
   if ((base == 0 || base == 16) && c == '0' &&
-      (*s == 'x' || *s == 'X') && isxdigit(static_cast<unsigned char>(s[1]))) {
+      (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
     c = s[1];
     s += 2;
     base = 16;
@@ -160,11 +161,11 @@
   int cutlim = Max % static_cast<T>(base);
   T acc = 0;
   int any = 0;
-  for (; ; c = static_cast<unsigned char>(*s++)) {
-    if (isdigit(c)) {
+  for (; ; c = *s++) {
+    if (IsDigit(c)) {
       c -= '0';
-    } else if (isalpha(c)) {
-      c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+    } else if (IsAlpha(c)) {
+      c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
     } else {
       break;
     }
diff --git a/libc/private/bionic_ctype.h b/libc/private/bionic_ctype.h
new file mode 100644
index 0000000..96df974
--- /dev/null
+++ b/libc/private/bionic_ctype.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __BIONIC_PRIVATE_BIONIC_CTYPE_H_
+#define __BIONIC_PRIVATE_BIONIC_CTYPE_H_
+
+static inline bool IsAlpha(int ch) {
+  return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+static inline bool IsDigit(int ch) {
+  return (ch >= '0' && ch <= '9');
+}
+
+static inline bool IsSpace(int ch) {
+  return (ch == ' ') || (ch >= '\t' && ch <= '\r');
+}
+
+static inline bool IsUpper(int ch) {
+  return (ch >= 'A' && ch <= 'Z');
+}
+
+static inline bool IsXDigit(int ch) {
+  return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
+}
+
+#endif
diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c
index c9e4385..f0ed4ae 100644
--- a/libc/stdio/vfscanf.c
+++ b/libc/stdio/vfscanf.c
@@ -31,7 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <ctype.h>
 #include <inttypes.h>
 #include <stdarg.h>
 #include <stddef.h>
@@ -41,6 +40,8 @@
 #include <wctype.h>
 #include "local.h"
 
+#include <private/bionic_ctype.h>
+
 #define BUF 513 /* Maximum length of numeric string. */
 
 /*
@@ -116,8 +117,8 @@
   for (;;) {
     c = *fmt++;
     if (c == 0) return (nassigned);
-    if (isspace(c)) {
-      while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p)) nread++, fp->_r--, fp->_p++;
+    if (IsSpace(c)) {
+      while ((fp->_r > 0 || __srefill(fp) == 0) && IsSpace(*fp->_p)) nread++, fp->_r--, fp->_p++;
       continue;
     }
     if (c != '%') goto literal;
@@ -127,11 +128,11 @@
      * switch on the format.  continue if done;
      * break once format type is derived.
      */
-  again:
+again:
     c = *fmt++;
     switch (c) {
       case '%':
-      literal:
+literal:
         if (fp->_r <= 0 && __srefill(fp)) goto input_failure;
         if (*fp->_p != c) goto match_failure;
         fp->_r--, fp->_p++;
@@ -286,7 +287,7 @@
         return (EOF);
 
       default: /* compat */
-        if (isupper(c)) flags |= LONG;
+        if (IsUpper(c)) flags |= LONG;
         c = CT_INT;
         base = 10;
         break;
@@ -302,12 +303,13 @@
      * that suppress this.
      */
     if ((flags & NOSKIP) == 0) {
-      while (isspace(*fp->_p)) {
+      while (IsSpace(*fp->_p)) {
         nread++;
-        if (--fp->_r > 0)
+        if (--fp->_r > 0) {
           fp->_p++;
-        else if (__srefill(fp))
+        } else if (__srefill(fp)) {
           goto input_failure;
+        }
       }
       /*
        * Note that there is at least one character in
@@ -395,7 +397,7 @@
 
           wcp = (flags & SUPPRESS) == 0 ? va_arg(ap, wchar_t*) : &twc;
           n = 0;
-          while ((c == CT_CCL || !isspace(*fp->_p)) && width != 0) {
+          while ((c == CT_CCL || !IsSpace(*fp->_p)) && width != 0) {
             if (n == (int)MB_CUR_MAX) {
               fp->_flags |= __SERR;
               goto input_failure;
@@ -439,7 +441,7 @@
           n = nchars;
         } else if (flags & SUPPRESS) {
           n = 0;
-          while ((c == CT_CCL && ccltab[*fp->_p]) || (c == CT_STRING && !isspace(*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)) {
@@ -449,7 +451,7 @@
           }
         } else {
           p0 = p = va_arg(ap, char*);
-          while ((c == CT_CCL && ccltab[*fp->_p]) || (c == CT_STRING && !isspace(*fp->_p))) {
+          while ((c == CT_CCL && ccltab[*fp->_p]) || (c == CT_STRING && !IsSpace(*fp->_p))) {
             fp->_r--;
             *p++ = *fp->_p++;
             if (--width == 0) break;