bug-coreutils
[Top][All Lists]
Advanced

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

coreutils assumes locale functions exist


From: Paul Eggert
Subject: coreutils assumes locale functions exist
Date: Wed, 01 Dec 2004 23:00:01 -0800
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I noticed that coreutils's src/sort.c assumes that setlocale exists.
This assumption was inadvertant, but has been present for a while
without anyone complaining (at least since 5.0 -- I didn't check back
older than that) so I guess it's safe to make the assumption
everywhere.  I installed this.

2004-12-01  Paul Eggert  <address@hidden>

        * lib/hard-locale.c: Assume <locale.h> exists.
        Include "strdup.h".
        (GLIBC_VERSION): New macro.
        (hard_locale): Assume setlocale exists.
        Rewrite to avoid #ifdef.
        Use strdup rather than malloc + strcpy.
        * lib/human.c: Assume <locale.h> exists.
        (human_readable): Assume localeconv exists.

        * m4/hard-locale.m4 (gl_HARD_LOCALE): Assume locale.h and setlocale
        exist.
        * m4/human.m4 (gl_HUMAN): Assume locale.h and localeconv exist.
        * m4/jm-macros.m4 (gl_MACROS): Assume localeconv exists.

        * src/comm.c (compare_files): Assume setlocale exists.
        * src/join.c (keycmp): Likewise.
        * src/seq.c (decimal_point): Treat like sort.  Now char.
        All uses changed.
        (main): Assume localeconv exists.  Use same code as sort.
        * src/sort.c (C_DECIMAL_POINT): Remove.  Use changed to '.'.
        Assume setlocale exists.
        (thousands_sep): Renamed from th_sep.
        (IS_THOUSANDS_SEP): Remove.  All uses replaced by comparisons.
        (NONZERO): Parenthesize use of arg.
        (numcompare): Avoid duplicate loads.  Use ISDIGIT as boolean, for
        consistency.  Avoid unnecessary negation by reversing
        fraccompare args.
        (main): Rewrite localeconv call to match seq.c.
        * src/system.h: Assume locale.h exists.
        (HAVE_SETLOCALE): Remove.
        * src/uniq.c (different): Assume setlocale exists.

Index: lib/hard-locale.c
===================================================================
RCS file: /fetish/cu/lib/hard-locale.c,v
retrieving revision 1.9
diff -p -u -r1.9 hard-locale.c
--- lib/hard-locale.c   2 Aug 2004 22:48:49 -0000       1.9
+++ lib/hard-locale.c   2 Dec 2004 06:42:36 -0000
@@ -23,53 +23,53 @@
 
 #include "hard-locale.h"
 
-#if HAVE_LOCALE_H
-# include <locale.h>
-#endif
-
+#include <locale.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "strdup.h"
+
+#ifdef __GLIBC__
+# define GLIBC_VERSION __GLIBC__
+#else
+# define GLIBC_VERSION 0
+#endif
+
 /* Return true if the current CATEGORY locale is hard, i.e. if you
    can't get away with assuming traditional C or POSIX behavior.  */
 bool
 hard_locale (int category)
 {
-#if ! HAVE_SETLOCALE
-  return false;
-#else
-
   bool hard = true;
   char const *p = setlocale (category, NULL);
 
   if (p)
     {
-# if defined __GLIBC__ && 2 <= __GLIBC__
-      if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
-       hard = false;
-# else
-      char *locale = malloc (strlen (p) + 1);
-      if (locale)
+      if (2 <= GLIBC_VERSION)
        {
-         strcpy (locale, p);
-
-         /* Temporarily set the locale to the "C" and "POSIX" locales
-            to find their names, so that we can determine whether one
-            or the other is the caller's locale.  */
-         if (((p = setlocale (category, "C"))
-              && strcmp (p, locale) == 0)
-             || ((p = setlocale (category, "POSIX"))
-                 && strcmp (p, locale) == 0))
+         if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
            hard = false;
-
-         /* Restore the caller's locale.  */
-         setlocale (category, locale);
-         free (locale);
        }
-# endif
+      else
+       {
+         char *locale = strdup (p);
+         if (locale)
+           {
+             /* Temporarily set the locale to the "C" and "POSIX" locales
+                to find their names, so that we can determine whether one
+                or the other is the caller's locale.  */
+             if (((p = setlocale (category, "C"))
+                  && strcmp (p, locale) == 0)
+                 || ((p = setlocale (category, "POSIX"))
+                     && strcmp (p, locale) == 0))
+               hard = false;
+
+             /* Restore the caller's locale.  */
+             setlocale (category, locale);
+             free (locale);
+           }
+       }
     }
 
   return hard;
-
-#endif
 }
Index: lib/human.c
===================================================================
RCS file: /fetish/cu/lib/human.c,v
retrieving revision 1.28
diff -p -u -r1.28 human.c
--- lib/human.c 16 Nov 2004 07:53:08 -0000      1.28
+++ lib/human.c 2 Dec 2004 06:42:36 -0000
@@ -32,10 +32,7 @@
 # define UINTMAX_MAX ((uintmax_t) -1)
 #endif
 
-#if HAVE_LOCALE_H && HAVE_LOCALECONV
-# include <locale.h>
-#endif
-
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -193,7 +190,6 @@ human_readable (uintmax_t n, char *buf, 
   size_t decimal_pointlen = 1;
   char const *grouping = "";
   char const *thousands_sep = "";
-#if HAVE_LOCALE_H && HAVE_LOCALECONV
   struct lconv const *l = localeconv ();
   size_t pointlen = strlen (l->decimal_point);
   if (0 < pointlen && pointlen <= MB_LEN_MAX)
@@ -204,7 +200,6 @@ human_readable (uintmax_t n, char *buf, 
   grouping = l->grouping;
   if (strlen (l->thousands_sep) <= MB_LEN_MAX)
     thousands_sep = l->thousands_sep;
-#endif
 
   psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
   p = psuffix;
Index: m4/hard-locale.m4
===================================================================
RCS file: /fetish/cu/m4/hard-locale.m4,v
retrieving revision 1.2
diff -p -u -r1.2 hard-locale.m4
--- m4/hard-locale.m4   13 Sep 2003 06:30:59 -0000      1.2
+++ m4/hard-locale.m4   2 Dec 2004 06:42:36 -0000
@@ -1,4 +1,4 @@
-# hard-locale.m4 serial 2
+# hard-locale.m4 serial 3
 dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
 dnl This file is free software, distributed under the terms of the GNU
 dnl General Public License.  As a special exception to the GNU General
@@ -6,9 +6,5 @@ dnl Public License, this file may be dis
 dnl that contains a configuration script generated by Autoconf, under
 dnl the same distribution terms as the rest of that program.
 
-AC_DEFUN([gl_HARD_LOCALE],
-[
-  dnl Prerequisites of lib/hard-locale.c.
-  AC_CHECK_HEADERS_ONCE(locale.h)
-  AC_CHECK_FUNCS_ONCE(setlocale)
-])
+dnl No prerequisites of lib/hard-locale.c.
+AC_DEFUN([gl_HARD_LOCALE], [:])
Index: m4/human.m4
===================================================================
RCS file: /fetish/cu/m4/human.m4,v
retrieving revision 1.3
diff -p -u -r1.3 human.m4
--- m4/human.m4 13 Apr 2004 15:28:45 -0000      1.3
+++ m4/human.m4 2 Dec 2004 06:42:36 -0000
@@ -13,6 +13,5 @@ AC_DEFUN([gl_HUMAN],
   AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])
 
   dnl Prerequisites of lib/human.c.
-  AC_CHECK_HEADERS_ONCE(locale.h)
-  AC_CHECK_FUNCS_ONCE(localeconv)
+  :
 ])
Index: m4/jm-macros.m4
===================================================================
RCS file: /fetish/cu/m4/jm-macros.m4,v
retrieving revision 1.205
diff -p -u -r1.205 jm-macros.m4
--- m4/jm-macros.m4     30 Nov 2004 14:53:26 -0000      1.205
+++ m4/jm-macros.m4     2 Dec 2004 06:42:36 -0000
@@ -109,7 +109,6 @@ AC_DEFUN([gl_MACROS],
     iswspace \
     lchown \
     listmntent \
-    localeconv \
     memcpy \
     mempcpy \
     mkfifo \
Index: src/comm.c
===================================================================
RCS file: /fetish/cu/src/comm.c,v
retrieving revision 1.77
diff -p -u -r1.77 comm.c
--- src/comm.c  21 Sep 2004 22:26:42 -0000      1.77
+++ src/comm.c  2 Dec 2004 06:42:36 -0000
@@ -187,7 +187,7 @@ compare_files (char **infiles)
        order = -1;
       else
        {
-         if (HAVE_SETLOCALE && hard_LC_COLLATE)
+         if (hard_LC_COLLATE)
            order = xmemcoll (thisline[0]->buffer, thisline[0]->length - 1,
                              thisline[1]->buffer, thisline[1]->length - 1);
          else
Index: src/join.c
===================================================================
RCS file: /fetish/cu/src/join.c,v
retrieving revision 1.131
diff -p -u -r1.131 join.c
--- src/join.c  21 Sep 2004 22:26:42 -0000      1.131
+++ src/join.c  2 Dec 2004 06:42:36 -0000
@@ -378,7 +378,7 @@ keycmp (struct line const *line1, struct
     }
   else
     {
-      if (HAVE_SETLOCALE && hard_LC_COLLATE)
+      if (hard_LC_COLLATE)
        return xmemcoll (beg1, len1, beg2, len2);
       diff = memcmp (beg1, beg2, MIN (len1, len2));
     }
Index: src/seq.c
===================================================================
RCS file: /fetish/cu/src/seq.c,v
retrieving revision 1.83
diff -p -u -r1.83 seq.c
--- src/seq.c   21 Sep 2004 22:26:42 -0000      1.83
+++ src/seq.c   2 Dec 2004 06:42:36 -0000
@@ -49,9 +49,8 @@ static char *separator;
 /* FIXME: make this an option.  */
 static char *terminator = "\n";
 
-/* The representation of the decimal point in the current locale.
-   Always "." if the localeconv function is not supported.  */
-static char *decimal_point = ".";
+/* The representation of the decimal point in the current locale.  */
+static char decimal_point;
 
 /* The starting number.  */
 static double first;
@@ -251,9 +250,7 @@ get_width_format ()
   else
     {
       if (buffer[0] != '1'
-         /* FIXME: assumes that decimal_point is a single character
-            string.  */
-         || buffer[1] != decimal_point[0]
+         || buffer[1] != decimal_point
          || buffer[2 + strspn (&buffer[2], "0123456789")] != '\0')
        return "%g";
       width1 -= 2;
@@ -266,9 +263,7 @@ get_width_format ()
   else
     {
       if (buffer[0] != '1'
-         /* FIXME: assumes that decimal_point is a single character
-            string.  */
-         || buffer[1] != decimal_point[0]
+         || buffer[1] != decimal_point
          || buffer[2 + strspn (&buffer[2], "0123456789")] != '\0')
        return "%g";
       width2 -= 2;
@@ -315,17 +310,17 @@ main (int argc, char **argv)
   separator = "\n";
   first = 1.0;
 
-  /* Figure out the locale's idea of a decimal point.  */
-#if HAVE_LOCALECONV
+  /* Get locale's representation of the decimal point.  */
   {
-    struct lconv *locale;
+    struct lconv const *locale = localeconv ();
 
-    locale = localeconv ();
-    /* Paranoia.  */
-    if (locale && locale->decimal_point && locale->decimal_point[0] != '\0')
-      decimal_point = locale->decimal_point;
+    /* If the locale doesn't define a decimal point, or if the decimal
+       point is multibyte, use the C locale's decimal point.  FIXME:
+       add support for multibyte decimal points.  */
+    decimal_point = locale->decimal_point[0];
+    if (! decimal_point || locale->decimal_point[1])
+      decimal_point = '.';
   }
-#endif
 
   /* We have to handle negative numbers in the command line but this
      conflicts with the command line arguments.  So explicitly check first
@@ -333,7 +328,7 @@ main (int argc, char **argv)
   while (optind < argc)
     {
       if (argv[optind][0] == '-'
-         && ((optc = argv[optind][1]) == decimal_point[0]
+         && ((optc = argv[optind][1]) == decimal_point
              || ISDIGIT (optc)))
        {
          /* means negative number */
Index: src/sort.c
===================================================================
RCS file: /fetish/cu/src/sort.c,v
retrieving revision 1.301
diff -p -u -r1.301 sort.c
--- src/sort.c  14 Nov 2004 08:36:30 -0000      1.301
+++ src/sort.c  2 Dec 2004 06:42:36 -0000
@@ -82,31 +82,22 @@ enum
     SORT_FAILURE = 2
   };
 
-#define C_DECIMAL_POINT '.'
 #define NEGATION_SIGN   '-'
 #define NUMERIC_ZERO    '0'
 
-#if HAVE_SETLOCALE
-
+/* The representation of the decimal point in the current locale.  */
 static char decimal_point;
-static int th_sep; /* if CHAR_MAX + 1, then there is no thousands separator */
+
+/* Thousands separator; if CHAR_MAX + 1, then there isn't one.  */
+static int thousands_sep;
 
 /* Nonzero if the corresponding locales are hard.  */
 static bool hard_LC_COLLATE;
-# if HAVE_NL_LANGINFO
+#if HAVE_NL_LANGINFO
 static bool hard_LC_TIME;
-# endif
-
-# define IS_THOUSANDS_SEP(x) ((x) == th_sep)
-
-#else
-
-# define decimal_point C_DECIMAL_POINT
-# define IS_THOUSANDS_SEP(x) false
-
 #endif
 
-#define NONZERO(x) (x != 0)
+#define NONZERO(x) ((x) != 0)
 
 /* The kind of blanks for '-b' to skip in various options. */
 enum blanktype { bl_start, bl_end, bl_both };
@@ -1139,19 +1130,16 @@ numcompare (register const char *a, regi
   size_t log_a;
   size_t log_b;
 
-  tmpa = *a;
-  tmpb = *b;
-
-  while (blanks[to_uchar (tmpa)])
-    tmpa = *++a;
-  while (blanks[to_uchar (tmpb)])
-    tmpb = *++b;
+  while (blanks[to_uchar (tmpa = *a)])
+    a++;
+  while (blanks[to_uchar (tmpb = *b)])
+    b++;
 
   if (tmpa == NEGATION_SIGN)
     {
       do
        tmpa = *++a;
-      while (tmpa == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpa));
+      while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep);
       if (tmpb != NEGATION_SIGN)
        {
          if (tmpa == decimal_point)
@@ -1160,45 +1148,43 @@ numcompare (register const char *a, regi
            while (tmpa == NUMERIC_ZERO);
          if (ISDIGIT (tmpa))
            return -1;
-         while (tmpb == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpb))
+         while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
            tmpb = *++b;
          if (tmpb == decimal_point)
            do
              tmpb = *++b;
            while (tmpb == NUMERIC_ZERO);
-         if (ISDIGIT (tmpb))
-           return -1;
-         return 0;
+         return - ISDIGIT (tmpb);
        }
       do
        tmpb = *++b;
-      while (tmpb == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpb));
+      while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
 
       while (tmpa == tmpb && ISDIGIT (tmpa))
        {
          do
            tmpa = *++a;
-         while (IS_THOUSANDS_SEP (tmpa));
+         while (tmpa == thousands_sep);
          do
            tmpb = *++b;
-         while (IS_THOUSANDS_SEP (tmpb));
+         while (tmpb == thousands_sep);
        }
 
       if ((tmpa == decimal_point && !ISDIGIT (tmpb))
          || (tmpb == decimal_point && !ISDIGIT (tmpa)))
-       return -fraccompare (a, b);
+       return fraccompare (b, a);
 
       tmp = tmpb - tmpa;
 
       for (log_a = 0; ISDIGIT (tmpa); ++log_a)
        do
          tmpa = *++a;
-       while (IS_THOUSANDS_SEP (tmpa));
+       while (tmpa == thousands_sep);
 
       for (log_b = 0; ISDIGIT (tmpb); ++log_b)
        do
          tmpb = *++b;
-       while (IS_THOUSANDS_SEP (tmpb));
+       while (tmpb == thousands_sep);
 
       if (log_a != log_b)
        return log_a < log_b ? 1 : -1;
@@ -1212,38 +1198,36 @@ numcompare (register const char *a, regi
     {
       do
        tmpb = *++b;
-      while (tmpb == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpb));
+      while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
       if (tmpb == decimal_point)
        do
          tmpb = *++b;
        while (tmpb == NUMERIC_ZERO);
       if (ISDIGIT (tmpb))
        return 1;
-      while (tmpa == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpa))
+      while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
        tmpa = *++a;
       if (tmpa == decimal_point)
        do
          tmpa = *++a;
        while (tmpa == NUMERIC_ZERO);
-      if (ISDIGIT (tmpa))
-       return 1;
-      return 0;
+      return ISDIGIT (tmpa);
     }
   else
     {
-      while (tmpa == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpa))
+      while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
        tmpa = *++a;
-      while (tmpb == NUMERIC_ZERO || IS_THOUSANDS_SEP (tmpb))
+      while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
        tmpb = *++b;
 
       while (tmpa == tmpb && ISDIGIT (tmpa))
        {
          do
            tmpa = *++a;
-         while (IS_THOUSANDS_SEP (tmpa));
+         while (tmpa == thousands_sep);
          do
            tmpb = *++b;
-         while (IS_THOUSANDS_SEP (tmpb));
+         while (tmpb == thousands_sep);
        }
 
       if ((tmpa == decimal_point && !ISDIGIT (tmpb))
@@ -1255,12 +1239,12 @@ numcompare (register const char *a, regi
       for (log_a = 0; ISDIGIT (tmpa); ++log_a)
        do
          tmpa = *++a;
-       while (IS_THOUSANDS_SEP (tmpa));
+       while (tmpa == thousands_sep);
 
       for (log_b = 0; ISDIGIT (tmpb); ++log_b)
        do
          tmpb = *++b;
-       while (IS_THOUSANDS_SEP (tmpb));
+       while (tmpb == thousands_sep);
 
       if (log_a != log_b)
        return log_a < log_b ? -1 : 1;
@@ -1387,7 +1371,7 @@ keycompare (const struct line *a, const 
        diff = getmonth (texta, lena) - getmonth (textb, lenb);
       /* Sorting like this may become slow, so in a simple locale the user
         can select a faster sort that is similar to ascii sort.  */
-      else if (HAVE_SETLOCALE && hard_LC_COLLATE)
+      else if (hard_LC_COLLATE)
        {
          if (ignore || translate)
            {
@@ -1548,7 +1532,7 @@ compare (register const struct line *a, 
     diff = - NONZERO (blen);
   else if (blen == 0)
     diff = 1;
-  else if (HAVE_SETLOCALE && hard_LC_COLLATE)
+  else if (hard_LC_COLLATE)
     diff = xmemcoll (a->text, alen, b->text, blen);
   else if (! (diff = memcmp (a->text, b->text, MIN (alen, blen))))
     diff = alen < blen ? -1 : alen != blen;
@@ -2316,24 +2300,22 @@ main (int argc, char **argv)
   hard_LC_TIME = hard_locale (LC_TIME);
 #endif
 
-#if HAVE_SETLOCALE
-  /* Let's get locale's representation of the decimal point */
+  /* Get locale's representation of the decimal point.  */
   {
-    struct lconv const *lconvp = localeconv ();
+    struct lconv const *locale = localeconv ();
 
     /* If the locale doesn't define a decimal point, or if the decimal
-       point is multibyte, use the C decimal point.  We don't support
-       multibyte decimal points yet.  */
-    decimal_point = *lconvp->decimal_point;
-    if (! decimal_point || lconvp->decimal_point[1])
-      decimal_point = C_DECIMAL_POINT;
-
-    /* We don't support multibyte thousands separators yet.  */
-    th_sep = *lconvp->thousands_sep;
-    if (! th_sep || lconvp->thousands_sep[1])
-      th_sep = CHAR_MAX + 1;
+       point is multibyte, use the C locale's decimal point.  FIXME:
+       add support for multibyte decimal points.  */
+    decimal_point = locale->decimal_point[0];
+    if (! decimal_point || locale->decimal_point[1])
+      decimal_point = '.';
+
+    /* FIXME: add support for multibyte thousands separators.  */
+    thousands_sep = *locale->thousands_sep;
+    if (! thousands_sep || locale->thousands_sep[1])
+      thousands_sep = CHAR_MAX + 1;
   }
-#endif
 
   have_read_stdin = false;
   inittables ();
Index: src/system.h
===================================================================
RCS file: /fetish/cu/src/system.h,v
retrieving revision 1.95
diff -p -u -r1.95 system.h
--- src/system.h        3 Nov 2004 18:44:33 -0000       1.95
+++ src/system.h        2 Dec 2004 06:42:37 -0000
@@ -466,13 +466,9 @@ initialize_exit_failure (int status)
    errors that the cast doesn't.  */
 static inline unsigned char to_uchar (char ch) { return ch; }
 
-/* Take care of NLS matters.  */
+#include <locale.h>
 
-#if HAVE_LOCALE_H
-# include <locale.h>
-#else
-# define setlocale(Category, Locale) /* empty */
-#endif
+/* Take care of NLS matters.  */
 
 #include "gettext.h"
 #if ! ENABLE_NLS
@@ -485,10 +481,6 @@ static inline unsigned char to_uchar (ch
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-#ifndef HAVE_SETLOCALE
-# define HAVE_SETLOCALE 0
-#endif
-
 #define STREQ(a, b) (strcmp ((a), (b)) == 0)
 
 #if !HAVE_DECL_FREE
Index: src/uniq.c
===================================================================
RCS file: /fetish/cu/src/uniq.c,v
retrieving revision 1.113
diff -p -u -r1.113 uniq.c
--- src/uniq.c  19 Nov 2004 18:56:16 -0000      1.113
+++ src/uniq.c  2 Dec 2004 06:42:37 -0000
@@ -228,7 +228,7 @@ different (char *old, char *new, size_t 
       /* FIXME: This should invoke strcoll somehow.  */
       return oldlen != newlen || memcasecmp (old, new, oldlen);
     }
-  else if (HAVE_SETLOCALE && hard_LC_COLLATE)
+  else if (hard_LC_COLLATE)
     return xmemcoll (old, oldlen, new, newlen) != 0;
   else
     return oldlen != newlen || memcmp (old, new, oldlen);




reply via email to

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