Improve memory cleanup in 'relocatable' module.
[gnulib.git] / lib / memchr.c
index dc3bec7..b47eaef 100644 (file)
@@ -1,5 +1,7 @@
-/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
-   Based on strlen implemention by Torbjorn Granlund (tege@sics.se),
+/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006 Free
+   Software Foundation, Inc.
+
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
    with help from Dan Sahlin (dan@sics.se) and
    commentary by Jim Blandy (jimb@ai.mit.edu);
    adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
    with help from Dan Sahlin (dan@sics.se) and
    commentary by Jim Blandy (jimb@ai.mit.edu);
    adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
@@ -8,9 +10,9 @@
 NOTE: The canonical source of this file is maintained with the GNU C Library.
 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
 
 NOTE: The canonical source of this file is maintained with the GNU C Library.
 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
 
-This program is free software; you can redistribute it and/or modify it
+This program is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3 of the License, or any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -19,64 +21,57 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef _LIBC
+# include <config.h>
 #endif
 
 #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.  */
+#include <string.h>
 
 
-#if defined (_LIBC)
-# include <string.h>
-#endif
+#include <stddef.h>
 
 
-#if defined (HAVE_LIMITS_H) || defined (_LIBC)
-# include <limits.h>
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# define reg_char char
 #endif
 
 #endif
 
-#define LONG_MAX_32_BITS 2147483647
+#include <limits.h>
 
 
-#ifndef LONG_MAX
-#define LONG_MAX LONG_MAX_32_BITS
+#if HAVE_BP_SYM_H || defined _LIBC
+# include <bp-sym.h>
+#else
+# define BP_SYM(sym) sym
 #endif
 
 #endif
 
-#include <sys/types.h>
-
+#undef memchr
+#undef __memchr
 
 /* Search no more than N bytes of S for C.  */
 
 /* Search no more than N bytes of S for C.  */
-
-__ptr_t
-memchr (s, c, n)
-     const __ptr_t s;
-     int c;
-     size_t n;
+void *
+__memchr (void const *s, int c_in, size_t n)
 {
   const unsigned char *char_ptr;
   const unsigned long int *longword_ptr;
   unsigned long int longword, magic_bits, charmask;
 {
   const unsigned char *char_ptr;
   const unsigned long int *longword_ptr;
   unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+  int i;
 
 
-  c = (unsigned char) c;
+  c = (unsigned char) c_in;
 
   /* Handle the first few characters by reading one character at a time.
      Do this until CHAR_PTR is aligned on a longword boundary.  */
   for (char_ptr = (const unsigned char *) s;
 
   /* Handle the first few characters by reading one character at a time.
      Do this until CHAR_PTR is aligned on a longword boundary.  */
   for (char_ptr = (const unsigned char *) s;
-       n > 0 && ((unsigned long int) char_ptr
-                & (sizeof (longword) - 1)) != 0;
+       n > 0 && (size_t) char_ptr % sizeof longword != 0;
        --n, ++char_ptr)
     if (*char_ptr == c)
        --n, ++char_ptr)
     if (*char_ptr == c)
-      return (__ptr_t) char_ptr;
+      return (void *) char_ptr;
 
   /* All these elucidatory comments refer to 4-byte longwords,
 
   /* All these elucidatory comments refer to 4-byte longwords,
-     but the theory applies equally well to 8-byte longwords.  */
+     but the theory applies equally well to any size longwords.  */
 
 
-  longword_ptr = (unsigned long int *) char_ptr;
+  longword_ptr = (const unsigned long int *) char_ptr;
 
   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
      the "holes."  Note that there is a hole just to the left of
 
   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
      the "holes."  Note that there is a hole just to the left of
@@ -88,26 +83,28 @@ memchr (s, c, n)
      The 1-bits make sure that carries propagate to the next 0-bit.
      The 0-bits provide holes for carries to fall into.  */
 
      The 1-bits make sure that carries propagate to the next 0-bit.
      The 0-bits provide holes for carries to fall into.  */
 
-  if (sizeof (longword) != 4 && sizeof (longword) != 8)
-    abort ();
+  /* Set MAGIC_BITS to be this pattern of 1 and 0 bits.
+     Set CHARMASK to be a longword, each of whose bytes is C.  */
 
 
-#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.  */
+  magic_bits = 0xfefefefe;
   charmask = c | (c << 8);
   charmask |= charmask << 16;
   charmask = c | (c << 8);
   charmask |= charmask << 16;
-#if LONG_MAX > LONG_MAX_32_BITS
+#if 0xffffffffU < ULONG_MAX
+  magic_bits |= magic_bits << 32;
   charmask |= charmask << 32;
   charmask |= charmask << 32;
+  if (8 < sizeof longword)
+    for (i = 64; i < sizeof longword * 8; i *= 2)
+      {
+       magic_bits |= magic_bits << i;
+       charmask |= charmask << i;
+      }
 #endif
 #endif
+  magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1);
 
   /* Instead of the traditional loop which tests each character,
      we will test a longword at a time.  The tricky part is testing
      if *any of the four* bytes in the longword in question are zero.  */
 
   /* Instead of the traditional loop which tests each character,
      we will test a longword at a time.  The tricky part is testing
      if *any of the four* bytes in the longword in question are zero.  */
-  while (n >= sizeof (longword))
+  while (n >= sizeof longword)
     {
       /* We tentatively exit the loop if adding MAGIC_BITS to
         LONGWORD fails to change any of the hole bits of LONGWORD.
     {
       /* We tentatively exit the loop if adding MAGIC_BITS to
         LONGWORD fails to change any of the hole bits of LONGWORD.
@@ -162,26 +159,28 @@ memchr (s, c, n)
          const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
 
          if (cp[0] == c)
          const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
 
          if (cp[0] == c)
-           return (__ptr_t) cp;
+           return (void *) cp;
          if (cp[1] == c)
          if (cp[1] == c)
-           return (__ptr_t) &cp[1];
+           return (void *) &cp[1];
          if (cp[2] == c)
          if (cp[2] == c)
-           return (__ptr_t) &cp[2];
+           return (void *) &cp[2];
          if (cp[3] == c)
          if (cp[3] == c)
-           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
+           return (void *) &cp[3];
+         if (4 < sizeof longword && cp[4] == c)
+           return (void *) &cp[4];
+         if (5 < sizeof longword && cp[5] == c)
+           return (void *) &cp[5];
+         if (6 < sizeof longword && cp[6] == c)
+           return (void *) &cp[6];
+         if (7 < sizeof longword && cp[7] == c)
+           return (void *) &cp[7];
+         if (8 < sizeof longword)
+           for (i = 8; i < sizeof longword; i++)
+             if (cp[i] == c)
+               return (void *) &cp[i];
        }
 
        }
 
-      n -= sizeof (longword);
+      n -= sizeof longword;
     }
 
   char_ptr = (const unsigned char *) longword_ptr;
     }
 
   char_ptr = (const unsigned char *) longword_ptr;
@@ -189,10 +188,13 @@ memchr (s, c, n)
   while (n-- > 0)
     {
       if (*char_ptr == c)
   while (n-- > 0)
     {
       if (*char_ptr == c)
-       return (__ptr_t) char_ptr;
+       return (void *) char_ptr;
       else
        ++char_ptr;
     }
 
   return 0;
 }
       else
        ++char_ptr;
     }
 
   return 0;
 }
+#ifdef weak_alias
+weak_alias (__memchr, BP_SYM (memchr))
+#endif