diff options
-rw-r--r-- | sysdeps/generic/memchr.c | 101 |
1 files changed, 64 insertions, 37 deletions
diff --git a/sysdeps/generic/memchr.c b/sysdeps/generic/memchr.c index d17f9c649e..1731574907 100644 --- a/sysdeps/generic/memchr.c +++ b/sysdeps/generic/memchr.c @@ -20,17 +20,44 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> -#include <string.h> +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#undef __ptr_t +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +# define __ptr_t void * +#else /* Not C++ or ANSI C. */ +# define __ptr_t char * +#endif /* C++ or ANSI C. */ + +#if defined (HAVE_STRING_H) || defined (_LIBC) +# include <string.h> +#endif + +#if defined (HAVE_LIMIT_H) || defined (_LIBC) +# include <limit.h> +#endif + +#define LONG_MAX_32_BITS 2147483647 + +#ifndef LONG_MAX +#define LONG_MAX LONG_MAX_32_BITS +#endif + +#include <sys/types.h> /* Search no more than N bytes of S for C. */ -PTR -DEFUN(memchr, (s, c, n), CONST PTR s AND int c AND size_t n) +__ptr_t +memchr (s, c, n) + const __ptr_t s; + int c; + size_t n; { - CONST unsigned char *char_ptr; - CONST unsigned long int *longword_ptr; + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; unsigned long int longword, magic_bits, charmask; c = (unsigned char) c; @@ -41,7 +68,7 @@ DEFUN(memchr, (s, c, n), CONST PTR s AND int c AND size_t n) & (sizeof (longword) - 1)) != 0; --n, ++char_ptr) if (*char_ptr == c) - return (PTR) char_ptr; + return (__ptr_t) char_ptr; /* All these elucidatory comments refer to 4-byte longwords, but the theory applies equally well to 8-byte longwords. */ @@ -57,21 +84,22 @@ DEFUN(memchr, (s, c, n), CONST PTR s AND int c AND size_t n) The 1-bits make sure that carries propagate to the next 0-bit. The 0-bits provide holes for carries to fall into. */ - switch (sizeof (longword)) - { - case 4: magic_bits = 0x7efefeffL; break; - case 8: magic_bits = (0x7efefefeL << 32) | 0xfefefeffL; break; - default: - abort (); - } + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif /* Set up a longword, each of whose bytes is C. */ charmask = c | (c << 8); charmask |= charmask << 16; - if (sizeof (longword) > 4) - charmask |= charmask << 32; - if (sizeof (longword) > 8) - abort (); +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif /* Instead of the traditional loop which tests each character, we will test a longword at a time. The tricky part is testing @@ -128,41 +156,40 @@ DEFUN(memchr, (s, c, n), CONST PTR s AND int c AND size_t n) /* Which of the bytes was C? If none of them were, it was a misfire; continue the search. */ - CONST unsigned char *cp = (CONST unsigned char *) (longword_ptr - 1); + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); if (cp[0] == c) - return (PTR) cp; + return (__ptr_t) cp; if (cp[1] == c) - return (PTR) &cp[1]; + return (__ptr_t) &cp[1]; if (cp[2] == c) - return (PTR) &cp[2]; + return (__ptr_t) &cp[2]; if (cp[3] == c) - return (PTR) &cp[3]; - if (sizeof (longword) > 4) - { - if (cp[4] == c) - return (PTR) &cp[4]; - if (cp[5] == c) - return (PTR) &cp[5]; - if (cp[6] == c) - return (PTR) &cp[6]; - if (cp[7] == c) - return (PTR) &cp[7]; - } + return (__ptr_t) &cp[3]; +#if LONG_MAX > 2147483647 + if (cp[4] == c) + return (__ptr_t) &cp[4]; + if (cp[5] == c) + return (__ptr_t) &cp[5]; + if (cp[6] == c) + return (__ptr_t) &cp[6]; + if (cp[7] == c) + return (__ptr_t) &cp[7]; +#endif } n -= sizeof (longword); } - char_ptr = (CONST unsigned char *) longword_ptr; + char_ptr = (const unsigned char *) longword_ptr; while (n-- > 0) { if (*char_ptr == c) - return (PTR) char_ptr; + return (__ptr_t) char_ptr; else ++char_ptr; } - return NULL; + return 0; } |