diff --git a/string/bits/string2.h b/string/bits/string2.h
index cff529728b7d31f207c6c43aedae4a1b0df4b4b4..e18c67530ec78338c9591015f3d95c785de54726 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -21,6 +21,10 @@
 # error "Never use <bits/string2.h> directly; include <string.h> instead."
 #endif

+#ifdef _FORCE_INLINES
+# error "This header no longer supports _FORCE_INLINES."
+#endif
+
 #ifndef __NO_STRING_INLINES

 /* Unlike the definitions in the header <bits/string.h> the
@@ -67,7 +71,7 @@
 /* Copy N bytes from SRC to DEST, returning pointer to byte following the
    last copied.  */
 #ifdef __USE_GNU
-# if !defined _HAVE_STRING_ARCH_mempcpy || defined _FORCE_INLINES
+# if !defined _HAVE_STRING_ARCH_mempcpy
 #  ifndef _HAVE_STRING_ARCH_mempcpy
 #   if __GNUC_PREREQ (3, 4)
 #    define __mempcpy(dest, src, n) __builtin_mempcpy (dest, src, n)
@@ -88,18 +92,13 @@ extern void *__rawmemchr (const void *__s, int __c);
                  && (c) == '\0'                                              \
                  ? (char *) __rawmemchr (s, c)                               \
                  : __builtin_strchr (s, c)))
-# else
-#  define strchr(s, c) \
-  (__extension__ (__builtin_constant_p (c) && (c) == '\0'                    \
-                 ? (char *) __rawmemchr (s, c)                               \
-                 : strchr (s, c)))
 # endif
 #endif


 /* Copy SRC to DEST, returning pointer to final NUL byte.  */
 #ifdef __USE_GNU
-# if !defined _HAVE_STRING_ARCH_stpcpy || defined _FORCE_INLINES
+# if !defined _HAVE_STRING_ARCH_stpcpy
 #  ifndef _HAVE_STRING_ARCH_stpcpy
 #   if __GNUC_PREREQ (3, 4)
 #    define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
@@ -157,37 +156,10 @@ extern void *__rawmemchr (const void *__s, int __c);
            && (__s2_len = strlen (s2), __s2_len < 4)                         \
            ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1)            \
               ? __builtin_strcmp (s1, s2)                                    \
-              : __strcmp_gc (s1, s2, __s2_len))                              \
+              : (- __strcmp_cg (s2, s1, __s2_len)))                          \
            : __builtin_strcmp (s1, s2)))); })
 # endif

-# define __strcmp_cc(s1, s2, l) \
-  (__extension__ ({ int __result =                                           \
-                     (((const unsigned char *) (const char *) (s1))[0]       \
-                      - ((const unsigned char *) (const char *)(s2))[0]);    \
-                   if (l > 0 && __result == 0)                               \
-                     {                                                       \
-                       __result = (((const unsigned char *)                  \
-                                    (const char *) (s1))[1]                  \
-                                   - ((const unsigned char *)                \
-                                      (const char *) (s2))[1]);              \
-                       if (l > 1 && __result == 0)                           \
-                         {                                                   \
-                           __result =                                        \
-                             (((const unsigned char *)                       \
-                               (const char *) (s1))[2]                       \
-                              - ((const unsigned char *)                     \
-                                 (const char *) (s2))[2]);                   \
-                           if (l > 2 && __result == 0)                       \
-                             __result =                                      \
-                               (((const unsigned char *)                     \
-                                 (const char *) (s1))[3]                     \
-                                - ((const unsigned char *)                   \
-                                   (const char *) (s2))[3]);                 \
-                         }                                                   \
-                     }                                                       \
-                   __result; }))
-
 # define __strcmp_cg(s1, s2, l1) \
   (__extension__ ({ const unsigned char *__s2 =                                      \
                      (const unsigned char *) (const char *) (s2);            \
@@ -210,7 +182,6 @@ extern void *__rawmemchr (const void *__s, int __c);
                      }                                                       \
                    __result; }))

-# define __strcmp_gc(s1, s2, l2) (- __strcmp_cg (s2, s1, l2))
 #endif


@@ -228,7 +199,7 @@ extern void *__rawmemchr (const void *__s, int __c);

 /* Return the length of the initial segment of S which
    consists entirely of characters not in REJECT.  */
-#if !defined _HAVE_STRING_ARCH_strcspn || defined _FORCE_INLINES
+#if !defined _HAVE_STRING_ARCH_strcspn
 # ifndef _HAVE_STRING_ARCH_strcspn
 #  if __GNUC_PREREQ (3, 2)
 #   define strcspn(s, reject) \
@@ -289,7 +260,7 @@ __strcspn_c3 (const char *__s, int __reject1, int __reject2,

 /* Return the length of the initial segment of S which
    consists entirely of characters in ACCEPT.  */
-#if !defined _HAVE_STRING_ARCH_strspn || defined _FORCE_INLINES
+#if !defined _HAVE_STRING_ARCH_strspn
 # ifndef _HAVE_STRING_ARCH_strspn
 #  if __GNUC_PREREQ (3, 2)
 #   define strspn(s, accept) \
@@ -350,7 +321,7 @@ __strspn_c3 (const char *__s, int __accept1, int __accept2, int __accept3)


 /* Find the first occurrence in S of any character in ACCEPT.  */
-#if !defined _HAVE_STRING_ARCH_strpbrk || defined _FORCE_INLINES
+#if !defined _HAVE_STRING_ARCH_strpbrk
 # ifndef _HAVE_STRING_ARCH_strpbrk
 #  if __GNUC_PREREQ (3, 2)
 #   define strpbrk(s, accept) \
@@ -397,7 +368,7 @@ __strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
 #endif


-#if !defined _HAVE_STRING_ARCH_strtok_r || defined _FORCE_INLINES
+#if !defined _HAVE_STRING_ARCH_strtok_r
 # ifndef _HAVE_STRING_ARCH_strtok_r
 #  define __strtok_r(s, sep, nextp) \
   (__extension__ (__builtin_constant_p (sep) && __string2_1bptr_p (sep)              \
@@ -436,7 +407,7 @@ __strtok_r_1c (char *__s, char __sep, char **__nextp)
 #endif


-#if !defined _HAVE_STRING_ARCH_strsep || defined _FORCE_INLINES
+#if !defined _HAVE_STRING_ARCH_strsep
 # ifndef _HAVE_STRING_ARCH_strsep

 extern char *__strsep_g (char **__stringp, const char *__delim);
@@ -585,8 +556,6 @@ extern char *__strndup (const char *__string, size_t __n)

 #endif /* Use misc. or use GNU.  */

-#ifndef _FORCE_INLINES
-# undef __STRING_INLINE
-#endif
+#undef __STRING_INLINE

 #endif /* No string inlines.  */
diff --git a/string/string-inlines.c b/string/string-inlines.c
index 4e91329df22b9c604fff1e833212a8b778c36390..a3c1d27f91d025c8bc4b3d9b8ed5f496562e024e 100644
--- a/string/string-inlines.c
+++ b/string/string-inlines.c
@@ -15,9 +15,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

-/*  <bits/string.h> and <bits/string2.h> declare some extern inline
-    functions.  These functions are declared additionally here if
-    inlining is not possible.  */
+/*  <bits/string.h> and <bits/string2.h> declare various extern inline
+    functions.  These functions are defined here as an external ABI in
+    case they are not inlined.  Even if these functions are removed
+    from the string headers, they must still be defined here.  */

 #undef __USE_STRING_INLINES
 #define __USE_STRING_INLINES
@@ -31,7 +32,14 @@

 #undef __NO_INLINE__
 #include <bits/string.h>
-#include <bits/string2.h>
+
+#ifndef __STRING_INLINE
+# ifdef __cplusplus
+#  define __STRING_INLINE inline
+# else
+#  define __STRING_INLINE __extern_inline
+# endif
+#endif

 /* These are a few types we need for the optimizations if we cannot
    use unaligned memory accesses.  */
@@ -378,3 +386,167 @@ __stpcpy_small (char *__dest,
   return __dest + __srclen - 1;
 }
 #endif
+
+__STRING_INLINE size_t
+__strcspn_c1 (const char *__s, int __reject)
+{
+  size_t __result = 0;
+  while (__s[__result] != '\0' && __s[__result] != __reject)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE size_t
+__strcspn_c2 (const char *__s, int __reject1, int __reject2)
+{
+  size_t __result = 0;
+  while (__s[__result] != '\0' && __s[__result] != __reject1
+        && __s[__result] != __reject2)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE size_t
+__strcspn_c3 (const char *__s, int __reject1, int __reject2,
+             int __reject3)
+{
+  size_t __result = 0;
+  while (__s[__result] != '\0' && __s[__result] != __reject1
+        && __s[__result] != __reject2 && __s[__result] != __reject3)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE size_t
+__strspn_c1 (const char *__s, int __accept)
+{
+  size_t __result = 0;
+  /* Please note that __accept never can be '\0'.  */
+  while (__s[__result] == __accept)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE size_t
+__strspn_c2 (const char *__s, int __accept1, int __accept2)
+{
+  size_t __result = 0;
+  /* Please note that __accept1 and __accept2 never can be '\0'.  */
+  while (__s[__result] == __accept1 || __s[__result] == __accept2)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE size_t
+__strspn_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
+{
+  size_t __result = 0;
+  /* Please note that __accept1 to __accept3 never can be '\0'.  */
+  while (__s[__result] == __accept1 || __s[__result] == __accept2
+        || __s[__result] == __accept3)
+    ++__result;
+  return __result;
+}
+
+__STRING_INLINE char *
+__strpbrk_c2 (const char *__s, int __accept1, int __accept2)
+{
+  /* Please note that __accept1 and __accept2 never can be '\0'.  */
+  while (*__s != '\0' && *__s != __accept1 && *__s != __accept2)
+    ++__s;
+  return *__s == '\0' ? NULL : (char *) (size_t) __s;
+}
+
+__STRING_INLINE char *
+__strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
+{
+  /* Please note that __accept1 to __accept3 never can be '\0'.  */
+  while (*__s != '\0' && *__s != __accept1 && *__s != __accept2
+        && *__s != __accept3)
+    ++__s;
+  return *__s == '\0' ? NULL : (char *) (size_t) __s;
+}
+
+__STRING_INLINE char *
+__strtok_r_1c (char *__s, char __sep, char **__nextp)
+{
+  char *__result;
+  if (__s == NULL)
+    __s = *__nextp;
+  while (*__s == __sep)
+    ++__s;
+  __result = NULL;
+  if (*__s != '\0')
+    {
+      __result = __s++;
+      while (*__s != '\0')
+       if (*__s++ == __sep)
+         {
+           __s[-1] = '\0';
+           break;
+         }
+    }
+  *__nextp = __s;
+  return __result;
+}
+
+__STRING_INLINE char *
+__strsep_1c (char **__s, char __reject)
+{
+  char *__retval = *__s;
+  if (__retval != NULL && (*__s = strchr (__retval, __reject)) != NULL)
+    *(*__s)++ = '\0';
+  return __retval;
+}
+
+__STRING_INLINE char *
+__strsep_2c (char **__s, char __reject1, char __reject2)
+{
+  char *__retval = *__s;
+  if (__retval != NULL)
+    {
+      char *__cp = __retval;
+      while (1)
+       {
+         if (*__cp == '\0')
+           {
+             __cp = NULL;
+         break;
+           }
+         if (*__cp == __reject1 || *__cp == __reject2)
+           {
+             *__cp++ = '\0';
+             break;
+           }
+         ++__cp;
+       }
+      *__s = __cp;
+    }
+  return __retval;
+}
+
+__STRING_INLINE char *
+__strsep_3c (char **__s, char __reject1, char __reject2, char __reject3)
+{
+  char *__retval = *__s;
+  if (__retval != NULL)
+    {
+      char *__cp = __retval;
+      while (1)
+       {
+         if (*__cp == '\0')
+           {
+             __cp = NULL;
+         break;
+           }
+         if (*__cp == __reject1 || *__cp == __reject2 || *__cp == __reject3)
+           {
+             *__cp++ = '\0';
+             break;
+           }
+         ++__cp;
+       }
+      *__s = __cp;
+    }
+  return __retval;
+}
