Merge "Speed up __sfileext initialization."
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;
diff --git a/tests/dlfcn_symlink_support.cpp b/tests/dlfcn_symlink_support.cpp
index be1839e..a5d3c3e 100644
--- a/tests/dlfcn_symlink_support.cpp
+++ b/tests/dlfcn_symlink_support.cpp
@@ -44,7 +44,7 @@
     return 0;
   }
 
-  if (android::base::EndsWith(info->dlpi_name, suffix.c_str())) {
+  if (android::base::EndsWith(info->dlpi_name, suffix)) {
     std::string* path = reinterpret_cast<std::string*>(data);
     *path = info->dlpi_name;
     return 1; // found
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 7a96760..fccff67 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -31,6 +31,31 @@
 
 #include "private/bionic_constants.h"
 
+TEST(time, time) {
+  // Acquire time
+  time_t p1, t1 = time(&p1);
+  // valid?
+  ASSERT_NE(static_cast<time_t>(0), t1);
+  ASSERT_NE(static_cast<time_t>(-1), t1);
+  ASSERT_EQ(p1, t1);
+
+  // Acquire time one+ second later
+  usleep(1010000);
+  time_t p2, t2 = time(&p2);
+  // valid?
+  ASSERT_NE(static_cast<time_t>(0), t2);
+  ASSERT_NE(static_cast<time_t>(-1), t2);
+  ASSERT_EQ(p2, t2);
+
+  // Expect time progression
+  ASSERT_LT(p1, p2);
+  ASSERT_LE(t2 - t1, static_cast<time_t>(2));
+
+  // Expect nullptr call to produce same results
+  ASSERT_LE(t2, time(nullptr));
+  ASSERT_LE(time(nullptr) - t2, static_cast<time_t>(1));
+}
+
 TEST(time, gmtime) {
   time_t t = 0;
   tm* broken_down = gmtime(&t);