maint: update all copyright year number ranges
[gnulib.git] / lib / memcmp.c
index 98dcb76..ecba128 100644 (file)
@@ -1,12 +1,14 @@
-/* Copyright (C) 1991, 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1993, 1995, 1997-1998, 2003, 2006, 2009-2013 Free
+   Software Foundation, Inc.
+
    Contributed by Torbjorn Granlund (tege@sics.se).
 
    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
-   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,
    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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-   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
 
-#undef __ptr_t
-#if defined __cplusplus || (defined __STDC__ && __STDC__)
-# define __ptr_t       void *
-#else /* Not C++ or ANSI C.  */
-# undef        const
-# define const
-# define __ptr_t       char *
-#endif /* C++ or ANSI C.  */
-
-#ifndef __P
-# if defined __GNUC__ || (defined __STDC__ && __STDC__)
-#  define __P(args) args
-# else
-#  define __P(args) ()
-# endif  /* GCC.  */
-#endif  /* Not __P.  */
+#include <string.h>
 
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#endif
+#include <stdint.h>
 
 #undef memcmp
 
 #ifdef _LIBC
 
 # include <memcopy.h>
+# include <endian.h>
+
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN
+# endif
 
-#else  /* Not in the GNU C library.  */
+#else   /* Not in the GNU C library.  */
 
 # include <sys/types.h>
 
 /* Type to use for aligned memory operations.
    This should normally be the biggest type supported by a single load
    and store.  Must be an unsigned type.  */
-# define op_t  unsigned long int
-# define OPSIZ (sizeof(op_t))
+# define op_t   unsigned long int
+# define OPSIZ  (sizeof(op_t))
 
 /* Threshold value for when to enter the unrolled loops.  */
-# define OP_T_THRES    16
+# define OP_T_THRES     16
 
 /* Type to use for unaligned operations.  */
 typedef unsigned char byte;
@@ -72,12 +60,12 @@ typedef unsigned char byte;
 #  define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
 # endif
 
-#endif /* In the GNU C library.  */
+#endif  /* In the GNU C library.  */
 
 #ifdef WORDS_BIGENDIAN
 # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
 #else
-# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
+# define CMP_LT_OR_GT(a, b) memcmp_bytes (a, b)
 #endif
 
 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
@@ -98,22 +86,20 @@ typedef unsigned char byte;
    A and B are known to be different.
    This is needed only on little-endian machines.  */
 
-static int memcmp_bytes __P((op_t, op_t));
-
 # ifdef  __GNUC__
 __inline
 # endif
 static int
-memcmp_bytes (long unsigned int a, long unsigned int b)
+memcmp_bytes (op_t a, op_t b)
 {
-  long int srcp1 = (long int) &a;
-  long int srcp2 = (long int) &b;
+  const byte *srcp1 = (const byte *) &a;
+  const byte *srcp2 = (const byte *) &b;
   op_t a0, b0;
 
   do
     {
-      a0 = ((byte *) srcp1)[0];
-      b0 = ((byte *) srcp2)[0];
+      a0 = srcp1[0];
+      b0 = srcp2[0];
       srcp1 += 1;
       srcp2 += 1;
     }
@@ -122,16 +108,14 @@ memcmp_bytes (long unsigned int a, long unsigned int b)
 }
 #endif
 
-static int memcmp_common_alignment __P((long, long, size_t));
-
-/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
+/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN 'op_t'
    objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
-   memory operations on `op_t's.  */
-#ifdef __GNUC__
+   memory operations on 'op_t's.  */
+#ifdef __GNUC__
 __inline
 #endif
 static int
-memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
+memcmp_common_alignment (uintptr_t srcp1, uintptr_t srcp2, size_t len)
 {
   op_t a0, a1;
   op_t b0, b1;
@@ -155,7 +139,7 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
       goto do2;
     case 0:
       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-       return 0;
+        return 0;
       a0 = ((op_t *) srcp1)[0];
       b0 = ((op_t *) srcp2)[0];
       goto do3;
@@ -166,7 +150,7 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
       srcp2 += OPSIZ;
       len -= 1;
       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-       goto do0;
+        goto do0;
       /* Fall through.  */
     }
 
@@ -175,25 +159,25 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
       a0 = ((op_t *) srcp1)[0];
       b0 = ((op_t *) srcp2)[0];
       if (a1 != b1)
-       return CMP_LT_OR_GT (a1, b1);
+        return CMP_LT_OR_GT (a1, b1);
 
     do3:
       a1 = ((op_t *) srcp1)[1];
       b1 = ((op_t *) srcp2)[1];
       if (a0 != b0)
-       return CMP_LT_OR_GT (a0, b0);
+        return CMP_LT_OR_GT (a0, b0);
 
     do2:
       a0 = ((op_t *) srcp1)[2];
       b0 = ((op_t *) srcp2)[2];
       if (a1 != b1)
-       return CMP_LT_OR_GT (a1, b1);
+        return CMP_LT_OR_GT (a1, b1);
 
     do1:
       a1 = ((op_t *) srcp1)[3];
       b1 = ((op_t *) srcp2)[3];
       if (a0 != b0)
-       return CMP_LT_OR_GT (a0, b0);
+        return CMP_LT_OR_GT (a0, b0);
 
       srcp1 += 4 * OPSIZ;
       srcp2 += 4 * OPSIZ;
@@ -209,16 +193,14 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
   return 0;
 }
 
-static int memcmp_not_common_alignment __P((long, long, size_t));
-
 /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
-   `op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
-   operations on `op_t', but SRCP1 *should be unaligned*.  */
-#ifdef __GNUC__
+   'op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
+   operations on 'op_t', but SRCP1 *should be unaligned*.  */
+#ifdef __GNUC__
 __inline
 #endif
 static int
-memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
+memcmp_not_common_alignment (uintptr_t srcp1, uintptr_t srcp2, size_t len)
 {
   op_t a0, a1, a2, a3;
   op_t b0, b1, b2, b3;
@@ -231,7 +213,7 @@ memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
   shl = 8 * (srcp1 % OPSIZ);
   shr = 8 * OPSIZ - shl;
 
-  /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
+  /* Make SRCP1 aligned by rounding it down to the beginning of the 'op_t'
      it points in the middle of.  */
   srcp1 &= -OPSIZ;
 
@@ -255,7 +237,7 @@ memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
       goto do2;
     case 0:
       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-       return 0;
+        return 0;
       a3 = ((op_t *) srcp1)[0];
       a0 = ((op_t *) srcp1)[1];
       b0 = ((op_t *) srcp2)[0];
@@ -269,7 +251,7 @@ memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
       srcp2 += 1 * OPSIZ;
       len -= 1;
       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-       goto do0;
+        goto do0;
       /* Fall through.  */
     }
 
@@ -277,30 +259,30 @@ memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
     {
       a0 = ((op_t *) srcp1)[0];
       b0 = ((op_t *) srcp2)[0];
-      x = MERGE(a2, shl, a3, shr);
+      x = MERGE (a2, shl, a3, shr);
       if (x != b3)
-       return CMP_LT_OR_GT (x, b3);
+        return CMP_LT_OR_GT (x, b3);
 
     do3:
       a1 = ((op_t *) srcp1)[1];
       b1 = ((op_t *) srcp2)[1];
-      x = MERGE(a3, shl, a0, shr);
+      x = MERGE (a3, shl, a0, shr);
       if (x != b0)
-       return CMP_LT_OR_GT (x, b0);
+        return CMP_LT_OR_GT (x, b0);
 
     do2:
       a2 = ((op_t *) srcp1)[2];
       b2 = ((op_t *) srcp2)[2];
-      x = MERGE(a0, shl, a1, shr);
+      x = MERGE (a0, shl, a1, shr);
       if (x != b1)
-       return CMP_LT_OR_GT (x, b1);
+        return CMP_LT_OR_GT (x, b1);
 
     do1:
       a3 = ((op_t *) srcp1)[3];
       b3 = ((op_t *) srcp2)[3];
-      x = MERGE(a1, shl, a2, shr);
+      x = MERGE (a1, shl, a2, shr);
       if (x != b2)
-       return CMP_LT_OR_GT (x, b2);
+        return CMP_LT_OR_GT (x, b2);
 
       srcp1 += 4 * OPSIZ;
       srcp2 += 4 * OPSIZ;
@@ -311,7 +293,7 @@ memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len)
   /* This is the right position for do0.  Please don't move
      it into the loop.  */
  do0:
-  x = MERGE(a2, shl, a3, shr);
+  x = MERGE (a2, shl, a3, shr);
   if (x != b3)
     return CMP_LT_OR_GT (x, b3);
   return 0;
@@ -322,36 +304,36 @@ rpl_memcmp (const void *s1, const void *s2, size_t len)
 {
   op_t a0;
   op_t b0;
-  long int srcp1 = (long int) s1;
-  long int srcp2 = (long int) s2;
+  uintptr_t srcp1 = (uintptr_t) s1;
+  uintptr_t srcp2 = (uintptr_t) s2;
   op_t res;
 
   if (len >= OP_T_THRES)
     {
       /* There are at least some bytes to compare.  No need to test
-        for LEN == 0 in this alignment loop.  */
+         for LEN == 0 in this alignment loop.  */
       while (srcp2 % OPSIZ != 0)
-       {
-         a0 = ((byte *) srcp1)[0];
-         b0 = ((byte *) srcp2)[0];
-         srcp1 += 1;
-         srcp2 += 1;
-         res = a0 - b0;
-         if (res != 0)
-           return res;
-         len -= 1;
-       }
-
-      /* SRCP2 is now aligned for memory operations on `op_t'.
-        SRCP1 alignment determines if we can do a simple,
-        aligned compare or need to shuffle bits.  */
+        {
+          a0 = ((byte *) srcp1)[0];
+          b0 = ((byte *) srcp2)[0];
+          srcp1 += 1;
+          srcp2 += 1;
+          res = a0 - b0;
+          if (res != 0)
+            return res;
+          len -= 1;
+        }
+
+      /* SRCP2 is now aligned for memory operations on 'op_t'.
+         SRCP1 alignment determines if we can do a simple,
+         aligned compare or need to shuffle bits.  */
 
       if (srcp1 % OPSIZ == 0)
-       res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
+        res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
       else
-       res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
+        res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
       if (res != 0)
-       return res;
+        return res;
 
       /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
       srcp1 += len & -OPSIZ;
@@ -368,7 +350,7 @@ rpl_memcmp (const void *s1, const void *s2, size_t len)
       srcp2 += 1;
       res = a0 - b0;
       if (res != 0)
-       return res;
+        return res;
       len -= 1;
     }