diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-03-02 12:04:08 (GMT) |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-03-07 20:05:31 (GMT) |
commit | 2345af9b4829ed3eed5abf60f2483055649f8af7 (patch) | |
tree | 96a9a31e4b1957b93c4fe3eb669117d2752caf0d | |
parent | c4901328fe5cf912c0965e5b011b64a95a9bcb9d (diff) | |
download | poky-uninative-1.5.tar.gz |
recipes: Move out stale GPLv2 versions to a seperate layeruninative-1.5
These are recipes where the upstream has moved to GPLv3 and these old
versions are the last ones under the GPLv2 license.
There are several reasons for making this move. There is a different
quality of service with these recipes in that they don't get security
fixes and upstream no longer care about them, in fact they're actively
hostile against people using old versions. The recipes tend to need a
different kind of maintenance to work with changes in the wider ecosystem
and there needs to be isolation between changes made in the v3 versions
and those in the v2 versions.
There are probably better ways to handle a "non-GPLv3" system but right
now having these in OE-Core makes them look like a first class citizen
when I believe they have potential for a variety of undesireable issues.
Moving them into a separate layer makes their different needs clearer, it
also makes it clear how many of these there are. Some are probably not
needed (e.g. mc), I also wonder whether some are useful (e.g. gmp)
since most things that use them are GPLv3 only already. Someone could
now more clearly see how to streamline the list of recipes here.
I'm proposing we mmove to this separate layer for 2.3 with its future
maintinership and testing to be determined in 2.4 and beyond.
(From OE-Core rev: 19b7e950346fb1dde6505c45236eba6cd9b33b4b)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
164 files changed, 0 insertions, 33689 deletions
diff --git a/meta/recipes-bsp/grub/grub-0.97/autohell.patch b/meta/recipes-bsp/grub/grub-0.97/autohell.patch deleted file mode 100644 index d66207a..0000000 --- a/meta/recipes-bsp/grub/grub-0.97/autohell.patch +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [configuration] | ||
2 | |||
3 | --- | ||
4 | configure.ac | 4 ++-- | ||
5 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
6 | |||
7 | Index: grub-0.97/configure.ac | ||
8 | =================================================================== | ||
9 | --- grub-0.97.orig/configure.ac 2008-09-12 17:39:52.000000000 +0200 | ||
10 | +++ grub-0.97/configure.ac 2008-09-12 17:40:21.000000000 +0200 | ||
11 | @@ -60,8 +60,8 @@ AC_PROG_CC | ||
12 | _AM_DEPENDENCIES(CC) | ||
13 | |||
14 | dnl Because recent automake complains about AS, set it here. | ||
15 | -CCAS="$CC" | ||
16 | -AC_SUBST(CCAS) | ||
17 | +AM_PROG_AS | ||
18 | +AC_SUBST(AS) | ||
19 | |||
20 | AC_ARG_WITH(binutils, | ||
21 | [ --with-binutils=DIR search the directory DIR to find binutils]) | ||
diff --git a/meta/recipes-bsp/grub/grub-0.97/grub-support-256byte-inode.patch b/meta/recipes-bsp/grub/grub-0.97/grub-support-256byte-inode.patch deleted file mode 100644 index d225d13..0000000 --- a/meta/recipes-bsp/grub/grub-0.97/grub-support-256byte-inode.patch +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [No Longer Maintained] | ||
2 | |||
3 | diff -Naur grub-0.97-800/stage2/fsys_ext2fs.c grub-0.97-810/stage2/fsys_ext2fs.c | ||
4 | --- grub-0.97-800/stage2/fsys_ext2fs.c 2008-07-21 00:40:21.668879475 -0600 | ||
5 | +++ grub-0.97-810/stage2/fsys_ext2fs.c 2008-07-21 01:01:11.063953773 -0600 | ||
6 | @@ -79,7 +79,52 @@ | ||
7 | __u32 s_rev_level; /* Revision level */ | ||
8 | __u16 s_def_resuid; /* Default uid for reserved blocks */ | ||
9 | __u16 s_def_resgid; /* Default gid for reserved blocks */ | ||
10 | - __u32 s_reserved[235]; /* Padding to the end of the block */ | ||
11 | + /* | ||
12 | + * These fields are for EXT2_DYNAMIC_REV superblocks only. | ||
13 | + * | ||
14 | + * Note: the difference between the compatible feature set and | ||
15 | + * the incompatible feature set is that if there is a bit set | ||
16 | + * in the incompatible feature set that the kernel doesn't | ||
17 | + * know about, it should refuse to mount the filesystem. | ||
18 | + * | ||
19 | + * e2fsck's requirements are more strict; if it doesn't know | ||
20 | + * about a feature in either the compatible or incompatible | ||
21 | + * feature set, it must abort and not try to meddle with | ||
22 | + * things it doesn't understand... | ||
23 | + */ | ||
24 | + __u32 s_first_ino; /* First non-reserved inode */ | ||
25 | + __u16 s_inode_size; /* size of inode structure */ | ||
26 | + __u16 s_block_group_nr; /* block group # of this superblock */ | ||
27 | + __u32 s_feature_compat; /* compatible feature set */ | ||
28 | + __u32 s_feature_incompat; /* incompatible feature set */ | ||
29 | + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ | ||
30 | + __u8 s_uuid[16]; /* 128-bit uuid for volume */ | ||
31 | + char s_volume_name[16]; /* volume name */ | ||
32 | + char s_last_mounted[64]; /* directory where last mounted */ | ||
33 | + __u32 s_algorithm_usage_bitmap; /* For compression */ | ||
34 | + /* | ||
35 | + * Performance hints. Directory preallocation should only | ||
36 | + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. | ||
37 | + */ | ||
38 | + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ | ||
39 | + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ | ||
40 | + __u16 s_reserved_gdt_blocks;/* Per group table for online growth */ | ||
41 | + /* | ||
42 | + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. | ||
43 | + */ | ||
44 | + __u8 s_journal_uuid[16]; /* uuid of journal superblock */ | ||
45 | + __u32 s_journal_inum; /* inode number of journal file */ | ||
46 | + __u32 s_journal_dev; /* device number of journal file */ | ||
47 | + __u32 s_last_orphan; /* start of list of inodes to delete */ | ||
48 | + __u32 s_hash_seed[4]; /* HTREE hash seed */ | ||
49 | + __u8 s_def_hash_version; /* Default hash version to use */ | ||
50 | + __u8 s_jnl_backup_type; /* Default type of journal backup */ | ||
51 | + __u16 s_reserved_word_pad; | ||
52 | + __u32 s_default_mount_opts; | ||
53 | + __u32 s_first_meta_bg; /* First metablock group */ | ||
54 | + __u32 s_mkfs_time; /* When the filesystem was created */ | ||
55 | + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ | ||
56 | + __u32 s_reserved[172]; /* Padding to the end of the block */ | ||
57 | }; | ||
58 | |||
59 | struct ext2_group_desc | ||
60 | @@ -218,6 +263,14 @@ | ||
61 | #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) | ||
62 | #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s))) | ||
63 | |||
64 | +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ | ||
65 | +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ | ||
66 | +#define EXT2_GOOD_OLD_INODE_SIZE 128 | ||
67 | +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ | ||
68 | + EXT2_GOOD_OLD_INODE_SIZE : \ | ||
69 | + (s)->s_inode_size) | ||
70 | +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) | ||
71 | + | ||
72 | /* linux/ext2_fs.h */ | ||
73 | #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) | ||
74 | /* kind of from ext2/super.c */ | ||
75 | @@ -553,7 +606,7 @@ | ||
76 | gdp = GROUP_DESC; | ||
77 | ino_blk = gdp[desc].bg_inode_table + | ||
78 | (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) | ||
79 | - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); | ||
80 | + >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK))); | ||
81 | #ifdef E2DEBUG | ||
82 | printf ("inode table fsblock=%d\n", ino_blk); | ||
83 | #endif /* E2DEBUG */ | ||
84 | @@ -565,13 +618,12 @@ | ||
85 | /* reset indirect blocks! */ | ||
86 | mapblock2 = mapblock1 = -1; | ||
87 | |||
88 | - raw_inode = INODE + | ||
89 | - ((current_ino - 1) | ||
90 | - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1)); | ||
91 | + raw_inode = (struct ext2_inode *)((char *)INODE + | ||
92 | + ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) * | ||
93 | + EXT2_INODE_SIZE (SUPERBLOCK)); | ||
94 | #ifdef E2DEBUG | ||
95 | printf ("ipb=%d, sizeof(inode)=%d\n", | ||
96 | - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)), | ||
97 | - sizeof (struct ext2_inode)); | ||
98 | + EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK)); | ||
99 | printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode); | ||
100 | printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE); | ||
101 | for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode; | ||
diff --git a/meta/recipes-bsp/grub/grub-0.97/grub_fix_for_automake-1.12.patch b/meta/recipes-bsp/grub/grub-0.97/grub_fix_for_automake-1.12.patch deleted file mode 100644 index 0cf7dc9..0000000 --- a/meta/recipes-bsp/grub/grub-0.97/grub_fix_for_automake-1.12.patch +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate | ||
2 | |||
3 | Subject: [PATCH] grub: fix for automake-1.12 | ||
4 | |||
5 | automake 1.12 has depricated automatic de-ANSI-fication support | ||
6 | |||
7 | this patch avoids these kinds of errors: | ||
8 | |||
9 | | stage1/Makefile.am:2: error: 'pkglibdir' is not a legitimate directory for 'DATA' | ||
10 | | stage2/Makefile.am:35: error: 'pkglibdir' is not a legitimate directory for 'DATA' | ||
11 | | stage2/Makefile.am:46: error: 'pkglibdir' is not a legitimate directory for 'DATA' | ||
12 | | autoreconf: automake failed with exit status: 1 | ||
13 | | ERROR: autoreconf execution failed. | ||
14 | |||
15 | The upstream status is marked as 'Inappropriate' because this problem is not uncommon, | ||
16 | it has been there for a long time and no change in upstream. | ||
17 | |||
18 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
19 | |||
20 | Index: grub-0.97/stage1/Makefile.am | ||
21 | =================================================================== | ||
22 | --- a/stage1/Makefile.am | ||
23 | +++ b/stage1/Makefile.am | ||
24 | @@ -1,7 +1,7 @@ | ||
25 | -pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) | ||
26 | -nodist_pkglib_DATA = stage1 | ||
27 | +pkgdatadir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) | ||
28 | +nodist_pkgdata_DATA = stage1 | ||
29 | |||
30 | -CLEANFILES = $(nodist_pkglib_DATA) | ||
31 | +CLEANFILES = $(nodist_pkgdata_DATA) | ||
32 | |||
33 | # We can't use builtins or standard includes. | ||
34 | AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc | ||
35 | Index: grub-0.97/stage2/Makefile.am | ||
36 | =================================================================== | ||
37 | --- a/stage2/Makefile.am | ||
38 | +++ b/stage2/Makefile.am | ||
39 | @@ -27,12 +27,12 @@ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ | ||
40 | -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 | ||
41 | |||
42 | # Stage 2 and Stage 1.5's. | ||
43 | -pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) | ||
44 | +pkgdatadir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) | ||
45 | |||
46 | EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec | ||
47 | |||
48 | if DISKLESS_SUPPORT | ||
49 | -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ | ||
50 | +pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ | ||
51 | ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \ | ||
52 | reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \ | ||
53 | nbgrub pxegrub | ||
54 | @@ -43,7 +43,7 @@ noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \ | ||
55 | reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \ | ||
56 | xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec | ||
57 | else | ||
58 | -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ | ||
59 | +pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ | ||
60 | ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \ | ||
61 | reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 | ||
62 | noinst_DATA = pre_stage2 start start_eltorito | ||
63 | @@ -105,7 +105,7 @@ else | ||
64 | BUILT_SOURCES = stage2_size.h | ||
65 | endif | ||
66 | |||
67 | -CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES) | ||
68 | +CLEANFILES = $(pkgdata_DATA) $(noinst_DATA) $(BUILT_SOURCES) | ||
69 | |||
70 | stage2_size.h: pre_stage2 | ||
71 | -rm -f stage2_size.h | ||
72 | -- | ||
73 | 1.7.9.5 | ||
74 | |||
diff --git a/meta/recipes-bsp/grub/grub-0.97/no-reorder-functions.patch b/meta/recipes-bsp/grub/grub-0.97/no-reorder-functions.patch deleted file mode 100644 index 70037e4..0000000 --- a/meta/recipes-bsp/grub/grub-0.97/no-reorder-functions.patch +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [disable feature] | ||
2 | |||
3 | After the commit "tcmode-default: switch to gcc 4.6.0 for x86, x86-64 & arm", | ||
4 | we got bug 1099 (http://bugzilla.yoctoproject.org/show_bug.cgi?id=1099): | ||
5 | |||
6 | Running "install --stage2=/ssd/boot/grub/stage2 /boot/grub/stage1(hd0) | ||
7 | /boot/grub/stage2 p /boot/grub/menu list" failed | ||
8 | Error 6: Mismatched or corrupt version of stage1/stage2 | ||
9 | |||
10 | This turned out to be a gcc's bug. See | ||
11 | https://bugs.gentoo.org/show_bug.cgi?id=360513 | ||
12 | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39333 | ||
13 | |||
14 | Upstream gcc seems uninterested in the bug, so at present we can disable the | ||
15 | option as a workaround. Thanks Ryan Hill for the investigation and the | ||
16 | workaround patch. | ||
17 | |||
18 | Dexuan Cui <dexuan.cui@intel.com> | ||
19 | Wed Jun 29 20:21:39 CST 2011 | ||
20 | |||
21 | --- grub-0.97/stage2/Makefile.am.orig | ||
22 | +++ grub-0.97/stage2/Makefile.am | ||
23 | @@ -79,7 +79,7 @@ | ||
24 | HERCULES_FLAGS = | ||
25 | endif | ||
26 | |||
27 | -STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ | ||
28 | +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-reorder-functions -fno-builtin -nostdinc \ | ||
29 | $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) | ||
30 | |||
31 | STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 | ||
diff --git a/meta/recipes-bsp/grub/grub-0.97/objcopy-absolute.patch b/meta/recipes-bsp/grub/grub-0.97/objcopy-absolute.patch deleted file mode 100644 index bd8e0a8..0000000 --- a/meta/recipes-bsp/grub/grub-0.97/objcopy-absolute.patch +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | |||
2 | This patch is from ubuntu: | ||
3 | * objcopy-absolute.diff (update): Remove .note, .comment, and | ||
4 | .note.gnu.build-id sections from images (LP: #444703). | ||
5 | |||
6 | Upstream-Status: Inappropriate [no longer maintained] | ||
7 | |||
8 | Index: b/acinclude.m4 | ||
9 | =================================================================== | ||
10 | --- a/acinclude.m4 | ||
11 | +++ b/acinclude.m4 | ||
12 | @@ -61,7 +61,7 @@ | ||
13 | else | ||
14 | AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) | ||
15 | fi | ||
16 | - if AC_TRY_COMMAND([${OBJCOPY-objcopy} -O binary conftest.exec conftest]); then : | ||
17 | + if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : | ||
18 | else | ||
19 | AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files]) | ||
20 | fi | ||
21 | Index: b/stage1/Makefile.am | ||
22 | =================================================================== | ||
23 | --- a/stage1/Makefile.am | ||
24 | +++ b/stage1/Makefile.am | ||
25 | @@ -12,4 +12,4 @@ | ||
26 | |||
27 | SUFFIXES = .exec | ||
28 | .exec: | ||
29 | - $(OBJCOPY) -O binary $< $@ | ||
30 | + $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@ | ||
31 | Index: b/stage2/Makefile.am | ||
32 | =================================================================== | ||
33 | --- a/stage2/Makefile.am | ||
34 | +++ b/stage2/Makefile.am | ||
35 | @@ -293,4 +293,4 @@ | ||
36 | # General rule for making a raw binary. | ||
37 | SUFFIXES = .exec | ||
38 | .exec: | ||
39 | - $(OBJCOPY) -O binary $< $@ | ||
40 | + $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@ | ||
diff --git a/meta/recipes-bsp/grub/grub_0.97.bb b/meta/recipes-bsp/grub/grub_0.97.bb deleted file mode 100644 index 997a045..0000000 --- a/meta/recipes-bsp/grub/grub_0.97.bb +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | SUMMARY = "GRUB is the GRand Unified Bootloader" | ||
2 | DESCRIPTION = "GRUB is a GPLed bootloader intended to unify bootloading across x86 \ | ||
3 | operating systems. In addition to loading the Linux kernel, it implements the Multiboot \ | ||
4 | standard, which allows for flexible loading of multiple boot images." | ||
5 | HOMEPAGE = "http://www.gnu.org/software/grub/" | ||
6 | SECTION = "bootloaders" | ||
7 | |||
8 | LICENSE = "GPLv2+" | ||
9 | LIC_FILES_CHKSUM = "file://COPYING;md5=c93c0550bd3173f4504b2cbd8991e50b \ | ||
10 | file://grub/main.c;beginline=3;endline=9;md5=22a5f28d2130fff9f2a17ed54be90ed6" | ||
11 | |||
12 | RDEPENDS_${PN} = "diffutils" | ||
13 | PR = "r6" | ||
14 | |||
15 | SRC_URI = "ftp://alpha.gnu.org/gnu/grub/grub-${PV}.tar.gz; \ | ||
16 | file://no-reorder-functions.patch \ | ||
17 | file://autohell.patch \ | ||
18 | file://grub_fix_for_automake-1.12.patch \ | ||
19 | file://objcopy-absolute.patch \ | ||
20 | file://grub-support-256byte-inode.patch \ | ||
21 | " | ||
22 | |||
23 | SRC_URI[md5sum] = "cd3f3eb54446be6003156158d51f4884" | ||
24 | SRC_URI[sha256sum] = "4e1d15d12dbd3e9208111d6b806ad5a9857ca8850c47877d36575b904559260b" | ||
25 | |||
26 | inherit autotools texinfo | ||
27 | |||
28 | COMPATIBLE_HOST = "i.86.*-linux" | ||
29 | |||
30 | EXTRA_OECONF = "--without-curses" | ||
31 | |||
32 | do_install_append_vmware() { | ||
33 | mkdir -p ${D}/boot/ | ||
34 | ln -sf ../usr/lib/grub/{$TARGET_ARCH}{$TARGET_VENDOR}/ ${D}/boot/grub | ||
35 | } | ||
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 deleted file mode 100644 index 5452b46..0000000 --- a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-6.9-cp-i-u.patch +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [legacy version] | ||
2 | |||
3 | This patch was imported from the Fedora Core 8 coreutils-6.9-9 package. | ||
4 | |||
5 | The package is stated as being Licensed as GPLv2+. | ||
6 | |||
7 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> | ||
8 | |||
9 | ---- | ||
10 | |||
11 | When "cp -i --update old new" would do nothing because "new" is | ||
12 | newer than "old", cp would nonetheless prompt for whether it is | ||
13 | ok to overwrite "new". Then, regardless of the response (because | ||
14 | of the --update option), cp would do nothing. | ||
15 | |||
16 | The following patch eliminates the unnecessary prompt in that case. | ||
17 | |||
18 | diff --git a/src/copy.c b/src/copy.c | ||
19 | index b7bf73b..0e549d2 100644 | ||
20 | --- a/src/copy.c | ||
21 | +++ b/src/copy.c | ||
22 | @@ -1210,6 +1210,30 @@ copy_internal (char const *src_name, char const *dst_name, | ||
23 | return false; | ||
24 | } | ||
25 | |||
26 | + if (!S_ISDIR (src_mode) && x->update) | ||
27 | + { | ||
28 | + /* When preserving time stamps (but not moving within a file | ||
29 | + system), don't worry if the destination time stamp is | ||
30 | + less than the source merely because of time stamp | ||
31 | + truncation. */ | ||
32 | + int options = ((x->preserve_timestamps | ||
33 | + && ! (x->move_mode | ||
34 | + && dst_sb.st_dev == src_sb.st_dev)) | ||
35 | + ? UTIMECMP_TRUNCATE_SOURCE | ||
36 | + : 0); | ||
37 | + | ||
38 | + if (0 <= utimecmp (dst_name, &dst_sb, &src_sb, options)) | ||
39 | + { | ||
40 | + /* We're using --update and the destination is not older | ||
41 | + than the source, so do not copy or move. Pretend the | ||
42 | + rename succeeded, so the caller (if it's mv) doesn't | ||
43 | + end up removing the source file. */ | ||
44 | + if (rename_succeeded) | ||
45 | + *rename_succeeded = true; | ||
46 | + return true; | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | /* When there is an existing destination file, we may end up | ||
51 | returning early, and hence not copying/moving the file. | ||
52 | This may be due to an interactive `negative' reply to the | ||
53 | @@ -1302,30 +1326,6 @@ copy_internal (char const *src_name, char const *dst_name, | ||
54 | return false; | ||
55 | } | ||
56 | } | ||
57 | - | ||
58 | - if (x->update) | ||
59 | - { | ||
60 | - /* When preserving time stamps (but not moving within a file | ||
61 | - system), don't worry if the destination time stamp is | ||
62 | - less than the source merely because of time stamp | ||
63 | - truncation. */ | ||
64 | - int options = ((x->preserve_timestamps | ||
65 | - && ! (x->move_mode | ||
66 | - && dst_sb.st_dev == src_sb.st_dev)) | ||
67 | - ? UTIMECMP_TRUNCATE_SOURCE | ||
68 | - : 0); | ||
69 | - | ||
70 | - if (0 <= utimecmp (dst_name, &dst_sb, &src_sb, options)) | ||
71 | - { | ||
72 | - /* We're using --update and the destination is not older | ||
73 | - than the source, so do not copy or move. Pretend the | ||
74 | - rename succeeded, so the caller (if it's mv) doesn't | ||
75 | - end up removing the source file. */ | ||
76 | - if (rename_succeeded) | ||
77 | - *rename_succeeded = true; | ||
78 | - return true; | ||
79 | - } | ||
80 | - } | ||
81 | } | ||
82 | |||
83 | if (x->move_mode) | ||
84 | diff --git a/tests/mv/update b/tests/mv/update | ||
85 | index 0c06024..6c3d149 100755 | ||
86 | --- a/tests/mv/update | ||
87 | +++ b/tests/mv/update | ||
88 | @@ -1,7 +1,7 @@ | ||
89 | #!/bin/sh | ||
90 | # make sure --update works as advertised | ||
91 | |||
92 | -# Copyright (C) 2001, 2004, 2006 Free Software Foundation, Inc. | ||
93 | +# Copyright (C) 2001, 2004, 2006-2007 Free Software Foundation, Inc. | ||
94 | |||
95 | # This program is free software; you can redistribute it and/or modify | ||
96 | # it under the terms of the GNU General Public License as published by | ||
97 | @@ -46,11 +46,16 @@ fi | ||
98 | |||
99 | fail=0 | ||
100 | |||
101 | -for cp_or_mv in cp mv; do | ||
102 | - # This is a no-op. | ||
103 | - $cp_or_mv --update old new || fail=1 | ||
104 | - case "`cat new`" in new) ;; *) fail=1 ;; esac | ||
105 | - case "`cat old`" in old) ;; *) fail=1 ;; esac | ||
106 | +for interactive in '' -i; do | ||
107 | + for cp_or_mv in cp mv; do | ||
108 | + # This is a no-op, with no prompt. | ||
109 | + # With coreutils-6.9 and earlier, using --update with -i would | ||
110 | + # mistakenly elicit a prompt. | ||
111 | + $cp_or_mv $interactive --update old new < /dev/null > out 2>&1 || fail=1 | ||
112 | + test -s out && fail=1 | ||
113 | + case "`cat new`" in new) ;; *) fail=1 ;; esac | ||
114 | + case "`cat old`" in old) ;; *) fail=1 ;; esac | ||
115 | + done | ||
116 | done | ||
117 | |||
118 | # This will actually perform the rename. | ||
119 | -- | ||
120 | 1.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 deleted file mode 100644 index 88f61fa..0000000 --- a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-install.patch +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [legacy version] | ||
2 | |||
3 | The install command doesn't over write the dangling symlink, for | ||
4 | example: | ||
5 | |||
6 | $ install fileA /tmp/fileA | ||
7 | |||
8 | If /tmp/fileA is a dangling symlink, there would be an error: | ||
9 | |||
10 | install: cannot create regular file '/tmp/fileA': File exists | ||
11 | |||
12 | This is because of the following code in copy.c: | ||
13 | |||
14 | if (!new_dst) | ||
15 | { | ||
16 | if (XSTAT (x, dst_name, &dst_sb) != 0) | ||
17 | { | ||
18 | if (errno != ENOENT) | ||
19 | { | ||
20 | error (0, errno, _("cannot stat %s"), quote (dst_name)); | ||
21 | return false; | ||
22 | } | ||
23 | else | ||
24 | { | ||
25 | new_dst = true; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | XSTAT() use stat() for dst_name(the dangling symlink /tmp/fileA) when | ||
30 | install.c invokes it, and stat will set errno to ENOENT, and then | ||
31 | new_dst will be set to true which means that /tmp/fileA doesn't exist, | ||
32 | then we will create /tmp/fileA without remove it first, so the error | ||
33 | comes. | ||
34 | |||
35 | This is fixed in a way which adds the member cmd_install in | ||
36 | struct cp_options to make sure my change only affected to the install | ||
37 | command and use lstat to fix the problem. | ||
38 | |||
39 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
40 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> | ||
41 | |||
42 | --- | ||
43 | src/copy.c | 10 +++++++++- | ||
44 | src/copy.h | 3 +++ | ||
45 | src/install.c | 1 + | ||
46 | 3 files changed, 13 insertions(+), 1 deletions(-) | ||
47 | |||
48 | diff --git a/src/copy.c b/src/copy.c | ||
49 | --- a/src/copy.c | ||
50 | +++ b/src/copy.c | ||
51 | @@ -1029,6 +1029,7 @@ copy_internal (char const *src_name, char const *dst_name, | ||
52 | bool delayed_ok; | ||
53 | bool copied_as_regular = false; | ||
54 | bool preserve_metadata; | ||
55 | + int dst_stat_result; | ||
56 | |||
57 | if (x->move_mode && rename_succeeded) | ||
58 | *rename_succeeded = false; | ||
59 | @@ -1069,7 +1070,14 @@ copy_internal (char const *src_name, char const *dst_name, | ||
60 | |||
61 | if (!new_dst) | ||
62 | { | ||
63 | - if (XSTAT (x, dst_name, &dst_sb) != 0) | ||
64 | + if ( x->cmd_install && ( x->backup_type == no_backups)) | ||
65 | + dst_stat_result = lstat (dst_name, &dst_sb); | ||
66 | + else | ||
67 | + { | ||
68 | + dst_stat_result = XSTAT (x, dst_name, &dst_sb); | ||
69 | + } | ||
70 | + | ||
71 | + if (dst_stat_result != 0) | ||
72 | { | ||
73 | if (errno != ENOENT) | ||
74 | { | ||
75 | diff --git a/src/copy.h b/src/copy.h | ||
76 | --- a/src/copy.h | ||
77 | +++ b/src/copy.h | ||
78 | @@ -114,6 +114,9 @@ struct cp_options | ||
79 | If that fails, then resort to copying. */ | ||
80 | bool move_mode; | ||
81 | |||
82 | + /* For the install command */ | ||
83 | + bool cmd_install; | ||
84 | + | ||
85 | /* Whether this process has appropriate privileges to chown a file | ||
86 | whose owner is not the effective user ID. */ | ||
87 | bool chown_privileges; | ||
88 | diff --git a/src/install.c b/src/install.c | ||
89 | --- a/src/install.c | ||
90 | +++ b/src/install.c | ||
91 | @@ -149,6 +149,7 @@ cp_option_init (struct cp_options *x) | ||
92 | x->hard_link = false; | ||
93 | x->interactive = I_UNSPECIFIED; | ||
94 | x->move_mode = false; | ||
95 | + x->cmd_install = true; | ||
96 | x->chown_privileges = chown_privileges (); | ||
97 | x->one_file_system = false; | ||
98 | x->preserve_ownership = false; | ||
99 | -- | ||
100 | 1.7.0.1 | ||
101 | |||
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-texinfo.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-texinfo.patch deleted file mode 100644 index 3ae5a2f..0000000 --- a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-fix-texinfo.patch +++ /dev/null | |||
@@ -1,375 +0,0 @@ | |||
1 | From 170be4023bbf9e9698a709e03265945588ac8e01 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Tue, 26 Nov 2013 00:21:50 +0800 | ||
4 | Subject: [PATCH] doc/coreutils.texi: Use '@item' instead of '@itemx' | ||
5 | |||
6 | Use '@item' instead of '@itemx' in several places, as Texinfo 5 refuses | ||
7 | to process an '@itemx' that is not preceded by an '@item'. Ensure that | ||
8 | node extended names in menus and sectioning are consistent, and that | ||
9 | ordering and presence of nodes in menus and in the actual text are | ||
10 | consistent as well. | ||
11 | |||
12 | Upstream-Status: Backport [From: coreutils.7620.n7.nabble.com, bug#11828] | ||
13 | |||
14 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
15 | --- | ||
16 | doc/coreutils.texi | 82 +++++++++++++++++++++++++++--------------------------- | ||
17 | 1 file changed, 41 insertions(+), 41 deletions(-) | ||
18 | |||
19 | diff --git a/doc/coreutils.texi b/doc/coreutils.texi | ||
20 | index 588147f..2dae3fe 100644 | ||
21 | --- a/doc/coreutils.texi | ||
22 | +++ b/doc/coreutils.texi | ||
23 | @@ -555,7 +555,7 @@ symbolic link to a directory. @xref{Target directory}. | ||
24 | @end macro | ||
25 | |||
26 | @macro optSi | ||
27 | -@itemx --si | ||
28 | +@item --si | ||
29 | @opindex --si | ||
30 | @cindex SI output | ||
31 | Append an SI-style abbreviation to each size, such as @samp{M} for | ||
32 | @@ -578,7 +578,7 @@ Use the @option{--si} option if you prefer powers of 1000. | ||
33 | @end macro | ||
34 | |||
35 | @macro optStripTrailingSlashes | ||
36 | -@itemx @w{@kbd{--strip-trailing-slashes}} | ||
37 | +@item @w{@kbd{--strip-trailing-slashes}} | ||
38 | @opindex --strip-trailing-slashes | ||
39 | @cindex stripping trailing slashes | ||
40 | Remove any trailing slashes from each @var{source} argument. | ||
41 | @@ -2496,7 +2496,7 @@ by 1048576. | ||
42 | However, if @var{n} starts with a @samp{-}, | ||
43 | print all but the last @var{n} bytes of each file. | ||
44 | |||
45 | -@itemx -n @var{n} | ||
46 | +@item -n @var{n} | ||
47 | @itemx --lines=@var{n} | ||
48 | @opindex -n | ||
49 | @opindex --lines | ||
50 | @@ -2633,7 +2633,7 @@ This option is the same as @option{--follow=name --retry}. That is, tail | ||
51 | will attempt to reopen a file when it is removed. Should this fail, tail | ||
52 | will keep trying until it becomes accessible again. | ||
53 | |||
54 | -@itemx --retry | ||
55 | +@item --retry | ||
56 | @opindex --retry | ||
57 | This option is useful mainly when following by name (i.e., with | ||
58 | @option{--follow=name}). | ||
59 | @@ -2641,7 +2641,7 @@ Without this option, when tail encounters a file that doesn't | ||
60 | exist or is otherwise inaccessible, it reports that fact and | ||
61 | never checks it again. | ||
62 | |||
63 | -@itemx --sleep-interval=@var{number} | ||
64 | +@item --sleep-interval=@var{number} | ||
65 | @opindex --sleep-interval | ||
66 | Change the number of seconds to wait between iterations (the default is 1.0). | ||
67 | During one iteration, every specified file is checked to see if it has | ||
68 | @@ -2651,7 +2651,7 @@ Historical implementations of @command{tail} have required that | ||
69 | an arbitrary floating point number (using a period before any | ||
70 | fractional digits). | ||
71 | |||
72 | -@itemx --pid=@var{pid} | ||
73 | +@item --pid=@var{pid} | ||
74 | @opindex --pid | ||
75 | When following by name or by descriptor, you may specify the process ID, | ||
76 | @var{pid}, of the sole writer of all @var{file} arguments. Then, shortly | ||
77 | @@ -2674,7 +2674,7 @@ terminate until long after the real writer has terminated. | ||
78 | Note that @option{--pid} cannot be supported on some systems; @command{tail} | ||
79 | will print a warning if this is the case. | ||
80 | |||
81 | -@itemx --max-unchanged-stats=@var{n} | ||
82 | +@item --max-unchanged-stats=@var{n} | ||
83 | @opindex --max-unchanged-stats | ||
84 | When tailing a file by name, if there have been @var{n} (default | ||
85 | n=@value{DEFAULT_MAX_N_UNCHANGED_STATS_BETWEEN_OPENS}) consecutive | ||
86 | @@ -2686,7 +2686,7 @@ number of seconds between when tail prints the last pre-rotation lines | ||
87 | and when it prints the lines that have accumulated in the new log file. | ||
88 | This option is meaningful only when following by name. | ||
89 | |||
90 | -@itemx -n @var{n} | ||
91 | +@item -n @var{n} | ||
92 | @itemx --lines=@var{n} | ||
93 | @opindex -n | ||
94 | @opindex --lines | ||
95 | @@ -2817,7 +2817,7 @@ option. | ||
96 | @opindex --numeric-suffixes | ||
97 | Use digits in suffixes rather than lower-case letters. | ||
98 | |||
99 | -@itemx --verbose | ||
100 | +@item --verbose | ||
101 | @opindex --verbose | ||
102 | Write a diagnostic to standard error just before each output file is opened. | ||
103 | |||
104 | @@ -3055,7 +3055,7 @@ Print only the newline counts. | ||
105 | @opindex --max-line-length | ||
106 | Print only the maximum line lengths. | ||
107 | |||
108 | -@itemx --files0-from=@var{FILE} | ||
109 | +@item --files0-from=@var{FILE} | ||
110 | @opindex --files0-from=@var{FILE} | ||
111 | @cindex including files from @command{du} | ||
112 | Rather than processing files named on the command line, process those | ||
113 | @@ -3250,7 +3250,7 @@ an MD5 checksum inconsistent with the associated file, or if no valid | ||
114 | line is found, @command{md5sum} exits with nonzero status. Otherwise, | ||
115 | it exits successfully. | ||
116 | |||
117 | -@itemx --status | ||
118 | +@item --status | ||
119 | @opindex --status | ||
120 | @cindex verifying MD5 checksums | ||
121 | This option is useful only when verifying checksums. | ||
122 | @@ -5837,7 +5837,7 @@ command line unless the @option{--dereference-command-line} (@option{-H}), | ||
123 | If a command line argument specifies a symbolic link, show information | ||
124 | for the file the link references rather than for the link itself. | ||
125 | |||
126 | -@itemx --dereference-command-line-symlink-to-dir | ||
127 | +@item --dereference-command-line-symlink-to-dir | ||
128 | @opindex --dereference-command-line-symlink-to-dir | ||
129 | @cindex symbolic links, dereferencing | ||
130 | Do not dereference symbolic links, with one exception: | ||
131 | @@ -7015,15 +7015,15 @@ If specified, the @var{attribute_list} must be a comma-separated list | ||
132 | of one or more of the following strings: | ||
133 | |||
134 | @table @samp | ||
135 | -@itemx mode | ||
136 | +@item mode | ||
137 | Preserve the file mode bits and access control lists. | ||
138 | -@itemx ownership | ||
139 | +@item ownership | ||
140 | Preserve the owner and group. On most modern systems, | ||
141 | only users with appropriate privileges may change the owner of a file, | ||
142 | and ordinary users | ||
143 | may preserve the group ownership of a file only if they happen to be | ||
144 | a member of the desired group. | ||
145 | -@itemx timestamps | ||
146 | +@item timestamps | ||
147 | Preserve the times of last access and last modification, when possible. | ||
148 | In general, it is not possible to preserve these attributes | ||
149 | when the affected file is a symbolic link. | ||
150 | @@ -7031,12 +7031,12 @@ However, FreeBSD now provides the @code{lutimes} function, which makes | ||
151 | it possibile even for symbolic links. However, this implementation does | ||
152 | not yet take advantage of that. | ||
153 | @c FIXME: once we provide lutimes support, update the above. | ||
154 | -@itemx links | ||
155 | +@item links | ||
156 | Preserve in the destination files | ||
157 | any links between corresponding source files. | ||
158 | @c Give examples illustrating how hard links are preserved. | ||
159 | @c Also, show how soft links map to hard links with -L and -H. | ||
160 | -@itemx all | ||
161 | +@item all | ||
162 | Preserve all file attributes. | ||
163 | Equivalent to specifying all of the above. | ||
164 | @end table | ||
165 | @@ -7049,12 +7049,12 @@ mode bits of the corresponding source file, minus the bits set in the | ||
166 | umask and minus the set-user-ID and set-group-ID bits. | ||
167 | @xref{File permissions}. | ||
168 | |||
169 | -@itemx @w{@kbd{--no-preserve}=@var{attribute_list}} | ||
170 | +@item @w{@kbd{--no-preserve}=@var{attribute_list}} | ||
171 | @cindex file information, preserving | ||
172 | Do not preserve the specified attributes. The @var{attribute_list} | ||
173 | has the same form as for @option{--preserve}. | ||
174 | |||
175 | -@itemx --parents | ||
176 | +@item --parents | ||
177 | @opindex --parents | ||
178 | @cindex parent directories and @command{cp} | ||
179 | Form the name of each destination file by appending to the target | ||
180 | @@ -7070,7 +7070,7 @@ cp --parents a/b/c existing_dir | ||
181 | copies the file @file{a/b/c} to @file{existing_dir/a/b/c}, creating | ||
182 | any missing intermediate directories. | ||
183 | |||
184 | -@itemx @w{@kbd{--reply}=@var{how}} | ||
185 | +@item @w{@kbd{--reply}=@var{how}} | ||
186 | @opindex --reply | ||
187 | @cindex interactivity | ||
188 | @c FIXME: remove in 2008 | ||
189 | @@ -7742,7 +7742,7 @@ Prompt whether to overwrite each existing destination file, regardless | ||
190 | of its permissions. | ||
191 | If the response is not affirmative, the file is skipped. | ||
192 | |||
193 | -@itemx @w{@kbd{--reply}=@var{how}} | ||
194 | +@item @w{@kbd{--reply}=@var{how}} | ||
195 | @opindex --reply | ||
196 | @cindex interactivity | ||
197 | @c FIXME: remove in 2008 | ||
198 | @@ -7847,7 +7847,7 @@ files are named or if a recursive removal is requested. Ignore any | ||
199 | previous @option{--force} (@option{-f}) option. Equivalent to | ||
200 | @option{--interactive=once}. | ||
201 | |||
202 | -@itemx --interactive [=@var{when}] | ||
203 | +@item --interactive [=@var{when}] | ||
204 | @opindex --interactive | ||
205 | Specify when to issue an interactive prompt. @var{when} may be | ||
206 | omitted, or one of: | ||
207 | @@ -7866,7 +7866,7 @@ removal is requested. Equivalent to @option{-I}. | ||
208 | Specifying @option{--interactive} and no @var{when} is equivalent to | ||
209 | @option{--interactive=always}. | ||
210 | |||
211 | -@itemx --one-file-system | ||
212 | +@item --one-file-system | ||
213 | @opindex --one-file-system | ||
214 | @cindex one file system, restricting @command{rm} to | ||
215 | When removing a hierarchy recursively, skip any directory that is on a | ||
216 | @@ -7884,7 +7884,7 @@ warn about and skip directories on other file systems. | ||
217 | Of course, this will not save your @file{/home} if it and your | ||
218 | chroot happen to be on the same file system. | ||
219 | |||
220 | -@itemx --preserve-root | ||
221 | +@item --preserve-root | ||
222 | @opindex --preserve-root | ||
223 | @cindex root directory, disallow recursive destruction | ||
224 | Fail upon any attempt to remove the root directory, @file{/}, | ||
225 | @@ -7892,7 +7892,7 @@ when used with the @option{--recursive} option. | ||
226 | This is the default behavior. | ||
227 | @xref{Treating / specially}. | ||
228 | |||
229 | -@itemx --no-preserve-root | ||
230 | +@item --no-preserve-root | ||
231 | @opindex --no-preserve-root | ||
232 | @cindex root directory, allow recursive destruction | ||
233 | Do not treat @file{/} specially when removing recursively. | ||
234 | @@ -8874,7 +8874,7 @@ actually changes. | ||
235 | Do not print error messages about files whose ownership cannot be | ||
236 | changed. | ||
237 | |||
238 | -@itemx @w{@kbd{--from}=@var{old-owner}} | ||
239 | +@item @w{@kbd{--from}=@var{old-owner}} | ||
240 | @opindex --from | ||
241 | @cindex symbolic links, changing owner | ||
242 | Change a @var{file}'s ownership only if it has current attributes specified | ||
243 | @@ -8928,14 +8928,14 @@ is a symbolic link. | ||
244 | By default, no diagnostic is issued for symbolic links encountered | ||
245 | during a recursive traversal, but see @option{--verbose}. | ||
246 | |||
247 | -@itemx --preserve-root | ||
248 | +@item --preserve-root | ||
249 | @opindex --preserve-root | ||
250 | @cindex root directory, disallow recursive modification | ||
251 | Fail upon any attempt to recursively change the root directory, @file{/}. | ||
252 | Without @option{--recursive}, this option has no effect. | ||
253 | @xref{Treating / specially}. | ||
254 | |||
255 | -@itemx --no-preserve-root | ||
256 | +@item --no-preserve-root | ||
257 | @opindex --no-preserve-root | ||
258 | @cindex root directory, allow recursive modification | ||
259 | Cancel the effect of any preceding @option{--preserve-root} option. | ||
260 | @@ -9054,14 +9054,14 @@ is a symbolic link. | ||
261 | By default, no diagnostic is issued for symbolic links encountered | ||
262 | during a recursive traversal, but see @option{--verbose}. | ||
263 | |||
264 | -@itemx --preserve-root | ||
265 | +@item --preserve-root | ||
266 | @opindex --preserve-root | ||
267 | @cindex root directory, disallow recursive modification | ||
268 | Fail upon any attempt to recursively change the root directory, @file{/}. | ||
269 | Without @option{--recursive}, this option has no effect. | ||
270 | @xref{Treating / specially}. | ||
271 | |||
272 | -@itemx --no-preserve-root | ||
273 | +@item --no-preserve-root | ||
274 | @opindex --no-preserve-root | ||
275 | @cindex root directory, allow recursive modification | ||
276 | Cancel the effect of any preceding @option{--preserve-root} option. | ||
277 | @@ -9175,14 +9175,14 @@ actually changes. | ||
278 | Do not print error messages about files whose permissions cannot be | ||
279 | changed. | ||
280 | |||
281 | -@itemx --preserve-root | ||
282 | +@item --preserve-root | ||
283 | @opindex --preserve-root | ||
284 | @cindex root directory, disallow recursive modification | ||
285 | Fail upon any attempt to recursively change the root directory, @file{/}. | ||
286 | Without @option{--recursive}, this option has no effect. | ||
287 | @xref{Treating / specially}. | ||
288 | |||
289 | -@itemx --no-preserve-root | ||
290 | +@item --no-preserve-root | ||
291 | @opindex --no-preserve-root | ||
292 | @cindex root directory, allow recursive modification | ||
293 | Cancel the effect of any preceding @option{--preserve-root} option. | ||
294 | @@ -9603,7 +9603,7 @@ The program accepts the following options. Also see @ref{Common options}. | ||
295 | @opindex --all | ||
296 | Show counts for all files, not just directories. | ||
297 | |||
298 | -@itemx --apparent-size | ||
299 | +@item --apparent-size | ||
300 | @opindex --apparent-size | ||
301 | Print apparent sizes, rather than disk usage. The apparent size of a | ||
302 | file is the number of bytes reported by @code{wc -c} on regular files, | ||
303 | @@ -9654,7 +9654,7 @@ Does not affect other symbolic links. This is helpful for finding | ||
304 | out the disk usage of directories, such as @file{/usr/tmp}, which | ||
305 | are often symbolic links. | ||
306 | |||
307 | -@itemx --files0-from=@var{FILE} | ||
308 | +@item --files0-from=@var{FILE} | ||
309 | @opindex --files0-from=@var{FILE} | ||
310 | @cindex including files from @command{du} | ||
311 | Rather than processing files named on the command line, process those | ||
312 | @@ -9733,7 +9733,7 @@ Output a null byte at the end of each line, rather than a newline. | ||
313 | This option enables other programs to parse the output of @command{du} | ||
314 | even when that output would contain file names with embedded newlines. | ||
315 | |||
316 | -@itemx --si | ||
317 | +@item --si | ||
318 | @opindex --si | ||
319 | @cindex SI output | ||
320 | Append an SI-style abbreviation to each size, such as @samp{MB} for | ||
321 | @@ -9754,13 +9754,13 @@ Display only a total for each argument. | ||
322 | Report the size of each directory separately, not including the sizes | ||
323 | of subdirectories. | ||
324 | |||
325 | -@itemx --time | ||
326 | +@item --time | ||
327 | @opindex --time | ||
328 | @cindex last modified dates, displaying in @command{du} | ||
329 | Show time of the most recent modification of any file in the directory, | ||
330 | or any of its subdirectories. | ||
331 | |||
332 | -@itemx --time=ctime | ||
333 | +@item --time=ctime | ||
334 | @itemx --time=status | ||
335 | @itemx --time=use | ||
336 | @opindex --time | ||
337 | @@ -9770,7 +9770,7 @@ or any of its subdirectories. | ||
338 | Show the most recent status change time (the @samp{ctime} in the inode) of | ||
339 | any file in the directory, instead of the modification time. | ||
340 | |||
341 | -@itemx --time=atime | ||
342 | +@item --time=atime | ||
343 | @itemx --time=access | ||
344 | @opindex --time | ||
345 | @opindex atime@r{, show the most recent} | ||
346 | @@ -9911,7 +9911,7 @@ $ stat --format=%d:%i / /usr | ||
347 | 2057:2 | ||
348 | @end example | ||
349 | |||
350 | -@itemx --printf=@var{format} | ||
351 | +@item --printf=@var{format} | ||
352 | @opindex --printf=@var{format} | ||
353 | @cindex output format | ||
354 | Use @var{format} rather than the default format. | ||
355 | @@ -12240,7 +12240,7 @@ Overrides all other options. | ||
356 | @opindex -s | ||
357 | Ignored; for compatibility with other versions of @command{who}. | ||
358 | |||
359 | -@itemx -u | ||
360 | +@item -u | ||
361 | @opindex -u | ||
362 | @cindex idle time | ||
363 | After the login time, print the number of hours and minutes that the | ||
364 | @@ -12254,7 +12254,7 @@ user has been idle. @samp{.} means the user was active in the last minute. | ||
365 | List only the entries that correspond to processes via which the | ||
366 | system is waiting for a user to login. The user name is always @samp{LOGIN}. | ||
367 | |||
368 | -@itemx --lookup | ||
369 | +@item --lookup | ||
370 | @opindex --lookup | ||
371 | Attempt to canonicalize hostnames found in utmp through a DNS lookup. This | ||
372 | is not the default because it can cause significant delays on systems with | ||
373 | -- | ||
374 | 1.8.3.1 | ||
375 | |||
diff --git a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch b/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch deleted file mode 100644 index 6537223..0000000 --- a/meta/recipes-core/coreutils/coreutils-6.9/coreutils-i18n.patch +++ /dev/null | |||
@@ -1,4051 +0,0 @@ | |||
1 | Upstream-Status: Inappropriate [legacy version] | ||
2 | |||
3 | This patch was imported from the Fedora Core 8 coreutils-6.9-9 package. | ||
4 | |||
5 | The package is stated as being Licensed as GPLv2+. | ||
6 | |||
7 | The comment indicates that the purpose is lin18nux/lsb compliance. | ||
8 | |||
9 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> | ||
10 | |||
11 | --- /dev/null 2007-03-01 09:16:39.219409909 +0000 | ||
12 | +++ coreutils-6.8+/tests/sort/sort-mb-tests 2007-03-01 15:08:24.000000000 +0000 | ||
13 | @@ -0,0 +1,58 @@ | ||
14 | +#! /bin/sh | ||
15 | +case $# in | ||
16 | + 0) xx='../../src/sort';; | ||
17 | + *) xx="$1";; | ||
18 | +esac | ||
19 | +test "$VERBOSE" && echo=echo || echo=: | ||
20 | +$echo testing program: $xx | ||
21 | +errors=0 | ||
22 | +test "$srcdir" || srcdir=. | ||
23 | +test "$VERBOSE" && $xx --version 2> /dev/null | ||
24 | + | ||
25 | +export LC_ALL=en_US.UTF-8 | ||
26 | +locale -k LC_CTYPE 2>&1 | grep -q charmap.*UTF-8 || exit 77 | ||
27 | +errors=0 | ||
28 | + | ||
29 | +$xx -t ï¼ -k2 -n mb1.I > mb1.O | ||
30 | +code=$? | ||
31 | +if test $code != 0; then | ||
32 | + $echo "Test mb1 failed: $xx return code $code differs from expected value 0" 1>&2 | ||
33 | + errors=`expr $errors + 1` | ||
34 | +else | ||
35 | + cmp mb1.O $srcdir/mb1.X > /dev/null 2>&1 | ||
36 | + case $? in | ||
37 | + 0) if test "$VERBOSE"; then $echo "passed mb1"; fi;; | ||
38 | + 1) $echo "Test mb1 failed: files mb1.O and $srcdir/mb1.X differ" 1>&2 | ||
39 | + (diff -c mb1.O $srcdir/mb1.X) 2> /dev/null | ||
40 | + errors=`expr $errors + 1`;; | ||
41 | + 2) $echo "Test mb1 may have failed." 1>&2 | ||
42 | + $echo The command "cmp mb1.O $srcdir/mb1.X" failed. 1>&2 | ||
43 | + errors=`expr $errors + 1`;; | ||
44 | + esac | ||
45 | +fi | ||
46 | + | ||
47 | +$xx -t ï¼ -k4 -n mb2.I > mb2.O | ||
48 | +code=$? | ||
49 | +if test $code != 0; then | ||
50 | + $echo "Test mb2 failed: $xx return code $code differs from expected value 0" 1>&2 | ||
51 | + errors=`expr $errors + 1` | ||
52 | +else | ||
53 | + cmp mb2.O $srcdir/mb2.X > /dev/null 2>&1 | ||
54 | + case $? in | ||
55 | + 0) if test "$VERBOSE"; then $echo "passed mb2"; fi;; | ||
56 | + 1) $echo "Test mb2 failed: files mb2.O and $srcdir/mb2.X differ" 1>&2 | ||
57 | + (diff -c mb2.O $srcdir/mb2.X) 2> /dev/null | ||
58 | + errors=`expr $errors + 1`;; | ||
59 | + 2) $echo "Test mb2 may have failed." 1>&2 | ||
60 | + $echo The command "cmp mb2.O $srcdir/mb2.X" failed. 1>&2 | ||
61 | + errors=`expr $errors + 1`;; | ||
62 | + esac | ||
63 | +fi | ||
64 | + | ||
65 | +if test $errors = 0; then | ||
66 | + $echo Passed all 113 tests. 1>&2 | ||
67 | +else | ||
68 | + $echo Failed $errors tests. 1>&2 | ||
69 | +fi | ||
70 | +test $errors = 0 || errors=1 | ||
71 | +exit $errors | ||
72 | --- /dev/null 2007-03-01 09:16:39.219409909 +0000 | ||
73 | +++ coreutils-6.8+/tests/sort/mb2.I 2007-03-01 15:08:24.000000000 +0000 | ||
74 | @@ -0,0 +1,4 @@ | ||
75 | +Appleï¼ ï¼¡ï¼¡10ï¼ ï¼ 20 | ||
76 | +Bananaï¼ ï¼¡ï¼¡5ï¼ ï¼ 30 | ||
77 | +Citrusï¼ ï¼¡ï¼¡20ï¼ ï¼ 5 | ||
78 | +Cherryï¼ ï¼¡ï¼¡30ï¼ ï¼ 10 | ||
79 | --- /dev/null 2007-03-01 09:16:39.219409909 +0000 | ||
80 | +++ coreutils-6.8+/tests/sort/mb2.X 2007-03-01 15:08:24.000000000 +0000 | ||
81 | @@ -0,0 +1,4 @@ | ||
82 | +Citrusï¼ ï¼¡ï¼¡20ï¼ ï¼ 5 | ||
83 | +Cherryï¼ ï¼¡ï¼¡30ï¼ ï¼ 10 | ||
84 | +Appleï¼ ï¼¡ï¼¡10ï¼ ï¼ 20 | ||
85 | +Bananaï¼ ï¼¡ï¼¡5ï¼ ï¼ 30 | ||
86 | --- /dev/null 2007-03-01 09:16:39.219409909 +0000 | ||
87 | +++ coreutils-6.8+/tests/sort/mb1.I 2007-03-01 15:08:24.000000000 +0000 | ||
88 | @@ -0,0 +1,4 @@ | ||
89 | +Appleï¼ 10 | ||
90 | +Bananaï¼ 5 | ||
91 | +Citrusï¼ 20 | ||
92 | +Cherryï¼ 30 | ||
93 | --- /dev/null 2007-03-01 09:16:39.219409909 +0000 | ||
94 | +++ coreutils-6.8+/tests/sort/mb1.X 2007-03-01 15:08:24.000000000 +0000 | ||
95 | @@ -0,0 +1,4 @@ | ||
96 | +Bananaï¼ 5 | ||
97 | +Appleï¼ 10 | ||
98 | +Citrusï¼ 20 | ||
99 | +Cherryï¼ 30 | ||
100 | --- coreutils-6.8+/tests/sort/Makefile.am.i18n 2007-01-24 07:47:37.000000000 +0000 | ||
101 | +++ coreutils-6.8+/tests/sort/Makefile.am 2007-03-01 15:09:59.000000000 +0000 | ||
102 | @@ -66,15 +66,17 @@ | ||
103 | bigfield.O bigfield.E | ||
104 | ##test-files-end | ||
105 | |||
106 | -EXTRA_DIST = Test.pm $x-tests $(explicit) $(maint_gen) | ||
107 | -noinst_SCRIPTS = $x-tests | ||
108 | +run_gen += mb1.0 mb2.0 | ||
109 | + | ||
110 | +EXTRA_DIST = Test.pm $x-tests $(explicit) $(maint_gen) mb1.I mb1.X mb2.I mb2.X | ||
111 | +noinst_SCRIPTS = $x-tests # $x-mb-tests | ||
112 | TESTS_ENVIRONMENT = \ | ||
113 | CU_TEST_NAME=`basename $(abs_srcdir)`,$$tst \ | ||
114 | PATH="$(VG_PATH_PREFIX)`pwd`/../../src$(PATH_SEPARATOR)$$PATH" | ||
115 | |||
116 | editpl = sed -e 's,@''PERL''@,$(PERL),g' -e 's,@''srcdir''@,$(srcdir),g' | ||
117 | |||
118 | -TESTS = $x-tests | ||
119 | +TESTS = $x-tests $x-mb-tests | ||
120 | |||
121 | mk_script = $(srcdir)/../mk-script | ||
122 | $(srcdir)/$x-tests: $(mk_script) Test.pm Makefile.am | ||
123 | --- coreutils-6.8+/lib/linebuffer.h.i18n 2005-05-14 07:44:24.000000000 +0100 | ||
124 | +++ coreutils-6.8+/lib/linebuffer.h 2007-03-01 15:08:24.000000000 +0000 | ||
125 | @@ -22,6 +22,11 @@ | ||
126 | |||
127 | # include <stdio.h> | ||
128 | |||
129 | +/* Get mbstate_t. */ | ||
130 | +# if HAVE_WCHAR_H | ||
131 | +# include <wchar.h> | ||
132 | +# endif | ||
133 | + | ||
134 | /* A `struct linebuffer' holds a line of text. */ | ||
135 | |||
136 | struct linebuffer | ||
137 | @@ -29,6 +34,9 @@ | ||
138 | size_t size; /* Allocated. */ | ||
139 | size_t length; /* Used. */ | ||
140 | char *buffer; | ||
141 | +# if HAVE_WCHAR_H | ||
142 | + mbstate_t state; | ||
143 | +# endif | ||
144 | }; | ||
145 | |||
146 | /* Initialize linebuffer LINEBUFFER for use. */ | ||
147 | --- coreutils-6.8+/src/expand.c.i18n 2007-01-14 15:41:28.000000000 +0000 | ||
148 | +++ coreutils-6.8+/src/expand.c 2007-03-01 15:08:24.000000000 +0000 | ||
149 | @@ -38,11 +38,28 @@ | ||
150 | #include <stdio.h> | ||
151 | #include <getopt.h> | ||
152 | #include <sys/types.h> | ||
153 | + | ||
154 | +/* Get mbstate_t, mbrtowc(), wcwidth(). */ | ||
155 | +#if HAVE_WCHAR_H | ||
156 | +# include <wchar.h> | ||
157 | +#endif | ||
158 | + | ||
159 | #include "system.h" | ||
160 | #include "error.h" | ||
161 | #include "quote.h" | ||
162 | #include "xstrndup.h" | ||
163 | |||
164 | +/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC | ||
165 | + installation; work around this configuration error. */ | ||
166 | +#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 | ||
167 | +# define MB_LEN_MAX 16 | ||
168 | +#endif | ||
169 | + | ||
170 | +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ | ||
171 | +#if HAVE_MBRTOWC && defined mbstate_t | ||
172 | +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) | ||
173 | +#endif | ||
174 | + | ||
175 | /* The official name of this program (e.g., no `g' prefix). */ | ||
176 | #define PROGRAM_NAME "expand" | ||
177 | |||
178 | @@ -183,6 +200,7 @@ | ||
179 | stops = num_start + len - 1; | ||
180 | } | ||
181 | } | ||
182 | + | ||
183 | else | ||
184 | { | ||
185 | error (0, 0, _("tab size contains invalid character(s): %s"), | ||
186 | @@ -365,6 +383,142 @@ | ||
187 | } | ||
188 | } | ||
189 | |||
190 | +#if HAVE_MBRTOWC | ||
191 | +static void | ||
192 | +expand_multibyte (void) | ||
193 | +{ | ||
194 | + FILE *fp; /* Input strem. */ | ||
195 | + mbstate_t i_state; /* Current shift state of the input stream. */ | ||
196 | + mbstate_t i_state_bak; /* Back up the I_STATE. */ | ||
197 | + mbstate_t o_state; /* Current shift state of the output stream. */ | ||
198 | + char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ | ||
199 | + char *bufpos; /* Next read position of BUF. */ | ||
200 | + size_t buflen = 0; /* The length of the byte sequence in buf. */ | ||
201 | + wchar_t wc; /* A gotten wide character. */ | ||
202 | + size_t mblength; /* The byte size of a multibyte character | ||
203 | + which shows as same character as WC. */ | ||
204 | + int tab_index = 0; /* Index in `tab_list' of next tabstop. */ | ||
205 | + int column = 0; /* Column on screen of the next char. */ | ||
206 | + int next_tab_column; /* Column the next tab stop is on. */ | ||
207 | + int convert = 1; /* If nonzero, perform translations. */ | ||
208 | + | ||
209 | + fp = next_file ((FILE *) NULL); | ||
210 | + if (fp == NULL) | ||
211 | + return; | ||
212 | + | ||
213 | + memset (&o_state, '\0', sizeof(mbstate_t)); | ||
214 | + memset (&i_state, '\0', sizeof(mbstate_t)); | ||
215 | + | ||
216 | + for (;;) | ||
217 | + { | ||
218 | + /* Refill the buffer BUF. */ | ||
219 | + if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp)) | ||
220 | + { | ||
221 | + memmove (buf, bufpos, buflen); | ||
222 | + buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp); | ||
223 | + bufpos = buf; | ||
224 | + } | ||
225 | + | ||
226 | + /* No character is left in BUF. */ | ||
227 | + if (buflen < 1) | ||
228 | + { | ||
229 | + fp = next_file (fp); | ||
230 | + | ||
231 | + if (fp == NULL) | ||
232 | + break; /* No more files. */ | ||
233 | + else | ||
234 | + { | ||
235 | + memset (&i_state, '\0', sizeof(mbstate_t)); | ||
236 | + continue; | ||
237 | + } | ||
238 | + } | ||
239 | + | ||
240 | + /* Get a wide character. */ | ||
241 | + i_state_bak = i_state; | ||
242 | + mblength = mbrtowc (&wc, bufpos, buflen, &i_state); | ||
243 | + | ||
244 | + switch (mblength) | ||
245 | + { | ||
246 | + case (size_t)-1: /* illegal byte sequence. */ | ||
247 | + case (size_t)-2: | ||
248 | + mblength = 1; | ||
249 | + i_state = i_state_bak; | ||
250 | + if (convert) | ||
251 | + { | ||
252 | + ++column; | ||
253 | + if (convert_entire_line == 0) | ||
254 | + convert = 0; | ||
255 | + } | ||
256 | + putchar (*bufpos); | ||
257 | + break; | ||
258 | + | ||
259 | + case 0: /* null. */ | ||
260 | + mblength = 1; | ||
261 | + if (convert && convert_entire_line == 0) | ||
262 | + convert = 0; | ||
263 | + putchar ('\0'); | ||
264 | + break; | ||
265 | + | ||
266 | + default: | ||
267 | + if (wc == L'\n') /* LF. */ | ||
268 | + { | ||
269 | + tab_index = 0; | ||
270 | + column = 0; | ||
271 | + convert = 1; | ||
272 | + putchar ('\n'); | ||
273 | + } | ||
274 | + else if (wc == L'\t' && convert) /* Tab. */ | ||
275 | + { | ||
276 | + if (tab_size == 0) | ||
277 | + { | ||
278 | + /* Do not let tab_index == first_free_tab; | ||
279 | + stop when it is 1 less. */ | ||
280 | + while (tab_index < first_free_tab - 1 | ||
281 | + && column >= tab_list[tab_index]) | ||
282 | + tab_index++; | ||
283 | + next_tab_column = tab_list[tab_index]; | ||
284 | + if (tab_index < first_free_tab - 1) | ||
285 | + tab_index++; | ||
286 | + if (column >= next_tab_column) | ||
287 | + next_tab_column = column + 1; | ||
288 | + } | ||
289 | + else | ||
290 | + next_tab_column = column + tab_size - column % tab_size; | ||
291 | + | ||
292 | + while (column < next_tab_column) | ||
293 | + { | ||
294 | + putchar (' '); | ||
295 | + ++column; | ||
296 | + } | ||
297 | + } | ||
298 | + else /* Others. */ | ||
299 | + { | ||
300 | + if (convert) | ||
301 | + { | ||
302 | + if (wc == L'\b') | ||
303 | + { | ||
304 | + if (column > 0) | ||
305 | + --column; | ||
306 | + } | ||
307 | + else | ||
308 | + { | ||
309 | + int width; /* The width of WC. */ | ||
310 | + | ||
311 | + width = wcwidth (wc); | ||
312 | + column += (width > 0) ? width : 0; | ||
313 | + if (convert_entire_line == 0) | ||
314 | + convert = 0; | ||
315 | + } | ||
316 | + } | ||
317 | + fwrite (bufpos, sizeof(char), mblength, stdout); | ||
318 | + } | ||
319 | + } | ||
320 | + buflen -= mblength; | ||
321 | + bufpos += mblength; | ||
322 | + } | ||
323 | +} | ||
324 | +#endif | ||
325 | + | ||
326 | int | ||
327 | main (int argc, char **argv) | ||
328 | { | ||
329 | @@ -429,7 +583,12 @@ | ||
330 | |||
331 | file_list = (optind < argc ? &argv[optind] : stdin_argv); | ||
332 | |||
333 | - expand (); | ||
334 | +#if HAVE_MBRTOWC | ||
335 | + if (MB_CUR_MAX > 1) | ||
336 | + expand_multibyte (); | ||
337 | + else | ||
338 | +#endif | ||
339 | + expand (); | ||
340 | |||
341 | if (have_read_stdin && fclose (stdin) != 0) | ||
342 | error (EXIT_FAILURE, errno, "-"); | ||
343 | --- coreutils-6.8+/src/join.c.i18n 2007-01-14 15:41:28.000000000 +0000 | ||
344 | +++ coreutils-6.8+/src/join.c 2007-03-01 15:08:24.000000000 +0000 | ||
345 | @@ -23,16 +23,30 @@ | ||
346 | #include <sys/types.h> | ||
347 | #include <getopt.h> | ||
348 | |||
349 | +/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth(). */ | ||
350 | +#if HAVE_WCHAR_H | ||
351 | +# include <wchar.h> | ||
352 | +#endif | ||
353 | + | ||
354 | +/* Get iswblank(), towupper. */ | ||
355 | +#if HAVE_WCTYPE_H | ||
356 | +# include <wctype.h> | ||
357 | +#endif | ||
358 | + | ||
359 | #include "system.h" | ||
360 | #include "error.h" | ||
361 | #include "hard-locale.h" | ||
362 | #include "linebuffer.h" | ||
363 | -#include "memcasecmp.h" | ||
364 | #include "quote.h" | ||
365 | #include "stdio--.h" | ||
366 | #include "xmemcoll.h" | ||
367 | #include "xstrtol.h" | ||
368 | |||
369 | +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ | ||
370 | +#if HAVE_MBRTOWC && defined mbstate_t | ||
371 | +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) | ||
372 | +#endif | ||
373 | + | ||
374 | /* The official name of this program (e.g., no `g' prefix). */ | ||
375 | #define PROGRAM_NAME "join" | ||
376 | |||
377 | @@ -104,10 +118,12 @@ | ||
378 | /* Last element in `outlist', where a new element can be added. */ | ||
379 | static struct outlist *outlist_end = &outlist_head; | ||
380 | |||
381 | -/* Tab character separating fields. If negative, fields are separated | ||
382 | - by any nonempty string of blanks, otherwise by exactly one | ||
383 | - tab character whose value (when cast to unsigned char) equals TAB. */ | ||
384 | -static int tab = -1; | ||
385 | +/* Tab character separating fields. If NULL, fields are separated | ||
386 | + by any nonempty string of blanks. */ | ||
387 | +static char *tab = NULL; | ||
388 | + | ||
389 | +/* The number of bytes used for tab. */ | ||
390 | +static size_t tablen = 0; | ||
391 | |||
392 | static struct option const longopts[] = | ||
393 | { | ||
394 | @@ -190,6 +206,8 @@ | ||
395 | |||
396 | /* Fill in the `fields' structure in LINE. */ | ||
397 | |||
398 | +/* Fill in the `fields' structure in LINE. */ | ||
399 | + | ||
400 | static void | ||
401 | xfields (struct line *line) | ||
402 | { | ||
403 | @@ -199,10 +217,11 @@ | ||
404 | if (ptr == lim) | ||
405 | return; | ||
406 | |||
407 | - if (0 <= tab) | ||
408 | + if (tab != NULL) | ||
409 | { | ||
410 | + unsigned char t = tab[0]; | ||
411 | char *sep; | ||
412 | - for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1) | ||
413 | + for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1) | ||
414 | extract_field (line, ptr, sep - ptr); | ||
415 | } | ||
416 | else | ||
417 | @@ -229,6 +248,148 @@ | ||
418 | extract_field (line, ptr, lim - ptr); | ||
419 | } | ||
420 | |||
421 | +#if HAVE_MBRTOWC | ||
422 | +static void | ||
423 | +xfields_multibyte (struct line *line) | ||
424 | +{ | ||
425 | + char *ptr = line->buf.buffer; | ||
426 | + char const *lim = ptr + line->buf.length - 1; | ||
427 | + wchar_t wc = 0; | ||
428 | + size_t mblength = 1; | ||
429 | + mbstate_t state, state_bak; | ||
430 | + | ||
431 | + memset (&state, 0, sizeof (mbstate_t)); | ||
432 | + | ||
433 | + if (ptr == lim) | ||
434 | + return; | ||
435 | + | ||
436 | + if (tab != NULL) | ||
437 | + { | ||
438 | + unsigned char t = tab[0]; | ||
439 | + char *sep = ptr; | ||
440 | + for (; ptr < lim; ptr = sep + mblength) | ||
441 | + { | ||
442 | + sep = ptr; | ||
443 | + while (sep < lim) | ||
444 | + { | ||
445 | + state_bak = state; | ||
446 | + mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); | ||
447 | + | ||
448 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
449 | + { | ||
450 | + mblength = 1; | ||
451 | + state = state_bak; | ||
452 | + } | ||
453 | + mblength = (mblength < 1) ? 1 : mblength; | ||
454 | + | ||
455 | + if (mblength == tablen && !memcmp (sep, tab, mblength)) | ||
456 | + break; | ||
457 | + else | ||
458 | + { | ||
459 | + sep += mblength; | ||
460 | + continue; | ||
461 | + } | ||
462 | + } | ||
463 | + | ||
464 | + if (sep == lim) | ||
465 | + break; | ||
466 | + | ||
467 | + extract_field (line, ptr, sep - ptr); | ||
468 | + } | ||
469 | + } | ||
470 | + else | ||
471 | + { | ||
472 | + /* Skip leading blanks before the first field. */ | ||
473 | + while(ptr < lim) | ||
474 | + { | ||
475 | + state_bak = state; | ||
476 | + mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); | ||
477 | + | ||
478 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
479 | + { | ||
480 | + mblength = 1; | ||
481 | + state = state_bak; | ||
482 | + break; | ||
483 | + } | ||
484 | + mblength = (mblength < 1) ? 1 : mblength; | ||
485 | + | ||
486 | + if (!iswblank(wc)) | ||
487 | + break; | ||
488 | + ptr += mblength; | ||
489 | + } | ||
490 | + | ||
491 | + do | ||
492 | + { | ||
493 | + char *sep; | ||
494 | + state_bak = state; | ||
495 | + mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); | ||
496 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
497 | + { | ||
498 | + mblength = 1; | ||
499 | + state = state_bak; | ||
500 | + break; | ||
501 | + } | ||
502 | + mblength = (mblength < 1) ? 1 : mblength; | ||
503 | + | ||
504 | + sep = ptr + mblength; | ||
505 | + while (sep != lim) | ||
506 | + { | ||
507 | + state_bak = state; | ||
508 | + mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); | ||
509 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
510 | + { | ||
511 | + mblength = 1; | ||
512 | + state = state_bak; | ||
513 | + break; | ||
514 | + } | ||
515 | + mblength = (mblength < 1) ? 1 : mblength; | ||
516 | + | ||
517 | + if (iswblank (wc)) | ||
518 | + break; | ||
519 | + | ||
520 | + sep += mblength; | ||
521 | + } | ||
522 | + | ||
523 | + extract_field (line, ptr, sep - ptr); | ||
524 | + if (sep == lim) | ||
525 | + return; | ||
526 | + | ||
527 | + state_bak = state; | ||
528 | + mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); | ||
529 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
530 | + { | ||
531 | + mblength = 1; | ||
532 | + state = state_bak; | ||
533 | + break; | ||
534 | + } | ||
535 | + mblength = (mblength < 1) ? 1 : mblength; | ||
536 | + | ||
537 | + ptr = sep + mblength; | ||
538 | + while (ptr != lim) | ||
539 | + { | ||
540 | + state_bak = state; | ||
541 | + mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); | ||
542 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
543 | + { | ||
544 | + mblength = 1; | ||
545 | + state = state_bak; | ||
546 | + break; | ||
547 | + } | ||
548 | + mblength = (mblength < 1) ? 1 : mblength; | ||
549 | + | ||
550 | + if (!iswblank (wc)) | ||
551 | + break; | ||
552 | + | ||
553 | + ptr += mblength; | ||
554 | + } | ||
555 | + } | ||
556 | + while (ptr != lim); | ||
557 | + } | ||
558 | + | ||
559 | + extract_field (line, ptr, lim - ptr); | ||
560 | +} | ||
561 | +#endif | ||
562 | + | ||
563 | /* Read a line from FP into LINE and split it into fields. | ||
564 | Return true if successful. */ | ||
565 | |||
566 | @@ -249,6 +410,11 @@ | ||
567 | line->nfields_allocated = 0; | ||
568 | line->nfields = 0; | ||
569 | line->fields = NULL; | ||
570 | +#if HAVE_MBRTOWC | ||
571 | + if (MB_CUR_MAX > 1) | ||
572 | + xfields_multibyte (line); | ||
573 | + else | ||
574 | +#endif | ||
575 | xfields (line); | ||
576 | return true; | ||
577 | } | ||
578 | @@ -303,56 +469,114 @@ | ||
579 | keycmp (struct line const *line1, struct line const *line2) | ||
580 | { | ||
581 | /* Start of field to compare in each file. */ | ||
582 | - char *beg1; | ||
583 | - char *beg2; | ||
584 | - | ||
585 | - size_t len1; | ||
586 | - size_t len2; /* Length of fields to compare. */ | ||
587 | + char *beg[2]; | ||
588 | + char *copy[2]; | ||
589 | + size_t len[2]; /* Length of fields to compare. */ | ||
590 | int diff; | ||
591 | + int i, j; | ||
592 | |||
593 | if (join_field_1 < line1->nfields) | ||
594 | { | ||
595 | - beg1 = line1->fields[join_field_1].beg; | ||
596 | - len1 = line1->fields[join_field_1].len; | ||
597 | + beg[0] = line1->fields[join_field_1].beg; | ||
598 | + len[0] = line1->fields[join_field_1].len; | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | - beg1 = NULL; | ||
603 | - len1 = 0; | ||
604 | + beg[0] = NULL; | ||
605 | + len[0] = 0; | ||
606 | } | ||
607 | |||
608 | if (join_field_2 < line2->nfields) | ||
609 | { | ||
610 | - beg2 = line2->fields[join_field_2].beg; | ||
611 | - len2 = line2->fields[join_field_2].len; | ||
612 | + beg[1] = line2->fields[join_field_2].beg; | ||
613 | + len[1] = line2->fields[join_field_2].len; | ||
614 | } | ||
615 | else | ||
616 | { | ||
617 | - beg2 = NULL; | ||
618 | - len2 = 0; | ||
619 | + beg[1] = NULL; | ||
620 | + len[1] = 0; | ||
621 | } | ||
622 | |||
623 | - if (len1 == 0) | ||
624 | - return len2 == 0 ? 0 : -1; | ||
625 | - if (len2 == 0) | ||
626 | + if (len[0] == 0) | ||
627 | + return len[1] == 0 ? 0 : -1; | ||
628 | + if (len[1] == 0) | ||
629 | return 1; | ||
630 | |||
631 | if (ignore_case) | ||
632 | { | ||
633 | - /* FIXME: ignore_case does not work with NLS (in particular, | ||
634 | - with multibyte chars). */ | ||
635 | - diff = memcasecmp (beg1, beg2, MIN (len1, len2)); | ||
636 | +#ifdef HAVE_MBRTOWC | ||
637 | + if (MB_CUR_MAX > 1) | ||
638 | + { | ||
639 | + size_t mblength; | ||
640 | + wchar_t wc, uwc; | ||
641 | + mbstate_t state, state_bak; | ||
642 | + | ||
643 | + memset (&state, '\0', sizeof (mbstate_t)); | ||
644 | + | ||
645 | + for (i = 0; i < 2; i++) | ||
646 | + { | ||
647 | + copy[i] = alloca (len[i] + 1); | ||
648 | + | ||
649 | + for (j = 0; j < MIN (len[0], len[1]);) | ||
650 | + { | ||
651 | + state_bak = state; | ||
652 | + mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state); | ||
653 | + | ||
654 | + switch (mblength) | ||
655 | + { | ||
656 | + case (size_t) -1: | ||
657 | + case (size_t) -2: | ||
658 | + state = state_bak; | ||
659 | + /* Fall through */ | ||
660 | + case 0: | ||
661 | + mblength = 1; | ||
662 | + break; | ||
663 | + | ||
664 | + default: | ||
665 | + uwc = towupper (wc); | ||
666 | + | ||
667 | + if (uwc != wc) | ||
668 | + { | ||
669 | + mbstate_t state_wc; | ||
670 | + | ||
671 | + memset (&state_wc, '\0', sizeof (mbstate_t)); | ||
672 | + wcrtomb (copy[i] + j, uwc, &state_wc); | ||
673 | + } | ||
674 | + else | ||
675 | + memcpy (copy[i] + j, beg[i] + j, mblength); | ||
676 | + } | ||
677 | + j += mblength; | ||
678 | + } | ||
679 | + copy[i][j] = '\0'; | ||
680 | + } | ||
681 | + } | ||
682 | + else | ||
683 | +#endif | ||
684 | + { | ||
685 | + for (i = 0; i < 2; i++) | ||
686 | + { | ||
687 | + copy[i] = alloca (len[i] + 1); | ||
688 | + | ||
689 | + for (j = 0; j < MIN (len[0], len[1]); j++) | ||
690 | + copy[i][j] = toupper (beg[i][j]); | ||
691 | + | ||
692 | + copy[i][j] = '\0'; | ||
693 | + } | ||
694 | + } | ||
695 | } | ||
696 | else | ||
697 | { | ||
698 | - if (hard_LC_COLLATE) | ||
699 | - return xmemcoll (beg1, len1, beg2, len2); | ||
700 | - diff = memcmp (beg1, beg2, MIN (len1, len2)); | ||
701 | + copy[0] = (unsigned char *) beg[0]; | ||
702 | + copy[1] = (unsigned char *) beg[1]; | ||
703 | } | ||
704 | |||
705 | + if (hard_LC_COLLATE) | ||
706 | + return xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]); | ||
707 | + diff = memcmp (copy[0], copy[1], MIN (len[0], len[1])); | ||
708 | + | ||
709 | if (diff) | ||
710 | return diff; | ||
711 | - return len1 < len2 ? -1 : len1 != len2; | ||
712 | + return len[0] - len[1]; | ||
713 | } | ||
714 | |||
715 | /* Print field N of LINE if it exists and is nonempty, otherwise | ||
716 | @@ -377,11 +601,18 @@ | ||
717 | |||
718 | /* Print the join of LINE1 and LINE2. */ | ||
719 | |||
720 | +#define PUT_TAB_CHAR \ | ||
721 | + do \ | ||
722 | + { \ | ||
723 | + (tab != NULL) ? \ | ||
724 | + fwrite(tab, sizeof(char), tablen, stdout) : putchar (' '); \ | ||
725 | + } \ | ||
726 | + while (0) | ||
727 | + | ||
728 | static void | ||
729 | prjoin (struct line const *line1, struct line const *line2) | ||
730 | { | ||
731 | const struct outlist *outlist; | ||
732 | - char output_separator = tab < 0 ? ' ' : tab; | ||
733 | |||
734 | outlist = outlist_head.next; | ||
735 | if (outlist) | ||
736 | @@ -397,12 +628,12 @@ | ||
737 | if (o->file == 0) | ||
738 | { | ||
739 | if (line1 == &uni_blank) | ||
740 | - { | ||
741 | + { | ||
742 | line = line2; | ||
743 | field = join_field_2; | ||
744 | } | ||
745 | else | ||
746 | - { | ||
747 | + { | ||
748 | line = line1; | ||
749 | field = join_field_1; | ||
750 | } | ||
751 | @@ -416,7 +647,7 @@ | ||
752 | o = o->next; | ||
753 | if (o == NULL) | ||
754 | break; | ||
755 | - putchar (output_separator); | ||
756 | + PUT_TAB_CHAR; | ||
757 | } | ||
758 | putchar ('\n'); | ||
759 | } | ||
760 | @@ -434,23 +665,23 @@ | ||
761 | prfield (join_field_1, line1); | ||
762 | for (i = 0; i < join_field_1 && i < line1->nfields; ++i) | ||
763 | { | ||
764 | - putchar (output_separator); | ||
765 | + PUT_TAB_CHAR; | ||
766 | prfield (i, line1); | ||
767 | } | ||
768 | for (i = join_field_1 + 1; i < line1->nfields; ++i) | ||
769 | { | ||
770 | - putchar (output_separator); | ||
771 | + PUT_TAB_CHAR; | ||
772 | prfield (i, line1); | ||
773 | } | ||
774 | |||
775 | for (i = 0; i < join_field_2 && i < line2->nfields; ++i) | ||
776 | { | ||
777 | - putchar (output_separator); | ||
778 | + PUT_TAB_CHAR; | ||
779 | prfield (i, line2); | ||
780 | } | ||
781 | for (i = join_field_2 + 1; i < line2->nfields; ++i) | ||
782 | { | ||
783 | - putchar (output_separator); | ||
784 | + PUT_TAB_CHAR; | ||
785 | prfield (i, line2); | ||
786 | } | ||
787 | putchar ('\n'); | ||
788 | @@ -859,20 +1090,41 @@ | ||
789 | |||
790 | case 't': | ||
791 | { | ||
792 | - unsigned char newtab = optarg[0]; | ||
793 | - if (! newtab) | ||
794 | + char *newtab; | ||
795 | + size_t newtablen; | ||
796 | + if (! optarg[0]) | ||
797 | error (EXIT_FAILURE, 0, _("empty tab")); | ||
798 | - if (optarg[1]) | ||
799 | + newtab = xstrdup (optarg); | ||
800 | +#if HAVE_MBRTOWC | ||
801 | + if (MB_CUR_MAX > 1) | ||
802 | + { | ||
803 | + mbstate_t state; | ||
804 | + | ||
805 | + memset (&state, 0, sizeof (mbstate_t)); | ||
806 | + newtablen = mbrtowc (NULL, newtab, | ||
807 | + strnlen (newtab, MB_LEN_MAX), | ||
808 | + &state); | ||
809 | + if (newtablen == (size_t) 0 | ||
810 | + || newtablen == (size_t) -1 | ||
811 | + || newtablen == (size_t) -2) | ||
812 | + newtablen = 1; | ||
813 | + } | ||
814 | + else | ||
815 | +#endif | ||
816 | + newtablen = 1; | ||
817 | + | ||
818 | + if (newtablen == 1 && newtab[1]) | ||
819 | + { | ||
820 | + if (STREQ (newtab, "\\0")) | ||
821 | + newtab[0] = '\0'; | ||
822 | + } | ||
823 | + if (tab != NULL && strcmp (tab, newtab)) | ||
824 | { | ||
825 | - if (STREQ (optarg, "\\0")) | ||
826 | - newtab = '\0'; | ||
827 | - else | ||
828 | - error (EXIT_FAILURE, 0, _("multi-character tab %s"), | ||
829 | - quote (optarg)); | ||
830 | + free (newtab); | ||
831 | + error (EXIT_FAILURE, 0, _("incompatible tabs")); | ||
832 | } | ||
833 | - if (0 <= tab && tab != newtab) | ||
834 | - error (EXIT_FAILURE, 0, _("incompatible tabs")); | ||
835 | tab = newtab; | ||
836 | + tablen = newtablen; | ||
837 | } | ||
838 | break; | ||
839 | |||
840 | --- coreutils-6.8+/src/uniq.c.i18n 2007-01-14 15:41:28.000000000 +0000 | ||
841 | +++ coreutils-6.8+/src/uniq.c 2007-03-01 15:08:24.000000000 +0000 | ||
842 | @@ -23,6 +23,16 @@ | ||
843 | #include <getopt.h> | ||
844 | #include <sys/types.h> | ||
845 | |||
846 | +/* Get mbstate_t, mbrtowc(). */ | ||
847 | +#if HAVE_WCHAR_H | ||
848 | +# include <wchar.h> | ||
849 | +#endif | ||
850 | + | ||
851 | +/* Get isw* functions. */ | ||
852 | +#if HAVE_WCTYPE_H | ||
853 | +# include <wctype.h> | ||
854 | +#endif | ||
855 | + | ||
856 | #include "system.h" | ||
857 | #include "argmatch.h" | ||
858 | #include "linebuffer.h" | ||
859 | @@ -32,7 +42,19 @@ | ||
860 | #include "quote.h" | ||
861 | #include "xmemcoll.h" | ||
862 | #include "xstrtol.h" | ||
863 | -#include "memcasecmp.h" | ||
864 | +#include "xmemcoll.h" | ||
865 | + | ||
866 | +/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC | ||
867 | + installation; work around this configuration error. */ | ||
868 | +#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 | ||
869 | +# define MB_LEN_MAX 16 | ||
870 | +#endif | ||
871 | + | ||
872 | +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ | ||
873 | +#if HAVE_MBRTOWC && defined mbstate_t | ||
874 | +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) | ||
875 | +#endif | ||
876 | + | ||
877 | |||
878 | /* The official name of this program (e.g., no `g' prefix). */ | ||
879 | #define PROGRAM_NAME "uniq" | ||
880 | @@ -109,6 +131,10 @@ | ||
881 | /* Select whether/how to delimit groups of duplicate lines. */ | ||
882 | static enum delimit_method delimit_groups; | ||
883 | |||
884 | +/* Function pointers. */ | ||
885 | +static char * | ||
886 | +(*find_field) (struct linebuffer *line); | ||
887 | + | ||
888 | static struct option const longopts[] = | ||
889 | { | ||
890 | {"count", no_argument, NULL, 'c'}, | ||
891 | @@ -198,7 +224,7 @@ | ||
892 | return a pointer to the beginning of the line's field to be compared. */ | ||
893 | |||
894 | static char * | ||
895 | -find_field (const struct linebuffer *line) | ||
896 | +find_field_uni (struct linebuffer *line) | ||
897 | { | ||
898 | size_t count; | ||
899 | char *lp = line->buffer; | ||
900 | @@ -219,6 +245,83 @@ | ||
901 | return lp + i; | ||
902 | } | ||
903 | |||
904 | +#if HAVE_MBRTOWC | ||
905 | + | ||
906 | +# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL) \ | ||
907 | + do \ | ||
908 | + { \ | ||
909 | + mbstate_t state_bak; \ | ||
910 | + \ | ||
911 | + CONVFAIL = 0; \ | ||
912 | + state_bak = *STATEP; \ | ||
913 | + \ | ||
914 | + MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP); \ | ||
915 | + \ | ||
916 | + switch (MBLENGTH) \ | ||
917 | + { \ | ||
918 | + case (size_t)-2: \ | ||
919 | + case (size_t)-1: \ | ||
920 | + *STATEP = state_bak; \ | ||
921 | + CONVFAIL++; \ | ||
922 | + /* Fall through */ \ | ||
923 | + case 0: \ | ||
924 | + MBLENGTH = 1; \ | ||
925 | + } \ | ||
926 | + } \ | ||
927 | + while (0) | ||
928 | + | ||
929 | +static char * | ||
930 | +find_field_multi (struct linebuffer *line) | ||
931 | +{ | ||
932 | + size_t count; | ||
933 | + char *lp = line->buffer; | ||
934 | + size_t size = line->length - 1; | ||
935 | + size_t pos; | ||
936 | + size_t mblength; | ||
937 | + wchar_t wc; | ||
938 | + mbstate_t *statep; | ||
939 | + int convfail; | ||
940 | + | ||
941 | + pos = 0; | ||
942 | + statep = &(line->state); | ||
943 | + | ||
944 | + /* skip fields. */ | ||
945 | + for (count = 0; count < skip_fields && pos < size; count++) | ||
946 | + { | ||
947 | + while (pos < size) | ||
948 | + { | ||
949 | + MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); | ||
950 | + | ||
951 | + if (convfail || !iswblank (wc)) | ||
952 | + { | ||
953 | + pos += mblength; | ||
954 | + break; | ||
955 | + } | ||
956 | + pos += mblength; | ||
957 | + } | ||
958 | + | ||
959 | + while (pos < size) | ||
960 | + { | ||
961 | + MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); | ||
962 | + | ||
963 | + if (!convfail && iswblank (wc)) | ||
964 | + break; | ||
965 | + | ||
966 | + pos += mblength; | ||
967 | + } | ||
968 | + } | ||
969 | + | ||
970 | + /* skip fields. */ | ||
971 | + for (count = 0; count < skip_chars && pos < size; count++) | ||
972 | + { | ||
973 | + MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); | ||
974 | + pos += mblength; | ||
975 | + } | ||
976 | + | ||
977 | + return lp + pos; | ||
978 | +} | ||
979 | +#endif | ||
980 | + | ||
981 | /* Return false if two strings OLD and NEW match, true if not. | ||
982 | OLD and NEW point not to the beginnings of the lines | ||
983 | but rather to the beginnings of the fields to compare. | ||
984 | @@ -227,6 +330,8 @@ | ||
985 | static bool | ||
986 | different (char *old, char *new, size_t oldlen, size_t newlen) | ||
987 | { | ||
988 | + char *copy_old, *copy_new; | ||
989 | + | ||
990 | if (check_chars < oldlen) | ||
991 | oldlen = check_chars; | ||
992 | if (check_chars < newlen) | ||
993 | @@ -234,14 +339,92 @@ | ||
994 | |||
995 | if (ignore_case) | ||
996 | { | ||
997 | - /* FIXME: This should invoke strcoll somehow. */ | ||
998 | - return oldlen != newlen || memcasecmp (old, new, oldlen); | ||
999 | + size_t i; | ||
1000 | + | ||
1001 | + copy_old = alloca (oldlen + 1); | ||
1002 | + copy_new = alloca (oldlen + 1); | ||
1003 | + | ||
1004 | + for (i = 0; i < oldlen; i++) | ||
1005 | + { | ||
1006 | + copy_old[i] = toupper (old[i]); | ||
1007 | + copy_new[i] = toupper (new[i]); | ||
1008 | + } | ||
1009 | } | ||
1010 | - else if (hard_LC_COLLATE) | ||
1011 | - return xmemcoll (old, oldlen, new, newlen) != 0; | ||
1012 | else | ||
1013 | - return oldlen != newlen || memcmp (old, new, oldlen); | ||
1014 | + { | ||
1015 | + copy_old = (char *)old; | ||
1016 | + copy_new = (char *)new; | ||
1017 | + } | ||
1018 | + | ||
1019 | + return xmemcoll (copy_old, oldlen, copy_new, newlen); | ||
1020 | +} | ||
1021 | + | ||
1022 | +#if HAVE_MBRTOWC | ||
1023 | +static int | ||
1024 | +different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate) | ||
1025 | +{ | ||
1026 | + size_t i, j, chars; | ||
1027 | + const char *str[2]; | ||
1028 | + char *copy[2]; | ||
1029 | + size_t len[2]; | ||
1030 | + mbstate_t state[2]; | ||
1031 | + size_t mblength; | ||
1032 | + wchar_t wc, uwc; | ||
1033 | + mbstate_t state_bak; | ||
1034 | + | ||
1035 | + str[0] = old; | ||
1036 | + str[1] = new; | ||
1037 | + len[0] = oldlen; | ||
1038 | + len[1] = newlen; | ||
1039 | + state[0] = oldstate; | ||
1040 | + state[1] = newstate; | ||
1041 | + | ||
1042 | + for (i = 0; i < 2; i++) | ||
1043 | + { | ||
1044 | + copy[i] = alloca (len[i] + 1); | ||
1045 | + | ||
1046 | + for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++) | ||
1047 | + { | ||
1048 | + state_bak = state[i]; | ||
1049 | + mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i])); | ||
1050 | + | ||
1051 | + switch (mblength) | ||
1052 | + { | ||
1053 | + case (size_t)-1: | ||
1054 | + case (size_t)-2: | ||
1055 | + state[i] = state_bak; | ||
1056 | + /* Fall through */ | ||
1057 | + case 0: | ||
1058 | + mblength = 1; | ||
1059 | + break; | ||
1060 | + | ||
1061 | + default: | ||
1062 | + if (ignore_case) | ||
1063 | + { | ||
1064 | + uwc = towupper (wc); | ||
1065 | + | ||
1066 | + if (uwc != wc) | ||
1067 | + { | ||
1068 | + mbstate_t state_wc; | ||
1069 | + | ||
1070 | + memset (&state_wc, '\0', sizeof(mbstate_t)); | ||
1071 | + wcrtomb (copy[i] + j, uwc, &state_wc); | ||
1072 | + } | ||
1073 | + else | ||
1074 | + memcpy (copy[i] + j, str[i] + j, mblength); | ||
1075 | + } | ||
1076 | + else | ||
1077 | + memcpy (copy[i] + j, str[i] + j, mblength); | ||
1078 | + } | ||
1079 | + j += mblength; | ||
1080 | + } | ||
1081 | + copy[i][j] = '\0'; | ||
1082 | + len[i] = j; | ||
1083 | + } | ||
1084 | + | ||
1085 | + return xmemcoll (copy[0], len[0], copy[1], len[1]); | ||
1086 | } | ||
1087 | +#endif | ||
1088 | |||
1089 | /* Output the line in linebuffer LINE to standard output | ||
1090 | provided that the switches say it should be output. | ||
1091 | @@ -295,15 +478,43 @@ | ||
1092 | { | ||
1093 | char *prevfield IF_LINT (= NULL); | ||
1094 | size_t prevlen IF_LINT (= 0); | ||
1095 | +#if HAVE_MBRTOWC | ||
1096 | + mbstate_t prevstate; | ||
1097 | + | ||
1098 | + memset (&prevstate, '\0', sizeof (mbstate_t)); | ||
1099 | +#endif | ||
1100 | |||
1101 | while (!feof (stdin)) | ||
1102 | { | ||
1103 | char *thisfield; | ||
1104 | size_t thislen; | ||
1105 | +#if HAVE_MBRTOWC | ||
1106 | + mbstate_t thisstate; | ||
1107 | +#endif | ||
1108 | + | ||
1109 | if (readlinebuffer (thisline, stdin) == 0) | ||
1110 | break; | ||
1111 | thisfield = find_field (thisline); | ||
1112 | thislen = thisline->length - 1 - (thisfield - thisline->buffer); | ||
1113 | +#if HAVE_MBRTOWC | ||
1114 | + if (MB_CUR_MAX > 1) | ||
1115 | + { | ||
1116 | + thisstate = thisline->state; | ||
1117 | + | ||
1118 | + if (prevline->length == 0 || different_multi | ||
1119 | + (thisfield, prevfield, thislen, prevlen, thisstate, prevstate)) | ||
1120 | + { | ||
1121 | + fwrite (thisline->buffer, sizeof (char), | ||
1122 | + thisline->length, stdout); | ||
1123 | + | ||
1124 | + SWAP_LINES (prevline, thisline); | ||
1125 | + prevfield = thisfield; | ||
1126 | + prevlen = thislen; | ||
1127 | + prevstate = thisstate; | ||
1128 | + } | ||
1129 | + } | ||
1130 | + else | ||
1131 | +#endif | ||
1132 | if (prevline->length == 0 | ||
1133 | || different (thisfield, prevfield, thislen, prevlen)) | ||
1134 | { | ||
1135 | @@ -322,17 +533,26 @@ | ||
1136 | size_t prevlen; | ||
1137 | uintmax_t match_count = 0; | ||
1138 | bool first_delimiter = true; | ||
1139 | +#if HAVE_MBRTOWC | ||
1140 | + mbstate_t prevstate; | ||
1141 | +#endif | ||
1142 | |||
1143 | if (readlinebuffer (prevline, stdin) == 0) | ||
1144 | goto closefiles; | ||
1145 | prevfield = find_field (prevline); | ||
1146 | prevlen = prevline->length - 1 - (prevfield - prevline->buffer); | ||
1147 | +#if HAVE_MBRTOWC | ||
1148 | + prevstate = prevline->state; | ||
1149 | +#endif | ||
1150 | |||
1151 | while (!feof (stdin)) | ||
1152 | { | ||
1153 | bool match; | ||
1154 | char *thisfield; | ||
1155 | size_t thislen; | ||
1156 | +#if HAVE_MBRTOWC | ||
1157 | + mbstate_t thisstate; | ||
1158 | +#endif | ||
1159 | if (readlinebuffer (thisline, stdin) == 0) | ||
1160 | { | ||
1161 | if (ferror (stdin)) | ||
1162 | @@ -341,6 +561,15 @@ | ||
1163 | } | ||
1164 | thisfield = find_field (thisline); | ||
1165 | thislen = thisline->length - 1 - (thisfield - thisline->buffer); | ||
1166 | +#if HAVE_MBRTOWC | ||
1167 | + if (MB_CUR_MAX > 1) | ||
1168 | + { | ||
1169 | + thisstate = thisline->state; | ||
1170 | + match = !different_multi (thisfield, prevfield, | ||
1171 | + thislen, prevlen, thisstate, prevstate); | ||
1172 | + } | ||
1173 | + else | ||
1174 | +#endif | ||
1175 | match = !different (thisfield, prevfield, thislen, prevlen); | ||
1176 | match_count += match; | ||
1177 | |||
1178 | @@ -373,6 +602,9 @@ | ||
1179 | SWAP_LINES (prevline, thisline); | ||
1180 | prevfield = thisfield; | ||
1181 | prevlen = thislen; | ||
1182 | +#if HAVE_MBRTOWC | ||
1183 | + prevstate = thisstate; | ||
1184 | +#endif | ||
1185 | if (!match) | ||
1186 | match_count = 0; | ||
1187 | } | ||
1188 | @@ -417,6 +649,19 @@ | ||
1189 | |||
1190 | atexit (close_stdout); | ||
1191 | |||
1192 | +#if HAVE_MBRTOWC | ||
1193 | + if (MB_CUR_MAX > 1) | ||
1194 | + { | ||
1195 | + find_field = find_field_multi; | ||
1196 | + } | ||
1197 | + else | ||
1198 | +#endif | ||
1199 | + { | ||
1200 | + find_field = find_field_uni; | ||
1201 | + } | ||
1202 | + | ||
1203 | + | ||
1204 | + | ||
1205 | skip_chars = 0; | ||
1206 | skip_fields = 0; | ||
1207 | check_chars = SIZE_MAX; | ||
1208 | --- coreutils-6.8+/src/fold.c.i18n 2007-02-23 12:01:47.000000000 +0000 | ||
1209 | +++ coreutils-6.8+/src/fold.c 2007-03-01 15:08:24.000000000 +0000 | ||
1210 | @@ -23,11 +23,33 @@ | ||
1211 | #include <getopt.h> | ||
1212 | #include <sys/types.h> | ||
1213 | |||
1214 | +/* Get mbstate_t, mbrtowc(), wcwidth(). */ | ||
1215 | +#if HAVE_WCHAR_H | ||
1216 | +# include <wchar.h> | ||
1217 | +#endif | ||
1218 | + | ||
1219 | +/* Get iswprint(), iswblank(), wcwidth(). */ | ||
1220 | +#if HAVE_WCTYPE_H | ||
1221 | +# include <wctype.h> | ||
1222 | +#endif | ||
1223 | + | ||
1224 | #include "system.h" | ||
1225 | #include "error.h" | ||
1226 | #include "quote.h" | ||
1227 | #include "xstrtol.h" | ||
1228 | |||
1229 | +/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC | ||
1230 | + installation; work around this configuration error. */ | ||
1231 | +#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 | ||
1232 | +# undef MB_LEN_MAX | ||
1233 | +# define MB_LEN_MAX 16 | ||
1234 | +#endif | ||
1235 | + | ||
1236 | +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ | ||
1237 | +#if HAVE_MBRTOWC && defined mbstate_t | ||
1238 | +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) | ||
1239 | +#endif | ||
1240 | + | ||
1241 | #define TAB_WIDTH 8 | ||
1242 | |||
1243 | /* The official name of this program (e.g., no `g' prefix). */ | ||
1244 | @@ -35,23 +57,44 @@ | ||
1245 | |||
1246 | #define AUTHORS "David MacKenzie" | ||
1247 | |||
1248 | +#define FATAL_ERROR(Message) \ | ||
1249 | + do \ | ||
1250 | + { \ | ||
1251 | + error (0, 0, (Message)); \ | ||
1252 | + usage (2); \ | ||
1253 | + } \ | ||
1254 | + while (0) | ||
1255 | + | ||
1256 | +enum operating_mode | ||
1257 | +{ | ||
1258 | + /* Fold texts by columns that are at the given positions. */ | ||
1259 | + column_mode, | ||
1260 | + | ||
1261 | + /* Fold texts by bytes that are at the given positions. */ | ||
1262 | + byte_mode, | ||
1263 | + | ||
1264 | + /* Fold texts by characters that are at the given positions. */ | ||
1265 | + character_mode, | ||
1266 | +}; | ||
1267 | + | ||
1268 | /* The name this program was run with. */ | ||
1269 | char *program_name; | ||
1270 | |||
1271 | +/* The argument shows current mode. (Default: column_mode) */ | ||
1272 | +static enum operating_mode operating_mode; | ||
1273 | + | ||
1274 | /* If nonzero, try to break on whitespace. */ | ||
1275 | static bool break_spaces; | ||
1276 | |||
1277 | -/* If nonzero, count bytes, not column positions. */ | ||
1278 | -static bool count_bytes; | ||
1279 | - | ||
1280 | /* If nonzero, at least one of the files we read was standard input. */ | ||
1281 | static bool have_read_stdin; | ||
1282 | |||
1283 | -static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::"; | ||
1284 | +static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::"; | ||
1285 | |||
1286 | static struct option const longopts[] = | ||
1287 | { | ||
1288 | {"bytes", no_argument, NULL, 'b'}, | ||
1289 | + {"characters", no_argument, NULL, 'c'}, | ||
1290 | {"spaces", no_argument, NULL, 's'}, | ||
1291 | {"width", required_argument, NULL, 'w'}, | ||
1292 | {GETOPT_HELP_OPTION_DECL}, | ||
1293 | @@ -81,6 +124,7 @@ | ||
1294 | "), stdout); | ||
1295 | fputs (_("\ | ||
1296 | -b, --bytes count bytes rather than columns\n\ | ||
1297 | + -c, --characters count characters rather than columns\n\ | ||
1298 | -s, --spaces break at spaces\n\ | ||
1299 | -w, --width=WIDTH use WIDTH columns instead of 80\n\ | ||
1300 | "), stdout); | ||
1301 | @@ -98,7 +142,7 @@ | ||
1302 | static size_t | ||
1303 | adjust_column (size_t column, char c) | ||
1304 | { | ||
1305 | - if (!count_bytes) | ||
1306 | + if (operating_mode != byte_mode) | ||
1307 | { | ||
1308 | if (c == '\b') | ||
1309 | { | ||
1310 | @@ -121,30 +165,14 @@ | ||
1311 | to stdout, with maximum line length WIDTH. | ||
1312 | Return true if successful. */ | ||
1313 | |||
1314 | -static bool | ||
1315 | -fold_file (char const *filename, size_t width) | ||
1316 | +static void | ||
1317 | +fold_text (FILE *istream, size_t width, int *saved_errno) | ||
1318 | { | ||
1319 | - FILE *istream; | ||
1320 | int c; | ||
1321 | size_t column = 0; /* Screen column where next char will go. */ | ||
1322 | size_t offset_out = 0; /* Index in `line_out' for next char. */ | ||
1323 | static char *line_out = NULL; | ||
1324 | static size_t allocated_out = 0; | ||
1325 | - int saved_errno; | ||
1326 | - | ||
1327 | - if (STREQ (filename, "-")) | ||
1328 | - { | ||
1329 | - istream = stdin; | ||
1330 | - have_read_stdin = true; | ||
1331 | - } | ||
1332 | - else | ||
1333 | - istream = fopen (filename, "r"); | ||
1334 | - | ||
1335 | - if (istream == NULL) | ||
1336 | - { | ||
1337 | - error (0, errno, "%s", filename); | ||
1338 | - return false; | ||
1339 | - } | ||
1340 | |||
1341 | while ((c = getc (istream)) != EOF) | ||
1342 | { | ||
1343 | @@ -172,6 +200,15 @@ | ||
1344 | bool found_blank = false; | ||
1345 | size_t logical_end = offset_out; | ||
1346 | |||
1347 | + /* If LINE_OUT has no wide character, | ||
1348 | + put a new wide character in LINE_OUT | ||
1349 | + if column is bigger than width. */ | ||
1350 | + if (offset_out == 0) | ||
1351 | + { | ||
1352 | + line_out[offset_out++] = c; | ||
1353 | + continue; | ||
1354 | + } | ||
1355 | + | ||
1356 | /* Look for the last blank. */ | ||
1357 | while (logical_end) | ||
1358 | { | ||
1359 | @@ -218,11 +255,225 @@ | ||
1360 | line_out[offset_out++] = c; | ||
1361 | } | ||
1362 | |||
1363 | - saved_errno = errno; | ||
1364 | + *saved_errno = errno; | ||
1365 | + | ||
1366 | + if (offset_out) | ||
1367 | + fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); | ||
1368 | + | ||
1369 | + free(line_out); | ||
1370 | +} | ||
1371 | + | ||
1372 | +#if HAVE_MBRTOWC | ||
1373 | +static void | ||
1374 | +fold_multibyte_text (FILE *istream, size_t width, int *saved_errno) | ||
1375 | +{ | ||
1376 | + char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ | ||
1377 | + size_t buflen = 0; /* The length of the byte sequence in buf. */ | ||
1378 | + char *bufpos; /* Next read position of BUF. */ | ||
1379 | + wint_t wc; /* A gotten wide character. */ | ||
1380 | + size_t mblength; /* The byte size of a multibyte character which shows | ||
1381 | + as same character as WC. */ | ||
1382 | + mbstate_t state, state_bak; /* State of the stream. */ | ||
1383 | + int convfail; /* 1, when conversion is failed. Otherwise 0. */ | ||
1384 | + | ||
1385 | + char *line_out = NULL; | ||
1386 | + size_t offset_out = 0; /* Index in `line_out' for next char. */ | ||
1387 | + size_t allocated_out = 0; | ||
1388 | + | ||
1389 | + int increment; | ||
1390 | + size_t column = 0; | ||
1391 | + | ||
1392 | + size_t last_blank_pos; | ||
1393 | + size_t last_blank_column; | ||
1394 | + int is_blank_seen; | ||
1395 | + int last_blank_increment; | ||
1396 | + int is_bs_following_last_blank; | ||
1397 | + size_t bs_following_last_blank_num; | ||
1398 | + int is_cr_after_last_blank; | ||
1399 | + | ||
1400 | +#define CLEAR_FLAGS \ | ||
1401 | + do \ | ||
1402 | + { \ | ||
1403 | + last_blank_pos = 0; \ | ||
1404 | + last_blank_column = 0; \ | ||
1405 | + is_blank_seen = 0; \ | ||
1406 | + is_bs_following_last_blank = 0; \ | ||
1407 | + bs_following_last_blank_num = 0; \ | ||
1408 | + is_cr_after_last_blank = 0; \ | ||
1409 | + } \ | ||
1410 | + while (0) | ||
1411 | + | ||
1412 | +#define START_NEW_LINE \ | ||
1413 | + do \ | ||
1414 | + { \ | ||
1415 | + putchar ('\n'); \ | ||
1416 | + column = 0; \ | ||
1417 | + offset_out = 0; \ | ||
1418 | + CLEAR_FLAGS; \ | ||
1419 | + } \ | ||
1420 | + while (0) | ||
1421 | + | ||
1422 | + CLEAR_FLAGS; | ||
1423 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
1424 | + | ||
1425 | + for (;; bufpos += mblength, buflen -= mblength) | ||
1426 | + { | ||
1427 | + if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream)) | ||
1428 | + { | ||
1429 | + memmove (buf, bufpos, buflen); | ||
1430 | + buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream); | ||
1431 | + bufpos = buf; | ||
1432 | + } | ||
1433 | + | ||
1434 | + if (buflen < 1) | ||
1435 | + break; | ||
1436 | + | ||
1437 | + /* Get a wide character. */ | ||
1438 | + convfail = 0; | ||
1439 | + state_bak = state; | ||
1440 | + mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state); | ||
1441 | + | ||
1442 | + switch (mblength) | ||
1443 | + { | ||
1444 | + case (size_t)-1: | ||
1445 | + case (size_t)-2: | ||
1446 | + convfail++; | ||
1447 | + state = state_bak; | ||
1448 | + /* Fall through. */ | ||
1449 | + | ||
1450 | + case 0: | ||
1451 | + mblength = 1; | ||
1452 | + break; | ||
1453 | + } | ||
1454 | + | ||
1455 | +rescan: | ||
1456 | + if (operating_mode == byte_mode) /* byte mode */ | ||
1457 | + increment = mblength; | ||
1458 | + else if (operating_mode == character_mode) /* character mode */ | ||
1459 | + increment = 1; | ||
1460 | + else /* column mode */ | ||
1461 | + { | ||
1462 | + if (convfail) | ||
1463 | + increment = 1; | ||
1464 | + else | ||
1465 | + { | ||
1466 | + switch (wc) | ||
1467 | + { | ||
1468 | + case L'\n': | ||
1469 | + fwrite (line_out, sizeof(char), offset_out, stdout); | ||
1470 | + START_NEW_LINE; | ||
1471 | + continue; | ||
1472 | + | ||
1473 | + case L'\b': | ||
1474 | + increment = (column > 0) ? -1 : 0; | ||
1475 | + break; | ||
1476 | + | ||
1477 | + case L'\r': | ||
1478 | + increment = -1 * column; | ||
1479 | + break; | ||
1480 | + | ||
1481 | + case L'\t': | ||
1482 | + increment = 8 - column % 8; | ||
1483 | + break; | ||
1484 | + | ||
1485 | + default: | ||
1486 | + increment = wcwidth (wc); | ||
1487 | + increment = (increment < 0) ? 0 : increment; | ||
1488 | + } | ||
1489 | + } | ||
1490 | + } | ||
1491 | + | ||
1492 | + if (column + increment > width && break_spaces && last_blank_pos) | ||
1493 | + { | ||
1494 | + fwrite (line_out, sizeof(char), last_blank_pos, stdout); | ||
1495 | + putchar ('\n'); | ||
1496 | + | ||
1497 | + offset_out = offset_out - last_blank_pos; | ||
1498 | + column = column - last_blank_column + ((is_cr_after_last_blank) | ||
1499 | + ? last_blank_increment : bs_following_last_blank_num); | ||
1500 | + memmove (line_out, line_out + last_blank_pos, offset_out); | ||
1501 | + CLEAR_FLAGS; | ||
1502 | + goto rescan; | ||
1503 | + } | ||
1504 | + | ||
1505 | + if (column + increment > width && column != 0) | ||
1506 | + { | ||
1507 | + fwrite (line_out, sizeof(char), offset_out, stdout); | ||
1508 | + START_NEW_LINE; | ||
1509 | + goto rescan; | ||
1510 | + } | ||
1511 | + | ||
1512 | + if (allocated_out < offset_out + mblength) | ||
1513 | + { | ||
1514 | + allocated_out += 1024; | ||
1515 | + line_out = xrealloc (line_out, allocated_out); | ||
1516 | + } | ||
1517 | + | ||
1518 | + memcpy (line_out + offset_out, bufpos, mblength); | ||
1519 | + offset_out += mblength; | ||
1520 | + column += increment; | ||
1521 | + | ||
1522 | + if (is_blank_seen && !convfail && wc == L'\r') | ||
1523 | + is_cr_after_last_blank = 1; | ||
1524 | + | ||
1525 | + if (is_bs_following_last_blank && !convfail && wc == L'\b') | ||
1526 | + ++bs_following_last_blank_num; | ||
1527 | + else | ||
1528 | + is_bs_following_last_blank = 0; | ||
1529 | + | ||
1530 | + if (break_spaces && !convfail && iswblank (wc)) | ||
1531 | + { | ||
1532 | + last_blank_pos = offset_out; | ||
1533 | + last_blank_column = column; | ||
1534 | + is_blank_seen = 1; | ||
1535 | + last_blank_increment = increment; | ||
1536 | + is_bs_following_last_blank = 1; | ||
1537 | + bs_following_last_blank_num = 0; | ||
1538 | + is_cr_after_last_blank = 0; | ||
1539 | + } | ||
1540 | + } | ||
1541 | + | ||
1542 | + *saved_errno = errno; | ||
1543 | |||
1544 | if (offset_out) | ||
1545 | fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); | ||
1546 | |||
1547 | + free(line_out); | ||
1548 | +} | ||
1549 | +#endif | ||
1550 | + | ||
1551 | +/* Fold file FILENAME, or standard input if FILENAME is "-", | ||
1552 | + to stdout, with maximum line length WIDTH. | ||
1553 | + Return 0 if successful, 1 if an error occurs. */ | ||
1554 | + | ||
1555 | +static bool | ||
1556 | +fold_file (char *filename, size_t width) | ||
1557 | +{ | ||
1558 | + FILE *istream; | ||
1559 | + int saved_errno; | ||
1560 | + | ||
1561 | + if (STREQ (filename, "-")) | ||
1562 | + { | ||
1563 | + istream = stdin; | ||
1564 | + have_read_stdin = 1; | ||
1565 | + } | ||
1566 | + else | ||
1567 | + istream = fopen (filename, "r"); | ||
1568 | + | ||
1569 | + if (istream == NULL) | ||
1570 | + { | ||
1571 | + error (0, errno, "%s", filename); | ||
1572 | + return 1; | ||
1573 | + } | ||
1574 | + | ||
1575 | + /* Define how ISTREAM is being folded. */ | ||
1576 | +#if HAVE_MBRTOWC | ||
1577 | + if (MB_CUR_MAX > 1) | ||
1578 | + fold_multibyte_text (istream, width, &saved_errno); | ||
1579 | + else | ||
1580 | +#endif | ||
1581 | + fold_text (istream, width, &saved_errno); | ||
1582 | + | ||
1583 | if (ferror (istream)) | ||
1584 | { | ||
1585 | error (0, saved_errno, "%s", filename); | ||
1586 | @@ -255,7 +506,8 @@ | ||
1587 | |||
1588 | atexit (close_stdout); | ||
1589 | |||
1590 | - break_spaces = count_bytes = have_read_stdin = false; | ||
1591 | + operating_mode = column_mode; | ||
1592 | + break_spaces = have_read_stdin = false; | ||
1593 | |||
1594 | while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) | ||
1595 | { | ||
1596 | @@ -264,7 +516,15 @@ | ||
1597 | switch (optc) | ||
1598 | { | ||
1599 | case 'b': /* Count bytes rather than columns. */ | ||
1600 | - count_bytes = true; | ||
1601 | + if (operating_mode != column_mode) | ||
1602 | + FATAL_ERROR (_("only one way of folding may be specified")); | ||
1603 | + operating_mode = byte_mode; | ||
1604 | + break; | ||
1605 | + | ||
1606 | + case 'c': | ||
1607 | + if (operating_mode != column_mode) | ||
1608 | + FATAL_ERROR (_("only one way of folding may be specified")); | ||
1609 | + operating_mode = character_mode; | ||
1610 | break; | ||
1611 | |||
1612 | case 's': /* Break at word boundaries. */ | ||
1613 | --- coreutils-6.8+/src/sort.c.i18n 2007-02-24 11:23:23.000000000 +0000 | ||
1614 | +++ coreutils-6.8+/src/sort.c 2007-03-01 15:10:57.000000000 +0000 | ||
1615 | @@ -23,10 +23,19 @@ | ||
1616 | |||
1617 | #include <config.h> | ||
1618 | |||
1619 | +#include <assert.h> | ||
1620 | #include <getopt.h> | ||
1621 | #include <sys/types.h> | ||
1622 | #include <sys/wait.h> | ||
1623 | #include <signal.h> | ||
1624 | +#if HAVE_WCHAR_H | ||
1625 | +# include <wchar.h> | ||
1626 | +#endif | ||
1627 | +/* Get isw* functions. */ | ||
1628 | +#if HAVE_WCTYPE_H | ||
1629 | +# include <wctype.h> | ||
1630 | +#endif | ||
1631 | + | ||
1632 | #include "system.h" | ||
1633 | #include "argmatch.h" | ||
1634 | #include "error.h" | ||
1635 | @@ -116,14 +125,38 @@ | ||
1636 | /* Thousands separator; if -1, then there isn't one. */ | ||
1637 | static int thousands_sep; | ||
1638 | |||
1639 | +static int force_general_numcompare = 0; | ||
1640 | + | ||
1641 | /* Nonzero if the corresponding locales are hard. */ | ||
1642 | static bool hard_LC_COLLATE; | ||
1643 | -#if HAVE_NL_LANGINFO | ||
1644 | +#if HAVE_LANGINFO_CODESET | ||
1645 | static bool hard_LC_TIME; | ||
1646 | #endif | ||
1647 | |||
1648 | #define NONZERO(x) ((x) != 0) | ||
1649 | |||
1650 | +/* get a multibyte character's byte length. */ | ||
1651 | +#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE) \ | ||
1652 | + do \ | ||
1653 | + { \ | ||
1654 | + wchar_t wc; \ | ||
1655 | + mbstate_t state_bak; \ | ||
1656 | + \ | ||
1657 | + state_bak = STATE; \ | ||
1658 | + mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE); \ | ||
1659 | + \ | ||
1660 | + switch (MBLENGTH) \ | ||
1661 | + { \ | ||
1662 | + case (size_t)-1: \ | ||
1663 | + case (size_t)-2: \ | ||
1664 | + STATE = state_bak; \ | ||
1665 | + /* Fall through. */ \ | ||
1666 | + case 0: \ | ||
1667 | + MBLENGTH = 1; \ | ||
1668 | + } \ | ||
1669 | + } \ | ||
1670 | + while (0) | ||
1671 | + | ||
1672 | /* The kind of blanks for '-b' to skip in various options. */ | ||
1673 | enum blanktype { bl_start, bl_end, bl_both }; | ||
1674 | |||
1675 | @@ -261,13 +294,11 @@ | ||
1676 | they were read if all keys compare equal. */ | ||
1677 | static bool stable; | ||
1678 | |||
1679 | -/* If TAB has this value, blanks separate fields. */ | ||
1680 | -enum { TAB_DEFAULT = CHAR_MAX + 1 }; | ||
1681 | - | ||
1682 | -/* Tab character separating fields. If TAB_DEFAULT, then fields are | ||
1683 | +/* Tab character separating fields. If tab_length is 0, then fields are | ||
1684 | separated by the empty string between a non-blank character and a blank | ||
1685 | character. */ | ||
1686 | -static int tab = TAB_DEFAULT; | ||
1687 | +static char tab[MB_LEN_MAX + 1]; | ||
1688 | +static size_t tab_length = 0; | ||
1689 | |||
1690 | /* Flag to remove consecutive duplicate lines from the output. | ||
1691 | Only the last of a sequence of equal lines will be output. */ | ||
1692 | @@ -639,6 +670,44 @@ | ||
1693 | update_proc (pid); | ||
1694 | } | ||
1695 | |||
1696 | +/* Function pointers. */ | ||
1697 | +static void | ||
1698 | +(*inittables) (void); | ||
1699 | +static char * | ||
1700 | +(*begfield) (const struct line*, const struct keyfield *); | ||
1701 | +static char * | ||
1702 | +(*limfield) (const struct line*, const struct keyfield *); | ||
1703 | +static int | ||
1704 | +(*getmonth) (char const *, size_t); | ||
1705 | +static int | ||
1706 | +(*keycompare) (const struct line *, const struct line *); | ||
1707 | +static int | ||
1708 | +(*numcompare) (const char *, const char *); | ||
1709 | + | ||
1710 | +/* Test for white space multibyte character. | ||
1711 | + Set LENGTH the byte length of investigated multibyte character. */ | ||
1712 | +#if HAVE_MBRTOWC | ||
1713 | +static int | ||
1714 | +ismbblank (const char *str, size_t len, size_t *length) | ||
1715 | +{ | ||
1716 | + size_t mblength; | ||
1717 | + wchar_t wc; | ||
1718 | + mbstate_t state; | ||
1719 | + | ||
1720 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
1721 | + mblength = mbrtowc (&wc, str, len, &state); | ||
1722 | + | ||
1723 | + if (mblength == (size_t)-1 || mblength == (size_t)-2) | ||
1724 | + { | ||
1725 | + *length = 1; | ||
1726 | + return 0; | ||
1727 | + } | ||
1728 | + | ||
1729 | + *length = (mblength < 1) ? 1 : mblength; | ||
1730 | + return iswblank (wc); | ||
1731 | +} | ||
1732 | +#endif | ||
1733 | + | ||
1734 | /* Clean up any remaining temporary files. */ | ||
1735 | |||
1736 | static void | ||
1737 | @@ -978,7 +1047,7 @@ | ||
1738 | free (node); | ||
1739 | } | ||
1740 | |||
1741 | -#if HAVE_NL_LANGINFO | ||
1742 | +#if HAVE_LANGINFO_CODESET | ||
1743 | |||
1744 | static int | ||
1745 | struct_month_cmp (const void *m1, const void *m2) | ||
1746 | @@ -993,7 +1062,7 @@ | ||
1747 | /* Initialize the character class tables. */ | ||
1748 | |||
1749 | static void | ||
1750 | -inittables (void) | ||
1751 | +inittables_uni (void) | ||
1752 | { | ||
1753 | size_t i; | ||
1754 | |||
1755 | @@ -1005,7 +1074,7 @@ | ||
1756 | fold_toupper[i] = toupper (i); | ||
1757 | } | ||
1758 | |||
1759 | -#if HAVE_NL_LANGINFO | ||
1760 | +#if HAVE_LANGINFO_CODESET | ||
1761 | /* If we're not in the "C" locale, read different names for months. */ | ||
1762 | if (hard_LC_TIME) | ||
1763 | { | ||
1764 | @@ -1031,6 +1100,64 @@ | ||
1765 | #endif | ||
1766 | } | ||
1767 | |||
1768 | +#if HAVE_MBRTOWC | ||
1769 | +static void | ||
1770 | +inittables_mb (void) | ||
1771 | +{ | ||
1772 | + int i, j, k, l; | ||
1773 | + char *name, *s; | ||
1774 | + size_t s_len, mblength; | ||
1775 | + char mbc[MB_LEN_MAX]; | ||
1776 | + wchar_t wc, pwc; | ||
1777 | + mbstate_t state_mb, state_wc; | ||
1778 | + | ||
1779 | + for (i = 0; i < MONTHS_PER_YEAR; i++) | ||
1780 | + { | ||
1781 | + s = (char *) nl_langinfo (ABMON_1 + i); | ||
1782 | + s_len = strlen (s); | ||
1783 | + monthtab[i].name = name = (char *) xmalloc (s_len + 1); | ||
1784 | + monthtab[i].val = i + 1; | ||
1785 | + | ||
1786 | + memset (&state_mb, '\0', sizeof (mbstate_t)); | ||
1787 | + memset (&state_wc, '\0', sizeof (mbstate_t)); | ||
1788 | + | ||
1789 | + for (j = 0; j < s_len;) | ||
1790 | + { | ||
1791 | + if (!ismbblank (s + j, s_len - j, &mblength)) | ||
1792 | + break; | ||
1793 | + j += mblength; | ||
1794 | + } | ||
1795 | + | ||
1796 | + for (k = 0; j < s_len;) | ||
1797 | + { | ||
1798 | + mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb); | ||
1799 | + assert (mblength != (size_t)-1 && mblength != (size_t)-2); | ||
1800 | + if (mblength == 0) | ||
1801 | + break; | ||
1802 | + | ||
1803 | + pwc = towupper (wc); | ||
1804 | + if (pwc == wc) | ||
1805 | + { | ||
1806 | + memcpy (mbc, s + j, mblength); | ||
1807 | + j += mblength; | ||
1808 | + } | ||
1809 | + else | ||
1810 | + { | ||
1811 | + j += mblength; | ||
1812 | + mblength = wcrtomb (mbc, pwc, &state_wc); | ||
1813 | + assert (mblength != (size_t)0 && mblength != (size_t)-1); | ||
1814 | + } | ||
1815 | + | ||
1816 | + for (l = 0; l < mblength; l++) | ||
1817 | + name[k++] = mbc[l]; | ||
1818 | + } | ||
1819 | + name[k] = '\0'; | ||
1820 | + } | ||
1821 | + qsort ((void *) monthtab, MONTHS_PER_YEAR, | ||
1822 | + sizeof (struct month), struct_month_cmp); | ||
1823 | +} | ||
1824 | +#endif | ||
1825 | + | ||
1826 | /* Specify the amount of main memory to use when sorting. */ | ||
1827 | static void | ||
1828 | specify_sort_size (char const *s) | ||
1829 | @@ -1241,7 +1368,7 @@ | ||
1830 | by KEY in LINE. */ | ||
1831 | |||
1832 | static char * | ||
1833 | -begfield (const struct line *line, const struct keyfield *key) | ||
1834 | +begfield_uni (const struct line *line, const struct keyfield *key) | ||
1835 | { | ||
1836 | char *ptr = line->text, *lim = ptr + line->length - 1; | ||
1837 | size_t sword = key->sword; | ||
1838 | @@ -1251,10 +1378,10 @@ | ||
1839 | /* The leading field separator itself is included in a field when -t | ||
1840 | is absent. */ | ||
1841 | |||
1842 | - if (tab != TAB_DEFAULT) | ||
1843 | + if (tab_length) | ||
1844 | while (ptr < lim && sword--) | ||
1845 | { | ||
1846 | - while (ptr < lim && *ptr != tab) | ||
1847 | + while (ptr < lim && *ptr != tab[0]) | ||
1848 | ++ptr; | ||
1849 | if (ptr < lim) | ||
1850 | ++ptr; | ||
1851 | @@ -1282,11 +1409,70 @@ | ||
1852 | return ptr; | ||
1853 | } | ||
1854 | |||
1855 | +#if HAVE_MBRTOWC | ||
1856 | +static char * | ||
1857 | +begfield_mb (const struct line *line, const struct keyfield *key) | ||
1858 | +{ | ||
1859 | + int i; | ||
1860 | + char *ptr = line->text, *lim = ptr + line->length - 1; | ||
1861 | + size_t sword = key->sword; | ||
1862 | + size_t schar = key->schar; | ||
1863 | + size_t mblength; | ||
1864 | + mbstate_t state; | ||
1865 | + | ||
1866 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
1867 | + | ||
1868 | + if (tab_length) | ||
1869 | + while (ptr < lim && sword--) | ||
1870 | + { | ||
1871 | + while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) | ||
1872 | + { | ||
1873 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1874 | + ptr += mblength; | ||
1875 | + } | ||
1876 | + if (ptr < lim) | ||
1877 | + { | ||
1878 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1879 | + ptr += mblength; | ||
1880 | + } | ||
1881 | + } | ||
1882 | + else | ||
1883 | + while (ptr < lim && sword--) | ||
1884 | + { | ||
1885 | + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) | ||
1886 | + ptr += mblength; | ||
1887 | + if (ptr < lim) | ||
1888 | + { | ||
1889 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1890 | + ptr += mblength; | ||
1891 | + } | ||
1892 | + while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength)) | ||
1893 | + ptr += mblength; | ||
1894 | + } | ||
1895 | + | ||
1896 | + if (key->skipsblanks) | ||
1897 | + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) | ||
1898 | + ptr += mblength; | ||
1899 | + | ||
1900 | + for (i = 0; i < schar; i++) | ||
1901 | + { | ||
1902 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1903 | + | ||
1904 | + if (ptr + mblength > lim) | ||
1905 | + break; | ||
1906 | + else | ||
1907 | + ptr += mblength; | ||
1908 | + } | ||
1909 | + | ||
1910 | + return ptr; | ||
1911 | +} | ||
1912 | +#endif | ||
1913 | + | ||
1914 | /* Return the limit of (a pointer to the first character after) the field | ||
1915 | in LINE specified by KEY. */ | ||
1916 | |||
1917 | static char * | ||
1918 | -limfield (const struct line *line, const struct keyfield *key) | ||
1919 | +limfield_uni (const struct line *line, const struct keyfield *key) | ||
1920 | { | ||
1921 | char *ptr = line->text, *lim = ptr + line->length - 1; | ||
1922 | size_t eword = key->eword, echar = key->echar; | ||
1923 | @@ -1299,10 +1485,10 @@ | ||
1924 | `beginning' is the first character following the delimiting TAB. | ||
1925 | Otherwise, leave PTR pointing at the first `blank' character after | ||
1926 | the preceding field. */ | ||
1927 | - if (tab != TAB_DEFAULT) | ||
1928 | + if (tab_length) | ||
1929 | while (ptr < lim && eword--) | ||
1930 | { | ||
1931 | - while (ptr < lim && *ptr != tab) | ||
1932 | + while (ptr < lim && *ptr != tab[0]) | ||
1933 | ++ptr; | ||
1934 | if (ptr < lim && (eword | echar)) | ||
1935 | ++ptr; | ||
1936 | @@ -1348,10 +1534,10 @@ | ||
1937 | */ | ||
1938 | |||
1939 | /* Make LIM point to the end of (one byte past) the current field. */ | ||
1940 | - if (tab != TAB_DEFAULT) | ||
1941 | + if (tab_length) | ||
1942 | { | ||
1943 | char *newlim; | ||
1944 | - newlim = memchr (ptr, tab, lim - ptr); | ||
1945 | + newlim = memchr (ptr, tab[0], lim - ptr); | ||
1946 | if (newlim) | ||
1947 | lim = newlim; | ||
1948 | } | ||
1949 | @@ -1384,6 +1570,107 @@ | ||
1950 | return ptr; | ||
1951 | } | ||
1952 | |||
1953 | +#if HAVE_MBRTOWC | ||
1954 | +static char * | ||
1955 | +limfield_mb (const struct line *line, const struct keyfield *key) | ||
1956 | +{ | ||
1957 | + char *ptr = line->text, *lim = ptr + line->length - 1; | ||
1958 | + size_t eword = key->eword, echar = key->echar; | ||
1959 | + int i; | ||
1960 | + size_t mblength; | ||
1961 | + mbstate_t state; | ||
1962 | + | ||
1963 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
1964 | + | ||
1965 | + if (tab_length) | ||
1966 | + while (ptr < lim && eword--) | ||
1967 | + { | ||
1968 | + while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) | ||
1969 | + { | ||
1970 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1971 | + ptr += mblength; | ||
1972 | + } | ||
1973 | + if (ptr < lim && (eword | echar)) | ||
1974 | + { | ||
1975 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1976 | + ptr += mblength; | ||
1977 | + } | ||
1978 | + } | ||
1979 | + else | ||
1980 | + while (ptr < lim && eword--) | ||
1981 | + { | ||
1982 | + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) | ||
1983 | + ptr += mblength; | ||
1984 | + if (ptr < lim) | ||
1985 | + { | ||
1986 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
1987 | + ptr += mblength; | ||
1988 | + } | ||
1989 | + while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength)) | ||
1990 | + ptr += mblength; | ||
1991 | + } | ||
1992 | + | ||
1993 | + | ||
1994 | +# ifdef POSIX_UNSPECIFIED | ||
1995 | + /* Make LIM point to the end of (one byte past) the current field. */ | ||
1996 | + if (tab_length) | ||
1997 | + { | ||
1998 | + char *newlim, *p; | ||
1999 | + | ||
2000 | + newlim = NULL; | ||
2001 | + for (p = ptr; p < lim;) | ||
2002 | + { | ||
2003 | + if (memcmp (p, tab, tab_length) == 0) | ||
2004 | + { | ||
2005 | + newlim = p; | ||
2006 | + break; | ||
2007 | + } | ||
2008 | + | ||
2009 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
2010 | + p += mblength; | ||
2011 | + } | ||
2012 | + } | ||
2013 | + else | ||
2014 | + { | ||
2015 | + char *newlim; | ||
2016 | + newlim = ptr; | ||
2017 | + | ||
2018 | + while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength)) | ||
2019 | + newlim += mblength; | ||
2020 | + if (ptr < lim) | ||
2021 | + { | ||
2022 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
2023 | + ptr += mblength; | ||
2024 | + } | ||
2025 | + while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength)) | ||
2026 | + newlim += mblength; | ||
2027 | + lim = newlim; | ||
2028 | + } | ||
2029 | +# endif | ||
2030 | + | ||
2031 | + /* If we're skipping leading blanks, don't start counting characters | ||
2032 | + * until after skipping past any leading blanks. */ | ||
2033 | + if (key->skipsblanks) | ||
2034 | + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) | ||
2035 | + ptr += mblength; | ||
2036 | + | ||
2037 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
2038 | + | ||
2039 | + /* Advance PTR by ECHAR (if possible), but no further than LIM. */ | ||
2040 | + for (i = 0; i < echar; i++) | ||
2041 | + { | ||
2042 | + GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); | ||
2043 | + | ||
2044 | + if (ptr + mblength > lim) | ||
2045 | + break; | ||
2046 | + else | ||
2047 | + ptr += mblength; | ||
2048 | + } | ||
2049 | + | ||
2050 | + return ptr; | ||
2051 | +} | ||
2052 | +#endif | ||
2053 | + | ||
2054 | /* Fill BUF reading from FP, moving buf->left bytes from the end | ||
2055 | of buf->buf to the beginning first. If EOF is reached and the | ||
2056 | file wasn't terminated by a newline, supply one. Set up BUF's line | ||
2057 | @@ -1466,8 +1753,24 @@ | ||
2058 | else | ||
2059 | { | ||
2060 | if (key->skipsblanks) | ||
2061 | - while (blanks[to_uchar (*line_start)]) | ||
2062 | - line_start++; | ||
2063 | + { | ||
2064 | +#if HAVE_MBRTOWC | ||
2065 | + if (MB_CUR_MAX > 1) | ||
2066 | + { | ||
2067 | + size_t mblength; | ||
2068 | + mbstate_t state; | ||
2069 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
2070 | + while (line_start < line->keylim && | ||
2071 | + ismbblank (line_start, | ||
2072 | + line->keylim - line_start, | ||
2073 | + &mblength)) | ||
2074 | + line_start += mblength; | ||
2075 | + } | ||
2076 | + else | ||
2077 | +#endif | ||
2078 | + while (blanks[to_uchar (*line_start)]) | ||
2079 | + line_start++; | ||
2080 | + } | ||
2081 | line->keybeg = line_start; | ||
2082 | } | ||
2083 | } | ||
2084 | @@ -1500,7 +1803,7 @@ | ||
2085 | hideously fast. */ | ||
2086 | |||
2087 | static int | ||
2088 | -numcompare (const char *a, const char *b) | ||
2089 | +numcompare_uni (const char *a, const char *b) | ||
2090 | { | ||
2091 | while (blanks[to_uchar (*a)]) | ||
2092 | a++; | ||
2093 | @@ -1510,6 +1813,25 @@ | ||
2094 | return strnumcmp (a, b, decimal_point, thousands_sep); | ||
2095 | } | ||
2096 | |||
2097 | +#if HAVE_MBRTOWC | ||
2098 | +static int | ||
2099 | +numcompare_mb (const char *a, const char *b) | ||
2100 | +{ | ||
2101 | + size_t mblength, len; | ||
2102 | + len = strlen (a); /* okay for UTF-8 */ | ||
2103 | + while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength)) | ||
2104 | + { | ||
2105 | + a += mblength; | ||
2106 | + len -= mblength; | ||
2107 | + } | ||
2108 | + len = strlen (b); /* okay for UTF-8 */ | ||
2109 | + while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength)) | ||
2110 | + b += mblength; | ||
2111 | + | ||
2112 | + return strnumcmp (a, b, decimal_point, thousands_sep); | ||
2113 | +} | ||
2114 | +#endif /* HAV_EMBRTOWC */ | ||
2115 | + | ||
2116 | static int | ||
2117 | general_numcompare (const char *sa, const char *sb) | ||
2118 | { | ||
2119 | @@ -1543,7 +1865,7 @@ | ||
2120 | Return 0 if the name in S is not recognized. */ | ||
2121 | |||
2122 | static int | ||
2123 | -getmonth (char const *month, size_t len) | ||
2124 | +getmonth_uni (char const *month, size_t len) | ||
2125 | { | ||
2126 | size_t lo = 0; | ||
2127 | size_t hi = MONTHS_PER_YEAR; | ||
2128 | @@ -1698,11 +2020,79 @@ | ||
2129 | return diff; | ||
2130 | } | ||
2131 | |||
2132 | +#if HAVE_MBRTOWC | ||
2133 | +static int | ||
2134 | +getmonth_mb (const char *s, size_t len) | ||
2135 | +{ | ||
2136 | + char *month; | ||
2137 | + register size_t i; | ||
2138 | + register int lo = 0, hi = MONTHS_PER_YEAR, result; | ||
2139 | + char *tmp; | ||
2140 | + size_t wclength, mblength; | ||
2141 | + const char **pp; | ||
2142 | + const wchar_t **wpp; | ||
2143 | + wchar_t *month_wcs; | ||
2144 | + mbstate_t state; | ||
2145 | + | ||
2146 | + while (len > 0 && ismbblank (s, len, &mblength)) | ||
2147 | + { | ||
2148 | + s += mblength; | ||
2149 | + len -= mblength; | ||
2150 | + } | ||
2151 | + | ||
2152 | + if (len == 0) | ||
2153 | + return 0; | ||
2154 | + | ||
2155 | + month = (char *) alloca (len + 1); | ||
2156 | + | ||
2157 | + tmp = (char *) alloca (len + 1); | ||
2158 | + memcpy (tmp, s, len); | ||
2159 | + tmp[len] = '\0'; | ||
2160 | + pp = (const char **)&tmp; | ||
2161 | + month_wcs = (wchar_t *) alloca ((len + 1) * sizeof (wchar_t)); | ||
2162 | + memset (&state, '\0', sizeof(mbstate_t)); | ||
2163 | + | ||
2164 | + wclength = mbsrtowcs (month_wcs, pp, len + 1, &state); | ||
2165 | + assert (wclength != (size_t)-1 && *pp == NULL); | ||
2166 | + | ||
2167 | + for (i = 0; i < wclength; i++) | ||
2168 | + { | ||
2169 | + month_wcs[i] = towupper(month_wcs[i]); | ||
2170 | + if (iswblank (month_wcs[i])) | ||
2171 | + { | ||
2172 | + month_wcs[i] = L'\0'; | ||
2173 | + break; | ||
2174 | + } | ||
2175 | + } | ||
2176 | + | ||
2177 | + wpp = (const wchar_t **)&month_wcs; | ||
2178 | + | ||
2179 | + mblength = wcsrtombs (month, wpp, len + 1, &state); | ||
2180 | + assert (mblength != (-1) && *wpp == NULL); | ||
2181 | + | ||
2182 | + do | ||
2183 | + { | ||
2184 | + int ix = (lo + hi) / 2; | ||
2185 | + | ||
2186 | + if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0) | ||
2187 | + hi = ix; | ||
2188 | + else | ||
2189 | + lo = ix; | ||
2190 | + } | ||
2191 | + while (hi - lo > 1); | ||
2192 | + | ||
2193 | + result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name)) | ||
2194 | + ? monthtab[lo].val : 0); | ||
2195 | + | ||
2196 | + return result; | ||
2197 | +} | ||
2198 | +#endif | ||
2199 | + | ||
2200 | /* Compare two lines A and B trying every key in sequence until there | ||
2201 | are no more keys or a difference is found. */ | ||
2202 | |||
2203 | static int | ||
2204 | -keycompare (const struct line *a, const struct line *b) | ||
2205 | +keycompare_uni (const struct line *a, const struct line *b) | ||
2206 | { | ||
2207 | struct keyfield const *key = keylist; | ||
2208 | |||
2209 | @@ -1875,6 +2265,179 @@ | ||
2210 | return key->reverse ? -diff : diff; | ||
2211 | } | ||
2212 | |||
2213 | +#if HAVE_MBRTOWC | ||
2214 | +static int | ||
2215 | +keycompare_mb (const struct line *a, const struct line *b) | ||
2216 | +{ | ||
2217 | + struct keyfield *key = keylist; | ||
2218 | + | ||
2219 | + /* For the first iteration only, the key positions have been | ||
2220 | + precomputed for us. */ | ||
2221 | + char *texta = a->keybeg; | ||
2222 | + char *textb = b->keybeg; | ||
2223 | + char *lima = a->keylim; | ||
2224 | + char *limb = b->keylim; | ||
2225 | + | ||
2226 | + size_t mblength_a, mblength_b; | ||
2227 | + wchar_t wc_a, wc_b; | ||
2228 | + mbstate_t state_a, state_b; | ||
2229 | + | ||
2230 | + int diff; | ||
2231 | + | ||
2232 | + memset (&state_a, '\0', sizeof(mbstate_t)); | ||
2233 | + memset (&state_b, '\0', sizeof(mbstate_t)); | ||
2234 | + | ||
2235 | + for (;;) | ||
2236 | + { | ||
2237 | + unsigned char *translate = (unsigned char *) key->translate; | ||
2238 | + bool const *ignore = key->ignore; | ||
2239 | + | ||
2240 | + /* Find the lengths. */ | ||
2241 | + size_t lena = lima <= texta ? 0 : lima - texta; | ||
2242 | + size_t lenb = limb <= textb ? 0 : limb - textb; | ||
2243 | + | ||
2244 | + /* Actually compare the fields. */ | ||
2245 | + if (key->random) | ||
2246 | + diff = compare_random (texta, lena, textb, lenb); | ||
2247 | + else if (key->numeric | key->general_numeric) | ||
2248 | + { | ||
2249 | + char savea = *lima, saveb = *limb; | ||
2250 | + | ||
2251 | + *lima = *limb = '\0'; | ||
2252 | + if (force_general_numcompare) | ||
2253 | + diff = general_numcompare (texta, textb); | ||
2254 | + else | ||
2255 | + diff = ((key->numeric ? numcompare : general_numcompare) | ||
2256 | + (texta, textb)); | ||
2257 | + *lima = savea, *limb = saveb; | ||
2258 | + } | ||