emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r117751: Improve robustness of new string-collation


From: Paul Eggert
Subject: [Emacs-diffs] trunk r117751: Improve robustness of new string-collation code.
Date: Wed, 27 Aug 2014 18:56:52 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 117751
revision-id: address@hidden
parent: address@hidden
fixes bug: http://debbugs.gnu.org/18051
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Wed 2014-08-27 11:56:47 -0700
message:
  Improve robustness of new string-collation code.
  
  * configure.ac (newlocale): Check for this, not for uselocale.
  * src/sysdep.c (LC_COLLATE, LC_COLLATE_MASK, freelocale, locale_t)
  (newlocale, wcscoll_l): Define substitutes for platforms that
  lack them, so as to simplify the mainline code.
  (str_collate): Simplify the code by assuming the above definitions.
  Use wcscoll_l, not uselocale, as uselocale is too fragile.  For
  example, the old version left the Emacs in the wrong locale if
  wcscoll reported an error.  Use 'int', not ptrdiff_t, for the int
  result.  Report an error if newlocale fails.
modified:
  ChangeLog                      changelog-20091113204419-o5vbwnq5f7feedwu-1538
  configure.ac                   
configure.in-20091113204419-o5vbwnq5f7feedwu-783
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/sysdep.c                   sysdep.c-20091113204419-o5vbwnq5f7feedwu-448
=== modified file 'ChangeLog'
--- a/ChangeLog 2014-08-26 14:42:06 +0000
+++ b/ChangeLog 2014-08-27 18:56:47 +0000
@@ -1,3 +1,8 @@
+2014-08-27  Paul Eggert  <address@hidden>
+
+       Improve robustness of new string-collation code (Bug#18051).
+       * configure.ac (newlocale): Check for this, not for uselocale.
+
 2014-08-26  Dmitry Antipov  <address@hidden>
 
        Detect features needed to handle C stack overflows.

=== modified file 'configure.ac'
--- a/configure.ac      2014-08-26 14:42:06 +0000
+++ b/configure.ac      2014-08-27 18:56:47 +0000
@@ -3558,7 +3558,7 @@
 AC_CHECK_FUNCS(accept4 fchdir gethostname \
 getrusage get_current_dir_name \
 lrand48 random rint \
-select getpagesize setlocale uselocale \
+select getpagesize setlocale newlocale \
 getrlimit setrlimit shutdown getaddrinfo \
 pthread_sigmask strsignal setitimer \
 sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2014-08-27 11:22:37 +0000
+++ b/src/ChangeLog     2014-08-27 18:56:47 +0000
@@ -1,3 +1,15 @@
+2014-08-27  Paul Eggert  <address@hidden>
+
+       Improve robustness of new string-collation code (Bug#18051).
+       * sysdep.c (LC_COLLATE, LC_COLLATE_MASK, freelocale, locale_t)
+       (newlocale, wcscoll_l): Define substitutes for platforms that
+       lack them, so as to simplify the mainline code.
+       (str_collate): Simplify the code by assuming the above definitions.
+       Use wcscoll_l, not uselocale, as uselocale is too fragile.  For
+       example, the old version left the Emacs in the wrong locale if
+       wcscoll reported an error.  Use 'int', not ptrdiff_t, for the int
+       result.  Report an error if newlocale fails.
+
 2014-08-27  Michael Albinus  <address@hidden>
 
        * lisp.h (str_collate):

=== modified file 'src/sysdep.c'
--- a/src/sysdep.c      2014-08-27 11:22:37 +0000
+++ b/src/sysdep.c      2014-08-27 18:56:47 +0000
@@ -3599,24 +3599,89 @@
 #ifdef __STDC_ISO_10646__
 # include <wchar.h>
 
-# if defined HAVE_USELOCALE || defined HAVE_SETLOCALE
+# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE
 #  include <locale.h>
+# else
+#  define LC_COLLATE 0
+#  define LC_COLLATE_MASK 0
 # endif
-# ifndef HAVE_SETLOCALE
-#  define setlocale(category, locale) ((char *) 0)
+# ifndef HAVE_NEWLOCALE
+#  undef freelocale
+#  undef locale_t
+#  undef newlocale
+#  undef wcscoll_l
+#  define freelocale emacs_freelocale
+#  define locale_t emacs_locale_t
+#  define newlocale emacs_newlocale
+#  define wcscoll_l emacs_wcscoll_l
+
+typedef char const *locale_t;
+
+static locale_t
+newlocale (int category_mask, char const *locale, locale_t loc)
+{
+  return locale;
+}
+
+static void
+freelocale (locale_t loc)
+{
+}
+
+static char *
+emacs_setlocale (int category, char const *locale)
+{
+#  ifdef HAVE_SETLOCALE
+  errno = 0;
+  char *loc = setlocale (category, locale);
+  if (loc || errno)
+    return loc;
+  errno = EINVAL;
+#  else
+  errno = ENOTSUP;
+#  endif
+  return 0;
+}
+
+static int
+wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc)
+{
+  int result = 0;
+  char *oldloc = emacs_setlocale (LC_COLLATE, NULL);
+  int err;
+
+  if (! oldloc)
+    err = errno;
+  else
+    {
+      USE_SAFE_ALLOCA;
+      char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
+      strcpy (oldcopy, oldloc);
+      if (! emacs_setlocale (LC_COLLATE, loc))
+       err = errno;
+      else
+       {
+         errno = 0;
+         result = wcscoll (a, b);
+         err = errno;
+         if (! emacs_setlocale (LC_COLLATE, oldcopy))
+           err = errno;
+       }
+      SAFE_FREE ();
+    }
+
+  errno = err;
+  return result;
+}
 # endif
 
 int
 str_collate (Lisp_Object s1, Lisp_Object s2)
 {
-  ptrdiff_t res, len, i, i_byte;
+  int res, err;
+  ptrdiff_t len, i, i_byte;
   wchar_t *p1, *p2;
   Lisp_Object lc_collate;
-# ifdef HAVE_USELOCALE
-  locale_t loc = 0, oldloc = 0;
-# else
-  char *oldloc = NULL;
-# endif
 
   USE_SAFE_ALLOCA;
 
@@ -3633,44 +3698,28 @@
     FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte);
   *(p2+len) = 0;
 
-  /* Create a new locale object, and set it.  */
   lc_collate =
     Fgetenv_internal (build_string ("LC_COLLATE"), Vprocess_environment);
 
   if (STRINGP (lc_collate))
     {
-#ifdef HAVE_USELOCALE
-      loc = newlocale (LC_COLLATE_MASK, SSDATA (lc_collate), 0);
-      if (loc)
-       oldloc = uselocale (loc);
-#else
-      oldloc = setlocale (LC_COLLATE, NULL);
-      if (oldloc)
-       {
-         oldloc = xstrdup (oldloc);
-         setlocale (LC_COLLATE, SSDATA (lc_collate));
-       }
-#endif
-    }
-
-  errno = 0;
-  res = wcscoll (p1, p2);
-  if (errno)
-    error ("Wrong argument: %s", strerror (errno));
-
-#ifdef HAVE_USELOCALE
-  /* Free the locale object, and reset.  */
-  if (loc)
-    freelocale (loc);
-  if (oldloc)
-    uselocale (oldloc);
-#else
-  /* Restore the original locale. */
-  setlocale (LC_COLLATE, oldloc);
-  xfree (oldloc);
-#endif
-
-  /* Return result.  */
+      locale_t loc = newlocale (LC_COLLATE_MASK, SSDATA (lc_collate), 0);
+      if (!loc)
+       error ("Wrong locale: %s", strerror (errno));
+      errno = 0;
+      res = wcscoll_l (p1, p2, loc);
+      err = errno;
+      freelocale (loc);
+    }
+  else
+    {
+      errno = 0;
+      res = wcscoll (p1, p2);
+      err = errno;
+    }
+  if (err)
+    error ("Wrong argument: %s", strerror (err));
+
   SAFE_FREE ();
   return res;
 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]