- Finished porting i18n patch to sort.c.
This commit is contained in:
parent
b43cfa4724
commit
b4f8aa7273
@ -3196,3 +3196,802 @@
|
|||||||
mk_script = $(srcdir)/../mk-script
|
mk_script = $(srcdir)/../mk-script
|
||||||
MAINTAINERCLEANFILES = $x-tests $(maint_gen)
|
MAINTAINERCLEANFILES = $x-tests $(maint_gen)
|
||||||
CLEANFILES = $(run_gen)
|
CLEANFILES = $(run_gen)
|
||||||
|
--- coreutils-5.92/src/sort.c.i18n-sort 2005-10-07 20:16:56.000000000 +0100
|
||||||
|
+++ coreutils-5.92/src/sort.c 2005-10-28 15:24:37.000000000 +0100
|
||||||
|
@@ -23,9 +23,18 @@
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
+#include <assert.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
+#if HAVE_WCHAR_H
|
||||||
|
+# include <wchar.h>
|
||||||
|
+#endif
|
||||||
|
+/* Get isw* functions. */
|
||||||
|
+#if HAVE_WCTYPE_H
|
||||||
|
+# include <wctype.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#include "system.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "hard-locale.h"
|
||||||
|
@@ -95,14 +104,38 @@
|
||||||
|
/* Thousands separator; if -1, then there isn't one. */
|
||||||
|
static int thousands_sep;
|
||||||
|
|
||||||
|
+static int force_general_numcompare = 0;
|
||||||
|
+
|
||||||
|
/* Nonzero if the corresponding locales are hard. */
|
||||||
|
static bool hard_LC_COLLATE;
|
||||||
|
-#if HAVE_NL_LANGINFO
|
||||||
|
+#if HAVE_LANGINFO_CODESET
|
||||||
|
static bool hard_LC_TIME;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NONZERO(x) ((x) != 0)
|
||||||
|
|
||||||
|
+/* get a multibyte character's byte length. */
|
||||||
|
+#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE) \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ wchar_t wc; \
|
||||||
|
+ mbstate_t state_bak; \
|
||||||
|
+ \
|
||||||
|
+ state_bak = STATE; \
|
||||||
|
+ mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE); \
|
||||||
|
+ \
|
||||||
|
+ switch (MBLENGTH) \
|
||||||
|
+ { \
|
||||||
|
+ case (size_t)-1: \
|
||||||
|
+ case (size_t)-2: \
|
||||||
|
+ STATE = state_bak; \
|
||||||
|
+ /* Fall through. */ \
|
||||||
|
+ case 0: \
|
||||||
|
+ MBLENGTH = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ while (0)
|
||||||
|
+
|
||||||
|
/* The kind of blanks for '-b' to skip in various options. */
|
||||||
|
enum blanktype { bl_start, bl_end, bl_both };
|
||||||
|
|
||||||
|
@@ -239,13 +272,11 @@
|
||||||
|
they were read if all keys compare equal. */
|
||||||
|
static bool stable;
|
||||||
|
|
||||||
|
-/* If TAB has this value, blanks separate fields. */
|
||||||
|
-enum { TAB_DEFAULT = CHAR_MAX + 1 };
|
||||||
|
-
|
||||||
|
-/* Tab character separating fields. If TAB_DEFAULT, then fields are
|
||||||
|
+/* Tab character separating fields. If tab_length is 0, then fields are
|
||||||
|
separated by the empty string between a non-blank character and a blank
|
||||||
|
character. */
|
||||||
|
-static int tab = TAB_DEFAULT;
|
||||||
|
+static char tab[MB_LEN_MAX + 1];
|
||||||
|
+static size_t tab_length = 0;
|
||||||
|
|
||||||
|
/* Flag to remove consecutive duplicate lines from the output.
|
||||||
|
Only the last of a sequence of equal lines will be output. */
|
||||||
|
@@ -392,6 +423,42 @@
|
||||||
|
static struct tempnode *volatile temphead;
|
||||||
|
static struct tempnode *volatile *temptail = &temphead;
|
||||||
|
|
||||||
|
+/* Function pointers. */
|
||||||
|
+static void
|
||||||
|
+(*inittables) (void);
|
||||||
|
+static char *
|
||||||
|
+(*begfield) (const struct line*, const struct keyfield *);
|
||||||
|
+static char *
|
||||||
|
+(*limfield) (const struct line*, const struct keyfield *);
|
||||||
|
+static int
|
||||||
|
+(*getmonth) (char const *, size_t);
|
||||||
|
+static int
|
||||||
|
+(*keycompare) (const struct line *, const struct line *);
|
||||||
|
+
|
||||||
|
+/* Test for white space multibyte character.
|
||||||
|
+ Set LENGTH the byte length of investigated multibyte character. */
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static int
|
||||||
|
+ismbblank (const char *str, size_t len, size_t *length)
|
||||||
|
+{
|
||||||
|
+ size_t mblength;
|
||||||
|
+ wchar_t wc;
|
||||||
|
+ mbstate_t state;
|
||||||
|
+
|
||||||
|
+ memset (&state, '\0', sizeof(mbstate_t));
|
||||||
|
+ mblength = mbrtowc (&wc, str, len, &state);
|
||||||
|
+
|
||||||
|
+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
|
||||||
|
+ {
|
||||||
|
+ *length = 1;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *length = (mblength < 1) ? 1 : mblength;
|
||||||
|
+ return iswblank (wc);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Clean up any remaining temporary files. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -545,7 +612,7 @@
|
||||||
|
free (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if HAVE_NL_LANGINFO
|
||||||
|
+#if HAVE_LANGINFO_CODESET
|
||||||
|
|
||||||
|
static int
|
||||||
|
struct_month_cmp (const void *m1, const void *m2)
|
||||||
|
@@ -560,7 +627,7 @@
|
||||||
|
/* Initialize the character class tables. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
-inittables (void)
|
||||||
|
+inittables_uni (void)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
@@ -572,7 +639,7 @@
|
||||||
|
fold_toupper[i] = (ISLOWER (i) ? toupper (i) : i);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if HAVE_NL_LANGINFO
|
||||||
|
+#if HAVE_LANGINFO_CODESET
|
||||||
|
/* If we're not in the "C" locale, read different names for months. */
|
||||||
|
if (hard_LC_TIME)
|
||||||
|
{
|
||||||
|
@@ -598,6 +665,64 @@
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static void
|
||||||
|
+inittables_mb (void)
|
||||||
|
+{
|
||||||
|
+ int i, j, k, l;
|
||||||
|
+ char *name, *s;
|
||||||
|
+ size_t s_len, mblength;
|
||||||
|
+ char mbc[MB_LEN_MAX];
|
||||||
|
+ wchar_t wc, pwc;
|
||||||
|
+ mbstate_t state_mb, state_wc;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < MONTHS_PER_YEAR; i++)
|
||||||
|
+ {
|
||||||
|
+ s = (char *) nl_langinfo (ABMON_1 + i);
|
||||||
|
+ s_len = strlen (s);
|
||||||
|
+ monthtab[i].name = name = (char *) xmalloc (s_len + 1);
|
||||||
|
+ monthtab[i].val = i + 1;
|
||||||
|
+
|
||||||
|
+ memset (&state_mb, '\0', sizeof (mbstate_t));
|
||||||
|
+ memset (&state_wc, '\0', sizeof (mbstate_t));
|
||||||
|
+
|
||||||
|
+ for (j = 0; j < s_len;)
|
||||||
|
+ {
|
||||||
|
+ if (!ismbblank (s + j, s_len - j, &mblength))
|
||||||
|
+ break;
|
||||||
|
+ j += mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (k = 0; j < s_len;)
|
||||||
|
+ {
|
||||||
|
+ mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb);
|
||||||
|
+ assert (mblength != (size_t)-1 && mblength != (size_t)-2);
|
||||||
|
+ if (mblength == 0)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ pwc = towupper (wc);
|
||||||
|
+ if (pwc == wc)
|
||||||
|
+ {
|
||||||
|
+ memcpy (mbc, s + j, mblength);
|
||||||
|
+ j += mblength;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ j += mblength;
|
||||||
|
+ mblength = wcrtomb (mbc, pwc, &state_wc);
|
||||||
|
+ assert (mblength != (size_t)0 && mblength != (size_t)-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (l = 0; l < mblength; l++)
|
||||||
|
+ name[k++] = mbc[l];
|
||||||
|
+ }
|
||||||
|
+ name[k] = '\0';
|
||||||
|
+ }
|
||||||
|
+ qsort ((void *) monthtab, MONTHS_PER_YEAR,
|
||||||
|
+ sizeof (struct month), struct_month_cmp);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Specify the amount of main memory to use when sorting. */
|
||||||
|
static void
|
||||||
|
specify_sort_size (char const *s)
|
||||||
|
@@ -808,7 +933,7 @@
|
||||||
|
by KEY in LINE. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
-begfield (const struct line *line, const struct keyfield *key)
|
||||||
|
+begfield_uni (const struct line *line, const struct keyfield *key)
|
||||||
|
{
|
||||||
|
char *ptr = line->text, *lim = ptr + line->length - 1;
|
||||||
|
size_t sword = key->sword;
|
||||||
|
@@ -818,10 +943,10 @@
|
||||||
|
/* The leading field separator itself is included in a field when -t
|
||||||
|
is absent. */
|
||||||
|
|
||||||
|
- if (tab != TAB_DEFAULT)
|
||||||
|
+ if (tab_length)
|
||||||
|
while (ptr < lim && sword--)
|
||||||
|
{
|
||||||
|
- while (ptr < lim && *ptr != tab)
|
||||||
|
+ while (ptr < lim && *ptr != tab[0])
|
||||||
|
++ptr;
|
||||||
|
if (ptr < lim)
|
||||||
|
++ptr;
|
||||||
|
@@ -849,11 +974,70 @@
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static char *
|
||||||
|
+begfield_mb (const struct line *line, const struct keyfield *key)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+ char *ptr = line->text, *lim = ptr + line->length - 1;
|
||||||
|
+ size_t sword = key->sword;
|
||||||
|
+ size_t schar = key->schar;
|
||||||
|
+ size_t mblength;
|
||||||
|
+ mbstate_t state;
|
||||||
|
+
|
||||||
|
+ memset (&state, '\0', sizeof(mbstate_t));
|
||||||
|
+
|
||||||
|
+ if (tab_length)
|
||||||
|
+ while (ptr < lim && sword--)
|
||||||
|
+ {
|
||||||
|
+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ if (ptr < lim)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ while (ptr < lim && sword--)
|
||||||
|
+ {
|
||||||
|
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ if (ptr < lim)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (key->skipsblanks)
|
||||||
|
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < schar; i++)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+
|
||||||
|
+ if (ptr + mblength > lim)
|
||||||
|
+ break;
|
||||||
|
+ else
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ptr;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Return the limit of (a pointer to the first character after) the field
|
||||||
|
in LINE specified by KEY. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
-limfield (const struct line *line, const struct keyfield *key)
|
||||||
|
+limfield_uni (const struct line *line, const struct keyfield *key)
|
||||||
|
{
|
||||||
|
char *ptr = line->text, *lim = ptr + line->length - 1;
|
||||||
|
size_t eword = key->eword, echar = key->echar;
|
||||||
|
@@ -866,10 +1050,10 @@
|
||||||
|
`beginning' is the first character following the delimiting TAB.
|
||||||
|
Otherwise, leave PTR pointing at the first `blank' character after
|
||||||
|
the preceding field. */
|
||||||
|
- if (tab != TAB_DEFAULT)
|
||||||
|
+ if (tab_length)
|
||||||
|
while (ptr < lim && eword--)
|
||||||
|
{
|
||||||
|
- while (ptr < lim && *ptr != tab)
|
||||||
|
+ while (ptr < lim && *ptr != tab[0])
|
||||||
|
++ptr;
|
||||||
|
if (ptr < lim && (eword | echar))
|
||||||
|
++ptr;
|
||||||
|
@@ -915,10 +1099,10 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Make LIM point to the end of (one byte past) the current field. */
|
||||||
|
- if (tab != TAB_DEFAULT)
|
||||||
|
+ if (tab_length)
|
||||||
|
{
|
||||||
|
char *newlim;
|
||||||
|
- newlim = memchr (ptr, tab, lim - ptr);
|
||||||
|
+ newlim = memchr (ptr, tab[0], lim - ptr);
|
||||||
|
if (newlim)
|
||||||
|
lim = newlim;
|
||||||
|
}
|
||||||
|
@@ -951,6 +1135,107 @@
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static char *
|
||||||
|
+limfield_mb (const struct line *line, const struct keyfield *key)
|
||||||
|
+{
|
||||||
|
+ char *ptr = line->text, *lim = ptr + line->length - 1;
|
||||||
|
+ size_t eword = key->eword, echar = key->echar;
|
||||||
|
+ int i;
|
||||||
|
+ size_t mblength;
|
||||||
|
+ mbstate_t state;
|
||||||
|
+
|
||||||
|
+ memset (&state, '\0', sizeof(mbstate_t));
|
||||||
|
+
|
||||||
|
+ if (tab_length)
|
||||||
|
+ while (ptr < lim && eword--)
|
||||||
|
+ {
|
||||||
|
+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ if (ptr < lim && (eword | echar))
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ while (ptr < lim && eword--)
|
||||||
|
+ {
|
||||||
|
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ if (ptr < lim)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# ifdef POSIX_UNSPECIFIED
|
||||||
|
+ /* Make LIM point to the end of (one byte past) the current field. */
|
||||||
|
+ if (tab_length)
|
||||||
|
+ {
|
||||||
|
+ char *newlim, *p;
|
||||||
|
+
|
||||||
|
+ newlim = NULL;
|
||||||
|
+ for (p = ptr; p < lim;)
|
||||||
|
+ {
|
||||||
|
+ if (memcmp (p, tab, tab_length) == 0)
|
||||||
|
+ {
|
||||||
|
+ newlim = p;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ p += mblength;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ char *newlim;
|
||||||
|
+ newlim = ptr;
|
||||||
|
+
|
||||||
|
+ while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength))
|
||||||
|
+ newlim += mblength;
|
||||||
|
+ if (ptr < lim)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+ while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength))
|
||||||
|
+ newlim += mblength;
|
||||||
|
+ lim = newlim;
|
||||||
|
+ }
|
||||||
|
+# endif
|
||||||
|
+
|
||||||
|
+ /* If we're skipping leading blanks, don't start counting characters
|
||||||
|
+ * until after skipping past any leading blanks. */
|
||||||
|
+ if (key->skipsblanks)
|
||||||
|
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
|
||||||
|
+ ptr += mblength;
|
||||||
|
+
|
||||||
|
+ memset (&state, '\0', sizeof(mbstate_t));
|
||||||
|
+
|
||||||
|
+ /* Advance PTR by ECHAR (if possible), but no further than LIM. */
|
||||||
|
+ for (i = 0; i < echar; i++)
|
||||||
|
+ {
|
||||||
|
+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
|
||||||
|
+
|
||||||
|
+ if (ptr + mblength > lim)
|
||||||
|
+ break;
|
||||||
|
+ else
|
||||||
|
+ ptr += mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ptr;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Fill BUF reading from FP, moving buf->left bytes from the end
|
||||||
|
of buf->buf to the beginning first. If EOF is reached and the
|
||||||
|
file wasn't terminated by a newline, supply one. Set up BUF's line
|
||||||
|
@@ -1110,7 +1395,7 @@
|
||||||
|
Return 0 if the name in S is not recognized. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
-getmonth (char const *month, size_t len)
|
||||||
|
+getmonth_uni (char const *month, size_t len)
|
||||||
|
{
|
||||||
|
size_t lo = 0;
|
||||||
|
size_t hi = MONTHS_PER_YEAR;
|
||||||
|
@@ -1152,11 +1437,79 @@
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static int
|
||||||
|
+getmonth_mb (const char *s, size_t len)
|
||||||
|
+{
|
||||||
|
+ char *month;
|
||||||
|
+ register size_t i;
|
||||||
|
+ register int lo = 0, hi = MONTHS_PER_YEAR, result;
|
||||||
|
+ char *tmp;
|
||||||
|
+ size_t wclength, mblength;
|
||||||
|
+ const char **pp;
|
||||||
|
+ const wchar_t **wpp;
|
||||||
|
+ wchar_t *month_wcs;
|
||||||
|
+ mbstate_t state;
|
||||||
|
+
|
||||||
|
+ while (len > 0 && ismbblank (s, len, &mblength))
|
||||||
|
+ {
|
||||||
|
+ s += mblength;
|
||||||
|
+ len -= mblength;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len == 0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ month = (char *) alloca (len + 1);
|
||||||
|
+
|
||||||
|
+ tmp = (char *) alloca (len + 1);
|
||||||
|
+ memcpy (tmp, s, len);
|
||||||
|
+ tmp[len] = '\0';
|
||||||
|
+ pp = (const char **)&tmp;
|
||||||
|
+ month_wcs = (wchar_t *) alloca ((len + 1) * sizeof (wchar_t));
|
||||||
|
+ memset (&state, '\0', sizeof(mbstate_t));
|
||||||
|
+
|
||||||
|
+ wclength = mbsrtowcs (month_wcs, pp, len + 1, &state);
|
||||||
|
+ assert (wclength != (size_t)-1 && *pp == NULL);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < wclength; i++)
|
||||||
|
+ {
|
||||||
|
+ month_wcs[i] = towupper(month_wcs[i]);
|
||||||
|
+ if (iswblank (month_wcs[i]))
|
||||||
|
+ {
|
||||||
|
+ month_wcs[i] = L'\0';
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ wpp = (const wchar_t **)&month_wcs;
|
||||||
|
+
|
||||||
|
+ mblength = wcsrtombs (month, wpp, len + 1, &state);
|
||||||
|
+ assert (mblength != (-1) && *wpp == NULL);
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ int ix = (lo + hi) / 2;
|
||||||
|
+
|
||||||
|
+ if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0)
|
||||||
|
+ hi = ix;
|
||||||
|
+ else
|
||||||
|
+ lo = ix;
|
||||||
|
+ }
|
||||||
|
+ while (hi - lo > 1);
|
||||||
|
+
|
||||||
|
+ result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name))
|
||||||
|
+ ? monthtab[lo].val : 0);
|
||||||
|
+
|
||||||
|
+ return result;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Compare two lines A and B trying every key in sequence until there
|
||||||
|
are no more keys or a difference is found. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
-keycompare (const struct line *a, const struct line *b)
|
||||||
|
+keycompare_uni (const struct line *a, const struct line *b)
|
||||||
|
{
|
||||||
|
struct keyfield const *key = keylist;
|
||||||
|
|
||||||
|
@@ -1326,6 +1679,177 @@
|
||||||
|
return key->reverse ? -diff : diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+static int
|
||||||
|
+keycompare_mb (const struct line *a, const struct line *b)
|
||||||
|
+{
|
||||||
|
+ struct keyfield *key = keylist;
|
||||||
|
+
|
||||||
|
+ /* For the first iteration only, the key positions have been
|
||||||
|
+ precomputed for us. */
|
||||||
|
+ char *texta = a->keybeg;
|
||||||
|
+ char *textb = b->keybeg;
|
||||||
|
+ char *lima = a->keylim;
|
||||||
|
+ char *limb = b->keylim;
|
||||||
|
+
|
||||||
|
+ size_t mblength_a, mblength_b;
|
||||||
|
+ wchar_t wc_a, wc_b;
|
||||||
|
+ mbstate_t state_a, state_b;
|
||||||
|
+
|
||||||
|
+ int diff;
|
||||||
|
+
|
||||||
|
+ memset (&state_a, '\0', sizeof(mbstate_t));
|
||||||
|
+ memset (&state_b, '\0', sizeof(mbstate_t));
|
||||||
|
+
|
||||||
|
+ for (;;)
|
||||||
|
+ {
|
||||||
|
+ unsigned char *translate = (unsigned char *) key->translate;
|
||||||
|
+ bool const *ignore = key->ignore;
|
||||||
|
+
|
||||||
|
+ /* Find the lengths. */
|
||||||
|
+ size_t lena = lima <= texta ? 0 : lima - texta;
|
||||||
|
+ size_t lenb = limb <= textb ? 0 : limb - textb;
|
||||||
|
+
|
||||||
|
+ /* Actually compare the fields. */
|
||||||
|
+ if (key->numeric | key->general_numeric)
|
||||||
|
+ {
|
||||||
|
+ char savea = *lima, saveb = *limb;
|
||||||
|
+
|
||||||
|
+ *lima = *limb = '\0';
|
||||||
|
+ if (force_general_numcompare)
|
||||||
|
+ diff = general_numcompare (texta, textb);
|
||||||
|
+ else
|
||||||
|
+ diff = ((key->numeric ? numcompare : general_numcompare)
|
||||||
|
+ (texta, textb));
|
||||||
|
+ *lima = savea, *limb = saveb;
|
||||||
|
+ }
|
||||||
|
+ else if (key->month)
|
||||||
|
+ diff = getmonth (texta, lena) - getmonth (textb, lenb);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (ignore || translate)
|
||||||
|
+ {
|
||||||
|
+ char *copy_a = (char *) alloca (lena + 1 + lenb + 1);
|
||||||
|
+ char *copy_b = copy_a + lena + 1;
|
||||||
|
+ size_t new_len_a, new_len_b;
|
||||||
|
+ size_t i, j;
|
||||||
|
+
|
||||||
|
+ /* Ignore and/or translate chars before comparing. */
|
||||||
|
+# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ wchar_t uwc; \
|
||||||
|
+ char mbc[MB_LEN_MAX]; \
|
||||||
|
+ mbstate_t state_wc; \
|
||||||
|
+ \
|
||||||
|
+ for (NEW_LEN = i = 0; i < LEN;) \
|
||||||
|
+ { \
|
||||||
|
+ mbstate_t state_bak; \
|
||||||
|
+ \
|
||||||
|
+ state_bak = STATE; \
|
||||||
|
+ MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE); \
|
||||||
|
+ \
|
||||||
|
+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1 \
|
||||||
|
+ || MBLENGTH == 0) \
|
||||||
|
+ { \
|
||||||
|
+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1) \
|
||||||
|
+ STATE = state_bak; \
|
||||||
|
+ if (!ignore) \
|
||||||
|
+ COPY[NEW_LEN++] = TEXT[i++]; \
|
||||||
|
+ continue; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (ignore) \
|
||||||
|
+ { \
|
||||||
|
+ if ((ignore == nonprinting && !iswprint (WC)) \
|
||||||
|
+ || (ignore == nondictionary \
|
||||||
|
+ && !iswalnum (WC) && !iswblank (WC))) \
|
||||||
|
+ { \
|
||||||
|
+ i += MBLENGTH; \
|
||||||
|
+ continue; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (translate) \
|
||||||
|
+ { \
|
||||||
|
+ \
|
||||||
|
+ uwc = towupper(WC); \
|
||||||
|
+ if (WC == uwc) \
|
||||||
|
+ { \
|
||||||
|
+ memcpy (mbc, TEXT + i, MBLENGTH); \
|
||||||
|
+ i += MBLENGTH; \
|
||||||
|
+ } \
|
||||||
|
+ else \
|
||||||
|
+ { \
|
||||||
|
+ i += MBLENGTH; \
|
||||||
|
+ WC = uwc; \
|
||||||
|
+ memset (&state_wc, '\0', sizeof (mbstate_t)); \
|
||||||
|
+ \
|
||||||
|
+ MBLENGTH = wcrtomb (mbc, WC, &state_wc); \
|
||||||
|
+ assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0); \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ for (j = 0; j < MBLENGTH; j++) \
|
||||||
|
+ COPY[NEW_LEN++] = mbc[j]; \
|
||||||
|
+ } \
|
||||||
|
+ else \
|
||||||
|
+ for (j = 0; j < MBLENGTH; j++) \
|
||||||
|
+ COPY[NEW_LEN++] = TEXT[i++]; \
|
||||||
|
+ } \
|
||||||
|
+ COPY[NEW_LEN] = '\0'; \
|
||||||
|
+ } \
|
||||||
|
+ while (0)
|
||||||
|
+ IGNORE_CHARS (new_len_a, lena, texta, copy_a,
|
||||||
|
+ wc_a, mblength_a, state_a);
|
||||||
|
+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
|
||||||
|
+ wc_b, mblength_b, state_b);
|
||||||
|
+ diff = xmemcoll (copy_a, new_len_a, copy_b, new_len_b);
|
||||||
|
+ }
|
||||||
|
+ else if (lena == 0)
|
||||||
|
+ diff = - NONZERO (lenb);
|
||||||
|
+ else if (lenb == 0)
|
||||||
|
+ goto greater;
|
||||||
|
+ else
|
||||||
|
+ diff = xmemcoll (texta, lena, textb, lenb);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (diff)
|
||||||
|
+ goto not_equal;
|
||||||
|
+
|
||||||
|
+ key = key->next;
|
||||||
|
+ if (! key)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ /* Find the beginning and limit of the next field. */
|
||||||
|
+ if (key->eword != -1)
|
||||||
|
+ lima = limfield (a, key), limb = limfield (b, key);
|
||||||
|
+ else
|
||||||
|
+ lima = a->text + a->length - 1, limb = b->text + b->length - 1;
|
||||||
|
+
|
||||||
|
+ if (key->sword != -1)
|
||||||
|
+ texta = begfield (a, key), textb = begfield (b, key);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ texta = a->text, textb = b->text;
|
||||||
|
+ if (key->skipsblanks)
|
||||||
|
+ {
|
||||||
|
+ while (texta < lima && ismbblank (texta, lima - texta, &mblength_a))
|
||||||
|
+ texta += mblength_a;
|
||||||
|
+ while (textb < limb && ismbblank (textb, limb - textb, &mblength_b))
|
||||||
|
+ textb += mblength_b;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+greater:
|
||||||
|
+ diff = 1;
|
||||||
|
+not_equal:
|
||||||
|
+ return key->reverse ? -diff : diff;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Compare two lines A and B, returning negative, zero, or positive
|
||||||
|
depending on whether A compares less than, equal to, or greater than B. */
|
||||||
|
|
||||||
|
@@ -2127,7 +2651,7 @@
|
||||||
|
atexit (close_stdout);
|
||||||
|
|
||||||
|
hard_LC_COLLATE = hard_locale (LC_COLLATE);
|
||||||
|
-#if HAVE_NL_LANGINFO
|
||||||
|
+#if HAVE_LANGINFO_CODESET
|
||||||
|
hard_LC_TIME = hard_locale (LC_TIME);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -2148,6 +2672,25 @@
|
||||||
|
thousands_sep = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+ if (MB_CUR_MAX > 1)
|
||||||
|
+ {
|
||||||
|
+ inittables = inittables_mb;
|
||||||
|
+ begfield = begfield_mb;
|
||||||
|
+ limfield = limfield_mb;
|
||||||
|
+ getmonth = getmonth_mb;
|
||||||
|
+ keycompare = keycompare_mb;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ {
|
||||||
|
+ inittables = inittables_uni;
|
||||||
|
+ begfield = begfield_uni;
|
||||||
|
+ limfield = limfield_uni;
|
||||||
|
+ keycompare = keycompare_uni;
|
||||||
|
+ getmonth = getmonth_uni;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
have_read_stdin = false;
|
||||||
|
inittables ();
|
||||||
|
|
||||||
|
@@ -2349,13 +2892,35 @@
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
{
|
||||||
|
- char newtab = optarg[0];
|
||||||
|
- if (! newtab)
|
||||||
|
+ char newtab[MB_LEN_MAX + 1];
|
||||||
|
+ size_t newtab_length = 1;
|
||||||
|
+ strncpy (newtab, optarg, MB_LEN_MAX);
|
||||||
|
+ if (! newtab[0])
|
||||||
|
error (SORT_FAILURE, 0, _("empty tab"));
|
||||||
|
- if (optarg[1])
|
||||||
|
+#if HAVE_MBRTOWC
|
||||||
|
+ if (MB_CUR_MAX > 1)
|
||||||
|
+ {
|
||||||
|
+ wchar_t wc;
|
||||||
|
+ mbstate_t state;
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ memset (&state, '\0', sizeof (mbstate_t));
|
||||||
|
+ newtab_length = mbrtowc (&wc, newtab, strnlen (newtab,
|
||||||
|
+ MB_LEN_MAX),
|
||||||
|
+ &state);
|
||||||
|
+ switch (newtab_length)
|
||||||
|
+ {
|
||||||
|
+ case (size_t) -1:
|
||||||
|
+ case (size_t) -2:
|
||||||
|
+ case 0:
|
||||||
|
+ newtab_length = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ if (newtab_length == 1 && optarg[1])
|
||||||
|
{
|
||||||
|
if (STREQ (optarg, "\\0"))
|
||||||
|
- newtab = '\0';
|
||||||
|
+ newtab[0] = '\0';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Provoke with `sort -txx'. Complain about
|
||||||
|
@@ -2366,9 +2931,12 @@
|
||||||
|
quote (optarg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (tab != TAB_DEFAULT && tab != newtab)
|
||||||
|
+ if (tab_length
|
||||||
|
+ && (tab_length != newtab_length
|
||||||
|
+ || memcmp (tab, newtab, tab_length) != 0))
|
||||||
|
error (SORT_FAILURE, 0, _("incompatible tabs"));
|
||||||
|
- tab = newtab;
|
||||||
|
+ memcpy (tab, newtab, newtab_length);
|
||||||
|
+ tab_length = newtab_length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ Patch715: coreutils-4.5.3-sysinfo.patch
|
|||||||
|
|
||||||
# (sb) lin18nux/lsb compliance
|
# (sb) lin18nux/lsb compliance
|
||||||
Patch800: coreutils-i18n.patch
|
Patch800: coreutils-i18n.patch
|
||||||
Patch801: coreutils-i18n-sort.patch
|
|
||||||
|
|
||||||
Patch907: coreutils-5.2.1-runuser.patch
|
Patch907: coreutils-5.2.1-runuser.patch
|
||||||
Patch908: coreutils-getgrouplist.patch
|
Patch908: coreutils-getgrouplist.patch
|
||||||
@ -92,7 +91,6 @@ the old GNU fileutils, sh-utils, and textutils packages.
|
|||||||
|
|
||||||
# li18nux/lsb
|
# li18nux/lsb
|
||||||
%patch800 -p1 -b .i18n
|
%patch800 -p1 -b .i18n
|
||||||
%patch801 -p1 -b .i18n-sort
|
|
||||||
|
|
||||||
# Coreutils
|
# Coreutils
|
||||||
%patch907 -p1 -b .runuser
|
%patch907 -p1 -b .runuser
|
||||||
@ -265,8 +263,8 @@ fi
|
|||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Fri Oct 28 2005 Tim Waugh <twaugh@redhat.com>
|
* Fri Oct 28 2005 Tim Waugh <twaugh@redhat.com>
|
||||||
|
- Finished porting i18n patch to sort.c.
|
||||||
- Fixed for sort-mb-tests (avoid +n syntax).
|
- Fixed for sort-mb-tests (avoid +n syntax).
|
||||||
- Start porting i18n patch to sort.c.
|
|
||||||
|
|
||||||
* Fri Oct 28 2005 Tim Waugh <twaugh@redhat.com> 5.92-0.2
|
* Fri Oct 28 2005 Tim Waugh <twaugh@redhat.com> 5.92-0.2
|
||||||
- Fix chgrp basic test.
|
- Fix chgrp basic test.
|
||||||
|
Loading…
Reference in New Issue
Block a user