Blob Blame History Raw
--- valgrind/memcheck/mc_replace_strmem.c.jj	2010-10-20 22:19:25.000000000 +0200
+++ valgrind/memcheck/mc_replace_strmem.c	2010-11-12 10:07:58.559830040 +0100
@@ -431,6 +430,111 @@ STRCMP(VG_Z_LD64_SO_1,            strcmp
 #endif
 
 
+#if defined(VGO_linux)
+extern int tolower (int);
+
+#define STRCASECMP(soname, fnname) \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2 ); \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2 ) \
+   { \
+      register unsigned char c1; \
+      register unsigned char c2; \
+      while (True) { \
+         c1 = tolower(*(unsigned char *)s1); \
+         c2 = tolower(*(unsigned char *)s2); \
+         if (c1 != c2) break; \
+         if (c1 == 0) break; \
+         s1++; s2++; \
+      } \
+      if (c1 < c2) return -1; \
+      if (c1 > c2) return 1; \
+      return 0; \
+   }
+
+STRCASECMP(VG_Z_LIBC_SONAME,          strcasecmp)
+STRCASECMP(VG_Z_LIBC_SONAME,          __GI_strcasecmp)
+
+
+#define STRNCASECMP(soname, fnname) \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, SizeT nmax ); \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, SizeT nmax ) \
+   { \
+      register unsigned char c1; \
+      register unsigned char c2; \
+      SizeT n = 0; \
+      while (True) { \
+         if (n >= nmax) return 0; \
+         if (*s1 == 0 && *s2 == 0) return 0; \
+         if (*s1 == 0) return -1; \
+         if (*s2 == 0) return 1; \
+         c1 = tolower(*(unsigned char*)s1); \
+         c2 = tolower(*(unsigned char*)s2); \
+         if (c1 < c2) return -1; \
+         if (c1 > c2) return 1; \
+         s1++; s2++; n++; \
+      } \
+   }
+
+STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
+STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
+
+extern int tolower_l (int, void *) __attribute__((weak));
+
+#define STRCASECMP_L(soname, fnname) \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, void* l ); \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, void* l ) \
+   { \
+      register unsigned char c1; \
+      register unsigned char c2; \
+      while (True) { \
+         c1 = tolower_l(*(unsigned char *)s1, l); \
+         c2 = tolower_l(*(unsigned char *)s2, l); \
+         if (c1 != c2) break; \
+         if (c1 == 0) break; \
+         s1++; s2++; \
+      } \
+      if (c1 < c2) return -1; \
+      if (c1 > c2) return 1; \
+      return 0; \
+   }
+
+STRCASECMP_L(VG_Z_LIBC_SONAME,          strcasecmp_l)
+STRCASECMP_L(VG_Z_LIBC_SONAME,          __GI_strcasecmp_l)
+
+
+#define STRNCASECMP_L(soname, fnname) \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, SizeT nmax, void* l ); \
+   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+          ( const char* s1, const char* s2, SizeT nmax, void* l ) \
+   { \
+      register unsigned char c1; \
+      register unsigned char c2; \
+      SizeT n = 0; \
+      while (True) { \
+         if (n >= nmax) return 0; \
+         if (*s1 == 0 && *s2 == 0) return 0; \
+         if (*s1 == 0) return -1; \
+         if (*s2 == 0) return 1; \
+         c1 = tolower_l(*(unsigned char*)s1, l); \
+         c2 = tolower_l(*(unsigned char*)s2, l); \
+         if (c1 < c2) return -1; \
+         if (c1 > c2) return 1; \
+         s1++; s2++; n++; \
+      } \
+   }
+
+STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
+STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
+#endif
+
+
 #define MEMCHR(soname, fnname) \
    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \