This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Don't duplicate declarations between string.h and strings.h


On 11/16/2016 03:55 PM, Zack Weinberg wrote:
> I was looking into something else and noticed that all of the
> declarations in strings.h are duplicated in string.h, but not quite
> consistently.  This patch cleans that all up

And as a follow-on, here is a patch that makes declaring const-covariant
string functions much tidier.  The macros involved are messy, but I
think the reduced duplication in the public header file is worth it.

zw

commit d076c75978afa4b22f1827503c197f90c309586a
Author: Zack Weinberg <zackw@panix.com>
Date:   Wed Nov 16 18:34:27 2016 -0500

    New mechanism for declaring const-covariant string functions.

    Several functions in string.h and strings.h return a pointer into a
    buffer passed as their first argument.  That pointer logically ought
    to inherit the 'const'-ness of the original buffer.  There's no way to
    express that in C, so all these functions are specified with a
    prototype that, as a side-effect, strips the 'const', potentially
    leading to bugs:

        char *strfoo(const char *buf, ...);

    In C++, however, you can get it exactly right via function overloads:

        char *strfoo(char *buf, ...);
        const char *strfoo(const char *buf, ...);

    and C++11 (21.7 [c.strings]) requires the library to do just that.
    We were implementing this requirement via a repetitive and error-prone
    mess of #ifdefs for each and every one of the affected functions.

    This patch absorbs the entire mess into a pair of macros,
    __CONST_COV_PROTO and __CONST_COV_BUILTIN, which are far less
    error-prone to use, and which make the public header file much nicer
    to read, too.  They needed some black magic to _implement_, but it's
    hiding in a bits header and hopefully nobody need ever change that
    file again.

            * string/bits/const-covariance.h: New file.
            * string/string.h: Use __CONST_COV_PROTO and
__CONST_COV_BUILTIN to
            declare memchr, rawmemchr, memrchr, strchr, strrchr, strchrnul,
            strpbrk, strstr, strcasestr, memmem, and basename.
            * string/strings.h: Likewise for index and rindex.

            * include/bits/const-covariance.h: New wrapper.
            * include/string.h: Suppress internal definitions when
__cplusplus
            is defined, as well as when _ISOMAC is defined.

diff --git a/ChangeLog b/ChangeLog
index 4a5dc8a..18f8296 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2016-11-16  Zack Weinberg  <zackw@panix.com>

+	* string/bits/const-covariance.h: New file.
+	* string/string.h: Use __CONST_COV_PROTO and __CONST_COV_BUILTIN to
+	declare memchr, rawmemchr, memrchr, strchr, strrchr, strchrnul,
+	strpbrk, strstr, strcasestr, memmem, and basename.
+	* string/strings.h: Likewise for index and rindex.
+
+	* include/bits/const-covariance.h: New wrapper.
+	* include/string.h: Suppress internal definitions when __cplusplus
+	is defined, as well as when _ISOMAC is defined.
+
+2016-11-16  Zack Weinberg  <zackw@panix.com>
+
 	* string/string.h [__USE_MISC]: Include strings.h.
 	(__bzero, bcmp, bcopy, bzero, index, rindex)
 	(strcasecmp, strncasecmp, strcasecmp_l, strncasecmp_l)
diff --git a/include/bits/const-covariance.h
b/include/bits/const-covariance.h
new file mode 100644
index 0000000..564d730
--- /dev/null
+++ b/include/bits/const-covariance.h
@@ -0,0 +1 @@
+#include <string/bits/const-covariance.h>
diff --git a/include/string.h b/include/string.h
index 749e691..4c029cf 100644
--- a/include/string.h
+++ b/include/string.h
@@ -1,6 +1,6 @@
 #ifndef _STRING_H

-#ifndef _ISOMAC
+#if !defined _ISOMAC && !defined __cplusplus
 #include <sys/types.h>

 extern void *__memccpy (void *__dest, const void *__src,
@@ -46,16 +46,16 @@ extern void __bzero (void *__s, size_t __n) __THROW
__nonnull ((1));
 extern int __ffs (int __i) __attribute__ ((const));

 extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);
-#endif

 /* Get _STRING_ARCH_unaligned.  */
 #include <string_private.h>
+#endif /* !_ISOMAC && !__cplusplus */

 /* Now the real definitions.  We do this here since some of the functions
    above are defined as macros in the headers.  */
 #include <string/string.h>

-#ifndef _ISOMAC
+#if !defined _ISOMAC && !defined __cplusplus
 extern __typeof (strcoll_l) __strcoll_l;
 extern __typeof (strxfrm_l) __strxfrm_l;
 extern __typeof (strcasecmp_l) __strcasecmp_l;
@@ -151,13 +151,11 @@ extern __typeof (mempcpy) mempcpy __asm__
("__mempcpy");
 extern __typeof (stpcpy) stpcpy __asm__ ("__stpcpy");
 #endif

-# ifndef _ISOMAC
-#  ifndef index
-#   define index(s, c)	(strchr ((s), (c)))
-#  endif
-#  ifndef rindex
-#   define rindex(s, c)	(strrchr ((s), (c)))
-#  endif
+# ifndef index
+#  define index(s, c)	(strchr ((s), (c)))
+# endif
+# ifndef rindex
+#  define rindex(s, c)	(strrchr ((s), (c)))
 # endif

 extern void *__memcpy_chk (void *__restrict __dest,
@@ -185,6 +183,6 @@ extern char *__strcat_chk (char *__restrict __dest,
 extern char *__strncat_chk (char *__restrict __dest,
 			    const char *__restrict __src,
 			    size_t __len, size_t __destlen) __THROW;
-#endif
+#endif /* !_ISOMAC && !__cplusplus */

 #endif
diff --git a/string/Makefile b/string/Makefile
index 69d3f80..c009872 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -24,7 +24,8 @@ include ../Makeconfig

 headers	:= string.h strings.h memory.h endian.h bits/endian.h \
 	   argz.h envz.h byteswap.h bits/byteswap.h bits/byteswap-16.h \
-	   bits/string.h bits/string2.h bits/string3.h
+	   bits/string.h bits/string2.h bits/string3.h \
+	   bits/const-covariance.h

 routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 		   strverscmp strdup strndup				\
diff --git a/string/bits/const-covariance.h b/string/bits/const-covariance.h
new file mode 100644
index 0000000..19b3e31
--- /dev/null
+++ b/string/bits/const-covariance.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_CONST_COVARIANCE_H
+#define _BITS_CONST_COVARIANCE_H 1
+
+#if !defined _STRING_H && !defined _STRINGS_H
+# error "Never use <bits/const-covariance.h> directly; include
<string.h> or <strings.h> instead."
+#endif
+
+/* This header defines internal-use macros that expand a C prototype
+   declaration like
+
+       extern void *memchr (const void *, int, size_t) attrs;
+
+   to a pair of C++ overloaded function declarations with improved
+   const-correctness:
+
+       extern void *memchr (void *, int, size_t) attrs;
+       extern const void *memchr (const void *, int, size_t) attrs;
+
+   You use them like this:
+
+       __CONST_COV_PROTO (memchr, attrs,
+                          void *, __s, int, __c, size_t, __n);
+
+    where the arguments after 'attrs' are the function's arguments,
+    alternating with argument names.  The first of these will be used
+    as the const-covariant return type.  It should be written without
+    a 'const' qualifier.
+
+    If the compiler has intrinsic knowledge of the function, use
+    __CONST_COV_BUILTIN instead of __CONST_COV_PROTO.  In C++ mode,
+    this will also generate inline functions of the form
+
+        __extern_always_inline [const] void *
+        memchr (void *__s, int __c, size_t __n) attrs
+        {
+          return __builtin_memchr (__s, __c, __n);
+        }
+
+    Due to limitations in the preprocessor, these macros support no
+    more than four arguments to any function.  This is all that
+    string.h/strings.h currently require.
+
+    Because g++ only accepts throw(), __asm("..."), and
+    __attribute__((whatever)) annotations in a specific order, all
+    functions declared with __CONST_COV_PROTO or defined with
+    __CONST_COV_BUILTIN are automatically marked __THROW.  Do not put
+    __THROW in 'attrs'.  */
+
+#define __CC_VA_NARGS(...)  __CC_VA_NARGS_(__VA_ARGS__, __CC_RSEQ)
+#define __CC_VA_NARGS_(...) __CC_VA_NARGS__(__VA_ARGS__)
+#define __CC_VA_NARGS__(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
+#define __CC_RSEQ 8, 7, 6, 5, 4, 3, 2, 1
+
+#define __CC_2FOR2(op, a, b)	  op (a, b)
+#define __CC_2FOR4(op, a, b, ...) op (a, b), __CC_2FOR2 (op, __VA_ARGS__)
+#define __CC_2FOR6(op, a, b, ...) op (a, b), __CC_2FOR4 (op, __VA_ARGS__)
+#define __CC_2FOR8(op, a, b, ...) op (a, b), __CC_2FOR6 (op, __VA_ARGS__)
+
+#define __CC_2FOR(op, ...) \
+ __CC_2FOR_ (__CC_VA_NARGS (__VA_ARGS__)) (op, __VA_ARGS__)
+#define __CC_2FOR_(n) __CC_2FOR__ (n)
+#define __CC_2FOR__(n) __CC_2FOR##n
+
+#define __CC_XPROTO(...) (__CC_2FOR (__CC_XPROTO_, __VA_ARGS__))
+#define __CC_XPROTO_(type, name) type name
+
+#define __CC_XCALL(...) (__CC_2FOR (__CC_XCALL_, __VA_ARGS__))
+#define __CC_XCALL_(type, name) name
+
+#if !defined __cplusplus || !__GNUC_PREREQ (4, 4)
+
+# define __CONST_COV_PROTO(name, attrs, rtype, ...)			\
+   extern rtype name __CC_XPROTO(const rtype, __VA_ARGS__) __THROW attrs
+
+# define __CONST_COV_BUILTIN(...) __CONST_COV_PROTO (__VA_ARGS__)
+
+#else
+
+# define __CONST_COV_PROTO_BODY(name, attrs, rtype, ...)		\
+  extern rtype name __CC_XPROTO(rtype, __VA_ARGS__)			\
+    __THROW __asm (#name) attrs;					\
+  extern const rtype name __CC_XPROTO(const rtype, __VA_ARGS__)		\
+    __THROW __asm (#name) attrs;
+
+# define __CONST_COV_PROTO(...)						\
+   extern "C++"								\
+   {									\
+     __CONST_COV_PROTO_BODY(__VA_ARGS__)				\
+   }									\
+   struct __require_semicolon
+
+# ifndef __OPTIMIZE__
+#  define __CONST_COV_BUILTIN(...) __CONST_COV_PROTO (__VA_ARGS__)
+
+# else
+
+#  define __CONST_COV_BUILTIN(name, attrs, rtype, ...)			\
+  extern "C++"								\
+  {									\
+    __CONST_COV_PROTO_BODY (name, attrs, rtype, __VA_ARGS__)		\
+    __extern_always_inline rtype					\
+    name __CC_XPROTO (rtype, __VA_ARGS__) __THROW			\
+    { return __builtin_##name __CC_XCALL (rtype, __VA_ARGS__); }	\
+    __extern_always_inline const rtype					\
+    name __CC_XPROTO (const rtype, __VA_ARGS__) __THROW			\
+    { return __builtin_##name __CC_XCALL (rtype, __VA_ARGS__); }	\
+  }									\
+  struct __require_semicolon
+
+# endif /* __OPTIMIZE__ */
+#endif /* C++ and GCC >=4.4 */
+
+#endif /* const-covariance.h */
diff --git a/string/string.h b/string/string.h
index ca22cd0..601025b 100644
--- a/string/string.h
+++ b/string/string.h
@@ -36,7 +36,7 @@ __BEGIN_DECLS
 #if defined __cplusplus && __GNUC_PREREQ (4, 4)
 # define __CORRECT_ISO_CPP_STRING_H_PROTO
 #endif
-
+#include <bits/const-covariance.h>

 __BEGIN_NAMESPACE_STD
 /* Copy N bytes of SRC to DEST.  */
@@ -66,61 +66,31 @@ extern void *memset (void *__s, int __c, size_t __n)
__THROW __nonnull ((1));
 extern int memcmp (const void *__s1, const void *__s2, size_t __n)
      __THROW __attribute_pure__ __nonnull ((1, 2));

-/* Search N bytes of S for C.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern void *memchr (void *__s, int __c, size_t __n)
-      __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
-extern const void *memchr (const void *__s, int __c, size_t __n)
-      __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline void *
-memchr (void *__s, int __c, size_t __n) __THROW
-{
-  return __builtin_memchr (__s, __c, __n);
-}
-
-__extern_always_inline const void *
-memchr (const void *__s, int __c, size_t __n) __THROW
-{
-  return __builtin_memchr (__s, __c, __n);
-}
-# endif
-}
-#else
-extern void *memchr (const void *__s, int __c, size_t __n)
-      __THROW __attribute_pure__ __nonnull ((1));
-#endif
+/* Search N bytes of S for C.
+   [C]    extern void *memchr (const void *s, int c, size_t n);
+   [C++]  extern void *memchr (void *s, int c, size_t n);
+          extern const void *memchr (const void *s, int c, size_t n);  */
+__CONST_COV_BUILTIN (memchr, __attribute_pure__ __nonnull ((1)),
+                     void *, __s, int, __c, size_t, __n);
 __END_NAMESPACE_STD

 #ifdef __USE_GNU
-/* Search in S for C.  This is similar to `memchr' but there is no
-   length limit.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" void *rawmemchr (void *__s, int __c)
-     __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
-extern "C++" const void *rawmemchr (const void *__s, int __c)
-     __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
-# else
-extern void *rawmemchr (const void *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Search in S for C.  This is similar to 'memchr' but there is no
+   length limit.
+   [C]    extern void *rawmemchr (const void *s, int c);
+   [C++]  extern void *rawmemchr (void *s, int c);
+          extern const void *rawmemchr (const void *s, int c);  */
+__CONST_COV_PROTO (rawmemchr, __attribute_pure__ __nonnull ((1)),
+                   void *, __s, int, __c);

-/* Search N bytes of S for the final occurrence of C.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" void *memrchr (void *__s, int __c, size_t __n)
-      __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
-extern "C++" const void *memrchr (const void *__s, int __c, size_t __n)
-      __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
-# else
-extern void *memrchr (const void *__s, int __c, size_t __n)
-      __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Search N bytes of S for the final occurrence of C.
+   [C]    extern void *memrchr (const void *s, int c, size_t n);
+   [C++]  extern void *memrchr (void *s, int c, size_t n);
+          extern const void *memrchr (const void *s, int c, size_t n);  */
+__CONST_COV_PROTO (memrchr, __attribute_pure__ __nonnull ((1)),
+                   void *, __s, int, __c, size_t, __n);
 #endif

-
 __BEGIN_NAMESPACE_STD
 /* Copy SRC to DEST.  */
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
@@ -204,74 +174,30 @@ extern char *strndup (const char *__string, size_t
__n)
 #endif

 __BEGIN_NAMESPACE_STD
-/* Find the first occurrence of C in S.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strchr (char *__s, int __c)
-     __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
-extern const char *strchr (const char *__s, int __c)
-     __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
+/* Find the first occurrence of C in S.
+   [C]    extern char *strchr (const char *s, int c);
+   [C++]  extern char *strchr (char *s, int c);
+          extern const char *strchr (const char *s, int c);  */
+__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
+                   char *, __s, int, __c);

-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strchr (char *__s, int __c) __THROW
-{
-  return __builtin_strchr (__s, __c);
-}
+/* Find the last occurrence of C in S.
+   [C]    extern char *strrchr (const char *s, int c);
+   [C++]  extern char *strrchr (char *s, int c);
+          extern const char *strrchr (const char *s, int c);  */
+__CONST_COV_BUILTIN (strrchr, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);

-__extern_always_inline const char *
-strchr (const char *__s, int __c) __THROW
-{
-  return __builtin_strchr (__s, __c);
-}
-# endif
-}
-#else
-extern char *strchr (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-#endif
-/* Find the last occurrence of C in S.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strrchr (char *__s, int __c)
-     __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
-extern const char *strrchr (const char *__s, int __c)
-     __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strrchr (char *__s, int __c) __THROW
-{
-  return __builtin_strrchr (__s, __c);
-}
-
-__extern_always_inline const char *
-strrchr (const char *__s, int __c) __THROW
-{
-  return __builtin_strrchr (__s, __c);
-}
-# endif
-}
-#else
-extern char *strrchr (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-#endif
 __END_NAMESPACE_STD

 #ifdef __USE_GNU
 /* This function is similar to `strchr'.  But it returns a pointer to
-   the closing NUL byte in case C is not found in S.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *strchrnul (char *__s, int __c)
-     __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
-extern "C++" const char *strchrnul (const char *__s, int __c)
-     __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
-# else
-extern char *strchrnul (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+   the closing NUL byte in case C is not found in S.
+   [C]    extern char *strchrnul (const char *s, int c);
+   [C++]  extern char *strchrnul (char *s, int c);
+          extern const char *strchrnul (const char *s, int c);  */
+__CONST_COV_PROTO (strchrnul, __attribute_pure__ __nonnull ((1)),
+                   char *, __s, int, __c);
 #endif

 __BEGIN_NAMESPACE_STD
@@ -279,65 +205,26 @@ __BEGIN_NAMESPACE_STD
    consists entirely of characters not in REJECT.  */
 extern size_t strcspn (const char *__s, const char *__reject)
      __THROW __attribute_pure__ __nonnull ((1, 2));
+
 /* Return the length of the initial segment of S which
    consists entirely of characters in ACCEPT.  */
 extern size_t strspn (const char *__s, const char *__accept)
      __THROW __attribute_pure__ __nonnull ((1, 2));
-/* Find the first occurrence in S of any character in ACCEPT.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strpbrk (char *__s, const char *__accept)
-     __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));
-extern const char *strpbrk (const char *__s, const char *__accept)
-     __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));

-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strpbrk (char *__s, const char *__accept) __THROW
-{
-  return __builtin_strpbrk (__s, __accept);
-}
-
-__extern_always_inline const char *
-strpbrk (const char *__s, const char *__accept) __THROW
-{
-  return __builtin_strpbrk (__s, __accept);
-}
-# endif
-}
-#else
-extern char *strpbrk (const char *__s, const char *__accept)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-#endif
-/* Find the first occurrence of NEEDLE in HAYSTACK.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strstr (char *__haystack, const char *__needle)
-     __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
-extern const char *strstr (const char *__haystack, const char *__needle)
-     __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strstr (char *__haystack, const char *__needle) __THROW
-{
-  return __builtin_strstr (__haystack, __needle);
-}
-
-__extern_always_inline const char *
-strstr (const char *__haystack, const char *__needle) __THROW
-{
-  return __builtin_strstr (__haystack, __needle);
-}
-# endif
-}
-#else
-extern char *strstr (const char *__haystack, const char *__needle)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-#endif
+/* Find the first occurrence in S of any character in ACCEPT.
+   [C]   extern char *strpbrk (const char *s, const char *accept);
+   [C++] extern char *strpbrk (char *s, const char *accept);
+         extern const char *strpbrk (const char *s, const char *accept); */
+__CONST_COV_BUILTIN (strpbrk, __attribute_pure__ __nonnull ((1, 2)),
+                     char *, __s, const char *, __accept);

+/* Find the first occurrence of NEEDLE in HAYSTACK.
+   [C]   extern char *strstr (const char *haystack, const char *needle);
+   [C++] extern char *strstr (char *haystack, const char *needle);
+         extern const char *strstr (const char *haystack, const char
*needle);
+ */
+__CONST_COV_BUILTIN (strstr, __attribute_pure__ __nonnull ((1, 2)),
+                     char *, __haystack, const char *, __needle);

 /* Divide S into tokens separated by characters in DELIM.  */
 extern char *strtok (char *__restrict __s, const char *__restrict __delim)
@@ -357,26 +244,26 @@ extern char *strtok_r (char *__restrict __s, const
char *__restrict __delim,
 #endif

 #ifdef __USE_GNU
-/* Similar to `strstr' but this function ignores the case of both
strings.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *strcasestr (char *__haystack, const char *__needle)
-     __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
-extern "C++" const char *strcasestr (const char *__haystack,
-				     const char *__needle)
-     __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
-# else
-extern char *strcasestr (const char *__haystack, const char *__needle)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-# endif
-#endif
+/* Similar to 'strstr', but ignores the case of both strings.
+   [C]   extern char *strcasestr (const char *haystack, const char
*needle);
+   [C++] extern char *strcasestr (char *haystack, const char *needle);
+         extern const char *strcasestr (const char *haystack,
+                                        const char *needle);  */
+__CONST_COV_PROTO (strcasestr, __attribute_pure__ __nonnull ((1, 2)),
+                   char *, __haystack, const char *, __needle);

-#ifdef __USE_GNU
 /* Find the first occurrence of NEEDLE in HAYSTACK.
    NEEDLE is NEEDLELEN bytes long;
-   HAYSTACK is HAYSTACKLEN bytes long.  */
-extern void *memmem (const void *__haystack, size_t __haystacklen,
-		     const void *__needle, size_t __needlelen)
-     __THROW __attribute_pure__ __nonnull ((1, 3));
+   HAYSTACK is HAYSTACKLEN bytes long.
+   [C]   extern void *memmem (const void *haystack, size_t haystacklen,
+                              const void *needle, size_t needlelen);
+   [C++] extern void *memmem (void *haystack, size_t haystacklen,
+                              const void *needle, size_t needlelen);
+         extern const void *memmem (const void *haystack, size_t
haystacklen,
+                                    const void *needle, size_t
needlelen);  */
+__CONST_COV_PROTO (memmem, __attribute_pure__ __nonnull ((1, 3)),
+                   void *, __haystack, size_t, __haystacklen,
+                   const void *, __needle, size_t, __needlelen);

 /* Copy N bytes of SRC to DEST, return pointer to bytes after the
    last written byte.  */
@@ -487,15 +374,12 @@ extern void *memfrob (void *__s, size_t __n)
__THROW __nonnull ((1));
 /* Return the file name within directory of FILENAME.  We don't
    declare the function if the `basename' macro is available (defined
    in <libgen.h>) which makes the XPG version of this function
-   available.  */
-#  ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *basename (char *__filename)
-     __THROW __asm ("basename") __nonnull ((1));
-extern "C++" const char *basename (const char *__filename)
-     __THROW __asm ("basename") __nonnull ((1));
-#  else
-extern char *basename (const char *__filename) __THROW __nonnull ((1));
-#  endif
+   available.
+   [C]   char *basename (const char *filename);
+   [C++] char *basename (char *filename);
+         const char *basename (const char *filename);  */
+__CONST_COV_PROTO (basename, __nonnull ((1)),
+                   char *, __filename);
 # endif
 #endif

diff --git a/string/strings.h b/string/strings.h
index f78eca5..a72530a 100644
--- a/string/strings.h
+++ b/string/strings.h
@@ -26,6 +26,7 @@
 #if defined __cplusplus && __GNUC_PREREQ (4, 4)
 # define __CORRECT_ISO_CPP_STRINGS_H_PROTO
 #endif
+#include <bits/const-covariance.h>

 __BEGIN_DECLS

@@ -41,61 +42,19 @@ extern void bcopy (const void *__src, void *__dest,
size_t __n)
 /* Set N bytes of S to 0.  */
 extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));

-/* Find the first occurrence of C in S (same as strchr).  */
-# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
-extern "C++"
-{
-extern char *index (char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
-extern const char *index (const char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
+/* Find the first occurrence of C in S (same as strchr).
+   [C]    extern char *index (const char *s, int c);
+   [C++]  extern char *index (char *s, int c);
+          extern const char *index (const char *s, int c);  */
+__CONST_COV_BUILTIN (index, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);

-#  if defined __OPTIMIZE__
-__extern_always_inline char *
-index (char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-
-__extern_always_inline const char *
-index (const char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-#  endif
-}
-# else
-extern char *index (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
-
-/* Find the last occurrence of C in S (same as strrchr).  */
-# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
-extern "C++"
-{
-extern char *rindex (char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-extern const char *rindex (const char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-
-#  if defined __OPTIMIZE__
-__extern_always_inline char *
-rindex (char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-
-__extern_always_inline const char *
-rindex (const char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-#  endif
-}
-# else
-extern char *rindex (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Find the last occurrence of C in S (same as strrchr).
+   [C]    extern char *rindex (const char *s, int c);
+   [C++]  extern char *rindex (char *s, int c);
+          extern const char *rindex (const char *s, int c);  */
+__CONST_COV_BUILTIN (rindex, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);
 #endif

 #if defined __USE_MISC || !defined __USE_XOPEN2K8 || defined
__USE_XOPEN2K8XSI
@@ -106,11 +65,11 @@ extern int ffs (int __i) __THROW __attribute_const__;

 /* The following two functions are non-standard but necessary for
non-32 bit
    platforms.  */
-# ifdef	__USE_GNU
+#ifdef	__USE_GNU
 extern int ffsl (long int __l) __THROW __attribute_const__;
 __extension__ extern int ffsll (long long int __ll)
      __THROW __attribute_const__;
-# endif
+#endif

 /* Compare S1 and S2, ignoring case.  */
 extern int strcasecmp (const char *__s1, const char *__s2)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]