Subject: bug#11786: closed (Re: bug#11786: Use c_strcasecmp for portable ASCII case-insensitive comparison)

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 06 Jul 2012 21:20:02 +0000

Your bug report

#11786: Use c_strcasecmp for portable ASCII case-insensitive comparison

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
11786: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11786
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#11786: Use c_strcasecmp for portable ASCII case-insensitive comparison
From: Paul Eggert <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]
Date: Fri, 06 Jul 2012 14:14:06 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

No further comment, and there is a bug to fix here,
with no other proposal on the table.

I refactored to trim down the size of the patch, to
make it less intrusive into the src directory and
I hope to ameliorate at least some of the objections,
and installed the result as trunk bzr 108922.  Since
the bug is now fixed I'll mark it as done, but of course
further code improvements are welcome.

Subject: Use c_strcasecmp for portable ASCII case-insensitive comparison
From: Paul Eggert <[email-masked]>
To: [email-masked]
Date: Mon, 25 Jun 2012 18:42:08 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Tags: patch

Emacs currently use 'strcasecmp' and 'strncasecmp' for
case-insensitive comparison but these have problems in multibyte
locales.  In practice Emacs code really just wants a C-locale
version of these functions so I'm planning on installing the
following patch after some more testing.  I'm giving some
heads-up as this affects the Microsoft ports.

=== modified file 'ChangeLog'
--- ChangeLog	2012-06-26 01:05:39 +0000
+++ ChangeLog	2012-06-26 01:35:27 +0000
@@ -1,5 +1,14 @@
 2012-06-26  Paul Eggert  <[email-masked]>
 
+	Use c_strcasecmp for portable ASCII case-insensitive comparison.
+	This is safer than strcasecmp, which has unspecified behavior
+	outside the POSIX locale and in practice sometimes does not work
+	in multibyte locales.  Similarly for c_strncasecmp and strncasecmp.
+	* configure.in (strcasecmp, strncasecmp): Remove checks.
+	* lib/c-ctype.c, lib/c-ctype.h, lib/c-strcase.h, lib/c-strcasecmp.c:
+	* lib/c-strncasecmp.c: New files, taken from gnulib.
+	* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
 	Clean out last vestiges of the old HAVE_CONFIG_H stuff.
 	* lib/makefile.w32-in (LOCAL_FLAGS): Remove -DHAVE_CONFIG_H.

=== modified file 'admin/ChangeLog'
--- admin/ChangeLog	2012-06-24 16:18:41 +0000
+++ admin/ChangeLog	2012-06-26 01:35:27 +0000
@@ -1,3 +1,8 @@
+2012-06-26  Paul Eggert  <[email-masked]>
+
+	Use c_strcasecmp for portable ASCII case-insensitive comparison.
+	* merge-gnulib (GNULIB_MODULES): Add c-strcase.
+
 2012-06-24  Dmitry Antipov  <[email-masked]>
 
 	First Coccinelle semantic patch.

=== modified file 'admin/merge-gnulib'
--- admin/merge-gnulib	2012-06-22 21:17:42 +0000
+++ admin/merge-gnulib	2012-06-26 01:35:27 +0000
@@ -26,7 +26,7 @@
 GNULIB_URL=git://git.savannah.gnu.org/gnulib.git
 
 GNULIB_MODULES='
-  alloca-opt
+  alloca-opt c-strcase
   careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
   dtoastr dtotimespec dup2
   filemode getloadavg getopt-gnu gettime gettimeofday

=== modified file 'configure.in'
--- configure.in	2012-06-25 14:07:04 +0000
+++ configure.in	2012-06-26 01:35:27 +0000
@@ -2671,7 +2671,6 @@
 difftime posix_memalign \
 getpwent endpwent getgrent endgrent \
 touchlock \
-strcasecmp strncasecmp \
 cfmakeraw cfsetspeed copysign __executable_start)
 
 dnl Cannot use AC_CHECK_FUNCS

=== modified file 'lib-src/ChangeLog'
--- lib-src/ChangeLog	2012-06-26 01:05:39 +0000
+++ lib-src/ChangeLog	2012-06-26 01:35:27 +0000
@@ -1,5 +1,10 @@
 2012-06-26  Paul Eggert  <[email-masked]>
 
+	Use c_strcasecmp for portable ASCII case-insensitive comparison.
+	* etags.c: Include c-strcase.h.
+	(etags_strcasecmp, etags_strncasecmp): Remove.
+	All uses replaced with c_strcasecmp and c_strncasecmp.
+
 	Clean out last vestiges of the old HAVE_CONFIG_H stuff.
 	* Makefile.in (BASE_CFLAGS):
 	* makefile.w32-in (LOCAL_FLAGS): Remove -DHAVE_CONFIG_H.

=== modified file 'lib-src/etags.c'
--- lib-src/etags.c	2012-06-26 01:05:39 +0000
+++ lib-src/etags.c	2012-06-26 01:35:27 +0000
@@ -144,6 +144,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <c-strcase.h>
 
 #include <assert.h>
 #ifdef NDEBUG
@@ -174,9 +175,9 @@
 #endif
 
 #define streq(s,t)	(assert ((s)!=NULL || (t)!=NULL), !strcmp (s, t))
-#define strcaseeq(s,t)	(assert ((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
+#define strcaseeq(s,t)	(assert ((s)!=NULL && (t)!=NULL), !c_strcasecmp (s, t))
 #define strneq(s,t,n)	(assert ((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
-#define strncaseeq(s,t,n) (assert ((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
+#define strncaseeq(s,t,n) (assert ((s)!=NULL && (t)!=NULL), !c_strncasecmp (s, t, n))
 
 #define CHARS 256		/* 2^sizeof(char) */
 #define CHAR(x)		((unsigned int)(x) & (CHARS - 1))
@@ -375,16 +376,6 @@
 static char *savestr (const char *);
 static char *etags_strchr (const char *, int);
 static char *etags_strrchr (const char *, int);
-#ifdef HAVE_STRCASECMP
-#define etags_strcasecmp(x,y) strcasecmp ((x), (y))
-#else
-static int etags_strcasecmp (const char *, const char *);
-#endif
-#ifdef HAVE_STRNCASECMP
-#define etags_strncasecmp(x,y,z) strncasecmp ((x), (y), (z))
-#else
-static int etags_strncasecmp (const char *, const char *, int);
-#endif
 static char *etags_getcwd (void);
 static char *relative_filename (char *, char *);
 static char *absolute_filename (char *, char *);
@@ -6314,52 +6305,6 @@
   return NULL;
 }
 
-#ifndef HAVE_STRCASECMP
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- *
- * Same as BSD's strcasecmp, included for portability.
- */
-static int
-etags_strcasecmp (register const char *s1, register const char *s2)
-{
-  while (*s1 != '\0'
-	 && (ISALPHA (*s1) && ISALPHA (*s2)
-	     ? lowcase (*s1) == lowcase (*s2)
-	     : *s1 == *s2))
-    s1++, s2++;
-
-  return (ISALPHA (*s1) && ISALPHA (*s2)
-	  ? lowcase (*s1) - lowcase (*s2)
-	  : *s1 - *s2);
-}
-#endif /* HAVE_STRCASECMP */
-
-#ifndef HAVE_STRNCASECMP
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- * Stop after a given number of characters
- *
- * Same as BSD's strncasecmp, included for portability.
- */
-static int
-etags_strncasecmp (register const char *s1, register const char *s2, register int n)
-{
-  while (*s1 != '\0' && n-- > 0
-	 && (ISALPHA (*s1) && ISALPHA (*s2)
-	     ? lowcase (*s1) == lowcase (*s2)
-	     : *s1 == *s2))
-    s1++, s2++;
-
-  if (n < 0)
-    return 0;
-  else
-    return (ISALPHA (*s1) && ISALPHA (*s2)
-	    ? lowcase (*s1) - lowcase (*s2)
-	    : *s1 - *s2);
-}
-#endif /* HAVE_STRCASECMP */
-
 /* Skip spaces (end of string is not space), return new pointer. */
 static char *
 skip_spaces (char *cp)

=== added file 'lib/c-ctype.c'
--- lib/c-ctype.c	1970-01-01 00:00:00 +0000
+++ lib/c-ctype.c	2012-06-26 01:35:27 +0000
@@ -0,0 +1,395 @@
+/* Character handling in C locale.
+
+   Copyright 2000-2003, 2006, 2009-2012 Free Software Foundation, Inc.
+
+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 3 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#define NO_C_CTYPE_MACROS
+#include "c-ctype.h"
+
+/* The function isascii is not locale dependent. Its use in EBCDIC is
+   questionable. */
+bool
+c_isascii (int c)
+{
+  return (c >= 0x00 && c <= 0x7f);
+}
+
+bool
+c_isalnum (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c >= '0' && c <= '9')
+          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'));
+#else
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'Z')
+          || (c >= 'a' && c <= 'z'));
+#endif
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isalpha (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z');
+#else
+  return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
+#endif
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isblank (int c)
+{
+  return (c == ' ' || c == '\t');
+}
+
+bool
+c_iscntrl (int c)
+{
+#if C_CTYPE_ASCII
+  return ((c & ~0x1f) == 0 || c == 0x7f);
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 0;
+    default:
+      return 1;
+    }
+#endif
+}
+
+bool
+c_isdigit (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS
+  return (c >= '0' && c <= '9');
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_islower (int c)
+{
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z');
+#else
+  switch (c)
+    {
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isgraph (int c)
+{
+#if C_CTYPE_ASCII
+  return (c >= '!' && c <= '~');
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isprint (int c)
+{
+#if C_CTYPE_ASCII
+  return (c >= ' ' && c <= '~');
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_ispunct (int c)
+{
+#if C_CTYPE_ASCII
+  return ((c >= '!' && c <= '~')
+          && !((c >= '0' && c <= '9')
+               || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')));
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isspace (int c)
+{
+  return (c == ' ' || c == '\t'
+          || c == '\n' || c == '\v' || c == '\f' || c == '\r');
+}
+
+bool
+c_isupper (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+  return (c >= 'A' && c <= 'Z');
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isxdigit (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c >= '0' && c <= '9')
+          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F'));
+#else
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'F')
+          || (c >= 'a' && c <= 'f'));
+#endif
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_tolower (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
+#else
+  switch (c)
+    {
+    case 'A': return 'a';
+    case 'B': return 'b';
+    case 'C': return 'c';
+    case 'D': return 'd';
+    case 'E': return 'e';
+    case 'F': return 'f';
+    case 'G': return 'g';
+    case 'H': return 'h';
+    case 'I': return 'i';
+    case 'J': return 'j';
+    case 'K': return 'k';
+    case 'L': return 'l';
+    case 'M': return 'm';
+    case 'N': return 'n';
+    case 'O': return 'o';
+    case 'P': return 'p';
+    case 'Q': return 'q';
+    case 'R': return 'r';
+    case 'S': return 's';
+    case 'T': return 't';
+    case 'U': return 'u';
+    case 'V': return 'v';
+    case 'W': return 'w';
+    case 'X': return 'x';
+    case 'Y': return 'y';
+    case 'Z': return 'z';
+    default: return c;
+    }
+#endif
+}
+
+int
+c_toupper (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
+#else
+  switch (c)
+    {
+    case 'a': return 'A';
+    case 'b': return 'B';
+    case 'c': return 'C';
+    case 'd': return 'D';
+    case 'e': return 'E';
+    case 'f': return 'F';
+    case 'g': return 'G';
+    case 'h': return 'H';
+    case 'i': return 'I';
+    case 'j': return 'J';
+    case 'k': return 'K';
+    case 'l': return 'L';
+    case 'm': return 'M';
+    case 'n': return 'N';
+    case 'o': return 'O';
+    case 'p': return 'P';
+    case 'q': return 'Q';
+    case 'r': return 'R';
+    case 's': return 'S';
+    case 't': return 'T';
+    case 'u': return 'U';
+    case 'v': return 'V';
+    case 'w': return 'W';
+    case 'x': return 'X';
+    case 'y': return 'Y';
+    case 'z': return 'Z';
+    default: return c;
+    }
+#endif
+}

=== added file 'lib/c-ctype.h'
--- lib/c-ctype.h	1970-01-01 00:00:00 +0000
+++ lib/c-ctype.h	2012-06-26 01:35:27 +0000
@@ -0,0 +1,294 @@
+/* Character handling in C locale.
+
+   These functions work like the corresponding functions in <ctype.h>,
+   except that they have the C (POSIX) locale hardwired, whereas the
+   <ctype.h> functions' behaviour depends on the current locale set via
+   setlocale.
+
+   Copyright (C) 2000-2003, 2006, 2008-2012 Free Software Foundation, Inc.
+
+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 3 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef C_CTYPE_H
+#define C_CTYPE_H
+
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* The functions defined in this file assume the "C" locale and a character
+   set without diacritics (ASCII-US or EBCDIC-US or something like that).
+   Even if the "C" locale on a particular system is an extension of the ASCII
+   character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+   is ISO-8859-1), the functions in this file recognize only the ASCII
+   characters.  */
+
+
+/* Check whether the ASCII optimizations apply. */
+
+/* ANSI C89 (and ISO C99 5.2.1.3 too) already guarantees that
+   '0', '1', ..., '9' have consecutive integer values.  */
+#define C_CTYPE_CONSECUTIVE_DIGITS 1
+
+#if ('A' <= 'Z') \
+    && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \
+    && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \
+    && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \
+    && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \
+    && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \
+    && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \
+    && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \
+    && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \
+    && ('Y' + 1 == 'Z')
+#define C_CTYPE_CONSECUTIVE_UPPERCASE 1
+#endif
+
+#if ('a' <= 'z') \
+    && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \
+    && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \
+    && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \
+    && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \
+    && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \
+    && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \
+    && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \
+    && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \
+    && ('y' + 1 == 'z')
+#define C_CTYPE_CONSECUTIVE_LOWERCASE 1
+#endif
+
+#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+    && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+    && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+    && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+    && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+    && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+    && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+    && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+    && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+    && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+    && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+    && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+    && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+    && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+    && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+    && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+    && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+    && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+    && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+    && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+    && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+    && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+    && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
+/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
+   Testing the value of '\n' and '\r' is not relevant.  */
+#define C_CTYPE_ASCII 1
+#endif
+
+
+/* Function declarations. */
+
+/* Unlike the functions in <ctype.h>, which require an argument in the range
+   of the 'unsigned char' type, the functions here operate on values that are
+   in the 'unsigned char' range or in the 'char' range.  In other words,
+   when you have a 'char' value, you need to cast it before using it as
+   argument to a <ctype.h> function:
+
+         const char *s = ...;
+         if (isalpha ((unsigned char) *s)) ...
+
+   but you don't need to cast it for the functions defined in this file:
+
+         const char *s = ...;
+         if (c_isalpha (*s)) ...
+ */
+
+extern bool c_isascii (int c) _GL_ATTRIBUTE_CONST; /* not locale dependent */
+
+extern bool c_isalnum (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isalpha (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isblank (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_iscntrl (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isdigit (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_islower (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isgraph (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isprint (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_ispunct (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isspace (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isupper (int c) _GL_ATTRIBUTE_CONST;
+extern bool c_isxdigit (int c) _GL_ATTRIBUTE_CONST;
+
+extern int c_tolower (int c) _GL_ATTRIBUTE_CONST;
+extern int c_toupper (int c) _GL_ATTRIBUTE_CONST;
+
+
+#if defined __GNUC__ && defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ && !defined NO_C_CTYPE_MACROS
+
+/* ASCII optimizations. */
+
+#undef c_isascii
+#define c_isascii(c) \
+  ({ int __c = (c); \
+     (__c >= 0x00 && __c <= 0x7f); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isalnum
+#define c_isalnum(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z')); \
+   })
+#else
+#undef c_isalnum
+#define c_isalnum(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'Z') \
+      || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isalpha
+#define c_isalpha(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z'); \
+   })
+#else
+#undef c_isalpha
+#define c_isalpha(c) \
+  ({ int __c = (c); \
+     ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+#endif
+
+#undef c_isblank
+#define c_isblank(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t'); \
+   })
+
+#if C_CTYPE_ASCII
+#undef c_iscntrl
+#define c_iscntrl(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x1f) == 0 || __c == 0x7f); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS
+#undef c_isdigit
+#define c_isdigit(c) \
+  ({ int __c = (c); \
+     (__c >= '0' && __c <= '9'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+#undef c_islower
+#define c_islower(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_isgraph
+#define c_isgraph(c) \
+  ({ int __c = (c); \
+     (__c >= '!' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_isprint
+#define c_isprint(c) \
+  ({ int __c = (c); \
+     (__c >= ' ' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_ispunct
+#define c_ispunct(c) \
+  ({ int _c = (c); \
+     (c_isgraph (_c) && ! c_isalnum (_c)); \
+   })
+#endif
+
+#undef c_isspace
+#define c_isspace(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t' \
+      || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+#undef c_isupper
+#define c_isupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isxdigit
+#define c_isxdigit(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'F')); \
+   })
+#else
+#undef c_isxdigit
+#define c_isxdigit(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'F') \
+      || (__c >= 'a' && __c <= 'f')); \
+   })
+#endif
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#undef c_tolower
+#define c_tolower(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \
+   })
+#undef c_toupper
+#define c_toupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \
+   })
+#endif
+
+#endif /* optimizing for speed */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* C_CTYPE_H */

=== added file 'lib/c-strcase.h'
--- lib/c-strcase.h	1970-01-01 00:00:00 +0000
+++ lib/c-strcase.h	2012-06-26 01:35:27 +0000
@@ -0,0 +1,56 @@
+/* Case-insensitive string comparison functions in C locale.
+   Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2012 Free Software
+   Foundation, Inc.
+
+   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 3, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef C_STRCASE_H
+#define C_STRCASE_H
+
+#include <stddef.h>
+
+
+/* The functions defined in this file assume the "C" locale and a character
+   set without diacritics (ASCII-US or EBCDIC-US or something like that).
+   Even if the "C" locale on a particular system is an extension of the ASCII
+   character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+   is ISO-8859-1), the functions in this file recognize only the ASCII
+   characters.  More precisely, one of the string arguments must be an ASCII
+   string; the other one can also contain non-ASCII characters (but then
+   the comparison result will be nonzero).  */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than, equal to or greater
+   than S2.  */
+extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE;
+
+/* Compare no more than N characters of strings S1 and S2, ignoring case,
+   returning less than, equal to or greater than zero if S1 is
+   lexicographically less than, equal to or greater than S2.  */
+extern int c_strncasecmp (const char *s1, const char *s2, size_t n)
+  _GL_ATTRIBUTE_PURE;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* C_STRCASE_H */

=== added file 'lib/c-strcasecmp.c'
--- lib/c-strcasecmp.c	1970-01-01 00:00:00 +0000
+++ lib/c-strcasecmp.c	2012-06-26 01:35:27 +0000
@@ -0,0 +1,56 @@
+/* c-strcasecmp.c -- case insensitive string comparator in C locale
+   Copyright (C) 1998-1999, 2005-2006, 2009-2012 Free Software Foundation, Inc.
+
+   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 3, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#include "c-ctype.h"
+
+int
+c_strcasecmp (const char *s1, const char *s2)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      c1 = c_tolower (*p1);
+      c2 = c_tolower (*p2);
+
+      if (c1 == '\0')
+        break;
+
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  if (UCHAR_MAX <= INT_MAX)
+    return c1 - c2;
+  else
+    /* On machines where 'char' and 'int' are types of the same size, the
+       difference of two 'unsigned char' values - including the sign bit -
+       doesn't fit in an 'int'.  */
+    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}

=== added file 'lib/c-strncasecmp.c'
--- lib/c-strncasecmp.c	1970-01-01 00:00:00 +0000
+++ lib/c-strncasecmp.c	2012-06-26 01:35:27 +0000
@@ -0,0 +1,56 @@
+/* c-strncasecmp.c -- case insensitive string comparator in C locale
+   Copyright (C) 1998-1999, 2005-2006, 2009-2012 Free Software Foundation, Inc.
+
+   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 3, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#include "c-ctype.h"
+
+int
+c_strncasecmp (const char *s1, const char *s2, size_t n)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2 || n == 0)
+    return 0;
+
+  do
+    {
+      c1 = c_tolower (*p1);
+      c2 = c_tolower (*p2);
+
+      if (--n == 0 || c1 == '\0')
+        break;
+
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  if (UCHAR_MAX <= INT_MAX)
+    return c1 - c2;
+  else
+    /* On machines where 'char' and 'int' are types of the same size, the
+       difference of two 'unsigned char' values - including the sign bit -
+       doesn't fit in an 'int'.  */
+    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}

=== modified file 'lib/gnulib.mk'
--- lib/gnulib.mk	2012-06-22 21:17:42 +0000
+++ lib/gnulib.mk	2012-06-26 01:35:27 +0000
@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat --avoid=msvc-inval --avoid=msvc-nothrow --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timespec-add timespec-sub utimens warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat --avoid=msvc-inval --avoid=msvc-nothrow --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-strcase careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timespec-add timespec-sub utimens warnings

 MOSTLYCLEANFILES += core *.stackdump
@@ -64,6 +64,18 @@
 
 ## end   gnulib module allocator
 
+## begin gnulib module c-ctype
+
+libgnu_a_SOURCES += c-ctype.h c-ctype.c
+
+## end   gnulib module c-ctype
+
+## begin gnulib module c-strcase
+
+libgnu_a_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c
+
+## end   gnulib module c-strcase
+
 ## begin gnulib module careadlinkat
 
 libgnu_a_SOURCES += careadlinkat.c

=== modified file 'lwlib/ChangeLog'
--- lwlib/ChangeLog	2012-06-26 01:05:39 +0000
+++ lwlib/ChangeLog	2012-06-26 01:35:27 +0000
@@ -1,5 +1,9 @@
 2012-06-26  Paul Eggert  <[email-masked]>
 
+	Use c_strcasecmp for portable ASCII case-insensitive comparison.
+	* lwlib.c: Include c-strcase.h.
+	(lwlib_strcasecmp): Remove.  All uses replaced with c_strcasecmp.
+
 	Clean out last vestiges of the old HAVE_CONFIG_H stuff.
 	* Makefile.in (ALL_CFLAGS): Remove -DHAVE_CONFIG_H.
 	* lwlib-Xaw.c, lwlib-Xlw.c, lwlib-Xm.c, lwlib-utils.c, lwlib.c:

=== modified file 'lwlib/lwlib.c'
--- lwlib/lwlib.c	2012-06-26 01:05:39 +0000
+++ lwlib/lwlib.c	2012-06-26 01:35:27 +0000
@@ -24,6 +24,7 @@
 
 #include <setjmp.h>
 #include <lisp.h>
+#include <c-strcase.h>
 
 #include <sys/types.h>
 #include <stdio.h>
@@ -112,31 +113,6 @@
   return result;
 }
 
-#ifdef HAVE_STRCASECMP
-#define lwlib_strcasecmp(x,y) strcasecmp ((x), (y))
-#else
-
-/* Like strcmp but ignore differences in case.  */
-
-static int
-lwlib_strcasecmp (const char *s1, const char *s2)
-{
-  while (1)
-    {
-      int c1 = *s1++;
-      int c2 = *s2++;
-      if (isupper (c1))
-	c1 = tolower (c1);
-      if (isupper (c2))
-	c2 = tolower (c2);
-      if (c1 != c2)
-	return (c1 > c2 ? 1 : -1);
-      if (c1 == 0)
-	return 0;
-    }
-}
-#endif /* HAVE_STRCASECMP */
-
 static void
 safe_free_str (char *s)
 {
@@ -733,7 +709,7 @@
 {
   const widget_creation_entry* cur;
   for (cur = table; cur->type; cur++)
-    if (!lwlib_strcasecmp (type, cur->type))
+    if (!c_strcasecmp (type, cur->type))
       return cur->function;
   return NULL;
 }

=== modified file 'm4/gnulib-comp.m4'
--- m4/gnulib-comp.m4	2012-06-22 21:17:42 +0000
+++ m4/gnulib-comp.m4	2012-06-26 01:35:27 +0000
@@ -40,6 +40,8 @@
   AC_REQUIRE([gl_PROG_AR_RANLIB])
   # Code from module alloca-opt:
   # Code from module allocator:
+  # Code from module c-ctype:
+  # Code from module c-strcase:
   # Code from module careadlinkat:
   # Code from module clock-time:
   # Code from module crypto/md5:
@@ -518,6 +520,11 @@
   lib/alloca.in.h
   lib/allocator.c
   lib/allocator.h
+  lib/c-ctype.c
+  lib/c-ctype.h
+  lib/c-strcase.h
+  lib/c-strcasecmp.c
+  lib/c-strncasecmp.c
   lib/careadlinkat.c
   lib/careadlinkat.h
   lib/dosname.h

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-06-26 01:05:39 +0000
+++ src/ChangeLog	2012-06-26 01:35:27 +0000
@@ -1,5 +1,14 @@
 2012-06-26  Paul Eggert  <[email-masked]>
 
+	Use c_strcasecmp for portable ASCII case-insensitive comparison.
+	* dispextern.h (xstrcasecmp): Remove decl.
+	* dosfns.c, font.c, fontset.c, ftfont.c, image.c, nsfns.m, nsterm.m:
+	* process.c, w32.h, w32font.c, xfaces.c, xfns.c, xfont.c:
+	Include <c-strcase.h>.  Replace all uses of xstrcasecmp with
+	c_strcasecmp.
+	* xfaces.c (xstrcasecmp): Remove.
+	* xfont.c (compare_font_names): Rewrite to avoid casts.
+
 	Clean out last vestiges of the old HAVE_CONFIG_H stuff.
 	* Makefile.in (ALL_CFLAGS):
 	* makefile.w32-in (LOCAL_FLAGS): Remove -DHAVE_CONFIG_H.

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2012-06-25 14:07:04 +0000
+++ src/dispextern.h	2012-06-26 01:35:27 +0000
@@ -3216,11 +3216,6 @@
 char *choose_face_font (struct frame *, Lisp_Object *, Lisp_Object,
                         int *);
 void prepare_face_for_display (struct frame *, struct face *);
-#ifdef HAVE_STRCASECMP
-#define xstrcasecmp(x,y) strcasecmp ((x), (y))
-#else
-int xstrcasecmp (const char *, const char *);
-#endif
 int lookup_named_face (struct frame *, Lisp_Object, int);
 int lookup_basic_face (struct frame *, int);
 int smaller_face (struct frame *, int, int);

=== modified file 'src/dosfns.c'
--- src/dosfns.c	2012-06-19 16:56:28 +0000
+++ src/dosfns.c	2012-06-26 01:35:27 +0000
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <dos.h>
 #include <setjmp.h>
+#include <c-strcase.h>
 #include "lisp.h"
 #include "character.h"
 #include "buffer.h"
@@ -396,7 +397,7 @@
   int i;
 
   for (i = 0; i < sizeof (vga_colors) / sizeof (vga_colors[0]); i++)
-    if (xstrcasecmp (name, vga_colors[i]) == 0)
+    if (c_strcasecmp (name, vga_colors[i]) == 0)
       return i;
 
   return
@@ -764,4 +765,3 @@
   dos_decimal_point = 0;
 }
 #endif /* MSDOS */
-

=== modified file 'src/font.c'
--- src/font.c	2012-06-19 16:56:28 +0000
+++ src/font.c	2012-06-26 01:35:27 +0000
@@ -24,6 +24,7 @@
 #include <float.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <c-strcase.h>
 #include <setjmp.h>
 
 #include "lisp.h"
@@ -346,7 +347,7 @@
 	for (j = 1; j < ASIZE (AREF (table, i)); j++)
 	  {
 	    elt = AREF (AREF (table, i), j);
-	    if (xstrcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
+	    if (c_strcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
 	      return ((XINT (AREF (AREF (table, i), 0)) << 8)
 		      | (i << 4) | (j - 1));
 	  }

=== modified file 'src/fontset.c'
--- src/fontset.c	2012-06-16 12:24:15 +0000
+++ src/fontset.c	2012-06-26 01:35:27 +0000
@@ -29,6 +29,7 @@
 #include <config.h>
 #include <stdio.h>
 #include <setjmp.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 #include "blockinput.h"
@@ -1173,7 +1174,7 @@
       this_name = FONTSET_NAME (fontset);
       if (name_pattern == 1
 	  ? fast_string_match_ignore_case (name, this_name) >= 0
-	  : !xstrcasecmp (SSDATA (name), SSDATA (this_name)))
+	  : !c_strcasecmp (SSDATA (name), SSDATA (this_name)))
 	return i;
     }
   return -1;

=== modified file 'src/ftfont.c'
--- src/ftfont.c	2012-06-13 00:26:40 +0000
+++ src/ftfont.c	2012-06-26 01:35:27 +0000
@@ -26,6 +26,8 @@
 #include <fontconfig/fontconfig.h>
 #include <fontconfig/fcfreetype.h>
 
+#include <c-strcase.h>
+
 #include "lisp.h"
 #include "dispextern.h"
 #include "frame.h"
@@ -166,8 +168,8 @@
 
 #ifdef FC_FONTFORMAT
   if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
-      && xstrcasecmp ((char *) fcstr, "bdf") != 0
-      && xstrcasecmp ((char *) fcstr, "pcf") != 0)
+      && c_strcasecmp ((char *) fcstr, "bdf") != 0
+      && c_strcasecmp ((char *) fcstr, "pcf") != 0)
     /* Not a BDF nor PCF font.  */
     return Qnil;
 #endif
@@ -183,10 +185,10 @@
       end = newstr + (end - str);
       str = newstr;
     }
-  if (xstrcasecmp (str, "Regular") == 0
-      || xstrcasecmp (str, "Bold") == 0
-      || xstrcasecmp (str, "Oblique") == 0
-      || xstrcasecmp (str, "Italic") == 0)
+  if (c_strcasecmp (str, "Regular") == 0
+      || c_strcasecmp (str, "Bold") == 0
+      || c_strcasecmp (str, "Oblique") == 0
+      || c_strcasecmp (str, "Italic") == 0)
     return Qnil;
   adstyle = font_intern_prop (str, end - str, 1);
   if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
@@ -1051,12 +1053,12 @@
 
 	  if (! NILP (adstyle)
 	      && (NILP (this_adstyle)
-		  || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle)),
-				  SSDATA (SYMBOL_NAME (this_adstyle))) != 0))
+		  || c_strcasecmp (SSDATA (SYMBOL_NAME (adstyle)),
+				   SSDATA (SYMBOL_NAME (this_adstyle))) != 0))
 	    continue;
 	  if (langname
 	      && ! NILP (this_adstyle)
-	      && xstrcasecmp (langname, SSDATA (SYMBOL_NAME (this_adstyle))))
+	      && c_strcasecmp (langname, SSDATA (SYMBOL_NAME (this_adstyle))))
 	    continue;
 	}
       entity = ftfont_pattern_entity (fontset->fonts[i],
@@ -2625,13 +2627,13 @@
       if (len >= 4)
 	{
 	  str = (FcChar8 *) (SDATA (filename) + len - 4);
-	  if (xstrcasecmp ((char *) str, ".ttf") == 0)
+	  if (c_strcasecmp ((char *) str, ".ttf") == 0)
 	    return intern ("truetype");
-	  if (xstrcasecmp ((char *) str, ".pfb") == 0)
+	  if (c_strcasecmp ((char *) str, ".pfb") == 0)
 	    return intern ("type1");
-	  if (xstrcasecmp ((char *) str, ".pcf") == 0)
+	  if (c_strcasecmp ((char *) str, ".pcf") == 0)
 	    return intern ("pcf");
-	  if (xstrcasecmp ((char *) str, ".bdf") == 0)
+	  if (c_strcasecmp ((char *) str, ".bdf") == 0)
 	    return intern ("bdf");
 	}
     }

=== modified file 'src/image.c'
--- src/image.c	2012-06-24 17:39:14 +0000
+++ src/image.c	2012-06-26 01:35:27 +0000
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <math.h>
 #include <ctype.h>
+#include <c-strcase.h>
 #include <unistd.h>
 
 #ifdef HAVE_PNG
@@ -3969,7 +3970,7 @@
 
 	  if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
 	    {
-	      if (xstrcasecmp (SSDATA (XCDR (specified_color)), "None") == 0)
+	      if (c_strcasecmp (SSDATA (XCDR (specified_color)), "None") == 0)
 		color_val = Qt;
 	      else if (x_defined_color (f, SDATA (XCDR (specified_color)),
 					&cdef, 0))
@@ -3978,7 +3979,7 @@
 	}
       if (NILP (color_val) && max_key > 0)
 	{
-	  if (xstrcasecmp (max_color, "None") == 0)
+	  if (c_strcasecmp (max_color, "None") == 0)
 	    color_val = Qt;
 	  else if (x_defined_color (f, max_color, &cdef, 0))
 	    color_val = make_number (cdef.pixel);

=== modified file 'src/nsfns.m'
--- src/nsfns.m	2012-06-16 12:24:15 +0000
+++ src/nsfns.m	2012-06-26 01:35:27 +0000
@@ -33,6 +33,7 @@
 #include <signal.h>
 #include <math.h>
 #include <setjmp.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 #include "blockinput.h"
@@ -2227,8 +2228,8 @@
 
   res = ns_get_defaults_value (toCheck);
   return !res ? NULL :
-      (!strncasecmp (res, "YES", 3) ? "true" :
-          (!strncasecmp (res, "NO", 2) ? "false" : res));
+      (!c_strncasecmp (res, "YES", 3) ? "true" :
+          (!c_strncasecmp (res, "NO", 2) ? "false" : res));
 }

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2012-06-22 21:17:42 +0000
+++ src/nsterm.m	2012-06-26 01:35:27 +0000
@@ -36,6 +36,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <setjmp.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 #include "blockinput.h"
@@ -3855,9 +3856,9 @@
     {
       double f;
       char *pos;
-      if (strcasecmp (value, "YES") == 0)
+      if (c_strcasecmp (value, "YES") == 0)
         *result = yesval;
-      else if (strcasecmp (value, "NO") == 0)
+      else if (c_strcasecmp (value, "NO") == 0)
         *result = noval;
       else if (is_float && (f = strtod (value, &pos), pos != value))
         *result = make_float (f);
@@ -6074,7 +6075,7 @@
 
   if (nr_screens == 1)
     return [super constrainFrameRect:frameRect toScreen:screen];
-  
+
   if (f->output_data.ns->dont_constrain
       || ns_menu_bar_should_be_hidden ())
     return frameRect;

=== modified file 'src/process.c'
--- src/process.c	2012-06-24 20:34:48 +0000
+++ src/process.c	2012-06-26 01:35:27 +0000
@@ -31,6 +31,7 @@
 
 #include <unistd.h>
 #include <fcntl.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 
@@ -6124,7 +6125,7 @@
     }
 
 #define parse_signal(NAME, VALUE)		\
-  else if (!xstrcasecmp (name, NAME))		\
+  else if (!c_strcasecmp (name, NAME))		\
     XSETINT (sigcode, VALUE)
 
   if (INTEGERP (sigcode))

=== modified file 'src/w32.c'
--- src/w32.c	2012-06-23 16:56:47 +0000
+++ src/w32.c	2012-06-26 01:35:27 +0000
@@ -140,7 +140,7 @@
 #include "ndir.h"
 #include "w32heap.h"
 #include "systime.h"
-#include "dispextern.h"		/* for xstrcasecmp */
+#include "c-strcase.h"
 #include "coding.h"		/* for Vlocale_coding_system */
 
 #include "careadlinkat.h"
@@ -1025,7 +1025,7 @@
   if (!pw)
     return pw;
 
-  if (xstrcasecmp (name, pw->pw_name))
+  if (c_strcasecmp (name, pw->pw_name))
     return NULL;
 
   return pw;
@@ -1076,7 +1076,7 @@
     {
       strcpy (dflt_passwd.pw_name, uname);
       /* Determine a reasonable uid value.  */
-      if (xstrcasecmp ("administrator", uname) == 0)
+      if (c_strcasecmp ("administrator", uname) == 0)
 	{
 	  dflt_passwd.pw_uid = 500; /* well-known Administrator uid */
 	  dflt_passwd.pw_gid = 513; /* well-known None gid */
@@ -1118,7 +1118,7 @@
   else if (GetUserName (uname, &ulength))
     {
       strcpy (dflt_passwd.pw_name, uname);
-      if (xstrcasecmp ("administrator", uname) == 0)
+      if (c_strcasecmp ("administrator", uname) == 0)
 	dflt_passwd.pw_uid = 0;
       else
 	dflt_passwd.pw_uid = 123;
@@ -1674,7 +1674,7 @@
 	abort ();
       *p = 0;
 
-      if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
+      if ((p = strrchr (modname, '\\')) && c_strcasecmp (p, "\\bin") == 0)
 	{
 	  char buf[SET_ENV_BUF_SIZE];
 
@@ -1690,7 +1690,7 @@
       /* FIXME: should use substring of get_emacs_configuration ().
 	 But I don't think the Windows build supports alpha, mips etc
          anymore, so have taken the easy option for now.  */
-      else if (p && xstrcasecmp (p, "\\i386") == 0)
+      else if (p && c_strcasecmp (p, "\\i386") == 0)
 	{
 	  *p = 0;
 	  p = strrchr (modname, '\\');
@@ -1698,7 +1698,7 @@
 	    {
 	      *p = 0;
 	      p = strrchr (modname, '\\');
-	      if (p && xstrcasecmp (p, "\\src") == 0)
+	      if (p && c_strcasecmp (p, "\\src") == 0)
 		{
 		  char buf[SET_ENV_BUF_SIZE];
 
@@ -2101,7 +2101,7 @@
   volume_info_data * info;
 
   for (info = volume_cache; info; info = info->next)
-    if (xstrcasecmp (info->root_dir, root_dir) == 0)
+    if (c_strcasecmp (info->root_dir, root_dir) == 0)
       break;
   return info;
 }
@@ -2379,10 +2379,10 @@
   char * p = strrchr (name, '.');
   return
     (p != NULL
-     && (xstrcasecmp (p, ".exe") == 0 ||
-	 xstrcasecmp (p, ".com") == 0 ||
-	 xstrcasecmp (p, ".bat") == 0 ||
-	 xstrcasecmp (p, ".cmd") == 0));
+     && (c_strcasecmp (p, ".exe") == 0 ||
+	 c_strcasecmp (p, ".com") == 0 ||
+	 c_strcasecmp (p, ".bat") == 0 ||
+	 c_strcasecmp (p, ".cmd") == 0));
 }
 
 /* Emulate the Unix directory procedures opendir, closedir,
@@ -3450,7 +3450,7 @@
       if (dir_find_handle != INVALID_HANDLE_VALUE
 	  && strnicmp (name, dir_pathname, len) == 0
 	  && IS_DIRECTORY_SEP (name[len])
-	  && xstrcasecmp (name + len + 1, dir_static.d_name) == 0)
+	  && c_strcasecmp (name + len + 1, dir_static.d_name) == 0)
 	{
 	  /* This was the last entry returned by readdir.  */
 	  wfd = dir_find_data;
@@ -3673,10 +3673,10 @@
 #if 0 /* no way of knowing the filename */
       char * p = strrchr (name, '.');
       if (p != NULL &&
-	  (xstrcasecmp (p, ".exe") == 0 ||
-	   xstrcasecmp (p, ".com") == 0 ||
-	   xstrcasecmp (p, ".bat") == 0 ||
-	   xstrcasecmp (p, ".cmd") == 0))
+	  (c_strcasecmp (p, ".exe") == 0 ||
+	   c_strcasecmp (p, ".com") == 0 ||
+	   c_strcasecmp (p, ".bat") == 0 ||
+	   c_strcasecmp (p, ".cmd") == 0))
 	permission |= S_IEXEC;
 #endif
     }
@@ -4290,7 +4290,7 @@
       if (result)
 	{
 	  /* Determine a reasonable euid and gid values.  */
-	  if (xstrcasecmp ("administrator", uname) == 0)
+	  if (c_strcasecmp ("administrator", uname) == 0)
 	    {
 	      euid = 500;	/* well-known Administrator uid */
 	      egid = 513;	/* well-known None gid */
@@ -4351,7 +4351,7 @@
 	 user.  */
       else if (GetUserName (uname, &ulength))
 	{
-	  if (xstrcasecmp ("administrator", uname) == 0)
+	  if (c_strcasecmp ("administrator", uname) == 0)
 	    euid = 0;
 	  else
 	    euid = 123;

=== modified file 'src/w32font.c'
--- src/w32font.c	2012-05-02 10:12:13 +0000
+++ src/w32font.c	2012-06-26 01:35:27 +0000
@@ -20,6 +20,7 @@
 #include <windows.h>
 #include <math.h>
 #include <ctype.h>
+#include <c-strcase.h>
 #include <commdlg.h>
 #include <setjmp.h>
 
@@ -1466,7 +1467,7 @@
      to avoid non-truetype fonts, and ends up mixing the Type-1 Helvetica
      with Arial's characteristics, since that attempt to use TrueType works
      some places, but not others.  */
-  if (!xstrcasecmp (font->lfFaceName, "helvetica"))
+  if (!c_strcasecmp (font->lfFaceName, "helvetica"))
     {
       strncpy (full_iname, full_name, LF_FULLFACESIZE);
       full_iname[LF_FULLFACESIZE] = 0;
@@ -1474,7 +1475,7 @@
       return strstr ("helvetica", full_iname) != NULL;
     }
   /* Same for Helv.  */
-  if (!xstrcasecmp (font->lfFaceName, "helv"))
+  if (!c_strcasecmp (font->lfFaceName, "helv"))
     {
       strncpy (full_iname, full_name, LF_FULLFACESIZE);
       full_iname[LF_FULLFACESIZE] = 0;
@@ -1484,8 +1485,8 @@
 
   /* Since Times is mapped to Times New Roman, a substring
      match is not sufficient to filter out the bogus match.  */
-  else if (!xstrcasecmp (font->lfFaceName, "times"))
-    return xstrcasecmp (full_name, "times") == 0;
+  else if (!c_strcasecmp (font->lfFaceName, "times"))
+    return c_strcasecmp (full_name, "times") == 0;
 
   return 1;
 }
@@ -1660,7 +1661,7 @@
   if (NILP (this_entry))
     {
       /* At startup, we want iso8859-1 fonts to come up properly. */
-      if (xstrcasecmp (charset, "iso8859-1") == 0)
+      if (c_strcasecmp (charset, "iso8859-1") == 0)
         return ANSI_CHARSET;
       else
         return DEFAULT_CHARSET;

=== modified file 'src/w32proc.c'
--- src/w32proc.c	2012-06-23 12:44:42 +0000
+++ src/w32proc.c	2012-06-26 01:35:27 +0000
@@ -50,6 +50,8 @@
 #include <langinfo.h>
 #endif
 
+#include <c-strcase.h>
+
 #include "lisp.h"
 #include "w32.h"
 #include "w32heap.h"
@@ -58,7 +60,6 @@
 #include "process.h"
 #include "syssignal.h"
 #include "w32term.h"
-#include "dispextern.h"		/* for xstrcasecmp */
 #include "coding.h"
 
 #define RVA_TO_PTR(var,section,filedata) \
@@ -599,10 +600,10 @@
   p = strrchr (filename, '.');
 
   /* We can only identify DOS .com programs from the extension. */
-  if (p && xstrcasecmp (p, ".com") == 0)
+  if (p && c_strcasecmp (p, ".com") == 0)
     *is_dos_app = TRUE;
-  else if (p && (xstrcasecmp (p, ".bat") == 0
-		 || xstrcasecmp (p, ".cmd") == 0))
+  else if (p && (c_strcasecmp (p, ".bat") == 0
+		 || c_strcasecmp (p, ".cmd") == 0))
     {
       /* A DOS shell script - it appears that CreateProcess is happy to
 	 accept this (somewhat surprisingly); presumably it looks at

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2012-06-25 14:07:04 +0000
+++ src/xfaces.c	2012-06-26 01:35:27 +0000
@@ -205,6 +205,7 @@
 #include <sys/stat.h>
 #include <stdio.h>              /* This needs to be before termchar.h */
 #include <setjmp.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 #include "character.h"
@@ -716,30 +717,6 @@
 }
 #endif  /* HAVE_NS */
 
-#ifndef HAVE_STRCASECMP
-/* Like strcasecmp/stricmp.  Used to compare parts of font names which
-   are in ISO8859-1.  */
-
-int
-xstrcasecmp (const char *s1, const char *s2)
-{
-  while (*s1 && *s2)
-    {
-      unsigned char b1 = *s1;
-      unsigned char b2 = *s2;
-      unsigned char c1 = tolower (b1);
-      unsigned char c2 = tolower (b2);
-      if (c1 != c2)
-	return c1 < c2 ? -1 : 1;
-      ++s1, ++s2;
-    }
-
-  if (*s1 == 0)
-    return *s2 == 0 ? 0 : -1;
-  return 1;
-}
-#endif /* HAVE_STRCASECMP */
-
 /* If FRAME is nil, return a pointer to the selected frame.
    Otherwise, check that FRAME is a live frame, and return a pointer
    to it.  NPARAM is the parameter number of FRAME, for
@@ -1257,8 +1234,8 @@
 #ifdef HAVE_WINDOW_SYSTEM
     FRAME_WINDOW_P (f)
     ? (!NILP (Fxw_display_color_p (frame))
-       || xstrcasecmp (color_name, "black") == 0
-       || xstrcasecmp (color_name, "white") == 0
+       || c_strcasecmp (color_name, "black") == 0
+       || c_strcasecmp (color_name, "white") == 0
        || (background_p
 	   && face_color_gray_p (f, color_name))
        || (!NILP (Fx_display_grayscale_p (frame))
@@ -2953,7 +2930,7 @@
   else if (EQ (attr, QCunderline))
     {
       int valid_p = 0;
-      
+
       if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
 	valid_p = 1;
       else if (NILP (value) || EQ (value, Qt))
@@ -2973,8 +2950,8 @@
               list = CDR_SAFE (list);
               val = CAR_SAFE (list);
               list = CDR_SAFE (list);
-            
-              if(NILP (key) || NILP (val)) 
+
+              if(NILP (key) || NILP (val))
                 {
                   valid_p = 0;
                   break;
@@ -2987,8 +2964,8 @@
                   valid_p = 0;
                   break;
                 }
-              
-              else if (EQ (key, QCstyle) 
+
+              else if (EQ (key, QCstyle)
                        && !(EQ (val, Qline) || EQ (val, Qwave)))
                 {
                   valid_p = 0;
@@ -2996,10 +2973,10 @@
                 }
             }
         }
-      
+
       if (!valid_p)
         signal_error ("Invalid face underline", value);
-      
+
       old_value = LFACE_UNDERLINE (lface);
       LFACE_UNDERLINE (lface) = value;
     }
@@ -3517,13 +3494,13 @@
 
   xassert (STRINGP (value));
 
-  if (xstrcasecmp (SSDATA (value), "on") == 0
-      || xstrcasecmp (SSDATA (value), "true") == 0)
+  if (c_strcasecmp (SSDATA (value), "on") == 0
+      || c_strcasecmp (SSDATA (value), "true") == 0)
     result = Qt;
-  else if (xstrcasecmp (SSDATA (value), "off") == 0
-	   || xstrcasecmp (SSDATA (value), "false") == 0)
+  else if (c_strcasecmp (SSDATA (value), "off") == 0
+	   || c_strcasecmp (SSDATA (value), "false") == 0)
     result = Qnil;
-  else if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
+  else if (c_strcasecmp (SSDATA (value), "unspecified") == 0)
     result = Qunspecified;
   else if (signal_p)
     signal_error ("Invalid face attribute value from X resource", value);
@@ -3542,7 +3519,7 @@
   CHECK_SYMBOL (attr);
   CHECK_STRING (value);
 
-  if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
+  if (c_strcasecmp (SSDATA (value), "unspecified") == 0)
     value = Qunspecified;
   else if (EQ (attr, QCheight))
     {
@@ -4121,10 +4098,10 @@
 {
   xassert (lface_fully_specified_p (lface1)
 	   && lface_fully_specified_p (lface2));
-  return (xstrcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
-		       SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
-	  && xstrcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
-			  SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
+  return (c_strcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
+			SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
+	  && c_strcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
+			   SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
 	  && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
 	  && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
 	  && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
@@ -4133,8 +4110,8 @@
 	  && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
 	      || (STRINGP (lface1[LFACE_FONTSET_INDEX])
 		  && STRINGP (lface2[LFACE_FONTSET_INDEX])
-		  && ! xstrcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
-				    SSDATA (lface2[LFACE_FONTSET_INDEX]))))
+		  && ! c_strcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
+				     SSDATA (lface2[LFACE_FONTSET_INDEX]))))
 	  );
 }
 
@@ -5779,7 +5756,7 @@
     }
   else if (CONSP (underline))
     {
-      /* `(:color COLOR :style STYLE)'.  
+      /* `(:color COLOR :style STYLE)'.
          STYLE being one of `line' or `wave'. */
       face->underline_p = 1;
       face->underline_color = 0;
@@ -5821,7 +5798,7 @@
             }
         }
     }
-  
+
   overline = attrs[LFACE_OVERLINE_INDEX];
   if (STRINGP (overline))
     {

=== modified file 'src/xfns.c'
--- src/xfns.c	2012-06-25 10:16:11 +0000
+++ src/xfns.c	2012-06-26 01:35:27 +0000
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <math.h>
 #include <setjmp.h>
+#include <c-strcase.h>
 #include <ctype.h>
 #include <unistd.h>
 
@@ -1881,7 +1882,7 @@
 
   /* Make a fontset name from the base font name.  */
   if (xic_default_fontset == base_fontname)
-    { 
+    {
       /* There is no base font name, use the default.  */
       fontsetname = xmalloc (strlen (base_fontname) + 2);
       strcpy (fontsetname, base_fontname);
@@ -3977,7 +3978,7 @@
 
       /* Determine the visual class.  */
       for (i = 0; visual_classes[i].name; ++i)
-	if (xstrcasecmp (s, visual_classes[i].name) == 0)
+	if (c_strcasecmp (s, visual_classes[i].name) == 0)
 	  {
 	    class = visual_classes[i].class;
 	    break;

=== modified file 'src/xfont.c'
--- src/xfont.c	2012-06-13 00:26:40 +0000
+++ src/xfont.c	2012-06-26 01:35:27 +0000
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <setjmp.h>
 #include <X11/Xlib.h>
+#include <c-strcase.h>
 
 #include "lisp.h"
 #include "dispextern.h"
@@ -164,8 +165,9 @@
 static int
 compare_font_names (const void *name1, const void *name2)
 {
-  return xstrcasecmp (*(const char **) name1,
-		      *(const char **) name2);
+  char *const *n1 = name1;
+  char *const *n2 = name2;
+  return c_strcasecmp (*n1, *n2);
 }
 
 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
@@ -398,7 +400,7 @@
 	{
 	  Lisp_Object entity;
 
-	  if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
+	  if (i > 0 && c_strcasecmp (indices[i - 1], indices[i]) == 0)
 	    continue;
 	  entity = font_make_entity ();
 	  xfont_decode_coding_xlfd (indices[i], -1, buf);