summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/coreutils
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2011-02-03 20:40:40 -0600
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-02-07 16:52:41 +0000
commit522d16a70fb2f1ad922a4cac8d63f1dddc61ba8d (patch)
tree6507437450798a9759bbac328b298b00a9e41477 /meta/recipes-core/coreutils
parent427472e980cd6254a5e4ef37209b327e15af259b (diff)
downloadpoky-522d16a70fb2f1ad922a4cac8d63f1dddc61ba8d.tar.gz
coreutils: Add various bug fixes
Add a number of bug fixes, mostly imported from Fedora and Wind River Linux. cp-i-u: fix unnecessary prompting fix-install: Fix installing to a dangling symlink i18n: li18nux/lsb compliance ls-x: Fix incorrect output overflow: Fix potential overflow in who command Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
Diffstat (limited to 'meta/recipes-core/coreutils')
-rw-r--r--meta/recipes-core/coreutils/coreutils-6.9/coreutils-6.9-cp-i-u.patch118
-rw-r--r--meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-install.patch99
-rw-r--r--meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch4049
-rw-r--r--meta/recipes-core/coreutils/coreutils-6.9/coreutils-ls-x.patch115
-rw-r--r--meta/recipes-core/coreutils/coreutils-6.9/coreutils-overflow.patch17
-rw-r--r--meta/recipes-core/coreutils/coreutils_6.9.bb5
6 files changed, 4403 insertions, 0 deletions
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-6.9-cp-i-u.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-6.9-cp-i-u.patch
new file mode 100644
index 0000000000..6fec683bc3
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-6.9-cp-i-u.patch
@@ -0,0 +1,118 @@
1This patch was imported from the Fedora Core 8 coreutils-6.9-9 package.
2
3The package is stated as being Licensed as GPLv2+.
4
5Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
6
7----
8
9When "cp -i --update old new" would do nothing because "new" is
10newer than "old", cp would nonetheless prompt for whether it is
11ok to overwrite "new". Then, regardless of the response (because
12of the --update option), cp would do nothing.
13
14The following patch eliminates the unnecessary prompt in that case.
15
16diff --git a/src/copy.c b/src/copy.c
17index b7bf73b..0e549d2 100644
18--- a/src/copy.c
19+++ b/src/copy.c
20@@ -1210,6 +1210,30 @@ copy_internal (char const *src_name, char const *dst_name,
21 return false;
22 }
23
24+ if (!S_ISDIR (src_mode) && x->update)
25+ {
26+ /* When preserving time stamps (but not moving within a file
27+ system), don't worry if the destination time stamp is
28+ less than the source merely because of time stamp
29+ truncation. */
30+ int options = ((x->preserve_timestamps
31+ && ! (x->move_mode
32+ && dst_sb.st_dev == src_sb.st_dev))
33+ ? UTIMECMP_TRUNCATE_SOURCE
34+ : 0);
35+
36+ if (0 <= utimecmp (dst_name, &dst_sb, &src_sb, options))
37+ {
38+ /* We're using --update and the destination is not older
39+ than the source, so do not copy or move. Pretend the
40+ rename succeeded, so the caller (if it's mv) doesn't
41+ end up removing the source file. */
42+ if (rename_succeeded)
43+ *rename_succeeded = true;
44+ return true;
45+ }
46+ }
47+
48 /* When there is an existing destination file, we may end up
49 returning early, and hence not copying/moving the file.
50 This may be due to an interactive `negative' reply to the
51@@ -1302,30 +1326,6 @@ copy_internal (char const *src_name, char const *dst_name,
52 return false;
53 }
54 }
55-
56- if (x->update)
57- {
58- /* When preserving time stamps (but not moving within a file
59- system), don't worry if the destination time stamp is
60- less than the source merely because of time stamp
61- truncation. */
62- int options = ((x->preserve_timestamps
63- && ! (x->move_mode
64- && dst_sb.st_dev == src_sb.st_dev))
65- ? UTIMECMP_TRUNCATE_SOURCE
66- : 0);
67-
68- if (0 <= utimecmp (dst_name, &dst_sb, &src_sb, options))
69- {
70- /* We're using --update and the destination is not older
71- than the source, so do not copy or move. Pretend the
72- rename succeeded, so the caller (if it's mv) doesn't
73- end up removing the source file. */
74- if (rename_succeeded)
75- *rename_succeeded = true;
76- return true;
77- }
78- }
79 }
80
81 if (x->move_mode)
82diff --git a/tests/mv/update b/tests/mv/update
83index 0c06024..6c3d149 100755
84--- a/tests/mv/update
85+++ b/tests/mv/update
86@@ -1,7 +1,7 @@
87 #!/bin/sh
88 # make sure --update works as advertised
89
90-# Copyright (C) 2001, 2004, 2006 Free Software Foundation, Inc.
91+# Copyright (C) 2001, 2004, 2006-2007 Free Software Foundation, Inc.
92
93 # This program is free software; you can redistribute it and/or modify
94 # it under the terms of the GNU General Public License as published by
95@@ -46,11 +46,16 @@ fi
96
97 fail=0
98
99-for cp_or_mv in cp mv; do
100- # This is a no-op.
101- $cp_or_mv --update old new || fail=1
102- case "`cat new`" in new) ;; *) fail=1 ;; esac
103- case "`cat old`" in old) ;; *) fail=1 ;; esac
104+for interactive in '' -i; do
105+ for cp_or_mv in cp mv; do
106+ # This is a no-op, with no prompt.
107+ # With coreutils-6.9 and earlier, using --update with -i would
108+ # mistakenly elicit a prompt.
109+ $cp_or_mv $interactive --update old new < /dev/null > out 2>&1 || fail=1
110+ test -s out && fail=1
111+ case "`cat new`" in new) ;; *) fail=1 ;; esac
112+ case "`cat old`" in old) ;; *) fail=1 ;; esac
113+ done
114 done
115
116 # This will actually perform the rename.
117--
1181.5.3.rc1.16.g9d6f
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-install.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-install.patch
new file mode 100644
index 0000000000..1b989f5311
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-install.patch
@@ -0,0 +1,99 @@
1The install command doesn't over write the dangling symlink, for
2example:
3
4$ install fileA /tmp/fileA
5
6If /tmp/fileA is a dangling symlink, there would be an error:
7
8install: cannot create regular file '/tmp/fileA': File exists
9
10This is because of the following code in copy.c:
11
12 if (!new_dst)
13 {
14 if (XSTAT (x, dst_name, &dst_sb) != 0)
15 {
16 if (errno != ENOENT)
17 {
18 error (0, errno, _("cannot stat %s"), quote (dst_name));
19 return false;
20 }
21 else
22 {
23 new_dst = true;
24 }
25 }
26
27XSTAT() use stat() for dst_name(the dangling symlink /tmp/fileA) when
28install.c invokes it, and stat will set errno to ENOENT, and then
29new_dst will be set to true which means that /tmp/fileA doesn't exist,
30then we will create /tmp/fileA without remove it first, so the error
31comes.
32
33This is fixed in a way which adds the member cmd_install in
34struct cp_options to make sure my change only affected to the install
35command and use lstat to fix the problem.
36
37Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
38Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
39
40---
41 src/copy.c | 10 +++++++++-
42 src/copy.h | 3 +++
43 src/install.c | 1 +
44 3 files changed, 13 insertions(+), 1 deletions(-)
45
46diff --git a/src/copy.c b/src/copy.c
47--- a/src/copy.c
48+++ b/src/copy.c
49@@ -1029,6 +1029,7 @@ copy_internal (char const *src_name, char const *dst_name,
50 bool delayed_ok;
51 bool copied_as_regular = false;
52 bool preserve_metadata;
53+ int dst_stat_result;
54
55 if (x->move_mode && rename_succeeded)
56 *rename_succeeded = false;
57@@ -1069,7 +1070,14 @@ copy_internal (char const *src_name, char const *dst_name,
58
59 if (!new_dst)
60 {
61- if (XSTAT (x, dst_name, &dst_sb) != 0)
62+ if ( x->cmd_install && ( x->backup_type == no_backups))
63+ dst_stat_result = lstat (dst_name, &dst_sb);
64+ else
65+ {
66+ dst_stat_result = XSTAT (x, dst_name, &dst_sb);
67+ }
68+
69+ if (dst_stat_result != 0)
70 {
71 if (errno != ENOENT)
72 {
73diff --git a/src/copy.h b/src/copy.h
74--- a/src/copy.h
75+++ b/src/copy.h
76@@ -114,6 +114,9 @@ struct cp_options
77 If that fails, then resort to copying. */
78 bool move_mode;
79
80+ /* For the install command */
81+ bool cmd_install;
82+
83 /* Whether this process has appropriate privileges to chown a file
84 whose owner is not the effective user ID. */
85 bool chown_privileges;
86diff --git a/src/install.c b/src/install.c
87--- a/src/install.c
88+++ b/src/install.c
89@@ -149,6 +149,7 @@ cp_option_init (struct cp_options *x)
90 x->hard_link = false;
91 x->interactive = I_UNSPECIFIED;
92 x->move_mode = false;
93+ x->cmd_install = true;
94 x->chown_privileges = chown_privileges ();
95 x->one_file_system = false;
96 x->preserve_ownership = false;
97--
981.7.0.1
99
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch
new file mode 100644
index 0000000000..3587186af1
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch
@@ -0,0 +1,4049 @@
1This patch was imported from the Fedora Core 8 coreutils-6.9-9 package.
2
3The package is stated as being Licensed as GPLv2+.
4
5The comment indicates that the purpose is lin18nux/lsb compliance.
6
7Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
8
9--- /dev/null 2007-03-01 09:16:39.219409909 +0000
10+++ coreutils-6.8+/tests/sort/sort-mb-tests 2007-03-01 15:08:24.000000000 +0000
11@@ -0,0 +1,58 @@
12+#! /bin/sh
13+case $# in
14+ 0) xx='../../src/sort';;
15+ *) xx="$1";;
16+esac
17+test "$VERBOSE" && echo=echo || echo=:
18+$echo testing program: $xx
19+errors=0
20+test "$srcdir" || srcdir=.
21+test "$VERBOSE" && $xx --version 2> /dev/null
22+
23+export LC_ALL=en_US.UTF-8
24+locale -k LC_CTYPE 2>&1 | grep -q charmap.*UTF-8 || exit 77
25+errors=0
26+
27+$xx -t ï¼  -k2 -n mb1.I > mb1.O
28+code=$?
29+if test $code != 0; then
30+ $echo "Test mb1 failed: $xx return code $code differs from expected value 0" 1>&2
31+ errors=`expr $errors + 1`
32+else
33+ cmp mb1.O $srcdir/mb1.X > /dev/null 2>&1
34+ case $? in
35+ 0) if test "$VERBOSE"; then $echo "passed mb1"; fi;;
36+ 1) $echo "Test mb1 failed: files mb1.O and $srcdir/mb1.X differ" 1>&2
37+ (diff -c mb1.O $srcdir/mb1.X) 2> /dev/null
38+ errors=`expr $errors + 1`;;
39+ 2) $echo "Test mb1 may have failed." 1>&2
40+ $echo The command "cmp mb1.O $srcdir/mb1.X" failed. 1>&2
41+ errors=`expr $errors + 1`;;
42+ esac
43+fi
44+
45+$xx -t ï¼  -k4 -n mb2.I > mb2.O
46+code=$?
47+if test $code != 0; then
48+ $echo "Test mb2 failed: $xx return code $code differs from expected value 0" 1>&2
49+ errors=`expr $errors + 1`
50+else
51+ cmp mb2.O $srcdir/mb2.X > /dev/null 2>&1
52+ case $? in
53+ 0) if test "$VERBOSE"; then $echo "passed mb2"; fi;;
54+ 1) $echo "Test mb2 failed: files mb2.O and $srcdir/mb2.X differ" 1>&2
55+ (diff -c mb2.O $srcdir/mb2.X) 2> /dev/null
56+ errors=`expr $errors + 1`;;
57+ 2) $echo "Test mb2 may have failed." 1>&2
58+ $echo The command "cmp mb2.O $srcdir/mb2.X" failed. 1>&2
59+ errors=`expr $errors + 1`;;
60+ esac
61+fi
62+
63+if test $errors = 0; then
64+ $echo Passed all 113 tests. 1>&2
65+else
66+ $echo Failed $errors tests. 1>&2
67+fi
68+test $errors = 0 || errors=1
69+exit $errors
70--- /dev/null 2007-03-01 09:16:39.219409909 +0000
71+++ coreutils-6.8+/tests/sort/mb2.I 2007-03-01 15:08:24.000000000 +0000
72@@ -0,0 +1,4 @@
73+Apple@AA10@@20
74+Banana@AA5@@30
75+Citrus@AA20@@5
76+Cherry@AA30@@10
77--- /dev/null 2007-03-01 09:16:39.219409909 +0000
78+++ coreutils-6.8+/tests/sort/mb2.X 2007-03-01 15:08:24.000000000 +0000
79@@ -0,0 +1,4 @@
80+Citrus@AA20@@5
81+Cherry@AA30@@10
82+Apple@AA10@@20
83+Banana@AA5@@30
84--- /dev/null 2007-03-01 09:16:39.219409909 +0000
85+++ coreutils-6.8+/tests/sort/mb1.I 2007-03-01 15:08:24.000000000 +0000
86@@ -0,0 +1,4 @@
87+Appleï¼ 10
88+Bananaï¼ 5
89+Citrusï¼ 20
90+Cherryï¼ 30
91--- /dev/null 2007-03-01 09:16:39.219409909 +0000
92+++ coreutils-6.8+/tests/sort/mb1.X 2007-03-01 15:08:24.000000000 +0000
93@@ -0,0 +1,4 @@
94+Bananaï¼ 5
95+Appleï¼ 10
96+Citrusï¼ 20
97+Cherryï¼ 30
98--- coreutils-6.8+/tests/sort/Makefile.am.i18n 2007-01-24 07:47:37.000000000 +0000
99+++ coreutils-6.8+/tests/sort/Makefile.am 2007-03-01 15:09:59.000000000 +0000
100@@ -66,15 +66,17 @@
101 bigfield.O bigfield.E
102 ##test-files-end
103
104-EXTRA_DIST = Test.pm $x-tests $(explicit) $(maint_gen)
105-noinst_SCRIPTS = $x-tests
106+run_gen += mb1.0 mb2.0
107+
108+EXTRA_DIST = Test.pm $x-tests $(explicit) $(maint_gen) mb1.I mb1.X mb2.I mb2.X
109+noinst_SCRIPTS = $x-tests # $x-mb-tests
110 TESTS_ENVIRONMENT = \
111 CU_TEST_NAME=`basename $(abs_srcdir)`,$$tst \
112 PATH="$(VG_PATH_PREFIX)`pwd`/../../src$(PATH_SEPARATOR)$$PATH"
113
114 editpl = sed -e 's,@''PERL''@,$(PERL),g' -e 's,@''srcdir''@,$(srcdir),g'
115
116-TESTS = $x-tests
117+TESTS = $x-tests $x-mb-tests
118
119 mk_script = $(srcdir)/../mk-script
120 $(srcdir)/$x-tests: $(mk_script) Test.pm Makefile.am
121--- coreutils-6.8+/lib/linebuffer.h.i18n 2005-05-14 07:44:24.000000000 +0100
122+++ coreutils-6.8+/lib/linebuffer.h 2007-03-01 15:08:24.000000000 +0000
123@@ -22,6 +22,11 @@
124
125 # include <stdio.h>
126
127+/* Get mbstate_t. */
128+# if HAVE_WCHAR_H
129+# include <wchar.h>
130+# endif
131+
132 /* A `struct linebuffer' holds a line of text. */
133
134 struct linebuffer
135@@ -29,6 +34,9 @@
136 size_t size; /* Allocated. */
137 size_t length; /* Used. */
138 char *buffer;
139+# if HAVE_WCHAR_H
140+ mbstate_t state;
141+# endif
142 };
143
144 /* Initialize linebuffer LINEBUFFER for use. */
145--- coreutils-6.8+/src/expand.c.i18n 2007-01-14 15:41:28.000000000 +0000
146+++ coreutils-6.8+/src/expand.c 2007-03-01 15:08:24.000000000 +0000
147@@ -38,11 +38,28 @@
148 #include <stdio.h>
149 #include <getopt.h>
150 #include <sys/types.h>
151+
152+/* Get mbstate_t, mbrtowc(), wcwidth(). */
153+#if HAVE_WCHAR_H
154+# include <wchar.h>
155+#endif
156+
157 #include "system.h"
158 #include "error.h"
159 #include "quote.h"
160 #include "xstrndup.h"
161
162+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
163+ installation; work around this configuration error. */
164+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
165+# define MB_LEN_MAX 16
166+#endif
167+
168+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
169+#if HAVE_MBRTOWC && defined mbstate_t
170+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
171+#endif
172+
173 /* The official name of this program (e.g., no `g' prefix). */
174 #define PROGRAM_NAME "expand"
175
176@@ -183,6 +200,7 @@
177 stops = num_start + len - 1;
178 }
179 }
180+
181 else
182 {
183 error (0, 0, _("tab size contains invalid character(s): %s"),
184@@ -365,6 +383,142 @@
185 }
186 }
187
188+#if HAVE_MBRTOWC
189+static void
190+expand_multibyte (void)
191+{
192+ FILE *fp; /* Input strem. */
193+ mbstate_t i_state; /* Current shift state of the input stream. */
194+ mbstate_t i_state_bak; /* Back up the I_STATE. */
195+ mbstate_t o_state; /* Current shift state of the output stream. */
196+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */
197+ char *bufpos; /* Next read position of BUF. */
198+ size_t buflen = 0; /* The length of the byte sequence in buf. */
199+ wchar_t wc; /* A gotten wide character. */
200+ size_t mblength; /* The byte size of a multibyte character
201+ which shows as same character as WC. */
202+ int tab_index = 0; /* Index in `tab_list' of next tabstop. */
203+ int column = 0; /* Column on screen of the next char. */
204+ int next_tab_column; /* Column the next tab stop is on. */
205+ int convert = 1; /* If nonzero, perform translations. */
206+
207+ fp = next_file ((FILE *) NULL);
208+ if (fp == NULL)
209+ return;
210+
211+ memset (&o_state, '\0', sizeof(mbstate_t));
212+ memset (&i_state, '\0', sizeof(mbstate_t));
213+
214+ for (;;)
215+ {
216+ /* Refill the buffer BUF. */
217+ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp))
218+ {
219+ memmove (buf, bufpos, buflen);
220+ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp);
221+ bufpos = buf;
222+ }
223+
224+ /* No character is left in BUF. */
225+ if (buflen < 1)
226+ {
227+ fp = next_file (fp);
228+
229+ if (fp == NULL)
230+ break; /* No more files. */
231+ else
232+ {
233+ memset (&i_state, '\0', sizeof(mbstate_t));
234+ continue;
235+ }
236+ }
237+
238+ /* Get a wide character. */
239+ i_state_bak = i_state;
240+ mblength = mbrtowc (&wc, bufpos, buflen, &i_state);
241+
242+ switch (mblength)
243+ {
244+ case (size_t)-1: /* illegal byte sequence. */
245+ case (size_t)-2:
246+ mblength = 1;
247+ i_state = i_state_bak;
248+ if (convert)
249+ {
250+ ++column;
251+ if (convert_entire_line == 0)
252+ convert = 0;
253+ }
254+ putchar (*bufpos);
255+ break;
256+
257+ case 0: /* null. */
258+ mblength = 1;
259+ if (convert && convert_entire_line == 0)
260+ convert = 0;
261+ putchar ('\0');
262+ break;
263+
264+ default:
265+ if (wc == L'\n') /* LF. */
266+ {
267+ tab_index = 0;
268+ column = 0;
269+ convert = 1;
270+ putchar ('\n');
271+ }
272+ else if (wc == L'\t' && convert) /* Tab. */
273+ {
274+ if (tab_size == 0)
275+ {
276+ /* Do not let tab_index == first_free_tab;
277+ stop when it is 1 less. */
278+ while (tab_index < first_free_tab - 1
279+ && column >= tab_list[tab_index])
280+ tab_index++;
281+ next_tab_column = tab_list[tab_index];
282+ if (tab_index < first_free_tab - 1)
283+ tab_index++;
284+ if (column >= next_tab_column)
285+ next_tab_column = column + 1;
286+ }
287+ else
288+ next_tab_column = column + tab_size - column % tab_size;
289+
290+ while (column < next_tab_column)
291+ {
292+ putchar (' ');
293+ ++column;
294+ }
295+ }
296+ else /* Others. */
297+ {
298+ if (convert)
299+ {
300+ if (wc == L'\b')
301+ {
302+ if (column > 0)
303+ --column;
304+ }
305+ else
306+ {
307+ int width; /* The width of WC. */
308+
309+ width = wcwidth (wc);
310+ column += (width > 0) ? width : 0;
311+ if (convert_entire_line == 0)
312+ convert = 0;
313+ }
314+ }
315+ fwrite (bufpos, sizeof(char), mblength, stdout);
316+ }
317+ }
318+ buflen -= mblength;
319+ bufpos += mblength;
320+ }
321+}
322+#endif
323+
324 int
325 main (int argc, char **argv)
326 {
327@@ -429,7 +583,12 @@
328
329 file_list = (optind < argc ? &argv[optind] : stdin_argv);
330
331- expand ();
332+#if HAVE_MBRTOWC
333+ if (MB_CUR_MAX > 1)
334+ expand_multibyte ();
335+ else
336+#endif
337+ expand ();
338
339 if (have_read_stdin && fclose (stdin) != 0)
340 error (EXIT_FAILURE, errno, "-");
341--- coreutils-6.8+/src/join.c.i18n 2007-01-14 15:41:28.000000000 +0000
342+++ coreutils-6.8+/src/join.c 2007-03-01 15:08:24.000000000 +0000
343@@ -23,16 +23,30 @@
344 #include <sys/types.h>
345 #include <getopt.h>
346
347+/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth(). */
348+#if HAVE_WCHAR_H
349+# include <wchar.h>
350+#endif
351+
352+/* Get iswblank(), towupper. */
353+#if HAVE_WCTYPE_H
354+# include <wctype.h>
355+#endif
356+
357 #include "system.h"
358 #include "error.h"
359 #include "hard-locale.h"
360 #include "linebuffer.h"
361-#include "memcasecmp.h"
362 #include "quote.h"
363 #include "stdio--.h"
364 #include "xmemcoll.h"
365 #include "xstrtol.h"
366
367+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
368+#if HAVE_MBRTOWC && defined mbstate_t
369+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
370+#endif
371+
372 /* The official name of this program (e.g., no `g' prefix). */
373 #define PROGRAM_NAME "join"
374
375@@ -104,10 +118,12 @@
376 /* Last element in `outlist', where a new element can be added. */
377 static struct outlist *outlist_end = &outlist_head;
378
379-/* Tab character separating fields. If negative, fields are separated
380- by any nonempty string of blanks, otherwise by exactly one
381- tab character whose value (when cast to unsigned char) equals TAB. */
382-static int tab = -1;
383+/* Tab character separating fields. If NULL, fields are separated
384+ by any nonempty string of blanks. */
385+static char *tab = NULL;
386+
387+/* The number of bytes used for tab. */
388+static size_t tablen = 0;
389
390 static struct option const longopts[] =
391 {
392@@ -190,6 +206,8 @@
393
394 /* Fill in the `fields' structure in LINE. */
395
396+/* Fill in the `fields' structure in LINE. */
397+
398 static void
399 xfields (struct line *line)
400 {
401@@ -199,10 +217,11 @@
402 if (ptr == lim)
403 return;
404
405- if (0 <= tab)
406+ if (tab != NULL)
407 {
408+ unsigned char t = tab[0];
409 char *sep;
410- for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1)
411+ for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1)
412 extract_field (line, ptr, sep - ptr);
413 }
414 else
415@@ -229,6 +248,148 @@
416 extract_field (line, ptr, lim - ptr);
417 }
418
419+#if HAVE_MBRTOWC
420+static void
421+xfields_multibyte (struct line *line)
422+{
423+ char *ptr = line->buf.buffer;
424+ char const *lim = ptr + line->buf.length - 1;
425+ wchar_t wc = 0;
426+ size_t mblength = 1;
427+ mbstate_t state, state_bak;
428+
429+ memset (&state, 0, sizeof (mbstate_t));
430+
431+ if (ptr == lim)
432+ return;
433+
434+ if (tab != NULL)
435+ {
436+ unsigned char t = tab[0];
437+ char *sep = ptr;
438+ for (; ptr < lim; ptr = sep + mblength)
439+ {
440+ sep = ptr;
441+ while (sep < lim)
442+ {
443+ state_bak = state;
444+ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
445+
446+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
447+ {
448+ mblength = 1;
449+ state = state_bak;
450+ }
451+ mblength = (mblength < 1) ? 1 : mblength;
452+
453+ if (mblength == tablen && !memcmp (sep, tab, mblength))
454+ break;
455+ else
456+ {
457+ sep += mblength;
458+ continue;
459+ }
460+ }
461+
462+ if (sep == lim)
463+ break;
464+
465+ extract_field (line, ptr, sep - ptr);
466+ }
467+ }
468+ else
469+ {
470+ /* Skip leading blanks before the first field. */
471+ while(ptr < lim)
472+ {
473+ state_bak = state;
474+ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
475+
476+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
477+ {
478+ mblength = 1;
479+ state = state_bak;
480+ break;
481+ }
482+ mblength = (mblength < 1) ? 1 : mblength;
483+
484+ if (!iswblank(wc))
485+ break;
486+ ptr += mblength;
487+ }
488+
489+ do
490+ {
491+ char *sep;
492+ state_bak = state;
493+ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
494+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
495+ {
496+ mblength = 1;
497+ state = state_bak;
498+ break;
499+ }
500+ mblength = (mblength < 1) ? 1 : mblength;
501+
502+ sep = ptr + mblength;
503+ while (sep != lim)
504+ {
505+ state_bak = state;
506+ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
507+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
508+ {
509+ mblength = 1;
510+ state = state_bak;
511+ break;
512+ }
513+ mblength = (mblength < 1) ? 1 : mblength;
514+
515+ if (iswblank (wc))
516+ break;
517+
518+ sep += mblength;
519+ }
520+
521+ extract_field (line, ptr, sep - ptr);
522+ if (sep == lim)
523+ return;
524+
525+ state_bak = state;
526+ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
527+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
528+ {
529+ mblength = 1;
530+ state = state_bak;
531+ break;
532+ }
533+ mblength = (mblength < 1) ? 1 : mblength;
534+
535+ ptr = sep + mblength;
536+ while (ptr != lim)
537+ {
538+ state_bak = state;
539+ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
540+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
541+ {
542+ mblength = 1;
543+ state = state_bak;
544+ break;
545+ }
546+ mblength = (mblength < 1) ? 1 : mblength;
547+
548+ if (!iswblank (wc))
549+ break;
550+
551+ ptr += mblength;
552+ }
553+ }
554+ while (ptr != lim);
555+ }
556+
557+ extract_field (line, ptr, lim - ptr);
558+}
559+#endif
560+
561 /* Read a line from FP into LINE and split it into fields.
562 Return true if successful. */
563
564@@ -249,6 +410,11 @@
565 line->nfields_allocated = 0;
566 line->nfields = 0;
567 line->fields = NULL;
568+#if HAVE_MBRTOWC
569+ if (MB_CUR_MAX > 1)
570+ xfields_multibyte (line);
571+ else
572+#endif
573 xfields (line);
574 return true;
575 }
576@@ -303,56 +469,114 @@
577 keycmp (struct line const *line1, struct line const *line2)
578 {
579 /* Start of field to compare in each file. */
580- char *beg1;
581- char *beg2;
582-
583- size_t len1;
584- size_t len2; /* Length of fields to compare. */
585+ char *beg[2];
586+ char *copy[2];
587+ size_t len[2]; /* Length of fields to compare. */
588 int diff;
589+ int i, j;
590
591 if (join_field_1 < line1->nfields)
592 {
593- beg1 = line1->fields[join_field_1].beg;
594- len1 = line1->fields[join_field_1].len;
595+ beg[0] = line1->fields[join_field_1].beg;
596+ len[0] = line1->fields[join_field_1].len;
597 }
598 else
599 {
600- beg1 = NULL;
601- len1 = 0;
602+ beg[0] = NULL;
603+ len[0] = 0;
604 }
605
606 if (join_field_2 < line2->nfields)
607 {
608- beg2 = line2->fields[join_field_2].beg;
609- len2 = line2->fields[join_field_2].len;
610+ beg[1] = line2->fields[join_field_2].beg;
611+ len[1] = line2->fields[join_field_2].len;
612 }
613 else
614 {
615- beg2 = NULL;
616- len2 = 0;
617+ beg[1] = NULL;
618+ len[1] = 0;
619 }
620
621- if (len1 == 0)
622- return len2 == 0 ? 0 : -1;
623- if (len2 == 0)
624+ if (len[0] == 0)
625+ return len[1] == 0 ? 0 : -1;
626+ if (len[1] == 0)
627 return 1;
628
629 if (ignore_case)
630 {
631- /* FIXME: ignore_case does not work with NLS (in particular,
632- with multibyte chars). */
633- diff = memcasecmp (beg1, beg2, MIN (len1, len2));
634+#ifdef HAVE_MBRTOWC
635+ if (MB_CUR_MAX > 1)
636+ {
637+ size_t mblength;
638+ wchar_t wc, uwc;
639+ mbstate_t state, state_bak;
640+
641+ memset (&state, '\0', sizeof (mbstate_t));
642+
643+ for (i = 0; i < 2; i++)
644+ {
645+ copy[i] = alloca (len[i] + 1);
646+
647+ for (j = 0; j < MIN (len[0], len[1]);)
648+ {
649+ state_bak = state;
650+ mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state);
651+
652+ switch (mblength)
653+ {
654+ case (size_t) -1:
655+ case (size_t) -2:
656+ state = state_bak;
657+ /* Fall through */
658+ case 0:
659+ mblength = 1;
660+ break;
661+
662+ default:
663+ uwc = towupper (wc);
664+
665+ if (uwc != wc)
666+ {
667+ mbstate_t state_wc;
668+
669+ memset (&state_wc, '\0', sizeof (mbstate_t));
670+ wcrtomb (copy[i] + j, uwc, &state_wc);
671+ }
672+ else
673+ memcpy (copy[i] + j, beg[i] + j, mblength);
674+ }
675+ j += mblength;
676+ }
677+ copy[i][j] = '\0';
678+ }
679+ }
680+ else
681+#endif
682+ {
683+ for (i = 0; i < 2; i++)
684+ {
685+ copy[i] = alloca (len[i] + 1);
686+
687+ for (j = 0; j < MIN (len[0], len[1]); j++)
688+ copy[i][j] = toupper (beg[i][j]);
689+
690+ copy[i][j] = '\0';
691+ }
692+ }
693 }
694 else
695 {
696- if (hard_LC_COLLATE)
697- return xmemcoll (beg1, len1, beg2, len2);
698- diff = memcmp (beg1, beg2, MIN (len1, len2));
699+ copy[0] = (unsigned char *) beg[0];
700+ copy[1] = (unsigned char *) beg[1];
701 }
702
703+ if (hard_LC_COLLATE)
704+ return xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]);
705+ diff = memcmp (copy[0], copy[1], MIN (len[0], len[1]));
706+
707 if (diff)
708 return diff;
709- return len1 < len2 ? -1 : len1 != len2;
710+ return len[0] - len[1];
711 }
712
713 /* Print field N of LINE if it exists and is nonempty, otherwise
714@@ -377,11 +601,18 @@
715
716 /* Print the join of LINE1 and LINE2. */
717
718+#define PUT_TAB_CHAR \
719+ do \
720+ { \
721+ (tab != NULL) ? \
722+ fwrite(tab, sizeof(char), tablen, stdout) : putchar (' '); \
723+ } \
724+ while (0)
725+
726 static void
727 prjoin (struct line const *line1, struct line const *line2)
728 {
729 const struct outlist *outlist;
730- char output_separator = tab < 0 ? ' ' : tab;
731
732 outlist = outlist_head.next;
733 if (outlist)
734@@ -397,12 +628,12 @@
735 if (o->file == 0)
736 {
737 if (line1 == &uni_blank)
738- {
739+ {
740 line = line2;
741 field = join_field_2;
742 }
743 else
744- {
745+ {
746 line = line1;
747 field = join_field_1;
748 }
749@@ -416,7 +647,7 @@
750 o = o->next;
751 if (o == NULL)
752 break;
753- putchar (output_separator);
754+ PUT_TAB_CHAR;
755 }
756 putchar ('\n');
757 }
758@@ -434,23 +665,23 @@
759 prfield (join_field_1, line1);
760 for (i = 0; i < join_field_1 && i < line1->nfields; ++i)
761 {
762- putchar (output_separator);
763+ PUT_TAB_CHAR;
764 prfield (i, line1);
765 }
766 for (i = join_field_1 + 1; i < line1->nfields; ++i)
767 {
768- putchar (output_separator);
769+ PUT_TAB_CHAR;
770 prfield (i, line1);
771 }
772
773 for (i = 0; i < join_field_2 && i < line2->nfields; ++i)
774 {
775- putchar (output_separator);
776+ PUT_TAB_CHAR;
777 prfield (i, line2);
778 }
779 for (i = join_field_2 + 1; i < line2->nfields; ++i)
780 {
781- putchar (output_separator);
782+ PUT_TAB_CHAR;
783 prfield (i, line2);
784 }
785 putchar ('\n');
786@@ -859,20 +1090,41 @@
787
788 case 't':
789 {
790- unsigned char newtab = optarg[0];
791- if (! newtab)
792+ char *newtab;
793+ size_t newtablen;
794+ if (! optarg[0])
795 error (EXIT_FAILURE, 0, _("empty tab"));
796- if (optarg[1])
797+ newtab = xstrdup (optarg);
798+#if HAVE_MBRTOWC
799+ if (MB_CUR_MAX > 1)
800+ {
801+ mbstate_t state;
802+
803+ memset (&state, 0, sizeof (mbstate_t));
804+ newtablen = mbrtowc (NULL, newtab,
805+ strnlen (newtab, MB_LEN_MAX),
806+ &state);
807+ if (newtablen == (size_t) 0
808+ || newtablen == (size_t) -1
809+ || newtablen == (size_t) -2)
810+ newtablen = 1;
811+ }
812+ else
813+#endif
814+ newtablen = 1;
815+
816+ if (newtablen == 1 && newtab[1])
817+ {
818+ if (STREQ (newtab, "\\0"))
819+ newtab[0] = '\0';
820+ }
821+ if (tab != NULL && strcmp (tab, newtab))
822 {
823- if (STREQ (optarg, "\\0"))
824- newtab = '\0';
825- else
826- error (EXIT_FAILURE, 0, _("multi-character tab %s"),
827- quote (optarg));
828+ free (newtab);
829+ error (EXIT_FAILURE, 0, _("incompatible tabs"));
830 }
831- if (0 <= tab && tab != newtab)
832- error (EXIT_FAILURE, 0, _("incompatible tabs"));
833 tab = newtab;
834+ tablen = newtablen;
835 }
836 break;
837
838--- coreutils-6.8+/src/uniq.c.i18n 2007-01-14 15:41:28.000000000 +0000
839+++ coreutils-6.8+/src/uniq.c 2007-03-01 15:08:24.000000000 +0000
840@@ -23,6 +23,16 @@
841 #include <getopt.h>
842 #include <sys/types.h>
843
844+/* Get mbstate_t, mbrtowc(). */
845+#if HAVE_WCHAR_H
846+# include <wchar.h>
847+#endif
848+
849+/* Get isw* functions. */
850+#if HAVE_WCTYPE_H
851+# include <wctype.h>
852+#endif
853+
854 #include "system.h"
855 #include "argmatch.h"
856 #include "linebuffer.h"
857@@ -32,7 +42,19 @@
858 #include "quote.h"
859 #include "xmemcoll.h"
860 #include "xstrtol.h"
861-#include "memcasecmp.h"
862+#include "xmemcoll.h"
863+
864+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
865+ installation; work around this configuration error. */
866+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
867+# define MB_LEN_MAX 16
868+#endif
869+
870+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
871+#if HAVE_MBRTOWC && defined mbstate_t
872+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
873+#endif
874+
875
876 /* The official name of this program (e.g., no `g' prefix). */
877 #define PROGRAM_NAME "uniq"
878@@ -109,6 +131,10 @@
879 /* Select whether/how to delimit groups of duplicate lines. */
880 static enum delimit_method delimit_groups;
881
882+/* Function pointers. */
883+static char *
884+(*find_field) (struct linebuffer *line);
885+
886 static struct option const longopts[] =
887 {
888 {"count", no_argument, NULL, 'c'},
889@@ -198,7 +224,7 @@
890 return a pointer to the beginning of the line's field to be compared. */
891
892 static char *
893-find_field (const struct linebuffer *line)
894+find_field_uni (struct linebuffer *line)
895 {
896 size_t count;
897 char *lp = line->buffer;
898@@ -219,6 +245,83 @@
899 return lp + i;
900 }
901
902+#if HAVE_MBRTOWC
903+
904+# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL) \
905+ do \
906+ { \
907+ mbstate_t state_bak; \
908+ \
909+ CONVFAIL = 0; \
910+ state_bak = *STATEP; \
911+ \
912+ MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP); \
913+ \
914+ switch (MBLENGTH) \
915+ { \
916+ case (size_t)-2: \
917+ case (size_t)-1: \
918+ *STATEP = state_bak; \
919+ CONVFAIL++; \
920+ /* Fall through */ \
921+ case 0: \
922+ MBLENGTH = 1; \
923+ } \
924+ } \
925+ while (0)
926+
927+static char *
928+find_field_multi (struct linebuffer *line)
929+{
930+ size_t count;
931+ char *lp = line->buffer;
932+ size_t size = line->length - 1;
933+ size_t pos;
934+ size_t mblength;
935+ wchar_t wc;
936+ mbstate_t *statep;
937+ int convfail;
938+
939+ pos = 0;
940+ statep = &(line->state);
941+
942+ /* skip fields. */
943+ for (count = 0; count < skip_fields && pos < size; count++)
944+ {
945+ while (pos < size)
946+ {
947+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
948+
949+ if (convfail || !iswblank (wc))
950+ {
951+ pos += mblength;
952+ break;
953+ }
954+ pos += mblength;
955+ }
956+
957+ while (pos < size)
958+ {
959+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
960+
961+ if (!convfail && iswblank (wc))
962+ break;
963+
964+ pos += mblength;
965+ }
966+ }
967+
968+ /* skip fields. */
969+ for (count = 0; count < skip_chars && pos < size; count++)
970+ {
971+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
972+ pos += mblength;
973+ }
974+
975+ return lp + pos;
976+}
977+#endif
978+
979 /* Return false if two strings OLD and NEW match, true if not.
980 OLD and NEW point not to the beginnings of the lines
981 but rather to the beginnings of the fields to compare.
982@@ -227,6 +330,8 @@
983 static bool
984 different (char *old, char *new, size_t oldlen, size_t newlen)
985 {
986+ char *copy_old, *copy_new;
987+
988 if (check_chars < oldlen)
989 oldlen = check_chars;
990 if (check_chars < newlen)
991@@ -234,14 +339,92 @@
992
993 if (ignore_case)
994 {
995- /* FIXME: This should invoke strcoll somehow. */
996- return oldlen != newlen || memcasecmp (old, new, oldlen);
997+ size_t i;
998+
999+ copy_old = alloca (oldlen + 1);
1000+ copy_new = alloca (oldlen + 1);
1001+
1002+ for (i = 0; i < oldlen; i++)
1003+ {
1004+ copy_old[i] = toupper (old[i]);
1005+ copy_new[i] = toupper (new[i]);
1006+ }
1007 }
1008- else if (hard_LC_COLLATE)
1009- return xmemcoll (old, oldlen, new, newlen) != 0;
1010 else
1011- return oldlen != newlen || memcmp (old, new, oldlen);
1012+ {
1013+ copy_old = (char *)old;
1014+ copy_new = (char *)new;
1015+ }
1016+
1017+ return xmemcoll (copy_old, oldlen, copy_new, newlen);
1018+}
1019+
1020+#if HAVE_MBRTOWC
1021+static int
1022+different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate)
1023+{
1024+ size_t i, j, chars;
1025+ const char *str[2];
1026+ char *copy[2];
1027+ size_t len[2];
1028+ mbstate_t state[2];
1029+ size_t mblength;
1030+ wchar_t wc, uwc;
1031+ mbstate_t state_bak;
1032+
1033+ str[0] = old;
1034+ str[1] = new;
1035+ len[0] = oldlen;
1036+ len[1] = newlen;
1037+ state[0] = oldstate;
1038+ state[1] = newstate;
1039+
1040+ for (i = 0; i < 2; i++)
1041+ {
1042+ copy[i] = alloca (len[i] + 1);
1043+
1044+ for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++)
1045+ {
1046+ state_bak = state[i];
1047+ mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i]));
1048+
1049+ switch (mblength)
1050+ {
1051+ case (size_t)-1:
1052+ case (size_t)-2:
1053+ state[i] = state_bak;
1054+ /* Fall through */
1055+ case 0:
1056+ mblength = 1;
1057+ break;
1058+
1059+ default:
1060+ if (ignore_case)
1061+ {
1062+ uwc = towupper (wc);
1063+
1064+ if (uwc != wc)
1065+ {
1066+ mbstate_t state_wc;
1067+
1068+ memset (&state_wc, '\0', sizeof(mbstate_t));
1069+ wcrtomb (copy[i] + j, uwc, &state_wc);
1070+ }
1071+ else
1072+ memcpy (copy[i] + j, str[i] + j, mblength);
1073+ }
1074+ else
1075+ memcpy (copy[i] + j, str[i] + j, mblength);
1076+ }
1077+ j += mblength;
1078+ }
1079+ copy[i][j] = '\0';
1080+ len[i] = j;
1081+ }
1082+
1083+ return xmemcoll (copy[0], len[0], copy[1], len[1]);
1084 }
1085+#endif
1086
1087 /* Output the line in linebuffer LINE to standard output
1088 provided that the switches say it should be output.
1089@@ -295,15 +478,43 @@
1090 {
1091 char *prevfield IF_LINT (= NULL);
1092 size_t prevlen IF_LINT (= 0);
1093+#if HAVE_MBRTOWC
1094+ mbstate_t prevstate;
1095+
1096+ memset (&prevstate, '\0', sizeof (mbstate_t));
1097+#endif
1098
1099 while (!feof (stdin))
1100 {
1101 char *thisfield;
1102 size_t thislen;
1103+#if HAVE_MBRTOWC
1104+ mbstate_t thisstate;
1105+#endif
1106+
1107 if (readlinebuffer (thisline, stdin) == 0)
1108 break;
1109 thisfield = find_field (thisline);
1110 thislen = thisline->length - 1 - (thisfield - thisline->buffer);
1111+#if HAVE_MBRTOWC
1112+ if (MB_CUR_MAX > 1)
1113+ {
1114+ thisstate = thisline->state;
1115+
1116+ if (prevline->length == 0 || different_multi
1117+ (thisfield, prevfield, thislen, prevlen, thisstate, prevstate))
1118+ {
1119+ fwrite (thisline->buffer, sizeof (char),
1120+ thisline->length, stdout);
1121+
1122+ SWAP_LINES (prevline, thisline);
1123+ prevfield = thisfield;
1124+ prevlen = thislen;
1125+ prevstate = thisstate;
1126+ }
1127+ }
1128+ else
1129+#endif
1130 if (prevline->length == 0
1131 || different (thisfield, prevfield, thislen, prevlen))
1132 {
1133@@ -322,17 +533,26 @@
1134 size_t prevlen;
1135 uintmax_t match_count = 0;
1136 bool first_delimiter = true;
1137+#if HAVE_MBRTOWC
1138+ mbstate_t prevstate;
1139+#endif
1140
1141 if (readlinebuffer (prevline, stdin) == 0)
1142 goto closefiles;
1143 prevfield = find_field (prevline);
1144 prevlen = prevline->length - 1 - (prevfield - prevline->buffer);
1145+#if HAVE_MBRTOWC
1146+ prevstate = prevline->state;
1147+#endif
1148
1149 while (!feof (stdin))
1150 {
1151 bool match;
1152 char *thisfield;
1153 size_t thislen;
1154+#if HAVE_MBRTOWC
1155+ mbstate_t thisstate;
1156+#endif
1157 if (readlinebuffer (thisline, stdin) == 0)
1158 {
1159 if (ferror (stdin))
1160@@ -341,6 +561,15 @@
1161 }
1162 thisfield = find_field (thisline);
1163 thislen = thisline->length - 1 - (thisfield - thisline->buffer);
1164+#if HAVE_MBRTOWC
1165+ if (MB_CUR_MAX > 1)
1166+ {
1167+ thisstate = thisline->state;
1168+ match = !different_multi (thisfield, prevfield,
1169+ thislen, prevlen, thisstate, prevstate);
1170+ }
1171+ else
1172+#endif
1173 match = !different (thisfield, prevfield, thislen, prevlen);
1174 match_count += match;
1175
1176@@ -373,6 +602,9 @@
1177 SWAP_LINES (prevline, thisline);
1178 prevfield = thisfield;
1179 prevlen = thislen;
1180+#if HAVE_MBRTOWC
1181+ prevstate = thisstate;
1182+#endif
1183 if (!match)
1184 match_count = 0;
1185 }
1186@@ -417,6 +649,19 @@
1187
1188 atexit (close_stdout);
1189
1190+#if HAVE_MBRTOWC
1191+ if (MB_CUR_MAX > 1)
1192+ {
1193+ find_field = find_field_multi;
1194+ }
1195+ else
1196+#endif
1197+ {
1198+ find_field = find_field_uni;
1199+ }
1200+
1201+
1202+
1203 skip_chars = 0;
1204 skip_fields = 0;
1205 check_chars = SIZE_MAX;
1206--- coreutils-6.8+/src/fold.c.i18n 2007-02-23 12:01:47.000000000 +0000
1207+++ coreutils-6.8+/src/fold.c 2007-03-01 15:08:24.000000000 +0000
1208@@ -23,11 +23,33 @@
1209 #include <getopt.h>
1210 #include <sys/types.h>
1211
1212+/* Get mbstate_t, mbrtowc(), wcwidth(). */
1213+#if HAVE_WCHAR_H
1214+# include <wchar.h>
1215+#endif
1216+
1217+/* Get iswprint(), iswblank(), wcwidth(). */
1218+#if HAVE_WCTYPE_H
1219+# include <wctype.h>
1220+#endif
1221+
1222 #include "system.h"
1223 #include "error.h"
1224 #include "quote.h"
1225 #include "xstrtol.h"
1226
1227+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
1228+ installation; work around this configuration error. */
1229+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
1230+# undef MB_LEN_MAX
1231+# define MB_LEN_MAX 16
1232+#endif
1233+
1234+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
1235+#if HAVE_MBRTOWC && defined mbstate_t
1236+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
1237+#endif
1238+
1239 #define TAB_WIDTH 8
1240
1241 /* The official name of this program (e.g., no `g' prefix). */
1242@@ -35,23 +57,44 @@
1243
1244 #define AUTHORS "David MacKenzie"
1245
1246+#define FATAL_ERROR(Message) \
1247+ do \
1248+ { \
1249+ error (0, 0, (Message)); \
1250+ usage (2); \
1251+ } \
1252+ while (0)
1253+
1254+enum operating_mode
1255+{
1256+ /* Fold texts by columns that are at the given positions. */
1257+ column_mode,
1258+
1259+ /* Fold texts by bytes that are at the given positions. */
1260+ byte_mode,
1261+
1262+ /* Fold texts by characters that are at the given positions. */
1263+ character_mode,
1264+};
1265+
1266 /* The name this program was run with. */
1267 char *program_name;
1268
1269+/* The argument shows current mode. (Default: column_mode) */
1270+static enum operating_mode operating_mode;
1271+
1272 /* If nonzero, try to break on whitespace. */
1273 static bool break_spaces;
1274
1275-/* If nonzero, count bytes, not column positions. */
1276-static bool count_bytes;
1277-
1278 /* If nonzero, at least one of the files we read was standard input. */
1279 static bool have_read_stdin;
1280
1281-static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::";
1282+static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::";
1283
1284 static struct option const longopts[] =
1285 {
1286 {"bytes", no_argument, NULL, 'b'},
1287+ {"characters", no_argument, NULL, 'c'},
1288 {"spaces", no_argument, NULL, 's'},
1289 {"width", required_argument, NULL, 'w'},
1290 {GETOPT_HELP_OPTION_DECL},
1291@@ -81,6 +124,7 @@
1292 "), stdout);
1293 fputs (_("\
1294 -b, --bytes count bytes rather than columns\n\
1295+ -c, --characters count characters rather than columns\n\
1296 -s, --spaces break at spaces\n\
1297 -w, --width=WIDTH use WIDTH columns instead of 80\n\
1298 "), stdout);
1299@@ -98,7 +142,7 @@
1300 static size_t
1301 adjust_column (size_t column, char c)
1302 {
1303- if (!count_bytes)
1304+ if (operating_mode != byte_mode)
1305 {
1306 if (c == '\b')
1307 {
1308@@ -121,30 +165,14 @@
1309 to stdout, with maximum line length WIDTH.
1310 Return true if successful. */
1311
1312-static bool
1313-fold_file (char const *filename, size_t width)
1314+static void
1315+fold_text (FILE *istream, size_t width, int *saved_errno)
1316 {
1317- FILE *istream;
1318 int c;
1319 size_t column = 0; /* Screen column where next char will go. */
1320 size_t offset_out = 0; /* Index in `line_out' for next char. */
1321 static char *line_out = NULL;
1322 static size_t allocated_out = 0;
1323- int saved_errno;
1324-
1325- if (STREQ (filename, "-"))
1326- {
1327- istream = stdin;
1328- have_read_stdin = true;
1329- }
1330- else
1331- istream = fopen (filename, "r");
1332-
1333- if (istream == NULL)
1334- {
1335- error (0, errno, "%s", filename);
1336- return false;
1337- }
1338
1339 while ((c = getc (istream)) != EOF)
1340 {
1341@@ -172,6 +200,15 @@
1342 bool found_blank = false;
1343 size_t logical_end = offset_out;
1344
1345+ /* If LINE_OUT has no wide character,
1346+ put a new wide character in LINE_OUT
1347+ if column is bigger than width. */
1348+ if (offset_out == 0)
1349+ {
1350+ line_out[offset_out++] = c;
1351+ continue;
1352+ }
1353+
1354 /* Look for the last blank. */
1355 while (logical_end)
1356 {
1357@@ -218,11 +255,225 @@
1358 line_out[offset_out++] = c;
1359 }
1360
1361- saved_errno = errno;
1362+ *saved_errno = errno;
1363+
1364+ if (offset_out)
1365+ fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
1366+
1367+ free(line_out);
1368+}
1369+
1370+#if HAVE_MBRTOWC
1371+static void
1372+fold_multibyte_text (FILE *istream, size_t width, int *saved_errno)
1373+{
1374+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */
1375+ size_t buflen = 0; /* The length of the byte sequence in buf. */
1376+ char *bufpos; /* Next read position of BUF. */
1377+ wint_t wc; /* A gotten wide character. */
1378+ size_t mblength; /* The byte size of a multibyte character which shows
1379+ as same character as WC. */
1380+ mbstate_t state, state_bak; /* State of the stream. */
1381+ int convfail; /* 1, when conversion is failed. Otherwise 0. */
1382+
1383+ char *line_out = NULL;
1384+ size_t offset_out = 0; /* Index in `line_out' for next char. */
1385+ size_t allocated_out = 0;
1386+
1387+ int increment;
1388+ size_t column = 0;
1389+
1390+ size_t last_blank_pos;
1391+ size_t last_blank_column;
1392+ int is_blank_seen;
1393+ int last_blank_increment;
1394+ int is_bs_following_last_blank;
1395+ size_t bs_following_last_blank_num;
1396+ int is_cr_after_last_blank;
1397+
1398+#define CLEAR_FLAGS \
1399+ do \
1400+ { \
1401+ last_blank_pos = 0; \
1402+ last_blank_column = 0; \
1403+ is_blank_seen = 0; \
1404+ is_bs_following_last_blank = 0; \
1405+ bs_following_last_blank_num = 0; \
1406+ is_cr_after_last_blank = 0; \
1407+ } \
1408+ while (0)
1409+
1410+#define START_NEW_LINE \
1411+ do \
1412+ { \
1413+ putchar ('\n'); \
1414+ column = 0; \
1415+ offset_out = 0; \
1416+ CLEAR_FLAGS; \
1417+ } \
1418+ while (0)
1419+
1420+ CLEAR_FLAGS;
1421+ memset (&state, '\0', sizeof(mbstate_t));
1422+
1423+ for (;; bufpos += mblength, buflen -= mblength)
1424+ {
1425+ if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream))
1426+ {
1427+ memmove (buf, bufpos, buflen);
1428+ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream);
1429+ bufpos = buf;
1430+ }
1431+
1432+ if (buflen < 1)
1433+ break;
1434+
1435+ /* Get a wide character. */
1436+ convfail = 0;
1437+ state_bak = state;
1438+ mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state);
1439+
1440+ switch (mblength)
1441+ {
1442+ case (size_t)-1:
1443+ case (size_t)-2:
1444+ convfail++;
1445+ state = state_bak;
1446+ /* Fall through. */
1447+
1448+ case 0:
1449+ mblength = 1;
1450+ break;
1451+ }
1452+
1453+rescan:
1454+ if (operating_mode == byte_mode) /* byte mode */
1455+ increment = mblength;
1456+ else if (operating_mode == character_mode) /* character mode */
1457+ increment = 1;
1458+ else /* column mode */
1459+ {
1460+ if (convfail)
1461+ increment = 1;
1462+ else
1463+ {
1464+ switch (wc)
1465+ {
1466+ case L'\n':
1467+ fwrite (line_out, sizeof(char), offset_out, stdout);
1468+ START_NEW_LINE;
1469+ continue;
1470+
1471+ case L'\b':
1472+ increment = (column > 0) ? -1 : 0;
1473+ break;
1474+
1475+ case L'\r':
1476+ increment = -1 * column;
1477+ break;
1478+
1479+ case L'\t':
1480+ increment = 8 - column % 8;
1481+ break;
1482+
1483+ default:
1484+ increment = wcwidth (wc);
1485+ increment = (increment < 0) ? 0 : increment;
1486+ }
1487+ }
1488+ }
1489+
1490+ if (column + increment > width && break_spaces && last_blank_pos)
1491+ {
1492+ fwrite (line_out, sizeof(char), last_blank_pos, stdout);
1493+ putchar ('\n');
1494+
1495+ offset_out = offset_out - last_blank_pos;
1496+ column = column - last_blank_column + ((is_cr_after_last_blank)
1497+ ? last_blank_increment : bs_following_last_blank_num);
1498+ memmove (line_out, line_out + last_blank_pos, offset_out);
1499+ CLEAR_FLAGS;
1500+ goto rescan;
1501+ }
1502+
1503+ if (column + increment > width && column != 0)
1504+ {
1505+ fwrite (line_out, sizeof(char), offset_out, stdout);
1506+ START_NEW_LINE;
1507+ goto rescan;
1508+ }
1509+
1510+ if (allocated_out < offset_out + mblength)
1511+ {
1512+ allocated_out += 1024;
1513+ line_out = xrealloc (line_out, allocated_out);
1514+ }
1515+
1516+ memcpy (line_out + offset_out, bufpos, mblength);
1517+ offset_out += mblength;
1518+ column += increment;
1519+
1520+ if (is_blank_seen && !convfail && wc == L'\r')
1521+ is_cr_after_last_blank = 1;
1522+
1523+ if (is_bs_following_last_blank && !convfail && wc == L'\b')
1524+ ++bs_following_last_blank_num;
1525+ else
1526+ is_bs_following_last_blank = 0;
1527+
1528+ if (break_spaces && !convfail && iswblank (wc))
1529+ {
1530+ last_blank_pos = offset_out;
1531+ last_blank_column = column;
1532+ is_blank_seen = 1;
1533+ last_blank_increment = increment;
1534+ is_bs_following_last_blank = 1;
1535+ bs_following_last_blank_num = 0;
1536+ is_cr_after_last_blank = 0;
1537+ }
1538+ }
1539+
1540+ *saved_errno = errno;
1541
1542 if (offset_out)
1543 fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
1544
1545+ free(line_out);
1546+}
1547+#endif
1548+
1549+/* Fold file FILENAME, or standard input if FILENAME is "-",
1550+ to stdout, with maximum line length WIDTH.
1551+ Return 0 if successful, 1 if an error occurs. */
1552+
1553+static bool
1554+fold_file (char *filename, size_t width)
1555+{
1556+ FILE *istream;
1557+ int saved_errno;
1558+
1559+ if (STREQ (filename, "-"))
1560+ {
1561+ istream = stdin;
1562+ have_read_stdin = 1;
1563+ }
1564+ else
1565+ istream = fopen (filename, "r");
1566+
1567+ if (istream == NULL)
1568+ {
1569+ error (0, errno, "%s", filename);
1570+ return 1;
1571+ }
1572+
1573+ /* Define how ISTREAM is being folded. */
1574+#if HAVE_MBRTOWC
1575+ if (MB_CUR_MAX > 1)
1576+ fold_multibyte_text (istream, width, &saved_errno);
1577+ else
1578+#endif
1579+ fold_text (istream, width, &saved_errno);
1580+
1581 if (ferror (istream))
1582 {
1583 error (0, saved_errno, "%s", filename);
1584@@ -255,7 +506,8 @@
1585
1586 atexit (close_stdout);
1587
1588- break_spaces = count_bytes = have_read_stdin = false;
1589+ operating_mode = column_mode;
1590+ break_spaces = have_read_stdin = false;
1591
1592 while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
1593 {
1594@@ -264,7 +516,15 @@
1595 switch (optc)
1596 {
1597 case 'b': /* Count bytes rather than columns. */
1598- count_bytes = true;
1599+ if (operating_mode != column_mode)
1600+ FATAL_ERROR (_("only one way of folding may be specified"));
1601+ operating_mode = byte_mode;
1602+ break;
1603+
1604+ case 'c':
1605+ if (operating_mode != column_mode)
1606+ FATAL_ERROR (_("only one way of folding may be specified"));
1607+ operating_mode = character_mode;
1608 break;
1609
1610 case 's': /* Break at word boundaries. */
1611--- coreutils-6.8+/src/sort.c.i18n 2007-02-24 11:23:23.000000000 +0000
1612+++ coreutils-6.8+/src/sort.c 2007-03-01 15:10:57.000000000 +0000
1613@@ -23,10 +23,19 @@
1614
1615 #include <config.h>
1616
1617+#include <assert.h>
1618 #include <getopt.h>
1619 #include <sys/types.h>
1620 #include <sys/wait.h>
1621 #include <signal.h>
1622+#if HAVE_WCHAR_H
1623+# include <wchar.h>
1624+#endif
1625+/* Get isw* functions. */
1626+#if HAVE_WCTYPE_H
1627+# include <wctype.h>
1628+#endif
1629+
1630 #include "system.h"
1631 #include "argmatch.h"
1632 #include "error.h"
1633@@ -116,14 +125,38 @@
1634 /* Thousands separator; if -1, then there isn't one. */
1635 static int thousands_sep;
1636
1637+static int force_general_numcompare = 0;
1638+
1639 /* Nonzero if the corresponding locales are hard. */
1640 static bool hard_LC_COLLATE;
1641-#if HAVE_NL_LANGINFO
1642+#if HAVE_LANGINFO_CODESET
1643 static bool hard_LC_TIME;
1644 #endif
1645
1646 #define NONZERO(x) ((x) != 0)
1647
1648+/* get a multibyte character's byte length. */
1649+#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE) \
1650+ do \
1651+ { \
1652+ wchar_t wc; \
1653+ mbstate_t state_bak; \
1654+ \
1655+ state_bak = STATE; \
1656+ mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE); \
1657+ \
1658+ switch (MBLENGTH) \
1659+ { \
1660+ case (size_t)-1: \
1661+ case (size_t)-2: \
1662+ STATE = state_bak; \
1663+ /* Fall through. */ \
1664+ case 0: \
1665+ MBLENGTH = 1; \
1666+ } \
1667+ } \
1668+ while (0)
1669+
1670 /* The kind of blanks for '-b' to skip in various options. */
1671 enum blanktype { bl_start, bl_end, bl_both };
1672
1673@@ -261,13 +294,11 @@
1674 they were read if all keys compare equal. */
1675 static bool stable;
1676
1677-/* If TAB has this value, blanks separate fields. */
1678-enum { TAB_DEFAULT = CHAR_MAX + 1 };
1679-
1680-/* Tab character separating fields. If TAB_DEFAULT, then fields are
1681+/* Tab character separating fields. If tab_length is 0, then fields are
1682 separated by the empty string between a non-blank character and a blank
1683 character. */
1684-static int tab = TAB_DEFAULT;
1685+static char tab[MB_LEN_MAX + 1];
1686+static size_t tab_length = 0;
1687
1688 /* Flag to remove consecutive duplicate lines from the output.
1689 Only the last of a sequence of equal lines will be output. */
1690@@ -639,6 +670,44 @@
1691 update_proc (pid);
1692 }
1693
1694+/* Function pointers. */
1695+static void
1696+(*inittables) (void);
1697+static char *
1698+(*begfield) (const struct line*, const struct keyfield *);
1699+static char *
1700+(*limfield) (const struct line*, const struct keyfield *);
1701+static int
1702+(*getmonth) (char const *, size_t);
1703+static int
1704+(*keycompare) (const struct line *, const struct line *);
1705+static int
1706+(*numcompare) (const char *, const char *);
1707+
1708+/* Test for white space multibyte character.
1709+ Set LENGTH the byte length of investigated multibyte character. */
1710+#if HAVE_MBRTOWC
1711+static int
1712+ismbblank (const char *str, size_t len, size_t *length)
1713+{
1714+ size_t mblength;
1715+ wchar_t wc;
1716+ mbstate_t state;
1717+
1718+ memset (&state, '\0', sizeof(mbstate_t));
1719+ mblength = mbrtowc (&wc, str, len, &state);
1720+
1721+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
1722+ {
1723+ *length = 1;
1724+ return 0;
1725+ }
1726+
1727+ *length = (mblength < 1) ? 1 : mblength;
1728+ return iswblank (wc);
1729+}
1730+#endif
1731+
1732 /* Clean up any remaining temporary files. */
1733
1734 static void
1735@@ -978,7 +1047,7 @@
1736 free (node);
1737 }
1738
1739-#if HAVE_NL_LANGINFO
1740+#if HAVE_LANGINFO_CODESET
1741
1742 static int
1743 struct_month_cmp (const void *m1, const void *m2)
1744@@ -993,7 +1062,7 @@
1745 /* Initialize the character class tables. */
1746
1747 static void
1748-inittables (void)
1749+inittables_uni (void)
1750 {
1751 size_t i;
1752
1753@@ -1005,7 +1074,7 @@
1754 fold_toupper[i] = toupper (i);
1755 }
1756
1757-#if HAVE_NL_LANGINFO
1758+#if HAVE_LANGINFO_CODESET
1759 /* If we're not in the "C" locale, read different names for months. */
1760 if (hard_LC_TIME)
1761 {
1762@@ -1031,6 +1100,64 @@
1763 #endif
1764 }
1765
1766+#if HAVE_MBRTOWC
1767+static void
1768+inittables_mb (void)
1769+{
1770+ int i, j, k, l;
1771+ char *name, *s;
1772+ size_t s_len, mblength;
1773+ char mbc[MB_LEN_MAX];
1774+ wchar_t wc, pwc;
1775+ mbstate_t state_mb, state_wc;
1776+
1777+ for (i = 0; i < MONTHS_PER_YEAR; i++)
1778+ {
1779+ s = (char *) nl_langinfo (ABMON_1 + i);
1780+ s_len = strlen (s);
1781+ monthtab[i].name = name = (char *) xmalloc (s_len + 1);
1782+ monthtab[i].val = i + 1;
1783+
1784+ memset (&state_mb, '\0', sizeof (mbstate_t));
1785+ memset (&state_wc, '\0', sizeof (mbstate_t));
1786+
1787+ for (j = 0; j < s_len;)
1788+ {
1789+ if (!ismbblank (s + j, s_len - j, &mblength))
1790+ break;
1791+ j += mblength;
1792+ }
1793+
1794+ for (k = 0; j < s_len;)
1795+ {
1796+ mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb);
1797+ assert (mblength != (size_t)-1 && mblength != (size_t)-2);
1798+ if (mblength == 0)
1799+ break;
1800+
1801+ pwc = towupper (wc);
1802+ if (pwc == wc)
1803+ {
1804+ memcpy (mbc, s + j, mblength);
1805+ j += mblength;
1806+ }
1807+ else
1808+ {
1809+ j += mblength;
1810+ mblength = wcrtomb (mbc, pwc, &state_wc);
1811+ assert (mblength != (size_t)0 && mblength != (size_t)-1);
1812+ }
1813+
1814+ for (l = 0; l < mblength; l++)
1815+ name[k++] = mbc[l];
1816+ }
1817+ name[k] = '\0';
1818+ }
1819+ qsort ((void *) monthtab, MONTHS_PER_YEAR,
1820+ sizeof (struct month), struct_month_cmp);
1821+}
1822+#endif
1823+
1824 /* Specify the amount of main memory to use when sorting. */
1825 static void
1826 specify_sort_size (char const *s)
1827@@ -1241,7 +1368,7 @@
1828 by KEY in LINE. */
1829
1830 static char *
1831-begfield (const struct line *line, const struct keyfield *key)
1832+begfield_uni (const struct line *line, const struct keyfield *key)
1833 {
1834 char *ptr = line->text, *lim = ptr + line->length - 1;
1835 size_t sword = key->sword;
1836@@ -1251,10 +1378,10 @@
1837 /* The leading field separator itself is included in a field when -t
1838 is absent. */
1839
1840- if (tab != TAB_DEFAULT)
1841+ if (tab_length)
1842 while (ptr < lim && sword--)
1843 {
1844- while (ptr < lim && *ptr != tab)
1845+ while (ptr < lim && *ptr != tab[0])
1846 ++ptr;
1847 if (ptr < lim)
1848 ++ptr;
1849@@ -1282,11 +1409,70 @@
1850 return ptr;
1851 }
1852
1853+#if HAVE_MBRTOWC
1854+static char *
1855+begfield_mb (const struct line *line, const struct keyfield *key)
1856+{
1857+ int i;
1858+ char *ptr = line->text, *lim = ptr + line->length - 1;
1859+ size_t sword = key->sword;
1860+ size_t schar = key->schar;
1861+ size_t mblength;
1862+ mbstate_t state;
1863+
1864+ memset (&state, '\0', sizeof(mbstate_t));
1865+
1866+ if (tab_length)
1867+ while (ptr < lim && sword--)
1868+ {
1869+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
1870+ {
1871+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1872+ ptr += mblength;
1873+ }
1874+ if (ptr < lim)
1875+ {
1876+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1877+ ptr += mblength;
1878+ }
1879+ }
1880+ else
1881+ while (ptr < lim && sword--)
1882+ {
1883+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
1884+ ptr += mblength;
1885+ if (ptr < lim)
1886+ {
1887+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1888+ ptr += mblength;
1889+ }
1890+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
1891+ ptr += mblength;
1892+ }
1893+
1894+ if (key->skipsblanks)
1895+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
1896+ ptr += mblength;
1897+
1898+ for (i = 0; i < schar; i++)
1899+ {
1900+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1901+
1902+ if (ptr + mblength > lim)
1903+ break;
1904+ else
1905+ ptr += mblength;
1906+ }
1907+
1908+ return ptr;
1909+}
1910+#endif
1911+
1912 /* Return the limit of (a pointer to the first character after) the field
1913 in LINE specified by KEY. */
1914
1915 static char *
1916-limfield (const struct line *line, const struct keyfield *key)
1917+limfield_uni (const struct line *line, const struct keyfield *key)
1918 {
1919 char *ptr = line->text, *lim = ptr + line->length - 1;
1920 size_t eword = key->eword, echar = key->echar;
1921@@ -1299,10 +1485,10 @@
1922 `beginning' is the first character following the delimiting TAB.
1923 Otherwise, leave PTR pointing at the first `blank' character after
1924 the preceding field. */
1925- if (tab != TAB_DEFAULT)
1926+ if (tab_length)
1927 while (ptr < lim && eword--)
1928 {
1929- while (ptr < lim && *ptr != tab)
1930+ while (ptr < lim && *ptr != tab[0])
1931 ++ptr;
1932 if (ptr < lim && (eword | echar))
1933 ++ptr;
1934@@ -1348,10 +1534,10 @@
1935 */
1936
1937 /* Make LIM point to the end of (one byte past) the current field. */
1938- if (tab != TAB_DEFAULT)
1939+ if (tab_length)
1940 {
1941 char *newlim;
1942- newlim = memchr (ptr, tab, lim - ptr);
1943+ newlim = memchr (ptr, tab[0], lim - ptr);
1944 if (newlim)
1945 lim = newlim;
1946 }
1947@@ -1384,6 +1570,107 @@
1948 return ptr;
1949 }
1950
1951+#if HAVE_MBRTOWC
1952+static char *
1953+limfield_mb (const struct line *line, const struct keyfield *key)
1954+{
1955+ char *ptr = line->text, *lim = ptr + line->length - 1;
1956+ size_t eword = key->eword, echar = key->echar;
1957+ int i;
1958+ size_t mblength;
1959+ mbstate_t state;
1960+
1961+ memset (&state, '\0', sizeof(mbstate_t));
1962+
1963+ if (tab_length)
1964+ while (ptr < lim && eword--)
1965+ {
1966+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
1967+ {
1968+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1969+ ptr += mblength;
1970+ }
1971+ if (ptr < lim && (eword | echar))
1972+ {
1973+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1974+ ptr += mblength;
1975+ }
1976+ }
1977+ else
1978+ while (ptr < lim && eword--)
1979+ {
1980+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
1981+ ptr += mblength;
1982+ if (ptr < lim)
1983+ {
1984+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
1985+ ptr += mblength;
1986+ }
1987+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
1988+ ptr += mblength;
1989+ }
1990+
1991+
1992+# ifdef POSIX_UNSPECIFIED
1993+ /* Make LIM point to the end of (one byte past) the current field. */
1994+ if (tab_length)
1995+ {
1996+ char *newlim, *p;
1997+
1998+ newlim = NULL;
1999+ for (p = ptr; p < lim;)
2000+ {
2001+ if (memcmp (p, tab, tab_length) == 0)
2002+ {
2003+ newlim = p;
2004+ break;
2005+ }
2006+
2007+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
2008+ p += mblength;
2009+ }
2010+ }
2011+ else
2012+ {
2013+ char *newlim;
2014+ newlim = ptr;
2015+
2016+ while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength))
2017+ newlim += mblength;
2018+ if (ptr < lim)
2019+ {
2020+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
2021+ ptr += mblength;
2022+ }
2023+ while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength))
2024+ newlim += mblength;
2025+ lim = newlim;
2026+ }
2027+# endif
2028+
2029+ /* If we're skipping leading blanks, don't start counting characters
2030+ * until after skipping past any leading blanks. */
2031+ if (key->skipsblanks)
2032+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
2033+ ptr += mblength;
2034+
2035+ memset (&state, '\0', sizeof(mbstate_t));
2036+
2037+ /* Advance PTR by ECHAR (if possible), but no further than LIM. */
2038+ for (i = 0; i < echar; i++)
2039+ {
2040+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
2041+
2042+ if (ptr + mblength > lim)
2043+ break;
2044+ else
2045+ ptr += mblength;
2046+ }
2047+
2048+ return ptr;
2049+}
2050+#endif
2051+
2052 /* Fill BUF reading from FP, moving buf->left bytes from the end
2053 of buf->buf to the beginning first. If EOF is reached and the
2054 file wasn't terminated by a newline, supply one. Set up BUF's line
2055@@ -1466,8 +1753,24 @@
2056 else
2057 {
2058 if (key->skipsblanks)
2059- while (blanks[to_uchar (*line_start)])
2060- line_start++;
2061+ {
2062+#if HAVE_MBRTOWC
2063+ if (MB_CUR_MAX > 1)
2064+ {
2065+ size_t mblength;
2066+ mbstate_t state;
2067+ memset (&state, '\0', sizeof(mbstate_t));
2068+ while (line_start < line->keylim &&
2069+ ismbblank (line_start,
2070+ line->keylim - line_start,
2071+ &mblength))
2072+ line_start += mblength;
2073+ }
2074+ else
2075+#endif
2076+ while (blanks[to_uchar (*line_start)])
2077+ line_start++;
2078+ }
2079 line->keybeg = line_start;
2080 }
2081 }
2082@@ -1500,7 +1803,7 @@
2083 hideously fast. */
2084
2085 static int
2086-numcompare (const char *a, const char *b)
2087+numcompare_uni (const char *a, const char *b)
2088 {
2089 while (blanks[to_uchar (*a)])
2090 a++;
2091@@ -1510,6 +1813,25 @@
2092 return strnumcmp (a, b, decimal_point, thousands_sep);
2093 }
2094
2095+#if HAVE_MBRTOWC
2096+static int
2097+numcompare_mb (const char *a, const char *b)
2098+{
2099+ size_t mblength, len;
2100+ len = strlen (a); /* okay for UTF-8 */
2101+ while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
2102+ {
2103+ a += mblength;
2104+ len -= mblength;
2105+ }
2106+ len = strlen (b); /* okay for UTF-8 */
2107+ while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
2108+ b += mblength;
2109+
2110+ return strnumcmp (a, b, decimal_point, thousands_sep);
2111+}
2112+#endif /* HAV_EMBRTOWC */
2113+
2114 static int
2115 general_numcompare (const char *sa, const char *sb)
2116 {
2117@@ -1543,7 +1865,7 @@
2118 Return 0 if the name in S is not recognized. */
2119
2120 static int
2121-getmonth (char const *month, size_t len)
2122+getmonth_uni (char const *month, size_t len)
2123 {
2124 size_t lo = 0;
2125 size_t hi = MONTHS_PER_YEAR;
2126@@ -1698,11 +2020,79 @@
2127 return diff;
2128 }
2129
2130+#if HAVE_MBRTOWC
2131+static int
2132+getmonth_mb (const char *s, size_t len)
2133+{
2134+ char *month;
2135+ register size_t i;
2136+ register int lo = 0, hi = MONTHS_PER_YEAR, result;
2137+ char *tmp;
2138+ size_t wclength, mblength;
2139+ const char **pp;
2140+ const wchar_t **wpp;
2141+ wchar_t *month_wcs;
2142+ mbstate_t state;
2143+
2144+ while (len > 0 && ismbblank (s, len, &mblength))
2145+ {
2146+ s += mblength;
2147+ len -= mblength;
2148+ }
2149+
2150+ if (len == 0)
2151+ return 0;
2152+
2153+ month = (char *) alloca (len + 1);
2154+
2155+ tmp = (char *) alloca (len + 1);
2156+ memcpy (tmp, s, len);
2157+ tmp[len] = '\0';
2158+ pp = (const char **)&tmp;
2159+ month_wcs = (wchar_t *) alloca ((len + 1) * sizeof (wchar_t));
2160+ memset (&state, '\0', sizeof(mbstate_t));
2161+
2162+ wclength = mbsrtowcs (month_wcs, pp, len + 1, &state);
2163+ assert (wclength != (size_t)-1 && *pp == NULL);
2164+
2165+ for (i = 0; i < wclength; i++)
2166+ {
2167+ month_wcs[i] = towupper(month_wcs[i]);
2168+ if (iswblank (month_wcs[i]))
2169+ {
2170+ month_wcs[i] = L'\0';
2171+ break;
2172+ }
2173+ }
2174+
2175+ wpp = (const wchar_t **)&month_wcs;
2176+
2177+ mblength = wcsrtombs (month, wpp, len + 1, &state);
2178+ assert (mblength != (-1) && *wpp == NULL);
2179+
2180+ do
2181+ {
2182+ int ix = (lo + hi) / 2;
2183+
2184+ if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0)
2185+ hi = ix;
2186+ else
2187+ lo = ix;
2188+ }
2189+ while (hi - lo > 1);
2190+
2191+ result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name))
2192+ ? monthtab[lo].val : 0);
2193+
2194+ return result;
2195+}
2196+#endif
2197+
2198 /* Compare two lines A and B trying every key in sequence until there
2199 are no more keys or a difference is found. */
2200
2201 static int
2202-keycompare (const struct line *a, const struct line *b)
2203+keycompare_uni (const struct line *a, const struct line *b)
2204 {
2205 struct keyfield const *key = keylist;
2206
2207@@ -1875,6 +2265,179 @@
2208 return key->reverse ? -diff : diff;
2209 }
2210
2211+#if HAVE_MBRTOWC
2212+static int
2213+keycompare_mb (const struct line *a, const struct line *b)
2214+{
2215+ struct keyfield *key = keylist;
2216+
2217+ /* For the first iteration only, the key positions have been
2218+ precomputed for us. */
2219+ char *texta = a->keybeg;
2220+ char *textb = b->keybeg;
2221+ char *lima = a->keylim;
2222+ char *limb = b->keylim;
2223+
2224+ size_t mblength_a, mblength_b;
2225+ wchar_t wc_a, wc_b;
2226+ mbstate_t state_a, state_b;
2227+
2228+ int diff;
2229+
2230+ memset (&state_a, '\0', sizeof(mbstate_t));
2231+ memset (&state_b, '\0', sizeof(mbstate_t));
2232+
2233+ for (;;)
2234+ {
2235+ unsigned char *translate = (unsigned char *) key->translate;
2236+ bool const *ignore = key->ignore;
2237+
2238+ /* Find the lengths. */
2239+ size_t lena = lima <= texta ? 0 : lima - texta;
2240+ size_t lenb = limb <= textb ? 0 : limb - textb;
2241+
2242+ /* Actually compare the fields. */
2243+ if (key->random)
2244+ diff = compare_random (texta, lena, textb, lenb);
2245+ else if (key->numeric | key->general_numeric)
2246+ {
2247+ char savea = *lima, saveb = *limb;
2248+
2249+ *lima = *limb = '\0';
2250+ if (force_general_numcompare)
2251+ diff = general_numcompare (texta, textb);
2252+ else
2253+ diff = ((key->numeric ? numcompare : general_numcompare)
2254+ (texta, textb));
2255+ *lima = savea, *limb = saveb;
2256+ }
2257+ else if (key->month)
2258+ diff = getmonth (texta, lena) - getmonth (textb, lenb);
2259+ else
2260+ {
2261+ if (ignore || translate)
2262+ {
2263+ char *copy_a = (char *) alloca (lena + 1 + lenb + 1);
2264+ char *copy_b = copy_a + lena + 1;
2265+ size_t new_len_a, new_len_b;
2266+ size_t i, j;
2267+
2268+ /* Ignore and/or translate chars before comparing. */
2269+# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \
2270+ do \
2271+ { \
2272+ wchar_t uwc; \
2273+ char mbc[MB_LEN_MAX]; \
2274+ mbstate_t state_wc; \
2275+ \
2276+ for (NEW_LEN = i = 0; i < LEN;) \
2277+ { \
2278+ mbstate_t state_bak; \
2279+ \
2280+ state_bak = STATE; \
2281+ MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE); \
2282+ \
2283+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1 \
2284+ || MBLENGTH == 0) \
2285+ { \
2286+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1) \
2287+ STATE = state_bak; \
2288+ if (!ignore) \
2289+ COPY[NEW_LEN++] = TEXT[i++]; \
2290+ continue; \
2291+ } \
2292+ \
2293+ if (ignore) \
2294+ { \
2295+ if ((ignore == nonprinting && !iswprint (WC)) \
2296+ || (ignore == nondictionary \
2297+ && !iswalnum (WC) && !iswblank (WC))) \
2298+ { \
2299+ i += MBLENGTH; \
2300+ continue; \
2301+ } \
2302+ } \
2303+ \
2304+ if (translate) \
2305+ { \
2306+ \
2307+ uwc = towupper(WC); \
2308+ if (WC == uwc) \
2309+ { \
2310+ memcpy (mbc, TEXT + i, MBLENGTH); \
2311+ i += MBLENGTH; \
2312+ } \
2313+ else \
2314+ { \
2315+ i += MBLENGTH; \
2316+ WC = uwc; \
2317+ memset (&state_wc, '\0', sizeof (mbstate_t)); \
2318+ \
2319+ MBLENGTH = wcrtomb (mbc, WC, &state_wc); \
2320+ assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0); \
2321+ } \
2322+ \
2323+ for (j = 0; j < MBLENGTH; j++) \
2324+ COPY[NEW_LEN++] = mbc[j]; \
2325+ } \
2326+ else \
2327+ for (j = 0; j < MBLENGTH; j++) \
2328+ COPY[NEW_LEN++] = TEXT[i++]; \
2329+ } \
2330+ COPY[NEW_LEN] = '\0'; \
2331+ } \
2332+ while (0)
2333+ IGNORE_CHARS (new_len_a, lena, texta, copy_a,
2334+ wc_a, mblength_a, state_a);
2335+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
2336+ wc_b, mblength_b, state_b);
2337+ diff = xmemcoll (copy_a, new_len_a, copy_b, new_len_b);
2338+ }
2339+ else if (lena == 0)
2340+ diff = - NONZERO (lenb);
2341+ else if (lenb == 0)
2342+ goto greater;
2343+ else
2344+ diff = xmemcoll (texta, lena, textb, lenb);
2345+ }
2346+
2347+ if (diff)
2348+ goto not_equal;
2349+
2350+ key = key->next;
2351+ if (! key)
2352+ break;
2353+
2354+ /* Find the beginning and limit of the next field. */
2355+ if (key->eword != -1)
2356+ lima = limfield (a, key), limb = limfield (b, key);
2357+ else
2358+ lima = a->text + a->length - 1, limb = b->text + b->length - 1;
2359+
2360+ if (key->sword != -1)
2361+ texta = begfield (a, key), textb = begfield (b, key);
2362+ else
2363+ {
2364+ texta = a->text, textb = b->text;
2365+ if (key->skipsblanks)
2366+ {
2367+ while (texta < lima && ismbblank (texta, lima - texta, &mblength_a))
2368+ texta += mblength_a;
2369+ while (textb < limb && ismbblank (textb, limb - textb, &mblength_b))
2370+ textb += mblength_b;
2371+ }
2372+ }
2373+ }
2374+
2375+ return 0;
2376+
2377+greater:
2378+ diff = 1;
2379+not_equal:
2380+ return key->reverse ? -diff : diff;
2381+}
2382+#endif
2383+
2384 /* Compare two lines A and B, returning negative, zero, or positive
2385 depending on whether A compares less than, equal to, or greater than B. */
2386
2387@@ -2744,7 +3305,7 @@
2388 initialize_exit_failure (SORT_FAILURE);
2389
2390 hard_LC_COLLATE = hard_locale (LC_COLLATE);
2391-#if HAVE_NL_LANGINFO
2392+#if HAVE_LANGINFO_CODESET
2393 hard_LC_TIME = hard_locale (LC_TIME);
2394 #endif
2395
2396@@ -2765,6 +3326,27 @@
2397 thousands_sep = -1;
2398 }
2399
2400+#if HAVE_MBRTOWC
2401+ if (MB_CUR_MAX > 1)
2402+ {
2403+ inittables = inittables_mb;
2404+ begfield = begfield_mb;
2405+ limfield = limfield_mb;
2406+ getmonth = getmonth_mb;
2407+ keycompare = keycompare_mb;
2408+ numcompare = numcompare_mb;
2409+ }
2410+ else
2411+#endif
2412+ {
2413+ inittables = inittables_uni;
2414+ begfield = begfield_uni;
2415+ limfield = limfield_uni;
2416+ getmonth = getmonth_uni;
2417+ keycompare = keycompare_uni;
2418+ numcompare = numcompare_uni;
2419+ }
2420+
2421 have_read_stdin = false;
2422 inittables ();
2423
2424@@ -3015,13 +3597,35 @@
2425
2426 case 't':
2427 {
2428- char newtab = optarg[0];
2429- if (! newtab)
2430+ char newtab[MB_LEN_MAX + 1];
2431+ size_t newtab_length = 1;
2432+ strncpy (newtab, optarg, MB_LEN_MAX);
2433+ if (! newtab[0])
2434 error (SORT_FAILURE, 0, _("empty tab"));
2435- if (optarg[1])
2436+#if HAVE_MBRTOWC
2437+ if (MB_CUR_MAX > 1)
2438+ {
2439+ wchar_t wc;
2440+ mbstate_t state;
2441+ size_t i;
2442+
2443+ memset (&state, '\0', sizeof (mbstate_t));
2444+ newtab_length = mbrtowc (&wc, newtab, strnlen (newtab,
2445+ MB_LEN_MAX),
2446+ &state);
2447+ switch (newtab_length)
2448+ {
2449+ case (size_t) -1:
2450+ case (size_t) -2:
2451+ case 0:
2452+ newtab_length = 1;
2453+ }
2454+ }
2455+#endif
2456+ if (newtab_length == 1 && optarg[1])
2457 {
2458 if (STREQ (optarg, "\\0"))
2459- newtab = '\0';
2460+ newtab[0] = '\0';
2461 else
2462 {
2463 /* Provoke with `sort -txx'. Complain about
2464@@ -3032,9 +3636,12 @@
2465 quote (optarg));
2466 }
2467 }
2468- if (tab != TAB_DEFAULT && tab != newtab)
2469+ if (tab_length
2470+ && (tab_length != newtab_length
2471+ || memcmp (tab, newtab, tab_length) != 0))
2472 error (SORT_FAILURE, 0, _("incompatible tabs"));
2473- tab = newtab;
2474+ memcpy (tab, newtab, newtab_length);
2475+ tab_length = newtab_length;
2476 }
2477 break;
2478
2479--- coreutils-6.8+/src/unexpand.c.i18n 2007-01-14 15:41:28.000000000 +0000
2480+++ coreutils-6.8+/src/unexpand.c 2007-03-01 15:08:24.000000000 +0000
2481@@ -39,11 +39,28 @@
2482 #include <stdio.h>
2483 #include <getopt.h>
2484 #include <sys/types.h>
2485+
2486+/* Get mbstate_t, mbrtowc(), wcwidth(). */
2487+#if HAVE_WCHAR_H
2488+# include <wchar.h>
2489+#endif
2490+
2491 #include "system.h"
2492 #include "error.h"
2493 #include "quote.h"
2494 #include "xstrndup.h"
2495
2496+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
2497+ installation; work around this configuration error. */
2498+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
2499+# define MB_LEN_MAX 16
2500+#endif
2501+
2502+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
2503+#if HAVE_MBRTOWC && defined mbstate_t
2504+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
2505+#endif
2506+
2507 /* The official name of this program (e.g., no `g' prefix). */
2508 #define PROGRAM_NAME "unexpand"
2509
2510@@ -110,6 +127,208 @@
2511 {NULL, 0, NULL, 0}
2512 };
2513
2514+static FILE *next_file (FILE *fp);
2515+
2516+#if HAVE_MBRTOWC
2517+static void
2518+unexpand_multibyte (void)
2519+{
2520+ FILE *fp; /* Input stream. */
2521+ mbstate_t i_state; /* Current shift state of the input stream. */
2522+ mbstate_t i_state_bak; /* Back up the I_STATE. */
2523+ mbstate_t o_state; /* Current shift state of the output stream. */
2524+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */
2525+ char *bufpos; /* Next read position of BUF. */
2526+ size_t buflen = 0; /* The length of the byte sequence in buf. */
2527+ wint_t wc; /* A gotten wide character. */
2528+ size_t mblength; /* The byte size of a multibyte character
2529+ which shows as same character as WC. */
2530+
2531+ /* Index in `tab_list' of next tabstop: */
2532+ int tab_index = 0; /* For calculating width of pending tabs. */
2533+ int print_tab_index = 0; /* For printing as many tabs as possible. */
2534+ unsigned int column = 0; /* Column on screen of next char. */
2535+ int next_tab_column; /* Column the next tab stop is on. */
2536+ int convert = 1; /* If nonzero, perform translations. */
2537+ unsigned int pending = 0; /* Pending columns of blanks. */
2538+
2539+ fp = next_file ((FILE *) NULL);
2540+ if (fp == NULL)
2541+ return;
2542+
2543+ memset (&o_state, '\0', sizeof(mbstate_t));
2544+ memset (&i_state, '\0', sizeof(mbstate_t));
2545+
2546+ for (;;)
2547+ {
2548+ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp))
2549+ {
2550+ memmove (buf, bufpos, buflen);
2551+ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp);
2552+ bufpos = buf;
2553+ }
2554+
2555+ /* Get a wide character. */
2556+ if (buflen < 1)
2557+ {
2558+ mblength = 1;
2559+ wc = WEOF;
2560+ }
2561+ else
2562+ {
2563+ i_state_bak = i_state;
2564+ mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &i_state);
2565+ }
2566+
2567+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
2568+ {
2569+ i_state = i_state_bak;
2570+ wc = L'\0';
2571+ }
2572+
2573+ if (wc == L' ' && convert && column < INT_MAX)
2574+ {
2575+ ++pending;
2576+ ++column;
2577+ }
2578+ else if (wc == L'\t' && convert)
2579+ {
2580+ if (tab_size == 0)
2581+ {
2582+ /* Do not let tab_index == first_free_tab;
2583+ stop when it is 1 less. */
2584+ while (tab_index < first_free_tab - 1
2585+ && column >= tab_list[tab_index])
2586+ tab_index++;
2587+ next_tab_column = tab_list[tab_index];
2588+ if (tab_index < first_free_tab - 1)
2589+ tab_index++;
2590+ if (column >= next_tab_column)
2591+ {
2592+ convert = 0; /* Ran out of tab stops. */
2593+ goto flush_pend_mb;
2594+ }
2595+ }
2596+ else
2597+ {
2598+ next_tab_column = column + tab_size - column % tab_size;
2599+ }
2600+ pending += next_tab_column - column;
2601+ column = next_tab_column;
2602+ }
2603+ else
2604+ {
2605+flush_pend_mb:
2606+ /* Flush pending spaces. Print as many tabs as possible,
2607+ then print the rest as spaces. */
2608+ if (pending == 1)
2609+ {
2610+ putchar (' ');
2611+ pending = 0;
2612+ }
2613+ column -= pending;
2614+ while (pending > 0)
2615+ {
2616+ if (tab_size == 0)
2617+ {
2618+ /* Do not let print_tab_index == first_free_tab;
2619+ stop when it is 1 less. */
2620+ while (print_tab_index < first_free_tab - 1
2621+ && column >= tab_list[print_tab_index])
2622+ print_tab_index++;
2623+ next_tab_column = tab_list[print_tab_index];
2624+ if (print_tab_index < first_free_tab - 1)
2625+ print_tab_index++;
2626+ }
2627+ else
2628+ {
2629+ next_tab_column =
2630+ column + tab_size - column % tab_size;
2631+ }
2632+ if (next_tab_column - column <= pending)
2633+ {
2634+ putchar ('\t');
2635+ pending -= next_tab_column - column;
2636+ column = next_tab_column;
2637+ }
2638+ else
2639+ {
2640+ --print_tab_index;
2641+ column += pending;
2642+ while (pending != 0)
2643+ {
2644+ putchar (' ');
2645+ pending--;
2646+ }
2647+ }
2648+ }
2649+
2650+ if (wc == WEOF)
2651+ {
2652+ fp = next_file (fp);
2653+ if (fp == NULL)
2654+ break; /* No more files. */
2655+ else
2656+ {
2657+ memset (&i_state, '\0', sizeof(mbstate_t));
2658+ continue;
2659+ }
2660+ }
2661+
2662+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
2663+ {
2664+ if (convert)
2665+ {
2666+ ++column;
2667+ if (convert_entire_line == 0)
2668+ convert = 0;
2669+ }
2670+ mblength = 1;
2671+ putchar (buf[0]);
2672+ }
2673+ else if (mblength == 0)
2674+ {
2675+ if (convert && convert_entire_line == 0)
2676+ convert = 0;
2677+ mblength = 1;
2678+ putchar ('\0');
2679+ }
2680+ else
2681+ {
2682+ if (convert)
2683+ {
2684+ if (wc == L'\b')
2685+ {
2686+ if (column > 0)
2687+ --column;
2688+ }
2689+ else
2690+ {
2691+ int width; /* The width of WC. */
2692+
2693+ width = wcwidth (wc);
2694+ column += (width > 0) ? width : 0;
2695+ if (convert_entire_line == 0)
2696+ convert = 0;
2697+ }
2698+ }
2699+
2700+ if (wc == L'\n')
2701+ {
2702+ tab_index = print_tab_index = 0;
2703+ column = pending = 0;
2704+ convert = 1;
2705+ }
2706+ fwrite (bufpos, sizeof(char), mblength, stdout);
2707+ }
2708+ }
2709+ buflen -= mblength;
2710+ bufpos += mblength;
2711+ }
2712+}
2713+#endif
2714+
2715+
2716 void
2717 usage (int status)
2718 {
2719@@ -531,7 +750,12 @@
2720
2721 file_list = (optind < argc ? &argv[optind] : stdin_argv);
2722
2723- unexpand ();
2724+#if HAVE_MBRTOWC
2725+ if (MB_CUR_MAX > 1)
2726+ unexpand_multibyte ();
2727+ else
2728+#endif
2729+ unexpand ();
2730
2731 if (have_read_stdin && fclose (stdin) != 0)
2732 error (EXIT_FAILURE, errno, "-");
2733--- coreutils-6.8+/src/pr.c.i18n 2007-01-14 15:41:28.000000000 +0000
2734+++ coreutils-6.8+/src/pr.c 2007-03-01 15:08:24.000000000 +0000
2735@@ -313,6 +313,32 @@
2736
2737 #include <getopt.h>
2738 #include <sys/types.h>
2739+
2740+/* Get MB_LEN_MAX. */
2741+#include <limits.h>
2742+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
2743+ installation; work around this configuration error. */
2744+#if !defined MB_LEN_MAX || MB_LEN_MAX == 1
2745+# define MB_LEN_MAX 16
2746+#endif
2747+
2748+/* Get MB_CUR_MAX. */
2749+#include <stdlib.h>
2750+
2751+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
2752+/* Get mbstate_t, mbrtowc(), wcwidth(). */
2753+#if HAVE_WCHAR_H
2754+# include <wchar.h>
2755+#endif
2756+
2757+/* Get iswprint(). -- for wcwidth(). */
2758+#if HAVE_WCTYPE_H
2759+# include <wctype.h>
2760+#endif
2761+#if !defined iswprint && !HAVE_ISWPRINT
2762+# define iswprint(wc) 1
2763+#endif
2764+
2765 #include "system.h"
2766 #include "error.h"
2767 #include "hard-locale.h"
2768@@ -324,6 +350,18 @@
2769 #include "strftime.h"
2770 #include "xstrtol.h"
2771
2772+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
2773+#if HAVE_MBRTOWC && defined mbstate_t
2774+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
2775+#endif
2776+
2777+#ifndef HAVE_DECL_WCWIDTH
2778+"this configure-time declaration test was not run"
2779+#endif
2780+#if !HAVE_DECL_WCWIDTH
2781+extern int wcwidth ();
2782+#endif
2783+
2784 /* The official name of this program (e.g., no `g' prefix). */
2785 #define PROGRAM_NAME "pr"
2786
2787@@ -416,7 +454,20 @@
2788
2789 #define NULLCOL (COLUMN *)0
2790
2791-static int char_to_clump (char c);
2792+/* Funtion pointers to switch functions for single byte locale or for
2793+ multibyte locale. If multibyte functions do not exist in your sysytem,
2794+ these pointers always point the function for single byte locale. */
2795+static void (*print_char) (char c);
2796+static int (*char_to_clump) (char c);
2797+
2798+/* Functions for single byte locale. */
2799+static void print_char_single (char c);
2800+static int char_to_clump_single (char c);
2801+
2802+/* Functions for multibyte locale. */
2803+static void print_char_multi (char c);
2804+static int char_to_clump_multi (char c);
2805+
2806 static bool read_line (COLUMN *p);
2807 static bool print_page (void);
2808 static bool print_stored (COLUMN *p);
2809@@ -426,6 +477,7 @@
2810 static void pad_across_to (int position);
2811 static void add_line_number (COLUMN *p);
2812 static void getoptarg (char *arg, char switch_char, char *character,
2813+ int *character_length, int *character_width,
2814 int *number);
2815 void usage (int status);
2816 static void print_files (int number_of_files, char **av);
2817@@ -440,7 +492,6 @@
2818 static void pad_down (int lines);
2819 static void read_rest_of_line (COLUMN *p);
2820 static void skip_read (COLUMN *p, int column_number);
2821-static void print_char (char c);
2822 static void cleanup (void);
2823 static void print_sep_string (void);
2824 static void separator_string (const char *optarg_S);
2825@@ -455,7 +506,7 @@
2826 we store the leftmost columns contiguously in buff.
2827 To print a line from buff, get the index of the first character
2828 from line_vector[i], and print up to line_vector[i + 1]. */
2829-static char *buff;
2830+static unsigned char *buff;
2831
2832 /* Index of the position in buff where the next character
2833 will be stored. */
2834@@ -559,7 +610,7 @@
2835 static bool untabify_input = false;
2836
2837 /* (-e) The input tab character. */
2838-static char input_tab_char = '\t';
2839+static char input_tab_char[MB_LEN_MAX] = "\t";
2840
2841 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
2842 where the leftmost column is 1. */
2843@@ -569,7 +620,10 @@
2844 static bool tabify_output = false;
2845
2846 /* (-i) The output tab character. */
2847-static char output_tab_char = '\t';
2848+static char output_tab_char[MB_LEN_MAX] = "\t";
2849+
2850+/* (-i) The byte length of output tab character. */
2851+static int output_tab_char_length = 1;
2852
2853 /* (-i) The width of the output tab. */
2854 static int chars_per_output_tab = 8;
2855@@ -643,7 +697,13 @@
2856 static bool numbered_lines = false;
2857
2858 /* (-n) Character which follows each line number. */
2859-static char number_separator = '\t';
2860+static char number_separator[MB_LEN_MAX] = "\t";
2861+
2862+/* (-n) The byte length of the character which follows each line number. */
2863+static int number_separator_length = 1;
2864+
2865+/* (-n) The character width of the character which follows each line number. */
2866+static int number_separator_width = 0;
2867
2868 /* (-n) line counting starts with 1st line of input file (not with 1st
2869 line of 1st page printed). */
2870@@ -696,6 +756,7 @@
2871 -a|COLUMN|-m is a `space' and with the -J option a `tab'. */
2872 static char *col_sep_string = "";
2873 static int col_sep_length = 0;
2874+static int col_sep_width = 0;
2875 static char *column_separator = " ";
2876 static char *line_separator = "\t";
2877
2878@@ -852,6 +913,13 @@
2879 col_sep_length = (int) strlen (optarg_S);
2880 col_sep_string = xmalloc (col_sep_length + 1);
2881 strcpy (col_sep_string, optarg_S);
2882+
2883+#if HAVE_MBRTOWC
2884+ if (MB_CUR_MAX > 1)
2885+ col_sep_width = mbswidth (col_sep_string, 0);
2886+ else
2887+#endif
2888+ col_sep_width = col_sep_length;
2889 }
2890
2891 int
2892@@ -877,6 +945,21 @@
2893
2894 atexit (close_stdout);
2895
2896+/* Define which functions are used, the ones for single byte locale or the ones
2897+ for multibyte locale. */
2898+#if HAVE_MBRTOWC
2899+ if (MB_CUR_MAX > 1)
2900+ {
2901+ print_char = print_char_multi;
2902+ char_to_clump = char_to_clump_multi;
2903+ }
2904+ else
2905+#endif
2906+ {
2907+ print_char = print_char_single;
2908+ char_to_clump = char_to_clump_single;
2909+ }
2910+
2911 n_files = 0;
2912 file_names = (argc > 1
2913 ? xmalloc ((argc - 1) * sizeof (char *))
2914@@ -949,8 +1032,12 @@
2915 break;
2916 case 'e':
2917 if (optarg)
2918- getoptarg (optarg, 'e', &input_tab_char,
2919- &chars_per_input_tab);
2920+ {
2921+ int dummy_length, dummy_width;
2922+
2923+ getoptarg (optarg, 'e', input_tab_char, &dummy_length,
2924+ &dummy_width, &chars_per_input_tab);
2925+ }
2926 /* Could check tab width > 0. */
2927 untabify_input = true;
2928 break;
2929@@ -963,8 +1050,12 @@
2930 break;
2931 case 'i':
2932 if (optarg)
2933- getoptarg (optarg, 'i', &output_tab_char,
2934- &chars_per_output_tab);
2935+ {
2936+ int dummy_width;
2937+
2938+ getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length,
2939+ &dummy_width, &chars_per_output_tab);
2940+ }
2941 /* Could check tab width > 0. */
2942 tabify_output = true;
2943 break;
2944@@ -991,8 +1082,8 @@
2945 case 'n':
2946 numbered_lines = true;
2947 if (optarg)
2948- getoptarg (optarg, 'n', &number_separator,
2949- &chars_per_number);
2950+ getoptarg (optarg, 'n', number_separator, &number_separator_length,
2951+ &number_separator_width, &chars_per_number);
2952 break;
2953 case 'N':
2954 skip_count = false;
2955@@ -1031,7 +1122,7 @@
2956 old_s = false;
2957 /* Reset an additional input of -s, -S dominates -s */
2958 col_sep_string = "";
2959- col_sep_length = 0;
2960+ col_sep_length = col_sep_width = 0;
2961 use_col_separator = true;
2962 if (optarg)
2963 separator_string (optarg);
2964@@ -1188,10 +1279,45 @@
2965 a number. */
2966
2967 static void
2968-getoptarg (char *arg, char switch_char, char *character, int *number)
2969+getoptarg (char *arg, char switch_char, char *character, int *character_length,
2970+ int *character_width, int *number)
2971 {
2972 if (!ISDIGIT (*arg))
2973- *character = *arg++;
2974+ {
2975+#ifdef HAVE_MBRTOWC
2976+ if (MB_CUR_MAX > 1) /* for multibyte locale. */
2977+ {
2978+ wchar_t wc;
2979+ size_t mblength;
2980+ int width;
2981+ mbstate_t state = {'\0'};
2982+
2983+ mblength = mbrtowc (&wc, arg, strnlen(arg, MB_LEN_MAX), &state);
2984+
2985+ if (mblength == (size_t)-1 || mblength == (size_t)-2)
2986+ {
2987+ *character_length = 1;
2988+ *character_width = 1;
2989+ }
2990+ else
2991+ {
2992+ *character_length = (mblength < 1) ? 1 : mblength;
2993+ width = wcwidth (wc);
2994+ *character_width = (width < 0) ? 0 : width;
2995+ }
2996+
2997+ strncpy (character, arg, *character_length);
2998+ arg += *character_length;
2999+ }
3000+ else /* for single byte locale. */
3001+#endif
3002+ {
3003+ *character = *arg++;
3004+ *character_length = 1;
3005+ *character_width = 1;
3006+ }
3007+ }
3008+
3009 if (*arg)
3010 {
3011 long int tmp_long;
3012@@ -1256,7 +1382,7 @@
3013 else
3014 col_sep_string = column_separator;
3015
3016- col_sep_length = 1;
3017+ col_sep_length = col_sep_width = 1;
3018 use_col_separator = true;
3019 }
3020 /* It's rather pointless to define a TAB separator with column
3021@@ -1288,11 +1414,11 @@
3022 TAB_WIDTH (chars_per_input_tab, chars_per_number); */
3023
3024 /* Estimate chars_per_text without any margin and keep it constant. */
3025- if (number_separator == '\t')
3026+ if (number_separator[0] == '\t')
3027 number_width = chars_per_number +
3028 TAB_WIDTH (chars_per_default_tab, chars_per_number);
3029 else
3030- number_width = chars_per_number + 1;
3031+ number_width = chars_per_number + number_separator_width;
3032
3033 /* The number is part of the column width unless we are
3034 printing files in parallel. */
3035@@ -1307,7 +1433,7 @@
3036 }
3037
3038 chars_per_column = (chars_per_line - chars_used_by_number -
3039- (columns - 1) * col_sep_length) / columns;
3040+ (columns - 1) * col_sep_width) / columns;
3041
3042 if (chars_per_column < 1)
3043 error (EXIT_FAILURE, 0, _("page width too narrow"));
3044@@ -1432,7 +1558,7 @@
3045
3046 /* Enlarge p->start_position of first column to use the same form of
3047 padding_not_printed with all columns. */
3048- h = h + col_sep_length;
3049+ h = h + col_sep_width;
3050
3051 /* This loop takes care of all but the rightmost column. */
3052
3053@@ -1466,7 +1592,7 @@
3054 }
3055 else
3056 {
3057- h = h_next + col_sep_length;
3058+ h = h_next + col_sep_width;
3059 h_next = h + chars_per_column;
3060 }
3061 }
3062@@ -1756,9 +1882,9 @@
3063 align_column (COLUMN *p)
3064 {
3065 padding_not_printed = p->start_position;
3066- if (padding_not_printed - col_sep_length > 0)
3067+ if (padding_not_printed - col_sep_width > 0)
3068 {
3069- pad_across_to (padding_not_printed - col_sep_length);
3070+ pad_across_to (padding_not_printed - col_sep_width);
3071 padding_not_printed = ANYWHERE;
3072 }
3073
3074@@ -2029,13 +2155,13 @@
3075 /* May be too generous. */
3076 buff = X2REALLOC (buff, &buff_allocated);
3077 }
3078- buff[buff_current++] = c;
3079+ buff[buff_current++] = (unsigned char) c;
3080 }
3081
3082 static void
3083 add_line_number (COLUMN *p)
3084 {
3085- int i;
3086+ int i, j;
3087 char *s;
3088 int left_cut;
3089
3090@@ -2058,22 +2184,24 @@
3091 /* Tabification is assumed for multiple columns, also for n-separators,
3092 but `default n-separator = TAB' hasn't been given priority over
3093 equal column_width also specified by POSIX. */
3094- if (number_separator == '\t')
3095+ if (number_separator[0] == '\t')
3096 {
3097 i = number_width - chars_per_number;
3098 while (i-- > 0)
3099 (p->char_func) (' ');
3100 }
3101 else
3102- (p->char_func) (number_separator);
3103+ for (j = 0; j < number_separator_length; j++)
3104+ (p->char_func) (number_separator[j]);
3105 }
3106 else
3107 /* To comply with POSIX, we avoid any expansion of default TAB
3108 separator with a single column output. No column_width requirement
3109 has to be considered. */
3110 {
3111- (p->char_func) (number_separator);
3112- if (number_separator == '\t')
3113+ for (j = 0; j < number_separator_length; j++)
3114+ (p->char_func) (number_separator[j]);
3115+ if (number_separator[0] == '\t')
3116 output_position = POS_AFTER_TAB (chars_per_output_tab,
3117 output_position);
3118 }
3119@@ -2234,7 +2362,7 @@
3120 while (goal - h_old > 1
3121 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
3122 {
3123- putchar (output_tab_char);
3124+ fwrite (output_tab_char, sizeof(char), output_tab_char_length, stdout);
3125 h_old = h_new;
3126 }
3127 while (++h_old <= goal)
3128@@ -2254,6 +2382,7 @@
3129 {
3130 char *s;
3131 int l = col_sep_length;
3132+ int not_space_flag;
3133
3134 s = col_sep_string;
3135
3136@@ -2267,6 +2396,7 @@
3137 {
3138 for (; separators_not_printed > 0; --separators_not_printed)
3139 {
3140+ not_space_flag = 0;
3141 while (l-- > 0)
3142 {
3143 /* 3 types of sep_strings: spaces only, spaces and chars,
3144@@ -2280,12 +2410,15 @@
3145 }
3146 else
3147 {
3148+ not_space_flag = 1;
3149 if (spaces_not_printed > 0)
3150 print_white_space ();
3151 putchar (*s++);
3152- ++output_position;
3153 }
3154 }
3155+ if (not_space_flag)
3156+ output_position += col_sep_width;
3157+
3158 /* sep_string ends with some spaces */
3159 if (spaces_not_printed > 0)
3160 print_white_space ();
3161@@ -2313,7 +2446,7 @@
3162 required number of tabs and spaces. */
3163
3164 static void
3165-print_char (char c)
3166+print_char_single (char c)
3167 {
3168 if (tabify_output)
3169 {
3170@@ -2337,6 +2470,74 @@
3171 putchar (c);
3172 }
3173
3174+#ifdef HAVE_MBRTOWC
3175+static void
3176+print_char_multi (char c)
3177+{
3178+ static size_t mbc_pos = 0;
3179+ static char mbc[MB_LEN_MAX] = {'\0'};
3180+ static mbstate_t state = {'\0'};
3181+ mbstate_t state_bak;
3182+ wchar_t wc;
3183+ size_t mblength;
3184+ int width;
3185+
3186+ if (tabify_output)
3187+ {
3188+ state_bak = state;
3189+ mbc[mbc_pos++] = c;
3190+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
3191+
3192+ while (mbc_pos > 0)
3193+ {
3194+ switch (mblength)
3195+ {
3196+ case (size_t)-2:
3197+ state = state_bak;
3198+ return;
3199+
3200+ case (size_t)-1:
3201+ state = state_bak;
3202+ ++output_position;
3203+ putchar (mbc[0]);
3204+ memmove (mbc, mbc + 1, MB_CUR_MAX - 1);
3205+ --mbc_pos;
3206+ break;
3207+
3208+ case 0:
3209+ mblength = 1;
3210+
3211+ default:
3212+ if (wc == L' ')
3213+ {
3214+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
3215+ --mbc_pos;
3216+ ++spaces_not_printed;
3217+ return;
3218+ }
3219+ else if (spaces_not_printed > 0)
3220+ print_white_space ();
3221+
3222+ /* Nonprintables are assumed to have width 0, except L'\b'. */
3223+ if ((width = wcwidth (wc)) < 1)
3224+ {
3225+ if (wc == L'\b')
3226+ --output_position;
3227+ }
3228+ else
3229+ output_position += width;
3230+
3231+ fwrite (mbc, sizeof(char), mblength, stdout);
3232+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
3233+ mbc_pos -= mblength;
3234+ }
3235+ }
3236+ return;
3237+ }
3238+ putchar (c);
3239+}
3240+#endif
3241+
3242 /* Skip to page PAGE before printing.
3243 PAGE may be larger than total number of pages. */
3244
3245@@ -2517,9 +2718,9 @@
3246 align_empty_cols = false;
3247 }
3248
3249- if (padding_not_printed - col_sep_length > 0)
3250+ if (padding_not_printed - col_sep_width > 0)
3251 {
3252- pad_across_to (padding_not_printed - col_sep_length);
3253+ pad_across_to (padding_not_printed - col_sep_width);
3254 padding_not_printed = ANYWHERE;
3255 }
3256
3257@@ -2620,9 +2821,9 @@
3258 }
3259 }
3260
3261- if (padding_not_printed - col_sep_length > 0)
3262+ if (padding_not_printed - col_sep_width > 0)
3263 {
3264- pad_across_to (padding_not_printed - col_sep_length);
3265+ pad_across_to (padding_not_printed - col_sep_width);
3266 padding_not_printed = ANYWHERE;
3267 }
3268
3269@@ -2635,8 +2836,8 @@
3270 if (spaces_not_printed == 0)
3271 {
3272 output_position = p->start_position + end_vector[line];
3273- if (p->start_position - col_sep_length == chars_per_margin)
3274- output_position -= col_sep_length;
3275+ if (p->start_position - col_sep_width == chars_per_margin)
3276+ output_position -= col_sep_width;
3277 }
3278
3279 return true;
3280@@ -2655,7 +2856,7 @@
3281 number of characters is 1.) */
3282
3283 static int
3284-char_to_clump (char c)
3285+char_to_clump_single (char c)
3286 {
3287 unsigned char uc = c;
3288 char *s = clump_buff;
3289@@ -2665,10 +2866,10 @@
3290 int chars;
3291 int chars_per_c = 8;
3292
3293- if (c == input_tab_char)
3294+ if (c == input_tab_char[0])
3295 chars_per_c = chars_per_input_tab;
3296
3297- if (c == input_tab_char || c == '\t')
3298+ if (c == input_tab_char[0] || c == '\t')
3299 {
3300 width = TAB_WIDTH (chars_per_c, input_position);
3301
3302@@ -2739,6 +2940,154 @@
3303 return chars;
3304 }
3305
3306+#ifdef HAVE_MBRTOWC
3307+static int
3308+char_to_clump_multi (char c)
3309+{
3310+ static size_t mbc_pos = 0;
3311+ static char mbc[MB_LEN_MAX] = {'\0'};
3312+ static mbstate_t state = {'\0'};
3313+ mbstate_t state_bak;
3314+ wchar_t wc;
3315+ size_t mblength;
3316+ int wc_width;
3317+ register char *s = clump_buff;
3318+ register int i, j;
3319+ char esc_buff[4];
3320+ int width;
3321+ int chars;
3322+ int chars_per_c = 8;
3323+
3324+ state_bak = state;
3325+ mbc[mbc_pos++] = c;
3326+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
3327+
3328+ width = 0;
3329+ chars = 0;
3330+ while (mbc_pos > 0)
3331+ {
3332+ switch (mblength)
3333+ {
3334+ case (size_t)-2:
3335+ state = state_bak;
3336+ return 0;
3337+
3338+ case (size_t)-1:
3339+ state = state_bak;
3340+ mblength = 1;
3341+
3342+ if (use_esc_sequence || use_cntrl_prefix)
3343+ {
3344+ width = +4;
3345+ chars = +4;
3346+ *s++ = '\\';
3347+ sprintf (esc_buff, "%03o", mbc[0]);
3348+ for (i = 0; i <= 2; ++i)
3349+ *s++ = (int) esc_buff[i];
3350+ }
3351+ else
3352+ {
3353+ width += 1;
3354+ chars += 1;
3355+ *s++ = mbc[0];
3356+ }
3357+ break;
3358+
3359+ case 0:
3360+ mblength = 1;
3361+ /* Fall through */
3362+
3363+ default:
3364+ if (memcmp (mbc, input_tab_char, mblength) == 0)
3365+ chars_per_c = chars_per_input_tab;
3366+
3367+ if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t')
3368+ {
3369+ int width_inc;
3370+
3371+ width_inc = TAB_WIDTH (chars_per_c, input_position);
3372+ width += width_inc;
3373+
3374+ if (untabify_input)
3375+ {
3376+ for (i = width_inc; i; --i)
3377+ *s++ = ' ';
3378+ chars += width_inc;
3379+ }
3380+ else
3381+ {
3382+ for (i = 0; i < mblength; i++)
3383+ *s++ = mbc[i];
3384+ chars += mblength;
3385+ }
3386+ }
3387+ else if ((wc_width = wcwidth (wc)) < 1)
3388+ {
3389+ if (use_esc_sequence)
3390+ {
3391+ for (i = 0; i < mblength; i++)
3392+ {
3393+ width += 4;
3394+ chars += 4;
3395+ *s++ = '\\';
3396+ sprintf (esc_buff, "%03o", c);
3397+ for (j = 0; j <= 2; ++j)
3398+ *s++ = (int) esc_buff[j];
3399+ }
3400+ }
3401+ else if (use_cntrl_prefix)
3402+ {
3403+ if (wc < 0200)
3404+ {
3405+ width += 2;
3406+ chars += 2;
3407+ *s++ = '^';
3408+ *s++ = wc ^ 0100;
3409+ }
3410+ else
3411+ {
3412+ for (i = 0; i < mblength; i++)
3413+ {
3414+ width += 4;
3415+ chars += 4;
3416+ *s++ = '\\';
3417+ sprintf (esc_buff, "%03o", c);
3418+ for (j = 0; j <= 2; ++j)
3419+ *s++ = (int) esc_buff[j];
3420+ }
3421+ }
3422+ }
3423+ else if (wc == L'\b')
3424+ {
3425+ width += -1;
3426+ chars += 1;
3427+ *s++ = c;
3428+ }
3429+ else
3430+ {
3431+ width += 0;
3432+ chars += mblength;
3433+ for (i = 0; i < mblength; i++)
3434+ *s++ = mbc[i];
3435+ }
3436+ }
3437+ else
3438+ {
3439+ width += wc_width;
3440+ chars += mblength;
3441+ for (i = 0; i < mblength; i++)
3442+ *s++ = mbc[i];
3443+ }
3444+ }
3445+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
3446+ mbc_pos -= mblength;
3447+ }
3448+
3449+ input_position += width;
3450+ return chars;
3451+}
3452+#endif
3453+
3454 /* We've just printed some files and need to clean up things before
3455 looking for more options and printing the next batch of files.
3456
3457--- coreutils-6.8+/src/cut.c.i18n 2007-01-14 15:41:28.000000000 +0000
3458+++ coreutils-6.8+/src/cut.c 2007-03-01 15:08:24.000000000 +0000
3459@@ -29,6 +29,11 @@
3460 #include <assert.h>
3461 #include <getopt.h>
3462 #include <sys/types.h>
3463+
3464+/* Get mbstate_t, mbrtowc(). */
3465+#if HAVE_WCHAR_H
3466+# include <wchar.h>
3467+#endif
3468 #include "system.h"
3469
3470 #include "error.h"
3471@@ -37,6 +42,18 @@
3472 #include "quote.h"
3473 #include "xstrndup.h"
3474
3475+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
3476+ installation; work around this configuration error. */
3477+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
3478+# undef MB_LEN_MAX
3479+# define MB_LEN_MAX 16
3480+#endif
3481+
3482+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
3483+#if HAVE_MBRTOWC && defined mbstate_t
3484+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
3485+#endif
3486+
3487 /* The official name of this program (e.g., no `g' prefix). */
3488 #define PROGRAM_NAME "cut"
3489
3490@@ -67,6 +84,52 @@
3491 } \
3492 while (0)
3493
3494+/* Refill the buffer BUF to get a multibyte character. */
3495+#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM) \
3496+ do \
3497+ { \
3498+ if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM)) \
3499+ { \
3500+ memmove (BUF, BUFPOS, BUFLEN); \
3501+ BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \
3502+ BUFPOS = BUF; \
3503+ } \
3504+ } \
3505+ while (0)
3506+
3507+/* Get wide character on BUFPOS. BUFPOS is not included after that.
3508+ If byte sequence is not valid as a character, CONVFAIL is 1. Otherwise 0. */
3509+#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \
3510+ do \
3511+ { \
3512+ mbstate_t state_bak; \
3513+ \
3514+ if (BUFLEN < 1) \
3515+ { \
3516+ WC = WEOF; \
3517+ break; \
3518+ } \
3519+ \
3520+ /* Get a wide character. */ \
3521+ CONVFAIL = 0; \
3522+ state_bak = STATE; \
3523+ MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE); \
3524+ \
3525+ switch (MBLENGTH) \
3526+ { \
3527+ case (size_t)-1: \
3528+ case (size_t)-2: \
3529+ CONVFAIL++; \
3530+ STATE = state_bak; \
3531+ /* Fall througn. */ \
3532+ \
3533+ case 0: \
3534+ MBLENGTH = 1; \
3535+ break; \
3536+ } \
3537+ } \
3538+ while (0)
3539+
3540 struct range_pair
3541 {
3542 size_t lo;
3543@@ -85,7 +148,7 @@
3544 /* The number of bytes allocated for FIELD_1_BUFFER. */
3545 static size_t field_1_bufsize;
3546
3547-/* The largest field or byte index used as an endpoint of a closed
3548+/* The largest byte, character or field index used as an endpoint of a closed
3549 or degenerate range specification; this doesn't include the starting
3550 index of right-open-ended ranges. For example, with either range spec
3551 `2-5,9-', `2-3,5,9-' this variable would be set to 5. */
3552@@ -97,10 +160,11 @@
3553
3554 /* This is a bit vector.
3555 In byte mode, which bytes to output.
3556+ In character mode, which characters to output.
3557 In field mode, which DELIM-separated fields to output.
3558- Both bytes and fields are numbered starting with 1,
3559+ Bytes, characters and fields are numbered starting with 1,
3560 so the zeroth bit of this array is unused.
3561- A field or byte K has been selected if
3562+ A byte, character or field K has been selected if
3563 (K <= MAX_RANGE_ENDPOINT and is_printable_field(K))
3564 || (EOL_RANGE_START > 0 && K >= EOL_RANGE_START). */
3565 static unsigned char *printable_field;
3566@@ -109,9 +173,12 @@
3567 {
3568 undefined_mode,
3569
3570- /* Output characters that are in the given bytes. */
3571+ /* Output bytes that are at the given positions. */
3572 byte_mode,
3573
3574+ /* Output characters that are at the given positions. */
3575+ character_mode,
3576+
3577 /* Output the given delimeter-separated fields. */
3578 field_mode
3579 };
3580@@ -121,6 +188,13 @@
3581
3582 static enum operating_mode operating_mode;
3583
3584+/* If nonzero, when in byte mode, don't split multibyte characters. */
3585+static int byte_mode_character_aware;
3586+
3587+/* If nonzero, the function for single byte locale is work
3588+ if this program runs on multibyte locale. */
3589+static int force_singlebyte_mode;
3590+
3591 /* If true do not output lines containing no delimeter characters.
3592 Otherwise, all such lines are printed. This option is valid only
3593 with field mode. */
3594@@ -132,6 +206,9 @@
3595
3596 /* The delimeter character for field mode. */
3597 static unsigned char delim;
3598+#if HAVE_WCHAR_H
3599+static wchar_t wcdelim;
3600+#endif
3601
3602 /* True if the --output-delimiter=STRING option was specified. */
3603 static bool output_delimiter_specified;
3604@@ -205,7 +282,7 @@
3605 -f, --fields=LIST select only these fields; also print any line\n\
3606 that contains no delimiter character, unless\n\
3607 the -s option is specified\n\
3608- -n (ignored)\n\
3609+ -n with -b: don't split multibyte characters\n\
3610 "), stdout);
3611 fputs (_("\
3612 --complement complement the set of selected bytes, characters\n\
3613@@ -362,7 +439,7 @@
3614 in_digits = false;
3615 /* Starting a range. */
3616 if (dash_found)
3617- FATAL_ERROR (_("invalid byte or field list"));
3618+ FATAL_ERROR (_("invalid byte, character or field list"));
3619 dash_found = true;
3620 fieldstr++;
3621
3622@@ -387,14 +464,16 @@
3623 if (value == 0)
3624 {
3625 /* `n-'. From `initial' to end of line. */
3626- eol_range_start = initial;
3627+ if (eol_range_start == 0 ||
3628+ (eol_range_start != 0 && eol_range_start > initial))
3629+ eol_range_start = initial;
3630 field_found = true;
3631 }
3632 else
3633 {
3634 /* `m-n' or `-n' (1-n). */
3635 if (value < initial)
3636- FATAL_ERROR (_("invalid byte or field list"));
3637+ FATAL_ERROR (_("invalid byte, character or field list"));
3638
3639 /* Is there already a range going to end of line? */
3640 if (eol_range_start != 0)
3641@@ -467,6 +546,9 @@
3642 if (operating_mode == byte_mode)
3643 error (0, 0,
3644 _("byte offset %s is too large"), quote (bad_num));
3645+ else if (operating_mode == character_mode)
3646+ error (0, 0,
3647+ _("character offset %s is too large"), quote (bad_num));
3648 else
3649 error (0, 0,
3650 _("field number %s is too large"), quote (bad_num));
3651@@ -477,7 +559,7 @@
3652 fieldstr++;
3653 }
3654 else
3655- FATAL_ERROR (_("invalid byte or field list"));
3656+ FATAL_ERROR (_("invalid byte, character or field list"));
3657 }
3658
3659 max_range_endpoint = 0;
3660@@ -570,6 +652,63 @@
3661 }
3662 }
3663
3664+#if HAVE_MBRTOWC
3665+/* This function is in use for the following case.
3666+
3667+ 1. Read from the stream STREAM, printing to standard output any selected
3668+ characters.
3669+
3670+ 2. Read from stream STREAM, printing to standard output any selected bytes,
3671+ without splitting multibyte characters. */
3672+
3673+static void
3674+cut_characters_or_cut_bytes_no_split (FILE *stream)
3675+{
3676+ int idx; /* number of bytes or characters in the line so far. */
3677+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */
3678+ char *bufpos; /* Next read position of BUF. */
3679+ size_t buflen; /* The length of the byte sequence in buf. */
3680+ wint_t wc; /* A gotten wide character. */
3681+ size_t mblength; /* The byte size of a multibyte character which shows
3682+ as same character as WC. */
3683+ mbstate_t state; /* State of the stream. */
3684+ int convfail; /* 1, when conversion is failed. Otherwise 0. */
3685+
3686+ idx = 0;
3687+ buflen = 0;
3688+ bufpos = buf;
3689+ memset (&state, '\0', sizeof(mbstate_t));
3690+
3691+ while (1)
3692+ {
3693+ REFILL_BUFFER (buf, bufpos, buflen, stream);
3694+
3695+ GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail);
3696+
3697+ if (wc == WEOF)
3698+ {
3699+ if (idx > 0)
3700+ putchar ('\n');
3701+ break;
3702+ }
3703+ else if (wc == L'\n')
3704+ {
3705+ putchar ('\n');
3706+ idx = 0;
3707+ }
3708+ else
3709+ {
3710+ idx += (operating_mode == byte_mode) ? mblength : 1;
3711+ if (print_kth (idx, NULL))
3712+ fwrite (bufpos, mblength, sizeof(char), stdout);
3713+ }
3714+
3715+ buflen -= mblength;
3716+ bufpos += mblength;
3717+ }
3718+}
3719+#endif
3720+
3721 /* Read from stream STREAM, printing to standard output any selected fields. */
3722
3723 static void
3724@@ -692,13 +831,192 @@
3725 }
3726 }
3727
3728+#if HAVE_MBRTOWC
3729+static void
3730+cut_fields_mb (FILE *stream)
3731+{
3732+ int c;
3733+ unsigned int field_idx;
3734+ int found_any_selected_field;
3735+ int buffer_first_field;
3736+ int empty_input;
3737+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */
3738+ char *bufpos; /* Next read position of BUF. */
3739+ size_t buflen; /* The length of the byte sequence in buf. */
3740+ wint_t wc = 0; /* A gotten wide character. */
3741+ size_t mblength; /* The byte size of a multibyte character which shows
3742+ as same character as WC. */
3743+ mbstate_t state; /* State of the stream. */
3744+ int convfail; /* 1, when conversion is failed. Otherwise 0. */
3745+
3746+ found_any_selected_field = 0;
3747+ field_idx = 1;
3748+ bufpos = buf;
3749+ buflen = 0;
3750+ memset (&state, '\0', sizeof(mbstate_t));
3751+
3752+ c = getc (stream);
3753+ empty_input = (c == EOF);
3754+ if (c != EOF)
3755+ ungetc (c, stream);
3756+ else
3757+ wc = WEOF;
3758+
3759+ /* To support the semantics of the -s flag, we may have to buffer
3760+ all of the first field to determine whether it is `delimited.'
3761+ But that is unnecessary if all non-delimited lines must be printed
3762+ and the first field has been selected, or if non-delimited lines
3763+ must be suppressed and the first field has *not* been selected.
3764+ That is because a non-delimited line has exactly one field. */
3765+ buffer_first_field = (suppress_non_delimited ^ !print_kth (1, NULL));
3766+
3767+ while (1)
3768+ {
3769+ if (field_idx == 1 && buffer_first_field)
3770+ {
3771+ int len = 0;
3772+
3773+ while (1)
3774+ {
3775+ REFILL_BUFFER (buf, bufpos, buflen, stream);
3776+
3777+ GET_NEXT_WC_FROM_BUFFER
3778+ (wc, bufpos, buflen, mblength, state, convfail);
3779+
3780+ if (wc == WEOF)
3781+ break;
3782+
3783+ field_1_buffer = xrealloc (field_1_buffer, len + mblength);
3784+ memcpy (field_1_buffer + len, bufpos, mblength);
3785+ len += mblength;
3786+ buflen -= mblength;
3787+ bufpos += mblength;
3788+
3789+ if (!convfail && (wc == L'\n' || wc == wcdelim))
3790+ break;
3791+ }
3792+
3793+ if (wc == WEOF)
3794+ break;
3795+
3796+ /* If the first field extends to the end of line (it is not
3797+ delimited) and we are printing all non-delimited lines,
3798+ print this one. */
3799+ if (convfail || (!convfail && wc != wcdelim))
3800+ {
3801+ if (suppress_non_delimited)
3802+ {
3803+ /* Empty. */
3804+ }
3805+ else
3806+ {
3807+ fwrite (field_1_buffer, sizeof (char), len, stdout);
3808+ /* Make sure the output line is newline terminated. */
3809+ if (convfail || (!convfail && wc != L'\n'))
3810+ putchar ('\n');
3811+ }
3812+ continue;
3813+ }
3814+
3815+ if (print_kth (1, NULL))
3816+ {
3817+ /* Print the field, but not the trailing delimiter. */
3818+ fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
3819+ found_any_selected_field = 1;
3820+ }
3821+ ++field_idx;
3822+ }
3823+
3824+ if (wc != WEOF)
3825+ {
3826+ if (print_kth (field_idx, NULL))
3827+ {
3828+ if (found_any_selected_field)
3829+ {
3830+ fwrite (output_delimiter_string, sizeof (char),
3831+ output_delimiter_length, stdout);
3832+ }
3833+ found_any_selected_field = 1;
3834+ }
3835+
3836+ while (1)
3837+ {
3838+ REFILL_BUFFER (buf, bufpos, buflen, stream);
3839+
3840+ GET_NEXT_WC_FROM_BUFFER
3841+ (wc, bufpos, buflen, mblength, state, convfail);
3842+
3843+ if (wc == WEOF)
3844+ break;
3845+ else if (!convfail && (wc == wcdelim || wc == L'\n'))
3846+ {
3847+ buflen -= mblength;
3848+ bufpos += mblength;
3849+ break;
3850+ }
3851+
3852+ if (print_kth (field_idx, NULL))
3853+ fwrite (bufpos, mblength, sizeof(char), stdout);
3854+
3855+ buflen -= mblength;
3856+ bufpos += mblength;
3857+ }
3858+ }
3859+
3860+ if ((!convfail || wc == L'\n') && buflen < 1)
3861+ wc = WEOF;
3862+
3863+ if (!convfail && wc == wcdelim)
3864+ ++field_idx;
3865+ else if (wc == WEOF || (!convfail && wc == L'\n'))
3866+ {
3867+ if (found_any_selected_field
3868+ || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
3869+ putchar ('\n');
3870+ if (wc == WEOF)
3871+ break;
3872+ field_idx = 1;
3873+ found_any_selected_field = 0;
3874+ }
3875+ }
3876+}
3877+#endif
3878+
3879 static void
3880 cut_stream (FILE *stream)
3881 {
3882- if (operating_mode == byte_mode)
3883- cut_bytes (stream);
3884+#if HAVE_MBRTOWC
3885+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
3886+ {
3887+ switch (operating_mode)
3888+ {
3889+ case byte_mode:
3890+ if (byte_mode_character_aware)
3891+ cut_characters_or_cut_bytes_no_split (stream);
3892+ else
3893+ cut_bytes (stream);
3894+ break;
3895+
3896+ case character_mode:
3897+ cut_characters_or_cut_bytes_no_split (stream);
3898+ break;
3899+
3900+ case field_mode:
3901+ cut_fields_mb (stream);
3902+ break;
3903+
3904+ default:
3905+ abort ();
3906+ }
3907+ }
3908 else
3909- cut_fields (stream);
3910+#endif
3911+ {
3912+ if (operating_mode == field_mode)
3913+ cut_fields (stream);
3914+ else
3915+ cut_bytes (stream);
3916+ }
3917 }
3918
3919 /* Process file FILE to standard output.
3920@@ -748,6 +1066,8 @@
3921 bool ok;
3922 bool delim_specified = false;
3923 char *spec_list_string IF_LINT(= NULL);
3924+ char mbdelim[MB_LEN_MAX + 1];
3925+ size_t delimlen = 0;
3926
3927 initialize_main (&argc, &argv);
3928 program_name = argv[0];
3929@@ -770,7 +1090,6 @@
3930 switch (optc)
3931 {
3932 case 'b':
3933- case 'c':
3934 /* Build the byte list. */
3935 if (operating_mode != undefined_mode)
3936 FATAL_ERROR (_("only one type of list may be specified"));
3937@@ -778,6 +1097,14 @@
3938 spec_list_string = optarg;
3939 break;
3940
3941+ case 'c':
3942+ /* Build the character list. */
3943+ if (operating_mode != undefined_mode)
3944+ FATAL_ERROR (_("only one type of list may be specified"));
3945+ operating_mode = character_mode;
3946+ spec_list_string = optarg;
3947+ break;
3948+
3949 case 'f':
3950 /* Build the field list. */
3951 if (operating_mode != undefined_mode)
3952@@ -789,10 +1116,35 @@
3953 case 'd':
3954 /* New delimiter. */
3955 /* Interpret -d '' to mean `use the NUL byte as the delimiter.' */
3956- if (optarg[0] != '\0' && optarg[1] != '\0')
3957- FATAL_ERROR (_("the delimiter must be a single character"));
3958- delim = optarg[0];
3959- delim_specified = true;
3960+#if HAVE_MBRTOWC
3961+ {
3962+ if(MB_CUR_MAX > 1)
3963+ {
3964+ mbstate_t state;
3965+
3966+ memset (&state, '\0', sizeof(mbstate_t));
3967+ delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state);
3968+
3969+ if (delimlen == (size_t)-1 || delimlen == (size_t)-2)
3970+ ++force_singlebyte_mode;
3971+ else
3972+ {
3973+ delimlen = (delimlen < 1) ? 1 : delimlen;
3974+ if (wcdelim != L'\0' && *(optarg + delimlen) != '\0')
3975+ FATAL_ERROR (_("the delimiter must be a single character"));
3976+ memcpy (mbdelim, optarg, delimlen);
3977+ }
3978+ }
3979+
3980+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
3981+#endif
3982+ {
3983+ if (optarg[0] != '\0' && optarg[1] != '\0')
3984+ FATAL_ERROR (_("the delimiter must be a single character"));
3985+ delim = (unsigned char) optarg[0];
3986+ }
3987+ delim_specified = true;
3988+ }
3989 break;
3990
3991 case OUTPUT_DELIMITER_OPTION:
3992@@ -805,6 +1157,7 @@
3993 break;
3994
3995 case 'n':
3996+ byte_mode_character_aware = 1;
3997 break;
3998
3999 case 's':
4000@@ -827,7 +1180,7 @@
4001 if (operating_mode == undefined_mode)
4002 FATAL_ERROR (_("you must specify a list of bytes, characters, or fields"));
4003
4004- if (delim != '\0' && operating_mode != field_mode)
4005+ if (delim_specified && operating_mode != field_mode)
4006 FATAL_ERROR (_("an input delimiter may be specified only\
4007 when operating on fields"));
4008
4009@@ -854,15 +1207,34 @@
4010 }
4011
4012 if (!delim_specified)
4013- delim = '\t';
4014+ {
4015+ delim = '\t';
4016+#ifdef HAVE_MBRTOWC
4017+ wcdelim = L'\t';
4018+ mbdelim[0] = '\t';
4019+ mbdelim[1] = '\0';
4020+ delimlen = 1;
4021+#endif
4022+ }
4023
4024 if (output_delimiter_string == NULL)
4025 {
4026- static char dummy[2];
4027- dummy[0] = delim;
4028- dummy[1] = '\0';
4029- output_delimiter_string = dummy;
4030- output_delimiter_length = 1;
4031+#ifdef HAVE_MBRTOWC
4032+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
4033+ {
4034+ output_delimiter_string = xstrdup(mbdelim);
4035+ output_delimiter_length = delimlen;
4036+ }
4037+
4038+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
4039+#endif
4040+ {
4041+ static char dummy[2];
4042+ dummy[0] = delim;
4043+ dummy[1] = '\0';
4044+ output_delimiter_string = dummy;
4045+ output_delimiter_length = 1;
4046+ }
4047 }
4048
4049 if (optind == argc)
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-ls-x.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-ls-x.patch
new file mode 100644
index 0000000000..2d61438209
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-ls-x.patch
@@ -0,0 +1,115 @@
1This patch was imported from the Fedora Core 8 coreutils-6.9-9 package.
2
3The package is stated as being Licensed as GPLv2+.
4
5Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
6
7--- coreutils-6.9/src/ls.c.ls-x 2007-06-13 14:27:36.000000000 +0100
8+++ coreutils-6.9/src/ls.c 2007-06-13 14:28:42.000000000 +0100
9@@ -4151,16 +4151,16 @@
10 size_t pos = 0;
11 size_t cols = calculate_columns (false);
12 struct column_info const *line_fmt = &column_info[cols - 1];
13- size_t name_length = length_of_file_name_and_frills (cwd_file);
14+ struct fileinfo const *f = sorted_file[0];
15+ size_t name_length = length_of_file_name_and_frills (f);
16 size_t max_name_length = line_fmt->col_arr[0];
17
18 /* Print first entry. */
19- print_file_name_and_frills (cwd_file);
20+ print_file_name_and_frills (f);
21
22 /* Now the rest. */
23 for (filesno = 1; filesno < cwd_n_used; ++filesno)
24 {
25- struct fileinfo const *f;
26 size_t col = filesno % cols;
27
28 if (col == 0)
29--- coreutils-6.9/tests/ls/Makefile.am.ls-x 2007-03-18 21:36:43.000000000 +0000
30+++ coreutils-6.9/tests/ls/Makefile.am 2007-06-13 14:28:42.000000000 +0100
31@@ -24,7 +24,7 @@
32 stat-dtype \
33 inode dangle file-type recursive dired infloop \
34 rt-1 time-1 symlink-slash follow-slink no-arg m-option \
35- stat-vs-dirent
36+ stat-vs-dirent x-option
37
38 EXTRA_DIST = $(TESTS)
39 TESTS_ENVIRONMENT = \
40--- /dev/null 2007-06-13 08:43:51.993263382 +0100
41+++ coreutils-6.9/tests/ls/x-option 2007-06-13 14:28:42.000000000 +0100
42@@ -0,0 +1,59 @@
43+#!/bin/sh
44+# Exercise the -x option.
45+
46+# Copyright (C) 2007 Free Software Foundation, Inc.
47+
48+# This program is free software; you can redistribute it and/or modify
49+# it under the terms of the GNU General Public License as published by
50+# the Free Software Foundation; either version 2 of the License, or
51+# (at your option) any later version.
52+
53+# This program is distributed in the hope that it will be useful,
54+# but WITHOUT ANY WARRANTY; without even the implied warranty of
55+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56+# GNU General Public License for more details.
57+
58+# You should have received a copy of the GNU General Public License
59+# along with this program; if not, write to the Free Software
60+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
61+# 02110-1301, USA.
62+
63+if test "$VERBOSE" = yes; then
64+ set -x
65+ ls --version
66+fi
67+
68+. $srcdir/../envvar-check
69+. $srcdir/../lang-default
70+
71+pwd=`pwd`
72+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
73+trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
74+trap '(exit $?); exit $?' 1 2 13 15
75+
76+framework_failure=0
77+mkdir -p $tmp || framework_failure=1
78+cd $tmp || framework_failure=1
79+mkdir subdir || framework_failure=1
80+touch subdir/b || framework_failure=1
81+touch subdir/a || framework_failure=1
82+
83+if test $framework_failure = 1; then
84+ echo "$0: failure in testing framework" 1>&2
85+ (exit 1); exit 1
86+fi
87+
88+fail=0
89+
90+# Coreutils 6.8 and 6.9 would output this in the wrong order.
91+ls -x subdir > out || fail=1
92+ls -rx subdir >> out || fail=1
93+cat <<\EOF > exp || fail=1
94+a b
95+b a
96+EOF
97+
98+cmp out exp || fail=1
99+test $fail = 1 && diff out exp 2> /dev/null
100+
101+(exit $fail); exit $fail
102--- coreutils-6.9/NEWS.ls-x 2007-03-22 21:19:45.000000000 +0000
103+++ coreutils-6.9/NEWS 2007-06-13 14:28:42.000000000 +0100
104@@ -13,6 +13,11 @@
105 Using pr -m -s (i.e. merging files, with TAB as the output separator)
106 no longer inserts extraneous spaces between output columns.
107
108+** Bug fixes
109+
110+ ls -x DIR would sometimes output the wrong string in place of the
111+ first entry. [introduced in coreutils-6.8]
112+
113
114 * Noteworthy changes in release 6.8 (2007-02-24) [not-unstable]
115
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-overflow.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-overflow.patch
new file mode 100644
index 0000000000..d702757244
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-overflow.patch
@@ -0,0 +1,17 @@
1This patch was imported from the Fedora Core 8 coreutils-6.9-9 package.
2
3The package is stated as being Licensed as GPLv2+.
4
5Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
6
7--- coreutils-5.2.1/src/who.c.overflow 2005-05-25 09:59:06.000000000 +0100
8+++ coreutils-5.2.1/src/who.c 2005-05-25 10:00:31.000000000 +0100
9@@ -75,7 +75,7 @@
10 # define NEW_TIME 0
11 #endif
12
13-#define IDLESTR_LEN 6
14+#define IDLESTR_LEN 10
15
16 #if HAVE_STRUCT_XTMP_UT_PID
17 # define PIDSTR_DECL_AND_INIT(Var, Utmp_ent) \
diff --git a/meta/recipes-core/coreutils/coreutils_6.9.bb b/meta/recipes-core/coreutils/coreutils_6.9.bb
index 89f420a40b..60ea903432 100644
--- a/meta/recipes-core/coreutils/coreutils_6.9.bb
+++ b/meta/recipes-core/coreutils/coreutils_6.9.bb
@@ -16,6 +16,11 @@ inherit autotools gettext
16SRC_URI = "http://ftp.gnu.org/gnu/coreutils/${BP}.tar.bz2 \ 16SRC_URI = "http://ftp.gnu.org/gnu/coreutils/${BP}.tar.bz2 \
17 file://gnulib_m4.patch \ 17 file://gnulib_m4.patch \
18 file://futimens.patch \ 18 file://futimens.patch \
19 file://coreutils-ls-x.patch \
20 file://coreutils-6.9-cp-i-u.patch \
21 file://coreutils-i18n.patch \
22 file://coreutils-overflow.patch \
23 file://coreutils-fix-install.patch \
19 file://man-touch.patch" 24 file://man-touch.patch"
20 25
21# [ gets a special treatment and is not included in this 26# [ gets a special treatment and is not included in this