From patchwork Thu Nov 17 00:35:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Weinberg X-Patchwork-Id: 17536 Received: (qmail 43718 invoked by alias); 17 Nov 2016 00:36:06 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 43709 invoked by uid 89); 17 Nov 2016 00:36:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.2 required=5.0 tests=AWL, BAYES_20, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=makeconfig, REJECT, FILENAME, 10611 X-HELO: mail-qk0-f195.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=Uj4OCePO3n7ph9CmqWdHcumNAdQyqkMK1ruRp9PZ/HU=; b=N3XpmCbMk/em6nZod2pQvPnUmyz8DIU364SUeHHzS+NRnImqhVcsh6VQdlGZdO58KL TVfmgI5hXegzj+C8XLBOrenjLNBvMJuoUuU3ihCWYjbhXkgL1HWeQgZr98rpQOF+3YKG EdHALZCME1s+MSfJH4n2KxmqeyjOkM513EVJdEJ3Al054C0WyX8BW3nOUb/hpWExJkYv 6ucaM/AvvoVsP+clTJy9E3HjPMMaYgoOCy0Xl0uwhwXC2ETpAl9qT66JuApSjc6nCH6A fKfdca5GJW8/+F/aQFa8Hl//ZWUpGVa602E9hgE4vNy1m8E1bbkKnrVnmFJLWy9Pc9LC Bs4Q== X-Gm-Message-State: AKaTC03fjBoY2CKd6R75dOvYomr8tndeqLfUwtFr8SWLevzdBlAw1NbXI57WdxotLbhJlw== X-Received: by 10.55.163.138 with SMTP id m132mr446932qke.88.1479342952648; Wed, 16 Nov 2016 16:35:52 -0800 (PST) Subject: Re: [patch] Don't duplicate declarations between string.h and strings.h To: GNU C Library , Joseph Myers References: <1820d936-621b-1ca5-669c-68d8ab967ba3@panix.com> From: Zack Weinberg Message-ID: <413f5cee-ed1b-2520-b43c-d67a182db697@panix.com> Date: Wed, 16 Nov 2016 19:35:50 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.4.0 MIME-Version: 1.0 In-Reply-To: <1820d936-621b-1ca5-669c-68d8ab967ba3@panix.com> 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 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. #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) diff --git a/ChangeLog b/ChangeLog index 4a5dc8a..18f8296 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2016-11-16 Zack Weinberg + * 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 + * 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 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 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 +#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 -#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 + . */ + +#ifndef _BITS_CONST_COVARIANCE_H +#define _BITS_CONST_COVARIANCE_H 1 + +#if !defined _STRING_H && !defined _STRINGS_H +# error "Never use directly; include or 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 __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 ) 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 __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