wok-next rev 20436

Update packages listed in the LFS book.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Wed Feb 21 19:48:17 2018 +0200 (2018-02-21)
parents c3c324c07d3f
children efd5fe5db61e
files acl/receipt attr/receipt autoconf/receipt automake/receipt bash/receipt bc/receipt bc/stuff/fix-libmath_h bc/stuff/patches/bc-1.06.95-memory_leak-1.patch bc/stuff/patches/series binutils/receipt bison/receipt bzip2/receipt bzip2/stuff/patches/bzip2-1.0.4-bzip2recover.patch bzip2/stuff/patches/bzip2-1.0.6-fix_install.patch bzip2/stuff/patches/bzip2recover-CVE-2016-3189.patch bzip2/stuff/patches/series check/receipt coreutils-multicall/description.txt coreutils-multicall/receipt coreutils-multicall/stuff coreutils/receipt coreutils/stuff/patches/README coreutils/stuff/patches/coreutils-8.25-i18n-2.patch coreutils/stuff/patches/coreutils-8.27-i18n-1.patch coreutils/stuff/patches/coreutils-8.29-i18n-1.patch coreutils/stuff/patches/coreutils-fix-po.patch coreutils/stuff/patches/series diffutils/receipt e2fsprogs/receipt eudev/receipt expat/receipt file/receipt findutils/receipt flex/receipt gawk/receipt gcc/receipt gdbm/receipt gettext/receipt glibc/receipt glibc/stuff/ld.so.conf glibc/stuff/patches/glibc-2.25-fhs-1.patch glibc/stuff/patches/glibc-2.26-fhs-1.patch glibc/stuff/patches/glibc-po.patch glibc/stuff/patches/series gmp/receipt gperf/receipt grep/receipt groff/receipt grub2/receipt gzip/receipt iana-etc/receipt inetutils/receipt intltool/receipt iproute2/receipt kbd/receipt kmod/receipt less/receipt libcap/receipt libpipeline/receipt libtool/receipt linux-dev/receipt linux-dev/stuff/menuconfig.in linux-dev/stuff/mini.config linux-dev/stuff/vm-uml.in m4/receipt make/receipt man-db/receipt man-pages/receipt mpc-library/receipt mpfr/receipt ncurses/receipt patch/receipt perl-xml-parser/receipt perl/receipt perl/stuff/microperl.patch perl/stuff/miniperlmain.patch pkg-config/receipt procps-ng/receipt psmisc/receipt readline/receipt sed/receipt shadow/receipt sysklogd/receipt tar/receipt texinfo/receipt util-linux/receipt xz/receipt zlib/receipt
line diff
     1.1 --- a/acl/receipt	Wed Feb 21 18:10:55 2018 +0200
     1.2 +++ b/acl/receipt	Wed Feb 21 19:48:17 2018 +0200
     1.3 @@ -3,23 +3,20 @@
     1.4  PACKAGE="acl"
     1.5  VERSION="2.2.52"
     1.6  CATEGORY="system-tools"
     1.7 -SHORT_DESC="Commands for Manipulating POSIX Access Control Lists"
     1.8 +SHORT_DESC="Commands for manipulating POSIX Access Control Lists"
     1.9  MAINTAINER="rcx@zoominternet.net"
    1.10  LICENSE="LGPL2.1 GPL2"
    1.11  WEB_SITE="http://savannah.nongnu.org/projects/acl/"
    1.12 -HOST_ARCH="i486 arm"
    1.13 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/acl.html"
    1.14  
    1.15  TARBALL="$PACKAGE-$VERSION.src.tar.gz"
    1.16 -WGET_URL="http://download.savannah.gnu.org/releases/$PACKAGE/$TARBALL"
    1.17 +WGET_URL="http://download.savannah.gnu.org/releases/acl/$TARBALL"
    1.18  
    1.19  BUILD_DEPENDS="attr-dev bash libtool gettext"
    1.20 -BUILD_DEPENDS_arm="attr-dev"
    1.21  SPLIT="acl-dev"
    1.22  
    1.23 -# Rules to configure and make the package.
    1.24 -compile_rules()
    1.25 -{
    1.26 -	rm /bin/rpm
    1.27 +compile_rules() {
    1.28 +	rm /bin/rpm 2>/dev/null
    1.29  	sed -i -e 's|/@pkg_name@|&-@pkg_version@|' include/builddefs.in
    1.30  	sed -i -e "/TABS-1;/a if (x > (TABS-1)) x = (TABS-1);" \
    1.31  		libacl/__acl_to_any_text.c
    1.32 @@ -30,24 +27,23 @@
    1.33  		--libexecdir=/usr/lib \
    1.34  		$CONFIGURE_ARGS &&
    1.35  	make &&
    1.36 -	make install install-lib install-dev DIST_ROOT=$DESTDIR
    1.37 +	make install install-lib install-dev DIST_ROOT=$DESTDIR || return 1
    1.38  
    1.39 -	mkdir $install/lib
    1.40 +	mkdir -p $install/lib
    1.41  	mv -v $install/usr/lib/libacl.so.* $install/lib
    1.42  	ln -sfv ../../lib/$(readlink $install/usr/lib/libacl.so) \
    1.43  		$install/usr/lib/libacl.so
    1.44 +
    1.45  	find $install -type f \( -name '*.so*' -o -name '*.la' \) \
    1.46  		-exec chmod 755 \{\} \;
    1.47 -
    1.48  }
    1.49  
    1.50 -# Rules to gen a SliTaz package suitable for Tazpkg.
    1.51 -genpkg_rules()
    1.52 -{
    1.53 +genpkg_rules() {
    1.54  	case $PACKAGE in
    1.55  		acl)
    1.56  			copy @std
    1.57  			DEPENDS="attr"
    1.58 +			TAGS="LFS"
    1.59  			;;
    1.60  		acl-dev)
    1.61  			copy @dev
     2.1 --- a/attr/receipt	Wed Feb 21 18:10:55 2018 +0200
     2.2 +++ b/attr/receipt	Wed Feb 21 19:48:17 2018 +0200
     2.3 @@ -3,23 +3,21 @@
     2.4  PACKAGE="attr"
     2.5  VERSION="2.4.47"
     2.6  CATEGORY="system-tools"
     2.7 -SHORT_DESC="Commands for Manipulating Filesystem Extended Attributes"
     2.8 +SHORT_DESC="Commands for manipulating filesystem extended attributes"
     2.9  MAINTAINER="rcx@zoominternet.net"
    2.10  LICENSE="GPL2"
    2.11  WEB_SITE="http://savannah.nongnu.org/projects/attr"
    2.12 -HOST_ARCH="i486 arm"
    2.13 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/attr.html"
    2.14  
    2.15  TARBALL="$PACKAGE-$VERSION.src.tar.gz"
    2.16 -WGET_URL="http://download.savannah.gnu.org/releases/$PACKAGE/$TARBALL"
    2.17 +WGET_URL="http://download.savannah.gnu.org/releases/attr/$TARBALL"
    2.18  
    2.19 +BUILD_DEPENDS_arm=" "
    2.20  BUILD_DEPENDS="autoconf automake m4 libtool gettext coreutils-operations"
    2.21 -BUILD_DEPENDS_arm=" "
    2.22  SPLIT="attr-dev"
    2.23  
    2.24 -# Rules to configure and make the package.
    2.25 -compile_rules()
    2.26 -{
    2.27 -	rm /bin/rpm
    2.28 +compile_rules() {
    2.29 +	rm /bin/rpm >/dev/null
    2.30  	sed -i -e 's|/@pkg_name@|&-@pkg_version@|' include/builddefs.in
    2.31  
    2.32  	./configure \
    2.33 @@ -27,21 +25,23 @@
    2.34  		--disable-static \
    2.35  		$CONFIGURE_ARGS &&
    2.36  	make &&
    2.37 -	make install install-lib install-dev DIST_ROOT=$DESTDIR
    2.38 +	make install install-lib install-dev DIST_ROOT=$DESTDIR || return 1
    2.39  
    2.40  	mkdir -p $install/lib
    2.41  	mv $install/usr/lib/libattr.so.* $install/lib
    2.42  	ln -sf ../../lib/$(readlink $install/usr/lib/libattr.so) \
    2.43  		$install/usr/lib/libattr.so
    2.44 +
    2.45  	find $install -type f \( -name '*.so*' -o -name '*.la' \) \
    2.46  		-exec chmod 755 \{\} \;
    2.47  }
    2.48  
    2.49 -# Rules to gen a SliTaz package suitable for Tazpkg.
    2.50 -genpkg_rules()
    2.51 -{
    2.52 +genpkg_rules() {
    2.53  	case $PACKAGE in
    2.54 -		attr) copy @std ;;
    2.55 -		attr-dev) copy @dev ;;
    2.56 +		attr)
    2.57 +			copy @std
    2.58 +			TAGS="LFS"
    2.59 +			;;
    2.60 +		*-dev) copy @dev;;
    2.61  	esac
    2.62  }
     3.1 --- a/autoconf/receipt	Wed Feb 21 18:10:55 2018 +0200
     3.2 +++ b/autoconf/receipt	Wed Feb 21 19:48:17 2018 +0200
     3.3 @@ -6,22 +6,21 @@
     3.4  SHORT_DESC="A GNU tool for automatically configuring source code"
     3.5  MAINTAINER="pankso@slitaz.org"
     3.6  LICENSE="GPL2"
     3.7 -WEB_SITE="https://www.gnu.org/software/autoconf/autoconf.html"
     3.8 +WEB_SITE="https://www.gnu.org/software/autoconf/"
     3.9 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/autoconf.html"
    3.10 +HOST_ARCH="any"
    3.11  
    3.12  TARBALL="$PACKAGE-$VERSION.tar.xz"
    3.13  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
    3.14  
    3.15  BUILD_DEPENDS="m4 perl"
    3.16  
    3.17 -# Rules to configure and make the package.
    3.18 -compile_rules()
    3.19 -{
    3.20 +compile_rules() {
    3.21  	./configure $CONFIGURE_ARGS && make && make install
    3.22  }
    3.23  
    3.24 -# Rules to gen a SliTaz package suitable for Tazpkg.
    3.25 -genpkg_rules()
    3.26 -{
    3.27 +genpkg_rules() {
    3.28  	copy @std @dev
    3.29  	DEPENDS="m4 perl"
    3.30 +	TAGS="LFS"
    3.31  }
     4.1 --- a/automake/receipt	Wed Feb 21 18:10:55 2018 +0200
     4.2 +++ b/automake/receipt	Wed Feb 21 19:48:17 2018 +0200
     4.3 @@ -1,33 +1,26 @@
     4.4  # SliTaz package receipt v2.
     4.5  
     4.6  PACKAGE="automake"
     4.7 -VERSION="1.15"
     4.8 +VERSION="1.15.1"
     4.9  CATEGORY="development"
    4.10  SHORT_DESC="A GNU tool for automatically creating Makefiles"
    4.11  MAINTAINER="pankso@slitaz.org"
    4.12  LICENSE="GPL2"
    4.13  WEB_SITE="https://www.gnu.org/software/automake/"
    4.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/automake.html"
    4.15 +HOST_ARCH="i486 x86_64"
    4.16  
    4.17  TARBALL="$PACKAGE-$VERSION.tar.xz"
    4.18  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
    4.19  
    4.20  BUILD_DEPENDS="autoconf bison flex gfortran"
    4.21  
    4.22 -# Rules to configure and make the package.
    4.23 -compile_rules()
    4.24 -{
    4.25 -	sed -i 's:/\\\${:/\\\$\\{:' bin/automake.in
    4.26 -
    4.27 -	./configure \
    4.28 -		--docdir=/usr/share/doc/automake-$VERSION \
    4.29 -		$CONFIGURE_ARGS &&
    4.30 -	make &&
    4.31 -	make install
    4.32 +compile_rules() {
    4.33 +	./configure $CONFIGURE_ARGS && make && make install
    4.34  }
    4.35  
    4.36 -# Rules to gen a SliTaz package suitable for Tazpkg.
    4.37 -genpkg_rules()
    4.38 -{
    4.39 +genpkg_rules() {
    4.40  	copy @std @dev
    4.41  	DEPENDS="autoconf"
    4.42 +	TAGS="LFS"
    4.43  }
     5.1 --- a/bash/receipt	Wed Feb 21 18:10:55 2018 +0200
     5.2 +++ b/bash/receipt	Wed Feb 21 19:48:17 2018 +0200
     5.3 @@ -1,14 +1,14 @@
     5.4  # SliTaz package receipt v2.
     5.5  
     5.6  PACKAGE="bash"
     5.7 -VERSION="4.4.12"
     5.8 +VERSION="4.4.18"
     5.9  BASEVERSION="${VERSION%.*}"
    5.10  CATEGORY="shells"
    5.11  SHORT_DESC="The GNU bourne shell"
    5.12  MAINTAINER="pankso@slitaz.org"
    5.13  LICENSE="GPL3"
    5.14  WEB_SITE="https://www.gnu.org/software/bash/"
    5.15 -TAGS="shell"
    5.16 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/bash.html"
    5.17  
    5.18  TARBALL="$PACKAGE-$BASEVERSION.tar.gz"
    5.19  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
    5.20 @@ -21,8 +21,7 @@
    5.21  BUILD_DEPENDS="ncurses-dev readline-dev texinfo gettext patch"
    5.22  SPLIT="bash-dev"
    5.23  
    5.24 -patch_bash()
    5.25 -{
    5.26 +patch_bash() {
    5.27  	for i in $BASHPATCHES; do
    5.28  		[ -s "$SOURCES_REPOSITORY/$i" ] ||
    5.29  			wget -O "$SOURCES_REPOSITORY/$i" \
    5.30 @@ -33,19 +32,17 @@
    5.31  }
    5.32  
    5.33  # Rules to compile & install the temporary toolchain.
    5.34 -cook_tmp_toolchain()
    5.35 -{
    5.36 +cook_tmp_toolchain() {
    5.37  	cd $src
    5.38  	patch_bash
    5.39  	./configure --without-bash-malloc &&
    5.40  	make && make install
    5.41  }
    5.42  
    5.43 -# Rules to configure and make the package.
    5.44 -compile_rules()
    5.45 -{
    5.46 +compile_rules() {
    5.47  	# Patch and then build.
    5.48  	patch_bash
    5.49 +
    5.50  	# Skip tests that can not run while cross-compiling.
    5.51  	cat > config.cache <<EOF
    5.52  ac_cv_func_mmap_fixed_mapped=yes
    5.53 @@ -61,19 +58,20 @@
    5.54  bash_cv_unusable_rtsigs=no
    5.55  gt_cv_int_divbyzero_sigfpe=yes
    5.56  EOF
    5.57 +
    5.58  	./configure \
    5.59 -		$CONFIGURE_ARGS \
    5.60  		--cache-file=config.cache \
    5.61  		--bindir=/bin \
    5.62  		--enable-history \
    5.63 -		--enable-alias  \
    5.64 +		--enable-alias \
    5.65  		--disable-nls \
    5.66  		--without-bash-malloc \
    5.67  		--disable-help-builtin \
    5.68 -		--with-installed-readline &&
    5.69 +		--with-installed-readline \
    5.70 +		$CONFIGURE_ARGS &&
    5.71  	make &&
    5.72  	# Bash doesn't care about DESTDIR in environnment variable.
    5.73 -	make DESTDIR=$DESTDIR install
    5.74 +	make DESTDIR=$DESTDIR install || return 1
    5.75  
    5.76  	# Config files
    5.77  	cp -a $stuff/etc $install
    5.78 @@ -87,23 +85,22 @@
    5.79  	tee bashcheck.log
    5.80  	echo
    5.81  	grep Vulnerable bashcheck.log && echo "ERROR: Vulnerable"
    5.82 +	:
    5.83  }
    5.84  
    5.85 -# Rules to gen a SliTaz package suitable for Tazpkg.
    5.86 -genpkg_rules()
    5.87 -{
    5.88 +genpkg_rules() {
    5.89  	case $PACKAGE in
    5.90  		bash)
    5.91  			copy @std
    5.92  			DEPENDS="ncurses readline"
    5.93 +			TAGS="LFS shell"
    5.94  			;;
    5.95  		*-dev) copy @dev;;
    5.96  	esac
    5.97  }
    5.98  
    5.99  
   5.100 -post_install_bash()
   5.101 -{
   5.102 +post_install_bash() {
   5.103  	mkdir -p "$1/etc/skel"; cp -a "$1/etc/bashrc" "$1/etc/skel/.bashrc"
   5.104  
   5.105  	# Exit function in non-interactive mode (when user can't answer question)
   5.106 @@ -126,8 +123,7 @@
   5.107  }
   5.108  
   5.109  
   5.110 -pre_remove_bash()
   5.111 -{
   5.112 +pre_remove_bash() {
   5.113  	echo
   5.114  	echo 'Setting /bin/sh as default shell for all users'
   5.115  	sed -i 's|:/bin/bash$|:/bin/sh|' "$1/etc/passwd"
     6.1 --- a/bc/receipt	Wed Feb 21 18:10:55 2018 +0200
     6.2 +++ b/bc/receipt	Wed Feb 21 19:48:17 2018 +0200
     6.3 @@ -1,21 +1,24 @@
     6.4  # SliTaz package receipt v2.
     6.5  
     6.6  PACKAGE="bc"
     6.7 -VERSION="1.06.95"
     6.8 +VERSION="1.07.1"
     6.9  CATEGORY="utilities"
    6.10  SHORT_DESC="Bc is a cmdline calculator"
    6.11  MAINTAINER="pankso@slitaz.org"
    6.12  LICENSE="GPL2 LGPL2.1"
    6.13  WEB_SITE="https://www.gnu.org/software/bc/"
    6.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/bc.html"
    6.15 +HOST_ARCH="i486 x86_64"
    6.16  
    6.17 -TARBALL="$PACKAGE-$VERSION.tar.bz2"
    6.18 -WGET_URL="http://alpha.gnu.org/gnu/$PACKAGE/$TARBALL"
    6.19 +TARBALL="$PACKAGE-$VERSION.tar.gz"
    6.20 +WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
    6.21  
    6.22  BUILD_DEPENDS="flex readline-dev texinfo"
    6.23  
    6.24 -# Rules to configure and make the package.
    6.25 -compile_rules()
    6.26 -{
    6.27 +compile_rules() {
    6.28 +	# Change an internal script to use sed instead of ed
    6.29 +	install -m0755 $stuff/fix-libmath_h bc/fix-libmath_h
    6.30 +
    6.31  	./configure \
    6.32  		--with-readline \
    6.33  		$CONFIGURE_ARGS &&
    6.34 @@ -23,10 +26,8 @@
    6.35  	make install
    6.36  }
    6.37  
    6.38 -# Rules to gen a SliTaz package suitable for Tazpkg.
    6.39 -genpkg_rules()
    6.40 -{
    6.41 +genpkg_rules() {
    6.42  	copy @std
    6.43 -	TAGS="calculator"
    6.44 +	TAGS="LFS calculator"
    6.45  	DEPENDS="ncurses readline"
    6.46  }
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/bc/stuff/fix-libmath_h	Wed Feb 21 19:48:17 2018 +0200
     7.3 @@ -0,0 +1,9 @@
     7.4 +#! /bin/bash
     7.5 +sed -e '1   s/^/{"/' \
     7.6 +    -e     's/$/",/' \
     7.7 +    -e '2,$ s/^/"/'  \
     7.8 +    -e   '$ d'       \
     7.9 +    -i libmath.h
    7.10 +
    7.11 +sed -e '$ s/$/0}/' \
    7.12 +    -i libmath.h
     8.1 --- a/bc/stuff/patches/bc-1.06.95-memory_leak-1.patch	Wed Feb 21 18:10:55 2018 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,41 +0,0 @@
     8.4 -Submitted By: Bruce Dubbs (bdubbs at linuxfromscratch dot org)
     8.5 -Date: 2014-04-18
     8.6 -Initial Package Version: 1.06.95
     8.7 -Origin: Gentoo
     8.8 -Description: Fixes memory leaks and an uninitialized variable
     8.9 - 
    8.10 -diff -Naur bc-1.06.95.orig/bc/bc.y bc-1.06.95/bc/bc.y
    8.11 ---- bc-1.06.95.orig/bc/bc.y	2006-09-04 21:39:31.000000000 -0500
    8.12 -+++ bc-1.06.95/bc/bc.y	2014-04-09 13:27:04.602661243 -0500
    8.13 -@@ -569,6 +569,7 @@
    8.14 - 				    generate (">");
    8.15 - 				  break;
    8.16 - 				}
    8.17 -+			        free($2);	
    8.18 - 			    }
    8.19 - 			| expression '+' expression
    8.20 - 			    {
    8.21 -diff -Naur bc-1.06.95.orig/bc/storage.c bc-1.06.95/bc/storage.c
    8.22 ---- bc-1.06.95.orig/bc/storage.c	2006-09-04 21:39:31.000000000 -0500
    8.23 -+++ bc-1.06.95/bc/storage.c	2014-04-09 13:28:11.770763410 -0500
    8.24 -@@ -99,6 +99,7 @@
    8.25 -     {
    8.26 -       f = &functions[indx];
    8.27 -       f->f_defined = FALSE;
    8.28 -+      f->f_void = FALSE;
    8.29 -       f->f_body = (char *) bc_malloc (BC_START_SIZE);
    8.30 -       f->f_body_size = BC_START_SIZE;
    8.31 -       f->f_code_size = 0;
    8.32 -diff -Naur bc-1.06.95.orig/bc/util.c bc-1.06.95/bc/util.c
    8.33 ---- bc-1.06.95.orig/bc/util.c	2006-09-04 21:39:31.000000000 -0500
    8.34 -+++ bc-1.06.95/bc/util.c	2014-04-09 13:27:39.841190064 -0500
    8.35 -@@ -602,8 +602,7 @@
    8.36 -     case FUNCTDEF:
    8.37 -       if (id->f_name != 0)
    8.38 - 	{
    8.39 --	  if (namekind != FUNCT)
    8.40 --	    free(name);
    8.41 -+	  free(name);
    8.42 - 	  /* Check to see if we are redefining a math lib function. */ 
    8.43 - 	  if (use_math && namekind == FUNCTDEF && id->f_name <= 6)
    8.44 - 	    id->f_name = next_func++;
     9.1 --- a/bc/stuff/patches/series	Wed Feb 21 18:10:55 2018 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,1 +0,0 @@
     9.4 -bc-1.06.95-memory_leak-1.patch
    10.1 --- a/binutils/receipt	Wed Feb 21 18:10:55 2018 +0200
    10.2 +++ b/binutils/receipt	Wed Feb 21 19:48:17 2018 +0200
    10.3 @@ -1,40 +1,35 @@
    10.4  # SliTaz package receipt v2.
    10.5  
    10.6  PACKAGE="binutils"
    10.7 -VERSION="2.27"
    10.8 +VERSION="2.29"
    10.9  CATEGORY="development"
   10.10  SHORT_DESC="GNU assembler, linker and binary utilities"
   10.11  MAINTAINER="pankso@slitaz.org"
   10.12  LICENSE="GPL2 LGPL2 GPL3 LGPL3"
   10.13  WEB_SITE="http://www.gnu.org/software/binutils/"
   10.14 -TAGS="assembler linker"
   10.15 -HOST_ARCH="i486 arm"
   10.16 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/binutils.html"
   10.17  
   10.18  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   10.19  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   10.20  
   10.21 +BUILD_DEPENDS_arm=" "
   10.22  BUILD_DEPENDS="glibc-dev zlib-dev texinfo bison flex gettext-tools"
   10.23 -BUILD_DEPENDS_arm=" "
   10.24 -SPLIT="libbfd"
   10.25 +SPLIT="libbfd binutils"
   10.26  
   10.27 -# Rules to configure and make the package.
   10.28 -compile_rules()
   10.29 -{
   10.30 -	case "$ARCH" in
   10.31 -		i?86) ARCH_ARGS="--disable-werror" ;;
   10.32 -	esac
   10.33 -
   10.34 -	mkdir build; cd build
   10.35 +compile_rules() {
   10.36 +	mkdir build
   10.37 +	cd    build
   10.38  
   10.39  	$src/configure \
   10.40  		--enable-gold \
   10.41  		--enable-ld=default \
   10.42  		--enable-plugins \
   10.43  		--enable-shared \
   10.44 +		--disable-werror \
   10.45  		--with-system-zlib \
   10.46 -		$CONFIGURE_ARGS $ARCH_ARGS &&
   10.47 +		$CONFIGURE_ARGS &&
   10.48  	make tooldir=/usr &&
   10.49 -	make tooldir=/usr install
   10.50 +	make tooldir=/usr install || return 1
   10.51  
   10.52  	# Create prefixed version of the tools.
   10.53  	cd $install/usr/bin
   10.54 @@ -44,27 +39,21 @@
   10.55  		ln -s $TOOLPREFIX$i $i
   10.56  	done
   10.57  
   10.58 -	# Remove prefix from manpages name
   10.59 -	for i in $(find $install/usr/share/man/man1 -type f); do
   10.60 -		mv $i ${i/$TOOLPREFIX/}
   10.61 -	done
   10.62 -
   10.63  #	# Install libiberty (-liberty flag): dependency described in *.la files
   10.64  #	install -o root -g root -m 644 $src/include/libiberty.h $install/usr/include
   10.65  }
   10.66  
   10.67 -# Rules to gen a SliTaz package suitable for Tazpkg.
   10.68 -genpkg_rules()
   10.69 -{
   10.70 +genpkg_rules() {
   10.71  	case $PACKAGE in
   10.72 -		binutils)
   10.73 -			copy @std @dev
   10.74 -			DEPENDS="glibc zlib flex libbfd"
   10.75 -			;;
   10.76  		libbfd)
   10.77  			copy libbfd*.so
   10.78  			CAT="system-tools|Binary File Descriptor library"
   10.79  			DEPENDS="zlib"
   10.80  			;;
   10.81 +		binutils)
   10.82 +			copy @std @dev @rm
   10.83 +			DEPENDS="flex libbfd   glibc"
   10.84 +			TAGS="LFS assembler linker"
   10.85 +			;;
   10.86  	esac
   10.87  }
    11.1 --- a/bison/receipt	Wed Feb 21 18:10:55 2018 +0200
    11.2 +++ b/bison/receipt	Wed Feb 21 19:48:17 2018 +0200
    11.3 @@ -7,26 +7,20 @@
    11.4  MAINTAINER="pankso@slitaz.org"
    11.5  LICENSE="GPL3"
    11.6  WEB_SITE="https://www.gnu.org/software/bison/"
    11.7 -TAGS="parser language"
    11.8 -HOST_ARCH="i486 arm"
    11.9 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/bison.html"
   11.10  
   11.11  TARBALL="$PACKAGE-$VERSION.tar.xz"
   11.12  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   11.13  
   11.14  BUILD_DEPENDS="m4 perl libxslt gettext"
   11.15  
   11.16 -# Rules to configure and make the package.
   11.17 -compile_rules()
   11.18 -{
   11.19 -	./configure \
   11.20 -		--docdir=/usr/share/doc/bison-$VERSION \
   11.21 -		$CONFIGURE_ARGS &&
   11.22 -	make && make install
   11.23 +compile_rules() {
   11.24 +	./configure $CONFIGURE_ARGS && make && make install
   11.25  }
   11.26  
   11.27 -# Rules to gen a SliTaz package suitable for Tazpkg.
   11.28 -genpkg_rules()
   11.29 -{
   11.30 -	copy bin/ lib/ aclocal/ bison/
   11.31 +genpkg_rules() {
   11.32 +	copy @std @dev
   11.33 +	rm -rf $fs/usr/share/doc # one *.h file copied here with @dev
   11.34  	DEPENDS="m4"
   11.35 +	TAGS="LFS parser language"
   11.36  }
    12.1 --- a/bzip2/receipt	Wed Feb 21 18:10:55 2018 +0200
    12.2 +++ b/bzip2/receipt	Wed Feb 21 19:48:17 2018 +0200
    12.3 @@ -7,43 +7,45 @@
    12.4  MAINTAINER="pankso@slitaz.org"
    12.5  LICENSE="BSD"
    12.6  WEB_SITE="http://www.bzip.org/"
    12.7 -TAGS="compression archive"
    12.8 -HOST_ARCH="i486 arm"
    12.9 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/bzip2.html"
   12.10  
   12.11  TARBALL="$PACKAGE-$VERSION.tar.gz"
   12.12  WGET_URL="http://www.bzip.org/$VERSION/$TARBALL"
   12.13  
   12.14  SPLIT="bzlib bzip2-apps bzip2-dev"
   12.15  
   12.16 -# Rules to configure and make the package.
   12.17 -compile_rules()
   12.18 -{
   12.19 -	# No configure script, we must used CC, AR and RANLIB set by cook.
   12.20 +compile_rules() {
   12.21  	case "$ARCH" in
   12.22  		arm*)
   12.23 -			make -f Makefile-libbz2_so CC=${CC} AR=${AR} RANLIB=${RANLIB} &&
   12.24 -			make clean && make CC=${CC} AR=${AR} RANLIB=${RANLIB} ;;
   12.25 +			# No configure script, we must used CC, AR and RANLIB set by cook.
   12.26 +			make -f Makefile-libbz2_so CC=$CC AR=$AR RANLIB=$RANLIB &&
   12.27 +			make clean && make CC=$CC AR=$AR RANLIB=$RANLIB ;;
   12.28  		*)
   12.29 +			# add large-file support
   12.30 +			sed -i 's/^CFLAGS=\(.*\)$/CFLAGS=\1 \$(BIGFILES)/' ./Makefile-libbz2_so
   12.31 +
   12.32  			make -f Makefile-libbz2_so &&
   12.33  			make clean && make ;;
   12.34 -	esac
   12.35 +	esac &&
   12.36  
   12.37 -	make install
   12.38 +	make install || return 1
   12.39 +
   12.40 +	rm $install/usr/bin/bunzip2 $install/usr/bin/bzcat
   12.41 +	ln -s bzip2 $install/bin/bunzip2
   12.42 +	ln -s bzip2 $install/bin/bzcat
   12.43  }
   12.44  
   12.45  # Just to be sure when cross-compiling.
   12.46 -testsuite()
   12.47 -{
   12.48 +testsuite() {
   12.49  	readelf -h $src/bzip2-shared
   12.50  }
   12.51  
   12.52 -# Rules to gen a SliTaz package suitable for Tazpkg.
   12.53 -genpkg_rules()
   12.54 -{
   12.55 +genpkg_rules() {
   12.56  	case $PACKAGE in
   12.57  		bzip2)
   12.58  			copy bzip2 bunzip2 bzcat
   12.59  			DEPENDS="bzlib"
   12.60 +			TAGS="LFS compression archive"
   12.61  			;;
   12.62  		bzlib)
   12.63  			copy *.so*
   12.64 @@ -51,8 +53,7 @@
   12.65  			CAT="libs|library"
   12.66  			;;
   12.67  		bzip2-apps)
   12.68 -			copy bin/
   12.69 -			remove_already_packed
   12.70 +			copy bin/ @rm
   12.71  			DEPENDS="bzlib"
   12.72  			CAT="utilities|apps"
   12.73  			;;
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/bzip2/stuff/patches/bzip2-1.0.4-bzip2recover.patch	Wed Feb 21 19:48:17 2018 +0200
    13.3 @@ -0,0 +1,12 @@
    13.4 +--- bzip2-1.0.4/bzip2recover.c.pom	2007-01-03 03:00:55.000000000 +0100
    13.5 ++++ bzip2-1.0.4/bzip2recover.c	2007-02-05 11:55:17.000000000 +0100
    13.6 +@@ -309,7 +309,8 @@
    13.7 +    UInt32      buffHi, buffLo, blockCRC;
    13.8 +    Char*       p;
    13.9 + 
   13.10 +-   strcpy ( progName, argv[0] );
   13.11 ++   strncpy ( progName, argv[0], BZ_MAX_FILENAME-1);
   13.12 ++   progName[BZ_MAX_FILENAME-1]='\0';
   13.13 +    inFileName[0] = outFileName[0] = 0;
   13.14 + 
   13.15 +    fprintf ( stderr, 
    14.1 --- a/bzip2/stuff/patches/bzip2-1.0.6-fix_install.patch	Wed Feb 21 18:10:55 2018 +0200
    14.2 +++ b/bzip2/stuff/patches/bzip2-1.0.6-fix_install.patch	Wed Feb 21 19:48:17 2018 +0200
    14.3 @@ -14,7 +14,7 @@
    14.4         bzlib.o
    14.5   
    14.6  -all: libbz2.a bzip2 bzip2recover test
    14.7 -+all: libbz2.a bzip2 bzip2recover
    14.8 ++all: bzip2 bzip2recover
    14.9   
   14.10   bzip2: libbz2.a bzip2.o
   14.11   	$(CC) $(CFLAGS) $(LDFLAGS) -o bzip2 bzip2.o -L. -lbz2
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/bzip2/stuff/patches/bzip2recover-CVE-2016-3189.patch	Wed Feb 21 19:48:17 2018 +0200
    15.3 @@ -0,0 +1,11 @@
    15.4 +diff -up ./bzip2recover.c.old ./bzip2recover.c
    15.5 +--- ./bzip2recover.c.old	2016-03-22 08:49:38.855620000 +0100
    15.6 ++++ ./bzip2recover.c	2016-03-30 10:22:27.341430099 +0200
    15.7 +@@ -458,6 +458,7 @@ Int32 main ( Int32 argc, Char** argv )
    15.8 +             bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
    15.9 +             bsPutUInt32 ( bsWr, blockCRC );
   15.10 +             bsClose ( bsWr );
   15.11 ++            outFile = NULL;
   15.12 +          }
   15.13 +          if (wrBlock >= rbCtr) break;
   15.14 +          wrBlock++;
    16.1 --- a/bzip2/stuff/patches/series	Wed Feb 21 18:10:55 2018 +0200
    16.2 +++ b/bzip2/stuff/patches/series	Wed Feb 21 19:48:17 2018 +0200
    16.3 @@ -1,2 +1,4 @@
    16.4  bzip2-1.0.6-install_docs-1.patch
    16.5 -bzip2-1.0.6-fix_install.patch
    16.6 +-p1|bzip2-1.0.6-fix_install.patch
    16.7 +bzip2-1.0.4-bzip2recover.patch
    16.8 +bzip2recover-CVE-2016-3189.patch # https://bugzilla.redhat.com/attachment.cgi?id=1169843
    17.1 --- a/check/receipt	Wed Feb 21 18:10:55 2018 +0200
    17.2 +++ b/check/receipt	Wed Feb 21 19:48:17 2018 +0200
    17.3 @@ -7,27 +7,23 @@
    17.4  MAINTAINER="erjo@slitaz.org"
    17.5  LICENSE="LGPL2.1"
    17.6  WEB_SITE="https://libcheck.github.io/check/"
    17.7 -HOST_ARCH="i486 arm"
    17.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter05/check.html"
    17.9  
   17.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   17.11  WGET_URL="https://github.com/libcheck/check/releases/download/$VERSION/$TARBALL"
   17.12  
   17.13  SPLIT="check-dev"
   17.14  
   17.15 -# Rules to configure and make the package.
   17.16 -compile_rules()
   17.17 -{
   17.18 +compile_rules() {
   17.19  	./configure \
   17.20  		--disable-static \
   17.21  		$CONFIGURE_ARGS &&
   17.22  	make && make install
   17.23  }
   17.24  
   17.25 -# Rules to gen a SliTaz package suitable for Tazpkg.
   17.26 -genpkg_rules()
   17.27 -{
   17.28 +genpkg_rules() {
   17.29  	case $PACKAGE in
   17.30  		check) copy *.so* ;;
   17.31 -		check-dev) copy @dev checkmk ;;
   17.32 +		*-dev) copy @dev checkmk ;;
   17.33  	esac
   17.34  }
    18.1 --- a/coreutils-multicall/description.txt	Wed Feb 21 18:10:55 2018 +0200
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,108 +0,0 @@
    18.4 -Coreutils: Core GNU (file, text, shell) utilities.
    18.5 -
    18.6 -  * [          exit with the status determined by expression
    18.7 -  * base32:    base32 encode/decode data and print to standard output
    18.8 -  * base64:    base64 encode/decode data and print to standard output
    18.9 -  * basename:  strip directory and suffix from filenames
   18.10 -  * cat:       concatenate files and print on the standard output
   18.11 -  * chcon:     change file SELinux security context
   18.12 -  * chgrp:     change group ownership
   18.13 -  * chmod:     change file mode bits
   18.14 -  * chown:     change file owner and group
   18.15 -  * chroot:    run command or interactive shell with special root directory
   18.16 -  * cksum:     checksum and count the bytes in a file
   18.17 -  * comm:      compare two sorted files line by line
   18.18 -  * cp:        copy files and directories
   18.19 -  * csplit:    split a file into sections determined by context lines
   18.20 -  * cut:       remove sections from each line of files
   18.21 -  * date:      print or set the system date and time
   18.22 -  * dd:        convert and copy a file
   18.23 -  * df:        report file system disk space usage
   18.24 -  * dir:       list directory contents
   18.25 -  * dircolors: color setup for ls
   18.26 -  * dirname:   strip last component from file name
   18.27 -  * du:        estimate file space usage
   18.28 -  * echo:      display a line of text
   18.29 -  * env:       run a program in a modified environment
   18.30 -  * expand:    convert tabs to spaces
   18.31 -  * expr:      evaluate expressions
   18.32 -  * factor:    factor numbers
   18.33 -  * false:     do nothing, unsuccessfully
   18.34 -  * fmt:       simple optimal text formatter
   18.35 -  * fold:      wrap each input line to fit in specified width
   18.36 -  * groups:    print the groups a user is in
   18.37 -  * head:      output the first part of files
   18.38 -  * hostid:    print the numeric identifier for the current host
   18.39 -  * id:        print real and effective user and group IDs
   18.40 -  * install:   copy files and set attributes
   18.41 -  * join:      join lines of two files on a common field
   18.42 -  * kill:      send signals to processes, or list signals
   18.43 -  * link:      call the link function to create a link to a file
   18.44 -  * ln:        make links between files
   18.45 -  * logname:   print user's login name
   18.46 -  * ls:        list directory contents
   18.47 -  * md5sum:    compute and check MD5 message digest
   18.48 -  * mkdir:     make directories
   18.49 -  * mkfifo:    make FIFOs (named pipes)
   18.50 -  * mknod:     make block or character special files
   18.51 -  * mktemp:    create a temporary file or directory
   18.52 -  * mv:        move (rename) files
   18.53 -  * nice:      run a program with modified scheduling priority
   18.54 -  * nl:        number lines of files
   18.55 -  * nohup:     run a command immune to hangups, with output to a non-tty
   18.56 -  * nproc:     print the number of processing units available
   18.57 -  * numfmt:    convert numbers from/to human-readable strings
   18.58 -  * od:        dump files in octal and other formats
   18.59 -  * paste:     merge lines of files
   18.60 -  * pathchk:   check whether file names are valid or portable
   18.61 -  * pinky:     lightweight finger
   18.62 -  * pr:        convert text files for printing
   18.63 -  * printenv:  print all or part of environment
   18.64 -  * printf:    format and print data
   18.65 -  * ptx:       produce a permuted index of file contents
   18.66 -  * pwd:       print name of current/working directory
   18.67 -  * readlink:  print resolved symbolic links or canonical file names
   18.68 -  * realpath:  print the resolved path
   18.69 -  * rm:        remove files or directories
   18.70 -  * rmdir:     remove empty directories
   18.71 -  * runcon:    run command with specified SELinux security context
   18.72 -  * seq:       print a sequence of numbers
   18.73 -  * sha1sum:   compute and check SHA1 message digest
   18.74 -  * sha224sum: compute and check SHA224 message digest
   18.75 -  * sha256sum: compute and check SHA256 message digest
   18.76 -  * sha384sum: compute and check SHA384 message digest
   18.77 -  * sha512sum: compute and check SHA512 message digest
   18.78 -  * shred:     overwrite a file to hide its contents, and optionally delete it
   18.79 -  * shuf:      generate random permutations
   18.80 -  * sleep:     delay for a specified amount of time
   18.81 -  * sort:      sort lines of text files
   18.82 -  * split:     split a file into pieces
   18.83 -  * stat:      display file or file system status
   18.84 -  * stdbuf:    run command with modified buffering operations for its standard
   18.85 -               streams
   18.86 -  * stty:      change and print terminal line settings
   18.87 -  * sum:       checksum and count the blocks in a file
   18.88 -  * sync:      synchronize cached writes to persistent storage
   18.89 -  * tac:       concatenate and print files in reverse
   18.90 -  * tail:      output the last part of files
   18.91 -  * tee:       read from standard input and write to standard output and files
   18.92 -  * test:      check file types and compare values
   18.93 -  * timeout:   run a command with a time limit
   18.94 -  * touch:     change file timestamps
   18.95 -  * tr:        translate or delete characters
   18.96 -  * true:      do nothing, successfully
   18.97 -  * truncate:  shrink or extend the size of a file to the specified size
   18.98 -  * tsort:     perform topological sort
   18.99 -  * tty:       print the file name of the terminal connected to standard input
  18.100 -  * uname:     print system information
  18.101 -  * unexpand:  convert spaces to tabs
  18.102 -  * uniq:      report or omit repeated lines
  18.103 -  * unlink:    call the unlink function to remove the specified file
  18.104 -  * uptime:    tell how long the system has been running
  18.105 -  * users:     print the user names of users currently logged in to the current
  18.106 -               host
  18.107 -  * vdir:      list directory contents
  18.108 -  * wc:        print newline, word, and byte counts for each file
  18.109 -  * who:       show who is logged on
  18.110 -  * whoami:    print effective user ID
  18.111 -  * yes:       output a string repeatedly until killed
    19.1 --- a/coreutils-multicall/receipt	Wed Feb 21 18:10:55 2018 +0200
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,68 +0,0 @@
    19.4 -# SliTaz package receipt v2.
    19.5 -
    19.6 -PACKAGE="coreutils-multicall"
    19.7 -VERSION="8.25"
    19.8 -CATEGORY="system-tools"
    19.9 -SHORT_DESC="Utilities for using and setting the basic system"
   19.10 -MAINTAINER="al.bobylev@gmail.com"
   19.11 -LICENSE="GPL3"
   19.12 -WEB_SITE="https://www.gnu.org/software/coreutils/coreutils.html"
   19.13 -
   19.14 -TARBALL="coreutils-$VERSION.tar.xz"
   19.15 -WGET_URL="$GNU_MIRROR/coreutils/$TARBALL"
   19.16 -
   19.17 -SIBLINGS="coreutils"
   19.18 -BUILD_DEPENDS="automake autoconf gettext xz libcap-dev gmp-dev patch"
   19.19 -
   19.20 -# Rules to configure and make the package.
   19.21 -compile_rules()
   19.22 -{
   19.23 -	# Rebuild fixed translations
   19.24 -	msgfmt po/nb.po -o po/nb.gmo
   19.25 -	msgfmt po/sl.po -o po/sl.gmo
   19.26 -
   19.27 -	autoreconf -fi
   19.28 -
   19.29 -	FORCE_UNSAFE_CONFIGURE=1 \
   19.30 -	./configure \
   19.31 -		--enable-single-binary=symlinks \
   19.32 -		$CONFIGURE_ARGS &&
   19.33 -	make && make install
   19.34 -
   19.35 -	# LFS: Move programs to the locations specified by the FHS
   19.36 -	mkdir -p \
   19.37 -		$install/bin \
   19.38 -		$install/usr/sbin \
   19.39 -		$install/usr/share/man/man8
   19.40 -	for i in cat chgrp chmod chown cp date dd df echo false ln ls mkdir \
   19.41 -		mknod mv pwd rm rmdir stty sync true uname; do
   19.42 -		rm $install/usr/bin/$i
   19.43 -		ln -s /usr/bin/coreutils $install/bin/$i
   19.44 -	done
   19.45 -	rm $install/usr/bin/chroot
   19.46 -	ln -s /usr/bin/coreutils $install/usr/sbin/chroot
   19.47 -	mv  $install/usr/share/man/man1/chroot.1 \
   19.48 -		$install/usr/share/man/man8/chroot.8
   19.49 -	sed -i 's|"1"|"8"|' $install/usr/share/man/man8/chroot.8
   19.50 -}
   19.51 -
   19.52 -# Rules to gen a SliTaz package suitable for Tazpkg.
   19.53 -genpkg_rules()
   19.54 -{
   19.55 -	copy @std
   19.56 -	DEPENDS="glibc-base acl attr libcap gmp"
   19.57 -}
   19.58 -
   19.59 -	# Remove Busybox applets in order to not clash with ("/bin", "/sbin",
   19.60 -	# "/usr/bin" and "/usr/sbin" conflicts with the same filename)
   19.61 -post_install_coreutils_multicall()
   19.62 -{
   19.63 -	rm "$1/bin/base64"   # for /usr/bin/base64
   19.64 -	rm "$1/bin/kill"     # for /usr/bin/kill
   19.65 -	rm "$1/bin/mktemp"   # for /usr/bin/mktemp
   19.66 -	rm "$1/bin/nice"     # for /usr/bin/nice
   19.67 -	rm "$1/bin/printenv" # for /usr/bin/printenv
   19.68 -	rm "$1/bin/sleep"    # for /usr/bin/sleep
   19.69 -	rm "$1/bin/stat"     # for /usr/bin/stat
   19.70 -	rm "$1/bin/touch"    # for /usr/bin/touch
   19.71 -}
    20.1 --- a/coreutils-multicall/stuff	Wed Feb 21 18:10:55 2018 +0200
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,1 +0,0 @@
    20.4 -../coreutils/stuff
    20.5 \ No newline at end of file
    21.1 --- a/coreutils/receipt	Wed Feb 21 18:10:55 2018 +0200
    21.2 +++ b/coreutils/receipt	Wed Feb 21 19:48:17 2018 +0200
    21.3 @@ -1,171 +1,239 @@
    21.4  # SliTaz package receipt v2.
    21.5  
    21.6  PACKAGE="coreutils"
    21.7 -VERSION="8.25"
    21.8 +VERSION="8.29"
    21.9  CATEGORY="meta"
   21.10  SHORT_DESC="Utilities for using and setting the basic system"
   21.11  MAINTAINER="pankso@slitaz.org"
   21.12  LICENSE="GPL3"
   21.13  WEB_SITE="https://www.gnu.org/software/coreutils/coreutils.html"
   21.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter05/coreutils.html"
   21.15  
   21.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   21.17  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   21.18  
   21.19 -SIBLINGS="coreutils-multicall"
   21.20 -BUILD_DEPENDS="automake autoconf gettext xz libcap-dev gmp-dev patch"
   21.21 -SPLIT="coreutils-character coreutils-command coreutils-conditions coreutils-\
   21.22 -context-system coreutils-context-user coreutils-context-working coreutils-\
   21.23 -directory coreutils-disk coreutils-file-attributes coreutils-file-format \
   21.24 -coreutils-file-output-full coreutils-file-output-part coreutils-file-sort \
   21.25 -coreutils-file-special coreutils-file-summarize coreutils-line coreutils-\
   21.26 -numeric coreutils-operations coreutils-path coreutils-print coreutils-\
   21.27 -redirection"
   21.28 +BUILD_DEPENDS="automake autoconf gettext xz libcap-dev gmp-dev patch texinfo \
   21.29 +openssl-dev"
   21.30 +SPLIT="\
   21.31 +coreutils-character      coreutils-command          coreutils-conditions \
   21.32 +coreutils-context-system coreutils-context-user     coreutils-context-working \
   21.33 +coreutils-directory      coreutils-disk             coreutils-file-attributes \
   21.34 +coreutils-file-format    coreutils-file-output-full coreutils-file-output-part \
   21.35 +coreutils-file-sort      coreutils-file-special     coreutils-file-summarize \
   21.36 +coreutils-line           coreutils-numeric          coreutils-operations \
   21.37 +coreutils-path           coreutils-print            coreutils-redirection \
   21.38 +coreutils-multicall:multi"
   21.39  
   21.40 -# Rules to configure and make the package.
   21.41 -compile_rules()
   21.42 -{
   21.43 +compile_rules() {
   21.44 +	case $SET in
   21.45 +		multi) SET_ARGS='--enable-single-binary=symlinks';;
   21.46 +		*)     SET_ARGS='';;
   21.47 +	esac
   21.48  	# Rebuild fixed translations
   21.49  	msgfmt po/nb.po -o po/nb.gmo
   21.50  	msgfmt po/sl.po -o po/sl.gmo
   21.51  
   21.52  	autoreconf -fi
   21.53  
   21.54 -	FORCE_UNSAFE_CONFIGURE=1 ./configure $CONFIGURE_ARGS &&
   21.55 -	make && make install
   21.56 +	FORCE_UNSAFE_CONFIGURE=1 \
   21.57 +	./configure \
   21.58 +		--with-openssl \
   21.59 +		$SET_ARGS \
   21.60 +		$CONFIGURE_ARGS &&
   21.61 +	make && make install || return 1
   21.62  
   21.63  	# LFS: Move programs to the locations specified by the FHS
   21.64  	mkdir -p \
   21.65  		$install/bin \
   21.66  		$install/usr/sbin \
   21.67  		$install/usr/share/man/man8
   21.68 -	for i in cat chgrp chmod chown cp date dd df echo false ln ls mkdir \
   21.69 -		mknod mv pwd rm rmdir stty sync true uname; do
   21.70 -		mv $install/usr/bin/$i $install/bin
   21.71 -	done
   21.72 -	mv  $install/usr/bin/chroot $install/usr/sbin
   21.73 +
   21.74 +	while read from to; do
   21.75 +		case $SET in
   21.76 +			multi)
   21.77 +				rm $install$from
   21.78 +				# make relative symlinks
   21.79 +				case $to in
   21.80 +					/bin/*) ln -s ../../usr/bin/coreutils $install$to;;
   21.81 +					*)      ln -s        ../bin/coreutils $install$to;;
   21.82 +				esac
   21.83 +				;;
   21.84 +			*)
   21.85 +				mv $install$from $install$to
   21.86 +				;;
   21.87 +		esac
   21.88 +	done <<EOT
   21.89 +/usr/bin/cat    /bin/cat
   21.90 +/usr/bin/chgrp  /bin/chgrp
   21.91 +/usr/bin/chmod  /bin/chmod
   21.92 +/usr/bin/chown  /bin/chown
   21.93 +/usr/bin/cp     /bin/cp
   21.94 +/usr/bin/date   /bin/date
   21.95 +/usr/bin/dd     /bin/dd
   21.96 +/usr/bin/df     /bin/df
   21.97 +/usr/bin/echo   /bin/echo
   21.98 +/usr/bin/false  /bin/false
   21.99 +/usr/bin/kill   /bin/kill
  21.100 +/usr/bin/ln     /bin/ln
  21.101 +/usr/bin/ls     /bin/ls
  21.102 +/usr/bin/mkdir  /bin/mkdir
  21.103 +/usr/bin/mknod  /bin/mknod
  21.104 +/usr/bin/mv     /bin/mv
  21.105 +/usr/bin/pwd    /bin/pwd
  21.106 +/usr/bin/rm     /bin/rm
  21.107 +/usr/bin/rmdir  /bin/rmdir
  21.108 +/usr/bin/stty   /bin/stty
  21.109 +/usr/bin/sync   /bin/sync
  21.110 +/usr/bin/true   /bin/true
  21.111 +/usr/bin/uname  /bin/uname
  21.112 +/usr/bin/chroot /usr/sbin/chroot
  21.113 +EOT
  21.114  	mv  $install/usr/share/man/man1/chroot.1 \
  21.115  		$install/usr/share/man/man8/chroot.8
  21.116  	sed -i 's|"1"|"8"|' $install/usr/share/man/man8/chroot.8
  21.117  }
  21.118  
  21.119 -# Rules to gen a SliTaz package suitable for Tazpkg.
  21.120 -genpkg_rules()
  21.121 -{
  21.122 +genpkg_rules() {
  21.123 +	DEPENDS="glibc-base" # default
  21.124  	case $PACKAGE in
  21.125  		coreutils)
  21.126 -			DEPENDS="$SPLIT" ;;
  21.127 -		coreutils-character)
  21.128 +			DEPENDS=${SPLIT/coreutils-multicall:multi} # all but coreutils-multicall
  21.129 +			TAGS="LFS"
  21.130 +			;;
  21.131 +		*-character)
  21.132  			copy expand tr unexpand
  21.133  			CAT="system-tools|operate on characters"
  21.134 -			DEPENDS="glibc-base" ;;
  21.135 -		coreutils-command)
  21.136 +			;;
  21.137 +		*-command)
  21.138  			copy env kill nice nohup sleep stdbuf timeout libstdbuf.so chroot
  21.139  			CAT="system-tools|commands"
  21.140 -			DEPENDS="glibc-base" ;;
  21.141 -		coreutils-conditions)
  21.142 +			;;
  21.143 +		*-conditions)
  21.144  			copy false true [ expr test
  21.145  			CAT="system-tools|conditions"
  21.146  			DEPENDS="glibc-base gmp" ;;
  21.147 -		coreutils-context-system)
  21.148 +		*-context-system)
  21.149  			copy date uname chcon hostid nproc runcon uptime
  21.150  			CAT="system-tools|system context"
  21.151 -			DEPENDS="glibc-base" ;;
  21.152 -		coreutils-context-user)
  21.153 +			;;
  21.154 +		*-context-user)
  21.155  			copy groups id logname pinky users who whoami
  21.156  			CAT="system-tools|user context"
  21.157 -			DEPENDS="glibc-base" ;;
  21.158 -		coreutils-context-working)
  21.159 +			;;
  21.160 +		*-context-working)
  21.161  			copy pwd stty printenv tty
  21.162  			CAT="system-tools|working context"
  21.163 -			DEPENDS="glibc-base" ;;
  21.164 -		coreutils-directory)
  21.165 +			;;
  21.166 +		*-directory)
  21.167  			copy ls dir dircolors vdir
  21.168  			CAT="system-tools|list directories"
  21.169 -			DEPENDS="glibc-base attr libcap" ;;
  21.170 -		coreutils-disk)
  21.171 +			DEPENDS="glibc-base libcap" ;;
  21.172 +		*-disk)
  21.173  			copy df sync du stat truncate
  21.174  			CAT="system-tools|work with disks"
  21.175 -			DEPENDS="glibc-base" ;;
  21.176 -		coreutils-file-attributes)
  21.177 +			;;
  21.178 +		*-file-attributes)
  21.179  			copy chgrp chmod chown touch
  21.180  			CAT="system-tools|change file attributes"
  21.181 -			DEPENDS="glibc-base" ;;
  21.182 -		coreutils-file-format)
  21.183 +			;;
  21.184 +		*-file-format)
  21.185  			copy fmt fold pr
  21.186  			CAT="system-tools|format file contents"
  21.187 -			DEPENDS="glibc-base" ;;
  21.188 -		coreutils-file-output-full)
  21.189 +			;;
  21.190 +		*-file-output-full)
  21.191  			copy cat base32 base64 nl od tac
  21.192  			CAT="system-tools|output entire files"
  21.193 -			DEPENDS="glibc-base" ;;
  21.194 -		coreutils-file-output-part)
  21.195 +			;;
  21.196 +		*-file-output-part)
  21.197  			copy csplit head split tail
  21.198  			CAT="system-tools|output file parts"
  21.199 -			DEPENDS="glibc-base" ;;
  21.200 -		coreutils-file-sort)
  21.201 +			;;
  21.202 +		*-file-sort)
  21.203  			copy comm ptx shuf sort tsort uniq
  21.204  			CAT="system-tools|operate on sorted files"
  21.205 -			DEPENDS="glibc-base" ;;
  21.206 -		coreutils-file-special)
  21.207 +			DEPENDS="glibc-base openssl" # openssl for `sort`
  21.208 +			;;
  21.209 +		*-file-special)
  21.210  			copy ln mkdir mknod rmdir link mkfifo mktemp readlink realpath unlink
  21.211  			CAT="system-tools|work with special file types"
  21.212 -			DEPENDS="glibc-base" ;;
  21.213 -		coreutils-file-summarize)
  21.214 -			copy cksum md5sum sha1sum sha224sum sha256sum sha384sum sha512sum sum wc
  21.215 +			;;
  21.216 +		*-file-summarize)
  21.217 +			copy b2sum cksum md5sum sha1sum sha224sum sha256sum sha384sum sha512sum sum wc
  21.218  			CAT="system-tools|summarize files"
  21.219 -			DEPENDS="glibc-base" ;;
  21.220 -		coreutils-line)
  21.221 +			DEPENDS="glibc-base openssl"
  21.222 +			;;
  21.223 +		*-line)
  21.224  			copy cut join paste
  21.225  			CAT="system-tools|operate on fields within a line"
  21.226 -			DEPENDS="glibc-base" ;;
  21.227 -		coreutils-numeric)
  21.228 +			;;
  21.229 +		*-numeric)
  21.230  			copy factor seq
  21.231  			CAT="system-tools|numeric"
  21.232  			DEPENDS="glibc-base gmp" ;;
  21.233 -		coreutils-operations)
  21.234 +		*-operations)
  21.235  			copy cp dd mv install rm shred
  21.236  			CAT="system-tools|perform basic operations"
  21.237  			DEPENDS="glibc-base acl attr" ;;
  21.238 -		coreutils-path)
  21.239 +		*-path)
  21.240  			copy basename dirname pathchk
  21.241  			CAT="system-tools|perform path manipulation"
  21.242 -			DEPENDS="glibc-base" ;;
  21.243 -		coreutils-print)
  21.244 +			;;
  21.245 +		*-print)
  21.246  			copy echo numfmt printf yes
  21.247  			CAT="system-tools|print text"
  21.248 -			DEPENDS="glibc-base" ;;
  21.249 -		coreutils-redirection)
  21.250 +			;;
  21.251 +		*-redirection)
  21.252  			copy tee
  21.253  			CAT="system-tools|redirection"
  21.254 -			DEPENDS="glibc-base" ;;
  21.255 +			;;
  21.256 +		*-multicall)
  21.257 +			copy @std
  21.258 +			CAT="system-tools|packed in single binary like Busybox"
  21.259 +			DEPENDS="glibc-base acl attr gmp libcap openssl"
  21.260 +			;;
  21.261  	esac
  21.262  }
  21.263  
  21.264  # Remove Busybox applets in order to not clash with ("/bin", "/sbin",
  21.265  # "/usr/bin" and "/usr/sbin" conflicts with the same filename)
  21.266 -post_install_coreutils_command()
  21.267 -{
  21.268 -	rm "$1/bin/kill"     # for /usr/bin/kill
  21.269 -	rm "$1/bin/nice"     # for /usr/bin/nice
  21.270 -	rm "$1/bin/sleep"    # for /usr/bin/sleep
  21.271 +
  21.272 +# for /usr/bin/nice /usr/bin/sleep
  21.273 +post_install_coreutils_command() {
  21.274 +	for i in nice sleep; do
  21.275 +		readlink "$1/bin/$i" | grep -q busybox && rm "$1/bin/$i"
  21.276 +	done
  21.277 +	:
  21.278  }
  21.279 -post_install_coreutils_context_working()
  21.280 -{
  21.281 -	rm "$1/bin/printenv" # for /usr/bin/printenv
  21.282 +# for /usr/bin/printenv
  21.283 +post_install_coreutils_context_working() {
  21.284 +	readlink "$1/bin/printenv" | grep -q busybox && rm "$1/bin/printenv"
  21.285 +	:
  21.286  }
  21.287 -post_install_coreutils_disk()
  21.288 -{
  21.289 -	rm "$1/bin/stat"     # for /usr/bin/stat
  21.290 +# for /usr/bin/stat
  21.291 +post_install_coreutils_disk() {
  21.292 +	readlink "$1/bin/stat" | grep -q busybox && rm "$1/bin/stat"
  21.293 +	:
  21.294  }
  21.295 -post_install_coreutils_file_attributes()
  21.296 -{
  21.297 -	rm "$1/bin/touch"    # for /usr/bin/touch
  21.298 +# for /usr/bin/touch
  21.299 +post_install_coreutils_file_attributes() {
  21.300 +	readlink "$1/bin/touch" | grep -q busybox && rm "$1/bin/touch"
  21.301 +	:
  21.302  }
  21.303 -post_install_coreutils_file_output_full()
  21.304 -{
  21.305 -	rm "$1/bin/base64"   # for /usr/bin/base64
  21.306 +# for /usr/bin/base64
  21.307 +post_install_coreutils_file_output_full() {
  21.308 +	readlink "$1/bin/base64" | grep -q busybox && rm "$1/bin/base64"
  21.309 +	:
  21.310  }
  21.311 -post_install_coreutils_file_special()
  21.312 -{
  21.313 -	rm "$1/bin/mktemp"   # for /usr/bin/mktemp
  21.314 +# for /usr/bin/mktemp
  21.315 +post_install_coreutils_file_special() {
  21.316 +	readlink "$1/bin/mktemp" | grep -q busybox && rm "$1/bin/mktemp"
  21.317 +	:
  21.318  }
  21.319 +# for /usr/bin/base64 /usr/bin/mktemp /usr/bin/nice /usr/bin/printenv
  21.320 +# /usr/bin/sleep /usr/bin/stat /usr/bin/touch
  21.321 +post_install_coreutils_multicall() {
  21.322 +	for i in base64 mktemp nice printenv sleep stat touch; do
  21.323 +		readlink "$1/bin/$i" | grep -q busybox && rm "$1/bin/$i"
  21.324 +	done
  21.325 +	:
  21.326 +}
    22.1 --- a/coreutils/stuff/patches/README	Wed Feb 21 18:10:55 2018 +0200
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,3 +0,0 @@
    22.4 -coreutils-8.25-i18n-2.patch: LFS: Coreutils Internationalization Fixes Patch
    22.5 -uname.u: SliTaz: show extended info touching CPU via uname
    22.6 -coreutils-fix-po.patch: SliTaz: fix translations, especially deprecated symbol '\v'
    23.1 --- a/coreutils/stuff/patches/coreutils-8.25-i18n-2.patch	Wed Feb 21 18:10:55 2018 +0200
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,4790 +0,0 @@
    23.4 -Submitted by:            DJ Lucas (dj_AT_linuxfromscratch_DOT_org)
    23.5 -Date:                    2016-02-09
    23.6 -Initial Package Version: 8.25
    23.7 -Upstream Status:         Rejected
    23.8 -Origin:                  Based on Suse's i18n patches at https://build.opensuse.org/package/view_file/Base:System/coreutils/coreutils-i18n.patch
    23.9 -Description:             Fixes several i18n issues with various Coreutils programs
   23.10 -
   23.11 -diff -Naurp coreutils-8.25-orig/lib/linebuffer.h coreutils-8.25/lib/linebuffer.h
   23.12 ---- coreutils-8.25-orig/lib/linebuffer.h	2016-01-01 07:45:55.000000000 -0600
   23.13 -+++ coreutils-8.25/lib/linebuffer.h	2016-02-08 19:07:10.298944609 -0600
   23.14 -@@ -21,6 +21,11 @@
   23.15 - 
   23.16 - # include <stdio.h>
   23.17 - 
   23.18 -+/* Get mbstate_t.  */
   23.19 -+# if HAVE_WCHAR_H
   23.20 -+#  include <wchar.h>
   23.21 -+# endif
   23.22 -+
   23.23 - /* A 'struct linebuffer' holds a line of text. */
   23.24 - 
   23.25 - struct linebuffer
   23.26 -@@ -28,6 +33,9 @@ struct linebuffer
   23.27 -   size_t size;                  /* Allocated. */
   23.28 -   size_t length;                /* Used. */
   23.29 -   char *buffer;
   23.30 -+# if HAVE_WCHAR_H
   23.31 -+  mbstate_t state;
   23.32 -+# endif
   23.33 - };
   23.34 - 
   23.35 - /* Initialize linebuffer LINEBUFFER for use. */
   23.36 -diff -Naurp coreutils-8.25-orig/src/cut.c coreutils-8.25/src/cut.c
   23.37 ---- coreutils-8.25-orig/src/cut.c	2016-01-13 05:08:59.000000000 -0600
   23.38 -+++ coreutils-8.25/src/cut.c	2016-02-08 19:07:10.300944616 -0600
   23.39 -@@ -28,6 +28,11 @@
   23.40 - #include <assert.h>
   23.41 - #include <getopt.h>
   23.42 - #include <sys/types.h>
   23.43 -+
   23.44 -+/* Get mbstate_t, mbrtowc().  */
   23.45 -+#if HAVE_WCHAR_H
   23.46 -+# include <wchar.h>
   23.47 -+#endif
   23.48 - #include "system.h"
   23.49 - 
   23.50 - #include "error.h"
   23.51 -@@ -38,6 +43,18 @@
   23.52 - 
   23.53 - #include "set-fields.h"
   23.54 - 
   23.55 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
   23.56 -+   installation; work around this configuration error.        */
   23.57 -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
   23.58 -+# undef MB_LEN_MAX
   23.59 -+# define MB_LEN_MAX 16
   23.60 -+#endif
   23.61 -+
   23.62 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
   23.63 -+#if HAVE_MBRTOWC && defined mbstate_t
   23.64 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
   23.65 -+#endif
   23.66 -+
   23.67 - /* The official name of this program (e.g., no 'g' prefix).  */
   23.68 - #define PROGRAM_NAME "cut"
   23.69 - 
   23.70 -@@ -54,6 +71,52 @@
   23.71 -     }									\
   23.72 -   while (0)
   23.73 - 
   23.74 -+/* Refill the buffer BUF to get a multibyte character. */
   23.75 -+#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM)                        \
   23.76 -+  do                                                                        \
   23.77 -+    {                                                                        \
   23.78 -+      if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM))        \
   23.79 -+        {                                                                \
   23.80 -+          memmove (BUF, BUFPOS, BUFLEN);                                \
   23.81 -+          BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \
   23.82 -+          BUFPOS = BUF;                                                        \
   23.83 -+        }                                                                \
   23.84 -+    }                                                                        \
   23.85 -+  while (0)
   23.86 -+
   23.87 -+/* Get wide character on BUFPOS. BUFPOS is not included after that.
   23.88 -+   If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */
   23.89 -+#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \
   23.90 -+  do                                                                        \
   23.91 -+    {                                                                        \
   23.92 -+      mbstate_t state_bak;                                                \
   23.93 -+                                                                        \
   23.94 -+      if (BUFLEN < 1)                                                        \
   23.95 -+        {                                                                \
   23.96 -+          WC = WEOF;                                                        \
   23.97 -+          break;                                                        \
   23.98 -+        }                                                                \
   23.99 -+                                                                        \
  23.100 -+      /* Get a wide character. */                                        \
  23.101 -+      CONVFAIL = false;                                                        \
  23.102 -+      state_bak = STATE;                                                \
  23.103 -+      MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE);        \
  23.104 -+                                                                        \
  23.105 -+      switch (MBLENGTH)                                                        \
  23.106 -+        {                                                                \
  23.107 -+        case (size_t)-1:                                                \
  23.108 -+        case (size_t)-2:                                                \
  23.109 -+          CONVFAIL = true;                                                        \
  23.110 -+          STATE = state_bak;                                                \
  23.111 -+          /* Fall througn. */                                                \
  23.112 -+                                                                        \
  23.113 -+        case 0:                                                                \
  23.114 -+          MBLENGTH = 1;                                                        \
  23.115 -+          break;                                                        \
  23.116 -+        }                                                                \
  23.117 -+    }                                                                        \
  23.118 -+  while (0)
  23.119 -+
  23.120 - 
  23.121 - /* Pointer inside RP.  When checking if a byte or field is selected
  23.122 -    by a finite range, we check if it is between CURRENT_RP.LO
  23.123 -@@ -61,6 +124,9 @@
  23.124 -    CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */
  23.125 - static struct field_range_pair *current_rp;
  23.126 - 
  23.127 -+/* Length of the delimiter given as argument to -d.  */
  23.128 -+size_t delimlen;
  23.129 -+
  23.130 - /* This buffer is used to support the semantics of the -s option
  23.131 -    (or lack of same) when the specified field list includes (does
  23.132 -    not include) the first field.  In both of those cases, the entire
  23.133 -@@ -77,15 +143,25 @@ enum operating_mode
  23.134 -   {
  23.135 -     undefined_mode,
  23.136 - 
  23.137 --    /* Output characters that are in the given bytes. */
  23.138 -+    /* Output bytes that are at the given positions. */
  23.139 -     byte_mode,
  23.140 - 
  23.141 -+    /* Output characters that are at the given positions. */
  23.142 -+    character_mode,
  23.143 -+
  23.144 -     /* Output the given delimiter-separated fields. */
  23.145 -     field_mode
  23.146 -   };
  23.147 - 
  23.148 - static enum operating_mode operating_mode;
  23.149 - 
  23.150 -+/* If nonzero, when in byte mode, don't split multibyte characters.  */
  23.151 -+static int byte_mode_character_aware;
  23.152 -+
  23.153 -+/* If nonzero, the function for single byte locale is work
  23.154 -+   if this program runs on multibyte locale. */
  23.155 -+static int force_singlebyte_mode;
  23.156 -+
  23.157 - /* If true do not output lines containing no delimiter characters.
  23.158 -    Otherwise, all such lines are printed.  This option is valid only
  23.159 -    with field mode.  */
  23.160 -@@ -97,6 +173,9 @@ static bool complement;
  23.161 - 
  23.162 - /* The delimiter character for field mode. */
  23.163 - static unsigned char delim;
  23.164 -+#if HAVE_WCHAR_H
  23.165 -+static wchar_t wcdelim;
  23.166 -+#endif
  23.167 - 
  23.168 - /* The delimiter for each line/record. */
  23.169 - static unsigned char line_delim = '\n';
  23.170 -@@ -164,7 +243,7 @@ Print selected parts of lines from each
  23.171 -   -f, --fields=LIST       select only these fields;  also print any line\n\
  23.172 -                             that contains no delimiter character, unless\n\
  23.173 -                             the -s option is specified\n\
  23.174 --  -n                      (ignored)\n\
  23.175 -+  -n                      with -b: don't split multibyte characters\n\
  23.176 - "), stdout);
  23.177 -       fputs (_("\
  23.178 -       --complement        complement the set of selected bytes, characters\n\
  23.179 -@@ -280,6 +359,82 @@ cut_bytes (FILE *stream)
  23.180 -     }
  23.181 - }
  23.182 - 
  23.183 -+#if HAVE_MBRTOWC
  23.184 -+/* This function is in use for the following case.
  23.185 -+
  23.186 -+   1. Read from the stream STREAM, printing to standard output any selected
  23.187 -+   characters.
  23.188 -+
  23.189 -+   2. Read from stream STREAM, printing to standard output any selected bytes,
  23.190 -+   without splitting multibyte characters.  */
  23.191 -+
  23.192 -+static void
  23.193 -+cut_characters_or_cut_bytes_no_split (FILE *stream)
  23.194 -+{
  23.195 -+  size_t idx;                /* number of bytes or characters in the line so far. */
  23.196 -+  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  23.197 -+  char *bufpos;                /* Next read position of BUF. */
  23.198 -+  size_t buflen;        /* The length of the byte sequence in buf. */
  23.199 -+  wint_t wc;                /* A gotten wide character. */
  23.200 -+  size_t mblength;        /* The byte size of a multibyte character which shows
  23.201 -+                           as same character as WC. */
  23.202 -+  mbstate_t state;        /* State of the stream. */
  23.203 -+  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  23.204 -+  /* Whether to begin printing delimiters between ranges for the current line.
  23.205 -+     Set after we've begun printing data corresponding to the first range.  */
  23.206 -+  bool print_delimiter = false;
  23.207 -+
  23.208 -+  idx = 0;
  23.209 -+  buflen = 0;
  23.210 -+  bufpos = buf;
  23.211 -+  memset (&state, '\0', sizeof(mbstate_t));
  23.212 -+
  23.213 -+  current_rp = frp;
  23.214 -+
  23.215 -+  while (1)
  23.216 -+    {
  23.217 -+      REFILL_BUFFER (buf, bufpos, buflen, stream);
  23.218 -+
  23.219 -+      GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail);
  23.220 -+      (void) convfail;  /* ignore unused */
  23.221 -+
  23.222 -+      if (wc == WEOF)
  23.223 -+        {
  23.224 -+          if (idx > 0)
  23.225 -+            putchar (line_delim);
  23.226 -+          break;
  23.227 -+        }
  23.228 -+      else if (wc == line_delim)
  23.229 -+        {
  23.230 -+          putchar (line_delim);
  23.231 -+          idx = 0;
  23.232 -+          print_delimiter = false;
  23.233 -+          current_rp = frp;
  23.234 -+        }
  23.235 -+      else
  23.236 -+        {
  23.237 -+          next_item (&idx);
  23.238 -+          if (print_kth (idx))
  23.239 -+            {
  23.240 -+              if (output_delimiter_specified)
  23.241 -+                {
  23.242 -+                  if (print_delimiter && is_range_start_index (idx))
  23.243 -+                    {
  23.244 -+                      fwrite (output_delimiter_string, sizeof (char),
  23.245 -+                              output_delimiter_length, stdout);
  23.246 -+                    }
  23.247 -+                  print_delimiter = true;
  23.248 -+                }
  23.249 -+              fwrite (bufpos, mblength, sizeof(char), stdout);
  23.250 -+            }
  23.251 -+        }
  23.252 -+
  23.253 -+      buflen -= mblength;
  23.254 -+      bufpos += mblength;
  23.255 -+    }
  23.256 -+}
  23.257 -+#endif
  23.258 -+
  23.259 - /* Read from stream STREAM, printing to standard output any selected fields.  */
  23.260 - 
  23.261 - static void
  23.262 -@@ -425,13 +580,211 @@ cut_fields (FILE *stream)
  23.263 -     }
  23.264 - }
  23.265 - 
  23.266 -+#if HAVE_MBRTOWC
  23.267 -+static void
  23.268 -+cut_fields_mb (FILE *stream)
  23.269 -+{
  23.270 -+  int c;
  23.271 -+  size_t field_idx;
  23.272 -+  int found_any_selected_field;
  23.273 -+  int buffer_first_field;
  23.274 -+  int empty_input;
  23.275 -+  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  23.276 -+  char *bufpos;                /* Next read position of BUF. */
  23.277 -+  size_t buflen;        /* The length of the byte sequence in buf. */
  23.278 -+  wint_t wc = 0;        /* A gotten wide character. */
  23.279 -+  size_t mblength;        /* The byte size of a multibyte character which shows
  23.280 -+                           as same character as WC. */
  23.281 -+  mbstate_t state;        /* State of the stream. */
  23.282 -+  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  23.283 -+
  23.284 -+  current_rp = frp;
  23.285 -+
  23.286 -+  found_any_selected_field = 0;
  23.287 -+  field_idx = 1;
  23.288 -+  bufpos = buf;
  23.289 -+  buflen = 0;
  23.290 -+  memset (&state, '\0', sizeof(mbstate_t));
  23.291 -+
  23.292 -+  c = getc (stream);
  23.293 -+  empty_input = (c == EOF);
  23.294 -+  if (c != EOF)
  23.295 -+  {
  23.296 -+    ungetc (c, stream);
  23.297 -+    wc = 0;
  23.298 -+  }
  23.299 -+  else
  23.300 -+    wc = WEOF;
  23.301 -+
  23.302 -+  /* To support the semantics of the -s flag, we may have to buffer
  23.303 -+     all of the first field to determine whether it is `delimited.'
  23.304 -+     But that is unnecessary if all non-delimited lines must be printed
  23.305 -+     and the first field has been selected, or if non-delimited lines
  23.306 -+     must be suppressed and the first field has *not* been selected.
  23.307 -+     That is because a non-delimited line has exactly one field.  */
  23.308 -+  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
  23.309 -+
  23.310 -+  while (1)
  23.311 -+    {
  23.312 -+      if (field_idx == 1 && buffer_first_field)
  23.313 -+        {
  23.314 -+          int len = 0;
  23.315 -+
  23.316 -+          while (1)
  23.317 -+            {
  23.318 -+              REFILL_BUFFER (buf, bufpos, buflen, stream);
  23.319 -+
  23.320 -+              GET_NEXT_WC_FROM_BUFFER
  23.321 -+                (wc, bufpos, buflen, mblength, state, convfail);
  23.322 -+
  23.323 -+              if (wc == WEOF)
  23.324 -+                break;
  23.325 -+
  23.326 -+              field_1_buffer = xrealloc (field_1_buffer, len + mblength);
  23.327 -+              memcpy (field_1_buffer + len, bufpos, mblength);
  23.328 -+              len += mblength;
  23.329 -+              buflen -= mblength;
  23.330 -+              bufpos += mblength;
  23.331 -+
  23.332 -+              if (!convfail && (wc == line_delim || wc == wcdelim))
  23.333 -+                break;
  23.334 -+            }
  23.335 -+
  23.336 -+          if (len <= 0 && wc == WEOF)
  23.337 -+            break;
  23.338 -+
  23.339 -+          /* If the first field extends to the end of line (it is not
  23.340 -+             delimited) and we are printing all non-delimited lines,
  23.341 -+             print this one.  */
  23.342 -+          if (convfail || (!convfail && wc != wcdelim))
  23.343 -+            {
  23.344 -+              if (suppress_non_delimited)
  23.345 -+                {
  23.346 -+                  /* Empty.        */
  23.347 -+                }
  23.348 -+              else
  23.349 -+                {
  23.350 -+                  fwrite (field_1_buffer, sizeof (char), len, stdout);
  23.351 -+                  /* Make sure the output line is newline terminated.  */
  23.352 -+                  if (convfail || (!convfail && wc != line_delim))
  23.353 -+                    putchar (line_delim);
  23.354 -+                }
  23.355 -+              continue;
  23.356 -+            }
  23.357 -+
  23.358 -+          if (print_kth (1))
  23.359 -+            {
  23.360 -+              /* Print the field, but not the trailing delimiter.  */
  23.361 -+              fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
  23.362 -+              found_any_selected_field = 1;
  23.363 -+            }
  23.364 -+          next_item (&field_idx);
  23.365 -+        }
  23.366 -+
  23.367 -+      if (wc != WEOF)
  23.368 -+        {
  23.369 -+          if (print_kth (field_idx))
  23.370 -+            {
  23.371 -+              if (found_any_selected_field)
  23.372 -+                {
  23.373 -+                  fwrite (output_delimiter_string, sizeof (char),
  23.374 -+                          output_delimiter_length, stdout);
  23.375 -+                }
  23.376 -+              found_any_selected_field = 1;
  23.377 -+            }
  23.378 -+
  23.379 -+          while (1)
  23.380 -+            {
  23.381 -+              REFILL_BUFFER (buf, bufpos, buflen, stream);
  23.382 -+
  23.383 -+              GET_NEXT_WC_FROM_BUFFER
  23.384 -+                (wc, bufpos, buflen, mblength, state, convfail);
  23.385 -+
  23.386 -+              if (wc == WEOF)
  23.387 -+                break;
  23.388 -+              else if (!convfail && (wc == wcdelim || wc == line_delim))
  23.389 -+                {
  23.390 -+                  buflen -= mblength;
  23.391 -+                  bufpos += mblength;
  23.392 -+                  break;
  23.393 -+                }
  23.394 -+
  23.395 -+              if (print_kth (field_idx))
  23.396 -+                fwrite (bufpos, mblength, sizeof(char), stdout);
  23.397 -+
  23.398 -+              buflen -= mblength;
  23.399 -+              bufpos += mblength;
  23.400 -+            }
  23.401 -+        }
  23.402 -+
  23.403 -+      if ((!convfail || wc == line_delim) && buflen < 1)
  23.404 -+        wc = WEOF;
  23.405 -+
  23.406 -+      if (!convfail && wc == wcdelim)
  23.407 -+        next_item (&field_idx);
  23.408 -+      else if (wc == WEOF || (!convfail && wc == line_delim))
  23.409 -+        {
  23.410 -+          if (found_any_selected_field
  23.411 -+              || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
  23.412 -+            putchar (line_delim);
  23.413 -+          if (wc == WEOF)
  23.414 -+            break;
  23.415 -+          field_idx = 1;
  23.416 -+          current_rp = frp;
  23.417 -+          found_any_selected_field = 0;
  23.418 -+        }
  23.419 -+    }
  23.420 -+}
  23.421 -+#endif
  23.422 -+
  23.423 - static void
  23.424 - cut_stream (FILE *stream)
  23.425 - {
  23.426 --  if (operating_mode == byte_mode)
  23.427 --    cut_bytes (stream);
  23.428 -+#if HAVE_MBRTOWC
  23.429 -+  if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  23.430 -+    {
  23.431 -+      switch (operating_mode)
  23.432 -+        {
  23.433 -+        case byte_mode:
  23.434 -+          if (byte_mode_character_aware)
  23.435 -+            cut_characters_or_cut_bytes_no_split (stream);
  23.436 -+          else
  23.437 -+            cut_bytes (stream);
  23.438 -+          break;
  23.439 -+
  23.440 -+        case character_mode:
  23.441 -+          cut_characters_or_cut_bytes_no_split (stream);
  23.442 -+          break;
  23.443 -+
  23.444 -+        case field_mode:
  23.445 -+          if (delimlen == 1)
  23.446 -+            {
  23.447 -+              /* Check if we have utf8 multibyte locale, so we can use this
  23.448 -+                 optimization because of uniqueness of characters, which is
  23.449 -+                 not true for e.g. SJIS */
  23.450 -+              char * loc = setlocale(LC_CTYPE, NULL);
  23.451 -+              if (loc && (strstr (loc, "UTF-8") || strstr (loc, "utf-8") ||
  23.452 -+                  strstr (loc, "UTF8") || strstr (loc, "utf8")))
  23.453 -+                {
  23.454 -+                  cut_fields (stream);
  23.455 -+                  break;
  23.456 -+                }
  23.457 -+            }
  23.458 -+          cut_fields_mb (stream);
  23.459 -+          break;
  23.460 -+
  23.461 -+        default:
  23.462 -+          abort ();
  23.463 -+        }
  23.464 -+    }
  23.465 -   else
  23.466 --    cut_fields (stream);
  23.467 -+#endif
  23.468 -+    {
  23.469 -+      if (operating_mode == field_mode)
  23.470 -+        cut_fields (stream);
  23.471 -+      else
  23.472 -+        cut_bytes (stream);
  23.473 -+    }
  23.474 - }
  23.475 - 
  23.476 - /* Process file FILE to standard output.
  23.477 -@@ -483,6 +836,7 @@ main (int argc, char **argv)
  23.478 -   bool ok;
  23.479 -   bool delim_specified = false;
  23.480 -   char *spec_list_string IF_LINT ( = NULL);
  23.481 -+  char mbdelim[MB_LEN_MAX + 1];
  23.482 - 
  23.483 -   initialize_main (&argc, &argv);
  23.484 -   set_program_name (argv[0]);
  23.485 -@@ -505,7 +859,6 @@ main (int argc, char **argv)
  23.486 -       switch (optc)
  23.487 -         {
  23.488 -         case 'b':
  23.489 --        case 'c':
  23.490 -           /* Build the byte list. */
  23.491 -           if (operating_mode != undefined_mode)
  23.492 -             FATAL_ERROR (_("only one type of list may be specified"));
  23.493 -@@ -513,6 +866,14 @@ main (int argc, char **argv)
  23.494 -           spec_list_string = optarg;
  23.495 -           break;
  23.496 - 
  23.497 -+        case 'c':
  23.498 -+          /* Build the character list. */
  23.499 -+          if (operating_mode != undefined_mode)
  23.500 -+            FATAL_ERROR (_("only one type of list may be specified"));
  23.501 -+          operating_mode = character_mode;
  23.502 -+          spec_list_string = optarg;
  23.503 -+          break;
  23.504 -+
  23.505 -         case 'f':
  23.506 -           /* Build the field list. */
  23.507 -           if (operating_mode != undefined_mode)
  23.508 -@@ -524,10 +885,38 @@ main (int argc, char **argv)
  23.509 -         case 'd':
  23.510 -           /* New delimiter. */
  23.511 -           /* Interpret -d '' to mean 'use the NUL byte as the delimiter.'  */
  23.512 --          if (optarg[0] != '\0' && optarg[1] != '\0')
  23.513 --            FATAL_ERROR (_("the delimiter must be a single character"));
  23.514 --          delim = optarg[0];
  23.515 --          delim_specified = true;
  23.516 -+            {
  23.517 -+#if HAVE_MBRTOWC
  23.518 -+              if(MB_CUR_MAX > 1)
  23.519 -+                {
  23.520 -+                  mbstate_t state;
  23.521 -+
  23.522 -+                  memset (&state, '\0', sizeof(mbstate_t));
  23.523 -+                  delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state);
  23.524 -+
  23.525 -+                  if (delimlen == (size_t)-1 || delimlen == (size_t)-2)
  23.526 -+                    ++force_singlebyte_mode;
  23.527 -+                  else
  23.528 -+                    {
  23.529 -+                      delimlen = (delimlen < 1) ? 1 : delimlen;
  23.530 -+                      if (wcdelim != L'\0' && *(optarg + delimlen) != '\0')
  23.531 -+                        FATAL_ERROR (_("the delimiter must be a single character"));
  23.532 -+                      memcpy (mbdelim, optarg, delimlen);
  23.533 -+                      mbdelim[delimlen] = '\0';
  23.534 -+                      if (delimlen == 1)
  23.535 -+                        delim = *optarg;
  23.536 -+                    }
  23.537 -+                }
  23.538 -+
  23.539 -+              if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  23.540 -+#endif
  23.541 -+                {
  23.542 -+                  if (optarg[0] != '\0' && optarg[1] != '\0')
  23.543 -+                    FATAL_ERROR (_("the delimiter must be a single character"));
  23.544 -+                  delim = (unsigned char) optarg[0];
  23.545 -+                }
  23.546 -+            delim_specified = true;
  23.547 -+          }
  23.548 -           break;
  23.549 - 
  23.550 -         case OUTPUT_DELIMITER_OPTION:
  23.551 -@@ -540,6 +929,7 @@ main (int argc, char **argv)
  23.552 -           break;
  23.553 - 
  23.554 -         case 'n':
  23.555 -+          byte_mode_character_aware = 1;
  23.556 -           break;
  23.557 - 
  23.558 -         case 's':
  23.559 -@@ -579,15 +969,34 @@ main (int argc, char **argv)
  23.560 -               | (complement ? SETFLD_COMPLEMENT : 0) );
  23.561 - 
  23.562 -   if (!delim_specified)
  23.563 --    delim = '\t';
  23.564 -+    {
  23.565 -+      delim = '\t';
  23.566 -+#ifdef HAVE_MBRTOWC
  23.567 -+      wcdelim = L'\t';
  23.568 -+      mbdelim[0] = '\t';
  23.569 -+      mbdelim[1] = '\0';
  23.570 -+      delimlen = 1;
  23.571 -+#endif
  23.572 -+    }
  23.573 - 
  23.574 -   if (output_delimiter_string == NULL)
  23.575 -     {
  23.576 --      static char dummy[2];
  23.577 --      dummy[0] = delim;
  23.578 --      dummy[1] = '\0';
  23.579 --      output_delimiter_string = dummy;
  23.580 --      output_delimiter_length = 1;
  23.581 -+#ifdef HAVE_MBRTOWC
  23.582 -+      if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  23.583 -+        {
  23.584 -+          output_delimiter_string = xstrdup(mbdelim);
  23.585 -+          output_delimiter_length = delimlen;
  23.586 -+        }
  23.587 -+
  23.588 -+      if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  23.589 -+#endif
  23.590 -+        {
  23.591 -+          static char dummy[2];
  23.592 -+          dummy[0] = delim;
  23.593 -+          dummy[1] = '\0';
  23.594 -+          output_delimiter_string = dummy;
  23.595 -+          output_delimiter_length = 1;
  23.596 -+        }
  23.597 -     }
  23.598 - 
  23.599 -   if (optind == argc)
  23.600 -diff -Naurp coreutils-8.25-orig/src/expand.c coreutils-8.25/src/expand.c
  23.601 ---- coreutils-8.25-orig/src/expand.c	2016-01-01 07:48:50.000000000 -0600
  23.602 -+++ coreutils-8.25/src/expand.c	2016-02-08 19:07:10.301944619 -0600
  23.603 -@@ -37,12 +37,34 @@
  23.604 - #include <stdio.h>
  23.605 - #include <getopt.h>
  23.606 - #include <sys/types.h>
  23.607 -+
  23.608 -+/* Get mbstate_t, mbrtowc(), wcwidth(). */
  23.609 -+#if HAVE_WCHAR_H
  23.610 -+# include <wchar.h>
  23.611 -+#endif
  23.612 -+
  23.613 -+/* Get iswblank(). */
  23.614 -+#if HAVE_WCTYPE_H
  23.615 -+# include <wctype.h>
  23.616 -+#endif
  23.617 -+
  23.618 - #include "system.h"
  23.619 - #include "error.h"
  23.620 - #include "fadvise.h"
  23.621 - #include "quote.h"
  23.622 - #include "xstrndup.h"
  23.623 - 
  23.624 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
  23.625 -+   installation; work around this configuration error.  */
  23.626 -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
  23.627 -+# define MB_LEN_MAX 16
  23.628 -+#endif
  23.629 -+
  23.630 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
  23.631 -+#if HAVE_MBRTOWC && defined mbstate_t
  23.632 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
  23.633 -+#endif
  23.634 -+
  23.635 - /* The official name of this program (e.g., no 'g' prefix).  */
  23.636 - #define PROGRAM_NAME "expand"
  23.637 - 
  23.638 -@@ -357,6 +379,142 @@ expand (void)
  23.639 -     }
  23.640 - }
  23.641 - 
  23.642 -+#if HAVE_MBRTOWC
  23.643 -+static void
  23.644 -+expand_multibyte (void)
  23.645 -+{
  23.646 -+  FILE *fp;			/* Input strem. */
  23.647 -+  mbstate_t i_state;		/* Current shift state of the input stream. */
  23.648 -+  mbstate_t i_state_bak;	/* Back up the I_STATE. */
  23.649 -+  mbstate_t o_state;		/* Current shift state of the output stream. */
  23.650 -+  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  23.651 -+  char *bufpos = buf;			/* Next read position of BUF. */
  23.652 -+  size_t buflen = 0;		/* The length of the byte sequence in buf. */
  23.653 -+  wchar_t wc;			/* A gotten wide character. */
  23.654 -+  size_t mblength;		/* The byte size of a multibyte character
  23.655 -+				   which shows as same character as WC. */
  23.656 -+  int tab_index = 0;		/* Index in `tab_list' of next tabstop. */
  23.657 -+  int column = 0;		/* Column on screen of the next char. */
  23.658 -+  int next_tab_column;		/* Column the next tab stop is on. */
  23.659 -+  int convert = 1;		/* If nonzero, perform translations. */
  23.660 -+
  23.661 -+  fp = next_file ((FILE *) NULL);
  23.662 -+  if (fp == NULL)
  23.663 -+    return;
  23.664 -+
  23.665 -+  memset (&o_state, '\0', sizeof(mbstate_t));
  23.666 -+  memset (&i_state, '\0', sizeof(mbstate_t));
  23.667 -+
  23.668 -+  for (;;)
  23.669 -+    {
  23.670 -+      /* Refill the buffer BUF. */
  23.671 -+      if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp))
  23.672 -+	{
  23.673 -+	  memmove (buf, bufpos, buflen);
  23.674 -+	  buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp);
  23.675 -+	  bufpos = buf;
  23.676 -+	}
  23.677 -+
  23.678 -+      /* No character is left in BUF. */
  23.679 -+      if (buflen < 1)
  23.680 -+	{
  23.681 -+	  fp = next_file (fp);
  23.682 -+
  23.683 -+	  if (fp == NULL)
  23.684 -+	    break;		/* No more files. */
  23.685 -+	  else
  23.686 -+	    {
  23.687 -+	      memset (&i_state, '\0', sizeof(mbstate_t));
  23.688 -+	      continue;
  23.689 -+	    }
  23.690 -+	}
  23.691 -+
  23.692 -+      /* Get a wide character. */
  23.693 -+      i_state_bak = i_state;
  23.694 -+      mblength = mbrtowc (&wc, bufpos, buflen, &i_state);
  23.695 -+
  23.696 -+      switch (mblength)
  23.697 -+	{
  23.698 -+	case (size_t)-1:	/* illegal byte sequence. */
  23.699 -+	case (size_t)-2:
  23.700 -+	  mblength = 1;
  23.701 -+	  i_state = i_state_bak;
  23.702 -+	  if (convert)
  23.703 -+	    {
  23.704 -+	      ++column;
  23.705 -+	      if (convert_entire_line == 0 && !isblank(*bufpos))
  23.706 -+		convert = 0;
  23.707 -+	    }
  23.708 -+	  putchar (*bufpos);
  23.709 -+	  break;
  23.710 -+
  23.711 -+	case 0:		/* null. */
  23.712 -+	  mblength = 1;
  23.713 -+	  if (convert && convert_entire_line == 0)
  23.714 -+	    convert = 0;
  23.715 -+	  putchar ('\0');
  23.716 -+	  break;
  23.717 -+
  23.718 -+	default:
  23.719 -+	  if (wc == L'\n')   /* LF. */
  23.720 -+	    {
  23.721 -+	      tab_index = 0;
  23.722 -+	      column = 0;
  23.723 -+	      convert = 1;
  23.724 -+	      putchar ('\n');
  23.725 -+	    }
  23.726 -+	  else if (wc == L'\t' && convert)	/* Tab. */
  23.727 -+	    {
  23.728 -+	      if (tab_size == 0)
  23.729 -+		{
  23.730 -+		  /* Do not let tab_index == first_free_tab;
  23.731 -+		     stop when it is 1 less. */
  23.732 -+		  while (tab_index < first_free_tab - 1
  23.733 -+		      && column >= tab_list[tab_index])
  23.734 -+		    tab_index++;
  23.735 -+		  next_tab_column = tab_list[tab_index];
  23.736 -+		  if (tab_index < first_free_tab - 1)
  23.737 -+		    tab_index++;
  23.738 -+		  if (column >= next_tab_column)
  23.739 -+		    next_tab_column = column + 1;
  23.740 -+		}
  23.741 -+	      else
  23.742 -+		next_tab_column = column + tab_size - column % tab_size;
  23.743 -+
  23.744 -+	      while (column < next_tab_column)
  23.745 -+		{
  23.746 -+		  putchar (' ');
  23.747 -+		  ++column;
  23.748 -+		}
  23.749 -+	    }
  23.750 -+	  else  /* Others. */
  23.751 -+	    {
  23.752 -+	      if (convert)
  23.753 -+		{
  23.754 -+		  if (wc == L'\b')
  23.755 -+		    {
  23.756 -+		      if (column > 0)
  23.757 -+			--column;
  23.758 -+		    }
  23.759 -+		  else
  23.760 -+		    {
  23.761 -+		      int width;		/* The width of WC. */
  23.762 -+
  23.763 -+		      width = wcwidth (wc);
  23.764 -+		      column += (width > 0) ? width : 0;
  23.765 -+		      if (convert_entire_line == 0 && !iswblank(wc))
  23.766 -+			convert = 0;
  23.767 -+		    }
  23.768 -+		}
  23.769 -+	      fwrite (bufpos, sizeof(char), mblength, stdout);
  23.770 -+	    }
  23.771 -+	}
  23.772 -+      buflen -= mblength;
  23.773 -+      bufpos += mblength;
  23.774 -+    }
  23.775 -+}
  23.776 -+#endif
  23.777 -+
  23.778 - int
  23.779 - main (int argc, char **argv)
  23.780 - {
  23.781 -@@ -421,7 +579,12 @@ main (int argc, char **argv)
  23.782 - 
  23.783 -   file_list = (optind < argc ? &argv[optind] : stdin_argv);
  23.784 - 
  23.785 --  expand ();
  23.786 -+#if HAVE_MBRTOWC
  23.787 -+  if (MB_CUR_MAX > 1)
  23.788 -+    expand_multibyte ();
  23.789 -+  else
  23.790 -+#endif
  23.791 -+    expand ();
  23.792 - 
  23.793 -   if (have_read_stdin && fclose (stdin) != 0)
  23.794 -     error (EXIT_FAILURE, errno, "-");
  23.795 -diff -Naurp coreutils-8.25-orig/src/fold.c coreutils-8.25/src/fold.c
  23.796 ---- coreutils-8.25-orig/src/fold.c	2016-01-01 07:48:50.000000000 -0600
  23.797 -+++ coreutils-8.25/src/fold.c	2016-02-08 19:07:10.302944622 -0600
  23.798 -@@ -22,11 +22,33 @@
  23.799 - #include <getopt.h>
  23.800 - #include <sys/types.h>
  23.801 - 
  23.802 -+/* Get mbstate_t, mbrtowc(), wcwidth().  */
  23.803 -+#if HAVE_WCHAR_H
  23.804 -+# include <wchar.h>
  23.805 -+#endif
  23.806 -+
  23.807 -+/* Get iswprint(), iswblank(), wcwidth().  */
  23.808 -+#if HAVE_WCTYPE_H
  23.809 -+# include <wctype.h>
  23.810 -+#endif
  23.811 -+
  23.812 - #include "system.h"
  23.813 - #include "error.h"
  23.814 - #include "fadvise.h"
  23.815 - #include "xdectoint.h"
  23.816 - 
  23.817 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
  23.818 -+      installation; work around this configuration error.  */
  23.819 -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
  23.820 -+# undef MB_LEN_MAX
  23.821 -+# define MB_LEN_MAX 16
  23.822 -+#endif
  23.823 -+
  23.824 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
  23.825 -+#if HAVE_MBRTOWC && defined mbstate_t
  23.826 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
  23.827 -+#endif
  23.828 -+
  23.829 - #define TAB_WIDTH 8
  23.830 - 
  23.831 - /* The official name of this program (e.g., no 'g' prefix).  */
  23.832 -@@ -34,20 +56,41 @@
  23.833 - 
  23.834 - #define AUTHORS proper_name ("David MacKenzie")
  23.835 - 
  23.836 -+#define FATAL_ERROR(Message)                                            \
  23.837 -+  do                                                                    \
  23.838 -+    {                                                                   \
  23.839 -+      error (0, 0, (Message));                                          \
  23.840 -+      usage (2);                                                        \
  23.841 -+    }                                                                   \
  23.842 -+  while (0)
  23.843 -+
  23.844 -+enum operating_mode
  23.845 -+{
  23.846 -+  /* Fold texts by columns that are at the given positions. */
  23.847 -+  column_mode,
  23.848 -+
  23.849 -+  /* Fold texts by bytes that are at the given positions. */
  23.850 -+  byte_mode,
  23.851 -+
  23.852 -+  /* Fold texts by characters that are at the given positions. */
  23.853 -+  character_mode,
  23.854 -+};
  23.855 -+
  23.856 -+/* The argument shows current mode. (Default: column_mode) */
  23.857 -+static enum operating_mode operating_mode;
  23.858 -+
  23.859 - /* If nonzero, try to break on whitespace. */
  23.860 - static bool break_spaces;
  23.861 - 
  23.862 --/* If nonzero, count bytes, not column positions. */
  23.863 --static bool count_bytes;
  23.864 --
  23.865 - /* If nonzero, at least one of the files we read was standard input. */
  23.866 - static bool have_read_stdin;
  23.867 - 
  23.868 --static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::";
  23.869 -+static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::";
  23.870 - 
  23.871 - static struct option const longopts[] =
  23.872 - {
  23.873 -   {"bytes", no_argument, NULL, 'b'},
  23.874 -+  {"characters", no_argument, NULL, 'c'},
  23.875 -   {"spaces", no_argument, NULL, 's'},
  23.876 -   {"width", required_argument, NULL, 'w'},
  23.877 -   {GETOPT_HELP_OPTION_DECL},
  23.878 -@@ -75,6 +118,7 @@ Wrap input lines in each FILE, writing t
  23.879 - 
  23.880 -       fputs (_("\
  23.881 -   -b, --bytes         count bytes rather than columns\n\
  23.882 -+  -c, --characters    count characters rather than columns\n\
  23.883 -   -s, --spaces        break at spaces\n\
  23.884 -   -w, --width=WIDTH   use WIDTH columns instead of 80\n\
  23.885 - "), stdout);
  23.886 -@@ -92,7 +136,7 @@ Wrap input lines in each FILE, writing t
  23.887 - static size_t
  23.888 - adjust_column (size_t column, char c)
  23.889 - {
  23.890 --  if (!count_bytes)
  23.891 -+  if (operating_mode != byte_mode)
  23.892 -     {
  23.893 -       if (c == '\b')
  23.894 -         {
  23.895 -@@ -115,30 +159,14 @@ adjust_column (size_t column, char c)
  23.896 -    to stdout, with maximum line length WIDTH.
  23.897 -    Return true if successful.  */
  23.898 - 
  23.899 --static bool
  23.900 --fold_file (char const *filename, size_t width)
  23.901 -+static void
  23.902 -+fold_text (FILE *istream, size_t width, int *saved_errno)
  23.903 - {
  23.904 --  FILE *istream;
  23.905 -   int c;
  23.906 -   size_t column = 0;		/* Screen column where next char will go. */
  23.907 -   size_t offset_out = 0;	/* Index in 'line_out' for next char. */
  23.908 -   static char *line_out = NULL;
  23.909 -   static size_t allocated_out = 0;
  23.910 --  int saved_errno;
  23.911 --
  23.912 --  if (STREQ (filename, "-"))
  23.913 --    {
  23.914 --      istream = stdin;
  23.915 --      have_read_stdin = true;
  23.916 --    }
  23.917 --  else
  23.918 --    istream = fopen (filename, "r");
  23.919 --
  23.920 --  if (istream == NULL)
  23.921 --    {
  23.922 --      error (0, errno, "%s", quotef (filename));
  23.923 --      return false;
  23.924 --    }
  23.925 - 
  23.926 -   fadvise (istream, FADVISE_SEQUENTIAL);
  23.927 - 
  23.928 -@@ -168,6 +196,15 @@ fold_file (char const *filename, size_t
  23.929 -               bool found_blank = false;
  23.930 -               size_t logical_end = offset_out;
  23.931 - 
  23.932 -+              /* If LINE_OUT has no wide character,
  23.933 -+                 put a new wide character in LINE_OUT
  23.934 -+                 if column is bigger than width. */
  23.935 -+              if (offset_out == 0)
  23.936 -+                {
  23.937 -+                  line_out[offset_out++] = c;
  23.938 -+                  continue;
  23.939 -+                }
  23.940 -+
  23.941 -               /* Look for the last blank. */
  23.942 -               while (logical_end)
  23.943 -                 {
  23.944 -@@ -214,11 +251,221 @@ fold_file (char const *filename, size_t
  23.945 -       line_out[offset_out++] = c;
  23.946 -     }
  23.947 - 
  23.948 --  saved_errno = errno;
  23.949 -+  *saved_errno = errno;
  23.950 -+
  23.951 -+  if (offset_out)
  23.952 -+    fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
  23.953 -+
  23.954 -+}
  23.955 -+
  23.956 -+#if HAVE_MBRTOWC
  23.957 -+static void
  23.958 -+fold_multibyte_text (FILE *istream, size_t width, int *saved_errno)
  23.959 -+{
  23.960 -+  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  23.961 -+  size_t buflen = 0;        /* The length of the byte sequence in buf. */
  23.962 -+  char *bufpos = buf;         /* Next read position of BUF. */
  23.963 -+  wint_t wc;                /* A gotten wide character. */
  23.964 -+  size_t mblength;        /* The byte size of a multibyte character which shows
  23.965 -+                           as same character as WC. */
  23.966 -+  mbstate_t state, state_bak;        /* State of the stream. */
  23.967 -+  int convfail = 0;                /* 1, when conversion is failed. Otherwise 0. */
  23.968 -+
  23.969 -+  static char *line_out = NULL;
  23.970 -+  size_t offset_out = 0;        /* Index in `line_out' for next char. */
  23.971 -+  static size_t allocated_out = 0;
  23.972 -+
  23.973 -+  int increment;
  23.974 -+  size_t column = 0;
  23.975 -+
  23.976 -+  size_t last_blank_pos;
  23.977 -+  size_t last_blank_column;
  23.978 -+  int is_blank_seen;
  23.979 -+  int last_blank_increment = 0;
  23.980 -+  int is_bs_following_last_blank;
  23.981 -+  size_t bs_following_last_blank_num;
  23.982 -+  int is_cr_after_last_blank;
  23.983 -+
  23.984 -+#define CLEAR_FLAGS                                \
  23.985 -+   do                                                \
  23.986 -+     {                                                \
  23.987 -+        last_blank_pos = 0;                        \
  23.988 -+        last_blank_column = 0;                        \
  23.989 -+        is_blank_seen = 0;                        \
  23.990 -+        is_bs_following_last_blank = 0;                \
  23.991 -+        bs_following_last_blank_num = 0;        \
  23.992 -+        is_cr_after_last_blank = 0;                \
  23.993 -+     }                                                \
  23.994 -+   while (0)
  23.995 -+
  23.996 -+#define START_NEW_LINE                        \
  23.997 -+   do                                        \
  23.998 -+     {                                        \
  23.999 -+      putchar ('\n');                        \
 23.1000 -+      column = 0;                        \
 23.1001 -+      offset_out = 0;                        \
 23.1002 -+      CLEAR_FLAGS;                        \
 23.1003 -+    }                                        \
 23.1004 -+   while (0)
 23.1005 -+
 23.1006 -+  CLEAR_FLAGS;
 23.1007 -+  memset (&state, '\0', sizeof(mbstate_t));
 23.1008 -+
 23.1009 -+  for (;; bufpos += mblength, buflen -= mblength)
 23.1010 -+    {
 23.1011 -+      if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream))
 23.1012 -+        {
 23.1013 -+          memmove (buf, bufpos, buflen);
 23.1014 -+          buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream);
 23.1015 -+          bufpos = buf;
 23.1016 -+        }
 23.1017 -+
 23.1018 -+      if (buflen < 1)
 23.1019 -+        break;
 23.1020 -+
 23.1021 -+      /* Get a wide character. */
 23.1022 -+      state_bak = state;
 23.1023 -+      mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state);
 23.1024 -+
 23.1025 -+      switch (mblength)
 23.1026 -+        {
 23.1027 -+        case (size_t)-1:
 23.1028 -+        case (size_t)-2:
 23.1029 -+          convfail++;
 23.1030 -+          state = state_bak;
 23.1031 -+          /* Fall through. */
 23.1032 -+
 23.1033 -+        case 0:
 23.1034 -+          mblength = 1;
 23.1035 -+          break;
 23.1036 -+        }
 23.1037 -+
 23.1038 -+rescan:
 23.1039 -+      if (operating_mode == byte_mode)                        /* byte mode */
 23.1040 -+        increment = mblength;
 23.1041 -+      else if (operating_mode == character_mode)        /* character mode */
 23.1042 -+        increment = 1;
 23.1043 -+      else                                                /* column mode */
 23.1044 -+        {
 23.1045 -+          if (convfail)
 23.1046 -+            increment = 1;
 23.1047 -+          else
 23.1048 -+            {
 23.1049 -+              switch (wc)
 23.1050 -+                {
 23.1051 -+                case L'\n':
 23.1052 -+                  fwrite (line_out, sizeof(char), offset_out, stdout);
 23.1053 -+                  START_NEW_LINE;
 23.1054 -+                  continue;
 23.1055 -+
 23.1056 -+                case L'\b':
 23.1057 -+                  increment = (column > 0) ? -1 : 0;
 23.1058 -+                  break;
 23.1059 -+
 23.1060 -+                case L'\r':
 23.1061 -+                  increment = -1 * column;
 23.1062 -+                  break;
 23.1063 -+
 23.1064 -+                case L'\t':
 23.1065 -+                  increment = 8 - column % 8;
 23.1066 -+                  break;
 23.1067 -+
 23.1068 -+                default:
 23.1069 -+                  increment = wcwidth (wc);
 23.1070 -+                  increment = (increment < 0) ? 0 : increment;
 23.1071 -+                }
 23.1072 -+            }
 23.1073 -+        }
 23.1074 -+
 23.1075 -+      if (column + increment > width && break_spaces && last_blank_pos)
 23.1076 -+        {
 23.1077 -+          fwrite (line_out, sizeof(char), last_blank_pos, stdout);
 23.1078 -+          putchar ('\n');
 23.1079 -+
 23.1080 -+          offset_out = offset_out - last_blank_pos;
 23.1081 -+          column = column - last_blank_column + ((is_cr_after_last_blank)
 23.1082 -+              ? last_blank_increment : bs_following_last_blank_num);
 23.1083 -+          memmove (line_out, line_out + last_blank_pos, offset_out);
 23.1084 -+          CLEAR_FLAGS;
 23.1085 -+          goto rescan;
 23.1086 -+        }
 23.1087 -+
 23.1088 -+      if (column + increment > width && column != 0)
 23.1089 -+        {
 23.1090 -+          fwrite (line_out, sizeof(char), offset_out, stdout);
 23.1091 -+          START_NEW_LINE;
 23.1092 -+          goto rescan;
 23.1093 -+        }
 23.1094 -+
 23.1095 -+      if (allocated_out < offset_out + mblength)
 23.1096 -+        {
 23.1097 -+          line_out = X2REALLOC (line_out, &allocated_out);
 23.1098 -+        }
 23.1099 -+
 23.1100 -+      memcpy (line_out + offset_out, bufpos, mblength);
 23.1101 -+      offset_out += mblength;
 23.1102 -+      column += increment;
 23.1103 -+
 23.1104 -+      if (is_blank_seen && !convfail && wc == L'\r')
 23.1105 -+        is_cr_after_last_blank = 1;
 23.1106 -+
 23.1107 -+      if (is_bs_following_last_blank && !convfail && wc == L'\b')
 23.1108 -+        ++bs_following_last_blank_num;
 23.1109 -+      else
 23.1110 -+        is_bs_following_last_blank = 0;
 23.1111 -+
 23.1112 -+      if (break_spaces && !convfail && iswblank (wc))
 23.1113 -+        {
 23.1114 -+          last_blank_pos = offset_out;
 23.1115 -+          last_blank_column = column;
 23.1116 -+          is_blank_seen = 1;
 23.1117 -+          last_blank_increment = increment;
 23.1118 -+          is_bs_following_last_blank = 1;
 23.1119 -+          bs_following_last_blank_num = 0;
 23.1120 -+          is_cr_after_last_blank = 0;
 23.1121 -+        }
 23.1122 -+    }
 23.1123 -+
 23.1124 -+  *saved_errno = errno;
 23.1125 - 
 23.1126 -   if (offset_out)
 23.1127 -     fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 23.1128 - 
 23.1129 -+}
 23.1130 -+#endif
 23.1131 -+
 23.1132 -+/* Fold file FILENAME, or standard input if FILENAME is "-",
 23.1133 -+   to stdout, with maximum line length WIDTH.
 23.1134 -+   Return 0 if successful, 1 if an error occurs. */
 23.1135 -+
 23.1136 -+static bool
 23.1137 -+fold_file (char const *filename, size_t width)
 23.1138 -+{
 23.1139 -+  FILE *istream;
 23.1140 -+  int saved_errno;
 23.1141 -+
 23.1142 -+  if (STREQ (filename, "-"))
 23.1143 -+    {
 23.1144 -+      istream = stdin;
 23.1145 -+      have_read_stdin = 1;
 23.1146 -+    }
 23.1147 -+  else
 23.1148 -+    istream = fopen (filename, "r");
 23.1149 -+
 23.1150 -+  if (istream == NULL)
 23.1151 -+    {
 23.1152 -+      error (0, errno, "%s", quotef (filename));
 23.1153 -+      return 1;
 23.1154 -+    }
 23.1155 -+
 23.1156 -+  /* Define how ISTREAM is being folded. */
 23.1157 -+#if HAVE_MBRTOWC
 23.1158 -+  if (MB_CUR_MAX > 1)
 23.1159 -+    fold_multibyte_text (istream, width, &saved_errno);
 23.1160 -+  else
 23.1161 -+#endif
 23.1162 -+    fold_text (istream, width, &saved_errno);
 23.1163 -+
 23.1164 -   if (ferror (istream))
 23.1165 -     {
 23.1166 -       error (0, saved_errno, "%s", quotef (filename));
 23.1167 -@@ -251,7 +498,8 @@ main (int argc, char **argv)
 23.1168 - 
 23.1169 -   atexit (close_stdout);
 23.1170 - 
 23.1171 --  break_spaces = count_bytes = have_read_stdin = false;
 23.1172 -+  operating_mode = column_mode;
 23.1173 -+  break_spaces = have_read_stdin = false;
 23.1174 - 
 23.1175 -   while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
 23.1176 -     {
 23.1177 -@@ -260,7 +508,15 @@ main (int argc, char **argv)
 23.1178 -       switch (optc)
 23.1179 -         {
 23.1180 -         case 'b':		/* Count bytes rather than columns. */
 23.1181 --          count_bytes = true;
 23.1182 -+          if (operating_mode != column_mode)
 23.1183 -+            FATAL_ERROR (_("only one way of folding may be specified"));
 23.1184 -+          operating_mode = byte_mode;
 23.1185 -+          break;
 23.1186 -+
 23.1187 -+        case 'c':
 23.1188 -+          if (operating_mode != column_mode)
 23.1189 -+            FATAL_ERROR (_("only one way of folding may be specified"));
 23.1190 -+          operating_mode = character_mode;
 23.1191 -           break;
 23.1192 - 
 23.1193 -         case 's':		/* Break at word boundaries. */
 23.1194 -diff -Naurp coreutils-8.25-orig/src/join.c coreutils-8.25/src/join.c
 23.1195 ---- coreutils-8.25-orig/src/join.c	2016-01-13 05:08:59.000000000 -0600
 23.1196 -+++ coreutils-8.25/src/join.c	2016-02-08 19:07:10.303944625 -0600
 23.1197 -@@ -22,18 +22,32 @@
 23.1198 - #include <sys/types.h>
 23.1199 - #include <getopt.h>
 23.1200 - 
 23.1201 -+/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth().  */
 23.1202 -+#if HAVE_WCHAR_H
 23.1203 -+# include <wchar.h>
 23.1204 -+#endif
 23.1205 -+
 23.1206 -+/* Get iswblank(), towupper.  */
 23.1207 -+#if HAVE_WCTYPE_H
 23.1208 -+# include <wctype.h>
 23.1209 -+#endif
 23.1210 -+
 23.1211 - #include "system.h"
 23.1212 - #include "error.h"
 23.1213 - #include "fadvise.h"
 23.1214 - #include "hard-locale.h"
 23.1215 - #include "linebuffer.h"
 23.1216 --#include "memcasecmp.h"
 23.1217 - #include "quote.h"
 23.1218 - #include "stdio--.h"
 23.1219 - #include "xmemcoll.h"
 23.1220 - #include "xstrtol.h"
 23.1221 - #include "argmatch.h"
 23.1222 - 
 23.1223 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 23.1224 -+#if HAVE_MBRTOWC && defined mbstate_t
 23.1225 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 23.1226 -+#endif
 23.1227 -+
 23.1228 - /* The official name of this program (e.g., no 'g' prefix).  */
 23.1229 - #define PROGRAM_NAME "join"
 23.1230 - 
 23.1231 -@@ -135,10 +149,12 @@ static struct outlist outlist_head;
 23.1232 - /* Last element in 'outlist', where a new element can be added.  */
 23.1233 - static struct outlist *outlist_end = &outlist_head;
 23.1234 - 
 23.1235 --/* Tab character separating fields.  If negative, fields are separated
 23.1236 --   by any nonempty string of blanks, otherwise by exactly one
 23.1237 --   tab character whose value (when cast to unsigned char) equals TAB.  */
 23.1238 --static int tab = -1;
 23.1239 -+/* Tab character separating fields.  If NULL, fields are separated
 23.1240 -+   by any nonempty string of blanks.  */
 23.1241 -+static char *tab = NULL;
 23.1242 -+
 23.1243 -+/* The number of bytes used for tab. */
 23.1244 -+static size_t tablen = 0;
 23.1245 - 
 23.1246 - /* If nonzero, check that the input is correctly ordered. */
 23.1247 - static enum
 23.1248 -@@ -275,13 +291,14 @@ xfields (struct line *line)
 23.1249 -   if (ptr == lim)
 23.1250 -     return;
 23.1251 - 
 23.1252 --  if (0 <= tab && tab != '\n')
 23.1253 -+  if (tab != NULL)
 23.1254 -     {
 23.1255 -+      unsigned char t = tab[0];
 23.1256 -       char *sep;
 23.1257 --      for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1)
 23.1258 -+      for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1)
 23.1259 -         extract_field (line, ptr, sep - ptr);
 23.1260 -     }
 23.1261 --  else if (tab < 0)
 23.1262 -+   else
 23.1263 -     {
 23.1264 -       /* Skip leading blanks before the first field.  */
 23.1265 -       while (field_sep (*ptr))
 23.1266 -@@ -305,6 +322,147 @@ xfields (struct line *line)
 23.1267 -   extract_field (line, ptr, lim - ptr);
 23.1268 - }
 23.1269 - 
 23.1270 -+#if HAVE_MBRTOWC
 23.1271 -+static void
 23.1272 -+xfields_multibyte (struct line *line)
 23.1273 -+{
 23.1274 -+  char *ptr = line->buf.buffer;
 23.1275 -+  char const *lim = ptr + line->buf.length - 1;
 23.1276 -+  wchar_t wc = 0;
 23.1277 -+  size_t mblength = 1;
 23.1278 -+  mbstate_t state, state_bak;
 23.1279 -+
 23.1280 -+  memset (&state, 0, sizeof (mbstate_t));
 23.1281 -+
 23.1282 -+  if (ptr >= lim)
 23.1283 -+    return;
 23.1284 -+
 23.1285 -+  if (tab != NULL)
 23.1286 -+    {
 23.1287 -+      char *sep = ptr;
 23.1288 -+      for (; ptr < lim; ptr = sep + mblength)
 23.1289 -+	{
 23.1290 -+	  sep = ptr;
 23.1291 -+	  while (sep < lim)
 23.1292 -+	    {
 23.1293 -+	      state_bak = state;
 23.1294 -+	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 23.1295 -+
 23.1296 -+	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1297 -+		{
 23.1298 -+		  mblength = 1;
 23.1299 -+		  state = state_bak;
 23.1300 -+		}
 23.1301 -+	      mblength = (mblength < 1) ? 1 : mblength;
 23.1302 -+
 23.1303 -+	      if (mblength == tablen && !memcmp (sep, tab, mblength))
 23.1304 -+		break;
 23.1305 -+	      else
 23.1306 -+		{
 23.1307 -+		  sep += mblength;
 23.1308 -+		  continue;
 23.1309 -+		}
 23.1310 -+	    }
 23.1311 -+
 23.1312 -+	  if (sep >= lim)
 23.1313 -+	    break;
 23.1314 -+
 23.1315 -+	  extract_field (line, ptr, sep - ptr);
 23.1316 -+	}
 23.1317 -+    }
 23.1318 -+  else
 23.1319 -+    {
 23.1320 -+      /* Skip leading blanks before the first field.  */
 23.1321 -+      while(ptr < lim)
 23.1322 -+      {
 23.1323 -+        state_bak = state;
 23.1324 -+        mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 23.1325 -+
 23.1326 -+        if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1327 -+          {
 23.1328 -+            mblength = 1;
 23.1329 -+            state = state_bak;
 23.1330 -+            break;
 23.1331 -+          }
 23.1332 -+        mblength = (mblength < 1) ? 1 : mblength;
 23.1333 -+
 23.1334 -+        if (!iswblank(wc) && wc != '\n')
 23.1335 -+          break;
 23.1336 -+        ptr += mblength;
 23.1337 -+      }
 23.1338 -+
 23.1339 -+      do
 23.1340 -+	{
 23.1341 -+	  char *sep;
 23.1342 -+	  state_bak = state;
 23.1343 -+	  mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 23.1344 -+	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1345 -+	    {
 23.1346 -+	      mblength = 1;
 23.1347 -+	      state = state_bak;
 23.1348 -+	      break;
 23.1349 -+	    }
 23.1350 -+	  mblength = (mblength < 1) ? 1 : mblength;
 23.1351 -+
 23.1352 -+	  sep = ptr + mblength;
 23.1353 -+	  while (sep < lim)
 23.1354 -+	    {
 23.1355 -+	      state_bak = state;
 23.1356 -+	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 23.1357 -+	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1358 -+		{
 23.1359 -+		  mblength = 1;
 23.1360 -+		  state = state_bak;
 23.1361 -+		  break;
 23.1362 -+		}
 23.1363 -+	      mblength = (mblength < 1) ? 1 : mblength;
 23.1364 -+
 23.1365 -+	      if (iswblank (wc) || wc == '\n')
 23.1366 -+		break;
 23.1367 -+
 23.1368 -+	      sep += mblength;
 23.1369 -+	    }
 23.1370 -+
 23.1371 -+	  extract_field (line, ptr, sep - ptr);
 23.1372 -+	  if (sep >= lim)
 23.1373 -+	    return;
 23.1374 -+
 23.1375 -+	  state_bak = state;
 23.1376 -+	  mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 23.1377 -+	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1378 -+	    {
 23.1379 -+	      mblength = 1;
 23.1380 -+	      state = state_bak;
 23.1381 -+	      break;
 23.1382 -+	    }
 23.1383 -+	  mblength = (mblength < 1) ? 1 : mblength;
 23.1384 -+
 23.1385 -+	  ptr = sep + mblength;
 23.1386 -+	  while (ptr < lim)
 23.1387 -+	    {
 23.1388 -+	      state_bak = state;
 23.1389 -+	      mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 23.1390 -+	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1391 -+		{
 23.1392 -+		  mblength = 1;
 23.1393 -+		  state = state_bak;
 23.1394 -+		  break;
 23.1395 -+		}
 23.1396 -+	      mblength = (mblength < 1) ? 1 : mblength;
 23.1397 -+
 23.1398 -+	      if (!iswblank (wc) && wc != '\n')
 23.1399 -+		break;
 23.1400 -+
 23.1401 -+	      ptr += mblength;
 23.1402 -+	    }
 23.1403 -+	}
 23.1404 -+      while (ptr < lim);
 23.1405 -+    }
 23.1406 -+
 23.1407 -+  extract_field (line, ptr, lim - ptr);
 23.1408 -+}
 23.1409 -+#endif
 23.1410 -+
 23.1411 - static void
 23.1412 - freeline (struct line *line)
 23.1413 - {
 23.1414 -@@ -326,56 +484,133 @@ keycmp (struct line const *line1, struct
 23.1415 -         size_t jf_1, size_t jf_2)
 23.1416 - {
 23.1417 -   /* Start of field to compare in each file.  */
 23.1418 --  char *beg1;
 23.1419 --  char *beg2;
 23.1420 --
 23.1421 --  size_t len1;
 23.1422 --  size_t len2;		/* Length of fields to compare.  */
 23.1423 -+  char *beg[2];
 23.1424 -+  char *copy[2];
 23.1425 -+  size_t len[2]; 	/* Length of fields to compare.  */
 23.1426 -   int diff;
 23.1427 -+  int i, j;
 23.1428 -+  int mallocd = 0;
 23.1429 - 
 23.1430 -   if (jf_1 < line1->nfields)
 23.1431 -     {
 23.1432 --      beg1 = line1->fields[jf_1].beg;
 23.1433 --      len1 = line1->fields[jf_1].len;
 23.1434 -+      beg[0] = line1->fields[jf_1].beg;
 23.1435 -+      len[0] = line1->fields[jf_1].len;
 23.1436 -     }
 23.1437 -   else
 23.1438 -     {
 23.1439 --      beg1 = NULL;
 23.1440 --      len1 = 0;
 23.1441 -+      beg[0] = NULL;
 23.1442 -+      len[0] = 0;
 23.1443 -     }
 23.1444 - 
 23.1445 -   if (jf_2 < line2->nfields)
 23.1446 -     {
 23.1447 --      beg2 = line2->fields[jf_2].beg;
 23.1448 --      len2 = line2->fields[jf_2].len;
 23.1449 -+      beg[1] = line2->fields[jf_2].beg;
 23.1450 -+      len[1] = line2->fields[jf_2].len;
 23.1451 -     }
 23.1452 -   else
 23.1453 -     {
 23.1454 --      beg2 = NULL;
 23.1455 --      len2 = 0;
 23.1456 -+      beg[1] = NULL;
 23.1457 -+      len[1] = 0;
 23.1458 -     }
 23.1459 - 
 23.1460 --  if (len1 == 0)
 23.1461 --    return len2 == 0 ? 0 : -1;
 23.1462 --  if (len2 == 0)
 23.1463 -+  if (len[0] == 0)
 23.1464 -+    return len[1] == 0 ? 0 : -1;
 23.1465 -+  if (len[1] == 0)
 23.1466 -     return 1;
 23.1467 - 
 23.1468 -   if (ignore_case)
 23.1469 -     {
 23.1470 --      /* FIXME: ignore_case does not work with NLS (in particular,
 23.1471 --         with multibyte chars).  */
 23.1472 --      diff = memcasecmp (beg1, beg2, MIN (len1, len2));
 23.1473 -+#ifdef HAVE_MBRTOWC
 23.1474 -+      if (MB_CUR_MAX > 1)
 23.1475 -+      {
 23.1476 -+        size_t mblength;
 23.1477 -+        wchar_t wc, uwc;
 23.1478 -+        mbstate_t state, state_bak;
 23.1479 -+
 23.1480 -+        memset (&state, '\0', sizeof (mbstate_t));
 23.1481 -+
 23.1482 -+        for (i = 0; i < 2; i++)
 23.1483 -+          {
 23.1484 -+            mallocd = 1;
 23.1485 -+            copy[i] = xmalloc (len[i] + 1);
 23.1486 -+            memset (copy[i], '\0',len[i] + 1);
 23.1487 -+
 23.1488 -+            for (j = 0; j < MIN (len[0], len[1]);)
 23.1489 -+              {
 23.1490 -+                state_bak = state;
 23.1491 -+                mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state);
 23.1492 -+
 23.1493 -+                switch (mblength)
 23.1494 -+                  {
 23.1495 -+                  case (size_t) -1:
 23.1496 -+                  case (size_t) -2:
 23.1497 -+                    state = state_bak;
 23.1498 -+                    /* Fall through */
 23.1499 -+                  case 0:
 23.1500 -+                    mblength = 1;
 23.1501 -+                    break;
 23.1502 -+
 23.1503 -+                  default:
 23.1504 -+                    uwc = towupper (wc);
 23.1505 -+
 23.1506 -+                    if (uwc != wc)
 23.1507 -+                      {
 23.1508 -+                        mbstate_t state_wc;
 23.1509 -+                        size_t mblen;
 23.1510 -+
 23.1511 -+                        memset (&state_wc, '\0', sizeof (mbstate_t));
 23.1512 -+                        mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 23.1513 -+                        assert (mblen != (size_t)-1);
 23.1514 -+                      }
 23.1515 -+                    else
 23.1516 -+                      memcpy (copy[i] + j, beg[i] + j, mblength);
 23.1517 -+                  }
 23.1518 -+                j += mblength;
 23.1519 -+              }
 23.1520 -+            copy[i][j] = '\0';
 23.1521 -+          }
 23.1522 -+      }
 23.1523 -+      else
 23.1524 -+#endif
 23.1525 -+      {
 23.1526 -+        for (i = 0; i < 2; i++)
 23.1527 -+          {
 23.1528 -+            mallocd = 1;
 23.1529 -+            copy[i] = xmalloc (len[i] + 1);
 23.1530 -+
 23.1531 -+            for (j = 0; j < MIN (len[0], len[1]); j++)
 23.1532 -+              copy[i][j] = toupper (beg[i][j]);
 23.1533 -+
 23.1534 -+            copy[i][j] = '\0';
 23.1535 -+          }
 23.1536 -+      }
 23.1537 -     }
 23.1538 -   else
 23.1539 -     {
 23.1540 --      if (hard_LC_COLLATE)
 23.1541 --        return xmemcoll (beg1, len1, beg2, len2);
 23.1542 --      diff = memcmp (beg1, beg2, MIN (len1, len2));
 23.1543 -+      copy[0] = beg[0];
 23.1544 -+      copy[1] = beg[1];
 23.1545 -+    }
 23.1546 -+
 23.1547 -+  if (hard_LC_COLLATE)
 23.1548 -+    {
 23.1549 -+      diff = xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]);
 23.1550 -+
 23.1551 -+      if (mallocd)
 23.1552 -+        for (i = 0; i < 2; i++)
 23.1553 -+          free (copy[i]);
 23.1554 -+
 23.1555 -+      return diff;
 23.1556 -     }
 23.1557 -+  diff = memcmp (copy[0], copy[1], MIN (len[0], len[1]));
 23.1558 -+
 23.1559 -+  if (mallocd)
 23.1560 -+    for (i = 0; i < 2; i++)
 23.1561 -+      free (copy[i]);
 23.1562 -+
 23.1563 - 
 23.1564 -   if (diff)
 23.1565 -     return diff;
 23.1566 --  return len1 < len2 ? -1 : len1 != len2;
 23.1567 -+  return len[0] - len[1];
 23.1568 - }
 23.1569 - 
 23.1570 - /* Check that successive input lines PREV and CURRENT from input file
 23.1571 -@@ -467,6 +702,11 @@ get_line (FILE *fp, struct line **linep,
 23.1572 -     }
 23.1573 -   ++line_no[which - 1];
 23.1574 - 
 23.1575 -+#if HAVE_MBRTOWC
 23.1576 -+  if (MB_CUR_MAX > 1)
 23.1577 -+    xfields_multibyte (line);
 23.1578 -+  else
 23.1579 -+#endif
 23.1580 -   xfields (line);
 23.1581 - 
 23.1582 -   if (prevline[which - 1])
 23.1583 -@@ -566,21 +806,28 @@ prfield (size_t n, struct line const *li
 23.1584 - 
 23.1585 - /* Output all the fields in line, other than the join field.  */
 23.1586 - 
 23.1587 -+#define PUT_TAB_CHAR							\
 23.1588 -+  do									\
 23.1589 -+    {									\
 23.1590 -+      (tab != NULL) ?							\
 23.1591 -+	fwrite(tab, sizeof(char), tablen, stdout) : putchar (' ');	\
 23.1592 -+    }									\
 23.1593 -+  while (0)
 23.1594 -+
 23.1595 - static void
 23.1596 - prfields (struct line const *line, size_t join_field, size_t autocount)
 23.1597 - {
 23.1598 -   size_t i;
 23.1599 -   size_t nfields = autoformat ? autocount : line->nfields;
 23.1600 --  char output_separator = tab < 0 ? ' ' : tab;
 23.1601 - 
 23.1602 -   for (i = 0; i < join_field && i < nfields; ++i)
 23.1603 -     {
 23.1604 --      putchar (output_separator);
 23.1605 -+      PUT_TAB_CHAR;
 23.1606 -       prfield (i, line);
 23.1607 -     }
 23.1608 -   for (i = join_field + 1; i < nfields; ++i)
 23.1609 -     {
 23.1610 --      putchar (output_separator);
 23.1611 -+      PUT_TAB_CHAR;
 23.1612 -       prfield (i, line);
 23.1613 -     }
 23.1614 - }
 23.1615 -@@ -591,7 +838,6 @@ static void
 23.1616 - prjoin (struct line const *line1, struct line const *line2)
 23.1617 - {
 23.1618 -   const struct outlist *outlist;
 23.1619 --  char output_separator = tab < 0 ? ' ' : tab;
 23.1620 -   size_t field;
 23.1621 -   struct line const *line;
 23.1622 - 
 23.1623 -@@ -625,7 +871,7 @@ prjoin (struct line const *line1, struct
 23.1624 -           o = o->next;
 23.1625 -           if (o == NULL)
 23.1626 -             break;
 23.1627 --          putchar (output_separator);
 23.1628 -+          PUT_TAB_CHAR;
 23.1629 -         }
 23.1630 -       putchar (eolchar);
 23.1631 -     }
 23.1632 -@@ -1103,21 +1349,46 @@ main (int argc, char **argv)
 23.1633 - 
 23.1634 -         case 't':
 23.1635 -           {
 23.1636 --            unsigned char newtab = optarg[0];
 23.1637 -+            char *newtab = NULL;
 23.1638 -+            size_t newtablen;
 23.1639 -+            newtab = xstrdup (optarg);
 23.1640 -+#if HAVE_MBRTOWC
 23.1641 -+            if (MB_CUR_MAX > 1)
 23.1642 -+              {
 23.1643 -+                mbstate_t state;
 23.1644 -+
 23.1645 -+                memset (&state, 0, sizeof (mbstate_t));
 23.1646 -+                newtablen = mbrtowc (NULL, newtab,
 23.1647 -+                                     strnlen (newtab, MB_LEN_MAX),
 23.1648 -+                                     &state);
 23.1649 -+                if (newtablen == (size_t) 0
 23.1650 -+                    || newtablen == (size_t) -1
 23.1651 -+                    || newtablen == (size_t) -2)
 23.1652 -+                  newtablen = 1;
 23.1653 -+              }
 23.1654 -+            else
 23.1655 -+#endif
 23.1656 -+              newtablen = 1;
 23.1657 -             if (! newtab)
 23.1658 --              newtab = '\n'; /* '' => process the whole line.  */
 23.1659 -+            {
 23.1660 -+              newtab = (char*)"\n"; /* '' => process the whole line.  */
 23.1661 -+            }
 23.1662 -             else if (optarg[1])
 23.1663 -               {
 23.1664 --                if (STREQ (optarg, "\\0"))
 23.1665 --                  newtab = '\0';
 23.1666 --                else
 23.1667 --                  error (EXIT_FAILURE, 0, _("multi-character tab %s"),
 23.1668 --                         quote (optarg));
 23.1669 -+                if (newtablen == 1 && newtab[1])
 23.1670 -+                {
 23.1671 -+                  if (STREQ (newtab, "\\0"))
 23.1672 -+                     newtab[0] = '\0';
 23.1673 -+                }
 23.1674 -+              }
 23.1675 -+            if (tab != NULL && strcmp (tab, newtab))
 23.1676 -+              {
 23.1677 -+                free (newtab);
 23.1678 -+                error (EXIT_FAILURE, 0, _("incompatible tabs"));
 23.1679 -               }
 23.1680 --            if (0 <= tab && tab != newtab)
 23.1681 --              error (EXIT_FAILURE, 0, _("incompatible tabs"));
 23.1682 -             tab = newtab;
 23.1683 --          }
 23.1684 -+            tablen = newtablen;
 23.1685 -+           }
 23.1686 -           break;
 23.1687 - 
 23.1688 -         case 'z':
 23.1689 -diff -Naurp coreutils-8.25-orig/src/pr.c coreutils-8.25/src/pr.c
 23.1690 ---- coreutils-8.25-orig/src/pr.c	2016-01-01 07:48:50.000000000 -0600
 23.1691 -+++ coreutils-8.25/src/pr.c	2016-02-08 19:07:10.306944635 -0600
 23.1692 -@@ -311,6 +311,24 @@
 23.1693 - 
 23.1694 - #include <getopt.h>
 23.1695 - #include <sys/types.h>
 23.1696 -+
 23.1697 -+/* Get MB_LEN_MAX.  */
 23.1698 -+#include <limits.h>
 23.1699 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 23.1700 -+   installation; work around this configuration error.  */
 23.1701 -+#if !defined MB_LEN_MAX || MB_LEN_MAX == 1
 23.1702 -+# define MB_LEN_MAX 16
 23.1703 -+#endif
 23.1704 -+
 23.1705 -+/* Get MB_CUR_MAX.  */
 23.1706 -+#include <stdlib.h>
 23.1707 -+
 23.1708 -+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
 23.1709 -+/* Get mbstate_t, mbrtowc(), wcwidth().  */
 23.1710 -+#if HAVE_WCHAR_H
 23.1711 -+# include <wchar.h>
 23.1712 -+#endif
 23.1713 -+
 23.1714 - #include "system.h"
 23.1715 - #include "error.h"
 23.1716 - #include "fadvise.h"
 23.1717 -@@ -323,6 +341,18 @@
 23.1718 - #include "xstrtol.h"
 23.1719 - #include "xdectoint.h"
 23.1720 - 
 23.1721 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 23.1722 -+#if HAVE_MBRTOWC && defined mbstate_t
 23.1723 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 23.1724 -+#endif
 23.1725 -+
 23.1726 -+#ifndef HAVE_DECL_WCWIDTH
 23.1727 -+"this configure-time declaration test was not run"
 23.1728 -+#endif
 23.1729 -+#if !HAVE_DECL_WCWIDTH
 23.1730 -+extern int wcwidth ();
 23.1731 -+#endif
 23.1732 -+
 23.1733 - /* The official name of this program (e.g., no 'g' prefix).  */
 23.1734 - #define PROGRAM_NAME "pr"
 23.1735 - 
 23.1736 -@@ -415,7 +445,20 @@ struct COLUMN
 23.1737 - 
 23.1738 - typedef struct COLUMN COLUMN;
 23.1739 - 
 23.1740 --static int char_to_clump (char c);
 23.1741 -+/* Funtion pointers to switch functions for single byte locale or for
 23.1742 -+   multibyte locale. If multibyte functions do not exist in your sysytem,
 23.1743 -+   these pointers always point the function for single byte locale. */
 23.1744 -+static void (*print_char) (char c);
 23.1745 -+static int (*char_to_clump) (char c);
 23.1746 -+
 23.1747 -+/* Functions for single byte locale. */
 23.1748 -+static void print_char_single (char c);
 23.1749 -+static int char_to_clump_single (char c);
 23.1750 -+
 23.1751 -+/* Functions for multibyte locale. */
 23.1752 -+static void print_char_multi (char c);
 23.1753 -+static int char_to_clump_multi (char c);
 23.1754 -+
 23.1755 - static bool read_line (COLUMN *p);
 23.1756 - static bool print_page (void);
 23.1757 - static bool print_stored (COLUMN *p);
 23.1758 -@@ -427,6 +470,7 @@ static void add_line_number (COLUMN *p);
 23.1759 - static void getoptnum (const char *n_str, int min, int *num,
 23.1760 -                        const char *errfmt);
 23.1761 - static void getoptarg (char *arg, char switch_char, char *character,
 23.1762 -+                       int *character_length, int *character_width,
 23.1763 -                        int *number);
 23.1764 - static void print_files (int number_of_files, char **av);
 23.1765 - static void init_parameters (int number_of_files);
 23.1766 -@@ -440,7 +484,6 @@ static void store_char (char c);
 23.1767 - static void pad_down (unsigned int lines);
 23.1768 - static void read_rest_of_line (COLUMN *p);
 23.1769 - static void skip_read (COLUMN *p, int column_number);
 23.1770 --static void print_char (char c);
 23.1771 - static void cleanup (void);
 23.1772 - static void print_sep_string (void);
 23.1773 - static void separator_string (const char *optarg_S);
 23.1774 -@@ -452,7 +495,7 @@ static COLUMN *column_vector;
 23.1775 -    we store the leftmost columns contiguously in buff.
 23.1776 -    To print a line from buff, get the index of the first character
 23.1777 -    from line_vector[i], and print up to line_vector[i + 1]. */
 23.1778 --static char *buff;
 23.1779 -+static unsigned char *buff;
 23.1780 - 
 23.1781 - /* Index of the position in buff where the next character
 23.1782 -    will be stored. */
 23.1783 -@@ -556,7 +599,7 @@ static int chars_per_column;
 23.1784 - static bool untabify_input = false;
 23.1785 - 
 23.1786 - /* (-e) The input tab character. */
 23.1787 --static char input_tab_char = '\t';
 23.1788 -+static char input_tab_char[MB_LEN_MAX] = "\t";
 23.1789 - 
 23.1790 - /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
 23.1791 -    where the leftmost column is 1. */
 23.1792 -@@ -566,7 +609,10 @@ static int chars_per_input_tab = 8;
 23.1793 - static bool tabify_output = false;
 23.1794 - 
 23.1795 - /* (-i) The output tab character. */
 23.1796 --static char output_tab_char = '\t';
 23.1797 -+static char output_tab_char[MB_LEN_MAX] = "\t";
 23.1798 -+
 23.1799 -+/* (-i) The byte length of output tab character. */
 23.1800 -+static int output_tab_char_length = 1;
 23.1801 - 
 23.1802 - /* (-i) The width of the output tab. */
 23.1803 - static int chars_per_output_tab = 8;
 23.1804 -@@ -636,7 +682,13 @@ static int line_number;
 23.1805 - static bool numbered_lines = false;
 23.1806 - 
 23.1807 - /* (-n) Character which follows each line number. */
 23.1808 --static char number_separator = '\t';
 23.1809 -+static char number_separator[MB_LEN_MAX] = "\t";
 23.1810 -+
 23.1811 -+/* (-n) The byte length of the character which follows each line number. */
 23.1812 -+static int number_separator_length = 1;
 23.1813 -+
 23.1814 -+/* (-n) The character width of the character which follows each line number. */
 23.1815 -+static int number_separator_width = 0;
 23.1816 - 
 23.1817 - /* (-n) line counting starts with 1st line of input file (not with 1st
 23.1818 -    line of 1st page printed). */
 23.1819 -@@ -689,6 +741,7 @@ static bool use_col_separator = false;
 23.1820 -    -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */
 23.1821 - static char *col_sep_string = (char *) "";
 23.1822 - static int col_sep_length = 0;
 23.1823 -+static int col_sep_width = 0;
 23.1824 - static char *column_separator = (char *) " ";
 23.1825 - static char *line_separator = (char *) "\t";
 23.1826 - 
 23.1827 -@@ -839,6 +892,13 @@ separator_string (const char *optarg_S)
 23.1828 -   col_sep_length = (int) strlen (optarg_S);
 23.1829 -   col_sep_string = xmalloc (col_sep_length + 1);
 23.1830 -   strcpy (col_sep_string, optarg_S);
 23.1831 -+
 23.1832 -+#if HAVE_MBRTOWC
 23.1833 -+  if (MB_CUR_MAX > 1)
 23.1834 -+    col_sep_width = mbswidth (col_sep_string, 0);
 23.1835 -+  else
 23.1836 -+#endif
 23.1837 -+    col_sep_width = col_sep_length;
 23.1838 - }
 23.1839 - 
 23.1840 - int
 23.1841 -@@ -863,6 +923,21 @@ main (int argc, char **argv)
 23.1842 - 
 23.1843 -   atexit (close_stdout);
 23.1844 - 
 23.1845 -+/* Define which functions are used, the ones for single byte locale or the ones
 23.1846 -+   for multibyte locale. */
 23.1847 -+#if HAVE_MBRTOWC
 23.1848 -+  if (MB_CUR_MAX > 1)
 23.1849 -+    {
 23.1850 -+      print_char = print_char_multi;
 23.1851 -+      char_to_clump = char_to_clump_multi;
 23.1852 -+    }
 23.1853 -+  else
 23.1854 -+#endif
 23.1855 -+    {
 23.1856 -+      print_char = print_char_single;
 23.1857 -+      char_to_clump = char_to_clump_single;
 23.1858 -+    }
 23.1859 -+
 23.1860 -   n_files = 0;
 23.1861 -   file_names = (argc > 1
 23.1862 -                 ? xmalloc ((argc - 1) * sizeof (char *))
 23.1863 -@@ -939,8 +1014,12 @@ main (int argc, char **argv)
 23.1864 -           break;
 23.1865 -         case 'e':
 23.1866 -           if (optarg)
 23.1867 --            getoptarg (optarg, 'e', &input_tab_char,
 23.1868 --                       &chars_per_input_tab);
 23.1869 -+            {
 23.1870 -+              int dummy_length, dummy_width;
 23.1871 -+
 23.1872 -+              getoptarg (optarg, 'e', input_tab_char, &dummy_length,
 23.1873 -+                         &dummy_width, &chars_per_input_tab);
 23.1874 -+            }
 23.1875 -           /* Could check tab width > 0. */
 23.1876 -           untabify_input = true;
 23.1877 -           break;
 23.1878 -@@ -953,8 +1032,12 @@ main (int argc, char **argv)
 23.1879 -           break;
 23.1880 -         case 'i':
 23.1881 -           if (optarg)
 23.1882 --            getoptarg (optarg, 'i', &output_tab_char,
 23.1883 --                       &chars_per_output_tab);
 23.1884 -+            {
 23.1885 -+              int dummy_width;
 23.1886 -+
 23.1887 -+              getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length,
 23.1888 -+                         &dummy_width, &chars_per_output_tab);
 23.1889 -+            }
 23.1890 -           /* Could check tab width > 0. */
 23.1891 -           tabify_output = true;
 23.1892 -           break;
 23.1893 -@@ -972,8 +1055,8 @@ main (int argc, char **argv)
 23.1894 -         case 'n':
 23.1895 -           numbered_lines = true;
 23.1896 -           if (optarg)
 23.1897 --            getoptarg (optarg, 'n', &number_separator,
 23.1898 --                       &chars_per_number);
 23.1899 -+            getoptarg (optarg, 'n', number_separator, &number_separator_length,
 23.1900 -+                       &number_separator_width, &chars_per_number);
 23.1901 -           break;
 23.1902 -         case 'N':
 23.1903 -           skip_count = false;
 23.1904 -@@ -997,7 +1080,7 @@ main (int argc, char **argv)
 23.1905 -           old_s = false;
 23.1906 -           /* Reset an additional input of -s, -S dominates -s */
 23.1907 -           col_sep_string = bad_cast ("");
 23.1908 --          col_sep_length = 0;
 23.1909 -+          col_sep_length = col_sep_width = 0;
 23.1910 -           use_col_separator = true;
 23.1911 -           if (optarg)
 23.1912 -             separator_string (optarg);
 23.1913 -@@ -1152,10 +1235,45 @@ getoptnum (const char *n_str, int min, i
 23.1914 -    a number. */
 23.1915 - 
 23.1916 - static void
 23.1917 --getoptarg (char *arg, char switch_char, char *character, int *number)
 23.1918 -+getoptarg (char *arg, char switch_char, char *character, int *character_length,
 23.1919 -+           int *character_width, int *number)
 23.1920 - {
 23.1921 -   if (!ISDIGIT (*arg))
 23.1922 --    *character = *arg++;
 23.1923 -+    {
 23.1924 -+#ifdef HAVE_MBRTOWC
 23.1925 -+      if (MB_CUR_MAX > 1)        /* for multibyte locale. */
 23.1926 -+        {
 23.1927 -+          wchar_t wc;
 23.1928 -+          size_t mblength;
 23.1929 -+          int width;
 23.1930 -+          mbstate_t state = {'\0'};
 23.1931 -+
 23.1932 -+          mblength = mbrtowc (&wc, arg, strnlen(arg, MB_LEN_MAX), &state);
 23.1933 -+
 23.1934 -+          if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.1935 -+            {
 23.1936 -+              *character_length = 1;
 23.1937 -+              *character_width = 1;
 23.1938 -+            }
 23.1939 -+          else
 23.1940 -+            {
 23.1941 -+              *character_length = (mblength < 1) ? 1 : mblength;
 23.1942 -+              width = wcwidth (wc);
 23.1943 -+              *character_width = (width < 0) ? 0 : width;
 23.1944 -+            }
 23.1945 -+
 23.1946 -+          strncpy (character, arg, *character_length);
 23.1947 -+          arg += *character_length;
 23.1948 -+        }
 23.1949 -+      else                        /* for single byte locale. */
 23.1950 -+#endif
 23.1951 -+        {
 23.1952 -+          *character = *arg++;
 23.1953 -+          *character_length = 1;
 23.1954 -+          *character_width = 1;
 23.1955 -+        }
 23.1956 -+    }
 23.1957 -+
 23.1958 -   if (*arg)
 23.1959 -     {
 23.1960 -       long int tmp_long;
 23.1961 -@@ -1177,6 +1295,11 @@ static void
 23.1962 - init_parameters (int number_of_files)
 23.1963 - {
 23.1964 -   int chars_used_by_number = 0;
 23.1965 -+  int mb_len = 1;
 23.1966 -+#if HAVE_MBRTOWC
 23.1967 -+  if (MB_CUR_MAX > 1)
 23.1968 -+    mb_len = MB_LEN_MAX;
 23.1969 -+#endif
 23.1970 - 
 23.1971 -   lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
 23.1972 -   if (lines_per_body <= 0)
 23.1973 -@@ -1214,7 +1337,7 @@ init_parameters (int number_of_files)
 23.1974 -           else
 23.1975 -             col_sep_string = column_separator;
 23.1976 - 
 23.1977 --          col_sep_length = 1;
 23.1978 -+          col_sep_length = col_sep_width = 1;
 23.1979 -           use_col_separator = true;
 23.1980 -         }
 23.1981 -       /* It's rather pointless to define a TAB separator with column
 23.1982 -@@ -1244,11 +1367,11 @@ init_parameters (int number_of_files)
 23.1983 -              + TAB_WIDTH (chars_per_input_tab, chars_per_number);   */
 23.1984 - 
 23.1985 -       /* Estimate chars_per_text without any margin and keep it constant. */
 23.1986 --      if (number_separator == '\t')
 23.1987 -+      if (number_separator[0] == '\t')
 23.1988 -         number_width = (chars_per_number
 23.1989 -                         + TAB_WIDTH (chars_per_default_tab, chars_per_number));
 23.1990 -       else
 23.1991 --        number_width = chars_per_number + 1;
 23.1992 -+        number_width = chars_per_number + number_separator_width;
 23.1993 - 
 23.1994 -       /* The number is part of the column width unless we are
 23.1995 -          printing files in parallel. */
 23.1996 -@@ -1257,7 +1380,7 @@ init_parameters (int number_of_files)
 23.1997 -     }
 23.1998 - 
 23.1999 -   chars_per_column = (chars_per_line - chars_used_by_number
 23.2000 --                      - (columns - 1) * col_sep_length) / columns;
 23.2001 -+                      - (columns - 1) * col_sep_width) / columns;
 23.2002 - 
 23.2003 -   if (chars_per_column < 1)
 23.2004 -     error (EXIT_FAILURE, 0, _("page width too narrow"));
 23.2005 -@@ -1275,7 +1398,7 @@ init_parameters (int number_of_files)
 23.2006 -      We've to use 8 as the lower limit, if we use chars_per_default_tab = 8
 23.2007 -      to expand a tab which is not an input_tab-char. */
 23.2008 -   free (clump_buff);
 23.2009 --  clump_buff = xmalloc (MAX (8, chars_per_input_tab));
 23.2010 -+  clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab));
 23.2011 - }
 23.2012 - 
 23.2013 - /* Open the necessary files,
 23.2014 -@@ -1383,7 +1506,7 @@ init_funcs (void)
 23.2015 - 
 23.2016 -   /* Enlarge p->start_position of first column to use the same form of
 23.2017 -      padding_not_printed with all columns. */
 23.2018 --  h = h + col_sep_length;
 23.2019 -+  h = h + col_sep_width;
 23.2020 - 
 23.2021 -   /* This loop takes care of all but the rightmost column. */
 23.2022 - 
 23.2023 -@@ -1417,7 +1540,7 @@ init_funcs (void)
 23.2024 -         }
 23.2025 -       else
 23.2026 -         {
 23.2027 --          h = h_next + col_sep_length;
 23.2028 -+          h = h_next + col_sep_width;
 23.2029 -           h_next = h + chars_per_column;
 23.2030 -         }
 23.2031 -     }
 23.2032 -@@ -1708,9 +1831,9 @@ static void
 23.2033 - align_column (COLUMN *p)
 23.2034 - {
 23.2035 -   padding_not_printed = p->start_position;
 23.2036 --  if (padding_not_printed - col_sep_length > 0)
 23.2037 -+  if (padding_not_printed - col_sep_width > 0)
 23.2038 -     {
 23.2039 --      pad_across_to (padding_not_printed - col_sep_length);
 23.2040 -+      pad_across_to (padding_not_printed - col_sep_width);
 23.2041 -       padding_not_printed = ANYWHERE;
 23.2042 -     }
 23.2043 - 
 23.2044 -@@ -1981,13 +2104,13 @@ store_char (char c)
 23.2045 -       /* May be too generous. */
 23.2046 -       buff = X2REALLOC (buff, &buff_allocated);
 23.2047 -     }
 23.2048 --  buff[buff_current++] = c;
 23.2049 -+  buff[buff_current++] = (unsigned char) c;
 23.2050 - }
 23.2051 - 
 23.2052 - static void
 23.2053 - add_line_number (COLUMN *p)
 23.2054 - {
 23.2055 --  int i;
 23.2056 -+  int i, j;
 23.2057 -   char *s;
 23.2058 -   int num_width;
 23.2059 - 
 23.2060 -@@ -2004,22 +2127,24 @@ add_line_number (COLUMN *p)
 23.2061 -       /* Tabification is assumed for multiple columns, also for n-separators,
 23.2062 -          but 'default n-separator = TAB' hasn't been given priority over
 23.2063 -          equal column_width also specified by POSIX. */
 23.2064 --      if (number_separator == '\t')
 23.2065 -+      if (number_separator[0] == '\t')
 23.2066 -         {
 23.2067 -           i = number_width - chars_per_number;
 23.2068 -           while (i-- > 0)
 23.2069 -             (p->char_func) (' ');
 23.2070 -         }
 23.2071 -       else
 23.2072 --        (p->char_func) (number_separator);
 23.2073 -+        for (j = 0; j < number_separator_length; j++)
 23.2074 -+          (p->char_func) (number_separator[j]);
 23.2075 -     }
 23.2076 -   else
 23.2077 -     /* To comply with POSIX, we avoid any expansion of default TAB
 23.2078 -        separator with a single column output. No column_width requirement
 23.2079 -        has to be considered. */
 23.2080 -     {
 23.2081 --      (p->char_func) (number_separator);
 23.2082 --      if (number_separator == '\t')
 23.2083 -+      for (j = 0; j < number_separator_length; j++)
 23.2084 -+        (p->char_func) (number_separator[j]);
 23.2085 -+      if (number_separator[0] == '\t')
 23.2086 -         output_position = POS_AFTER_TAB (chars_per_output_tab,
 23.2087 -                           output_position);
 23.2088 -     }
 23.2089 -@@ -2180,7 +2305,7 @@ print_white_space (void)
 23.2090 -   while (goal - h_old > 1
 23.2091 -          && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
 23.2092 -     {
 23.2093 --      putchar (output_tab_char);
 23.2094 -+      fwrite (output_tab_char, sizeof(char), output_tab_char_length, stdout);
 23.2095 -       h_old = h_new;
 23.2096 -     }
 23.2097 -   while (++h_old <= goal)
 23.2098 -@@ -2200,6 +2325,7 @@ print_sep_string (void)
 23.2099 - {
 23.2100 -   char *s;
 23.2101 -   int l = col_sep_length;
 23.2102 -+  int not_space_flag;
 23.2103 - 
 23.2104 -   s = col_sep_string;
 23.2105 - 
 23.2106 -@@ -2213,6 +2339,7 @@ print_sep_string (void)
 23.2107 -     {
 23.2108 -       for (; separators_not_printed > 0; --separators_not_printed)
 23.2109 -         {
 23.2110 -+          not_space_flag = 0;
 23.2111 -           while (l-- > 0)
 23.2112 -             {
 23.2113 -               /* 3 types of sep_strings: spaces only, spaces and chars,
 23.2114 -@@ -2226,12 +2353,15 @@ print_sep_string (void)
 23.2115 -                 }
 23.2116 -               else
 23.2117 -                 {
 23.2118 -+                  not_space_flag = 1;
 23.2119 -                   if (spaces_not_printed > 0)
 23.2120 -                     print_white_space ();
 23.2121 -                   putchar (*s++);
 23.2122 --                  ++output_position;
 23.2123 -                 }
 23.2124 -             }
 23.2125 -+          if (not_space_flag)
 23.2126 -+            output_position += col_sep_width;
 23.2127 -+
 23.2128 -           /* sep_string ends with some spaces */
 23.2129 -           if (spaces_not_printed > 0)
 23.2130 -             print_white_space ();
 23.2131 -@@ -2259,7 +2389,7 @@ print_clump (COLUMN *p, int n, char *clu
 23.2132 -    required number of tabs and spaces. */
 23.2133 - 
 23.2134 - static void
 23.2135 --print_char (char c)
 23.2136 -+print_char_single (char c)
 23.2137 - {
 23.2138 -   if (tabify_output)
 23.2139 -     {
 23.2140 -@@ -2283,6 +2413,74 @@ print_char (char c)
 23.2141 -   putchar (c);
 23.2142 - }
 23.2143 - 
 23.2144 -+#ifdef HAVE_MBRTOWC
 23.2145 -+static void
 23.2146 -+print_char_multi (char c)
 23.2147 -+{
 23.2148 -+  static size_t mbc_pos = 0;
 23.2149 -+  static char mbc[MB_LEN_MAX] = {'\0'};
 23.2150 -+  static mbstate_t state = {'\0'};
 23.2151 -+  mbstate_t state_bak;
 23.2152 -+  wchar_t wc;
 23.2153 -+  size_t mblength;
 23.2154 -+  int width;
 23.2155 -+
 23.2156 -+  if (tabify_output)
 23.2157 -+    {
 23.2158 -+      state_bak = state;
 23.2159 -+      mbc[mbc_pos++] = c;
 23.2160 -+      mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 23.2161 -+
 23.2162 -+      while (mbc_pos > 0)
 23.2163 -+        {
 23.2164 -+          switch (mblength)
 23.2165 -+            {
 23.2166 -+            case (size_t)-2:
 23.2167 -+              state = state_bak;
 23.2168 -+              return;
 23.2169 -+
 23.2170 -+            case (size_t)-1:
 23.2171 -+              state = state_bak;
 23.2172 -+              ++output_position;
 23.2173 -+              putchar (mbc[0]);
 23.2174 -+              memmove (mbc, mbc + 1, MB_CUR_MAX - 1);
 23.2175 -+              --mbc_pos;
 23.2176 -+              break;
 23.2177 -+
 23.2178 -+            case 0:
 23.2179 -+              mblength = 1;
 23.2180 -+
 23.2181 -+            default:
 23.2182 -+              if (wc == L' ')
 23.2183 -+                {
 23.2184 -+                  memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 23.2185 -+                  --mbc_pos;
 23.2186 -+                  ++spaces_not_printed;
 23.2187 -+                  return;
 23.2188 -+                }
 23.2189 -+              else if (spaces_not_printed > 0)
 23.2190 -+                print_white_space ();
 23.2191 -+
 23.2192 -+              /* Nonprintables are assumed to have width 0, except L'\b'. */
 23.2193 -+              if ((width = wcwidth (wc)) < 1)
 23.2194 -+                {
 23.2195 -+                  if (wc == L'\b')
 23.2196 -+                    --output_position;
 23.2197 -+                }
 23.2198 -+              else
 23.2199 -+                output_position += width;
 23.2200 -+
 23.2201 -+              fwrite (mbc, sizeof(char), mblength, stdout);
 23.2202 -+              memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 23.2203 -+              mbc_pos -= mblength;
 23.2204 -+            }
 23.2205 -+        }
 23.2206 -+      return;
 23.2207 -+    }
 23.2208 -+  putchar (c);
 23.2209 -+}
 23.2210 -+#endif
 23.2211 -+
 23.2212 - /* Skip to page PAGE before printing.
 23.2213 -    PAGE may be larger than total number of pages. */
 23.2214 - 
 23.2215 -@@ -2462,9 +2660,9 @@ read_line (COLUMN *p)
 23.2216 -           align_empty_cols = false;
 23.2217 -         }
 23.2218 - 
 23.2219 --      if (padding_not_printed - col_sep_length > 0)
 23.2220 -+      if (padding_not_printed - col_sep_width > 0)
 23.2221 -         {
 23.2222 --          pad_across_to (padding_not_printed - col_sep_length);
 23.2223 -+          pad_across_to (padding_not_printed - col_sep_width);
 23.2224 -           padding_not_printed = ANYWHERE;
 23.2225 -         }
 23.2226 - 
 23.2227 -@@ -2534,7 +2732,7 @@ print_stored (COLUMN *p)
 23.2228 -   int i;
 23.2229 - 
 23.2230 -   int line = p->current_line++;
 23.2231 --  char *first = &buff[line_vector[line]];
 23.2232 -+  unsigned char *first = &buff[line_vector[line]];
 23.2233 -   /* FIXME
 23.2234 -      UMR: Uninitialized memory read:
 23.2235 -      * This is occurring while in:
 23.2236 -@@ -2546,7 +2744,7 @@ print_stored (COLUMN *p)
 23.2237 -      xmalloc        [xmalloc.c:94]
 23.2238 -      init_store_cols [pr.c:1648]
 23.2239 -      */
 23.2240 --  char *last = &buff[line_vector[line + 1]];
 23.2241 -+  unsigned char *last = &buff[line_vector[line + 1]];
 23.2242 - 
 23.2243 -   pad_vertically = true;
 23.2244 - 
 23.2245 -@@ -2565,9 +2763,9 @@ print_stored (COLUMN *p)
 23.2246 -         }
 23.2247 -     }
 23.2248 - 
 23.2249 --  if (padding_not_printed - col_sep_length > 0)
 23.2250 -+  if (padding_not_printed - col_sep_width > 0)
 23.2251 -     {
 23.2252 --      pad_across_to (padding_not_printed - col_sep_length);
 23.2253 -+      pad_across_to (padding_not_printed - col_sep_width);
 23.2254 -       padding_not_printed = ANYWHERE;
 23.2255 -     }
 23.2256 - 
 23.2257 -@@ -2580,8 +2778,8 @@ print_stored (COLUMN *p)
 23.2258 -   if (spaces_not_printed == 0)
 23.2259 -     {
 23.2260 -       output_position = p->start_position + end_vector[line];
 23.2261 --      if (p->start_position - col_sep_length == chars_per_margin)
 23.2262 --        output_position -= col_sep_length;
 23.2263 -+      if (p->start_position - col_sep_width == chars_per_margin)
 23.2264 -+        output_position -= col_sep_width;
 23.2265 -     }
 23.2266 - 
 23.2267 -   return true;
 23.2268 -@@ -2600,7 +2798,7 @@ print_stored (COLUMN *p)
 23.2269 -    number of characters is 1.) */
 23.2270 - 
 23.2271 - static int
 23.2272 --char_to_clump (char c)
 23.2273 -+char_to_clump_single (char c)
 23.2274 - {
 23.2275 -   unsigned char uc = c;
 23.2276 -   char *s = clump_buff;
 23.2277 -@@ -2610,10 +2808,10 @@ char_to_clump (char c)
 23.2278 -   int chars;
 23.2279 -   int chars_per_c = 8;
 23.2280 - 
 23.2281 --  if (c == input_tab_char)
 23.2282 -+  if (c == input_tab_char[0])
 23.2283 -     chars_per_c = chars_per_input_tab;
 23.2284 - 
 23.2285 --  if (c == input_tab_char || c == '\t')
 23.2286 -+  if (c == input_tab_char[0] || c == '\t')
 23.2287 -     {
 23.2288 -       width = TAB_WIDTH (chars_per_c, input_position);
 23.2289 - 
 23.2290 -@@ -2694,6 +2892,164 @@ char_to_clump (char c)
 23.2291 -   return chars;
 23.2292 - }
 23.2293 - 
 23.2294 -+#ifdef HAVE_MBRTOWC
 23.2295 -+static int
 23.2296 -+char_to_clump_multi (char c)
 23.2297 -+{
 23.2298 -+  static size_t mbc_pos = 0;
 23.2299 -+  static char mbc[MB_LEN_MAX] = {'\0'};
 23.2300 -+  static mbstate_t state = {'\0'};
 23.2301 -+  mbstate_t state_bak;
 23.2302 -+  wchar_t wc;
 23.2303 -+  size_t mblength;
 23.2304 -+  int wc_width;
 23.2305 -+  register char *s = clump_buff;
 23.2306 -+  register int i, j;
 23.2307 -+  char esc_buff[4];
 23.2308 -+  int width;
 23.2309 -+  int chars;
 23.2310 -+  int chars_per_c = 8;
 23.2311 -+
 23.2312 -+  state_bak = state;
 23.2313 -+  mbc[mbc_pos++] = c;
 23.2314 -+  mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 23.2315 -+
 23.2316 -+  width = 0;
 23.2317 -+  chars = 0;
 23.2318 -+  while (mbc_pos > 0)
 23.2319 -+    {
 23.2320 -+      switch (mblength)
 23.2321 -+        {
 23.2322 -+        case (size_t)-2:
 23.2323 -+          state = state_bak;
 23.2324 -+          return 0;
 23.2325 -+
 23.2326 -+        case (size_t)-1:
 23.2327 -+          state = state_bak;
 23.2328 -+          mblength = 1;
 23.2329 -+
 23.2330 -+          if (use_esc_sequence || use_cntrl_prefix)
 23.2331 -+            {
 23.2332 -+              width = +4;
 23.2333 -+              chars = +4;
 23.2334 -+              *s++ = '\\';
 23.2335 -+              sprintf (esc_buff, "%03o", (unsigned char) mbc[0]);
 23.2336 -+              for (i = 0; i <= 2; ++i)
 23.2337 -+                *s++ = (int) esc_buff[i];
 23.2338 -+            }
 23.2339 -+          else
 23.2340 -+            {
 23.2341 -+              width += 1;
 23.2342 -+              chars += 1;
 23.2343 -+              *s++ = mbc[0];
 23.2344 -+            }
 23.2345 -+          break;
 23.2346 -+
 23.2347 -+        case 0:
 23.2348 -+          mblength = 1;
 23.2349 -+                /* Fall through */
 23.2350 -+
 23.2351 -+        default:
 23.2352 -+          if (memcmp (mbc, input_tab_char, mblength) == 0)
 23.2353 -+            chars_per_c = chars_per_input_tab;
 23.2354 -+
 23.2355 -+          if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t')
 23.2356 -+            {
 23.2357 -+              int  width_inc;
 23.2358 -+
 23.2359 -+              width_inc = TAB_WIDTH (chars_per_c, input_position);
 23.2360 -+              width += width_inc;
 23.2361 -+
 23.2362 -+              if (untabify_input)
 23.2363 -+                {
 23.2364 -+                  for (i = width_inc; i; --i)
 23.2365 -+                    *s++ = ' ';
 23.2366 -+                  chars += width_inc;
 23.2367 -+                }
 23.2368 -+              else
 23.2369 -+                {
 23.2370 -+                  for (i = 0; i <  mblength; i++)
 23.2371 -+                    *s++ = mbc[i];
 23.2372 -+                  chars += mblength;
 23.2373 -+                }
 23.2374 -+            }
 23.2375 -+          else if ((wc_width = wcwidth (wc)) < 1)
 23.2376 -+            {
 23.2377 -+              if (use_esc_sequence)
 23.2378 -+                {
 23.2379 -+                  for (i = 0; i < mblength; i++)
 23.2380 -+                    {
 23.2381 -+                      width += 4;
 23.2382 -+                      chars += 4;
 23.2383 -+                      *s++ = '\\';
 23.2384 -+                      sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 23.2385 -+                      for (j = 0; j <= 2; ++j)
 23.2386 -+                        *s++ = (int) esc_buff[j];
 23.2387 -+                    }
 23.2388 -+                }
 23.2389 -+              else if (use_cntrl_prefix)
 23.2390 -+                {
 23.2391 -+                  if (wc < 0200)
 23.2392 -+                    {
 23.2393 -+                      width += 2;
 23.2394 -+                      chars += 2;
 23.2395 -+                      *s++ = '^';
 23.2396 -+                      *s++ = wc ^ 0100;
 23.2397 -+                    }
 23.2398 -+                  else
 23.2399 -+                    {
 23.2400 -+                      for (i = 0; i < mblength; i++)
 23.2401 -+                        {
 23.2402 -+                          width += 4;
 23.2403 -+                          chars += 4;
 23.2404 -+                          *s++ = '\\';
 23.2405 -+                          sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 23.2406 -+                          for (j = 0; j <= 2; ++j)
 23.2407 -+                            *s++ = (int) esc_buff[j];
 23.2408 -+                        }
 23.2409 -+                    }
 23.2410 -+                }
 23.2411 -+              else if (wc == L'\b')
 23.2412 -+                {
 23.2413 -+                  width += -1;
 23.2414 -+                  chars += 1;
 23.2415 -+                  *s++ = c;
 23.2416 -+                }
 23.2417 -+              else
 23.2418 -+                {
 23.2419 -+                  width += 0;
 23.2420 -+                  chars += mblength;
 23.2421 -+                  for (i = 0; i < mblength; i++)
 23.2422 -+                    *s++ = mbc[i];
 23.2423 -+                }
 23.2424 -+            }
 23.2425 -+          else
 23.2426 -+            {
 23.2427 -+              width += wc_width;
 23.2428 -+              chars += mblength;
 23.2429 -+              for (i = 0; i < mblength; i++)
 23.2430 -+                *s++ = mbc[i];
 23.2431 -+            }
 23.2432 -+        }
 23.2433 -+      memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 23.2434 -+      mbc_pos -= mblength;
 23.2435 -+    }
 23.2436 -+
 23.2437 -+  /* Too many backspaces must put us in position 0 -- never negative. */
 23.2438 -+  if (width < 0 && input_position == 0)
 23.2439 -+    {
 23.2440 -+      chars = 0;
 23.2441 -+      input_position = 0;
 23.2442 -+    }
 23.2443 -+  else if (width < 0 && input_position <= -width)
 23.2444 -+    input_position = 0;
 23.2445 -+  else
 23.2446 -+   input_position += width;
 23.2447 -+
 23.2448 -+  return chars;
 23.2449 -+}
 23.2450 -+#endif
 23.2451 -+
 23.2452 - /* We've just printed some files and need to clean up things before
 23.2453 -    looking for more options and printing the next batch of files.
 23.2454 - 
 23.2455 -diff -Naurp coreutils-8.25-orig/src/sort.c coreutils-8.25/src/sort.c
 23.2456 ---- coreutils-8.25-orig/src/sort.c	2016-01-16 13:09:33.000000000 -0600
 23.2457 -+++ coreutils-8.25/src/sort.c	2016-02-08 19:07:10.310944648 -0600
 23.2458 -@@ -29,6 +29,14 @@
 23.2459 - #include <sys/wait.h>
 23.2460 - #include <signal.h>
 23.2461 - #include <assert.h>
 23.2462 -+#if HAVE_WCHAR_H
 23.2463 -+# include <wchar.h>
 23.2464 -+#endif
 23.2465 -+/* Get isw* functions. */
 23.2466 -+#if HAVE_WCTYPE_H
 23.2467 -+# include <wctype.h>
 23.2468 -+#endif
 23.2469 -+
 23.2470 - #include "system.h"
 23.2471 - #include "argmatch.h"
 23.2472 - #include "error.h"
 23.2473 -@@ -163,14 +171,39 @@ static int decimal_point;
 23.2474 - /* Thousands separator; if -1, then there isn't one.  */
 23.2475 - static int thousands_sep;
 23.2476 - 
 23.2477 -+/* True if -f is specified.  */
 23.2478 -+static bool folding;
 23.2479 -+
 23.2480 - /* Nonzero if the corresponding locales are hard.  */
 23.2481 - static bool hard_LC_COLLATE;
 23.2482 --#if HAVE_NL_LANGINFO
 23.2483 -+#if HAVE_LANGINFO_CODESET
 23.2484 - static bool hard_LC_TIME;
 23.2485 - #endif
 23.2486 - 
 23.2487 - #define NONZERO(x) ((x) != 0)
 23.2488 - 
 23.2489 -+/* get a multibyte character's byte length. */
 23.2490 -+#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE)                        \
 23.2491 -+  do                                                                        \
 23.2492 -+    {                                                                        \
 23.2493 -+      wchar_t wc;                                                        \
 23.2494 -+      mbstate_t state_bak;                                                \
 23.2495 -+                                                                        \
 23.2496 -+      state_bak = STATE;                                                \
 23.2497 -+      mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE);                        \
 23.2498 -+                                                                        \
 23.2499 -+      switch (MBLENGTH)                                                        \
 23.2500 -+        {                                                                \
 23.2501 -+        case (size_t)-1:                                                \
 23.2502 -+        case (size_t)-2:                                                \
 23.2503 -+          STATE = state_bak;                                                \
 23.2504 -+                /* Fall through. */                                        \
 23.2505 -+        case 0:                                                                \
 23.2506 -+          MBLENGTH = 1;                                                        \
 23.2507 -+      }                                                                        \
 23.2508 -+    }                                                                        \
 23.2509 -+  while (0)
 23.2510 -+
 23.2511 - /* The kind of blanks for '-b' to skip in various options. */
 23.2512 - enum blanktype { bl_start, bl_end, bl_both };
 23.2513 - 
 23.2514 -@@ -344,13 +377,11 @@ static bool reverse;
 23.2515 -    they were read if all keys compare equal.  */
 23.2516 - static bool stable;
 23.2517 - 
 23.2518 --/* If TAB has this value, blanks separate fields.  */
 23.2519 --enum { TAB_DEFAULT = CHAR_MAX + 1 };
 23.2520 --
 23.2521 --/* Tab character separating fields.  If TAB_DEFAULT, then fields are
 23.2522 -+/* Tab character separating fields.  If tab_length is 0, then fields are
 23.2523 -    separated by the empty string between a non-blank character and a blank
 23.2524 -    character. */
 23.2525 --static int tab = TAB_DEFAULT;
 23.2526 -+static char tab[MB_LEN_MAX + 1];
 23.2527 -+static size_t tab_length = 0;
 23.2528 - 
 23.2529 - /* Flag to remove consecutive duplicate lines from the output.
 23.2530 -    Only the last of a sequence of equal lines will be output. */
 23.2531 -@@ -810,6 +841,46 @@ reap_all (void)
 23.2532 -     reap (-1);
 23.2533 - }
 23.2534 - 
 23.2535 -+/* Function pointers. */
 23.2536 -+static void
 23.2537 -+(*inittables) (void);
 23.2538 -+static char *
 23.2539 -+(*begfield) (const struct line*, const struct keyfield *);
 23.2540 -+static char *
 23.2541 -+(*limfield) (const struct line*, const struct keyfield *);
 23.2542 -+static void
 23.2543 -+(*skipblanks) (char **ptr, char *lim);
 23.2544 -+static int
 23.2545 -+(*getmonth) (char const *, size_t, char **);
 23.2546 -+static int
 23.2547 -+(*keycompare) (const struct line *, const struct line *);
 23.2548 -+static int
 23.2549 -+(*numcompare) (const char *, const char *);
 23.2550 -+
 23.2551 -+/* Test for white space multibyte character.
 23.2552 -+   Set LENGTH the byte length of investigated multibyte character. */
 23.2553 -+#if HAVE_MBRTOWC
 23.2554 -+static int
 23.2555 -+ismbblank (const char *str, size_t len, size_t *length)
 23.2556 -+{
 23.2557 -+  size_t mblength;
 23.2558 -+  wchar_t wc;
 23.2559 -+  mbstate_t state;
 23.2560 -+
 23.2561 -+  memset (&state, '\0', sizeof(mbstate_t));
 23.2562 -+  mblength = mbrtowc (&wc, str, len, &state);
 23.2563 -+
 23.2564 -+  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.2565 -+    {
 23.2566 -+      *length = 1;
 23.2567 -+      return 0;
 23.2568 -+    }
 23.2569 -+
 23.2570 -+  *length = (mblength < 1) ? 1 : mblength;
 23.2571 -+  return iswblank (wc) || wc == '\n';
 23.2572 -+}
 23.2573 -+#endif
 23.2574 -+
 23.2575 - /* Clean up any remaining temporary files.  */
 23.2576 - 
 23.2577 - static void
 23.2578 -@@ -1254,7 +1325,7 @@ zaptemp (char const *name)
 23.2579 -   free (node);
 23.2580 - }
 23.2581 - 
 23.2582 --#if HAVE_NL_LANGINFO
 23.2583 -+#if HAVE_LANGINFO_CODESET
 23.2584 - 
 23.2585 - static int
 23.2586 - struct_month_cmp (void const *m1, void const *m2)
 23.2587 -@@ -1269,7 +1340,7 @@ struct_month_cmp (void const *m1, void c
 23.2588 - /* Initialize the character class tables. */
 23.2589 - 
 23.2590 - static void
 23.2591 --inittables (void)
 23.2592 -+inittables_uni (void)
 23.2593 - {
 23.2594 -   size_t i;
 23.2595 - 
 23.2596 -@@ -1281,7 +1352,7 @@ inittables (void)
 23.2597 -       fold_toupper[i] = toupper (i);
 23.2598 -     }
 23.2599 - 
 23.2600 --#if HAVE_NL_LANGINFO
 23.2601 -+#if HAVE_LANGINFO_CODESET
 23.2602 -   /* If we're not in the "C" locale, read different names for months.  */
 23.2603 -   if (hard_LC_TIME)
 23.2604 -     {
 23.2605 -@@ -1363,6 +1434,84 @@ specify_nmerge (int oi, char c, char con
 23.2606 -     xstrtol_fatal (e, oi, c, long_options, s);
 23.2607 - }
 23.2608 - 
 23.2609 -+#if HAVE_MBRTOWC
 23.2610 -+static void
 23.2611 -+inittables_mb (void)
 23.2612 -+{
 23.2613 -+  int i, j, k, l;
 23.2614 -+  char *name, *s, *lc_time, *lc_ctype;
 23.2615 -+  size_t s_len, mblength;
 23.2616 -+  char mbc[MB_LEN_MAX];
 23.2617 -+  wchar_t wc, pwc;
 23.2618 -+  mbstate_t state_mb, state_wc;
 23.2619 -+
 23.2620 -+  lc_time = setlocale (LC_TIME, "");
 23.2621 -+  if (lc_time)
 23.2622 -+    lc_time = xstrdup (lc_time);
 23.2623 -+
 23.2624 -+  lc_ctype = setlocale (LC_CTYPE, "");
 23.2625 -+  if (lc_ctype)
 23.2626 -+    lc_ctype = xstrdup (lc_ctype);
 23.2627 -+
 23.2628 -+  if (lc_time && lc_ctype)
 23.2629 -+    /* temporarily set LC_CTYPE to match LC_TIME, so that we can convert
 23.2630 -+     * the names of months to upper case */
 23.2631 -+    setlocale (LC_CTYPE, lc_time);
 23.2632 -+
 23.2633 -+  for (i = 0; i < MONTHS_PER_YEAR; i++)
 23.2634 -+    {
 23.2635 -+      s = (char *) nl_langinfo (ABMON_1 + i);
 23.2636 -+      s_len = strlen (s);
 23.2637 -+      monthtab[i].name = name = (char *) xmalloc (s_len + 1);
 23.2638 -+      monthtab[i].val = i + 1;
 23.2639 -+
 23.2640 -+      memset (&state_mb, '\0', sizeof (mbstate_t));
 23.2641 -+      memset (&state_wc, '\0', sizeof (mbstate_t));
 23.2642 -+
 23.2643 -+      for (j = 0; j < s_len;)
 23.2644 -+        {
 23.2645 -+          if (!ismbblank (s + j, s_len - j, &mblength))
 23.2646 -+            break;
 23.2647 -+          j += mblength;
 23.2648 -+        }
 23.2649 -+
 23.2650 -+      for (k = 0; j < s_len;)
 23.2651 -+        {
 23.2652 -+          mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb);
 23.2653 -+          assert (mblength != (size_t)-1 && mblength != (size_t)-2);
 23.2654 -+          if (mblength == 0)
 23.2655 -+            break;
 23.2656 -+
 23.2657 -+          pwc = towupper (wc);
 23.2658 -+          if (pwc == wc)
 23.2659 -+            {
 23.2660 -+              memcpy (mbc, s + j, mblength);
 23.2661 -+              j += mblength;
 23.2662 -+            }
 23.2663 -+          else
 23.2664 -+            {
 23.2665 -+              j += mblength;
 23.2666 -+              mblength = wcrtomb (mbc, pwc, &state_wc);
 23.2667 -+              assert (mblength != (size_t)0 && mblength != (size_t)-1);
 23.2668 -+            }
 23.2669 -+
 23.2670 -+          for (l = 0; l < mblength; l++)
 23.2671 -+            name[k++] = mbc[l];
 23.2672 -+        }
 23.2673 -+      name[k] = '\0';
 23.2674 -+    }
 23.2675 -+  qsort ((void *) monthtab, MONTHS_PER_YEAR,
 23.2676 -+      sizeof (struct month), struct_month_cmp);
 23.2677 -+
 23.2678 -+  if (lc_time && lc_ctype)
 23.2679 -+    /* restore the original locales */
 23.2680 -+    setlocale (LC_CTYPE, lc_ctype);
 23.2681 -+
 23.2682 -+  free (lc_ctype);
 23.2683 -+  free (lc_time);
 23.2684 -+}
 23.2685 -+#endif
 23.2686 -+
 23.2687 - /* Specify the amount of main memory to use when sorting.  */
 23.2688 - static void
 23.2689 - specify_sort_size (int oi, char c, char const *s)
 23.2690 -@@ -1596,7 +1745,7 @@ buffer_linelim (struct buffer const *buf
 23.2691 -    by KEY in LINE. */
 23.2692 - 
 23.2693 - static char *
 23.2694 --begfield (struct line const *line, struct keyfield const *key)
 23.2695 -+begfield_uni (const struct line *line, const struct keyfield *key)
 23.2696 - {
 23.2697 -   char *ptr = line->text, *lim = ptr + line->length - 1;
 23.2698 -   size_t sword = key->sword;
 23.2699 -@@ -1605,10 +1754,10 @@ begfield (struct line const *line, struc
 23.2700 -   /* The leading field separator itself is included in a field when -t
 23.2701 -      is absent.  */
 23.2702 - 
 23.2703 --  if (tab != TAB_DEFAULT)
 23.2704 -+  if (tab_length)
 23.2705 -     while (ptr < lim && sword--)
 23.2706 -       {
 23.2707 --        while (ptr < lim && *ptr != tab)
 23.2708 -+        while (ptr < lim && *ptr != tab[0])
 23.2709 -           ++ptr;
 23.2710 -         if (ptr < lim)
 23.2711 -           ++ptr;
 23.2712 -@@ -1634,11 +1783,70 @@ begfield (struct line const *line, struc
 23.2713 -   return ptr;
 23.2714 - }
 23.2715 - 
 23.2716 -+#if HAVE_MBRTOWC
 23.2717 -+static char *
 23.2718 -+begfield_mb (const struct line *line, const struct keyfield *key)
 23.2719 -+{
 23.2720 -+  int i;
 23.2721 -+  char *ptr = line->text, *lim = ptr + line->length - 1;
 23.2722 -+  size_t sword = key->sword;
 23.2723 -+  size_t schar = key->schar;
 23.2724 -+  size_t mblength;
 23.2725 -+  mbstate_t state;
 23.2726 -+
 23.2727 -+  memset (&state, '\0', sizeof(mbstate_t));
 23.2728 -+
 23.2729 -+  if (tab_length)
 23.2730 -+    while (ptr < lim && sword--)
 23.2731 -+      {
 23.2732 -+        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 23.2733 -+          {
 23.2734 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2735 -+            ptr += mblength;
 23.2736 -+          }
 23.2737 -+        if (ptr < lim)
 23.2738 -+          {
 23.2739 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2740 -+            ptr += mblength;
 23.2741 -+          }
 23.2742 -+      }
 23.2743 -+  else
 23.2744 -+    while (ptr < lim && sword--)
 23.2745 -+      {
 23.2746 -+        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 23.2747 -+          ptr += mblength;
 23.2748 -+        if (ptr < lim)
 23.2749 -+          {
 23.2750 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2751 -+            ptr += mblength;
 23.2752 -+          }
 23.2753 -+        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 23.2754 -+          ptr += mblength;
 23.2755 -+      }
 23.2756 -+
 23.2757 -+  if (key->skipsblanks)
 23.2758 -+    while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 23.2759 -+      ptr += mblength;
 23.2760 -+
 23.2761 -+  for (i = 0; i < schar; i++)
 23.2762 -+    {
 23.2763 -+      GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2764 -+
 23.2765 -+      if (ptr + mblength > lim)
 23.2766 -+        break;
 23.2767 -+      else
 23.2768 -+        ptr += mblength;
 23.2769 -+    }
 23.2770 -+
 23.2771 -+  return ptr;
 23.2772 -+}
 23.2773 -+#endif
 23.2774 -+
 23.2775 - /* Return the limit of (a pointer to the first character after) the field
 23.2776 -    in LINE specified by KEY. */
 23.2777 - 
 23.2778 - static char *
 23.2779 --limfield (struct line const *line, struct keyfield const *key)
 23.2780 -+limfield_uni (const struct line *line, const struct keyfield *key)
 23.2781 - {
 23.2782 -   char *ptr = line->text, *lim = ptr + line->length - 1;
 23.2783 -   size_t eword = key->eword, echar = key->echar;
 23.2784 -@@ -1653,10 +1861,10 @@ limfield (struct line const *line, struc
 23.2785 -      'beginning' is the first character following the delimiting TAB.
 23.2786 -      Otherwise, leave PTR pointing at the first 'blank' character after
 23.2787 -      the preceding field.  */
 23.2788 --  if (tab != TAB_DEFAULT)
 23.2789 -+  if (tab_length)
 23.2790 -     while (ptr < lim && eword--)
 23.2791 -       {
 23.2792 --        while (ptr < lim && *ptr != tab)
 23.2793 -+        while (ptr < lim && *ptr != tab[0])
 23.2794 -           ++ptr;
 23.2795 -         if (ptr < lim && (eword || echar))
 23.2796 -           ++ptr;
 23.2797 -@@ -1702,10 +1910,10 @@ limfield (struct line const *line, struc
 23.2798 -      */
 23.2799 - 
 23.2800 -   /* Make LIM point to the end of (one byte past) the current field.  */
 23.2801 --  if (tab != TAB_DEFAULT)
 23.2802 -+  if (tab_length)
 23.2803 -     {
 23.2804 -       char *newlim;
 23.2805 --      newlim = memchr (ptr, tab, lim - ptr);
 23.2806 -+      newlim = memchr (ptr, tab[0], lim - ptr);
 23.2807 -       if (newlim)
 23.2808 -         lim = newlim;
 23.2809 -     }
 23.2810 -@@ -1736,6 +1944,130 @@ limfield (struct line const *line, struc
 23.2811 -   return ptr;
 23.2812 - }
 23.2813 - 
 23.2814 -+#if HAVE_MBRTOWC
 23.2815 -+static char *
 23.2816 -+limfield_mb (const struct line *line, const struct keyfield *key)
 23.2817 -+{
 23.2818 -+  char *ptr = line->text, *lim = ptr + line->length - 1;
 23.2819 -+  size_t eword = key->eword, echar = key->echar;
 23.2820 -+  int i;
 23.2821 -+  size_t mblength;
 23.2822 -+  mbstate_t state;
 23.2823 -+
 23.2824 -+  if (echar == 0)
 23.2825 -+    eword++; /* skip all of end field. */
 23.2826 -+
 23.2827 -+  memset (&state, '\0', sizeof(mbstate_t));
 23.2828 -+
 23.2829 -+  if (tab_length)
 23.2830 -+    while (ptr < lim && eword--)
 23.2831 -+      {
 23.2832 -+        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 23.2833 -+          {
 23.2834 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2835 -+            ptr += mblength;
 23.2836 -+          }
 23.2837 -+        if (ptr < lim && (eword | echar))
 23.2838 -+          {
 23.2839 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2840 -+            ptr += mblength;
 23.2841 -+          }
 23.2842 -+      }
 23.2843 -+  else
 23.2844 -+    while (ptr < lim && eword--)
 23.2845 -+      {
 23.2846 -+        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 23.2847 -+          ptr += mblength;
 23.2848 -+        if (ptr < lim)
 23.2849 -+          {
 23.2850 -+            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2851 -+            ptr += mblength;
 23.2852 -+          }
 23.2853 -+        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 23.2854 -+          ptr += mblength;
 23.2855 -+      }
 23.2856 -+
 23.2857 -+
 23.2858 -+# ifdef POSIX_UNSPECIFIED
 23.2859 -+  /* Make LIM point to the end of (one byte past) the current field.  */
 23.2860 -+  if (tab_length)
 23.2861 -+    {
 23.2862 -+      char *newlim, *p;
 23.2863 -+
 23.2864 -+      newlim = NULL;
 23.2865 -+      for (p = ptr; p < lim;)
 23.2866 -+         {
 23.2867 -+          if (memcmp (p, tab, tab_length) == 0)
 23.2868 -+            {
 23.2869 -+              newlim = p;
 23.2870 -+              break;
 23.2871 -+            }
 23.2872 -+
 23.2873 -+          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2874 -+          p += mblength;
 23.2875 -+        }
 23.2876 -+    }
 23.2877 -+  else
 23.2878 -+    {
 23.2879 -+      char *newlim;
 23.2880 -+      newlim = ptr;
 23.2881 -+
 23.2882 -+      while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength))
 23.2883 -+        newlim += mblength;
 23.2884 -+      if (ptr < lim)
 23.2885 -+        {
 23.2886 -+          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2887 -+          ptr += mblength;
 23.2888 -+        }
 23.2889 -+      while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength))
 23.2890 -+        newlim += mblength;
 23.2891 -+      lim = newlim;
 23.2892 -+    }
 23.2893 -+# endif
 23.2894 -+
 23.2895 -+  if (echar != 0)
 23.2896 -+  {
 23.2897 -+    /* If we're skipping leading blanks, don't start counting characters
 23.2898 -+     *      until after skipping past any leading blanks.  */
 23.2899 -+    if (key->skipeblanks)
 23.2900 -+      while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 23.2901 -+        ptr += mblength;
 23.2902 -+
 23.2903 -+    memset (&state, '\0', sizeof(mbstate_t));
 23.2904 -+
 23.2905 -+    /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
 23.2906 -+    for (i = 0; i < echar; i++)
 23.2907 -+     {
 23.2908 -+        GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 23.2909 -+
 23.2910 -+        if (ptr + mblength > lim)
 23.2911 -+          break;
 23.2912 -+        else
 23.2913 -+          ptr += mblength;
 23.2914 -+      }
 23.2915 -+  }
 23.2916 -+
 23.2917 -+  return ptr;
 23.2918 -+}
 23.2919 -+#endif
 23.2920 -+
 23.2921 -+static void
 23.2922 -+skipblanks_uni (char **ptr, char *lim)
 23.2923 -+{
 23.2924 -+  while (*ptr < lim && blanks[to_uchar (**ptr)])
 23.2925 -+    ++(*ptr);
 23.2926 -+}
 23.2927 -+
 23.2928 -+#if HAVE_MBRTOWC
 23.2929 -+static void
 23.2930 -+skipblanks_mb (char **ptr, char *lim)
 23.2931 -+{
 23.2932 -+  size_t mblength;
 23.2933 -+  while (*ptr < lim && ismbblank (*ptr, lim - *ptr, &mblength))
 23.2934 -+    (*ptr) += mblength;
 23.2935 -+}
 23.2936 -+#endif
 23.2937 -+
 23.2938 - /* Fill BUF reading from FP, moving buf->left bytes from the end
 23.2939 -    of buf->buf to the beginning first.  If EOF is reached and the
 23.2940 -    file wasn't terminated by a newline, supply one.  Set up BUF's line
 23.2941 -@@ -1822,8 +2154,22 @@ fillbuf (struct buffer *buf, FILE *fp, c
 23.2942 -                   else
 23.2943 -                     {
 23.2944 -                       if (key->skipsblanks)
 23.2945 --                        while (blanks[to_uchar (*line_start)])
 23.2946 --                          line_start++;
 23.2947 -+                        {
 23.2948 -+#if HAVE_MBRTOWC
 23.2949 -+                          if (MB_CUR_MAX > 1)
 23.2950 -+                            {
 23.2951 -+                              size_t mblength;
 23.2952 -+                              while (line_start < line->keylim &&
 23.2953 -+                                     ismbblank (line_start,
 23.2954 -+                                                line->keylim - line_start,
 23.2955 -+                                                &mblength))
 23.2956 -+                                line_start += mblength;
 23.2957 -+                            }
 23.2958 -+                          else
 23.2959 -+#endif
 23.2960 -+                          while (blanks[to_uchar (*line_start)])
 23.2961 -+                            line_start++;
 23.2962 -+                        }
 23.2963 -                       line->keybeg = line_start;
 23.2964 -                     }
 23.2965 -                 }
 23.2966 -@@ -1944,7 +2290,7 @@ human_numcompare (char const *a, char co
 23.2967 -    hideously fast. */
 23.2968 - 
 23.2969 - static int
 23.2970 --numcompare (char const *a, char const *b)
 23.2971 -+numcompare_uni (const char *a, const char *b)
 23.2972 - {
 23.2973 -   while (blanks[to_uchar (*a)])
 23.2974 -     a++;
 23.2975 -@@ -1954,6 +2300,25 @@ numcompare (char const *a, char const *b
 23.2976 -   return strnumcmp (a, b, decimal_point, thousands_sep);
 23.2977 - }
 23.2978 - 
 23.2979 -+#if HAVE_MBRTOWC
 23.2980 -+static int
 23.2981 -+numcompare_mb (const char *a, const char *b)
 23.2982 -+{
 23.2983 -+  size_t mblength, len;
 23.2984 -+  len = strlen (a); /* okay for UTF-8 */
 23.2985 -+  while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 23.2986 -+    {
 23.2987 -+      a += mblength;
 23.2988 -+      len -= mblength;
 23.2989 -+    }
 23.2990 -+  len = strlen (b); /* okay for UTF-8 */
 23.2991 -+  while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 23.2992 -+    b += mblength;
 23.2993 -+
 23.2994 -+  return strnumcmp (a, b, decimal_point, thousands_sep);
 23.2995 -+}
 23.2996 -+#endif /* HAV_EMBRTOWC */
 23.2997 -+
 23.2998 - /* Work around a problem whereby the long double value returned by glibc's
 23.2999 -    strtold ("NaN", ...) contains uninitialized bits: clear all bytes of
 23.3000 -    A and B before calling strtold.  FIXME: remove this function once
 23.3001 -@@ -2004,7 +2369,7 @@ general_numcompare (char const *sa, char
 23.3002 -    Return 0 if the name in S is not recognized.  */
 23.3003 - 
 23.3004 - static int
 23.3005 --getmonth (char const *month, char **ea)
 23.3006 -+getmonth_uni (char const *month, size_t len, char **ea)
 23.3007 - {
 23.3008 -   size_t lo = 0;
 23.3009 -   size_t hi = MONTHS_PER_YEAR;
 23.3010 -@@ -2280,15 +2645,14 @@ debug_key (struct line const *line, stru
 23.3011 -           char saved = *lim;
 23.3012 -           *lim = '\0';
 23.3013 - 
 23.3014 --          while (blanks[to_uchar (*beg)])
 23.3015 --            beg++;
 23.3016 -+          skipblanks (&beg, lim);
 23.3017 - 
 23.3018 -           char *tighter_lim = beg;
 23.3019 - 
 23.3020 -           if (lim < beg)
 23.3021 -             tighter_lim = lim;
 23.3022 -           else if (key->month)
 23.3023 --            getmonth (beg, &tighter_lim);
 23.3024 -+            getmonth (beg, lim-beg, &tighter_lim);
 23.3025 -           else if (key->general_numeric)
 23.3026 -             ignore_value (strtold (beg, &tighter_lim));
 23.3027 -           else if (key->numeric || key->human_numeric)
 23.3028 -@@ -2432,7 +2796,7 @@ key_warnings (struct keyfield const *gke
 23.3029 -       bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key)
 23.3030 -                                  && !(key->schar || key->echar);
 23.3031 -       bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y  */
 23.3032 --      if (!gkey_only && tab == TAB_DEFAULT && !line_offset
 23.3033 -+      if (!gkey_only && !tab_length && !line_offset
 23.3034 -           && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned))
 23.3035 -               || (!key->skipsblanks && key->schar)
 23.3036 -               || (!key->skipeblanks && key->echar)))
 23.3037 -@@ -2490,11 +2854,87 @@ key_warnings (struct keyfield const *gke
 23.3038 -     error (0, 0, _("option '-r' only applies to last-resort comparison"));
 23.3039 - }
 23.3040 - 
 23.3041 -+#if HAVE_MBRTOWC
 23.3042 -+static int
 23.3043 -+getmonth_mb (const char *s, size_t len, char **ea)
 23.3044 -+{
 23.3045 -+  char *month;
 23.3046 -+  register size_t i;
 23.3047 -+  register int lo = 0, hi = MONTHS_PER_YEAR, result;
 23.3048 -+  char *tmp;
 23.3049 -+  size_t wclength, mblength;
 23.3050 -+  const char *pp;
 23.3051 -+  const wchar_t *wpp;
 23.3052 -+  wchar_t *month_wcs;
 23.3053 -+  mbstate_t state;
 23.3054 -+
 23.3055 -+  while (len > 0 && ismbblank (s, len, &mblength))
 23.3056 -+    {
 23.3057 -+      s += mblength;
 23.3058 -+      len -= mblength;
 23.3059 -+    }
 23.3060 -+
 23.3061 -+  if (len == 0)
 23.3062 -+    return 0;
 23.3063 -+
 23.3064 -+  if (SIZE_MAX - len < 1)
 23.3065 -+    xalloc_die ();
 23.3066 -+
 23.3067 -+  month = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 23.3068 -+
 23.3069 -+  pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 23.3070 -+  memcpy (tmp, s, len);
 23.3071 -+  tmp[len] = '\0';
 23.3072 -+  wpp = month_wcs = (wchar_t *) xnmalloc (len + 1, sizeof (wchar_t));
 23.3073 -+  memset (&state, '\0', sizeof (mbstate_t));
 23.3074 -+
 23.3075 -+  wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state);
 23.3076 -+  if (wclength == (size_t)-1 || pp != NULL)
 23.3077 -+    error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s));
 23.3078 -+
 23.3079 -+  for (i = 0; i < wclength; i++)
 23.3080 -+    {
 23.3081 -+      month_wcs[i] = towupper(month_wcs[i]);
 23.3082 -+      if (iswblank (month_wcs[i]))
 23.3083 -+        {
 23.3084 -+          month_wcs[i] = L'\0';
 23.3085 -+          break;
 23.3086 -+        }
 23.3087 -+    }
 23.3088 -+
 23.3089 -+  mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state);
 23.3090 -+  assert (mblength != (-1) && wpp == NULL);
 23.3091 -+
 23.3092 -+  do
 23.3093 -+    {
 23.3094 -+      int ix = (lo + hi) / 2;
 23.3095 -+
 23.3096 -+      if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0)
 23.3097 -+        hi = ix;
 23.3098 -+      else
 23.3099 -+        lo = ix;
 23.3100 -+    }
 23.3101 -+  while (hi - lo > 1);
 23.3102 -+
 23.3103 -+  result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name))
 23.3104 -+      ? monthtab[lo].val : 0);
 23.3105 -+
 23.3106 -+  if (ea && result)
 23.3107 -+     *ea = (char*) s + strlen (monthtab[lo].name);
 23.3108 -+
 23.3109 -+  free (month);
 23.3110 -+  free (tmp);
 23.3111 -+  free (month_wcs);
 23.3112 -+
 23.3113 -+  return result;
 23.3114 -+}
 23.3115 -+#endif
 23.3116 -+
 23.3117 - /* Compare two lines A and B trying every key in sequence until there
 23.3118 -    are no more keys or a difference is found. */
 23.3119 - 
 23.3120 - static int
 23.3121 --keycompare (struct line const *a, struct line const *b)
 23.3122 -+keycompare_uni (const struct line *a, const struct line *b)
 23.3123 - {
 23.3124 -   struct keyfield *key = keylist;
 23.3125 - 
 23.3126 -@@ -2579,7 +3019,7 @@ keycompare (struct line const *a, struct
 23.3127 -           else if (key->human_numeric)
 23.3128 -             diff = human_numcompare (ta, tb);
 23.3129 -           else if (key->month)
 23.3130 --            diff = getmonth (ta, NULL) - getmonth (tb, NULL);
 23.3131 -+            diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL);
 23.3132 -           else if (key->random)
 23.3133 -             diff = compare_random (ta, tlena, tb, tlenb);
 23.3134 -           else if (key->version)
 23.3135 -@@ -2695,6 +3135,211 @@ keycompare (struct line const *a, struct
 23.3136 -   return key->reverse ? -diff : diff;
 23.3137 - }
 23.3138 - 
 23.3139 -+#if HAVE_MBRTOWC
 23.3140 -+static int
 23.3141 -+keycompare_mb (const struct line *a, const struct line *b)
 23.3142 -+{
 23.3143 -+  struct keyfield *key = keylist;
 23.3144 -+
 23.3145 -+  /* For the first iteration only, the key positions have been
 23.3146 -+     precomputed for us. */
 23.3147 -+  char *texta = a->keybeg;
 23.3148 -+  char *textb = b->keybeg;
 23.3149 -+  char *lima = a->keylim;
 23.3150 -+  char *limb = b->keylim;
 23.3151 -+
 23.3152 -+  size_t mblength_a, mblength_b;
 23.3153 -+  wchar_t wc_a, wc_b;
 23.3154 -+  mbstate_t state_a, state_b;
 23.3155 -+
 23.3156 -+  int diff = 0;
 23.3157 -+
 23.3158 -+  memset (&state_a, '\0', sizeof(mbstate_t));
 23.3159 -+  memset (&state_b, '\0', sizeof(mbstate_t));
 23.3160 -+  /* Ignore keys with start after end.  */
 23.3161 -+  if (a->keybeg - a->keylim > 0)
 23.3162 -+    return 0;
 23.3163 -+
 23.3164 -+
 23.3165 -+              /* Ignore and/or translate chars before comparing.  */
 23.3166 -+# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE)        \
 23.3167 -+  do                                                                        \
 23.3168 -+    {                                                                        \
 23.3169 -+      wchar_t uwc;                                                        \
 23.3170 -+      char mbc[MB_LEN_MAX];                                                \
 23.3171 -+      mbstate_t state_wc;                                                \
 23.3172 -+                                                                        \
 23.3173 -+      for (NEW_LEN = i = 0; i < LEN;)                                        \
 23.3174 -+        {                                                                \
 23.3175 -+          mbstate_t state_bak;                                                \
 23.3176 -+                                                                        \
 23.3177 -+          state_bak = STATE;                                                \
 23.3178 -+          MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE);                \
 23.3179 -+                                                                        \
 23.3180 -+          if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1                \
 23.3181 -+              || MBLENGTH == 0)                                                \
 23.3182 -+            {                                                                \
 23.3183 -+              if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1)        \
 23.3184 -+                STATE = state_bak;                                        \
 23.3185 -+              if (!ignore)                                                \
 23.3186 -+                COPY[NEW_LEN++] = TEXT[i];                                \
 23.3187 -+              i++;                                                         \
 23.3188 -+              continue;                                                        \
 23.3189 -+            }                                                                \
 23.3190 -+                                                                        \
 23.3191 -+          if (ignore)                                                        \
 23.3192 -+            {                                                                \
 23.3193 -+              if ((ignore == nonprinting && !iswprint (WC))                \
 23.3194 -+                   || (ignore == nondictionary                                \
 23.3195 -+                       && !iswalnum (WC) && !iswblank (WC)))                \
 23.3196 -+                {                                                        \
 23.3197 -+                  i += MBLENGTH;                                        \
 23.3198 -+                  continue;                                                \
 23.3199 -+                }                                                        \
 23.3200 -+            }                                                                \
 23.3201 -+                                                                        \
 23.3202 -+          if (translate)                                                \
 23.3203 -+            {                                                                \
 23.3204 -+                                                                        \
 23.3205 -+              uwc = towupper(WC);                                        \
 23.3206 -+              if (WC == uwc)                                                \
 23.3207 -+                {                                                        \
 23.3208 -+                  memcpy (mbc, TEXT + i, MBLENGTH);                        \
 23.3209 -+                  i += MBLENGTH;                                        \
 23.3210 -+                }                                                        \
 23.3211 -+              else                                                        \
 23.3212 -+                {                                                        \
 23.3213 -+                  i += MBLENGTH;                                        \
 23.3214 -+                  WC = uwc;                                                \
 23.3215 -+                  memset (&state_wc, '\0', sizeof (mbstate_t));                \
 23.3216 -+                                                                        \
 23.3217 -+                  MBLENGTH = wcrtomb (mbc, WC, &state_wc);                \
 23.3218 -+                  assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0);        \
 23.3219 -+                }                                                        \
 23.3220 -+                                                                        \
 23.3221 -+              for (j = 0; j < MBLENGTH; j++)                                \
 23.3222 -+                COPY[NEW_LEN++] = mbc[j];                                \
 23.3223 -+            }                                                                \
 23.3224 -+          else                                                                \
 23.3225 -+            for (j = 0; j < MBLENGTH; j++)                                \
 23.3226 -+              COPY[NEW_LEN++] = TEXT[i++];                                \
 23.3227 -+        }                                                                \
 23.3228 -+      COPY[NEW_LEN] = '\0';                                                \
 23.3229 -+    }                                                                        \
 23.3230 -+  while (0)
 23.3231 -+
 23.3232 -+      /* Actually compare the fields. */
 23.3233 -+
 23.3234 -+  for (;;)
 23.3235 -+    {
 23.3236 -+      /* Find the lengths. */
 23.3237 -+      size_t lena = lima <= texta ? 0 : lima - texta;
 23.3238 -+      size_t lenb = limb <= textb ? 0 : limb - textb;
 23.3239 -+
 23.3240 -+      char enda IF_LINT (= 0);
 23.3241 -+      char endb IF_LINT (= 0);
 23.3242 -+
 23.3243 -+      char const *translate = key->translate;
 23.3244 -+      bool const *ignore = key->ignore;
 23.3245 -+
 23.3246 -+      if (ignore || translate)
 23.3247 -+        {
 23.3248 -+          if (SIZE_MAX - lenb - 2 < lena)
 23.3249 -+            xalloc_die ();
 23.3250 -+          char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX);
 23.3251 -+          char *copy_b = copy_a + lena * MB_CUR_MAX + 1;
 23.3252 -+          size_t new_len_a, new_len_b;
 23.3253 -+          size_t i, j;
 23.3254 -+
 23.3255 -+          IGNORE_CHARS (new_len_a, lena, texta, copy_a,
 23.3256 -+                        wc_a, mblength_a, state_a);
 23.3257 -+          IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
 23.3258 -+                        wc_b, mblength_b, state_b);
 23.3259 -+          texta = copy_a; textb = copy_b;
 23.3260 -+          lena = new_len_a; lenb = new_len_b;
 23.3261 -+        }
 23.3262 -+      else
 23.3263 -+        {
 23.3264 -+          /* Use the keys in-place, temporarily null-terminated.  */
 23.3265 -+          enda = texta[lena]; texta[lena] = '\0';
 23.3266 -+          endb = textb[lenb]; textb[lenb] = '\0';
 23.3267 -+        }
 23.3268 -+
 23.3269 -+      if (key->random)
 23.3270 -+        diff = compare_random (texta, lena, textb, lenb);
 23.3271 -+      else if (key->numeric | key->general_numeric | key->human_numeric)
 23.3272 -+        {
 23.3273 -+          char savea = *lima, saveb = *limb;
 23.3274 -+
 23.3275 -+          *lima = *limb = '\0';
 23.3276 -+          diff = (key->numeric ? numcompare (texta, textb)
 23.3277 -+                  : key->general_numeric ? general_numcompare (texta, textb)
 23.3278 -+                  : human_numcompare (texta, textb));
 23.3279 -+          *lima = savea, *limb = saveb;
 23.3280 -+        }
 23.3281 -+      else if (key->version)
 23.3282 -+        diff = filevercmp (texta, textb);
 23.3283 -+      else if (key->month)
 23.3284 -+        diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL);
 23.3285 -+      else if (lena == 0)
 23.3286 -+        diff = - NONZERO (lenb);
 23.3287 -+      else if (lenb == 0)
 23.3288 -+        diff = 1;
 23.3289 -+      else if (hard_LC_COLLATE && !folding)
 23.3290 -+        {
 23.3291 -+          diff = xmemcoll0 (texta, lena + 1, textb, lenb + 1);
 23.3292 -+        }
 23.3293 -+      else
 23.3294 -+        {
 23.3295 -+          diff = memcmp (texta, textb, MIN (lena, lenb));
 23.3296 -+          if (diff == 0)
 23.3297 -+            diff = lena < lenb ? -1 : lena != lenb;
 23.3298 -+        }
 23.3299 -+
 23.3300 -+      if (ignore || translate)
 23.3301 -+        free (texta);
 23.3302 -+      else
 23.3303 -+        {
 23.3304 -+          texta[lena] = enda;
 23.3305 -+          textb[lenb] = endb;
 23.3306 -+        }
 23.3307 -+
 23.3308 -+      if (diff)
 23.3309 -+        goto not_equal;
 23.3310 -+
 23.3311 -+      key = key->next;
 23.3312 -+      if (! key)
 23.3313 -+        break;
 23.3314 -+
 23.3315 -+      /* Find the beginning and limit of the next field.  */
 23.3316 -+      if (key->eword != -1)
 23.3317 -+        lima = limfield (a, key), limb = limfield (b, key);
 23.3318 -+      else
 23.3319 -+        lima = a->text + a->length - 1, limb = b->text + b->length - 1;
 23.3320 -+
 23.3321 -+      if (key->sword != -1)
 23.3322 -+        texta = begfield (a, key), textb = begfield (b, key);
 23.3323 -+      else
 23.3324 -+        {
 23.3325 -+          texta = a->text, textb = b->text;
 23.3326 -+          if (key->skipsblanks)
 23.3327 -+            {
 23.3328 -+              while (texta < lima && ismbblank (texta, lima - texta, &mblength_a))
 23.3329 -+                texta += mblength_a;
 23.3330 -+              while (textb < limb && ismbblank (textb, limb - textb, &mblength_b))
 23.3331 -+                textb += mblength_b;
 23.3332 -+            }
 23.3333 -+        }
 23.3334 -+    }
 23.3335 -+
 23.3336 -+not_equal:
 23.3337 -+  if (key && key->reverse)
 23.3338 -+    return -diff;
 23.3339 -+  else
 23.3340 -+    return diff;
 23.3341 -+}
 23.3342 -+#endif
 23.3343 -+
 23.3344 - /* Compare two lines A and B, returning negative, zero, or positive
 23.3345 -    depending on whether A compares less than, equal to, or greater than B. */
 23.3346 - 
 23.3347 -@@ -2722,7 +3367,7 @@ compare (struct line const *a, struct li
 23.3348 -     diff = - NONZERO (blen);
 23.3349 -   else if (blen == 0)
 23.3350 -     diff = 1;
 23.3351 --  else if (hard_LC_COLLATE)
 23.3352 -+  else if (hard_LC_COLLATE && !folding)
 23.3353 -     {
 23.3354 -       /* Note xmemcoll0 is a performance enhancement as
 23.3355 -          it will not unconditionally write '\0' after the
 23.3356 -@@ -4121,6 +4766,7 @@ set_ordering (char const *s, struct keyf
 23.3357 -           break;
 23.3358 -         case 'f':
 23.3359 -           key->translate = fold_toupper;
 23.3360 -+          folding = true;
 23.3361 -           break;
 23.3362 -         case 'g':
 23.3363 -           key->general_numeric = true;
 23.3364 -@@ -4199,7 +4845,7 @@ main (int argc, char **argv)
 23.3365 -   initialize_exit_failure (SORT_FAILURE);
 23.3366 - 
 23.3367 -   hard_LC_COLLATE = hard_locale (LC_COLLATE);
 23.3368 --#if HAVE_NL_LANGINFO
 23.3369 -+#if HAVE_LANGINFO_CODESET
 23.3370 -   hard_LC_TIME = hard_locale (LC_TIME);
 23.3371 - #endif
 23.3372 - 
 23.3373 -@@ -4220,6 +4866,29 @@ main (int argc, char **argv)
 23.3374 -       thousands_sep = -1;
 23.3375 -   }
 23.3376 - 
 23.3377 -+#if HAVE_MBRTOWC
 23.3378 -+  if (MB_CUR_MAX > 1)
 23.3379 -+    {
 23.3380 -+      inittables = inittables_mb;
 23.3381 -+      begfield = begfield_mb;
 23.3382 -+      limfield = limfield_mb;
 23.3383 -+      skipblanks = skipblanks_mb;
 23.3384 -+      getmonth = getmonth_mb;
 23.3385 -+      keycompare = keycompare_mb;
 23.3386 -+      numcompare = numcompare_mb;
 23.3387 -+    }
 23.3388 -+  else
 23.3389 -+#endif
 23.3390 -+    {
 23.3391 -+      inittables = inittables_uni;
 23.3392 -+      begfield = begfield_uni;
 23.3393 -+      limfield = limfield_uni;
 23.3394 -+      skipblanks = skipblanks_uni;
 23.3395 -+      getmonth = getmonth_uni;
 23.3396 -+      keycompare = keycompare_uni;
 23.3397 -+      numcompare = numcompare_uni;
 23.3398 -+    }
 23.3399 -+
 23.3400 -   have_read_stdin = false;
 23.3401 -   inittables ();
 23.3402 - 
 23.3403 -@@ -4494,13 +5163,34 @@ main (int argc, char **argv)
 23.3404 - 
 23.3405 -         case 't':
 23.3406 -           {
 23.3407 --            char newtab = optarg[0];
 23.3408 --            if (! newtab)
 23.3409 -+            char newtab[MB_LEN_MAX + 1];
 23.3410 -+            size_t newtab_length = 1;
 23.3411 -+            strncpy (newtab, optarg, MB_LEN_MAX);
 23.3412 -+            if (! newtab[0])
 23.3413 -               error (SORT_FAILURE, 0, _("empty tab"));
 23.3414 --            if (optarg[1])
 23.3415 -+#if HAVE_MBRTOWC
 23.3416 -+            if (MB_CUR_MAX > 1)
 23.3417 -+              {
 23.3418 -+                wchar_t wc;
 23.3419 -+                mbstate_t state;
 23.3420 -+
 23.3421 -+                memset (&state, '\0', sizeof (mbstate_t));
 23.3422 -+                newtab_length = mbrtowc (&wc, newtab, strnlen (newtab,
 23.3423 -+                                                               MB_LEN_MAX),
 23.3424 -+                                         &state);
 23.3425 -+                switch (newtab_length)
 23.3426 -+                  {
 23.3427 -+                  case (size_t) -1:
 23.3428 -+                  case (size_t) -2:
 23.3429 -+                  case 0:
 23.3430 -+                    newtab_length = 1;
 23.3431 -+                  }
 23.3432 -+              }
 23.3433 -+#endif
 23.3434 -+            if (newtab_length == 1 && optarg[1])
 23.3435 -               {
 23.3436 -                 if (STREQ (optarg, "\\0"))
 23.3437 --                  newtab = '\0';
 23.3438 -+                  newtab[0] = '\0';
 23.3439 -                 else
 23.3440 -                   {
 23.3441 -                     /* Provoke with 'sort -txx'.  Complain about
 23.3442 -@@ -4511,9 +5201,12 @@ main (int argc, char **argv)
 23.3443 -                            quote (optarg));
 23.3444 -                   }
 23.3445 -               }
 23.3446 --            if (tab != TAB_DEFAULT && tab != newtab)
 23.3447 -+            if (tab_length
 23.3448 -+                && (tab_length != newtab_length
 23.3449 -+                    || memcmp (tab, newtab, tab_length) != 0))
 23.3450 -               error (SORT_FAILURE, 0, _("incompatible tabs"));
 23.3451 --            tab = newtab;
 23.3452 -+            memcpy (tab, newtab, newtab_length);
 23.3453 -+            tab_length = newtab_length;
 23.3454 -           }
 23.3455 -           break;
 23.3456 - 
 23.3457 -@@ -4751,12 +5444,10 @@ main (int argc, char **argv)
 23.3458 -       sort (files, nfiles, outfile, nthreads);
 23.3459 -     }
 23.3460 - 
 23.3461 --#ifdef lint
 23.3462 -   if (files_from)
 23.3463 -     readtokens0_free (&tok);
 23.3464 -   else
 23.3465 -     free (files);
 23.3466 --#endif
 23.3467 - 
 23.3468 -   if (have_read_stdin && fclose (stdin) == EOF)
 23.3469 -     die (_("close failed"), "-");
 23.3470 -diff -Naurp coreutils-8.25-orig/src/unexpand.c coreutils-8.25/src/unexpand.c
 23.3471 ---- coreutils-8.25-orig/src/unexpand.c	2016-01-01 07:48:50.000000000 -0600
 23.3472 -+++ coreutils-8.25/src/unexpand.c	2016-02-08 19:07:10.311944651 -0600
 23.3473 -@@ -38,12 +38,29 @@
 23.3474 - #include <stdio.h>
 23.3475 - #include <getopt.h>
 23.3476 - #include <sys/types.h>
 23.3477 -+
 23.3478 -+/* Get mbstate_t, mbrtowc(), wcwidth(). */
 23.3479 -+#if HAVE_WCHAR_H
 23.3480 -+# include <wchar.h>
 23.3481 -+#endif
 23.3482 -+
 23.3483 - #include "system.h"
 23.3484 - #include "error.h"
 23.3485 - #include "fadvise.h"
 23.3486 - #include "quote.h"
 23.3487 - #include "xstrndup.h"
 23.3488 - 
 23.3489 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 23.3490 -+      installation; work around this configuration error.  */
 23.3491 -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 23.3492 -+# define MB_LEN_MAX 16
 23.3493 -+#endif
 23.3494 -+
 23.3495 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 23.3496 -+#if HAVE_MBRTOWC && defined mbstate_t
 23.3497 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 23.3498 -+#endif
 23.3499 -+
 23.3500 - /* The official name of this program (e.g., no 'g' prefix).  */
 23.3501 - #define PROGRAM_NAME "unexpand"
 23.3502 - 
 23.3503 -@@ -103,6 +120,210 @@ static struct option const longopts[] =
 23.3504 -   {NULL, 0, NULL, 0}
 23.3505 - };
 23.3506 - 
 23.3507 -+static FILE *next_file (FILE *fp);
 23.3508 -+
 23.3509 -+#if HAVE_MBRTOWC
 23.3510 -+static void
 23.3511 -+unexpand_multibyte (void)
 23.3512 -+{
 23.3513 -+  FILE *fp;			/* Input stream. */
 23.3514 -+  mbstate_t i_state;		/* Current shift state of the input stream. */
 23.3515 -+  mbstate_t i_state_bak;	/* Back up the I_STATE. */
 23.3516 -+  mbstate_t o_state;		/* Current shift state of the output stream. */
 23.3517 -+  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
 23.3518 -+  char *bufpos = buf;			/* Next read position of BUF. */
 23.3519 -+  size_t buflen = 0;		/* The length of the byte sequence in buf. */
 23.3520 -+  wint_t wc;			/* A gotten wide character. */
 23.3521 -+  size_t mblength;		/* The byte size of a multibyte character
 23.3522 -+				   which shows as same character as WC. */
 23.3523 -+  bool prev_tab = false;
 23.3524 -+
 23.3525 -+  /* Index in `tab_list' of next tabstop: */
 23.3526 -+  int tab_index = 0;		/* For calculating width of pending tabs. */
 23.3527 -+  int print_tab_index = 0;	/* For printing as many tabs as possible. */
 23.3528 -+  unsigned int column = 0;	/* Column on screen of next char. */
 23.3529 -+  int next_tab_column;		/* Column the next tab stop is on. */
 23.3530 -+  int convert = 1;		/* If nonzero, perform translations. */
 23.3531 -+  unsigned int pending = 0;	/* Pending columns of blanks. */
 23.3532 -+
 23.3533 -+  fp = next_file ((FILE *) NULL);
 23.3534 -+  if (fp == NULL)
 23.3535 -+    return;
 23.3536 -+
 23.3537 -+  memset (&o_state, '\0', sizeof(mbstate_t));
 23.3538 -+  memset (&i_state, '\0', sizeof(mbstate_t));
 23.3539 -+
 23.3540 -+  for (;;)
 23.3541 -+    {
 23.3542 -+      if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp))
 23.3543 -+	{
 23.3544 -+	  memmove (buf, bufpos, buflen);
 23.3545 -+	  buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp);
 23.3546 -+	  bufpos = buf;
 23.3547 -+	}
 23.3548 -+
 23.3549 -+      /* Get a wide character. */
 23.3550 -+      if (buflen < 1)
 23.3551 -+	{
 23.3552 -+	  mblength = 1;
 23.3553 -+	  wc = WEOF;
 23.3554 -+	}
 23.3555 -+      else
 23.3556 -+	{
 23.3557 -+	  i_state_bak = i_state;
 23.3558 -+	  mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &i_state);
 23.3559 -+	}
 23.3560 -+
 23.3561 -+      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.3562 -+	{
 23.3563 -+	  i_state = i_state_bak;
 23.3564 -+	  wc = L'\0';
 23.3565 -+	}
 23.3566 -+
 23.3567 -+      if (wc == L' ' && convert && column < INT_MAX)
 23.3568 -+	{
 23.3569 -+	  ++pending;
 23.3570 -+	  ++column;
 23.3571 -+	}
 23.3572 -+      else if (wc == L'\t' && convert)
 23.3573 -+	{
 23.3574 -+	  if (tab_size == 0)
 23.3575 -+	    {
 23.3576 -+	      /* Do not let tab_index == first_free_tab;
 23.3577 -+		 stop when it is 1 less. */
 23.3578 -+	      while (tab_index < first_free_tab - 1
 23.3579 -+		  && column >= tab_list[tab_index])
 23.3580 -+		tab_index++;
 23.3581 -+	      next_tab_column = tab_list[tab_index];
 23.3582 -+	      if (tab_index < first_free_tab - 1)
 23.3583 -+		tab_index++;
 23.3584 -+	      if (column >= next_tab_column)
 23.3585 -+		{
 23.3586 -+		  convert = 0;	/* Ran out of tab stops. */
 23.3587 -+		  goto flush_pend_mb;
 23.3588 -+		}
 23.3589 -+	    }
 23.3590 -+	  else
 23.3591 -+	    {
 23.3592 -+	      next_tab_column = column + tab_size - column % tab_size;
 23.3593 -+	    }
 23.3594 -+	  pending += next_tab_column - column;
 23.3595 -+	  column = next_tab_column;
 23.3596 -+	}
 23.3597 -+      else
 23.3598 -+	{
 23.3599 -+flush_pend_mb:
 23.3600 -+	  /* Flush pending spaces.  Print as many tabs as possible,
 23.3601 -+	     then print the rest as spaces. */
 23.3602 -+	  if (pending == 1 && column != 1 && !prev_tab)
 23.3603 -+	    {
 23.3604 -+	      putchar (' ');
 23.3605 -+	      pending = 0;
 23.3606 -+	    }
 23.3607 -+	  column -= pending;
 23.3608 -+	  while (pending > 0)
 23.3609 -+	    {
 23.3610 -+	      if (tab_size == 0)
 23.3611 -+		{
 23.3612 -+		  /* Do not let print_tab_index == first_free_tab;
 23.3613 -+		     stop when it is 1 less. */
 23.3614 -+		  while (print_tab_index < first_free_tab - 1
 23.3615 -+		      && column >= tab_list[print_tab_index])
 23.3616 -+		    print_tab_index++;
 23.3617 -+		  next_tab_column = tab_list[print_tab_index];
 23.3618 -+		  if (print_tab_index < first_free_tab - 1)
 23.3619 -+		    print_tab_index++;
 23.3620 -+		}
 23.3621 -+	      else
 23.3622 -+		{
 23.3623 -+		  next_tab_column =
 23.3624 -+		    column + tab_size - column % tab_size;
 23.3625 -+		}
 23.3626 -+	      if (next_tab_column - column <= pending)
 23.3627 -+		{
 23.3628 -+		  putchar ('\t');
 23.3629 -+		  pending -= next_tab_column - column;
 23.3630 -+		  column = next_tab_column;
 23.3631 -+		}
 23.3632 -+	      else
 23.3633 -+		{
 23.3634 -+		  --print_tab_index;
 23.3635 -+		  column += pending;
 23.3636 -+		  while (pending != 0)
 23.3637 -+		    {
 23.3638 -+		      putchar (' ');
 23.3639 -+		      pending--;
 23.3640 -+		    }
 23.3641 -+		}
 23.3642 -+	    }
 23.3643 -+
 23.3644 -+	  if (wc == WEOF)
 23.3645 -+	    {
 23.3646 -+	      fp = next_file (fp);
 23.3647 -+	      if (fp == NULL)
 23.3648 -+		break;          /* No more files. */
 23.3649 -+	      else
 23.3650 -+		{
 23.3651 -+		  memset (&i_state, '\0', sizeof(mbstate_t));
 23.3652 -+		  continue;
 23.3653 -+		}
 23.3654 -+	    }
 23.3655 -+
 23.3656 -+	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 23.3657 -+	    {
 23.3658 -+	      if (convert)
 23.3659 -+		{
 23.3660 -+		  ++column;
 23.3661 -+		  if (convert_entire_line == 0)
 23.3662 -+		    convert = 0;
 23.3663 -+		}
 23.3664 -+	      mblength = 1;
 23.3665 -+	      putchar (buf[0]);
 23.3666 -+	    }
 23.3667 -+	  else if (mblength == 0)
 23.3668 -+	    {
 23.3669 -+	      if (convert && convert_entire_line == 0)
 23.3670 -+		convert = 0;
 23.3671 -+	      mblength = 1;
 23.3672 -+	      putchar ('\0');
 23.3673 -+	    }
 23.3674 -+	  else
 23.3675 -+	    {
 23.3676 -+	      if (convert)
 23.3677 -+		{
 23.3678 -+		  if (wc == L'\b')
 23.3679 -+		    {
 23.3680 -+		      if (column > 0)
 23.3681 -+			--column;
 23.3682 -+		    }
 23.3683 -+		  else
 23.3684 -+		    {
 23.3685 -+		      int width;            /* The width of WC. */
 23.3686 -+
 23.3687 -+		      width = wcwidth (wc);
 23.3688 -+		      column += (width > 0) ? width : 0;
 23.3689 -+		      if (convert_entire_line == 0)
 23.3690 -+			convert = 0;
 23.3691 -+		    }
 23.3692 -+		}
 23.3693 -+
 23.3694 -+	      if (wc == L'\n')
 23.3695 -+		{
 23.3696 -+		  tab_index = print_tab_index = 0;
 23.3697 -+		  column = pending = 0;
 23.3698 -+		  convert = 1;
 23.3699 -+		}
 23.3700 -+	      fwrite (bufpos, sizeof(char), mblength, stdout);
 23.3701 -+	    }
 23.3702 -+	}
 23.3703 -+      prev_tab = wc == L'\t';
 23.3704 -+      buflen -= mblength;
 23.3705 -+      bufpos += mblength;
 23.3706 -+    }
 23.3707 -+}
 23.3708 -+#endif
 23.3709 -+
 23.3710 -+
 23.3711 - void
 23.3712 - usage (int status)
 23.3713 - {
 23.3714 -@@ -523,7 +744,12 @@ main (int argc, char **argv)
 23.3715 - 
 23.3716 -   file_list = (optind < argc ? &argv[optind] : stdin_argv);
 23.3717 - 
 23.3718 --  unexpand ();
 23.3719 -+#if HAVE_MBRTOWC
 23.3720 -+  if (MB_CUR_MAX > 1)
 23.3721 -+    unexpand_multibyte ();
 23.3722 -+  else
 23.3723 -+#endif
 23.3724 -+    unexpand ();
 23.3725 - 
 23.3726 -   if (have_read_stdin && fclose (stdin) != 0)
 23.3727 -     error (EXIT_FAILURE, errno, "-");
 23.3728 -diff -Naurp coreutils-8.25-orig/src/uniq.c coreutils-8.25/src/uniq.c
 23.3729 ---- coreutils-8.25-orig/src/uniq.c	2016-01-13 05:08:59.000000000 -0600
 23.3730 -+++ coreutils-8.25/src/uniq.c	2016-02-08 19:07:10.312944654 -0600
 23.3731 -@@ -21,6 +21,17 @@
 23.3732 - #include <getopt.h>
 23.3733 - #include <sys/types.h>
 23.3734 - 
 23.3735 -+/* Get mbstate_t, mbrtowc(). */
 23.3736 -+#if HAVE_WCHAR_H
 23.3737 -+# include <wchar.h>
 23.3738 -+#endif
 23.3739 -+
 23.3740 -+/* Get isw* functions. */
 23.3741 -+#if HAVE_WCTYPE_H
 23.3742 -+# include <wctype.h>
 23.3743 -+#endif
 23.3744 -+#include <assert.h>
 23.3745 -+
 23.3746 - #include "system.h"
 23.3747 - #include "argmatch.h"
 23.3748 - #include "linebuffer.h"
 23.3749 -@@ -33,6 +44,18 @@
 23.3750 - #include "xstrtol.h"
 23.3751 - #include "memcasecmp.h"
 23.3752 - #include "quote.h"
 23.3753 -+#include "xmemcoll.h"
 23.3754 -+
 23.3755 -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 23.3756 -+   installation; work around this configuration error.  */
 23.3757 -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 23.3758 -+# define MB_LEN_MAX 16
 23.3759 -+#endif
 23.3760 -+
 23.3761 -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 23.3762 -+#if HAVE_MBRTOWC && defined mbstate_t
 23.3763 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 23.3764 -+#endif
 23.3765 - 
 23.3766 - /* The official name of this program (e.g., no 'g' prefix).  */
 23.3767 - #define PROGRAM_NAME "uniq"
 23.3768 -@@ -143,6 +166,10 @@ enum
 23.3769 -   GROUP_OPTION = CHAR_MAX + 1
 23.3770 - };
 23.3771 - 
 23.3772 -+/* Function pointers. */
 23.3773 -+static char *
 23.3774 -+(*find_field) (struct linebuffer *line);
 23.3775 -+
 23.3776 - static struct option const longopts[] =
 23.3777 - {
 23.3778 -   {"count", no_argument, NULL, 'c'},
 23.3779 -@@ -252,7 +279,7 @@ size_opt (char const *opt, char const *m
 23.3780 -    return a pointer to the beginning of the line's field to be compared. */
 23.3781 - 
 23.3782 - static char * _GL_ATTRIBUTE_PURE
 23.3783 --find_field (struct linebuffer const *line)
 23.3784 -+find_field_uni (struct linebuffer *line)
 23.3785 - {
 23.3786 -   size_t count;
 23.3787 -   char const *lp = line->buffer;
 23.3788 -@@ -272,6 +299,83 @@ find_field (struct linebuffer const *lin
 23.3789 -   return line->buffer + i;
 23.3790 - }
 23.3791 - 
 23.3792 -+#if HAVE_MBRTOWC
 23.3793 -+
 23.3794 -+# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL)  \
 23.3795 -+  do                                                                        \
 23.3796 -+    {                                                                        \
 23.3797 -+      mbstate_t state_bak;                                                \
 23.3798 -+                                                                        \
 23.3799 -+      CONVFAIL = 0;                                                        \
 23.3800 -+      state_bak = *STATEP;                                                \
 23.3801 -+                                                                        \
 23.3802 -+      MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP);                \
 23.3803 -+                                                                        \
 23.3804 -+      switch (MBLENGTH)                                                        \
 23.3805 -+        {                                                                \
 23.3806 -+        case (size_t)-2:                                                \
 23.3807 -+        case (size_t)-1:                                                \
 23.3808 -+          *STATEP = state_bak;                                                \
 23.3809 -+          CONVFAIL++;                                                        \
 23.3810 -+          /* Fall through */                                                \
 23.3811 -+        case 0:                                                                \
 23.3812 -+          MBLENGTH = 1;                                                        \
 23.3813 -+        }                                                                \
 23.3814 -+    }                                                                        \
 23.3815 -+  while (0)
 23.3816 -+
 23.3817 -+static char *
 23.3818 -+find_field_multi (struct linebuffer *line)
 23.3819 -+{
 23.3820 -+  size_t count;
 23.3821 -+  char *lp = line->buffer;
 23.3822 -+  size_t size = line->length - 1;
 23.3823 -+  size_t pos;
 23.3824 -+  size_t mblength;
 23.3825 -+  wchar_t wc;
 23.3826 -+  mbstate_t *statep;
 23.3827 -+  int convfail = 0;
 23.3828 -+
 23.3829 -+  pos = 0;
 23.3830 -+  statep = &(line->state);
 23.3831 -+
 23.3832 -+  /* skip fields. */
 23.3833 -+  for (count = 0; count < skip_fields && pos < size; count++)
 23.3834 -+    {
 23.3835 -+      while (pos < size)
 23.3836 -+        {
 23.3837 -+          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 23.3838 -+
 23.3839 -+          if (convfail || !(iswblank (wc) || wc == '\n'))
 23.3840 -+            {
 23.3841 -+              pos += mblength;
 23.3842 -+              break;
 23.3843 -+            }
 23.3844 -+          pos += mblength;
 23.3845 -+        }
 23.3846 -+
 23.3847 -+      while (pos < size)
 23.3848 -+        {
 23.3849 -+          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 23.3850 -+
 23.3851 -+          if (!convfail && (iswblank (wc) || wc == '\n'))
 23.3852 -+            break;
 23.3853 -+
 23.3854 -+          pos += mblength;
 23.3855 -+        }
 23.3856 -+    }
 23.3857 -+
 23.3858 -+  /* skip fields. */
 23.3859 -+  for (count = 0; count < skip_chars && pos < size; count++)
 23.3860 -+    {
 23.3861 -+      MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 23.3862 -+      pos += mblength;
 23.3863 -+    }
 23.3864 -+
 23.3865 -+  return lp + pos;
 23.3866 -+}
 23.3867 -+#endif
 23.3868 -+
 23.3869 - /* Return false if two strings OLD and NEW match, true if not.
 23.3870 -    OLD and NEW point not to the beginnings of the lines
 23.3871 -    but rather to the beginnings of the fields to compare.
 23.3872 -@@ -280,6 +384,8 @@ find_field (struct linebuffer const *lin
 23.3873 - static bool
 23.3874 - different (char *old, char *new, size_t oldlen, size_t newlen)
 23.3875 - {
 23.3876 -+  char *copy_old, *copy_new;
 23.3877 -+
 23.3878 -   if (check_chars < oldlen)
 23.3879 -     oldlen = check_chars;
 23.3880 -   if (check_chars < newlen)
 23.3881 -@@ -287,15 +393,104 @@ different (char *old, char *new, size_t
 23.3882 - 
 23.3883 -   if (ignore_case)
 23.3884 -     {
 23.3885 --      /* FIXME: This should invoke strcoll somehow.  */
 23.3886 --      return oldlen != newlen || memcasecmp (old, new, oldlen);
 23.3887 -+      size_t i;
 23.3888 -+
 23.3889 -+      copy_old = xmalloc (oldlen + 1);
 23.3890 -+      copy_new = xmalloc (oldlen + 1);
 23.3891 -+
 23.3892 -+      for (i = 0; i < oldlen; i++)
 23.3893 -+        {
 23.3894 -+          copy_old[i] = toupper (old[i]);
 23.3895 -+          copy_new[i] = toupper (new[i]);
 23.3896 -+        }
 23.3897 -+      bool rc = xmemcoll (copy_old, oldlen, copy_new, newlen);
 23.3898 -+      free (copy_old);
 23.3899 -+      free (copy_new);
 23.3900 -+      return rc;
 23.3901 -     }
 23.3902 --  else if (hard_LC_COLLATE)
 23.3903 --    return xmemcoll (old, oldlen, new, newlen) != 0;
 23.3904 -   else
 23.3905 --    return oldlen != newlen || memcmp (old, new, oldlen);
 23.3906 -+    {
 23.3907 -+      copy_old = (char *)old;
 23.3908 -+      copy_new = (char *)new;
 23.3909 -+    }
 23.3910 -+
 23.3911 -+  return xmemcoll (copy_old, oldlen, copy_new, newlen);
 23.3912 -+
 23.3913 - }
 23.3914 - 
 23.3915 -+#if HAVE_MBRTOWC
 23.3916 -+static int
 23.3917 -+different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate)
 23.3918 -+{
 23.3919 -+  size_t i, j, chars;
 23.3920 -+  const char *str[2];
 23.3921 -+  char *copy[2];
 23.3922 -+  size_t len[2];
 23.3923 -+  mbstate_t state[2];
 23.3924 -+  size_t mblength;
 23.3925 -+  wchar_t wc, uwc;
 23.3926 -+  mbstate_t state_bak;
 23.3927 -+
 23.3928 -+  str[0] = old;
 23.3929 -+  str[1] = new;
 23.3930 -+  len[0] = oldlen;
 23.3931 -+  len[1] = newlen;
 23.3932 -+  state[0] = oldstate;
 23.3933 -+  state[1] = newstate;
 23.3934 -+
 23.3935 -+  for (i = 0; i < 2; i++)
 23.3936 -+    {
 23.3937 -+      copy[i] = xmalloc (len[i] + 1);
 23.3938 -+      memset (copy[i], '\0', len[i] + 1);
 23.3939 -+
 23.3940 -+      for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++)
 23.3941 -+        {
 23.3942 -+          state_bak = state[i];
 23.3943 -+          mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i]));
 23.3944 -+
 23.3945 -+          switch (mblength)
 23.3946 -+            {
 23.3947 -+            case (size_t)-1:
 23.3948 -+            case (size_t)-2:
 23.3949 -+              state[i] = state_bak;
 23.3950 -+              /* Fall through */
 23.3951 -+            case 0:
 23.3952 -+              mblength = 1;
 23.3953 -+              break;
 23.3954 -+
 23.3955 -+            default:
 23.3956 -+              if (ignore_case)
 23.3957 -+                {
 23.3958 -+                  uwc = towupper (wc);
 23.3959 -+
 23.3960 -+                  if (uwc != wc)
 23.3961 -+                    {
 23.3962 -+                      mbstate_t state_wc;
 23.3963 -+                      size_t mblen;
 23.3964 -+
 23.3965 -+                      memset (&state_wc, '\0', sizeof(mbstate_t));
 23.3966 -+                      mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 23.3967 -+                      assert (mblen != (size_t)-1);
 23.3968 -+                    }
 23.3969 -+                  else
 23.3970 -+                    memcpy (copy[i] + j, str[i] + j, mblength);
 23.3971 -+                }
 23.3972 -+              else
 23.3973 -+                memcpy (copy[i] + j, str[i] + j, mblength);
 23.3974 -+            }
 23.3975 -+          j += mblength;
 23.3976 -+        }
 23.3977 -+      copy[i][j] = '\0';
 23.3978 -+      len[i] = j;
 23.3979 -+    }
 23.3980 -+  int rc = xmemcoll (copy[0], len[0], copy[1], len[1]);
 23.3981 -+  free (copy[0]);
 23.3982 -+  free (copy[1]);
 23.3983 -+  return rc;
 23.3984 -+
 23.3985 -+}
 23.3986 -+#endif
 23.3987 -+
 23.3988 - /* Output the line in linebuffer LINE to standard output
 23.3989 -    provided that the switches say it should be output.
 23.3990 -    MATCH is true if the line matches the previous line.
 23.3991 -@@ -359,19 +554,38 @@ check_file (const char *infile, const ch
 23.3992 -       char *prevfield IF_LINT ( = NULL);
 23.3993 -       size_t prevlen IF_LINT ( = 0);
 23.3994 -       bool first_group_printed = false;
 23.3995 -+#if HAVE_MBRTOWC
 23.3996 -+      mbstate_t prevstate;
 23.3997 -+
 23.3998 -+      memset (&prevstate, '\0', sizeof (mbstate_t));
 23.3999 -+#endif
 23.4000 - 
 23.4001 -       while (!feof (stdin))
 23.4002 -         {
 23.4003 -           char *thisfield;
 23.4004 -           size_t thislen;
 23.4005 -           bool new_group;
 23.4006 -+#if HAVE_MBRTOWC
 23.4007 -+          mbstate_t thisstate;
 23.4008 -+#endif
 23.4009 - 
 23.4010 -           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 23.4011 -             break;
 23.4012 - 
 23.4013 -           thisfield = find_field (thisline);
 23.4014 -           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 23.4015 -+#if HAVE_MBRTOWC
 23.4016 -+          if (MB_CUR_MAX > 1)
 23.4017 -+            {
 23.4018 -+              thisstate = thisline->state;
 23.4019 - 
 23.4020 -+              new_group = (prevline->length == 0
 23.4021 -+                           || different_multi (thisfield, prevfield,
 23.4022 -+                                               thislen, prevlen,
 23.4023 -+                                               thisstate, prevstate));
 23.4024 -+            }
 23.4025 -+          else
 23.4026 -+#endif
 23.4027 -           new_group = (prevline->length == 0
 23.4028 -                        || different (thisfield, prevfield, thislen, prevlen));
 23.4029 - 
 23.4030 -@@ -389,6 +603,10 @@ check_file (const char *infile, const ch
 23.4031 -               SWAP_LINES (prevline, thisline);
 23.4032 -               prevfield = thisfield;
 23.4033 -               prevlen = thislen;
 23.4034 -+#if HAVE_MBRTOWC
 23.4035 -+              if (MB_CUR_MAX > 1)
 23.4036 -+                prevstate = thisstate;
 23.4037 -+#endif
 23.4038 -               first_group_printed = true;
 23.4039 -             }
 23.4040 -         }
 23.4041 -@@ -401,17 +619,26 @@ check_file (const char *infile, const ch
 23.4042 -       size_t prevlen;
 23.4043 -       uintmax_t match_count = 0;
 23.4044 -       bool first_delimiter = true;
 23.4045 -+#if HAVE_MBRTOWC
 23.4046 -+      mbstate_t prevstate;
 23.4047 -+#endif
 23.4048 - 
 23.4049 -       if (readlinebuffer_delim (prevline, stdin, delimiter) == 0)
 23.4050 -         goto closefiles;
 23.4051 -       prevfield = find_field (prevline);
 23.4052 -       prevlen = prevline->length - 1 - (prevfield - prevline->buffer);
 23.4053 -+#if HAVE_MBRTOWC
 23.4054 -+      prevstate = prevline->state;
 23.4055 -+#endif
 23.4056 - 
 23.4057 -       while (!feof (stdin))
 23.4058 -         {
 23.4059 -           bool match;
 23.4060 -           char *thisfield;
 23.4061 -           size_t thislen;
 23.4062 -+#if HAVE_MBRTOWC
 23.4063 -+          mbstate_t thisstate = thisline->state;
 23.4064 -+#endif
 23.4065 -           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 23.4066 -             {
 23.4067 -               if (ferror (stdin))
 23.4068 -@@ -420,6 +647,14 @@ check_file (const char *infile, const ch
 23.4069 -             }
 23.4070 -           thisfield = find_field (thisline);
 23.4071 -           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 23.4072 -+#if HAVE_MBRTOWC
 23.4073 -+          if (MB_CUR_MAX > 1)
 23.4074 -+            {
 23.4075 -+              match = !different_multi (thisfield, prevfield,
 23.4076 -+                                thislen, prevlen, thisstate, prevstate);
 23.4077 -+            }
 23.4078 -+          else
 23.4079 -+#endif
 23.4080 -           match = !different (thisfield, prevfield, thislen, prevlen);
 23.4081 -           match_count += match;
 23.4082 - 
 23.4083 -@@ -452,6 +687,9 @@ check_file (const char *infile, const ch
 23.4084 -               SWAP_LINES (prevline, thisline);
 23.4085 -               prevfield = thisfield;
 23.4086 -               prevlen = thislen;
 23.4087 -+#if HAVE_MBRTOWC
 23.4088 -+              prevstate = thisstate;
 23.4089 -+#endif
 23.4090 -               if (!match)
 23.4091 -                 match_count = 0;
 23.4092 -             }
 23.4093 -@@ -498,6 +736,19 @@ main (int argc, char **argv)
 23.4094 - 
 23.4095 -   atexit (close_stdout);
 23.4096 - 
 23.4097 -+#if HAVE_MBRTOWC
 23.4098 -+  if (MB_CUR_MAX > 1)
 23.4099 -+    {
 23.4100 -+      find_field = find_field_multi;
 23.4101 -+    }
 23.4102 -+  else
 23.4103 -+#endif
 23.4104 -+    {
 23.4105 -+      find_field = find_field_uni;
 23.4106 -+    }
 23.4107 -+
 23.4108 -+
 23.4109 -+
 23.4110 -   skip_chars = 0;
 23.4111 -   skip_fields = 0;
 23.4112 -   check_chars = SIZE_MAX;
 23.4113 -diff -Naurp coreutils-8.25-orig/tests/i18n/sort-month.sh coreutils-8.25/tests/i18n/sort-month.sh
 23.4114 ---- coreutils-8.25-orig/tests/i18n/sort-month.sh	1969-12-31 18:00:00.000000000 -0600
 23.4115 -+++ coreutils-8.25/tests/i18n/sort-month.sh	2016-02-08 19:07:10.312944654 -0600
 23.4116 -@@ -0,0 +1,34 @@
 23.4117 -+#!/bin/sh
 23.4118 -+# Verify sort -M multi-byte support.
 23.4119 -+
 23.4120 -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 23.4121 -+print_ver_ sort
 23.4122 -+require_valgrind_
 23.4123 -+
 23.4124 -+# Skip this test if some deallocations are
 23.4125 -+# avoided at process end.
 23.4126 -+grep '^#define lint 1' $CONFIG_HEADER > /dev/null ||
 23.4127 -+  skip_ 'Allocation checks only work reliably in "lint" mode'
 23.4128 -+
 23.4129 -+export LC_ALL=en_US.UTF-8
 23.4130 -+locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 23.4131 -+  || skip_ "No UTF-8 locale available"
 23.4132 -+
 23.4133 -+# Note the use of ɑ here which expands to
 23.4134 -+# a wider representation upon case conversion
 23.4135 -+# which triggered an assertion in sort -M
 23.4136 -+cat <<EOF > exp
 23.4137 -+.
 23.4138 -+ɑ
 23.4139 -+EOF
 23.4140 -+
 23.4141 -+
 23.4142 -+# check large mem leak with --month-sort
 23.4143 -+# https://bugzilla.redhat.com/show_bug.cgi?id=1259942
 23.4144 -+valgrind --leak-check=full \
 23.4145 -+         --error-exitcode=1 --errors-for-leak-kinds=definite \
 23.4146 -+         sort -M < exp > out || fail=1
 23.4147 -+compare exp out || { fail=1; cat out; }
 23.4148 -+
 23.4149 -+
 23.4150 -+Exit $fail
 23.4151 -diff -Naurp coreutils-8.25-orig/tests/i18n/sort.sh coreutils-8.25/tests/i18n/sort.sh
 23.4152 ---- coreutils-8.25-orig/tests/i18n/sort.sh	1969-12-31 18:00:00.000000000 -0600
 23.4153 -+++ coreutils-8.25/tests/i18n/sort.sh	2016-02-08 19:07:10.312944654 -0600
 23.4154 -@@ -0,0 +1,29 @@
 23.4155 -+#!/bin/sh
 23.4156 -+# Verify sort's multi-byte support.
 23.4157 -+
 23.4158 -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 23.4159 -+print_ver_ sort
 23.4160 -+
 23.4161 -+export LC_ALL=en_US.UTF-8
 23.4162 -+locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 23.4163 -+  || skip_ "No UTF-8 locale available"
 23.4164 -+
 23.4165 -+# Enable heap consistency checkng on older systems
 23.4166 -+export MALLOC_CHECK_=2
 23.4167 -+
 23.4168 -+
 23.4169 -+# check buffer overflow issue due to
 23.4170 -+# expanding multi-byte representation due to case conversion
 23.4171 -+# https://bugzilla.suse.com/show_bug.cgi?id=928749
 23.4172 -+cat <<EOF > exp
 23.4173 -+.
 23.4174 -+ɑ
 23.4175 -+EOF
 23.4176 -+cat <<EOF | sort -f > out || fail=1
 23.4177 -+.
 23.4178 -+ɑ
 23.4179 -+EOF
 23.4180 -+compare exp out || { fail=1; cat out; }
 23.4181 -+
 23.4182 -+
 23.4183 -+Exit $fail
 23.4184 -diff -Naurp coreutils-8.25-orig/tests/local.mk coreutils-8.25/tests/local.mk
 23.4185 ---- coreutils-8.25-orig/tests/local.mk	2016-01-16 12:18:13.000000000 -0600
 23.4186 -+++ coreutils-8.25/tests/local.mk	2016-02-08 19:07:10.313944658 -0600
 23.4187 -@@ -344,6 +344,9 @@ all_tests =					\
 23.4188 -   tests/misc/sort-discrim.sh			\
 23.4189 -   tests/misc/sort-files0-from.pl		\
 23.4190 -   tests/misc/sort-float.sh			\
 23.4191 -+  tests/misc/sort-mb-tests.sh			\
 23.4192 -+  tests/i18n/sort.sh				\
 23.4193 -+  tests/i18n/sort-month.sh			\
 23.4194 -   tests/misc/sort-merge.pl			\
 23.4195 -   tests/misc/sort-merge-fdlimit.sh		\
 23.4196 -   tests/misc/sort-month.sh			\
 23.4197 -diff -Naurp coreutils-8.25-orig/tests/misc/cut.pl coreutils-8.25/tests/misc/cut.pl
 23.4198 ---- coreutils-8.25-orig/tests/misc/cut.pl	2016-01-16 12:18:13.000000000 -0600
 23.4199 -+++ coreutils-8.25/tests/misc/cut.pl	2016-02-08 19:07:10.314944661 -0600
 23.4200 -@@ -23,9 +23,11 @@ use strict;
 23.4201 - # Turn off localization of executable's output.
 23.4202 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4203 - 
 23.4204 --my $mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4205 -+my $mb_locale;
 23.4206 -+# uncommented enable multibyte paths
 23.4207 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4208 - ! defined $mb_locale || $mb_locale eq 'none'
 23.4209 --  and $mb_locale = 'C';
 23.4210 -+ and $mb_locale = 'C';
 23.4211 - 
 23.4212 - my $prog = 'cut';
 23.4213 - my $try = "Try '$prog --help' for more information.\n";
 23.4214 -@@ -240,6 +242,7 @@ if ($mb_locale ne 'C')
 23.4215 -         my @new_t = @$t;
 23.4216 -         my $test_name = shift @new_t;
 23.4217 - 
 23.4218 -+        next if ($test_name =~ "newline-[12][0-9]");
 23.4219 -         push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4220 -       }
 23.4221 -     push @Tests, @new;
 23.4222 -diff -Naurp coreutils-8.25-orig/tests/misc/expand.pl coreutils-8.25/tests/misc/expand.pl
 23.4223 ---- coreutils-8.25-orig/tests/misc/expand.pl	2016-01-16 12:18:13.000000000 -0600
 23.4224 -+++ coreutils-8.25/tests/misc/expand.pl	2016-02-08 19:07:10.314944661 -0600
 23.4225 -@@ -23,6 +23,15 @@ use strict;
 23.4226 - # Turn off localization of executable's output.
 23.4227 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4228 - 
 23.4229 -+#comment out next line to disable multibyte tests
 23.4230 -+my $mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4231 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4232 -+ and $mb_locale = 'C';
 23.4233 -+
 23.4234 -+my $prog = 'expand';
 23.4235 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4236 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4237 -+
 23.4238 - my @Tests =
 23.4239 -   (
 23.4240 -    ['t1', '--tabs=3',     {IN=>"a\tb"}, {OUT=>"a  b"}],
 23.4241 -@@ -31,6 +40,37 @@ my @Tests =
 23.4242 -    ['i2', '--tabs=3 -i', {IN=>" \ta\tb"}, {OUT=>"   a\tb"}],
 23.4243 -   );
 23.4244 - 
 23.4245 -+if ($mb_locale ne 'C')
 23.4246 -+  {
 23.4247 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4248 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4249 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4250 -+    my @new;
 23.4251 -+    foreach my $t (@Tests)
 23.4252 -+      {
 23.4253 -+        my @new_t = @$t;
 23.4254 -+        my $test_name = shift @new_t;
 23.4255 -+
 23.4256 -+        # Depending on whether expand is multi-byte-patched,
 23.4257 -+        # it emits different diagnostics:
 23.4258 -+        #   non-MB: invalid byte or field list
 23.4259 -+        #   MB:     invalid byte, character or field list
 23.4260 -+        # Adjust the expected error output accordingly.
 23.4261 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4262 -+            (@new_t))
 23.4263 -+          {
 23.4264 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4265 -+            push @new_t, $sub;
 23.4266 -+            push @$t, $sub;
 23.4267 -+          }
 23.4268 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4269 -+      }
 23.4270 -+    push @Tests, @new;
 23.4271 -+  }
 23.4272 -+
 23.4273 -+
 23.4274 -+@Tests = triple_test \@Tests;
 23.4275 -+
 23.4276 - my $save_temps = $ENV{DEBUG};
 23.4277 - my $verbose = $ENV{VERBOSE};
 23.4278 - 
 23.4279 -diff -Naurp coreutils-8.25-orig/tests/misc/fold.pl coreutils-8.25/tests/misc/fold.pl
 23.4280 ---- coreutils-8.25-orig/tests/misc/fold.pl	2016-01-16 12:18:13.000000000 -0600
 23.4281 -+++ coreutils-8.25/tests/misc/fold.pl	2016-02-08 19:07:10.314944661 -0600
 23.4282 -@@ -20,9 +20,18 @@ use strict;
 23.4283 - 
 23.4284 - (my $program_name = $0) =~ s|.*/||;
 23.4285 - 
 23.4286 -+my $prog = 'fold';
 23.4287 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4288 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4289 -+
 23.4290 - # Turn off localization of executable's output.
 23.4291 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4292 - 
 23.4293 -+# uncommented to enable multibyte paths
 23.4294 -+my $mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4295 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4296 -+ and $mb_locale = 'C';
 23.4297 -+
 23.4298 - my @Tests =
 23.4299 -   (
 23.4300 -    ['s1', '-w2 -s', {IN=>"a\t"}, {OUT=>"a\n\t"}],
 23.4301 -@@ -31,9 +40,48 @@ my @Tests =
 23.4302 -    ['s4', '-w4 -s', {IN=>"abc ef\n"}, {OUT=>"abc \nef\n"}],
 23.4303 -   );
 23.4304 - 
 23.4305 -+# Add _POSIX2_VERSION=199209 to the environment of each test
 23.4306 -+# that uses an old-style option like +1.
 23.4307 -+if ($mb_locale ne 'C')
 23.4308 -+  {
 23.4309 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4310 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4311 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4312 -+    my @new;
 23.4313 -+    foreach my $t (@Tests)
 23.4314 -+      {
 23.4315 -+        my @new_t = @$t;
 23.4316 -+        my $test_name = shift @new_t;
 23.4317 -+
 23.4318 -+        # Depending on whether fold is multi-byte-patched,
 23.4319 -+        # it emits different diagnostics:
 23.4320 -+        #   non-MB: invalid byte or field list
 23.4321 -+        #   MB:     invalid byte, character or field list
 23.4322 -+        # Adjust the expected error output accordingly.
 23.4323 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4324 -+            (@new_t))
 23.4325 -+          {
 23.4326 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4327 -+            push @new_t, $sub;
 23.4328 -+            push @$t, $sub;
 23.4329 -+          }
 23.4330 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4331 -+      }
 23.4332 -+    push @Tests, @new;
 23.4333 -+  }
 23.4334 -+
 23.4335 -+@Tests = triple_test \@Tests;
 23.4336 -+
 23.4337 -+# Remember that triple_test creates from each test with exactly one "IN"
 23.4338 -+# file two more tests (.p and .r suffix on name) corresponding to reading
 23.4339 -+# input from a file and from a pipe.  The pipe-reading test would fail
 23.4340 -+# due to a race condition about 1 in 20 times.
 23.4341 -+# Remove the IN_PIPE version of the "output-is-input" test above.
 23.4342 -+# The others aren't susceptible because they have three inputs each.
 23.4343 -+@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 23.4344 -+
 23.4345 - my $save_temps = $ENV{DEBUG};
 23.4346 - my $verbose = $ENV{VERBOSE};
 23.4347 - 
 23.4348 --my $prog = 'fold';
 23.4349 - my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
 23.4350 - exit $fail;
 23.4351 -diff -Naurp coreutils-8.25-orig/tests/misc/join.pl coreutils-8.25/tests/misc/join.pl
 23.4352 ---- coreutils-8.25-orig/tests/misc/join.pl	2016-01-16 12:18:13.000000000 -0600
 23.4353 -+++ coreutils-8.25/tests/misc/join.pl	2016-02-08 19:07:10.315944664 -0600
 23.4354 -@@ -25,6 +25,15 @@ my $limits = getlimits ();
 23.4355 - 
 23.4356 - my $prog = 'join';
 23.4357 - 
 23.4358 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4359 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4360 -+
 23.4361 -+my $mb_locale;
 23.4362 -+#Comment out next line to disable multibyte tests
 23.4363 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4364 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4365 -+  and $mb_locale = 'C';
 23.4366 -+
 23.4367 - my $delim = chr 0247;
 23.4368 - sub t_subst ($)
 23.4369 - {
 23.4370 -@@ -329,8 +338,49 @@ foreach my $t (@tv)
 23.4371 -     push @Tests, $new_ent;
 23.4372 -   }
 23.4373 - 
 23.4374 -+# Add _POSIX2_VERSION=199209 to the environment of each test
 23.4375 -+# that uses an old-style option like +1.
 23.4376 -+if ($mb_locale ne 'C')
 23.4377 -+  {
 23.4378 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4379 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4380 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4381 -+    my @new;
 23.4382 -+    foreach my $t (@Tests)
 23.4383 -+      {
 23.4384 -+        my @new_t = @$t;
 23.4385 -+        my $test_name = shift @new_t;
 23.4386 -+
 23.4387 -+        # Depending on whether join is multi-byte-patched,
 23.4388 -+        # it emits different diagnostics:
 23.4389 -+        #   non-MB: invalid byte or field list
 23.4390 -+        #   MB:     invalid byte, character or field list
 23.4391 -+        # Adjust the expected error output accordingly.
 23.4392 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4393 -+            (@new_t))
 23.4394 -+          {
 23.4395 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4396 -+            push @new_t, $sub;
 23.4397 -+            push @$t, $sub;
 23.4398 -+          }
 23.4399 -+        #Adjust the output some error messages including test_name for mb
 23.4400 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR}}
 23.4401 -+             (@new_t))
 23.4402 -+          {
 23.4403 -+            my $sub2 = {ERR_SUBST => "s/$test_name-mb/$test_name/"};
 23.4404 -+            push @new_t, $sub2;
 23.4405 -+            push @$t, $sub2;
 23.4406 -+          }
 23.4407 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4408 -+      }
 23.4409 -+    push @Tests, @new;
 23.4410 -+  }
 23.4411 -+
 23.4412 - @Tests = triple_test \@Tests;
 23.4413 - 
 23.4414 -+#skip invalid-j-mb test, it is failing because of the format
 23.4415 -+@Tests = grep {$_->[0] ne 'invalid-j-mb'} @Tests;
 23.4416 -+
 23.4417 - my $save_temps = $ENV{DEBUG};
 23.4418 - my $verbose = $ENV{VERBOSE};
 23.4419 - 
 23.4420 -diff -Naurp coreutils-8.25-orig/tests/misc/sort-mb-tests.sh coreutils-8.25/tests/misc/sort-mb-tests.sh
 23.4421 ---- coreutils-8.25-orig/tests/misc/sort-mb-tests.sh	1969-12-31 18:00:00.000000000 -0600
 23.4422 -+++ coreutils-8.25/tests/misc/sort-mb-tests.sh	2016-02-08 19:07:10.315944664 -0600
 23.4423 -@@ -0,0 +1,45 @@
 23.4424 -+#!/bin/sh
 23.4425 -+# Verify sort's multi-byte support.
 23.4426 -+
 23.4427 -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 23.4428 -+print_ver_ sort
 23.4429 -+
 23.4430 -+export LC_ALL=en_US.UTF-8
 23.4431 -+locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 23.4432 -+  || skip_ "No UTF-8 locale available"
 23.4433 -+
 23.4434 -+
 23.4435 -+cat <<EOF > exp
 23.4436 -+Banana@5
 23.4437 -+Apple@10
 23.4438 -+Citrus@20
 23.4439 -+Cherry@30
 23.4440 -+EOF
 23.4441 -+
 23.4442 -+cat <<EOF | sort -t @ -k2 -n > out || fail=1
 23.4443 -+Apple@10
 23.4444 -+Banana@5
 23.4445 -+Citrus@20
 23.4446 -+Cherry@30
 23.4447 -+EOF
 23.4448 -+
 23.4449 -+compare exp out || { fail=1; cat out; }
 23.4450 -+
 23.4451 -+
 23.4452 -+cat <<EOF > exp
 23.4453 -+Citrus@AA20@@5
 23.4454 -+Cherry@AA30@@10
 23.4455 -+Apple@AA10@@20
 23.4456 -+Banana@AA5@@30
 23.4457 -+EOF
 23.4458 -+
 23.4459 -+cat <<EOF | sort -t @ -k4 -n > out || fail=1
 23.4460 -+Apple@AA10@@20
 23.4461 -+Banana@AA5@@30
 23.4462 -+Citrus@AA20@@5
 23.4463 -+Cherry@AA30@@10
 23.4464 -+EOF
 23.4465 -+
 23.4466 -+compare exp out || { fail=1; cat out; }
 23.4467 -+
 23.4468 -+Exit $fail
 23.4469 -diff -Naurp coreutils-8.25-orig/tests/misc/sort-merge.pl coreutils-8.25/tests/misc/sort-merge.pl
 23.4470 ---- coreutils-8.25-orig/tests/misc/sort-merge.pl	2016-01-16 12:18:14.000000000 -0600
 23.4471 -+++ coreutils-8.25/tests/misc/sort-merge.pl	2016-02-08 19:07:10.316944667 -0600
 23.4472 -@@ -26,6 +26,15 @@ my $prog = 'sort';
 23.4473 - # Turn off localization of executable's output.
 23.4474 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4475 - 
 23.4476 -+my $mb_locale;
 23.4477 -+# uncommented according to upstream commit enabling multibyte paths
 23.4478 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4479 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4480 -+ and $mb_locale = 'C';
 23.4481 -+
 23.4482 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4483 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4484 -+
 23.4485 - # three empty files and one that says 'foo'
 23.4486 - my @inputs = (+(map{{IN=> {"empty$_"=> ''}}}1..3), {IN=> {foo=> "foo\n"}});
 23.4487 - 
 23.4488 -@@ -77,6 +86,39 @@ my @Tests =
 23.4489 -         {OUT=>$big_input}],
 23.4490 -     );
 23.4491 - 
 23.4492 -+# Add _POSIX2_VERSION=199209 to the environment of each test
 23.4493 -+# that uses an old-style option like +1.
 23.4494 -+if ($mb_locale ne 'C')
 23.4495 -+  {
 23.4496 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4497 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4498 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4499 -+    my @new;
 23.4500 -+    foreach my $t (@Tests)
 23.4501 -+      {
 23.4502 -+        my @new_t = @$t;
 23.4503 -+        my $test_name = shift @new_t;
 23.4504 -+
 23.4505 -+        # Depending on whether sort is multi-byte-patched,
 23.4506 -+        # it emits different diagnostics:
 23.4507 -+        #   non-MB: invalid byte or field list
 23.4508 -+        #   MB:     invalid byte, character or field list
 23.4509 -+        # Adjust the expected error output accordingly.
 23.4510 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4511 -+            (@new_t))
 23.4512 -+          {
 23.4513 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4514 -+            push @new_t, $sub;
 23.4515 -+            push @$t, $sub;
 23.4516 -+          }
 23.4517 -+        next if ($test_name =~ "nmerge-.");
 23.4518 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4519 -+      }
 23.4520 -+    push @Tests, @new;
 23.4521 -+  }
 23.4522 -+
 23.4523 -+@Tests = triple_test \@Tests;
 23.4524 -+
 23.4525 - my $save_temps = $ENV{DEBUG};
 23.4526 - my $verbose = $ENV{VERBOSE};
 23.4527 - 
 23.4528 -diff -Naurp coreutils-8.25-orig/tests/misc/sort.pl coreutils-8.25/tests/misc/sort.pl
 23.4529 ---- coreutils-8.25-orig/tests/misc/sort.pl	2016-01-16 12:18:14.000000000 -0600
 23.4530 -+++ coreutils-8.25/tests/misc/sort.pl	2016-02-08 19:07:10.316944667 -0600
 23.4531 -@@ -24,10 +24,15 @@ my $prog = 'sort';
 23.4532 - # Turn off localization of executable's output.
 23.4533 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4534 - 
 23.4535 --my $mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4536 -+my $mb_locale;
 23.4537 -+#Comment out next line to disable multibyte tests
 23.4538 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4539 - ! defined $mb_locale || $mb_locale eq 'none'
 23.4540 -   and $mb_locale = 'C';
 23.4541 - 
 23.4542 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4543 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4544 -+
 23.4545 - # Since each test is run with a file name and with redirected stdin,
 23.4546 - # the name in the diagnostic is either the file name or "-".
 23.4547 - # Normalize each diagnostic to use '-'.
 23.4548 -@@ -424,6 +429,38 @@ foreach my $t (@Tests)
 23.4549 -       }
 23.4550 -   }
 23.4551 - 
 23.4552 -+if ($mb_locale ne 'C')
 23.4553 -+   {
 23.4554 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4555 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4556 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4557 -+    my @new;
 23.4558 -+    foreach my $t (@Tests)
 23.4559 -+       {
 23.4560 -+        my @new_t = @$t;
 23.4561 -+        my $test_name = shift @new_t;
 23.4562 -+
 23.4563 -+        # Depending on whether sort is multi-byte-patched,
 23.4564 -+        # it emits different diagnostics:
 23.4565 -+        #   non-MB: invalid byte or field list
 23.4566 -+        #   MB:     invalid byte, character or field list
 23.4567 -+        # Adjust the expected error output accordingly.
 23.4568 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4569 -+            (@new_t))
 23.4570 -+          {
 23.4571 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4572 -+            push @new_t, $sub;
 23.4573 -+            push @$t, $sub;
 23.4574 -+          }
 23.4575 -+        #disable several failing tests until investigation, disable all tests with envvars set
 23.4576 -+        next if (grep {ref $_ eq 'HASH' && exists $_->{ENV}} (@new_t));
 23.4577 -+        next if ($test_name =~ "18g" or $test_name =~ "sort-numeric" or $test_name =~ "08[ab]" or $test_name =~ "03[def]" or $test_name =~ "h4" or $test_name =~ "n1" or $test_name =~ "2[01]a");
 23.4578 -+        next if ($test_name =~ "11[ab]"); # avoid FP: expected result differs to MB result due to collation rules.
 23.4579 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4580 -+       }
 23.4581 -+    push @Tests, @new;
 23.4582 -+   }
 23.4583 -+
 23.4584 - @Tests = triple_test \@Tests;
 23.4585 - 
 23.4586 - # Remember that triple_test creates from each test with exactly one "IN"
 23.4587 -@@ -433,6 +470,7 @@ foreach my $t (@Tests)
 23.4588 - # Remove the IN_PIPE version of the "output-is-input" test above.
 23.4589 - # The others aren't susceptible because they have three inputs each.
 23.4590 - @Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 23.4591 -+@Tests = grep {$_->[0] ne 'output-is-input-mb.p'} @Tests;
 23.4592 - 
 23.4593 - my $save_temps = $ENV{DEBUG};
 23.4594 - my $verbose = $ENV{VERBOSE};
 23.4595 -diff -Naurp coreutils-8.25-orig/tests/misc/unexpand.pl coreutils-8.25/tests/misc/unexpand.pl
 23.4596 ---- coreutils-8.25-orig/tests/misc/unexpand.pl	2016-01-16 12:18:14.000000000 -0600
 23.4597 -+++ coreutils-8.25/tests/misc/unexpand.pl	2016-02-08 19:07:10.317944671 -0600
 23.4598 -@@ -27,6 +27,14 @@ my $limits = getlimits ();
 23.4599 - 
 23.4600 - my $prog = 'unexpand';
 23.4601 - 
 23.4602 -+# comment out next line to disable multibyte tests
 23.4603 -+my $mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4604 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4605 -+ and $mb_locale = 'C';
 23.4606 -+
 23.4607 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4608 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4609 -+
 23.4610 - my @Tests =
 23.4611 -     (
 23.4612 -      ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}],
 23.4613 -@@ -92,6 +100,37 @@ my @Tests =
 23.4614 -       {EXIT => 1}, {ERR => "$prog: tab stop value is too large\n"}],
 23.4615 -     );
 23.4616 - 
 23.4617 -+if ($mb_locale ne 'C')
 23.4618 -+  {
 23.4619 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4620 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4621 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4622 -+    my @new;
 23.4623 -+    foreach my $t (@Tests)
 23.4624 -+      {
 23.4625 -+        my @new_t = @$t;
 23.4626 -+        my $test_name = shift @new_t;
 23.4627 -+
 23.4628 -+        # Depending on whether unexpand is multi-byte-patched,
 23.4629 -+        # it emits different diagnostics:
 23.4630 -+        #   non-MB: invalid byte or field list
 23.4631 -+        #   MB:     invalid byte, character or field list
 23.4632 -+        # Adjust the expected error output accordingly.
 23.4633 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4634 -+            (@new_t))
 23.4635 -+          {
 23.4636 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4637 -+            push @new_t, $sub;
 23.4638 -+            push @$t, $sub;
 23.4639 -+          }
 23.4640 -+        next if ($test_name =~ 'b-1');
 23.4641 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4642 -+      }
 23.4643 -+    push @Tests, @new;
 23.4644 -+  }
 23.4645 -+
 23.4646 -+@Tests = triple_test \@Tests;
 23.4647 -+
 23.4648 - my $save_temps = $ENV{DEBUG};
 23.4649 - my $verbose = $ENV{VERBOSE};
 23.4650 - 
 23.4651 -diff -Naurp coreutils-8.25-orig/tests/misc/uniq.pl coreutils-8.25/tests/misc/uniq.pl
 23.4652 ---- coreutils-8.25-orig/tests/misc/uniq.pl	2016-01-16 12:18:14.000000000 -0600
 23.4653 -+++ coreutils-8.25/tests/misc/uniq.pl	2016-02-08 19:07:10.317944671 -0600
 23.4654 -@@ -23,9 +23,17 @@ my $limits = getlimits ();
 23.4655 - my $prog = 'uniq';
 23.4656 - my $try = "Try '$prog --help' for more information.\n";
 23.4657 - 
 23.4658 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4659 -+
 23.4660 - # Turn off localization of executable's output.
 23.4661 - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 23.4662 - 
 23.4663 -+my $mb_locale;
 23.4664 -+#Comment out next line to disable multibyte tests
 23.4665 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4666 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4667 -+  and $mb_locale = 'C';
 23.4668 -+
 23.4669 - # When possible, create a "-z"-testing variant of each test.
 23.4670 - sub add_z_variants($)
 23.4671 - {
 23.4672 -@@ -262,6 +270,53 @@ foreach my $t (@Tests)
 23.4673 -       and push @$t, {ENV=>'_POSIX2_VERSION=199209'};
 23.4674 -   }
 23.4675 - 
 23.4676 -+if ($mb_locale ne 'C')
 23.4677 -+  {
 23.4678 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4679 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4680 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4681 -+    my @new;
 23.4682 -+    foreach my $t (@Tests)
 23.4683 -+      {
 23.4684 -+        my @new_t = @$t;
 23.4685 -+        my $test_name = shift @new_t;
 23.4686 -+
 23.4687 -+        # Depending on whether uniq is multi-byte-patched,
 23.4688 -+        # it emits different diagnostics:
 23.4689 -+        #   non-MB: invalid byte or field list
 23.4690 -+        #   MB:     invalid byte, character or field list
 23.4691 -+        # Adjust the expected error output accordingly.
 23.4692 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4693 -+            (@new_t))
 23.4694 -+          {
 23.4695 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4696 -+            push @new_t, $sub;
 23.4697 -+            push @$t, $sub;
 23.4698 -+          }
 23.4699 -+        # In test #145, replace the each ‘...’ by '...'.
 23.4700 -+        if ($test_name =~ "145")
 23.4701 -+          {
 23.4702 -+            my $sub = { ERR_SUBST => "s/‘([^’]+)’/'\$1'/g"};
 23.4703 -+            push @new_t, $sub;
 23.4704 -+            push @$t, $sub;
 23.4705 -+          }
 23.4706 -+        next if (   $test_name =~ "schar"
 23.4707 -+                 or $test_name =~ "^obs-plus"
 23.4708 -+                 or $test_name =~ "119");
 23.4709 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4710 -+      }
 23.4711 -+    push @Tests, @new;
 23.4712 -+   }
 23.4713 -+
 23.4714 -+# Remember that triple_test creates from each test with exactly one "IN"
 23.4715 -+# file two more tests (.p and .r suffix on name) corresponding to reading
 23.4716 -+# input from a file and from a pipe.  The pipe-reading test would fail
 23.4717 -+# due to a race condition about 1 in 20 times.
 23.4718 -+# Remove the IN_PIPE version of the "output-is-input" test above.
 23.4719 -+# The others aren't susceptible because they have three inputs each.
 23.4720 -+
 23.4721 -+@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 23.4722 -+
 23.4723 - @Tests = add_z_variants \@Tests;
 23.4724 - @Tests = triple_test \@Tests;
 23.4725 - 
 23.4726 -diff -Naurp coreutils-8.25-orig/tests/pr/pr-tests.pl coreutils-8.25/tests/pr/pr-tests.pl
 23.4727 ---- coreutils-8.25-orig/tests/pr/pr-tests.pl	2016-01-16 12:18:14.000000000 -0600
 23.4728 -+++ coreutils-8.25/tests/pr/pr-tests.pl	2016-02-08 19:07:10.318944674 -0600
 23.4729 -@@ -24,6 +24,15 @@ use strict;
 23.4730 - my $prog = 'pr';
 23.4731 - my $normalize_strerror = "s/': .*/'/";
 23.4732 - 
 23.4733 -+my $mb_locale;
 23.4734 -+#Uncomment the following line to enable multibyte tests
 23.4735 -+$mb_locale = $ENV{LOCALE_FR_UTF8};
 23.4736 -+! defined $mb_locale || $mb_locale eq 'none'
 23.4737 -+  and $mb_locale = 'C';
 23.4738 -+
 23.4739 -+my $try = "Try \`$prog --help' for more information.\n";
 23.4740 -+my $inval = "$prog: invalid byte, character or field list\n$try";
 23.4741 -+
 23.4742 - my @tv = (
 23.4743 - 
 23.4744 - # -b option is no longer an official option. But it's still working to
 23.4745 -@@ -467,8 +476,48 @@ push @Tests,
 23.4746 -     {IN=>{3=>"x\ty\tz\n"}},
 23.4747 -      {OUT=>join("\t", qw(a b c m n o x y z)) . "\n"} ];
 23.4748 - 
 23.4749 -+# Add _POSIX2_VERSION=199209 to the environment of each test
 23.4750 -+# that uses an old-style option like +1.
 23.4751 -+if ($mb_locale ne 'C')
 23.4752 -+  {
 23.4753 -+    # Duplicate each test vector, appending "-mb" to the test name and
 23.4754 -+    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 23.4755 -+    # provide coverage for the distro-added multi-byte code paths.
 23.4756 -+    my @new;
 23.4757 -+    foreach my $t (@Tests)
 23.4758 -+      {
 23.4759 -+        my @new_t = @$t;
 23.4760 -+        my $test_name = shift @new_t;
 23.4761 -+
 23.4762 -+        # Depending on whether pr is multi-byte-patched,
 23.4763 -+        # it emits different diagnostics:
 23.4764 -+        #   non-MB: invalid byte or field list
 23.4765 -+        #   MB:     invalid byte, character or field list
 23.4766 -+        # Adjust the expected error output accordingly.
 23.4767 -+        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 23.4768 -+            (@new_t))
 23.4769 -+          {
 23.4770 -+            my $sub = {ERR_SUBST => 's/, character//'};
 23.4771 -+            push @new_t, $sub;
 23.4772 -+            push @$t, $sub;
 23.4773 -+          }
 23.4774 -+        #temporarily skip some failing tests
 23.4775 -+        next if ($test_name =~ "col-0" or $test_name =~ "col-inval");
 23.4776 -+        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 23.4777 -+      }
 23.4778 -+    push @Tests, @new;
 23.4779 -+  }
 23.4780 -+
 23.4781 - @Tests = triple_test \@Tests;
 23.4782 - 
 23.4783 -+# Remember that triple_test creates from each test with exactly one "IN"
 23.4784 -+# file two more tests (.p and .r suffix on name) corresponding to reading
 23.4785 -+# input from a file and from a pipe.  The pipe-reading test would fail
 23.4786 -+# due to a race condition about 1 in 20 times.
 23.4787 -+# Remove the IN_PIPE version of the "output-is-input" test above.
 23.4788 -+# The others aren't susceptible because they have three inputs each.
 23.4789 -+@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 23.4790 -+
 23.4791 - my $save_temps = $ENV{DEBUG};
 23.4792 - my $verbose = $ENV{VERBOSE};
 23.4793 - 
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/coreutils/stuff/patches/coreutils-8.27-i18n-1.patch	Wed Feb 21 19:48:17 2018 +0200
    24.3 @@ -0,0 +1,5521 @@
    24.4 +Submitted by:            DJ Lucas (dj_AT_linuxfromscratch_DOT_org)
    24.5 +Date:                    2017-03-12
    24.6 +Initial Package Version: 8.27
    24.7 +Upstream Status:         Rejected
    24.8 +Origin:                  Based on Fedora's i18n patches at
    24.9 +                         http://pkgs.fedoraproject.org/cgit/rpms/coreutils.git/tree/
   24.10 +Description:             Fixes i18n issues with various Coreutils programs
   24.11 +
   24.12 +diff -Naurp coreutils-8.27-orig/bootstrap.conf coreutils-8.27/bootstrap.conf
   24.13 +--- coreutils-8.27-orig/bootstrap.conf	2017-03-07 23:34:06.000000000 -0600
   24.14 ++++ coreutils-8.27/bootstrap.conf	2017-03-11 23:47:38.068058445 -0600
   24.15 +@@ -152,6 +152,7 @@ gnulib_modules="
   24.16 +   maintainer-makefile
   24.17 +   malloc-gnu
   24.18 +   manywarnings
   24.19 ++  mbfile
   24.20 +   mbrlen
   24.21 +   mbrtowc
   24.22 +   mbsalign
   24.23 +diff -Naurp coreutils-8.27-orig/configure.ac coreutils-8.27/configure.ac
   24.24 +--- coreutils-8.27-orig/configure.ac	2017-02-26 08:52:29.000000000 -0600
   24.25 ++++ coreutils-8.27/configure.ac	2017-03-11 23:47:38.068058445 -0600
   24.26 +@@ -429,6 +429,8 @@ fi
   24.27 + # I'm leaving it here for now.  This whole thing needs to be modernized...
   24.28 + gl_WINSIZE_IN_PTEM
   24.29 + 
   24.30 ++gl_MBFILE
   24.31 ++
   24.32 + gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H
   24.33 + 
   24.34 + if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \
   24.35 +diff -Naurp coreutils-8.27-orig/lib/linebuffer.h coreutils-8.27/lib/linebuffer.h
   24.36 +--- coreutils-8.27-orig/lib/linebuffer.h	2017-01-01 16:35:38.000000000 -0600
   24.37 ++++ coreutils-8.27/lib/linebuffer.h	2017-03-11 23:47:13.089286391 -0600
   24.38 +@@ -21,6 +21,11 @@
   24.39 + 
   24.40 + # include <stdio.h>
   24.41 + 
   24.42 ++/* Get mbstate_t.  */
   24.43 ++# if HAVE_WCHAR_H
   24.44 ++#  include <wchar.h>
   24.45 ++# endif
   24.46 ++
   24.47 + /* A 'struct linebuffer' holds a line of text. */
   24.48 + 
   24.49 + struct linebuffer
   24.50 +@@ -28,6 +33,9 @@ struct linebuffer
   24.51 +   size_t size;                  /* Allocated. */
   24.52 +   size_t length;                /* Used. */
   24.53 +   char *buffer;
   24.54 ++# if HAVE_WCHAR_H
   24.55 ++  mbstate_t state;
   24.56 ++# endif
   24.57 + };
   24.58 + 
   24.59 + /* Initialize linebuffer LINEBUFFER for use. */
   24.60 +diff -Naurp coreutils-8.27-orig/lib/mbfile.c coreutils-8.27/lib/mbfile.c
   24.61 +--- coreutils-8.27-orig/lib/mbfile.c	1969-12-31 18:00:00.000000000 -0600
   24.62 ++++ coreutils-8.27/lib/mbfile.c	2017-03-11 23:47:38.069058397 -0600
   24.63 +@@ -0,0 +1,3 @@
   24.64 ++#include <config.h>
   24.65 ++#define MBFILE_INLINE _GL_EXTERN_INLINE
   24.66 ++#include "mbfile.h"
   24.67 +diff -Naurp coreutils-8.27-orig/lib/mbfile.h coreutils-8.27/lib/mbfile.h
   24.68 +--- coreutils-8.27-orig/lib/mbfile.h	1969-12-31 18:00:00.000000000 -0600
   24.69 ++++ coreutils-8.27/lib/mbfile.h	2017-03-11 23:47:38.069058397 -0600
   24.70 +@@ -0,0 +1,255 @@
   24.71 ++/* Multibyte character I/O: macros for multi-byte encodings.
   24.72 ++   Copyright (C) 2001, 2005, 2009-2017 Free Software Foundation, Inc.
   24.73 ++
   24.74 ++   This program is free software: you can redistribute it and/or modify
   24.75 ++   it under the terms of the GNU General Public License as published by
   24.76 ++   the Free Software Foundation; either version 3 of the License, or
   24.77 ++   (at your option) any later version.
   24.78 ++
   24.79 ++   This program is distributed in the hope that it will be useful,
   24.80 ++   but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.81 ++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.82 ++   GNU General Public License for more details.
   24.83 ++
   24.84 ++   You should have received a copy of the GNU General Public License
   24.85 ++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   24.86 ++
   24.87 ++/* Written by Mitsuru Chinen <mchinen@yamato.ibm.com>
   24.88 ++   and Bruno Haible <bruno@clisp.org>.  */
   24.89 ++
   24.90 ++/* The macros in this file implement multi-byte character input from a
   24.91 ++   stream.
   24.92 ++
   24.93 ++   mb_file_t
   24.94 ++     is the type for multibyte character input stream, usable for variable
   24.95 ++     declarations.
   24.96 ++
   24.97 ++   mbf_char_t
   24.98 ++     is the type for multibyte character or EOF, usable for variable
   24.99 ++     declarations.
  24.100 ++
  24.101 ++   mbf_init (mbf, stream)
  24.102 ++     initializes the MB_FILE for reading from stream.
  24.103 ++
  24.104 ++   mbf_getc (mbc, mbf)
  24.105 ++     reads the next multibyte character from mbf and stores it in mbc.
  24.106 ++
  24.107 ++   mb_iseof (mbc)
  24.108 ++     returns true if mbc represents the EOF value.
  24.109 ++
  24.110 ++   Here are the function prototypes of the macros.
  24.111 ++
  24.112 ++   extern void          mbf_init (mb_file_t mbf, FILE *stream);
  24.113 ++   extern void          mbf_getc (mbf_char_t mbc, mb_file_t mbf);
  24.114 ++   extern bool          mb_iseof (const mbf_char_t mbc);
  24.115 ++ */
  24.116 ++
  24.117 ++#ifndef _MBFILE_H
  24.118 ++#define _MBFILE_H 1
  24.119 ++
  24.120 ++#include <assert.h>
  24.121 ++#include <stdbool.h>
  24.122 ++#include <stdio.h>
  24.123 ++#include <string.h>
  24.124 ++
  24.125 ++/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
  24.126 ++   <wchar.h>.
  24.127 ++   BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
  24.128 ++   <wchar.h>.  */
  24.129 ++#include <stdio.h>
  24.130 ++#include <time.h>
  24.131 ++#include <wchar.h>
  24.132 ++
  24.133 ++#include "mbchar.h"
  24.134 ++
  24.135 ++#ifndef _GL_INLINE_HEADER_BEGIN
  24.136 ++ #error "Please include config.h first."
  24.137 ++#endif
  24.138 ++_GL_INLINE_HEADER_BEGIN
  24.139 ++#ifndef MBFILE_INLINE
  24.140 ++# define MBFILE_INLINE _GL_INLINE
  24.141 ++#endif
  24.142 ++
  24.143 ++struct mbfile_multi {
  24.144 ++  FILE *fp;
  24.145 ++  bool eof_seen;
  24.146 ++  bool have_pushback;
  24.147 ++  mbstate_t state;
  24.148 ++  unsigned int bufcount;
  24.149 ++  char buf[MBCHAR_BUF_SIZE];
  24.150 ++  struct mbchar pushback;
  24.151 ++};
  24.152 ++
  24.153 ++MBFILE_INLINE void
  24.154 ++mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf)
  24.155 ++{
  24.156 ++  size_t bytes;
  24.157 ++
  24.158 ++  /* If EOF has already been seen, don't use getc.  This matters if
  24.159 ++     mbf->fp is connected to an interactive tty.  */
  24.160 ++  if (mbf->eof_seen)
  24.161 ++    goto eof;
  24.162 ++
  24.163 ++  /* Return character pushed back, if there is one.  */
  24.164 ++  if (mbf->have_pushback)
  24.165 ++    {
  24.166 ++      mb_copy (mbc, &mbf->pushback);
  24.167 ++      mbf->have_pushback = false;
  24.168 ++      return;
  24.169 ++    }
  24.170 ++
  24.171 ++  /* Before using mbrtowc, we need at least one byte.  */
  24.172 ++  if (mbf->bufcount == 0)
  24.173 ++    {
  24.174 ++      int c = getc (mbf->fp);
  24.175 ++      if (c == EOF)
  24.176 ++        {
  24.177 ++          mbf->eof_seen = true;
  24.178 ++          goto eof;
  24.179 ++        }
  24.180 ++      mbf->buf[0] = (unsigned char) c;
  24.181 ++      mbf->bufcount++;
  24.182 ++    }
  24.183 ++
  24.184 ++  /* Handle most ASCII characters quickly, without calling mbrtowc().  */
  24.185 ++  if (mbf->bufcount == 1 && mbsinit (&mbf->state) && is_basic (mbf->buf[0]))
  24.186 ++    {
  24.187 ++      /* These characters are part of the basic character set.  ISO C 99
  24.188 ++         guarantees that their wide character code is identical to their
  24.189 ++         char code.  */
  24.190 ++      mbc->wc = mbc->buf[0] = mbf->buf[0];
  24.191 ++      mbc->wc_valid = true;
  24.192 ++      mbc->ptr = &mbc->buf[0];
  24.193 ++      mbc->bytes = 1;
  24.194 ++      mbf->bufcount = 0;
  24.195 ++      return;
  24.196 ++    }
  24.197 ++
  24.198 ++  /* Use mbrtowc on an increasing number of bytes.  Read only as many bytes
  24.199 ++     from mbf->fp as needed.  This is needed to give reasonable interactive
  24.200 ++     behaviour when mbf->fp is connected to an interactive tty.  */
  24.201 ++  for (;;)
  24.202 ++    {
  24.203 ++      /* We don't know whether the 'mbrtowc' function updates the state when
  24.204 ++         it returns -2, - this is the ISO C 99 and glibc-2.2 behaviour - or
  24.205 ++         not - amended ANSI C, glibc-2.1 and Solaris 2.7 behaviour.  We
  24.206 ++         don't have an autoconf test for this, yet.
  24.207 ++         The new behaviour would allow us to feed the bytes one by one into
  24.208 ++         mbrtowc.  But the old behaviour forces us to feed all bytes since
  24.209 ++         the end of the last character into mbrtowc.  Since we want to retry
  24.210 ++         with more bytes when mbrtowc returns -2, we must backup the state
  24.211 ++         before calling mbrtowc, because implementations with the new
  24.212 ++         behaviour will clobber it.  */
  24.213 ++      mbstate_t backup_state = mbf->state;
  24.214 ++
  24.215 ++      bytes = mbrtowc (&mbc->wc, &mbf->buf[0], mbf->bufcount, &mbf->state);
  24.216 ++
  24.217 ++      if (bytes == (size_t) -1)
  24.218 ++        {
  24.219 ++          /* An invalid multibyte sequence was encountered.  */
  24.220 ++          /* Return a single byte.  */
  24.221 ++          bytes = 1;
  24.222 ++          mbc->wc_valid = false;
  24.223 ++          break;
  24.224 ++        }
  24.225 ++      else if (bytes == (size_t) -2)
  24.226 ++        {
  24.227 ++          /* An incomplete multibyte character.  */
  24.228 ++          mbf->state = backup_state;
  24.229 ++          if (mbf->bufcount == MBCHAR_BUF_SIZE)
  24.230 ++            {
  24.231 ++              /* An overlong incomplete multibyte sequence was encountered.  */
  24.232 ++              /* Return a single byte.  */
  24.233 ++              bytes = 1;
  24.234 ++              mbc->wc_valid = false;
  24.235 ++              break;
  24.236 ++            }
  24.237 ++          else
  24.238 ++            {
  24.239 ++              /* Read one more byte and retry mbrtowc.  */
  24.240 ++              int c = getc (mbf->fp);
  24.241 ++              if (c == EOF)
  24.242 ++                {
  24.243 ++                  /* An incomplete multibyte character at the end.  */
  24.244 ++                  mbf->eof_seen = true;
  24.245 ++                  bytes = mbf->bufcount;
  24.246 ++                  mbc->wc_valid = false;
  24.247 ++                  break;
  24.248 ++                }
  24.249 ++              mbf->buf[mbf->bufcount] = (unsigned char) c;
  24.250 ++              mbf->bufcount++;
  24.251 ++            }
  24.252 ++        }
  24.253 ++      else
  24.254 ++        {
  24.255 ++          if (bytes == 0)
  24.256 ++            {
  24.257 ++              /* A null wide character was encountered.  */
  24.258 ++              bytes = 1;
  24.259 ++              assert (mbf->buf[0] == '\0');
  24.260 ++              assert (mbc->wc == 0);
  24.261 ++            }
  24.262 ++          mbc->wc_valid = true;
  24.263 ++          break;
  24.264 ++        }
  24.265 ++    }
  24.266 ++
  24.267 ++  /* Return the multibyte sequence mbf->buf[0..bytes-1].  */
  24.268 ++  mbc->ptr = &mbc->buf[0];
  24.269 ++  memcpy (&mbc->buf[0], &mbf->buf[0], bytes);
  24.270 ++  mbc->bytes = bytes;
  24.271 ++
  24.272 ++  mbf->bufcount -= bytes;
  24.273 ++  if (mbf->bufcount > 0)
  24.274 ++    {
  24.275 ++      /* It's not worth calling memmove() for so few bytes.  */
  24.276 ++      unsigned int count = mbf->bufcount;
  24.277 ++      char *p = &mbf->buf[0];
  24.278 ++
  24.279 ++      do
  24.280 ++        {
  24.281 ++          *p = *(p + bytes);
  24.282 ++          p++;
  24.283 ++        }
  24.284 ++      while (--count > 0);
  24.285 ++    }
  24.286 ++  return;
  24.287 ++
  24.288 ++eof:
  24.289 ++  /* An mbchar_t with bytes == 0 is used to indicate EOF.  */
  24.290 ++  mbc->ptr = NULL;
  24.291 ++  mbc->bytes = 0;
  24.292 ++  mbc->wc_valid = false;
  24.293 ++  return;
  24.294 ++}
  24.295 ++
  24.296 ++MBFILE_INLINE void
  24.297 ++mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf)
  24.298 ++{
  24.299 ++  mb_copy (&mbf->pushback, mbc);
  24.300 ++  mbf->have_pushback = true;
  24.301 ++}
  24.302 ++
  24.303 ++typedef struct mbfile_multi mb_file_t;
  24.304 ++
  24.305 ++typedef mbchar_t mbf_char_t;
  24.306 ++
  24.307 ++#define mbf_init(mbf, stream)                                           \
  24.308 ++  ((mbf).fp = (stream),                                                 \
  24.309 ++   (mbf).eof_seen = false,                                              \
  24.310 ++   (mbf).have_pushback = false,                                         \
  24.311 ++   memset (&(mbf).state, '\0', sizeof (mbstate_t)),                     \
  24.312 ++   (mbf).bufcount = 0)
  24.313 ++
  24.314 ++#define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf))
  24.315 ++
  24.316 ++#define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf))
  24.317 ++
  24.318 ++#define mb_iseof(mbc) ((mbc).bytes == 0)
  24.319 ++
  24.320 ++#ifndef _GL_INLINE_HEADER_BEGIN
  24.321 ++ #error "Please include config.h first."
  24.322 ++#endif
  24.323 ++_GL_INLINE_HEADER_BEGIN
  24.324 ++
  24.325 ++#endif /* _MBFILE_H */
  24.326 +diff -Naurp coreutils-8.27-orig/m4/mbfile.m4 coreutils-8.27/m4/mbfile.m4
  24.327 +--- coreutils-8.27-orig/m4/mbfile.m4	1969-12-31 18:00:00.000000000 -0600
  24.328 ++++ coreutils-8.27/m4/mbfile.m4	2017-03-11 23:47:38.070058349 -0600
  24.329 +@@ -0,0 +1,14 @@
  24.330 ++# mbfile.m4 serial 7
  24.331 ++dnl Copyright (C) 2005, 2008-2017 Free Software Foundation, Inc.
  24.332 ++dnl This file is free software; the Free Software Foundation
  24.333 ++dnl gives unlimited permission to copy and/or distribute it,
  24.334 ++dnl with or without modifications, as long as this notice is preserved.
  24.335 ++
  24.336 ++dnl autoconf tests required for use of mbfile.h
  24.337 ++dnl From Bruno Haible.
  24.338 ++
  24.339 ++AC_DEFUN([gl_MBFILE],
  24.340 ++[
  24.341 ++  AC_REQUIRE([AC_TYPE_MBSTATE_T])
  24.342 ++  :
  24.343 ++])
  24.344 +diff -Naurp coreutils-8.27-orig/src/cut.c coreutils-8.27/src/cut.c
  24.345 +--- coreutils-8.27-orig/src/cut.c	2017-01-01 16:34:24.000000000 -0600
  24.346 ++++ coreutils-8.27/src/cut.c	2017-03-11 23:47:59.526048471 -0600
  24.347 +@@ -28,6 +28,11 @@
  24.348 + #include <assert.h>
  24.349 + #include <getopt.h>
  24.350 + #include <sys/types.h>
  24.351 ++
  24.352 ++/* Get mbstate_t, mbrtowc().  */
  24.353 ++#if HAVE_WCHAR_H
  24.354 ++# include <wchar.h>
  24.355 ++#endif
  24.356 + #include "system.h"
  24.357 + 
  24.358 + #include "error.h"
  24.359 +@@ -38,6 +43,18 @@
  24.360 + 
  24.361 + #include "set-fields.h"
  24.362 + 
  24.363 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
  24.364 ++   installation; work around this configuration error.        */
  24.365 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
  24.366 ++# undef MB_LEN_MAX
  24.367 ++# define MB_LEN_MAX 16
  24.368 ++#endif
  24.369 ++
  24.370 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
  24.371 ++#if HAVE_MBRTOWC && defined mbstate_t
  24.372 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
  24.373 ++#endif
  24.374 ++
  24.375 + /* The official name of this program (e.g., no 'g' prefix).  */
  24.376 + #define PROGRAM_NAME "cut"
  24.377 + 
  24.378 +@@ -54,6 +71,52 @@
  24.379 +     }									\
  24.380 +   while (0)
  24.381 + 
  24.382 ++/* Refill the buffer BUF to get a multibyte character. */
  24.383 ++#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM)                        \
  24.384 ++  do                                                                        \
  24.385 ++    {                                                                        \
  24.386 ++      if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM))        \
  24.387 ++        {                                                                \
  24.388 ++          memmove (BUF, BUFPOS, BUFLEN);                                \
  24.389 ++          BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \
  24.390 ++          BUFPOS = BUF;                                                        \
  24.391 ++        }                                                                \
  24.392 ++    }                                                                        \
  24.393 ++  while (0)
  24.394 ++
  24.395 ++/* Get wide character on BUFPOS. BUFPOS is not included after that.
  24.396 ++   If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */
  24.397 ++#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \
  24.398 ++  do                                                                        \
  24.399 ++    {                                                                        \
  24.400 ++      mbstate_t state_bak;                                                \
  24.401 ++                                                                        \
  24.402 ++      if (BUFLEN < 1)                                                        \
  24.403 ++        {                                                                \
  24.404 ++          WC = WEOF;                                                        \
  24.405 ++          break;                                                        \
  24.406 ++        }                                                                \
  24.407 ++                                                                        \
  24.408 ++      /* Get a wide character. */                                        \
  24.409 ++      CONVFAIL = false;                                                        \
  24.410 ++      state_bak = STATE;                                                \
  24.411 ++      MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE);        \
  24.412 ++                                                                        \
  24.413 ++      switch (MBLENGTH)                                                        \
  24.414 ++        {                                                                \
  24.415 ++        case (size_t)-1:                                                \
  24.416 ++        case (size_t)-2:                                                \
  24.417 ++          CONVFAIL = true;                                                        \
  24.418 ++          STATE = state_bak;                                                \
  24.419 ++          /* Fall througn. */                                                \
  24.420 ++                                                                        \
  24.421 ++        case 0:                                                                \
  24.422 ++          MBLENGTH = 1;                                                        \
  24.423 ++          break;                                                        \
  24.424 ++        }                                                                \
  24.425 ++    }                                                                        \
  24.426 ++  while (0)
  24.427 ++
  24.428 + 
  24.429 + /* Pointer inside RP.  When checking if a byte or field is selected
  24.430 +    by a finite range, we check if it is between CURRENT_RP.LO
  24.431 +@@ -61,6 +124,9 @@
  24.432 +    CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */
  24.433 + static struct field_range_pair *current_rp;
  24.434 + 
  24.435 ++/* Length of the delimiter given as argument to -d.  */
  24.436 ++size_t delimlen;
  24.437 ++
  24.438 + /* This buffer is used to support the semantics of the -s option
  24.439 +    (or lack of same) when the specified field list includes (does
  24.440 +    not include) the first field.  In both of those cases, the entire
  24.441 +@@ -77,15 +143,25 @@ enum operating_mode
  24.442 +   {
  24.443 +     undefined_mode,
  24.444 + 
  24.445 +-    /* Output characters that are in the given bytes. */
  24.446 ++    /* Output bytes that are at the given positions. */
  24.447 +     byte_mode,
  24.448 + 
  24.449 ++    /* Output characters that are at the given positions. */
  24.450 ++    character_mode,
  24.451 ++
  24.452 +     /* Output the given delimiter-separated fields. */
  24.453 +     field_mode
  24.454 +   };
  24.455 + 
  24.456 + static enum operating_mode operating_mode;
  24.457 + 
  24.458 ++/* If nonzero, when in byte mode, don't split multibyte characters.  */
  24.459 ++static int byte_mode_character_aware;
  24.460 ++
  24.461 ++/* If nonzero, the function for single byte locale is work
  24.462 ++   if this program runs on multibyte locale. */
  24.463 ++static int force_singlebyte_mode;
  24.464 ++
  24.465 + /* If true do not output lines containing no delimiter characters.
  24.466 +    Otherwise, all such lines are printed.  This option is valid only
  24.467 +    with field mode.  */
  24.468 +@@ -97,6 +173,9 @@ static bool complement;
  24.469 + 
  24.470 + /* The delimiter character for field mode. */
  24.471 + static unsigned char delim;
  24.472 ++#if HAVE_WCHAR_H
  24.473 ++static wchar_t wcdelim;
  24.474 ++#endif
  24.475 + 
  24.476 + /* The delimiter for each line/record. */
  24.477 + static unsigned char line_delim = '\n';
  24.478 +@@ -164,7 +243,7 @@ Print selected parts of lines from each
  24.479 +   -f, --fields=LIST       select only these fields;  also print any line\n\
  24.480 +                             that contains no delimiter character, unless\n\
  24.481 +                             the -s option is specified\n\
  24.482 +-  -n                      (ignored)\n\
  24.483 ++  -n                      with -b: don't split multibyte characters\n\
  24.484 + "), stdout);
  24.485 +       fputs (_("\
  24.486 +       --complement        complement the set of selected bytes, characters\n\
  24.487 +@@ -280,6 +359,82 @@ cut_bytes (FILE *stream)
  24.488 +     }
  24.489 + }
  24.490 + 
  24.491 ++#if HAVE_MBRTOWC
  24.492 ++/* This function is in use for the following case.
  24.493 ++
  24.494 ++   1. Read from the stream STREAM, printing to standard output any selected
  24.495 ++   characters.
  24.496 ++
  24.497 ++   2. Read from stream STREAM, printing to standard output any selected bytes,
  24.498 ++   without splitting multibyte characters.  */
  24.499 ++
  24.500 ++static void
  24.501 ++cut_characters_or_cut_bytes_no_split (FILE *stream)
  24.502 ++{
  24.503 ++  size_t idx;                /* number of bytes or characters in the line so far. */
  24.504 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  24.505 ++  char *bufpos;                /* Next read position of BUF. */
  24.506 ++  size_t buflen;        /* The length of the byte sequence in buf. */
  24.507 ++  wint_t wc;                /* A gotten wide character. */
  24.508 ++  size_t mblength;        /* The byte size of a multibyte character which shows
  24.509 ++                           as same character as WC. */
  24.510 ++  mbstate_t state;        /* State of the stream. */
  24.511 ++  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  24.512 ++  /* Whether to begin printing delimiters between ranges for the current line.
  24.513 ++     Set after we've begun printing data corresponding to the first range.  */
  24.514 ++  bool print_delimiter = false;
  24.515 ++
  24.516 ++  idx = 0;
  24.517 ++  buflen = 0;
  24.518 ++  bufpos = buf;
  24.519 ++  memset (&state, '\0', sizeof(mbstate_t));
  24.520 ++
  24.521 ++  current_rp = frp;
  24.522 ++
  24.523 ++  while (1)
  24.524 ++    {
  24.525 ++      REFILL_BUFFER (buf, bufpos, buflen, stream);
  24.526 ++
  24.527 ++      GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail);
  24.528 ++      (void) convfail;  /* ignore unused */
  24.529 ++
  24.530 ++      if (wc == WEOF)
  24.531 ++        {
  24.532 ++          if (idx > 0)
  24.533 ++            putchar (line_delim);
  24.534 ++          break;
  24.535 ++        }
  24.536 ++      else if (wc == line_delim)
  24.537 ++        {
  24.538 ++          putchar (line_delim);
  24.539 ++          idx = 0;
  24.540 ++          print_delimiter = false;
  24.541 ++          current_rp = frp;
  24.542 ++        }
  24.543 ++      else
  24.544 ++        {
  24.545 ++          next_item (&idx);
  24.546 ++          if (print_kth (idx))
  24.547 ++            {
  24.548 ++              if (output_delimiter_specified)
  24.549 ++                {
  24.550 ++                  if (print_delimiter && is_range_start_index (idx))
  24.551 ++                    {
  24.552 ++                      fwrite (output_delimiter_string, sizeof (char),
  24.553 ++                              output_delimiter_length, stdout);
  24.554 ++                    }
  24.555 ++                  print_delimiter = true;
  24.556 ++                }
  24.557 ++              fwrite (bufpos, mblength, sizeof(char), stdout);
  24.558 ++            }
  24.559 ++        }
  24.560 ++
  24.561 ++      buflen -= mblength;
  24.562 ++      bufpos += mblength;
  24.563 ++    }
  24.564 ++}
  24.565 ++#endif
  24.566 ++
  24.567 + /* Read from stream STREAM, printing to standard output any selected fields.  */
  24.568 + 
  24.569 + static void
  24.570 +@@ -425,13 +580,211 @@ cut_fields (FILE *stream)
  24.571 +     }
  24.572 + }
  24.573 + 
  24.574 ++#if HAVE_MBRTOWC
  24.575 ++static void
  24.576 ++cut_fields_mb (FILE *stream)
  24.577 ++{
  24.578 ++  int c;
  24.579 ++  size_t field_idx;
  24.580 ++  int found_any_selected_field;
  24.581 ++  int buffer_first_field;
  24.582 ++  int empty_input;
  24.583 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  24.584 ++  char *bufpos;                /* Next read position of BUF. */
  24.585 ++  size_t buflen;        /* The length of the byte sequence in buf. */
  24.586 ++  wint_t wc = 0;        /* A gotten wide character. */
  24.587 ++  size_t mblength;        /* The byte size of a multibyte character which shows
  24.588 ++                           as same character as WC. */
  24.589 ++  mbstate_t state;        /* State of the stream. */
  24.590 ++  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  24.591 ++
  24.592 ++  current_rp = frp;
  24.593 ++
  24.594 ++  found_any_selected_field = 0;
  24.595 ++  field_idx = 1;
  24.596 ++  bufpos = buf;
  24.597 ++  buflen = 0;
  24.598 ++  memset (&state, '\0', sizeof(mbstate_t));
  24.599 ++
  24.600 ++  c = getc (stream);
  24.601 ++  empty_input = (c == EOF);
  24.602 ++  if (c != EOF)
  24.603 ++  {
  24.604 ++    ungetc (c, stream);
  24.605 ++    wc = 0;
  24.606 ++  }
  24.607 ++  else
  24.608 ++    wc = WEOF;
  24.609 ++
  24.610 ++  /* To support the semantics of the -s flag, we may have to buffer
  24.611 ++     all of the first field to determine whether it is `delimited.'
  24.612 ++     But that is unnecessary if all non-delimited lines must be printed
  24.613 ++     and the first field has been selected, or if non-delimited lines
  24.614 ++     must be suppressed and the first field has *not* been selected.
  24.615 ++     That is because a non-delimited line has exactly one field.  */
  24.616 ++  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
  24.617 ++
  24.618 ++  while (1)
  24.619 ++    {
  24.620 ++      if (field_idx == 1 && buffer_first_field)
  24.621 ++        {
  24.622 ++          int len = 0;
  24.623 ++
  24.624 ++          while (1)
  24.625 ++            {
  24.626 ++              REFILL_BUFFER (buf, bufpos, buflen, stream);
  24.627 ++
  24.628 ++              GET_NEXT_WC_FROM_BUFFER
  24.629 ++                (wc, bufpos, buflen, mblength, state, convfail);
  24.630 ++
  24.631 ++              if (wc == WEOF)
  24.632 ++                break;
  24.633 ++
  24.634 ++              field_1_buffer = xrealloc (field_1_buffer, len + mblength);
  24.635 ++              memcpy (field_1_buffer + len, bufpos, mblength);
  24.636 ++              len += mblength;
  24.637 ++              buflen -= mblength;
  24.638 ++              bufpos += mblength;
  24.639 ++
  24.640 ++              if (!convfail && (wc == line_delim || wc == wcdelim))
  24.641 ++                break;
  24.642 ++            }
  24.643 ++
  24.644 ++          if (len <= 0 && wc == WEOF)
  24.645 ++            break;
  24.646 ++
  24.647 ++          /* If the first field extends to the end of line (it is not
  24.648 ++             delimited) and we are printing all non-delimited lines,
  24.649 ++             print this one.  */
  24.650 ++          if (convfail || (!convfail && wc != wcdelim))
  24.651 ++            {
  24.652 ++              if (suppress_non_delimited)
  24.653 ++                {
  24.654 ++                  /* Empty.        */
  24.655 ++                }
  24.656 ++              else
  24.657 ++                {
  24.658 ++                  fwrite (field_1_buffer, sizeof (char), len, stdout);
  24.659 ++                  /* Make sure the output line is newline terminated.  */
  24.660 ++                  if (convfail || (!convfail && wc != line_delim))
  24.661 ++                    putchar (line_delim);
  24.662 ++                }
  24.663 ++              continue;
  24.664 ++            }
  24.665 ++
  24.666 ++          if (print_kth (1))
  24.667 ++            {
  24.668 ++              /* Print the field, but not the trailing delimiter.  */
  24.669 ++              fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
  24.670 ++              found_any_selected_field = 1;
  24.671 ++            }
  24.672 ++          next_item (&field_idx);
  24.673 ++        }
  24.674 ++
  24.675 ++      if (wc != WEOF)
  24.676 ++        {
  24.677 ++          if (print_kth (field_idx))
  24.678 ++            {
  24.679 ++              if (found_any_selected_field)
  24.680 ++                {
  24.681 ++                  fwrite (output_delimiter_string, sizeof (char),
  24.682 ++                          output_delimiter_length, stdout);
  24.683 ++                }
  24.684 ++              found_any_selected_field = 1;
  24.685 ++            }
  24.686 ++
  24.687 ++          while (1)
  24.688 ++            {
  24.689 ++              REFILL_BUFFER (buf, bufpos, buflen, stream);
  24.690 ++
  24.691 ++              GET_NEXT_WC_FROM_BUFFER
  24.692 ++                (wc, bufpos, buflen, mblength, state, convfail);
  24.693 ++
  24.694 ++              if (wc == WEOF)
  24.695 ++                break;
  24.696 ++              else if (!convfail && (wc == wcdelim || wc == line_delim))
  24.697 ++                {
  24.698 ++                  buflen -= mblength;
  24.699 ++                  bufpos += mblength;
  24.700 ++                  break;
  24.701 ++                }
  24.702 ++
  24.703 ++              if (print_kth (field_idx))
  24.704 ++                fwrite (bufpos, mblength, sizeof(char), stdout);
  24.705 ++
  24.706 ++              buflen -= mblength;
  24.707 ++              bufpos += mblength;
  24.708 ++            }
  24.709 ++        }
  24.710 ++
  24.711 ++      if ((!convfail || wc == line_delim) && buflen < 1)
  24.712 ++        wc = WEOF;
  24.713 ++
  24.714 ++      if (!convfail && wc == wcdelim)
  24.715 ++        next_item (&field_idx);
  24.716 ++      else if (wc == WEOF || (!convfail && wc == line_delim))
  24.717 ++        {
  24.718 ++          if (found_any_selected_field
  24.719 ++              || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
  24.720 ++            putchar (line_delim);
  24.721 ++          if (wc == WEOF)
  24.722 ++            break;
  24.723 ++          field_idx = 1;
  24.724 ++          current_rp = frp;
  24.725 ++          found_any_selected_field = 0;
  24.726 ++        }
  24.727 ++    }
  24.728 ++}
  24.729 ++#endif
  24.730 ++
  24.731 + static void
  24.732 + cut_stream (FILE *stream)
  24.733 + {
  24.734 +-  if (operating_mode == byte_mode)
  24.735 +-    cut_bytes (stream);
  24.736 ++#if HAVE_MBRTOWC
  24.737 ++  if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  24.738 ++    {
  24.739 ++      switch (operating_mode)
  24.740 ++        {
  24.741 ++        case byte_mode:
  24.742 ++          if (byte_mode_character_aware)
  24.743 ++            cut_characters_or_cut_bytes_no_split (stream);
  24.744 ++          else
  24.745 ++            cut_bytes (stream);
  24.746 ++          break;
  24.747 ++
  24.748 ++        case character_mode:
  24.749 ++          cut_characters_or_cut_bytes_no_split (stream);
  24.750 ++          break;
  24.751 ++
  24.752 ++        case field_mode:
  24.753 ++          if (delimlen == 1)
  24.754 ++            {
  24.755 ++              /* Check if we have utf8 multibyte locale, so we can use this
  24.756 ++                 optimization because of uniqueness of characters, which is
  24.757 ++                 not true for e.g. SJIS */
  24.758 ++              char * loc = setlocale(LC_CTYPE, NULL);
  24.759 ++              if (loc && (strstr (loc, "UTF-8") || strstr (loc, "utf-8") ||
  24.760 ++                  strstr (loc, "UTF8") || strstr (loc, "utf8")))
  24.761 ++                {
  24.762 ++                  cut_fields (stream);
  24.763 ++                  break;
  24.764 ++                }
  24.765 ++            }
  24.766 ++          cut_fields_mb (stream);
  24.767 ++          break;
  24.768 ++
  24.769 ++        default:
  24.770 ++          abort ();
  24.771 ++        }
  24.772 ++    }
  24.773 +   else
  24.774 +-    cut_fields (stream);
  24.775 ++#endif
  24.776 ++    {
  24.777 ++      if (operating_mode == field_mode)
  24.778 ++        cut_fields (stream);
  24.779 ++      else
  24.780 ++        cut_bytes (stream);
  24.781 ++    }
  24.782 + }
  24.783 + 
  24.784 + /* Process file FILE to standard output.
  24.785 +@@ -483,6 +836,7 @@ main (int argc, char **argv)
  24.786 +   bool ok;
  24.787 +   bool delim_specified = false;
  24.788 +   char *spec_list_string IF_LINT ( = NULL);
  24.789 ++  char mbdelim[MB_LEN_MAX + 1];
  24.790 + 
  24.791 +   initialize_main (&argc, &argv);
  24.792 +   set_program_name (argv[0]);
  24.793 +@@ -505,7 +859,6 @@ main (int argc, char **argv)
  24.794 +       switch (optc)
  24.795 +         {
  24.796 +         case 'b':
  24.797 +-        case 'c':
  24.798 +           /* Build the byte list. */
  24.799 +           if (operating_mode != undefined_mode)
  24.800 +             FATAL_ERROR (_("only one type of list may be specified"));
  24.801 +@@ -513,6 +866,14 @@ main (int argc, char **argv)
  24.802 +           spec_list_string = optarg;
  24.803 +           break;
  24.804 + 
  24.805 ++        case 'c':
  24.806 ++          /* Build the character list. */
  24.807 ++          if (operating_mode != undefined_mode)
  24.808 ++            FATAL_ERROR (_("only one type of list may be specified"));
  24.809 ++          operating_mode = character_mode;
  24.810 ++          spec_list_string = optarg;
  24.811 ++          break;
  24.812 ++
  24.813 +         case 'f':
  24.814 +           /* Build the field list. */
  24.815 +           if (operating_mode != undefined_mode)
  24.816 +@@ -524,10 +885,38 @@ main (int argc, char **argv)
  24.817 +         case 'd':
  24.818 +           /* New delimiter. */
  24.819 +           /* Interpret -d '' to mean 'use the NUL byte as the delimiter.'  */
  24.820 +-          if (optarg[0] != '\0' && optarg[1] != '\0')
  24.821 +-            FATAL_ERROR (_("the delimiter must be a single character"));
  24.822 +-          delim = optarg[0];
  24.823 +-          delim_specified = true;
  24.824 ++            {
  24.825 ++#if HAVE_MBRTOWC
  24.826 ++              if(MB_CUR_MAX > 1)
  24.827 ++                {
  24.828 ++                  mbstate_t state;
  24.829 ++
  24.830 ++                  memset (&state, '\0', sizeof(mbstate_t));
  24.831 ++                  delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state);
  24.832 ++
  24.833 ++                  if (delimlen == (size_t)-1 || delimlen == (size_t)-2)
  24.834 ++                    ++force_singlebyte_mode;
  24.835 ++                  else
  24.836 ++                    {
  24.837 ++                      delimlen = (delimlen < 1) ? 1 : delimlen;
  24.838 ++                      if (wcdelim != L'\0' && *(optarg + delimlen) != '\0')
  24.839 ++                        FATAL_ERROR (_("the delimiter must be a single character"));
  24.840 ++                      memcpy (mbdelim, optarg, delimlen);
  24.841 ++                      mbdelim[delimlen] = '\0';
  24.842 ++                      if (delimlen == 1)
  24.843 ++                        delim = *optarg;
  24.844 ++                    }
  24.845 ++                }
  24.846 ++
  24.847 ++              if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  24.848 ++#endif
  24.849 ++                {
  24.850 ++                  if (optarg[0] != '\0' && optarg[1] != '\0')
  24.851 ++                    FATAL_ERROR (_("the delimiter must be a single character"));
  24.852 ++                  delim = (unsigned char) optarg[0];
  24.853 ++                }
  24.854 ++            delim_specified = true;
  24.855 ++          }
  24.856 +           break;
  24.857 + 
  24.858 +         case OUTPUT_DELIMITER_OPTION:
  24.859 +@@ -540,6 +929,7 @@ main (int argc, char **argv)
  24.860 +           break;
  24.861 + 
  24.862 +         case 'n':
  24.863 ++          byte_mode_character_aware = 1;
  24.864 +           break;
  24.865 + 
  24.866 +         case 's':
  24.867 +@@ -579,15 +969,34 @@ main (int argc, char **argv)
  24.868 +               | (complement ? SETFLD_COMPLEMENT : 0) );
  24.869 + 
  24.870 +   if (!delim_specified)
  24.871 +-    delim = '\t';
  24.872 ++    {
  24.873 ++      delim = '\t';
  24.874 ++#ifdef HAVE_MBRTOWC
  24.875 ++      wcdelim = L'\t';
  24.876 ++      mbdelim[0] = '\t';
  24.877 ++      mbdelim[1] = '\0';
  24.878 ++      delimlen = 1;
  24.879 ++#endif
  24.880 ++    }
  24.881 + 
  24.882 +   if (output_delimiter_string == NULL)
  24.883 +     {
  24.884 +-      static char dummy[2];
  24.885 +-      dummy[0] = delim;
  24.886 +-      dummy[1] = '\0';
  24.887 +-      output_delimiter_string = dummy;
  24.888 +-      output_delimiter_length = 1;
  24.889 ++#ifdef HAVE_MBRTOWC
  24.890 ++      if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  24.891 ++        {
  24.892 ++          output_delimiter_string = xstrdup(mbdelim);
  24.893 ++          output_delimiter_length = delimlen;
  24.894 ++        }
  24.895 ++
  24.896 ++      if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  24.897 ++#endif
  24.898 ++        {
  24.899 ++          static char dummy[2];
  24.900 ++          dummy[0] = delim;
  24.901 ++          dummy[1] = '\0';
  24.902 ++          output_delimiter_string = dummy;
  24.903 ++          output_delimiter_length = 1;
  24.904 ++        }
  24.905 +     }
  24.906 + 
  24.907 +   if (optind == argc)
  24.908 +diff -Naurp coreutils-8.27-orig/src/expand.c coreutils-8.27/src/expand.c
  24.909 +--- coreutils-8.27-orig/src/expand.c	2017-02-26 15:42:25.000000000 -0600
  24.910 ++++ coreutils-8.27/src/expand.c	2017-03-11 23:49:06.758133530 -0600
  24.911 +@@ -37,6 +37,9 @@
  24.912 + #include <stdio.h>
  24.913 + #include <getopt.h>
  24.914 + #include <sys/types.h>
  24.915 ++
  24.916 ++#include <mbfile.h>
  24.917 ++
  24.918 + #include "system.h"
  24.919 + #include "die.h"
  24.920 + #include "xstrndup.h"
  24.921 +@@ -100,19 +103,41 @@ expand (void)
  24.922 + {
  24.923 +   /* Input stream.  */
  24.924 +   FILE *fp = next_file (NULL);
  24.925 ++  mb_file_t mbf;
  24.926 ++  mbf_char_t c;
  24.927 ++  /* True if the starting locale is utf8.  */
  24.928 ++  bool using_utf_locale;
  24.929 ++
  24.930 ++  /* True if the first file contains BOM header.  */
  24.931 ++  bool found_bom;
  24.932 ++  using_utf_locale=check_utf_locale();
  24.933 + 
  24.934 +   if (!fp)
  24.935 +     return;
  24.936 ++  mbf_init (mbf, fp);
  24.937 ++  found_bom=check_bom(fp,&mbf);
  24.938 + 
  24.939 +-  while (true)
  24.940 ++  if (using_utf_locale == false && found_bom == true)
  24.941 ++  {
  24.942 ++    /*try using some predefined locale */
  24.943 ++
  24.944 ++    if (set_utf_locale () != 0)
  24.945 +     {
  24.946 +-      /* Input character, or EOF.  */
  24.947 +-      int c;
  24.948 ++      error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
  24.949 ++    }
  24.950 ++  }
  24.951 ++
  24.952 + 
  24.953 ++  if (found_bom == true)
  24.954 ++  {
  24.955 ++    print_bom();
  24.956 ++  }
  24.957 ++
  24.958 ++  while (true)
  24.959 ++    {
  24.960 +       /* If true, perform translations.  */
  24.961 +       bool convert = true;
  24.962 + 
  24.963 +-
  24.964 +       /* The following variables have valid values only when CONVERT
  24.965 +          is true:  */
  24.966 + 
  24.967 +@@ -122,17 +147,48 @@ expand (void)
  24.968 +       /* Index in TAB_LIST of next tab stop to examine.  */
  24.969 +       size_t tab_index = 0;
  24.970 + 
  24.971 +-
  24.972 +       /* Convert a line of text.  */
  24.973 + 
  24.974 +       do
  24.975 +         {
  24.976 +-          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
  24.977 +-            continue;
  24.978 ++          while (true) {
  24.979 ++            mbf_getc (c, mbf);
  24.980 ++            if ((mb_iseof (c)) && (fp = next_file (fp)))
  24.981 ++              {
  24.982 ++                mbf_init (mbf, fp);
  24.983 ++                if (fp!=NULL)
  24.984 ++                {
  24.985 ++                  if (check_bom(fp,&mbf)==true)
  24.986 ++                  {
  24.987 ++                    /*Not the first file - check BOM header*/
  24.988 ++                    if (using_utf_locale==false && found_bom==false)
  24.989 ++                    {
  24.990 ++                      /*BOM header in subsequent file but not in the first one. */
  24.991 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
  24.992 ++                    }
  24.993 ++                  }
  24.994 ++                  else
  24.995 ++                  {
  24.996 ++                    if(using_utf_locale==false && found_bom==true)
  24.997 ++                    {
  24.998 ++                      /*First file conatined BOM header - locale was switched to UTF
  24.999 ++                      /*all subsequent files should contain BOM. */
 24.1000 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 24.1001 ++                    }
 24.1002 ++                  }
 24.1003 ++                }
 24.1004 ++                continue;
 24.1005 ++              }
 24.1006 ++            else
 24.1007 ++              {
 24.1008 ++                break;
 24.1009 ++              }
 24.1010 ++            }
 24.1011 ++
 24.1012 + 
 24.1013 +           if (convert)
 24.1014 +             {
 24.1015 +-              if (c == '\t')
 24.1016 ++              if (mb_iseq (c, '\t'))
 24.1017 +                 {
 24.1018 +                   /* Column the next input tab stop is on.  */
 24.1019 +                   uintmax_t next_tab_column;
 24.1020 +@@ -151,32 +207,34 @@ expand (void)
 24.1021 +                     if (putchar (' ') < 0)
 24.1022 +                       die (EXIT_FAILURE, errno, _("write error"));
 24.1023 + 
 24.1024 +-                  c = ' ';
 24.1025 ++                  mb_setascii (&c, ' ');
 24.1026 +                 }
 24.1027 +-              else if (c == '\b')
 24.1028 ++              else if (mb_iseq (c, '\b'))
 24.1029 +                 {
 24.1030 +                   /* Go back one column, and force recalculation of the
 24.1031 +                      next tab stop.  */
 24.1032 +                   column -= !!column;
 24.1033 +                   tab_index -= !!tab_index;
 24.1034 +                 }
 24.1035 +-              else
 24.1036 ++              /* A leading control character could make us trip over.  */
 24.1037 ++              else if (!mb_iscntrl (c))
 24.1038 +                 {
 24.1039 +-                  column++;
 24.1040 ++                  column += mb_width (c);
 24.1041 +                   if (!column)
 24.1042 +                     die (EXIT_FAILURE, 0, _("input line is too long"));
 24.1043 +                 }
 24.1044 + 
 24.1045 +-              convert &= convert_entire_line || !! isblank (c);
 24.1046 ++              convert &= convert_entire_line || mb_isblank (c);
 24.1047 +             }
 24.1048 + 
 24.1049 +-          if (c < 0)
 24.1050 ++          if (mb_iseof (c))
 24.1051 +             return;
 24.1052 + 
 24.1053 +-          if (putchar (c) < 0)
 24.1054 ++          mb_putc (c, stdout);
 24.1055 ++          if (ferror (stdout))
 24.1056 +             die (EXIT_FAILURE, errno, _("write error"));
 24.1057 +         }
 24.1058 +-      while (c != '\n');
 24.1059 ++      while (!mb_iseq (c, '\n'));
 24.1060 +     }
 24.1061 + }
 24.1062 + 
 24.1063 +diff -Naurp coreutils-8.27-orig/src/expand-common.c coreutils-8.27/src/expand-common.c
 24.1064 +--- coreutils-8.27-orig/src/expand-common.c	2017-03-01 11:22:55.000000000 -0600
 24.1065 ++++ coreutils-8.27/src/expand-common.c	2017-03-11 23:49:06.757133570 -0600
 24.1066 +@@ -18,6 +18,7 @@
 24.1067 + 
 24.1068 + #include <stdio.h>
 24.1069 + #include <sys/types.h>
 24.1070 ++#include <mbfile.h>
 24.1071 + #include "system.h"
 24.1072 + #include "die.h"
 24.1073 + #include "error.h"
 24.1074 +@@ -105,6 +106,119 @@ set_extend_size (uintmax_t tabval)
 24.1075 +   return ok;
 24.1076 + }
 24.1077 + 
 24.1078 ++extern int
 24.1079 ++set_utf_locale (void)
 24.1080 ++{
 24.1081 ++      /*try using some predefined locale */
 24.1082 ++      const char* predef_locales[] = {"C.UTF8","en_US.UTF8","en_GB.UTF8"};
 24.1083 ++
 24.1084 ++      const int predef_locales_count=3;
 24.1085 ++      for (int i=0;i<predef_locales_count;i++)
 24.1086 ++        {
 24.1087 ++          if (setlocale(LC_ALL,predef_locales[i])!=NULL)
 24.1088 ++          {
 24.1089 ++            break;
 24.1090 ++          }
 24.1091 ++          else if (i==predef_locales_count-1)
 24.1092 ++          {
 24.1093 ++            return 1;
 24.1094 ++            error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
 24.1095 ++          }
 24.1096 ++        }
 24.1097 ++        return 0;
 24.1098 ++}
 24.1099 ++
 24.1100 ++extern bool
 24.1101 ++check_utf_locale(void)
 24.1102 ++{
 24.1103 ++  char* locale = setlocale (LC_CTYPE , NULL);
 24.1104 ++  if (locale == NULL)
 24.1105 ++  {
 24.1106 ++    return false;
 24.1107 ++  }
 24.1108 ++  else if (strcasestr(locale, "utf8") == NULL && strcasestr(locale, "utf-8") == NULL)
 24.1109 ++  {
 24.1110 ++    return false;
 24.1111 ++  }
 24.1112 ++  return true;
 24.1113 ++}
 24.1114 ++
 24.1115 ++extern bool
 24.1116 ++check_bom(FILE* fp, mb_file_t *mbf)
 24.1117 ++{
 24.1118 ++  int c;
 24.1119 ++
 24.1120 ++
 24.1121 ++  c=fgetc(fp);
 24.1122 ++
 24.1123 ++  /*test BOM header of the first file */
 24.1124 ++  mbf->bufcount=0;
 24.1125 ++  if (c == 0xEF)
 24.1126 ++  {
 24.1127 ++    c=fgetc(fp);
 24.1128 ++  }
 24.1129 ++  else
 24.1130 ++  {
 24.1131 ++    if (c != EOF)
 24.1132 ++    {
 24.1133 ++      ungetc(c,fp);
 24.1134 ++    }
 24.1135 ++    return false;
 24.1136 ++  }
 24.1137 ++
 24.1138 ++  if (c == 0xBB)
 24.1139 ++  {
 24.1140 ++    c=fgetc(fp);
 24.1141 ++  }
 24.1142 ++  else
 24.1143 ++  {
 24.1144 ++    if ( c!= EOF )
 24.1145 ++    {
 24.1146 ++      mbf->buf[0]=(unsigned char) 0xEF;
 24.1147 ++      mbf->bufcount=1;
 24.1148 ++      ungetc(c,fp);
 24.1149 ++      return false;
 24.1150 ++    }
 24.1151 ++    else
 24.1152 ++    {
 24.1153 ++      ungetc(0xEF,fp);
 24.1154 ++      return false;
 24.1155 ++    }
 24.1156 ++  }
 24.1157 ++  if (c == 0xBF)
 24.1158 ++  {
 24.1159 ++    mbf->bufcount=0;
 24.1160 ++    return true;
 24.1161 ++  }
 24.1162 ++  else
 24.1163 ++  {
 24.1164 ++    if (c != EOF)
 24.1165 ++    {
 24.1166 ++      mbf->buf[0]=(unsigned char) 0xEF;
 24.1167 ++      mbf->buf[1]=(unsigned char) 0xBB;
 24.1168 ++      mbf->bufcount=2;
 24.1169 ++      ungetc(c,fp);
 24.1170 ++      return false;
 24.1171 ++    }
 24.1172 ++    else
 24.1173 ++    {
 24.1174 ++      mbf->buf[0]=(unsigned char) 0xEF;
 24.1175 ++      mbf->bufcount=1;
 24.1176 ++      ungetc(0xBB,fp);
 24.1177 ++      return false;
 24.1178 ++    }
 24.1179 ++  }
 24.1180 ++  return false;
 24.1181 ++}
 24.1182 ++
 24.1183 ++extern void
 24.1184 ++print_bom(void)
 24.1185 ++{
 24.1186 ++  putc (0xEF, stdout);
 24.1187 ++  putc (0xBB, stdout);
 24.1188 ++  putc (0xBF, stdout);
 24.1189 ++}
 24.1190 ++
 24.1191 + /* Add the comma or blank separated list of tab stops STOPS
 24.1192 +    to the list of tab stops.  */
 24.1193 + extern void
 24.1194 +diff -Naurp coreutils-8.27-orig/src/expand-common.h coreutils-8.27/src/expand-common.h
 24.1195 +--- coreutils-8.27-orig/src/expand-common.h	2017-01-01 16:34:24.000000000 -0600
 24.1196 ++++ coreutils-8.27/src/expand-common.h	2017-03-11 23:49:06.758133530 -0600
 24.1197 +@@ -34,6 +34,18 @@ extern size_t max_column_width;
 24.1198 + /* The desired exit status.  */
 24.1199 + extern int exit_status;
 24.1200 + 
 24.1201 ++extern int
 24.1202 ++set_utf_locale (void);
 24.1203 ++
 24.1204 ++extern bool
 24.1205 ++check_utf_locale(void);
 24.1206 ++
 24.1207 ++extern bool
 24.1208 ++check_bom(FILE* fp, mb_file_t *mbf);
 24.1209 ++
 24.1210 ++extern void
 24.1211 ++print_bom(void);
 24.1212 ++
 24.1213 + /* Add tab stop TABVAL to the end of 'tab_list'.  */
 24.1214 + extern void
 24.1215 + add_tab_stop (uintmax_t tabval);
 24.1216 +diff -Naurp coreutils-8.27-orig/src/fold.c coreutils-8.27/src/fold.c
 24.1217 +--- coreutils-8.27-orig/src/fold.c	2017-01-01 16:34:24.000000000 -0600
 24.1218 ++++ coreutils-8.27/src/fold.c	2017-03-11 23:49:30.982169404 -0600
 24.1219 +@@ -22,12 +22,34 @@
 24.1220 + #include <getopt.h>
 24.1221 + #include <sys/types.h>
 24.1222 + 
 24.1223 ++/* Get mbstate_t, mbrtowc(), wcwidth().  */
 24.1224 ++#if HAVE_WCHAR_H
 24.1225 ++# include <wchar.h>
 24.1226 ++#endif
 24.1227 ++
 24.1228 ++/* Get iswprint(), iswblank(), wcwidth().  */
 24.1229 ++#if HAVE_WCTYPE_H
 24.1230 ++# include <wctype.h>
 24.1231 ++#endif
 24.1232 ++
 24.1233 + #include "system.h"
 24.1234 + #include "die.h"
 24.1235 + #include "error.h"
 24.1236 + #include "fadvise.h"
 24.1237 + #include "xdectoint.h"
 24.1238 + 
 24.1239 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 24.1240 ++      installation; work around this configuration error.  */
 24.1241 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 24.1242 ++# undef MB_LEN_MAX
 24.1243 ++# define MB_LEN_MAX 16
 24.1244 ++#endif
 24.1245 ++
 24.1246 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 24.1247 ++#if HAVE_MBRTOWC && defined mbstate_t
 24.1248 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 24.1249 ++#endif
 24.1250 ++
 24.1251 + #define TAB_WIDTH 8
 24.1252 + 
 24.1253 + /* The official name of this program (e.g., no 'g' prefix).  */
 24.1254 +@@ -35,20 +57,41 @@
 24.1255 + 
 24.1256 + #define AUTHORS proper_name ("David MacKenzie")
 24.1257 + 
 24.1258 ++#define FATAL_ERROR(Message)                                            \
 24.1259 ++  do                                                                    \
 24.1260 ++    {                                                                   \
 24.1261 ++      error (0, 0, (Message));                                          \
 24.1262 ++      usage (2);                                                        \
 24.1263 ++    }                                                                   \
 24.1264 ++  while (0)
 24.1265 ++
 24.1266 ++enum operating_mode
 24.1267 ++{
 24.1268 ++  /* Fold texts by columns that are at the given positions. */
 24.1269 ++  column_mode,
 24.1270 ++
 24.1271 ++  /* Fold texts by bytes that are at the given positions. */
 24.1272 ++  byte_mode,
 24.1273 ++
 24.1274 ++  /* Fold texts by characters that are at the given positions. */
 24.1275 ++  character_mode,
 24.1276 ++};
 24.1277 ++
 24.1278 ++/* The argument shows current mode. (Default: column_mode) */
 24.1279 ++static enum operating_mode operating_mode;
 24.1280 ++
 24.1281 + /* If nonzero, try to break on whitespace. */
 24.1282 + static bool break_spaces;
 24.1283 + 
 24.1284 +-/* If nonzero, count bytes, not column positions. */
 24.1285 +-static bool count_bytes;
 24.1286 +-
 24.1287 + /* If nonzero, at least one of the files we read was standard input. */
 24.1288 + static bool have_read_stdin;
 24.1289 + 
 24.1290 +-static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::";
 24.1291 ++static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::";
 24.1292 + 
 24.1293 + static struct option const longopts[] =
 24.1294 + {
 24.1295 +   {"bytes", no_argument, NULL, 'b'},
 24.1296 ++  {"characters", no_argument, NULL, 'c'},
 24.1297 +   {"spaces", no_argument, NULL, 's'},
 24.1298 +   {"width", required_argument, NULL, 'w'},
 24.1299 +   {GETOPT_HELP_OPTION_DECL},
 24.1300 +@@ -76,6 +119,7 @@ Wrap input lines in each FILE, writing t
 24.1301 + 
 24.1302 +       fputs (_("\
 24.1303 +   -b, --bytes         count bytes rather than columns\n\
 24.1304 ++  -c, --characters    count characters rather than columns\n\
 24.1305 +   -s, --spaces        break at spaces\n\
 24.1306 +   -w, --width=WIDTH   use WIDTH columns instead of 80\n\
 24.1307 + "), stdout);
 24.1308 +@@ -93,7 +137,7 @@ Wrap input lines in each FILE, writing t
 24.1309 + static size_t
 24.1310 + adjust_column (size_t column, char c)
 24.1311 + {
 24.1312 +-  if (!count_bytes)
 24.1313 ++  if (operating_mode != byte_mode)
 24.1314 +     {
 24.1315 +       if (c == '\b')
 24.1316 +         {
 24.1317 +@@ -116,30 +160,14 @@ adjust_column (size_t column, char c)
 24.1318 +    to stdout, with maximum line length WIDTH.
 24.1319 +    Return true if successful.  */
 24.1320 + 
 24.1321 +-static bool
 24.1322 +-fold_file (char const *filename, size_t width)
 24.1323 ++static void
 24.1324 ++fold_text (FILE *istream, size_t width, int *saved_errno)
 24.1325 + {
 24.1326 +-  FILE *istream;
 24.1327 +   int c;
 24.1328 +   size_t column = 0;		/* Screen column where next char will go. */
 24.1329 +   size_t offset_out = 0;	/* Index in 'line_out' for next char. */
 24.1330 +   static char *line_out = NULL;
 24.1331 +   static size_t allocated_out = 0;
 24.1332 +-  int saved_errno;
 24.1333 +-
 24.1334 +-  if (STREQ (filename, "-"))
 24.1335 +-    {
 24.1336 +-      istream = stdin;
 24.1337 +-      have_read_stdin = true;
 24.1338 +-    }
 24.1339 +-  else
 24.1340 +-    istream = fopen (filename, "r");
 24.1341 +-
 24.1342 +-  if (istream == NULL)
 24.1343 +-    {
 24.1344 +-      error (0, errno, "%s", quotef (filename));
 24.1345 +-      return false;
 24.1346 +-    }
 24.1347 + 
 24.1348 +   fadvise (istream, FADVISE_SEQUENTIAL);
 24.1349 + 
 24.1350 +@@ -169,6 +197,15 @@ fold_file (char const *filename, size_t
 24.1351 +               bool found_blank = false;
 24.1352 +               size_t logical_end = offset_out;
 24.1353 + 
 24.1354 ++              /* If LINE_OUT has no wide character,
 24.1355 ++                 put a new wide character in LINE_OUT
 24.1356 ++                 if column is bigger than width. */
 24.1357 ++              if (offset_out == 0)
 24.1358 ++                {
 24.1359 ++                  line_out[offset_out++] = c;
 24.1360 ++                  continue;
 24.1361 ++                }
 24.1362 ++
 24.1363 +               /* Look for the last blank. */
 24.1364 +               while (logical_end)
 24.1365 +                 {
 24.1366 +@@ -215,11 +252,220 @@ fold_file (char const *filename, size_t
 24.1367 +       line_out[offset_out++] = c;
 24.1368 +     }
 24.1369 + 
 24.1370 +-  saved_errno = errno;
 24.1371 ++  *saved_errno = errno;
 24.1372 ++
 24.1373 ++  if (offset_out)
 24.1374 ++    fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 24.1375 ++
 24.1376 ++}
 24.1377 ++
 24.1378 ++#if HAVE_MBRTOWC
 24.1379 ++static void
 24.1380 ++fold_multibyte_text (FILE *istream, size_t width, int *saved_errno)
 24.1381 ++{
 24.1382 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
 24.1383 ++  size_t buflen = 0;        /* The length of the byte sequence in buf. */
 24.1384 ++  char *bufpos = buf;         /* Next read position of BUF. */
 24.1385 ++  wint_t wc;                /* A gotten wide character. */
 24.1386 ++  size_t mblength;        /* The byte size of a multibyte character which shows
 24.1387 ++                           as same character as WC. */
 24.1388 ++  mbstate_t state, state_bak;        /* State of the stream. */
 24.1389 ++  int convfail = 0;                /* 1, when conversion is failed. Otherwise 0. */
 24.1390 ++
 24.1391 ++  static char *line_out = NULL;
 24.1392 ++  size_t offset_out = 0;        /* Index in `line_out' for next char. */
 24.1393 ++  static size_t allocated_out = 0;
 24.1394 ++
 24.1395 ++  int increment;
 24.1396 ++  size_t column = 0;
 24.1397 ++
 24.1398 ++  size_t last_blank_pos;
 24.1399 ++  size_t last_blank_column;
 24.1400 ++  int is_blank_seen;
 24.1401 ++  int last_blank_increment = 0;
 24.1402 ++  int is_bs_following_last_blank;
 24.1403 ++  size_t bs_following_last_blank_num;
 24.1404 ++  int is_cr_after_last_blank;
 24.1405 ++
 24.1406 ++#define CLEAR_FLAGS                                \
 24.1407 ++   do                                                \
 24.1408 ++     {                                                \
 24.1409 ++        last_blank_pos = 0;                        \
 24.1410 ++        last_blank_column = 0;                        \
 24.1411 ++        is_blank_seen = 0;                        \
 24.1412 ++        is_bs_following_last_blank = 0;                \
 24.1413 ++        bs_following_last_blank_num = 0;        \
 24.1414 ++        is_cr_after_last_blank = 0;                \
 24.1415 ++     }                                                \
 24.1416 ++   while (0)
 24.1417 ++
 24.1418 ++#define START_NEW_LINE                        \
 24.1419 ++   do                                        \
 24.1420 ++     {                                        \
 24.1421 ++      putchar ('\n');                        \
 24.1422 ++      column = 0;                        \
 24.1423 ++      offset_out = 0;                        \
 24.1424 ++      CLEAR_FLAGS;                        \
 24.1425 ++    }                                        \
 24.1426 ++   while (0)
 24.1427 ++
 24.1428 ++  CLEAR_FLAGS;
 24.1429 ++  memset (&state, '\0', sizeof(mbstate_t));
 24.1430 ++
 24.1431 ++  for (;; bufpos += mblength, buflen -= mblength)
 24.1432 ++    {
 24.1433 ++      if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream))
 24.1434 ++        {
 24.1435 ++          memmove (buf, bufpos, buflen);
 24.1436 ++          buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream);
 24.1437 ++          bufpos = buf;
 24.1438 ++        }
 24.1439 ++
 24.1440 ++      if (buflen < 1)
 24.1441 ++        break;
 24.1442 ++
 24.1443 ++      /* Get a wide character. */
 24.1444 ++      state_bak = state;
 24.1445 ++      mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state);
 24.1446 ++
 24.1447 ++      switch (mblength)
 24.1448 ++        {
 24.1449 ++        case (size_t)-1:
 24.1450 ++        case (size_t)-2:
 24.1451 ++          convfail++;
 24.1452 ++          state = state_bak;
 24.1453 ++          /* Fall through. */
 24.1454 ++
 24.1455 ++        case 0:
 24.1456 ++          mblength = 1;
 24.1457 ++          break;
 24.1458 ++        }
 24.1459 ++
 24.1460 ++rescan:
 24.1461 ++      if (convfail)
 24.1462 ++        increment = 1;
 24.1463 ++      else if (wc == L'\n')
 24.1464 ++        {
 24.1465 ++          /* preserve newline */
 24.1466 ++          fwrite (line_out, sizeof(char), offset_out, stdout);
 24.1467 ++          START_NEW_LINE;
 24.1468 ++          continue;
 24.1469 ++        }
 24.1470 ++      else if (operating_mode == byte_mode)                  /* byte mode */
 24.1471 ++        increment = mblength;
 24.1472 ++      else if (operating_mode == character_mode)        /* character mode */
 24.1473 ++        increment = 1;
 24.1474 ++      else                                                 /* column mode */
 24.1475 ++        {
 24.1476 ++          switch (wc)
 24.1477 ++            {
 24.1478 ++            case L'\b':
 24.1479 ++              increment = (column > 0) ? -1 : 0;
 24.1480 ++              break;
 24.1481 ++
 24.1482 ++            case L'\r':
 24.1483 ++              increment = -1 * column;
 24.1484 ++              break;
 24.1485 ++
 24.1486 ++            case L'\t':
 24.1487 ++              increment = 8 - column % 8;
 24.1488 ++              break;
 24.1489 ++
 24.1490 ++            default:
 24.1491 ++              increment = wcwidth (wc);
 24.1492 ++              increment = (increment < 0) ? 0 : increment;
 24.1493 ++            }
 24.1494 ++        }
 24.1495 ++
 24.1496 ++      if (column + increment > width && break_spaces && last_blank_pos)
 24.1497 ++        {
 24.1498 ++          fwrite (line_out, sizeof(char), last_blank_pos, stdout);
 24.1499 ++          putchar ('\n');
 24.1500 ++
 24.1501 ++          offset_out = offset_out - last_blank_pos;
 24.1502 ++          column = column - last_blank_column + ((is_cr_after_last_blank)
 24.1503 ++              ? last_blank_increment : bs_following_last_blank_num);
 24.1504 ++          memmove (line_out, line_out + last_blank_pos, offset_out);
 24.1505 ++          CLEAR_FLAGS;
 24.1506 ++          goto rescan;
 24.1507 ++        }
 24.1508 ++
 24.1509 ++      if (column + increment > width && column != 0)
 24.1510 ++        {
 24.1511 ++          fwrite (line_out, sizeof(char), offset_out, stdout);
 24.1512 ++          START_NEW_LINE;
 24.1513 ++          goto rescan;
 24.1514 ++        }
 24.1515 ++
 24.1516 ++      if (allocated_out < offset_out + mblength)
 24.1517 ++        {
 24.1518 ++          line_out = X2REALLOC (line_out, &allocated_out);
 24.1519 ++        }
 24.1520 ++
 24.1521 ++      memcpy (line_out + offset_out, bufpos, mblength);
 24.1522 ++      offset_out += mblength;
 24.1523 ++      column += increment;
 24.1524 ++
 24.1525 ++      if (is_blank_seen && !convfail && wc == L'\r')
 24.1526 ++        is_cr_after_last_blank = 1;
 24.1527 ++
 24.1528 ++      if (is_bs_following_last_blank && !convfail && wc == L'\b')
 24.1529 ++        ++bs_following_last_blank_num;
 24.1530 ++      else
 24.1531 ++        is_bs_following_last_blank = 0;
 24.1532 ++
 24.1533 ++      if (break_spaces && !convfail && iswblank (wc))
 24.1534 ++        {
 24.1535 ++          last_blank_pos = offset_out;
 24.1536 ++          last_blank_column = column;
 24.1537 ++          is_blank_seen = 1;
 24.1538 ++          last_blank_increment = increment;
 24.1539 ++          is_bs_following_last_blank = 1;
 24.1540 ++          bs_following_last_blank_num = 0;
 24.1541 ++          is_cr_after_last_blank = 0;
 24.1542 ++        }
 24.1543 ++    }
 24.1544 ++
 24.1545 ++  *saved_errno = errno;
 24.1546 + 
 24.1547 +   if (offset_out)
 24.1548 +     fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 24.1549 + 
 24.1550 ++}
 24.1551 ++#endif
 24.1552 ++
 24.1553 ++/* Fold file FILENAME, or standard input if FILENAME is "-",
 24.1554 ++   to stdout, with maximum line length WIDTH.
 24.1555 ++   Return 0 if successful, 1 if an error occurs. */
 24.1556 ++
 24.1557 ++static bool
 24.1558 ++fold_file (char const *filename, size_t width)
 24.1559 ++{
 24.1560 ++  FILE *istream;
 24.1561 ++  int saved_errno;
 24.1562 ++
 24.1563 ++  if (STREQ (filename, "-"))
 24.1564 ++    {
 24.1565 ++      istream = stdin;
 24.1566 ++      have_read_stdin = 1;
 24.1567 ++    }
 24.1568 ++  else
 24.1569 ++    istream = fopen (filename, "r");
 24.1570 ++
 24.1571 ++  if (istream == NULL)
 24.1572 ++    {
 24.1573 ++      error (0, errno, "%s", filename);
 24.1574 ++      return 1;
 24.1575 ++    }
 24.1576 ++
 24.1577 ++  /* Define how ISTREAM is being folded. */
 24.1578 ++#if HAVE_MBRTOWC
 24.1579 ++  if (MB_CUR_MAX > 1)
 24.1580 ++    fold_multibyte_text (istream, width, &saved_errno);
 24.1581 ++  else
 24.1582 ++#endif
 24.1583 ++    fold_text (istream, width, &saved_errno);
 24.1584 ++
 24.1585 +   if (ferror (istream))
 24.1586 +     {
 24.1587 +       error (0, saved_errno, "%s", quotef (filename));
 24.1588 +@@ -252,7 +498,8 @@ main (int argc, char **argv)
 24.1589 + 
 24.1590 +   atexit (close_stdout);
 24.1591 + 
 24.1592 +-  break_spaces = count_bytes = have_read_stdin = false;
 24.1593 ++  operating_mode = column_mode;
 24.1594 ++  break_spaces = have_read_stdin = false;
 24.1595 + 
 24.1596 +   while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
 24.1597 +     {
 24.1598 +@@ -261,7 +508,15 @@ main (int argc, char **argv)
 24.1599 +       switch (optc)
 24.1600 +         {
 24.1601 +         case 'b':		/* Count bytes rather than columns. */
 24.1602 +-          count_bytes = true;
 24.1603 ++          if (operating_mode != column_mode)
 24.1604 ++            FATAL_ERROR (_("only one way of folding may be specified"));
 24.1605 ++          operating_mode = byte_mode;
 24.1606 ++          break;
 24.1607 ++
 24.1608 ++        case 'c':
 24.1609 ++          if (operating_mode != column_mode)
 24.1610 ++            FATAL_ERROR (_("only one way of folding may be specified"));
 24.1611 ++          operating_mode = character_mode;
 24.1612 +           break;
 24.1613 + 
 24.1614 +         case 's':		/* Break at word boundaries. */
 24.1615 +diff -Naurp coreutils-8.27-orig/src/join.c coreutils-8.27/src/join.c
 24.1616 +--- coreutils-8.27-orig/src/join.c	2017-01-01 16:34:24.000000000 -0600
 24.1617 ++++ coreutils-8.27/src/join.c	2017-03-11 23:47:13.091286290 -0600
 24.1618 +@@ -22,19 +22,33 @@
 24.1619 + #include <sys/types.h>
 24.1620 + #include <getopt.h>
 24.1621 + 
 24.1622 ++/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth().  */
 24.1623 ++#if HAVE_WCHAR_H
 24.1624 ++# include <wchar.h>
 24.1625 ++#endif
 24.1626 ++
 24.1627 ++/* Get iswblank(), towupper.  */
 24.1628 ++#if HAVE_WCTYPE_H
 24.1629 ++# include <wctype.h>
 24.1630 ++#endif
 24.1631 ++
 24.1632 + #include "system.h"
 24.1633 + #include "die.h"
 24.1634 + #include "error.h"
 24.1635 + #include "fadvise.h"
 24.1636 + #include "hard-locale.h"
 24.1637 + #include "linebuffer.h"
 24.1638 +-#include "memcasecmp.h"
 24.1639 + #include "quote.h"
 24.1640 + #include "stdio--.h"
 24.1641 + #include "xmemcoll.h"
 24.1642 + #include "xstrtol.h"
 24.1643 + #include "argmatch.h"
 24.1644 + 
 24.1645 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 24.1646 ++#if HAVE_MBRTOWC && defined mbstate_t
 24.1647 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 24.1648 ++#endif
 24.1649 ++
 24.1650 + /* The official name of this program (e.g., no 'g' prefix).  */
 24.1651 + #define PROGRAM_NAME "join"
 24.1652 + 
 24.1653 +@@ -136,10 +150,12 @@ static struct outlist outlist_head;
 24.1654 + /* Last element in 'outlist', where a new element can be added.  */
 24.1655 + static struct outlist *outlist_end = &outlist_head;
 24.1656 + 
 24.1657 +-/* Tab character separating fields.  If negative, fields are separated
 24.1658 +-   by any nonempty string of blanks, otherwise by exactly one
 24.1659 +-   tab character whose value (when cast to unsigned char) equals TAB.  */
 24.1660 +-static int tab = -1;
 24.1661 ++/* Tab character separating fields.  If NULL, fields are separated
 24.1662 ++   by any nonempty string of blanks.  */
 24.1663 ++static char *tab = NULL;
 24.1664 ++
 24.1665 ++/* The number of bytes used for tab. */
 24.1666 ++static size_t tablen = 0;
 24.1667 + 
 24.1668 + /* If nonzero, check that the input is correctly ordered. */
 24.1669 + static enum
 24.1670 +@@ -276,13 +292,14 @@ xfields (struct line *line)
 24.1671 +   if (ptr == lim)
 24.1672 +     return;
 24.1673 + 
 24.1674 +-  if (0 <= tab && tab != '\n')
 24.1675 ++  if (tab != NULL)
 24.1676 +     {
 24.1677 ++      unsigned char t = tab[0];
 24.1678 +       char *sep;
 24.1679 +-      for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1)
 24.1680 ++      for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1)
 24.1681 +         extract_field (line, ptr, sep - ptr);
 24.1682 +     }
 24.1683 +-  else if (tab < 0)
 24.1684 ++   else
 24.1685 +     {
 24.1686 +       /* Skip leading blanks before the first field.  */
 24.1687 +       while (field_sep (*ptr))
 24.1688 +@@ -306,6 +323,147 @@ xfields (struct line *line)
 24.1689 +   extract_field (line, ptr, lim - ptr);
 24.1690 + }
 24.1691 + 
 24.1692 ++#if HAVE_MBRTOWC
 24.1693 ++static void
 24.1694 ++xfields_multibyte (struct line *line)
 24.1695 ++{
 24.1696 ++  char *ptr = line->buf.buffer;
 24.1697 ++  char const *lim = ptr + line->buf.length - 1;
 24.1698 ++  wchar_t wc = 0;
 24.1699 ++  size_t mblength = 1;
 24.1700 ++  mbstate_t state, state_bak;
 24.1701 ++
 24.1702 ++  memset (&state, 0, sizeof (mbstate_t));
 24.1703 ++
 24.1704 ++  if (ptr >= lim)
 24.1705 ++    return;
 24.1706 ++
 24.1707 ++  if (tab != NULL)
 24.1708 ++    {
 24.1709 ++      char *sep = ptr;
 24.1710 ++      for (; ptr < lim; ptr = sep + mblength)
 24.1711 ++	{
 24.1712 ++	  sep = ptr;
 24.1713 ++	  while (sep < lim)
 24.1714 ++	    {
 24.1715 ++	      state_bak = state;
 24.1716 ++	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 24.1717 ++
 24.1718 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1719 ++		{
 24.1720 ++		  mblength = 1;
 24.1721 ++		  state = state_bak;
 24.1722 ++		}
 24.1723 ++	      mblength = (mblength < 1) ? 1 : mblength;
 24.1724 ++
 24.1725 ++	      if (mblength == tablen && !memcmp (sep, tab, mblength))
 24.1726 ++		break;
 24.1727 ++	      else
 24.1728 ++		{
 24.1729 ++		  sep += mblength;
 24.1730 ++		  continue;
 24.1731 ++		}
 24.1732 ++	    }
 24.1733 ++
 24.1734 ++	  if (sep >= lim)
 24.1735 ++	    break;
 24.1736 ++
 24.1737 ++	  extract_field (line, ptr, sep - ptr);
 24.1738 ++	}
 24.1739 ++    }
 24.1740 ++  else
 24.1741 ++    {
 24.1742 ++      /* Skip leading blanks before the first field.  */
 24.1743 ++      while(ptr < lim)
 24.1744 ++      {
 24.1745 ++        state_bak = state;
 24.1746 ++        mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 24.1747 ++
 24.1748 ++        if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1749 ++          {
 24.1750 ++            mblength = 1;
 24.1751 ++            state = state_bak;
 24.1752 ++            break;
 24.1753 ++          }
 24.1754 ++        mblength = (mblength < 1) ? 1 : mblength;
 24.1755 ++
 24.1756 ++        if (!iswblank(wc) && wc != '\n')
 24.1757 ++          break;
 24.1758 ++        ptr += mblength;
 24.1759 ++      }
 24.1760 ++
 24.1761 ++      do
 24.1762 ++	{
 24.1763 ++	  char *sep;
 24.1764 ++	  state_bak = state;
 24.1765 ++	  mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 24.1766 ++	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1767 ++	    {
 24.1768 ++	      mblength = 1;
 24.1769 ++	      state = state_bak;
 24.1770 ++	      break;
 24.1771 ++	    }
 24.1772 ++	  mblength = (mblength < 1) ? 1 : mblength;
 24.1773 ++
 24.1774 ++	  sep = ptr + mblength;
 24.1775 ++	  while (sep < lim)
 24.1776 ++	    {
 24.1777 ++	      state_bak = state;
 24.1778 ++	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 24.1779 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1780 ++		{
 24.1781 ++		  mblength = 1;
 24.1782 ++		  state = state_bak;
 24.1783 ++		  break;
 24.1784 ++		}
 24.1785 ++	      mblength = (mblength < 1) ? 1 : mblength;
 24.1786 ++
 24.1787 ++	      if (iswblank (wc) || wc == '\n')
 24.1788 ++		break;
 24.1789 ++
 24.1790 ++	      sep += mblength;
 24.1791 ++	    }
 24.1792 ++
 24.1793 ++	  extract_field (line, ptr, sep - ptr);
 24.1794 ++	  if (sep >= lim)
 24.1795 ++	    return;
 24.1796 ++
 24.1797 ++	  state_bak = state;
 24.1798 ++	  mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 24.1799 ++	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1800 ++	    {
 24.1801 ++	      mblength = 1;
 24.1802 ++	      state = state_bak;
 24.1803 ++	      break;
 24.1804 ++	    }
 24.1805 ++	  mblength = (mblength < 1) ? 1 : mblength;
 24.1806 ++
 24.1807 ++	  ptr = sep + mblength;
 24.1808 ++	  while (ptr < lim)
 24.1809 ++	    {
 24.1810 ++	      state_bak = state;
 24.1811 ++	      mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 24.1812 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.1813 ++		{
 24.1814 ++		  mblength = 1;
 24.1815 ++		  state = state_bak;
 24.1816 ++		  break;
 24.1817 ++		}
 24.1818 ++	      mblength = (mblength < 1) ? 1 : mblength;
 24.1819 ++
 24.1820 ++	      if (!iswblank (wc) && wc != '\n')
 24.1821 ++		break;
 24.1822 ++
 24.1823 ++	      ptr += mblength;
 24.1824 ++	    }
 24.1825 ++	}
 24.1826 ++      while (ptr < lim);
 24.1827 ++    }
 24.1828 ++
 24.1829 ++  extract_field (line, ptr, lim - ptr);
 24.1830 ++}
 24.1831 ++#endif
 24.1832 ++
 24.1833 + static void
 24.1834 + freeline (struct line *line)
 24.1835 + {
 24.1836 +@@ -327,56 +485,133 @@ keycmp (struct line const *line1, struct
 24.1837 +         size_t jf_1, size_t jf_2)
 24.1838 + {
 24.1839 +   /* Start of field to compare in each file.  */
 24.1840 +-  char *beg1;
 24.1841 +-  char *beg2;
 24.1842 +-
 24.1843 +-  size_t len1;
 24.1844 +-  size_t len2;		/* Length of fields to compare.  */
 24.1845 ++  char *beg[2];
 24.1846 ++  char *copy[2];
 24.1847 ++  size_t len[2]; 	/* Length of fields to compare.  */
 24.1848 +   int diff;
 24.1849 ++  int i, j;
 24.1850 ++  int mallocd = 0;
 24.1851 + 
 24.1852 +   if (jf_1 < line1->nfields)
 24.1853 +     {
 24.1854 +-      beg1 = line1->fields[jf_1].beg;
 24.1855 +-      len1 = line1->fields[jf_1].len;
 24.1856 ++      beg[0] = line1->fields[jf_1].beg;
 24.1857 ++      len[0] = line1->fields[jf_1].len;
 24.1858 +     }
 24.1859 +   else
 24.1860 +     {
 24.1861 +-      beg1 = NULL;
 24.1862 +-      len1 = 0;
 24.1863 ++      beg[0] = NULL;
 24.1864 ++      len[0] = 0;
 24.1865 +     }
 24.1866 + 
 24.1867 +   if (jf_2 < line2->nfields)
 24.1868 +     {
 24.1869 +-      beg2 = line2->fields[jf_2].beg;
 24.1870 +-      len2 = line2->fields[jf_2].len;
 24.1871 ++      beg[1] = line2->fields[jf_2].beg;
 24.1872 ++      len[1] = line2->fields[jf_2].len;
 24.1873 +     }
 24.1874 +   else
 24.1875 +     {
 24.1876 +-      beg2 = NULL;
 24.1877 +-      len2 = 0;
 24.1878 ++      beg[1] = NULL;
 24.1879 ++      len[1] = 0;
 24.1880 +     }
 24.1881 + 
 24.1882 +-  if (len1 == 0)
 24.1883 +-    return len2 == 0 ? 0 : -1;
 24.1884 +-  if (len2 == 0)
 24.1885 ++  if (len[0] == 0)
 24.1886 ++    return len[1] == 0 ? 0 : -1;
 24.1887 ++  if (len[1] == 0)
 24.1888 +     return 1;
 24.1889 + 
 24.1890 +   if (ignore_case)
 24.1891 +     {
 24.1892 +-      /* FIXME: ignore_case does not work with NLS (in particular,
 24.1893 +-         with multibyte chars).  */
 24.1894 +-      diff = memcasecmp (beg1, beg2, MIN (len1, len2));
 24.1895 ++#ifdef HAVE_MBRTOWC
 24.1896 ++      if (MB_CUR_MAX > 1)
 24.1897 ++      {
 24.1898 ++        size_t mblength;
 24.1899 ++        wchar_t wc, uwc;
 24.1900 ++        mbstate_t state, state_bak;
 24.1901 ++
 24.1902 ++        memset (&state, '\0', sizeof (mbstate_t));
 24.1903 ++
 24.1904 ++        for (i = 0; i < 2; i++)
 24.1905 ++          {
 24.1906 ++            mallocd = 1;
 24.1907 ++            copy[i] = xmalloc (len[i] + 1);
 24.1908 ++            memset (copy[i], '\0',len[i] + 1);
 24.1909 ++
 24.1910 ++            for (j = 0; j < MIN (len[0], len[1]);)
 24.1911 ++              {
 24.1912 ++                state_bak = state;
 24.1913 ++                mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state);
 24.1914 ++
 24.1915 ++                switch (mblength)
 24.1916 ++                  {
 24.1917 ++                  case (size_t) -1:
 24.1918 ++                  case (size_t) -2:
 24.1919 ++                    state = state_bak;
 24.1920 ++                    /* Fall through */
 24.1921 ++                  case 0:
 24.1922 ++                    mblength = 1;
 24.1923 ++                    break;
 24.1924 ++
 24.1925 ++                  default:
 24.1926 ++                    uwc = towupper (wc);
 24.1927 ++
 24.1928 ++                    if (uwc != wc)
 24.1929 ++                      {
 24.1930 ++                        mbstate_t state_wc;
 24.1931 ++                        size_t mblen;
 24.1932 ++
 24.1933 ++                        memset (&state_wc, '\0', sizeof (mbstate_t));
 24.1934 ++                        mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 24.1935 ++                        assert (mblen != (size_t)-1);
 24.1936 ++                      }
 24.1937 ++                    else
 24.1938 ++                      memcpy (copy[i] + j, beg[i] + j, mblength);
 24.1939 ++                  }
 24.1940 ++                j += mblength;
 24.1941 ++              }
 24.1942 ++            copy[i][j] = '\0';
 24.1943 ++          }
 24.1944 ++      }
 24.1945 ++      else
 24.1946 ++#endif
 24.1947 ++      {
 24.1948 ++        for (i = 0; i < 2; i++)
 24.1949 ++          {
 24.1950 ++            mallocd = 1;
 24.1951 ++            copy[i] = xmalloc (len[i] + 1);
 24.1952 ++
 24.1953 ++            for (j = 0; j < MIN (len[0], len[1]); j++)
 24.1954 ++              copy[i][j] = toupper (beg[i][j]);
 24.1955 ++
 24.1956 ++            copy[i][j] = '\0';
 24.1957 ++          }
 24.1958 ++      }
 24.1959 +     }
 24.1960 +   else
 24.1961 +     {
 24.1962 +-      if (hard_LC_COLLATE)
 24.1963 +-        return xmemcoll (beg1, len1, beg2, len2);
 24.1964 +-      diff = memcmp (beg1, beg2, MIN (len1, len2));
 24.1965 ++      copy[0] = beg[0];
 24.1966 ++      copy[1] = beg[1];
 24.1967 +     }
 24.1968 + 
 24.1969 ++  if (hard_LC_COLLATE)
 24.1970 ++    {
 24.1971 ++      diff = xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]);
 24.1972 ++
 24.1973 ++      if (mallocd)
 24.1974 ++        for (i = 0; i < 2; i++)
 24.1975 ++          free (copy[i]);
 24.1976 ++
 24.1977 ++      return diff;
 24.1978 ++    }
 24.1979 ++  diff = memcmp (copy[0], copy[1], MIN (len[0], len[1]));
 24.1980 ++
 24.1981 ++  if (mallocd)
 24.1982 ++    for (i = 0; i < 2; i++)
 24.1983 ++      free (copy[i]);
 24.1984 ++
 24.1985 ++
 24.1986 +   if (diff)
 24.1987 +     return diff;
 24.1988 +-  return len1 < len2 ? -1 : len1 != len2;
 24.1989 ++  return len[0] - len[1];
 24.1990 + }
 24.1991 + 
 24.1992 + /* Check that successive input lines PREV and CURRENT from input file
 24.1993 +@@ -468,6 +703,11 @@ get_line (FILE *fp, struct line **linep,
 24.1994 +     }
 24.1995 +   ++line_no[which - 1];
 24.1996 + 
 24.1997 ++#if HAVE_MBRTOWC
 24.1998 ++  if (MB_CUR_MAX > 1)
 24.1999 ++    xfields_multibyte (line);
 24.2000 ++  else
 24.2001 ++#endif
 24.2002 +   xfields (line);
 24.2003 + 
 24.2004 +   if (prevline[which - 1])
 24.2005 +@@ -567,21 +807,28 @@ prfield (size_t n, struct line const *li
 24.2006 + 
 24.2007 + /* Output all the fields in line, other than the join field.  */
 24.2008 + 
 24.2009 ++#define PUT_TAB_CHAR							\
 24.2010 ++  do									\
 24.2011 ++    {									\
 24.2012 ++      (tab != NULL) ?							\
 24.2013 ++	fwrite(tab, sizeof(char), tablen, stdout) : putchar (' ');	\
 24.2014 ++    }									\
 24.2015 ++  while (0)
 24.2016 ++
 24.2017 + static void
 24.2018 + prfields (struct line const *line, size_t join_field, size_t autocount)
 24.2019 + {
 24.2020 +   size_t i;
 24.2021 +   size_t nfields = autoformat ? autocount : line->nfields;
 24.2022 +-  char output_separator = tab < 0 ? ' ' : tab;
 24.2023 + 
 24.2024 +   for (i = 0; i < join_field && i < nfields; ++i)
 24.2025 +     {
 24.2026 +-      putchar (output_separator);
 24.2027 ++      PUT_TAB_CHAR;
 24.2028 +       prfield (i, line);
 24.2029 +     }
 24.2030 +   for (i = join_field + 1; i < nfields; ++i)
 24.2031 +     {
 24.2032 +-      putchar (output_separator);
 24.2033 ++      PUT_TAB_CHAR;
 24.2034 +       prfield (i, line);
 24.2035 +     }
 24.2036 + }
 24.2037 +@@ -592,7 +839,6 @@ static void
 24.2038 + prjoin (struct line const *line1, struct line const *line2)
 24.2039 + {
 24.2040 +   const struct outlist *outlist;
 24.2041 +-  char output_separator = tab < 0 ? ' ' : tab;
 24.2042 +   size_t field;
 24.2043 +   struct line const *line;
 24.2044 + 
 24.2045 +@@ -626,7 +872,7 @@ prjoin (struct line const *line1, struct
 24.2046 +           o = o->next;
 24.2047 +           if (o == NULL)
 24.2048 +             break;
 24.2049 +-          putchar (output_separator);
 24.2050 ++          PUT_TAB_CHAR;
 24.2051 +         }
 24.2052 +       putchar (eolchar);
 24.2053 +     }
 24.2054 +@@ -1104,20 +1350,43 @@ main (int argc, char **argv)
 24.2055 + 
 24.2056 +         case 't':
 24.2057 +           {
 24.2058 +-            unsigned char newtab = optarg[0];
 24.2059 ++            char *newtab = NULL;
 24.2060 ++            size_t newtablen;
 24.2061 ++            newtab = xstrdup (optarg);
 24.2062 ++#if HAVE_MBRTOWC
 24.2063 ++            if (MB_CUR_MAX > 1)
 24.2064 ++              {
 24.2065 ++                mbstate_t state;
 24.2066 ++
 24.2067 ++                memset (&state, 0, sizeof (mbstate_t));
 24.2068 ++                newtablen = mbrtowc (NULL, newtab,
 24.2069 ++                                     strnlen (newtab, MB_LEN_MAX),
 24.2070 ++                                     &state);
 24.2071 ++                if (newtablen == (size_t) 0
 24.2072 ++                    || newtablen == (size_t) -1
 24.2073 ++                    || newtablen == (size_t) -2)
 24.2074 ++                  newtablen = 1;
 24.2075 ++              }
 24.2076 ++            else
 24.2077 ++#endif
 24.2078 ++              newtablen = 1;
 24.2079 +             if (! newtab)
 24.2080 +-              newtab = '\n'; /* '' => process the whole line.  */
 24.2081 ++              newtab = (char*)"\n"; /* '' => process the whole line.  */
 24.2082 +             else if (optarg[1])
 24.2083 +               {
 24.2084 +-                if (STREQ (optarg, "\\0"))
 24.2085 +-                  newtab = '\0';
 24.2086 +-                else
 24.2087 +-                  die (EXIT_FAILURE, 0, _("multi-character tab %s"),
 24.2088 +-                       quote (optarg));
 24.2089 ++                if (newtablen == 1 && newtab[1])
 24.2090 ++                {
 24.2091 ++                  if (STREQ (newtab, "\\0"))
 24.2092 ++                     newtab[0] = '\0';
 24.2093 ++                }
 24.2094 ++              }
 24.2095 ++            if (tab != NULL && strcmp (tab, newtab))
 24.2096 ++              {
 24.2097 ++                free (newtab);
 24.2098 ++                die (EXIT_FAILURE, 0, _("incompatible tabs"));
 24.2099 +               }
 24.2100 +-            if (0 <= tab && tab != newtab)
 24.2101 +-              die (EXIT_FAILURE, 0, _("incompatible tabs"));
 24.2102 +             tab = newtab;
 24.2103 ++            tablen = newtablen;
 24.2104 +           }
 24.2105 +           break;
 24.2106 + 
 24.2107 +diff -Naurp coreutils-8.27-orig/src/pr.c coreutils-8.27/src/pr.c
 24.2108 +--- coreutils-8.27-orig/src/pr.c	2017-01-01 16:34:24.000000000 -0600
 24.2109 ++++ coreutils-8.27/src/pr.c	2017-03-11 23:47:13.094286139 -0600
 24.2110 +@@ -311,6 +311,24 @@
 24.2111 + 
 24.2112 + #include <getopt.h>
 24.2113 + #include <sys/types.h>
 24.2114 ++
 24.2115 ++/* Get MB_LEN_MAX.  */
 24.2116 ++#include <limits.h>
 24.2117 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 24.2118 ++   installation; work around this configuration error.  */
 24.2119 ++#if !defined MB_LEN_MAX || MB_LEN_MAX == 1
 24.2120 ++# define MB_LEN_MAX 16
 24.2121 ++#endif
 24.2122 ++
 24.2123 ++/* Get MB_CUR_MAX.  */
 24.2124 ++#include <stdlib.h>
 24.2125 ++
 24.2126 ++/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
 24.2127 ++/* Get mbstate_t, mbrtowc(), wcwidth().  */
 24.2128 ++#if HAVE_WCHAR_H
 24.2129 ++# include <wchar.h>
 24.2130 ++#endif
 24.2131 ++
 24.2132 + #include "system.h"
 24.2133 + #include "die.h"
 24.2134 + #include "error.h"
 24.2135 +@@ -324,6 +342,18 @@
 24.2136 + #include "xstrtol.h"
 24.2137 + #include "xdectoint.h"
 24.2138 + 
 24.2139 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 24.2140 ++#if HAVE_MBRTOWC && defined mbstate_t
 24.2141 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 24.2142 ++#endif
 24.2143 ++
 24.2144 ++#ifndef HAVE_DECL_WCWIDTH
 24.2145 ++"this configure-time declaration test was not run"
 24.2146 ++#endif
 24.2147 ++#if !HAVE_DECL_WCWIDTH
 24.2148 ++extern int wcwidth ();
 24.2149 ++#endif
 24.2150 ++
 24.2151 + /* The official name of this program (e.g., no 'g' prefix).  */
 24.2152 + #define PROGRAM_NAME "pr"
 24.2153 + 
 24.2154 +@@ -416,7 +446,20 @@ struct COLUMN
 24.2155 + 
 24.2156 + typedef struct COLUMN COLUMN;
 24.2157 + 
 24.2158 +-static int char_to_clump (char c);
 24.2159 ++/* Funtion pointers to switch functions for single byte locale or for
 24.2160 ++   multibyte locale. If multibyte functions do not exist in your sysytem,
 24.2161 ++   these pointers always point the function for single byte locale. */
 24.2162 ++static void (*print_char) (char c);
 24.2163 ++static int (*char_to_clump) (char c);
 24.2164 ++
 24.2165 ++/* Functions for single byte locale. */
 24.2166 ++static void print_char_single (char c);
 24.2167 ++static int char_to_clump_single (char c);
 24.2168 ++
 24.2169 ++/* Functions for multibyte locale. */
 24.2170 ++static void print_char_multi (char c);
 24.2171 ++static int char_to_clump_multi (char c);
 24.2172 ++
 24.2173 + static bool read_line (COLUMN *p);
 24.2174 + static bool print_page (void);
 24.2175 + static bool print_stored (COLUMN *p);
 24.2176 +@@ -428,6 +471,7 @@ static void add_line_number (COLUMN *p);
 24.2177 + static void getoptnum (const char *n_str, int min, int *num,
 24.2178 +                        const char *errfmt);
 24.2179 + static void getoptarg (char *arg, char switch_char, char *character,
 24.2180 ++                       int *character_length, int *character_width,
 24.2181 +                        int *number);
 24.2182 + static void print_files (int number_of_files, char **av);
 24.2183 + static void init_parameters (int number_of_files);
 24.2184 +@@ -441,7 +485,6 @@ static void store_char (char c);
 24.2185 + static void pad_down (unsigned int lines);
 24.2186 + static void read_rest_of_line (COLUMN *p);
 24.2187 + static void skip_read (COLUMN *p, int column_number);
 24.2188 +-static void print_char (char c);
 24.2189 + static void cleanup (void);
 24.2190 + static void print_sep_string (void);
 24.2191 + static void separator_string (const char *optarg_S);
 24.2192 +@@ -453,7 +496,7 @@ static COLUMN *column_vector;
 24.2193 +    we store the leftmost columns contiguously in buff.
 24.2194 +    To print a line from buff, get the index of the first character
 24.2195 +    from line_vector[i], and print up to line_vector[i + 1]. */
 24.2196 +-static char *buff;
 24.2197 ++static unsigned char *buff;
 24.2198 + 
 24.2199 + /* Index of the position in buff where the next character
 24.2200 +    will be stored. */
 24.2201 +@@ -557,7 +600,7 @@ static int chars_per_column;
 24.2202 + static bool untabify_input = false;
 24.2203 + 
 24.2204 + /* (-e) The input tab character. */
 24.2205 +-static char input_tab_char = '\t';
 24.2206 ++static char input_tab_char[MB_LEN_MAX] = "\t";
 24.2207 + 
 24.2208 + /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
 24.2209 +    where the leftmost column is 1. */
 24.2210 +@@ -567,7 +610,10 @@ static int chars_per_input_tab = 8;
 24.2211 + static bool tabify_output = false;
 24.2212 + 
 24.2213 + /* (-i) The output tab character. */
 24.2214 +-static char output_tab_char = '\t';
 24.2215 ++static char output_tab_char[MB_LEN_MAX] = "\t";
 24.2216 ++
 24.2217 ++/* (-i) The byte length of output tab character. */
 24.2218 ++static int output_tab_char_length = 1;
 24.2219 + 
 24.2220 + /* (-i) The width of the output tab. */
 24.2221 + static int chars_per_output_tab = 8;
 24.2222 +@@ -637,7 +683,13 @@ static int line_number;
 24.2223 + static bool numbered_lines = false;
 24.2224 + 
 24.2225 + /* (-n) Character which follows each line number. */
 24.2226 +-static char number_separator = '\t';
 24.2227 ++static char number_separator[MB_LEN_MAX] = "\t";
 24.2228 ++
 24.2229 ++/* (-n) The byte length of the character which follows each line number. */
 24.2230 ++static int number_separator_length = 1;
 24.2231 ++
 24.2232 ++/* (-n) The character width of the character which follows each line number. */
 24.2233 ++static int number_separator_width = 0;
 24.2234 + 
 24.2235 + /* (-n) line counting starts with 1st line of input file (not with 1st
 24.2236 +    line of 1st page printed). */
 24.2237 +@@ -690,6 +742,7 @@ static bool use_col_separator = false;
 24.2238 +    -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */
 24.2239 + static char const *col_sep_string = "";
 24.2240 + static int col_sep_length = 0;
 24.2241 ++static int col_sep_width = 0;
 24.2242 + static char *column_separator = (char *) " ";
 24.2243 + static char *line_separator = (char *) "\t";
 24.2244 + 
 24.2245 +@@ -851,6 +904,13 @@ separator_string (const char *optarg_S)
 24.2246 +     integer_overflow ();
 24.2247 +   col_sep_length = len;
 24.2248 +   col_sep_string = optarg_S;
 24.2249 ++
 24.2250 ++#if HAVE_MBRTOWC
 24.2251 ++  if (MB_CUR_MAX > 1)
 24.2252 ++    col_sep_width = mbswidth (col_sep_string, 0);
 24.2253 ++  else
 24.2254 ++#endif
 24.2255 ++    col_sep_width = col_sep_length;
 24.2256 + }
 24.2257 + 
 24.2258 + int
 24.2259 +@@ -875,6 +935,21 @@ main (int argc, char **argv)
 24.2260 + 
 24.2261 +   atexit (close_stdout);
 24.2262 + 
 24.2263 ++/* Define which functions are used, the ones for single byte locale or the ones
 24.2264 ++   for multibyte locale. */
 24.2265 ++#if HAVE_MBRTOWC
 24.2266 ++  if (MB_CUR_MAX > 1)
 24.2267 ++    {
 24.2268 ++      print_char = print_char_multi;
 24.2269 ++      char_to_clump = char_to_clump_multi;
 24.2270 ++    }
 24.2271 ++  else
 24.2272 ++#endif
 24.2273 ++    {
 24.2274 ++      print_char = print_char_single;
 24.2275 ++      char_to_clump = char_to_clump_single;
 24.2276 ++    }
 24.2277 ++
 24.2278 +   n_files = 0;
 24.2279 +   file_names = (argc > 1
 24.2280 +                 ? xnmalloc (argc - 1, sizeof (char *))
 24.2281 +@@ -951,8 +1026,12 @@ main (int argc, char **argv)
 24.2282 +           break;
 24.2283 +         case 'e':
 24.2284 +           if (optarg)
 24.2285 +-            getoptarg (optarg, 'e', &input_tab_char,
 24.2286 +-                       &chars_per_input_tab);
 24.2287 ++            {
 24.2288 ++              int dummy_length, dummy_width;
 24.2289 ++
 24.2290 ++              getoptarg (optarg, 'e', input_tab_char, &dummy_length,
 24.2291 ++                         &dummy_width, &chars_per_input_tab);
 24.2292 ++            }
 24.2293 +           /* Could check tab width > 0. */
 24.2294 +           untabify_input = true;
 24.2295 +           break;
 24.2296 +@@ -965,8 +1044,12 @@ main (int argc, char **argv)
 24.2297 +           break;
 24.2298 +         case 'i':
 24.2299 +           if (optarg)
 24.2300 +-            getoptarg (optarg, 'i', &output_tab_char,
 24.2301 +-                       &chars_per_output_tab);
 24.2302 ++            {
 24.2303 ++              int dummy_width;
 24.2304 ++
 24.2305 ++              getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length,
 24.2306 ++                         &dummy_width, &chars_per_output_tab);
 24.2307 ++            }
 24.2308 +           /* Could check tab width > 0. */
 24.2309 +           tabify_output = true;
 24.2310 +           break;
 24.2311 +@@ -984,8 +1067,8 @@ main (int argc, char **argv)
 24.2312 +         case 'n':
 24.2313 +           numbered_lines = true;
 24.2314 +           if (optarg)
 24.2315 +-            getoptarg (optarg, 'n', &number_separator,
 24.2316 +-                       &chars_per_number);
 24.2317 ++            getoptarg (optarg, 'n', number_separator, &number_separator_length,
 24.2318 ++                       &number_separator_width, &chars_per_number);
 24.2319 +           break;
 24.2320 +         case 'N':
 24.2321 +           skip_count = false;
 24.2322 +@@ -1010,6 +1093,7 @@ main (int argc, char **argv)
 24.2323 +           /* Reset an additional input of -s, -S dominates -s */
 24.2324 +           col_sep_string = "";
 24.2325 +           col_sep_length = 0;
 24.2326 ++          col_sep_width = 0;
 24.2327 +           use_col_separator = true;
 24.2328 +           if (optarg)
 24.2329 +             separator_string (optarg);
 24.2330 +@@ -1166,10 +1250,45 @@ getoptnum (const char *n_str, int min, i
 24.2331 +    a number. */
 24.2332 + 
 24.2333 + static void
 24.2334 +-getoptarg (char *arg, char switch_char, char *character, int *number)
 24.2335 ++getoptarg (char *arg, char switch_char, char *character, int *character_length,
 24.2336 ++           int *character_width, int *number)
 24.2337 + {
 24.2338 +   if (!ISDIGIT (*arg))
 24.2339 +-    *character = *arg++;
 24.2340 ++    {
 24.2341 ++#ifdef HAVE_MBRTOWC
 24.2342 ++      if (MB_CUR_MAX > 1)        /* for multibyte locale. */
 24.2343 ++        {
 24.2344 ++          wchar_t wc;
 24.2345 ++          size_t mblength;
 24.2346 ++          int width;
 24.2347 ++          mbstate_t state = {'\0'};
 24.2348 ++
 24.2349 ++          mblength = mbrtowc (&wc, arg, strnlen(arg, MB_LEN_MAX), &state);
 24.2350 ++
 24.2351 ++          if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.2352 ++            {
 24.2353 ++              *character_length = 1;
 24.2354 ++              *character_width = 1;
 24.2355 ++            }
 24.2356 ++          else
 24.2357 ++            {
 24.2358 ++              *character_length = (mblength < 1) ? 1 : mblength;
 24.2359 ++              width = wcwidth (wc);
 24.2360 ++              *character_width = (width < 0) ? 0 : width;
 24.2361 ++            }
 24.2362 ++
 24.2363 ++          strncpy (character, arg, *character_length);
 24.2364 ++          arg += *character_length;
 24.2365 ++        }
 24.2366 ++      else                        /* for single byte locale. */
 24.2367 ++#endif
 24.2368 ++        {
 24.2369 ++          *character = *arg++;
 24.2370 ++          *character_length = 1;
 24.2371 ++          *character_width = 1;
 24.2372 ++        }
 24.2373 ++    }
 24.2374 ++
 24.2375 +   if (*arg)
 24.2376 +     {
 24.2377 +       long int tmp_long;
 24.2378 +@@ -1191,6 +1310,11 @@ static void
 24.2379 + init_parameters (int number_of_files)
 24.2380 + {
 24.2381 +   int chars_used_by_number = 0;
 24.2382 ++  int mb_len = 1;
 24.2383 ++#if HAVE_MBRTOWC
 24.2384 ++  if (MB_CUR_MAX > 1)
 24.2385 ++    mb_len = MB_LEN_MAX;
 24.2386 ++#endif
 24.2387 + 
 24.2388 +   lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
 24.2389 +   if (lines_per_body <= 0)
 24.2390 +@@ -1228,7 +1352,7 @@ init_parameters (int number_of_files)
 24.2391 +           else
 24.2392 +             col_sep_string = column_separator;
 24.2393 + 
 24.2394 +-          col_sep_length = 1;
 24.2395 ++          col_sep_length = col_sep_width = 1;
 24.2396 +           use_col_separator = true;
 24.2397 +         }
 24.2398 +       /* It's rather pointless to define a TAB separator with column
 24.2399 +@@ -1258,11 +1382,11 @@ init_parameters (int number_of_files)
 24.2400 +              + TAB_WIDTH (chars_per_input_tab, chars_per_number);   */
 24.2401 + 
 24.2402 +       /* Estimate chars_per_text without any margin and keep it constant. */
 24.2403 +-      if (number_separator == '\t')
 24.2404 ++      if (number_separator[0] == '\t')
 24.2405 +         number_width = (chars_per_number
 24.2406 +                         + TAB_WIDTH (chars_per_default_tab, chars_per_number));
 24.2407 +       else
 24.2408 +-        number_width = chars_per_number + 1;
 24.2409 ++        number_width = chars_per_number + number_separator_width;
 24.2410 + 
 24.2411 +       /* The number is part of the column width unless we are
 24.2412 +          printing files in parallel. */
 24.2413 +@@ -1271,7 +1395,7 @@ init_parameters (int number_of_files)
 24.2414 +     }
 24.2415 + 
 24.2416 +   int sep_chars, useful_chars;
 24.2417 +-  if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_length, &sep_chars))
 24.2418 ++  if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_width, &sep_chars))
 24.2419 +     sep_chars = INT_MAX;
 24.2420 +   if (INT_SUBTRACT_WRAPV (chars_per_line - chars_used_by_number, sep_chars,
 24.2421 +                           &useful_chars))
 24.2422 +@@ -1294,7 +1418,7 @@ init_parameters (int number_of_files)
 24.2423 +      We've to use 8 as the lower limit, if we use chars_per_default_tab = 8
 24.2424 +      to expand a tab which is not an input_tab-char. */
 24.2425 +   free (clump_buff);
 24.2426 +-  clump_buff = xmalloc (MAX (8, chars_per_input_tab));
 24.2427 ++  clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab));
 24.2428 + }
 24.2429 + 
 24.2430 + /* Open the necessary files,
 24.2431 +@@ -1402,7 +1526,7 @@ init_funcs (void)
 24.2432 + 
 24.2433 +   /* Enlarge p->start_position of first column to use the same form of
 24.2434 +      padding_not_printed with all columns. */
 24.2435 +-  h = h + col_sep_length;
 24.2436 ++  h = h + col_sep_width;
 24.2437 + 
 24.2438 +   /* This loop takes care of all but the rightmost column. */
 24.2439 + 
 24.2440 +@@ -1436,7 +1560,7 @@ init_funcs (void)
 24.2441 +         }
 24.2442 +       else
 24.2443 +         {
 24.2444 +-          h = h_next + col_sep_length;
 24.2445 ++          h = h_next + col_sep_width;
 24.2446 +           h_next = h + chars_per_column;
 24.2447 +         }
 24.2448 +     }
 24.2449 +@@ -1727,9 +1851,9 @@ static void
 24.2450 + align_column (COLUMN *p)
 24.2451 + {
 24.2452 +   padding_not_printed = p->start_position;
 24.2453 +-  if (col_sep_length < padding_not_printed)
 24.2454 ++  if (col_sep_width < padding_not_printed)
 24.2455 +     {
 24.2456 +-      pad_across_to (padding_not_printed - col_sep_length);
 24.2457 ++      pad_across_to (padding_not_printed - col_sep_width);
 24.2458 +       padding_not_printed = ANYWHERE;
 24.2459 +     }
 24.2460 + 
 24.2461 +@@ -2004,13 +2128,13 @@ store_char (char c)
 24.2462 +       /* May be too generous. */
 24.2463 +       buff = X2REALLOC (buff, &buff_allocated);
 24.2464 +     }
 24.2465 +-  buff[buff_current++] = c;
 24.2466 ++  buff[buff_current++] = (unsigned char) c;
 24.2467 + }
 24.2468 + 
 24.2469 + static void
 24.2470 + add_line_number (COLUMN *p)
 24.2471 + {
 24.2472 +-  int i;
 24.2473 ++  int i, j;
 24.2474 +   char *s;
 24.2475 +   int num_width;
 24.2476 + 
 24.2477 +@@ -2027,22 +2151,24 @@ add_line_number (COLUMN *p)
 24.2478 +       /* Tabification is assumed for multiple columns, also for n-separators,
 24.2479 +          but 'default n-separator = TAB' hasn't been given priority over
 24.2480 +          equal column_width also specified by POSIX. */
 24.2481 +-      if (number_separator == '\t')
 24.2482 ++      if (number_separator[0] == '\t')
 24.2483 +         {
 24.2484 +           i = number_width - chars_per_number;
 24.2485 +           while (i-- > 0)
 24.2486 +             (p->char_func) (' ');
 24.2487 +         }
 24.2488 +       else
 24.2489 +-        (p->char_func) (number_separator);
 24.2490 ++        for (j = 0; j < number_separator_length; j++)
 24.2491 ++          (p->char_func) (number_separator[j]);
 24.2492 +     }
 24.2493 +   else
 24.2494 +     /* To comply with POSIX, we avoid any expansion of default TAB
 24.2495 +        separator with a single column output. No column_width requirement
 24.2496 +        has to be considered. */
 24.2497 +     {
 24.2498 +-      (p->char_func) (number_separator);
 24.2499 +-      if (number_separator == '\t')
 24.2500 ++      for (j = 0; j < number_separator_length; j++)
 24.2501 ++        (p->char_func) (number_separator[j]);
 24.2502 ++      if (number_separator[0] == '\t')
 24.2503 +         output_position = POS_AFTER_TAB (chars_per_output_tab,
 24.2504 +                           output_position);
 24.2505 +     }
 24.2506 +@@ -2203,7 +2329,7 @@ print_white_space (void)
 24.2507 +   while (goal - h_old > 1
 24.2508 +          && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
 24.2509 +     {
 24.2510 +-      putchar (output_tab_char);
 24.2511 ++      fwrite (output_tab_char, sizeof(char), output_tab_char_length, stdout);
 24.2512 +       h_old = h_new;
 24.2513 +     }
 24.2514 +   while (++h_old <= goal)
 24.2515 +@@ -2223,6 +2349,7 @@ print_sep_string (void)
 24.2516 + {
 24.2517 +   char const *s = col_sep_string;
 24.2518 +   int l = col_sep_length;
 24.2519 ++  int not_space_flag;
 24.2520 + 
 24.2521 +   if (separators_not_printed <= 0)
 24.2522 +     {
 24.2523 +@@ -2234,6 +2361,7 @@ print_sep_string (void)
 24.2524 +     {
 24.2525 +       for (; separators_not_printed > 0; --separators_not_printed)
 24.2526 +         {
 24.2527 ++          not_space_flag = 0;
 24.2528 +           while (l-- > 0)
 24.2529 +             {
 24.2530 +               /* 3 types of sep_strings: spaces only, spaces and chars,
 24.2531 +@@ -2247,12 +2375,15 @@ print_sep_string (void)
 24.2532 +                 }
 24.2533 +               else
 24.2534 +                 {
 24.2535 ++                  not_space_flag = 1;
 24.2536 +                   if (spaces_not_printed > 0)
 24.2537 +                     print_white_space ();
 24.2538 +                   putchar (*s++);
 24.2539 +-                  ++output_position;
 24.2540 +                 }
 24.2541 +             }
 24.2542 ++          if (not_space_flag)
 24.2543 ++            output_position += col_sep_width;
 24.2544 ++
 24.2545 +           /* sep_string ends with some spaces */
 24.2546 +           if (spaces_not_printed > 0)
 24.2547 +             print_white_space ();
 24.2548 +@@ -2280,7 +2411,7 @@ print_clump (COLUMN *p, int n, char *clu
 24.2549 +    required number of tabs and spaces. */
 24.2550 + 
 24.2551 + static void
 24.2552 +-print_char (char c)
 24.2553 ++print_char_single (char c)
 24.2554 + {
 24.2555 +   if (tabify_output)
 24.2556 +     {
 24.2557 +@@ -2304,6 +2435,74 @@ print_char (char c)
 24.2558 +   putchar (c);
 24.2559 + }
 24.2560 + 
 24.2561 ++#ifdef HAVE_MBRTOWC
 24.2562 ++static void
 24.2563 ++print_char_multi (char c)
 24.2564 ++{
 24.2565 ++  static size_t mbc_pos = 0;
 24.2566 ++  static char mbc[MB_LEN_MAX] = {'\0'};
 24.2567 ++  static mbstate_t state = {'\0'};
 24.2568 ++  mbstate_t state_bak;
 24.2569 ++  wchar_t wc;
 24.2570 ++  size_t mblength;
 24.2571 ++  int width;
 24.2572 ++
 24.2573 ++  if (tabify_output)
 24.2574 ++    {
 24.2575 ++      state_bak = state;
 24.2576 ++      mbc[mbc_pos++] = c;
 24.2577 ++      mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 24.2578 ++
 24.2579 ++      while (mbc_pos > 0)
 24.2580 ++        {
 24.2581 ++          switch (mblength)
 24.2582 ++            {
 24.2583 ++            case (size_t)-2:
 24.2584 ++              state = state_bak;
 24.2585 ++              return;
 24.2586 ++
 24.2587 ++            case (size_t)-1:
 24.2588 ++              state = state_bak;
 24.2589 ++              ++output_position;
 24.2590 ++              putchar (mbc[0]);
 24.2591 ++              memmove (mbc, mbc + 1, MB_CUR_MAX - 1);
 24.2592 ++              --mbc_pos;
 24.2593 ++              break;
 24.2594 ++
 24.2595 ++            case 0:
 24.2596 ++              mblength = 1;
 24.2597 ++
 24.2598 ++            default:
 24.2599 ++              if (wc == L' ')
 24.2600 ++                {
 24.2601 ++                  memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 24.2602 ++                  --mbc_pos;
 24.2603 ++                  ++spaces_not_printed;
 24.2604 ++                  return;
 24.2605 ++                }
 24.2606 ++              else if (spaces_not_printed > 0)
 24.2607 ++                print_white_space ();
 24.2608 ++
 24.2609 ++              /* Nonprintables are assumed to have width 0, except L'\b'. */
 24.2610 ++              if ((width = wcwidth (wc)) < 1)
 24.2611 ++                {
 24.2612 ++                  if (wc == L'\b')
 24.2613 ++                    --output_position;
 24.2614 ++                }
 24.2615 ++              else
 24.2616 ++                output_position += width;
 24.2617 ++
 24.2618 ++              fwrite (mbc, sizeof(char), mblength, stdout);
 24.2619 ++              memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 24.2620 ++              mbc_pos -= mblength;
 24.2621 ++            }
 24.2622 ++        }
 24.2623 ++      return;
 24.2624 ++    }
 24.2625 ++  putchar (c);
 24.2626 ++}
 24.2627 ++#endif
 24.2628 ++
 24.2629 + /* Skip to page PAGE before printing.
 24.2630 +    PAGE may be larger than total number of pages. */
 24.2631 + 
 24.2632 +@@ -2483,9 +2682,9 @@ read_line (COLUMN *p)
 24.2633 +           align_empty_cols = false;
 24.2634 +         }
 24.2635 + 
 24.2636 +-      if (col_sep_length < padding_not_printed)
 24.2637 ++      if (col_sep_width < padding_not_printed)
 24.2638 +         {
 24.2639 +-          pad_across_to (padding_not_printed - col_sep_length);
 24.2640 ++          pad_across_to (padding_not_printed - col_sep_width);
 24.2641 +           padding_not_printed = ANYWHERE;
 24.2642 +         }
 24.2643 + 
 24.2644 +@@ -2555,7 +2754,7 @@ print_stored (COLUMN *p)
 24.2645 +   int i;
 24.2646 + 
 24.2647 +   int line = p->current_line++;
 24.2648 +-  char *first = &buff[line_vector[line]];
 24.2649 ++  unsigned char *first = &buff[line_vector[line]];
 24.2650 +   /* FIXME
 24.2651 +      UMR: Uninitialized memory read:
 24.2652 +      * This is occurring while in:
 24.2653 +@@ -2567,7 +2766,7 @@ print_stored (COLUMN *p)
 24.2654 +      xmalloc        [xmalloc.c:94]
 24.2655 +      init_store_cols [pr.c:1648]
 24.2656 +      */
 24.2657 +-  char *last = &buff[line_vector[line + 1]];
 24.2658 ++  unsigned char *last = &buff[line_vector[line + 1]];
 24.2659 + 
 24.2660 +   pad_vertically = true;
 24.2661 + 
 24.2662 +@@ -2586,9 +2785,9 @@ print_stored (COLUMN *p)
 24.2663 +         }
 24.2664 +     }
 24.2665 + 
 24.2666 +-  if (col_sep_length < padding_not_printed)
 24.2667 ++  if (col_sep_width < padding_not_printed)
 24.2668 +     {
 24.2669 +-      pad_across_to (padding_not_printed - col_sep_length);
 24.2670 ++      pad_across_to (padding_not_printed - col_sep_width);
 24.2671 +       padding_not_printed = ANYWHERE;
 24.2672 +     }
 24.2673 + 
 24.2674 +@@ -2601,8 +2800,8 @@ print_stored (COLUMN *p)
 24.2675 +   if (spaces_not_printed == 0)
 24.2676 +     {
 24.2677 +       output_position = p->start_position + end_vector[line];
 24.2678 +-      if (p->start_position - col_sep_length == chars_per_margin)
 24.2679 +-        output_position -= col_sep_length;
 24.2680 ++      if (p->start_position - col_sep_width == chars_per_margin)
 24.2681 ++        output_position -= col_sep_width;
 24.2682 +     }
 24.2683 + 
 24.2684 +   return true;
 24.2685 +@@ -2621,7 +2820,7 @@ print_stored (COLUMN *p)
 24.2686 +    number of characters is 1.) */
 24.2687 + 
 24.2688 + static int
 24.2689 +-char_to_clump (char c)
 24.2690 ++char_to_clump_single (char c)
 24.2691 + {
 24.2692 +   unsigned char uc = c;
 24.2693 +   char *s = clump_buff;
 24.2694 +@@ -2631,10 +2830,10 @@ char_to_clump (char c)
 24.2695 +   int chars;
 24.2696 +   int chars_per_c = 8;
 24.2697 + 
 24.2698 +-  if (c == input_tab_char)
 24.2699 ++  if (c == input_tab_char[0])
 24.2700 +     chars_per_c = chars_per_input_tab;
 24.2701 + 
 24.2702 +-  if (c == input_tab_char || c == '\t')
 24.2703 ++  if (c == input_tab_char[0] || c == '\t')
 24.2704 +     {
 24.2705 +       width = TAB_WIDTH (chars_per_c, input_position);
 24.2706 + 
 24.2707 +@@ -2715,6 +2914,164 @@ char_to_clump (char c)
 24.2708 +   return chars;
 24.2709 + }
 24.2710 + 
 24.2711 ++#ifdef HAVE_MBRTOWC
 24.2712 ++static int
 24.2713 ++char_to_clump_multi (char c)
 24.2714 ++{
 24.2715 ++  static size_t mbc_pos = 0;
 24.2716 ++  static char mbc[MB_LEN_MAX] = {'\0'};
 24.2717 ++  static mbstate_t state = {'\0'};
 24.2718 ++  mbstate_t state_bak;
 24.2719 ++  wchar_t wc;
 24.2720 ++  size_t mblength;
 24.2721 ++  int wc_width;
 24.2722 ++  register char *s = clump_buff;
 24.2723 ++  register int i, j;
 24.2724 ++  char esc_buff[4];
 24.2725 ++  int width;
 24.2726 ++  int chars;
 24.2727 ++  int chars_per_c = 8;
 24.2728 ++
 24.2729 ++  state_bak = state;
 24.2730 ++  mbc[mbc_pos++] = c;
 24.2731 ++  mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 24.2732 ++
 24.2733 ++  width = 0;
 24.2734 ++  chars = 0;
 24.2735 ++  while (mbc_pos > 0)
 24.2736 ++    {
 24.2737 ++      switch (mblength)
 24.2738 ++        {
 24.2739 ++        case (size_t)-2:
 24.2740 ++          state = state_bak;
 24.2741 ++          return 0;
 24.2742 ++
 24.2743 ++        case (size_t)-1:
 24.2744 ++          state = state_bak;
 24.2745 ++          mblength = 1;
 24.2746 ++
 24.2747 ++          if (use_esc_sequence || use_cntrl_prefix)
 24.2748 ++            {
 24.2749 ++              width = +4;
 24.2750 ++              chars = +4;
 24.2751 ++              *s++ = '\\';
 24.2752 ++              sprintf (esc_buff, "%03o", (unsigned char) mbc[0]);
 24.2753 ++              for (i = 0; i <= 2; ++i)
 24.2754 ++                *s++ = (int) esc_buff[i];
 24.2755 ++            }
 24.2756 ++          else
 24.2757 ++            {
 24.2758 ++              width += 1;
 24.2759 ++              chars += 1;
 24.2760 ++              *s++ = mbc[0];
 24.2761 ++            }
 24.2762 ++          break;
 24.2763 ++
 24.2764 ++        case 0:
 24.2765 ++          mblength = 1;
 24.2766 ++                /* Fall through */
 24.2767 ++
 24.2768 ++        default:
 24.2769 ++          if (memcmp (mbc, input_tab_char, mblength) == 0)
 24.2770 ++            chars_per_c = chars_per_input_tab;
 24.2771 ++
 24.2772 ++          if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t')
 24.2773 ++            {
 24.2774 ++              int  width_inc;
 24.2775 ++
 24.2776 ++              width_inc = TAB_WIDTH (chars_per_c, input_position);
 24.2777 ++              width += width_inc;
 24.2778 ++
 24.2779 ++              if (untabify_input)
 24.2780 ++                {
 24.2781 ++                  for (i = width_inc; i; --i)
 24.2782 ++                    *s++ = ' ';
 24.2783 ++                  chars += width_inc;
 24.2784 ++                }
 24.2785 ++              else
 24.2786 ++                {
 24.2787 ++                  for (i = 0; i <  mblength; i++)
 24.2788 ++                    *s++ = mbc[i];
 24.2789 ++                  chars += mblength;
 24.2790 ++                }
 24.2791 ++            }
 24.2792 ++          else if ((wc_width = wcwidth (wc)) < 1)
 24.2793 ++            {
 24.2794 ++              if (use_esc_sequence)
 24.2795 ++                {
 24.2796 ++                  for (i = 0; i < mblength; i++)
 24.2797 ++                    {
 24.2798 ++                      width += 4;
 24.2799 ++                      chars += 4;
 24.2800 ++                      *s++ = '\\';
 24.2801 ++                      sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 24.2802 ++                      for (j = 0; j <= 2; ++j)
 24.2803 ++                        *s++ = (int) esc_buff[j];
 24.2804 ++                    }
 24.2805 ++                }
 24.2806 ++              else if (use_cntrl_prefix)
 24.2807 ++                {
 24.2808 ++                  if (wc < 0200)
 24.2809 ++                    {
 24.2810 ++                      width += 2;
 24.2811 ++                      chars += 2;
 24.2812 ++                      *s++ = '^';
 24.2813 ++                      *s++ = wc ^ 0100;
 24.2814 ++                    }
 24.2815 ++                  else
 24.2816 ++                    {
 24.2817 ++                      for (i = 0; i < mblength; i++)
 24.2818 ++                        {
 24.2819 ++                          width += 4;
 24.2820 ++                          chars += 4;
 24.2821 ++                          *s++ = '\\';
 24.2822 ++                          sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 24.2823 ++                          for (j = 0; j <= 2; ++j)
 24.2824 ++                            *s++ = (int) esc_buff[j];
 24.2825 ++                        }
 24.2826 ++                    }
 24.2827 ++                }
 24.2828 ++              else if (wc == L'\b')
 24.2829 ++                {
 24.2830 ++                  width += -1;
 24.2831 ++                  chars += 1;
 24.2832 ++                  *s++ = c;
 24.2833 ++                }
 24.2834 ++              else
 24.2835 ++                {
 24.2836 ++                  width += 0;
 24.2837 ++                  chars += mblength;
 24.2838 ++                  for (i = 0; i < mblength; i++)
 24.2839 ++                    *s++ = mbc[i];
 24.2840 ++                }
 24.2841 ++            }
 24.2842 ++          else
 24.2843 ++            {
 24.2844 ++              width += wc_width;
 24.2845 ++              chars += mblength;
 24.2846 ++              for (i = 0; i < mblength; i++)
 24.2847 ++                *s++ = mbc[i];
 24.2848 ++            }
 24.2849 ++        }
 24.2850 ++      memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 24.2851 ++      mbc_pos -= mblength;
 24.2852 ++    }
 24.2853 ++
 24.2854 ++  /* Too many backspaces must put us in position 0 -- never negative. */
 24.2855 ++  if (width < 0 && input_position == 0)
 24.2856 ++    {
 24.2857 ++      chars = 0;
 24.2858 ++      input_position = 0;
 24.2859 ++    }
 24.2860 ++  else if (width < 0 && input_position <= -width)
 24.2861 ++    input_position = 0;
 24.2862 ++  else
 24.2863 ++   input_position += width;
 24.2864 ++
 24.2865 ++  return chars;
 24.2866 ++}
 24.2867 ++#endif
 24.2868 ++
 24.2869 + /* We've just printed some files and need to clean up things before
 24.2870 +    looking for more options and printing the next batch of files.
 24.2871 + 
 24.2872 +diff -Naurp coreutils-8.27-orig/src/sort.c coreutils-8.27/src/sort.c
 24.2873 +--- coreutils-8.27-orig/src/sort.c	2017-01-01 16:34:24.000000000 -0600
 24.2874 ++++ coreutils-8.27/src/sort.c	2017-03-11 23:49:22.416505389 -0600
 24.2875 +@@ -29,6 +29,14 @@
 24.2876 + #include <sys/wait.h>
 24.2877 + #include <signal.h>
 24.2878 + #include <assert.h>
 24.2879 ++#if HAVE_WCHAR_H
 24.2880 ++# include <wchar.h>
 24.2881 ++#endif
 24.2882 ++/* Get isw* functions. */
 24.2883 ++#if HAVE_WCTYPE_H
 24.2884 ++# include <wctype.h>
 24.2885 ++#endif
 24.2886 ++
 24.2887 + #include "system.h"
 24.2888 + #include "argmatch.h"
 24.2889 + #include "die.h"
 24.2890 +@@ -165,14 +173,39 @@ static int decimal_point;
 24.2891 + /* Thousands separator; if -1, then there isn't one.  */
 24.2892 + static int thousands_sep;
 24.2893 + 
 24.2894 ++/* True if -f is specified.  */
 24.2895 ++static bool folding;
 24.2896 ++
 24.2897 + /* Nonzero if the corresponding locales are hard.  */
 24.2898 + static bool hard_LC_COLLATE;
 24.2899 +-#if HAVE_NL_LANGINFO
 24.2900 ++#if HAVE_LANGINFO_CODESET
 24.2901 + static bool hard_LC_TIME;
 24.2902 + #endif
 24.2903 + 
 24.2904 + #define NONZERO(x) ((x) != 0)
 24.2905 + 
 24.2906 ++/* get a multibyte character's byte length. */
 24.2907 ++#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE)                        \
 24.2908 ++  do                                                                        \
 24.2909 ++    {                                                                        \
 24.2910 ++      wchar_t wc;                                                        \
 24.2911 ++      mbstate_t state_bak;                                                \
 24.2912 ++                                                                        \
 24.2913 ++      state_bak = STATE;                                                \
 24.2914 ++      mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE);                        \
 24.2915 ++                                                                        \
 24.2916 ++      switch (MBLENGTH)                                                        \
 24.2917 ++        {                                                                \
 24.2918 ++        case (size_t)-1:                                                \
 24.2919 ++        case (size_t)-2:                                                \
 24.2920 ++          STATE = state_bak;                                                \
 24.2921 ++                /* Fall through. */                                        \
 24.2922 ++        case 0:                                                                \
 24.2923 ++          MBLENGTH = 1;                                                        \
 24.2924 ++      }                                                                        \
 24.2925 ++    }                                                                        \
 24.2926 ++  while (0)
 24.2927 ++
 24.2928 + /* The kind of blanks for '-b' to skip in various options. */
 24.2929 + enum blanktype { bl_start, bl_end, bl_both };
 24.2930 + 
 24.2931 +@@ -346,13 +379,11 @@ static bool reverse;
 24.2932 +    they were read if all keys compare equal.  */
 24.2933 + static bool stable;
 24.2934 + 
 24.2935 +-/* If TAB has this value, blanks separate fields.  */
 24.2936 +-enum { TAB_DEFAULT = CHAR_MAX + 1 };
 24.2937 +-
 24.2938 +-/* Tab character separating fields.  If TAB_DEFAULT, then fields are
 24.2939 ++/* Tab character separating fields.  If tab_length is 0, then fields are
 24.2940 +    separated by the empty string between a non-blank character and a blank
 24.2941 +    character. */
 24.2942 +-static int tab = TAB_DEFAULT;
 24.2943 ++static char tab[MB_LEN_MAX + 1];
 24.2944 ++static size_t tab_length = 0;
 24.2945 + 
 24.2946 + /* Flag to remove consecutive duplicate lines from the output.
 24.2947 +    Only the last of a sequence of equal lines will be output. */
 24.2948 +@@ -811,6 +842,46 @@ reap_all (void)
 24.2949 +     reap (-1);
 24.2950 + }
 24.2951 + 
 24.2952 ++/* Function pointers. */
 24.2953 ++static void
 24.2954 ++(*inittables) (void);
 24.2955 ++static char *
 24.2956 ++(*begfield) (const struct line*, const struct keyfield *);
 24.2957 ++static char *
 24.2958 ++(*limfield) (const struct line*, const struct keyfield *);
 24.2959 ++static void
 24.2960 ++(*skipblanks) (char **ptr, char *lim);
 24.2961 ++static int
 24.2962 ++(*getmonth) (char const *, size_t, char **);
 24.2963 ++static int
 24.2964 ++(*keycompare) (const struct line *, const struct line *);
 24.2965 ++static int
 24.2966 ++(*numcompare) (const char *, const char *);
 24.2967 ++
 24.2968 ++/* Test for white space multibyte character.
 24.2969 ++   Set LENGTH the byte length of investigated multibyte character. */
 24.2970 ++#if HAVE_MBRTOWC
 24.2971 ++static int
 24.2972 ++ismbblank (const char *str, size_t len, size_t *length)
 24.2973 ++{
 24.2974 ++  size_t mblength;
 24.2975 ++  wchar_t wc;
 24.2976 ++  mbstate_t state;
 24.2977 ++
 24.2978 ++  memset (&state, '\0', sizeof(mbstate_t));
 24.2979 ++  mblength = mbrtowc (&wc, str, len, &state);
 24.2980 ++
 24.2981 ++  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 24.2982 ++    {
 24.2983 ++      *length = 1;
 24.2984 ++      return 0;
 24.2985 ++    }
 24.2986 ++
 24.2987 ++  *length = (mblength < 1) ? 1 : mblength;
 24.2988 ++  return iswblank (wc) || wc == '\n';
 24.2989 ++}
 24.2990 ++#endif
 24.2991 ++
 24.2992 + /* Clean up any remaining temporary files.  */
 24.2993 + 
 24.2994 + static void
 24.2995 +@@ -1255,7 +1326,7 @@ zaptemp (char const *name)
 24.2996 +   free (node);
 24.2997 + }
 24.2998 + 
 24.2999 +-#if HAVE_NL_LANGINFO
 24.3000 ++#if HAVE_LANGINFO_CODESET
 24.3001 + 
 24.3002 + static int
 24.3003 + struct_month_cmp (void const *m1, void const *m2)
 24.3004 +@@ -1270,7 +1341,7 @@ struct_month_cmp (void const *m1, void c
 24.3005 + /* Initialize the character class tables. */
 24.3006 + 
 24.3007 + static void
 24.3008 +-inittables (void)
 24.3009 ++inittables_uni (void)
 24.3010 + {
 24.3011 +   size_t i;
 24.3012 + 
 24.3013 +@@ -1282,7 +1353,7 @@ inittables (void)
 24.3014 +       fold_toupper[i] = toupper (i);
 24.3015 +     }
 24.3016 + 
 24.3017 +-#if HAVE_NL_LANGINFO
 24.3018 ++#if HAVE_LANGINFO_CODESET
 24.3019 +   /* If we're not in the "C" locale, read different names for months.  */
 24.3020 +   if (hard_LC_TIME)
 24.3021 +     {
 24.3022 +@@ -1364,6 +1435,84 @@ specify_nmerge (int oi, char c, char con
 24.3023 +     xstrtol_fatal (e, oi, c, long_options, s);
 24.3024 + }
 24.3025 + 
 24.3026 ++#if HAVE_MBRTOWC
 24.3027 ++static void
 24.3028 ++inittables_mb (void)
 24.3029 ++{
 24.3030 ++  int i, j, k, l;
 24.3031 ++  char *name, *s, *lc_time, *lc_ctype;
 24.3032 ++  size_t s_len, mblength;
 24.3033 ++  char mbc[MB_LEN_MAX];
 24.3034 ++  wchar_t wc, pwc;
 24.3035 ++  mbstate_t state_mb, state_wc;
 24.3036 ++
 24.3037 ++  lc_time = setlocale (LC_TIME, "");
 24.3038 ++  if (lc_time)
 24.3039 ++    lc_time = xstrdup (lc_time);
 24.3040 ++
 24.3041 ++  lc_ctype = setlocale (LC_CTYPE, "");
 24.3042 ++  if (lc_ctype)
 24.3043 ++    lc_ctype = xstrdup (lc_ctype);
 24.3044 ++
 24.3045 ++  if (lc_time && lc_ctype)
 24.3046 ++    /* temporarily set LC_CTYPE to match LC_TIME, so that we can convert
 24.3047 ++     * the names of months to upper case */
 24.3048 ++    setlocale (LC_CTYPE, lc_time);
 24.3049 ++
 24.3050 ++  for (i = 0; i < MONTHS_PER_YEAR; i++)
 24.3051 ++    {
 24.3052 ++      s = (char *) nl_langinfo (ABMON_1 + i);
 24.3053 ++      s_len = strlen (s);
 24.3054 ++      monthtab[i].name = name = (char *) xmalloc (s_len + 1);
 24.3055 ++      monthtab[i].val = i + 1;
 24.3056 ++
 24.3057 ++      memset (&state_mb, '\0', sizeof (mbstate_t));
 24.3058 ++      memset (&state_wc, '\0', sizeof (mbstate_t));
 24.3059 ++
 24.3060 ++      for (j = 0; j < s_len;)
 24.3061 ++        {
 24.3062 ++          if (!ismbblank (s + j, s_len - j, &mblength))
 24.3063 ++            break;
 24.3064 ++          j += mblength;
 24.3065 ++        }
 24.3066 ++
 24.3067 ++      for (k = 0; j < s_len;)
 24.3068 ++        {
 24.3069 ++          mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb);
 24.3070 ++          assert (mblength != (size_t)-1 && mblength != (size_t)-2);
 24.3071 ++          if (mblength == 0)
 24.3072 ++            break;
 24.3073 ++
 24.3074 ++          pwc = towupper (wc);
 24.3075 ++          if (pwc == wc)
 24.3076 ++            {
 24.3077 ++              memcpy (mbc, s + j, mblength);
 24.3078 ++              j += mblength;
 24.3079 ++            }
 24.3080 ++          else
 24.3081 ++            {
 24.3082 ++              j += mblength;
 24.3083 ++              mblength = wcrtomb (mbc, pwc, &state_wc);
 24.3084 ++              assert (mblength != (size_t)0 && mblength != (size_t)-1);
 24.3085 ++            }
 24.3086 ++
 24.3087 ++          for (l = 0; l < mblength; l++)
 24.3088 ++            name[k++] = mbc[l];
 24.3089 ++        }
 24.3090 ++      name[k] = '\0';
 24.3091 ++    }
 24.3092 ++  qsort ((void *) monthtab, MONTHS_PER_YEAR,
 24.3093 ++      sizeof (struct month), struct_month_cmp);
 24.3094 ++
 24.3095 ++  if (lc_time && lc_ctype)
 24.3096 ++    /* restore the original locales */
 24.3097 ++    setlocale (LC_CTYPE, lc_ctype);
 24.3098 ++
 24.3099 ++  free (lc_ctype);
 24.3100 ++  free (lc_time);
 24.3101 ++}
 24.3102 ++#endif
 24.3103 ++
 24.3104 + /* Specify the amount of main memory to use when sorting.  */
 24.3105 + static void
 24.3106 + specify_sort_size (int oi, char c, char const *s)
 24.3107 +@@ -1597,7 +1746,7 @@ buffer_linelim (struct buffer const *buf
 24.3108 +    by KEY in LINE. */
 24.3109 + 
 24.3110 + static char *
 24.3111 +-begfield (struct line const *line, struct keyfield const *key)
 24.3112 ++begfield_uni (const struct line *line, const struct keyfield *key)
 24.3113 + {
 24.3114 +   char *ptr = line->text, *lim = ptr + line->length - 1;
 24.3115 +   size_t sword = key->sword;
 24.3116 +@@ -1606,10 +1755,10 @@ begfield (struct line const *line, struc
 24.3117 +   /* The leading field separator itself is included in a field when -t
 24.3118 +      is absent.  */
 24.3119 + 
 24.3120 +-  if (tab != TAB_DEFAULT)
 24.3121 ++  if (tab_length)
 24.3122 +     while (ptr < lim && sword--)
 24.3123 +       {
 24.3124 +-        while (ptr < lim && *ptr != tab)
 24.3125 ++        while (ptr < lim && *ptr != tab[0])
 24.3126 +           ++ptr;
 24.3127 +         if (ptr < lim)
 24.3128 +           ++ptr;
 24.3129 +@@ -1635,11 +1784,70 @@ begfield (struct line const *line, struc
 24.3130 +   return ptr;
 24.3131 + }
 24.3132 + 
 24.3133 ++#if HAVE_MBRTOWC
 24.3134 ++static char *
 24.3135 ++begfield_mb (const struct line *line, const struct keyfield *key)
 24.3136 ++{
 24.3137 ++  int i;
 24.3138 ++  char *ptr = line->text, *lim = ptr + line->length - 1;
 24.3139 ++  size_t sword = key->sword;
 24.3140 ++  size_t schar = key->schar;
 24.3141 ++  size_t mblength;
 24.3142 ++  mbstate_t state;
 24.3143 ++
 24.3144 ++  memset (&state, '\0', sizeof(mbstate_t));
 24.3145 ++
 24.3146 ++  if (tab_length)
 24.3147 ++    while (ptr < lim && sword--)
 24.3148 ++      {
 24.3149 ++        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 24.3150 ++          {
 24.3151 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3152 ++            ptr += mblength;
 24.3153 ++          }
 24.3154 ++        if (ptr < lim)
 24.3155 ++          {
 24.3156 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3157 ++            ptr += mblength;
 24.3158 ++          }
 24.3159 ++      }
 24.3160 ++  else
 24.3161 ++    while (ptr < lim && sword--)
 24.3162 ++      {
 24.3163 ++        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 24.3164 ++          ptr += mblength;
 24.3165 ++        if (ptr < lim)
 24.3166 ++          {
 24.3167 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3168 ++            ptr += mblength;
 24.3169 ++          }
 24.3170 ++        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 24.3171 ++          ptr += mblength;
 24.3172 ++      }
 24.3173 ++
 24.3174 ++  if (key->skipsblanks)
 24.3175 ++    while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 24.3176 ++      ptr += mblength;
 24.3177 ++
 24.3178 ++  for (i = 0; i < schar; i++)
 24.3179 ++    {
 24.3180 ++      GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3181 ++
 24.3182 ++      if (ptr + mblength > lim)
 24.3183 ++        break;
 24.3184 ++      else
 24.3185 ++        ptr += mblength;
 24.3186 ++    }
 24.3187 ++
 24.3188 ++  return ptr;
 24.3189 ++}
 24.3190 ++#endif
 24.3191 ++
 24.3192 + /* Return the limit of (a pointer to the first character after) the field
 24.3193 +    in LINE specified by KEY. */
 24.3194 + 
 24.3195 + static char *
 24.3196 +-limfield (struct line const *line, struct keyfield const *key)
 24.3197 ++limfield_uni (const struct line *line, const struct keyfield *key)
 24.3198 + {
 24.3199 +   char *ptr = line->text, *lim = ptr + line->length - 1;
 24.3200 +   size_t eword = key->eword, echar = key->echar;
 24.3201 +@@ -1654,10 +1862,10 @@ limfield (struct line const *line, struc
 24.3202 +      'beginning' is the first character following the delimiting TAB.
 24.3203 +      Otherwise, leave PTR pointing at the first 'blank' character after
 24.3204 +      the preceding field.  */
 24.3205 +-  if (tab != TAB_DEFAULT)
 24.3206 ++  if (tab_length)
 24.3207 +     while (ptr < lim && eword--)
 24.3208 +       {
 24.3209 +-        while (ptr < lim && *ptr != tab)
 24.3210 ++        while (ptr < lim && *ptr != tab[0])
 24.3211 +           ++ptr;
 24.3212 +         if (ptr < lim && (eword || echar))
 24.3213 +           ++ptr;
 24.3214 +@@ -1703,10 +1911,10 @@ limfield (struct line const *line, struc
 24.3215 +      */
 24.3216 + 
 24.3217 +   /* Make LIM point to the end of (one byte past) the current field.  */
 24.3218 +-  if (tab != TAB_DEFAULT)
 24.3219 ++  if (tab_length)
 24.3220 +     {
 24.3221 +       char *newlim;
 24.3222 +-      newlim = memchr (ptr, tab, lim - ptr);
 24.3223 ++      newlim = memchr (ptr, tab[0], lim - ptr);
 24.3224 +       if (newlim)
 24.3225 +         lim = newlim;
 24.3226 +     }
 24.3227 +@@ -1737,6 +1945,130 @@ limfield (struct line const *line, struc
 24.3228 +   return ptr;
 24.3229 + }
 24.3230 + 
 24.3231 ++#if HAVE_MBRTOWC
 24.3232 ++static char *
 24.3233 ++limfield_mb (const struct line *line, const struct keyfield *key)
 24.3234 ++{
 24.3235 ++  char *ptr = line->text, *lim = ptr + line->length - 1;
 24.3236 ++  size_t eword = key->eword, echar = key->echar;
 24.3237 ++  int i;
 24.3238 ++  size_t mblength;
 24.3239 ++  mbstate_t state;
 24.3240 ++
 24.3241 ++  if (echar == 0)
 24.3242 ++    eword++; /* skip all of end field. */
 24.3243 ++
 24.3244 ++  memset (&state, '\0', sizeof(mbstate_t));
 24.3245 ++
 24.3246 ++  if (tab_length)
 24.3247 ++    while (ptr < lim && eword--)
 24.3248 ++      {
 24.3249 ++        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 24.3250 ++          {
 24.3251 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3252 ++            ptr += mblength;
 24.3253 ++          }
 24.3254 ++        if (ptr < lim && (eword | echar))
 24.3255 ++          {
 24.3256 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3257 ++            ptr += mblength;
 24.3258 ++          }
 24.3259 ++      }
 24.3260 ++  else
 24.3261 ++    while (ptr < lim && eword--)
 24.3262 ++      {
 24.3263 ++        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 24.3264 ++          ptr += mblength;
 24.3265 ++        if (ptr < lim)
 24.3266 ++          {
 24.3267 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3268 ++            ptr += mblength;
 24.3269 ++          }
 24.3270 ++        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 24.3271 ++          ptr += mblength;
 24.3272 ++      }
 24.3273 ++
 24.3274 ++
 24.3275 ++# ifdef POSIX_UNSPECIFIED
 24.3276 ++  /* Make LIM point to the end of (one byte past) the current field.  */
 24.3277 ++  if (tab_length)
 24.3278 ++    {
 24.3279 ++      char *newlim, *p;
 24.3280 ++
 24.3281 ++      newlim = NULL;
 24.3282 ++      for (p = ptr; p < lim;)
 24.3283 ++         {
 24.3284 ++          if (memcmp (p, tab, tab_length) == 0)
 24.3285 ++            {
 24.3286 ++              newlim = p;
 24.3287 ++              break;
 24.3288 ++            }
 24.3289 ++
 24.3290 ++          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3291 ++          p += mblength;
 24.3292 ++        }
 24.3293 ++    }
 24.3294 ++  else
 24.3295 ++    {
 24.3296 ++      char *newlim;
 24.3297 ++      newlim = ptr;
 24.3298 ++
 24.3299 ++      while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength))
 24.3300 ++        newlim += mblength;
 24.3301 ++      if (ptr < lim)
 24.3302 ++        {
 24.3303 ++          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3304 ++          ptr += mblength;
 24.3305 ++        }
 24.3306 ++      while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength))
 24.3307 ++        newlim += mblength;
 24.3308 ++      lim = newlim;
 24.3309 ++    }
 24.3310 ++# endif
 24.3311 ++
 24.3312 ++  if (echar != 0)
 24.3313 ++  {
 24.3314 ++    /* If we're skipping leading blanks, don't start counting characters
 24.3315 ++     *      until after skipping past any leading blanks.  */
 24.3316 ++    if (key->skipeblanks)
 24.3317 ++      while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 24.3318 ++        ptr += mblength;
 24.3319 ++
 24.3320 ++    memset (&state, '\0', sizeof(mbstate_t));
 24.3321 ++
 24.3322 ++    /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
 24.3323 ++    for (i = 0; i < echar; i++)
 24.3324 ++     {
 24.3325 ++        GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 24.3326 ++
 24.3327 ++        if (ptr + mblength > lim)
 24.3328 ++          break;
 24.3329 ++        else
 24.3330 ++          ptr += mblength;
 24.3331 ++      }
 24.3332 ++  }
 24.3333 ++
 24.3334 ++  return ptr;
 24.3335 ++}
 24.3336 ++#endif
 24.3337 ++
 24.3338 ++static void
 24.3339 ++skipblanks_uni (char **ptr, char *lim)
 24.3340 ++{
 24.3341 ++  while (*ptr < lim && blanks[to_uchar (**ptr)])
 24.3342 ++    ++(*ptr);
 24.3343 ++}
 24.3344 ++
 24.3345 ++#if HAVE_MBRTOWC
 24.3346 ++static void
 24.3347 ++skipblanks_mb (char **ptr, char *lim)
 24.3348 ++{
 24.3349 ++  size_t mblength;
 24.3350 ++  while (*ptr < lim && ismbblank (*ptr, lim - *ptr, &mblength))
 24.3351 ++    (*ptr) += mblength;
 24.3352 ++}
 24.3353 ++#endif
 24.3354 ++
 24.3355 + /* Fill BUF reading from FP, moving buf->left bytes from the end
 24.3356 +    of buf->buf to the beginning first.  If EOF is reached and the
 24.3357 +    file wasn't terminated by a newline, supply one.  Set up BUF's line
 24.3358 +@@ -1823,8 +2155,22 @@ fillbuf (struct buffer *buf, FILE *fp, c
 24.3359 +                   else
 24.3360 +                     {
 24.3361 +                       if (key->skipsblanks)
 24.3362 +-                        while (blanks[to_uchar (*line_start)])
 24.3363 +-                          line_start++;
 24.3364 ++                        {
 24.3365 ++#if HAVE_MBRTOWC
 24.3366 ++                          if (MB_CUR_MAX > 1)
 24.3367 ++                            {
 24.3368 ++                              size_t mblength;
 24.3369 ++                              while (line_start < line->keylim &&
 24.3370 ++                                     ismbblank (line_start,
 24.3371 ++                                                line->keylim - line_start,
 24.3372 ++                                                &mblength))
 24.3373 ++                                line_start += mblength;
 24.3374 ++                            }
 24.3375 ++                          else
 24.3376 ++#endif
 24.3377 ++                          while (blanks[to_uchar (*line_start)])
 24.3378 ++                            line_start++;
 24.3379 ++                        }
 24.3380 +                       line->keybeg = line_start;
 24.3381 +                     }
 24.3382 +                 }
 24.3383 +@@ -1958,12 +2304,10 @@ find_unit_order (char const *number)
 24.3384 +        <none/unknown> < K/k < M < G < T < P < E < Z < Y  */
 24.3385 + 
 24.3386 + static int
 24.3387 +-human_numcompare (char const *a, char const *b)
 24.3388 ++human_numcompare (char *a, char *b)
 24.3389 + {
 24.3390 +-  while (blanks[to_uchar (*a)])
 24.3391 +-    a++;
 24.3392 +-  while (blanks[to_uchar (*b)])
 24.3393 +-    b++;
 24.3394 ++  skipblanks(&a, a + strlen(a));
 24.3395 ++  skipblanks(&b, b + strlen(b));
 24.3396 + 
 24.3397 +   int diff = find_unit_order (a) - find_unit_order (b);
 24.3398 +   return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep));
 24.3399 +@@ -1974,7 +2318,7 @@ human_numcompare (char const *a, char co
 24.3400 +    hideously fast. */
 24.3401 + 
 24.3402 + static int
 24.3403 +-numcompare (char const *a, char const *b)
 24.3404 ++numcompare_uni (const char *a, const char *b)
 24.3405 + {
 24.3406 +   while (blanks[to_uchar (*a)])
 24.3407 +     a++;
 24.3408 +@@ -1984,6 +2328,25 @@ numcompare (char const *a, char const *b
 24.3409 +   return strnumcmp (a, b, decimal_point, thousands_sep);
 24.3410 + }
 24.3411 + 
 24.3412 ++#if HAVE_MBRTOWC
 24.3413 ++static int
 24.3414 ++numcompare_mb (const char *a, const char *b)
 24.3415 ++{
 24.3416 ++  size_t mblength, len;
 24.3417 ++  len = strlen (a); /* okay for UTF-8 */
 24.3418 ++  while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 24.3419 ++    {
 24.3420 ++      a += mblength;
 24.3421 ++      len -= mblength;
 24.3422 ++    }
 24.3423 ++  len = strlen (b); /* okay for UTF-8 */
 24.3424 ++  while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 24.3425 ++    b += mblength;
 24.3426 ++
 24.3427 ++  return strnumcmp (a, b, decimal_point, thousands_sep);
 24.3428 ++}
 24.3429 ++#endif /* HAV_EMBRTOWC */
 24.3430 ++
 24.3431 + /* Work around a problem whereby the long double value returned by glibc's
 24.3432 +    strtold ("NaN", ...) contains uninitialized bits: clear all bytes of
 24.3433 +    A and B before calling strtold.  FIXME: remove this function once
 24.3434 +@@ -2034,7 +2397,7 @@ general_numcompare (char const *sa, char
 24.3435 +    Return 0 if the name in S is not recognized.  */
 24.3436 + 
 24.3437 + static int
 24.3438 +-getmonth (char const *month, char **ea)
 24.3439 ++getmonth_uni (char const *month, size_t len, char **ea)
 24.3440 + {
 24.3441 +   size_t lo = 0;
 24.3442 +   size_t hi = MONTHS_PER_YEAR;
 24.3443 +@@ -2310,15 +2673,14 @@ debug_key (struct line const *line, stru
 24.3444 +           char saved = *lim;
 24.3445 +           *lim = '\0';
 24.3446 + 
 24.3447 +-          while (blanks[to_uchar (*beg)])
 24.3448 +-            beg++;
 24.3449 ++          skipblanks (&beg, lim);
 24.3450 + 
 24.3451 +           char *tighter_lim = beg;
 24.3452 + 
 24.3453 +           if (lim < beg)
 24.3454 +             tighter_lim = lim;
 24.3455 +           else if (key->month)
 24.3456 +-            getmonth (beg, &tighter_lim);
 24.3457 ++            getmonth (beg, lim-beg, &tighter_lim);
 24.3458 +           else if (key->general_numeric)
 24.3459 +             ignore_value (strtold (beg, &tighter_lim));
 24.3460 +           else if (key->numeric || key->human_numeric)
 24.3461 +@@ -2452,7 +2814,7 @@ key_warnings (struct keyfield const *gke
 24.3462 +       /* Warn about significant leading blanks.  */
 24.3463 +       bool implicit_skip = key_numeric (key) || key->month;
 24.3464 +       bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y  */
 24.3465 +-      if (!zero_width && !gkey_only && tab == TAB_DEFAULT && !line_offset
 24.3466 ++      if (!zero_width && !gkey_only && !tab_length && !line_offset
 24.3467 +           && ((!key->skipsblanks && !implicit_skip)
 24.3468 +               || (!key->skipsblanks && key->schar)
 24.3469 +               || (!key->skipeblanks && key->echar)))
 24.3470 +@@ -2510,11 +2872,87 @@ key_warnings (struct keyfield const *gke
 24.3471 +     error (0, 0, _("option '-r' only applies to last-resort comparison"));
 24.3472 + }
 24.3473 + 
 24.3474 ++#if HAVE_MBRTOWC
 24.3475 ++static int
 24.3476 ++getmonth_mb (const char *s, size_t len, char **ea)
 24.3477 ++{
 24.3478 ++  char *month;
 24.3479 ++  register size_t i;
 24.3480 ++  register int lo = 0, hi = MONTHS_PER_YEAR, result;
 24.3481 ++  char *tmp;
 24.3482 ++  size_t wclength, mblength;
 24.3483 ++  const char *pp;
 24.3484 ++  const wchar_t *wpp;
 24.3485 ++  wchar_t *month_wcs;
 24.3486 ++  mbstate_t state;
 24.3487 ++
 24.3488 ++  while (len > 0 && ismbblank (s, len, &mblength))
 24.3489 ++    {
 24.3490 ++      s += mblength;
 24.3491 ++      len -= mblength;
 24.3492 ++    }
 24.3493 ++
 24.3494 ++  if (len == 0)
 24.3495 ++    return 0;
 24.3496 ++
 24.3497 ++  if (SIZE_MAX - len < 1)
 24.3498 ++    xalloc_die ();
 24.3499 ++
 24.3500 ++  month = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 24.3501 ++
 24.3502 ++  pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 24.3503 ++  memcpy (tmp, s, len);
 24.3504 ++  tmp[len] = '\0';
 24.3505 ++  wpp = month_wcs = (wchar_t *) xnmalloc (len + 1, sizeof (wchar_t));
 24.3506 ++  memset (&state, '\0', sizeof (mbstate_t));
 24.3507 ++
 24.3508 ++  wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state);
 24.3509 ++  if (wclength == (size_t)-1 || pp != NULL)
 24.3510 ++    error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s));
 24.3511 ++
 24.3512 ++  for (i = 0; i < wclength; i++)
 24.3513 ++    {
 24.3514 ++      month_wcs[i] = towupper(month_wcs[i]);
 24.3515 ++      if (iswblank (month_wcs[i]))
 24.3516 ++        {
 24.3517 ++          month_wcs[i] = L'\0';
 24.3518 ++          break;
 24.3519 ++        }
 24.3520 ++    }
 24.3521 ++
 24.3522 ++  mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state);
 24.3523 ++  assert (mblength != (-1) && wpp == NULL);
 24.3524 ++
 24.3525 ++  do
 24.3526 ++    {
 24.3527 ++      int ix = (lo + hi) / 2;
 24.3528 ++
 24.3529 ++      if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0)
 24.3530 ++        hi = ix;
 24.3531 ++      else
 24.3532 ++        lo = ix;
 24.3533 ++    }
 24.3534 ++  while (hi - lo > 1);
 24.3535 ++
 24.3536 ++  result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name))
 24.3537 ++      ? monthtab[lo].val : 0);
 24.3538 ++
 24.3539 ++  if (ea && result)
 24.3540 ++     *ea = (char*) s + strlen (monthtab[lo].name);
 24.3541 ++
 24.3542 ++  free (month);
 24.3543 ++  free (tmp);
 24.3544 ++  free (month_wcs);
 24.3545 ++
 24.3546 ++  return result;
 24.3547 ++}
 24.3548 ++#endif
 24.3549 ++
 24.3550 + /* Compare two lines A and B trying every key in sequence until there
 24.3551 +    are no more keys or a difference is found. */
 24.3552 + 
 24.3553 + static int
 24.3554 +-keycompare (struct line const *a, struct line const *b)
 24.3555 ++keycompare_uni (const struct line *a, const struct line *b)
 24.3556 + {
 24.3557 +   struct keyfield *key = keylist;
 24.3558 + 
 24.3559 +@@ -2599,7 +3037,7 @@ keycompare (struct line const *a, struct
 24.3560 +           else if (key->human_numeric)
 24.3561 +             diff = human_numcompare (ta, tb);
 24.3562 +           else if (key->month)
 24.3563 +-            diff = getmonth (ta, NULL) - getmonth (tb, NULL);
 24.3564 ++            diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL);
 24.3565 +           else if (key->random)
 24.3566 +             diff = compare_random (ta, tlena, tb, tlenb);
 24.3567 +           else if (key->version)
 24.3568 +@@ -2715,6 +3153,211 @@ keycompare (struct line const *a, struct
 24.3569 +   return key->reverse ? -diff : diff;
 24.3570 + }
 24.3571 + 
 24.3572 ++#if HAVE_MBRTOWC
 24.3573 ++static int
 24.3574 ++keycompare_mb (const struct line *a, const struct line *b)
 24.3575 ++{
 24.3576 ++  struct keyfield *key = keylist;
 24.3577 ++
 24.3578 ++  /* For the first iteration only, the key positions have been
 24.3579 ++     precomputed for us. */
 24.3580 ++  char *texta = a->keybeg;
 24.3581 ++  char *textb = b->keybeg;
 24.3582 ++  char *lima = a->keylim;
 24.3583 ++  char *limb = b->keylim;
 24.3584 ++
 24.3585 ++  size_t mblength_a, mblength_b;
 24.3586 ++  wchar_t wc_a, wc_b;
 24.3587 ++  mbstate_t state_a, state_b;
 24.3588 ++
 24.3589 ++  int diff = 0;
 24.3590 ++
 24.3591 ++  memset (&state_a, '\0', sizeof(mbstate_t));
 24.3592 ++  memset (&state_b, '\0', sizeof(mbstate_t));
 24.3593 ++  /* Ignore keys with start after end.  */
 24.3594 ++  if (a->keybeg - a->keylim > 0)
 24.3595 ++    return 0;
 24.3596 ++
 24.3597 ++
 24.3598 ++              /* Ignore and/or translate chars before comparing.  */
 24.3599 ++# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE)        \
 24.3600 ++  do                                                                        \
 24.3601 ++    {                                                                        \
 24.3602 ++      wchar_t uwc;                                                        \
 24.3603 ++      char mbc[MB_LEN_MAX];                                                \
 24.3604 ++      mbstate_t state_wc;                                                \
 24.3605 ++                                                                        \
 24.3606 ++      for (NEW_LEN = i = 0; i < LEN;)                                        \
 24.3607 ++        {                                                                \
 24.3608 ++          mbstate_t state_bak;                                                \
 24.3609 ++                                                                        \
 24.3610 ++          state_bak = STATE;                                                \
 24.3611 ++          MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE);                \
 24.3612 ++                                                                        \
 24.3613 ++          if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1                \
 24.3614 ++              || MBLENGTH == 0)                                                \
 24.3615 ++            {                                                                \
 24.3616 ++              if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1)        \
 24.3617 ++                STATE = state_bak;                                        \
 24.3618 ++              if (!ignore)                                                \
 24.3619 ++                COPY[NEW_LEN++] = TEXT[i];                                \
 24.3620 ++              i++;                                                         \
 24.3621 ++              continue;                                                        \
 24.3622 ++            }                                                                \
 24.3623 ++                                                                        \
 24.3624 ++          if (ignore)                                                        \
 24.3625 ++            {                                                                \
 24.3626 ++              if ((ignore == nonprinting && !iswprint (WC))                \
 24.3627 ++                   || (ignore == nondictionary                                \
 24.3628 ++                       && !iswalnum (WC) && !iswblank (WC)))                \
 24.3629 ++                {                                                        \
 24.3630 ++                  i += MBLENGTH;                                        \
 24.3631 ++                  continue;                                                \
 24.3632 ++                }                                                        \
 24.3633 ++            }                                                                \
 24.3634 ++                                                                        \
 24.3635 ++          if (translate)                                                \
 24.3636 ++            {                                                                \
 24.3637 ++                                                                        \
 24.3638 ++              uwc = towupper(WC);                                        \
 24.3639 ++              if (WC == uwc)                                                \
 24.3640 ++                {                                                        \
 24.3641 ++                  memcpy (mbc, TEXT + i, MBLENGTH);                        \
 24.3642 ++                  i += MBLENGTH;                                        \
 24.3643 ++                }                                                        \
 24.3644 ++              else                                                        \
 24.3645 ++                {                                                        \
 24.3646 ++                  i += MBLENGTH;                                        \
 24.3647 ++                  WC = uwc;                                                \
 24.3648 ++                  memset (&state_wc, '\0', sizeof (mbstate_t));                \
 24.3649 ++                                                                        \
 24.3650 ++                  MBLENGTH = wcrtomb (mbc, WC, &state_wc);                \
 24.3651 ++                  assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0);        \
 24.3652 ++                }                                                        \
 24.3653 ++                                                                        \
 24.3654 ++              for (j = 0; j < MBLENGTH; j++)                                \
 24.3655 ++                COPY[NEW_LEN++] = mbc[j];                                \
 24.3656 ++            }                                                                \
 24.3657 ++          else                                                                \
 24.3658 ++            for (j = 0; j < MBLENGTH; j++)                                \
 24.3659 ++              COPY[NEW_LEN++] = TEXT[i++];                                \
 24.3660 ++        }                                                                \
 24.3661 ++      COPY[NEW_LEN] = '\0';                                                \
 24.3662 ++    }                                                                        \
 24.3663 ++  while (0)
 24.3664 ++
 24.3665 ++      /* Actually compare the fields. */
 24.3666 ++
 24.3667 ++  for (;;)
 24.3668 ++    {
 24.3669 ++      /* Find the lengths. */
 24.3670 ++      size_t lena = lima <= texta ? 0 : lima - texta;
 24.3671 ++      size_t lenb = limb <= textb ? 0 : limb - textb;
 24.3672 ++
 24.3673 ++      char enda IF_LINT (= 0);
 24.3674 ++      char endb IF_LINT (= 0);
 24.3675 ++
 24.3676 ++      char const *translate = key->translate;
 24.3677 ++      bool const *ignore = key->ignore;
 24.3678 ++
 24.3679 ++      if (ignore || translate)
 24.3680 ++        {
 24.3681 ++          if (SIZE_MAX - lenb - 2 < lena)
 24.3682 ++            xalloc_die ();
 24.3683 ++          char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX);
 24.3684 ++          char *copy_b = copy_a + lena * MB_CUR_MAX + 1;
 24.3685 ++          size_t new_len_a, new_len_b;
 24.3686 ++          size_t i, j;
 24.3687 ++
 24.3688 ++          IGNORE_CHARS (new_len_a, lena, texta, copy_a,
 24.3689 ++                        wc_a, mblength_a, state_a);
 24.3690 ++          IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
 24.3691 ++                        wc_b, mblength_b, state_b);
 24.3692 ++          texta = copy_a; textb = copy_b;
 24.3693 ++          lena = new_len_a; lenb = new_len_b;
 24.3694 ++        }
 24.3695 ++      else
 24.3696 ++        {
 24.3697 ++          /* Use the keys in-place, temporarily null-terminated.  */
 24.3698 ++          enda = texta[lena]; texta[lena] = '\0';
 24.3699 ++          endb = textb[lenb]; textb[lenb] = '\0';
 24.3700 ++        }
 24.3701 ++
 24.3702 ++      if (key->random)
 24.3703 ++        diff = compare_random (texta, lena, textb, lenb);
 24.3704 ++      else if (key->numeric | key->general_numeric | key->human_numeric)
 24.3705 ++        {
 24.3706 ++          char savea = *lima, saveb = *limb;
 24.3707 ++
 24.3708 ++          *lima = *limb = '\0';
 24.3709 ++          diff = (key->numeric ? numcompare (texta, textb)
 24.3710 ++                  : key->general_numeric ? general_numcompare (texta, textb)
 24.3711 ++                  : human_numcompare (texta, textb));
 24.3712 ++          *lima = savea, *limb = saveb;
 24.3713 ++        }
 24.3714 ++      else if (key->version)
 24.3715 ++        diff = filevercmp (texta, textb);
 24.3716 ++      else if (key->month)
 24.3717 ++        diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL);
 24.3718 ++      else if (lena == 0)
 24.3719 ++        diff = - NONZERO (lenb);
 24.3720 ++      else if (lenb == 0)
 24.3721 ++        diff = 1;
 24.3722 ++      else if (hard_LC_COLLATE && !folding)
 24.3723 ++        {
 24.3724 ++          diff = xmemcoll0 (texta, lena + 1, textb, lenb + 1);
 24.3725 ++        }
 24.3726 ++      else
 24.3727 ++        {
 24.3728 ++          diff = memcmp (texta, textb, MIN (lena, lenb));
 24.3729 ++          if (diff == 0)
 24.3730 ++            diff = lena < lenb ? -1 : lena != lenb;
 24.3731 ++        }
 24.3732 ++
 24.3733 ++      if (ignore || translate)
 24.3734 ++        free (texta);
 24.3735 ++      else
 24.3736 ++        {
 24.3737 ++          texta[lena] = enda;
 24.3738 ++          textb[lenb] = endb;
 24.3739 ++        }
 24.3740 ++
 24.3741 ++      if (diff)
 24.3742 ++        goto not_equal;
 24.3743 ++
 24.3744 ++      key = key->next;
 24.3745 ++      if (! key)
 24.3746 ++        break;
 24.3747 ++
 24.3748 ++      /* Find the beginning and limit of the next field.  */
 24.3749 ++      if (key->eword != -1)
 24.3750 ++        lima = limfield (a, key), limb = limfield (b, key);
 24.3751 ++      else
 24.3752 ++        lima = a->text + a->length - 1, limb = b->text + b->length - 1;
 24.3753 ++
 24.3754 ++      if (key->sword != -1)
 24.3755 ++        texta = begfield (a, key), textb = begfield (b, key);
 24.3756 ++      else
 24.3757 ++        {
 24.3758 ++          texta = a->text, textb = b->text;
 24.3759 ++          if (key->skipsblanks)
 24.3760 ++            {
 24.3761 ++              while (texta < lima && ismbblank (texta, lima - texta, &mblength_a))
 24.3762 ++                texta += mblength_a;
 24.3763 ++              while (textb < limb && ismbblank (textb, limb - textb, &mblength_b))
 24.3764 ++                textb += mblength_b;
 24.3765 ++            }
 24.3766 ++        }
 24.3767 ++    }
 24.3768 ++
 24.3769 ++not_equal:
 24.3770 ++  if (key && key->reverse)
 24.3771 ++    return -diff;
 24.3772 ++  else
 24.3773 ++    return diff;
 24.3774 ++}
 24.3775 ++#endif
 24.3776 ++
 24.3777 + /* Compare two lines A and B, returning negative, zero, or positive
 24.3778 +    depending on whether A compares less than, equal to, or greater than B. */
 24.3779 + 
 24.3780 +@@ -2742,7 +3385,7 @@ compare (struct line const *a, struct li
 24.3781 +     diff = - NONZERO (blen);
 24.3782 +   else if (blen == 0)
 24.3783 +     diff = 1;
 24.3784 +-  else if (hard_LC_COLLATE)
 24.3785 ++  else if (hard_LC_COLLATE && !folding)
 24.3786 +     {
 24.3787 +       /* Note xmemcoll0 is a performance enhancement as
 24.3788 +          it will not unconditionally write '\0' after the
 24.3789 +@@ -4139,6 +4782,7 @@ set_ordering (char const *s, struct keyf
 24.3790 +           break;
 24.3791 +         case 'f':
 24.3792 +           key->translate = fold_toupper;
 24.3793 ++          folding = true;
 24.3794 +           break;
 24.3795 +         case 'g':
 24.3796 +           key->general_numeric = true;
 24.3797 +@@ -4218,7 +4862,7 @@ main (int argc, char **argv)
 24.3798 +   initialize_exit_failure (SORT_FAILURE);
 24.3799 + 
 24.3800 +   hard_LC_COLLATE = hard_locale (LC_COLLATE);
 24.3801 +-#if HAVE_NL_LANGINFO
 24.3802 ++#if HAVE_LANGINFO_CODESET
 24.3803 +   hard_LC_TIME = hard_locale (LC_TIME);
 24.3804 + #endif
 24.3805 + 
 24.3806 +@@ -4239,6 +4883,29 @@ main (int argc, char **argv)
 24.3807 +       thousands_sep = -1;
 24.3808 +   }
 24.3809 + 
 24.3810 ++#if HAVE_MBRTOWC
 24.3811 ++  if (MB_CUR_MAX > 1)
 24.3812 ++    {
 24.3813 ++      inittables = inittables_mb;
 24.3814 ++      begfield = begfield_mb;
 24.3815 ++      limfield = limfield_mb;
 24.3816 ++      skipblanks = skipblanks_mb;
 24.3817 ++      getmonth = getmonth_mb;
 24.3818 ++      keycompare = keycompare_mb;
 24.3819 ++      numcompare = numcompare_mb;
 24.3820 ++    }
 24.3821 ++  else
 24.3822 ++#endif
 24.3823 ++    {
 24.3824 ++      inittables = inittables_uni;
 24.3825 ++      begfield = begfield_uni;
 24.3826 ++      limfield = limfield_uni;
 24.3827 ++      skipblanks = skipblanks_uni;
 24.3828 ++      getmonth = getmonth_uni;
 24.3829 ++      keycompare = keycompare_uni;
 24.3830 ++      numcompare = numcompare_uni;
 24.3831 ++    }
 24.3832 ++
 24.3833 +   have_read_stdin = false;
 24.3834 +   inittables ();
 24.3835 + 
 24.3836 +@@ -4513,13 +5180,34 @@ main (int argc, char **argv)
 24.3837 + 
 24.3838 +         case 't':
 24.3839 +           {
 24.3840 +-            char newtab = optarg[0];
 24.3841 +-            if (! newtab)
 24.3842 ++            char newtab[MB_LEN_MAX + 1];
 24.3843 ++            size_t newtab_length = 1;
 24.3844 ++            strncpy (newtab, optarg, MB_LEN_MAX);
 24.3845 ++            if (! newtab[0])
 24.3846 +               die (SORT_FAILURE, 0, _("empty tab"));
 24.3847 +-            if (optarg[1])
 24.3848 ++#if HAVE_MBRTOWC
 24.3849 ++            if (MB_CUR_MAX > 1)
 24.3850 ++              {
 24.3851 ++                wchar_t wc;
 24.3852 ++                mbstate_t state;
 24.3853 ++
 24.3854 ++                memset (&state, '\0', sizeof (mbstate_t));
 24.3855 ++                newtab_length = mbrtowc (&wc, newtab, strnlen (newtab,
 24.3856 ++                                                               MB_LEN_MAX),
 24.3857 ++                                         &state);
 24.3858 ++                switch (newtab_length)
 24.3859 ++                  {
 24.3860 ++                  case (size_t) -1:
 24.3861 ++                  case (size_t) -2:
 24.3862 ++                  case 0:
 24.3863 ++                    newtab_length = 1;
 24.3864 ++                  }
 24.3865 ++              }
 24.3866 ++#endif
 24.3867 ++            if (newtab_length == 1 && optarg[1])
 24.3868 +               {
 24.3869 +                 if (STREQ (optarg, "\\0"))
 24.3870 +-                  newtab = '\0';
 24.3871 ++                  newtab[0] = '\0';
 24.3872 +                 else
 24.3873 +                   {
 24.3874 +                     /* Provoke with 'sort -txx'.  Complain about
 24.3875 +@@ -4530,9 +5218,11 @@ main (int argc, char **argv)
 24.3876 +                          quote (optarg));
 24.3877 +                   }
 24.3878 +               }
 24.3879 +-            if (tab != TAB_DEFAULT && tab != newtab)
 24.3880 ++            if (tab_length && (tab_length != newtab_length
 24.3881 ++                        || memcmp (tab, newtab, tab_length) != 0))
 24.3882 +               die (SORT_FAILURE, 0, _("incompatible tabs"));
 24.3883 +-            tab = newtab;
 24.3884 ++            memcpy (tab, newtab, newtab_length);
 24.3885 ++            tab_length = newtab_length;
 24.3886 +           }
 24.3887 +           break;
 24.3888 + 
 24.3889 +@@ -4770,12 +5460,10 @@ main (int argc, char **argv)
 24.3890 +       sort (files, nfiles, outfile, nthreads);
 24.3891 +     }
 24.3892 + 
 24.3893 +-#ifdef lint
 24.3894 +   if (files_from)
 24.3895 +     readtokens0_free (&tok);
 24.3896 +   else
 24.3897 +     free (files);
 24.3898 +-#endif
 24.3899 + 
 24.3900 +   if (have_read_stdin && fclose (stdin) == EOF)
 24.3901 +     sort_die (_("close failed"), "-");
 24.3902 +diff -Naurp coreutils-8.27-orig/src/unexpand.c coreutils-8.27/src/unexpand.c
 24.3903 +--- coreutils-8.27-orig/src/unexpand.c	2017-01-01 16:34:24.000000000 -0600
 24.3904 ++++ coreutils-8.27/src/unexpand.c	2017-03-11 23:49:06.758133530 -0600
 24.3905 +@@ -38,6 +38,9 @@
 24.3906 + #include <stdio.h>
 24.3907 + #include <getopt.h>
 24.3908 + #include <sys/types.h>
 24.3909 ++
 24.3910 ++#include <mbfile.h>
 24.3911 ++
 24.3912 + #include "system.h"
 24.3913 + #include "die.h"
 24.3914 + #include "xstrndup.h"
 24.3915 +@@ -107,24 +110,47 @@ unexpand (void)
 24.3916 + {
 24.3917 +   /* Input stream.  */
 24.3918 +   FILE *fp = next_file (NULL);
 24.3919 ++  mb_file_t mbf;
 24.3920 + 
 24.3921 +   /* The array of pending blanks.  In non-POSIX locales, blanks can
 24.3922 +      include characters other than spaces, so the blanks must be
 24.3923 +      stored, not merely counted.  */
 24.3924 +-  char *pending_blank;
 24.3925 ++  mbf_char_t *pending_blank;
 24.3926 ++  /* True if the starting locale is utf8.  */
 24.3927 ++  bool using_utf_locale;
 24.3928 ++
 24.3929 ++  /* True if the first file contains BOM header.  */
 24.3930 ++  bool found_bom;
 24.3931 ++  using_utf_locale=check_utf_locale();
 24.3932 + 
 24.3933 +   if (!fp)
 24.3934 +     return;
 24.3935 ++  mbf_init (mbf, fp);
 24.3936 ++  found_bom=check_bom(fp,&mbf);
 24.3937 + 
 24.3938 ++  if (using_utf_locale == false && found_bom == true)
 24.3939 ++  {
 24.3940 ++    /*try using some predefined locale */
 24.3941 ++
 24.3942 ++    if (set_utf_locale () != 0)
 24.3943 ++    {
 24.3944 ++      error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
 24.3945 ++    }
 24.3946 ++  }
 24.3947 +   /* The worst case is a non-blank character, then one blank, then a
 24.3948 +      tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so
 24.3949 +      allocate MAX_COLUMN_WIDTH bytes to store the blanks.  */
 24.3950 +-  pending_blank = xmalloc (max_column_width);
 24.3951 ++  pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t));
 24.3952 ++
 24.3953 ++  if (found_bom == true)
 24.3954 ++  {
 24.3955 ++    print_bom();
 24.3956 ++  }
 24.3957 + 
 24.3958 +   while (true)
 24.3959 +     {
 24.3960 +       /* Input character, or EOF.  */
 24.3961 +-      int c;
 24.3962 ++      mbf_char_t c;
 24.3963 + 
 24.3964 +       /* If true, perform translations.  */
 24.3965 +       bool convert = true;
 24.3966 +@@ -158,12 +184,44 @@ unexpand (void)
 24.3967 + 
 24.3968 +       do
 24.3969 +         {
 24.3970 +-          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
 24.3971 +-            continue;
 24.3972 ++          while (true) {
 24.3973 ++            mbf_getc (c, mbf);
 24.3974 ++            if ((mb_iseof (c)) && (fp = next_file (fp)))
 24.3975 ++              {
 24.3976 ++                mbf_init (mbf, fp);
 24.3977 ++                if (fp!=NULL)
 24.3978 ++                {
 24.3979 ++                  if (check_bom(fp,&mbf)==true)
 24.3980 ++                  {
 24.3981 ++                    /*Not the first file - check BOM header*/
 24.3982 ++                    if (using_utf_locale==false && found_bom==false)
 24.3983 ++                    {
 24.3984 ++                      /*BOM header in subsequent file but not in the first one. */
 24.3985 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 24.3986 ++                    }
 24.3987 ++                  }
 24.3988 ++                  else
 24.3989 ++                  {
 24.3990 ++                    if(using_utf_locale==false && found_bom==true)
 24.3991 ++                    {
 24.3992 ++                      /*First file conatined BOM header - locale was switched to UTF
 24.3993 ++                      /*all subsequent files should contain BOM. */
 24.3994 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 24.3995 ++                    }
 24.3996 ++                  }
 24.3997 ++                }
 24.3998 ++                continue;
 24.3999 ++              }
 24.4000 ++            else
 24.4001 ++              {
 24.4002 ++                break;
 24.4003 ++              }
 24.4004 ++            }
 24.4005 ++
 24.4006 + 
 24.4007 +           if (convert)
 24.4008 +             {
 24.4009 +-              bool blank = !! isblank (c);
 24.4010 ++              bool blank = mb_isblank (c);
 24.4011 + 
 24.4012 +               if (blank)
 24.4013 +                 {
 24.4014 +@@ -180,16 +238,16 @@ unexpand (void)
 24.4015 +                       if (next_tab_column < column)
 24.4016 +                         die (EXIT_FAILURE, 0, _("input line is too long"));
 24.4017 + 
 24.4018 +-                      if (c == '\t')
 24.4019 ++                      if (mb_iseq (c, '\t'))
 24.4020 +                         {
 24.4021 +                           column = next_tab_column;
 24.4022 + 
 24.4023 +                           if (pending)
 24.4024 +-                            pending_blank[0] = '\t';
 24.4025 ++                            mb_setascii (&pending_blank[0], '\t');
 24.4026 +                         }
 24.4027 +                       else
 24.4028 +                         {
 24.4029 +-                          column++;
 24.4030 ++                          column += mb_width (c);
 24.4031 + 
 24.4032 +                           if (! (prev_blank && column == next_tab_column))
 24.4033 +                             {
 24.4034 +@@ -197,13 +255,14 @@ unexpand (void)
 24.4035 +                                  will be replaced by tabs.  */
 24.4036 +                               if (column == next_tab_column)
 24.4037 +                                 one_blank_before_tab_stop = true;
 24.4038 +-                              pending_blank[pending++] = c;
 24.4039 ++                              mb_copy (&pending_blank[pending++], &c);
 24.4040 +                               prev_blank = true;
 24.4041 +                               continue;
 24.4042 +                             }
 24.4043 + 
 24.4044 +                           /* Replace the pending blanks by a tab or two.  */
 24.4045 +-                          pending_blank[0] = c = '\t';
 24.4046 ++                          mb_setascii (&c, '\t');
 24.4047 ++                          mb_setascii (&pending_blank[0], '\t');
 24.4048 +                         }
 24.4049 + 
 24.4050 +                       /* Discard pending blanks, unless it was a single
 24.4051 +@@ -211,7 +270,7 @@ unexpand (void)
 24.4052 +                       pending = one_blank_before_tab_stop;
 24.4053 +                     }
 24.4054 +                 }
 24.4055 +-              else if (c == '\b')
 24.4056 ++              else if (mb_iseq (c, '\b'))
 24.4057 +                 {
 24.4058 +                   /* Go back one column, and force recalculation of the
 24.4059 +                      next tab stop.  */
 24.4060 +@@ -219,9 +278,9 @@ unexpand (void)
 24.4061 +                   next_tab_column = column;
 24.4062 +                   tab_index -= !!tab_index;
 24.4063 +                 }
 24.4064 +-              else
 24.4065 ++              else if (!mb_iseq (c, '\n'))
 24.4066 +                 {
 24.4067 +-                  column++;
 24.4068 ++                  column += mb_width (c);
 24.4069 +                   if (!column)
 24.4070 +                     die (EXIT_FAILURE, 0, _("input line is too long"));
 24.4071 +                 }
 24.4072 +@@ -229,8 +288,11 @@ unexpand (void)
 24.4073 +               if (pending)
 24.4074 +                 {
 24.4075 +                   if (pending > 1 && one_blank_before_tab_stop)
 24.4076 +-                    pending_blank[0] = '\t';
 24.4077 +-                  if (fwrite (pending_blank, 1, pending, stdout) != pending)
 24.4078 ++                    mb_setascii (&pending_blank[0], '\t');
 24.4079 ++
 24.4080 ++                  for (int n = 0; n < pending; ++n)
 24.4081 ++                    mb_putc (pending_blank[n], stdout);
 24.4082 ++                  if (ferror (stdout))
 24.4083 +                     die (EXIT_FAILURE, errno, _("write error"));
 24.4084 +                   pending = 0;
 24.4085 +                   one_blank_before_tab_stop = false;
 24.4086 +@@ -240,16 +302,17 @@ unexpand (void)
 24.4087 +               convert &= convert_entire_line || blank;
 24.4088 +             }
 24.4089 + 
 24.4090 +-          if (c < 0)
 24.4091 ++          if (mb_iseof (c))
 24.4092 +             {
 24.4093 +               free (pending_blank);
 24.4094 +               return;
 24.4095 +             }
 24.4096 + 
 24.4097 +-          if (putchar (c) < 0)
 24.4098 ++          mb_putc (c, stdout);
 24.4099 ++          if (ferror (stdout))
 24.4100 +             die (EXIT_FAILURE, errno, _("write error"));
 24.4101 +         }
 24.4102 +-      while (c != '\n');
 24.4103 ++      while (!mb_iseq (c, '\n'));
 24.4104 +     }
 24.4105 + }
 24.4106 + 
 24.4107 +diff -Naurp coreutils-8.27-orig/src/uniq.c coreutils-8.27/src/uniq.c
 24.4108 +--- coreutils-8.27-orig/src/uniq.c	2017-01-01 16:34:24.000000000 -0600
 24.4109 ++++ coreutils-8.27/src/uniq.c	2017-03-11 23:47:13.098285938 -0600
 24.4110 +@@ -21,6 +21,17 @@
 24.4111 + #include <getopt.h>
 24.4112 + #include <sys/types.h>
 24.4113 + 
 24.4114 ++/* Get mbstate_t, mbrtowc(). */
 24.4115 ++#if HAVE_WCHAR_H
 24.4116 ++# include <wchar.h>
 24.4117 ++#endif
 24.4118 ++
 24.4119 ++/* Get isw* functions. */
 24.4120 ++#if HAVE_WCTYPE_H
 24.4121 ++# include <wctype.h>
 24.4122 ++#endif
 24.4123 ++#include <assert.h>
 24.4124 ++
 24.4125 + #include "system.h"
 24.4126 + #include "argmatch.h"
 24.4127 + #include "linebuffer.h"
 24.4128 +@@ -32,9 +43,21 @@
 24.4129 + #include "stdio--.h"
 24.4130 + #include "xmemcoll.h"
 24.4131 + #include "xstrtol.h"
 24.4132 +-#include "memcasecmp.h"
 24.4133 ++#include "xmemcoll.h"
 24.4134 + #include "quote.h"
 24.4135 + 
 24.4136 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 24.4137 ++   installation; work around this configuration error.  */
 24.4138 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 24.4139 ++# define MB_LEN_MAX 16
 24.4140 ++#endif
 24.4141 ++
 24.4142 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 24.4143 ++#if HAVE_MBRTOWC && defined mbstate_t
 24.4144 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 24.4145 ++#endif
 24.4146 ++
 24.4147 ++
 24.4148 + /* The official name of this program (e.g., no 'g' prefix).  */
 24.4149 + #define PROGRAM_NAME "uniq"
 24.4150 + 
 24.4151 +@@ -144,6 +167,10 @@ enum
 24.4152 +   GROUP_OPTION = CHAR_MAX + 1
 24.4153 + };
 24.4154 + 
 24.4155 ++/* Function pointers. */
 24.4156 ++static char *
 24.4157 ++(*find_field) (struct linebuffer *line);
 24.4158 ++
 24.4159 + static struct option const longopts[] =
 24.4160 + {
 24.4161 +   {"count", no_argument, NULL, 'c'},
 24.4162 +@@ -260,7 +287,7 @@ size_opt (char const *opt, char const *m
 24.4163 +    return a pointer to the beginning of the line's field to be compared. */
 24.4164 + 
 24.4165 + static char * _GL_ATTRIBUTE_PURE
 24.4166 +-find_field (struct linebuffer const *line)
 24.4167 ++find_field_uni (struct linebuffer *line)
 24.4168 + {
 24.4169 +   size_t count;
 24.4170 +   char const *lp = line->buffer;
 24.4171 +@@ -280,6 +307,83 @@ find_field (struct linebuffer const *lin
 24.4172 +   return line->buffer + i;
 24.4173 + }
 24.4174 + 
 24.4175 ++#if HAVE_MBRTOWC
 24.4176 ++
 24.4177 ++# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL)  \
 24.4178 ++  do                                                                        \
 24.4179 ++    {                                                                        \
 24.4180 ++      mbstate_t state_bak;                                                \
 24.4181 ++                                                                        \
 24.4182 ++      CONVFAIL = 0;                                                        \
 24.4183 ++      state_bak = *STATEP;                                                \
 24.4184 ++                                                                        \
 24.4185 ++      MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP);                \
 24.4186 ++                                                                        \
 24.4187 ++      switch (MBLENGTH)                                                        \
 24.4188 ++        {                                                                \
 24.4189 ++        case (size_t)-2:                                                \
 24.4190 ++        case (size_t)-1:                                                \
 24.4191 ++          *STATEP = state_bak;                                                \
 24.4192 ++          CONVFAIL++;                                                        \
 24.4193 ++          /* Fall through */                                                \
 24.4194 ++        case 0:                                                                \
 24.4195 ++          MBLENGTH = 1;                                                        \
 24.4196 ++        }                                                                \
 24.4197 ++    }                                                                        \
 24.4198 ++  while (0)
 24.4199 ++
 24.4200 ++static char *
 24.4201 ++find_field_multi (struct linebuffer *line)
 24.4202 ++{
 24.4203 ++  size_t count;
 24.4204 ++  char *lp = line->buffer;
 24.4205 ++  size_t size = line->length - 1;
 24.4206 ++  size_t pos;
 24.4207 ++  size_t mblength;
 24.4208 ++  wchar_t wc;
 24.4209 ++  mbstate_t *statep;
 24.4210 ++  int convfail = 0;
 24.4211 ++
 24.4212 ++  pos = 0;
 24.4213 ++  statep = &(line->state);
 24.4214 ++
 24.4215 ++  /* skip fields. */
 24.4216 ++  for (count = 0; count < skip_fields && pos < size; count++)
 24.4217 ++    {
 24.4218 ++      while (pos < size)
 24.4219 ++        {
 24.4220 ++          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 24.4221 ++
 24.4222 ++          if (convfail || !(iswblank (wc) || wc == '\n'))
 24.4223 ++            {
 24.4224 ++              pos += mblength;
 24.4225 ++              break;
 24.4226 ++            }
 24.4227 ++          pos += mblength;
 24.4228 ++        }
 24.4229 ++
 24.4230 ++      while (pos < size)
 24.4231 ++        {
 24.4232 ++          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 24.4233 ++
 24.4234 ++          if (!convfail && (iswblank (wc) || wc == '\n'))
 24.4235 ++            break;
 24.4236 ++
 24.4237 ++          pos += mblength;
 24.4238 ++        }
 24.4239 ++    }
 24.4240 ++
 24.4241 ++  /* skip fields. */
 24.4242 ++  for (count = 0; count < skip_chars && pos < size; count++)
 24.4243 ++    {
 24.4244 ++      MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 24.4245 ++      pos += mblength;
 24.4246 ++    }
 24.4247 ++
 24.4248 ++  return lp + pos;
 24.4249 ++}
 24.4250 ++#endif
 24.4251 ++
 24.4252 + /* Return false if two strings OLD and NEW match, true if not.
 24.4253 +    OLD and NEW point not to the beginnings of the lines
 24.4254 +    but rather to the beginnings of the fields to compare.
 24.4255 +@@ -288,6 +392,8 @@ find_field (struct linebuffer const *lin
 24.4256 + static bool
 24.4257 + different (char *old, char *new, size_t oldlen, size_t newlen)
 24.4258 + {
 24.4259 ++  char *copy_old, *copy_new;
 24.4260 ++
 24.4261 +   if (check_chars < oldlen)
 24.4262 +     oldlen = check_chars;
 24.4263 +   if (check_chars < newlen)
 24.4264 +@@ -295,14 +401,103 @@ different (char *old, char *new, size_t
 24.4265 + 
 24.4266 +   if (ignore_case)
 24.4267 +     {
 24.4268 +-      /* FIXME: This should invoke strcoll somehow.  */
 24.4269 +-      return oldlen != newlen || memcasecmp (old, new, oldlen);
 24.4270 ++      size_t i;
 24.4271 ++
 24.4272 ++      copy_old = xmalloc (oldlen + 1);
 24.4273 ++      copy_new = xmalloc (oldlen + 1);
 24.4274 ++
 24.4275 ++      for (i = 0; i < oldlen; i++)
 24.4276 ++        {
 24.4277 ++          copy_old[i] = toupper (old[i]);
 24.4278 ++          copy_new[i] = toupper (new[i]);
 24.4279 ++        }
 24.4280 ++      bool rc = xmemcoll (copy_old, oldlen, copy_new, newlen);
 24.4281 ++      free (copy_old);
 24.4282 ++      free (copy_new);
 24.4283 ++      return rc;
 24.4284 +     }
 24.4285 +-  else if (hard_LC_COLLATE)
 24.4286 +-    return xmemcoll (old, oldlen, new, newlen) != 0;
 24.4287 +   else
 24.4288 +-    return oldlen != newlen || memcmp (old, new, oldlen);
 24.4289 ++    {
 24.4290 ++      copy_old = (char *)old;
 24.4291 ++      copy_new = (char *)new;
 24.4292 ++    }
 24.4293 ++
 24.4294 ++  return xmemcoll (copy_old, oldlen, copy_new, newlen);
 24.4295 ++
 24.4296 ++}
 24.4297 ++
 24.4298 ++#if HAVE_MBRTOWC
 24.4299 ++static int
 24.4300 ++different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate)
 24.4301 ++{
 24.4302 ++  size_t i, j, chars;
 24.4303 ++  const char *str[2];
 24.4304 ++  char *copy[2];
 24.4305 ++  size_t len[2];
 24.4306 ++  mbstate_t state[2];
 24.4307 ++  size_t mblength;
 24.4308 ++  wchar_t wc, uwc;
 24.4309 ++  mbstate_t state_bak;
 24.4310 ++
 24.4311 ++  str[0] = old;
 24.4312 ++  str[1] = new;
 24.4313 ++  len[0] = oldlen;
 24.4314 ++  len[1] = newlen;
 24.4315 ++  state[0] = oldstate;
 24.4316 ++  state[1] = newstate;
 24.4317 ++
 24.4318 ++  for (i = 0; i < 2; i++)
 24.4319 ++    {
 24.4320 ++      copy[i] = xmalloc (len[i] + 1);
 24.4321 ++      memset (copy[i], '\0', len[i] + 1);
 24.4322 ++
 24.4323 ++      for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++)
 24.4324 ++        {
 24.4325 ++          state_bak = state[i];
 24.4326 ++          mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i]));
 24.4327 ++
 24.4328 ++          switch (mblength)
 24.4329 ++            {
 24.4330 ++            case (size_t)-1:
 24.4331 ++            case (size_t)-2:
 24.4332 ++              state[i] = state_bak;
 24.4333 ++              /* Fall through */
 24.4334 ++            case 0:
 24.4335 ++              mblength = 1;
 24.4336 ++              break;
 24.4337 ++
 24.4338 ++            default:
 24.4339 ++              if (ignore_case)
 24.4340 ++                {
 24.4341 ++                  uwc = towupper (wc);
 24.4342 ++
 24.4343 ++                  if (uwc != wc)
 24.4344 ++                    {
 24.4345 ++                      mbstate_t state_wc;
 24.4346 ++                      size_t mblen;
 24.4347 ++
 24.4348 ++                      memset (&state_wc, '\0', sizeof(mbstate_t));
 24.4349 ++                      mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 24.4350 ++                      assert (mblen != (size_t)-1);
 24.4351 ++                    }
 24.4352 ++                  else
 24.4353 ++                    memcpy (copy[i] + j, str[i] + j, mblength);
 24.4354 ++                }
 24.4355 ++              else
 24.4356 ++                memcpy (copy[i] + j, str[i] + j, mblength);
 24.4357 ++            }
 24.4358 ++          j += mblength;
 24.4359 ++        }
 24.4360 ++      copy[i][j] = '\0';
 24.4361 ++      len[i] = j;
 24.4362 ++    }
 24.4363 ++  int rc = xmemcoll (copy[0], len[0], copy[1], len[1]);
 24.4364 ++  free (copy[0]);
 24.4365 ++  free (copy[1]);
 24.4366 ++  return rc;
 24.4367 ++
 24.4368 + }
 24.4369 ++#endif
 24.4370 + 
 24.4371 + /* Output the line in linebuffer LINE to standard output
 24.4372 +    provided that the switches say it should be output.
 24.4373 +@@ -367,19 +562,38 @@ check_file (const char *infile, const ch
 24.4374 +       char *prevfield IF_LINT ( = NULL);
 24.4375 +       size_t prevlen IF_LINT ( = 0);
 24.4376 +       bool first_group_printed = false;
 24.4377 ++#if HAVE_MBRTOWC
 24.4378 ++      mbstate_t prevstate;
 24.4379 ++
 24.4380 ++      memset (&prevstate, '\0', sizeof (mbstate_t));
 24.4381 ++#endif
 24.4382 + 
 24.4383 +       while (!feof (stdin))
 24.4384 +         {
 24.4385 +           char *thisfield;
 24.4386 +           size_t thislen;
 24.4387 +           bool new_group;
 24.4388 ++#if HAVE_MBRTOWC
 24.4389 ++          mbstate_t thisstate;
 24.4390 ++#endif
 24.4391 + 
 24.4392 +           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 24.4393 +             break;
 24.4394 + 
 24.4395 +           thisfield = find_field (thisline);
 24.4396 +           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 24.4397 ++#if HAVE_MBRTOWC
 24.4398 ++          if (MB_CUR_MAX > 1)
 24.4399 ++            {
 24.4400 ++              thisstate = thisline->state;
 24.4401 + 
 24.4402 ++              new_group = (prevline->length == 0
 24.4403 ++                           || different_multi (thisfield, prevfield,
 24.4404 ++                                               thislen, prevlen,
 24.4405 ++                                               thisstate, prevstate));
 24.4406 ++            }
 24.4407 ++          else
 24.4408 ++#endif
 24.4409 +           new_group = (prevline->length == 0
 24.4410 +                        || different (thisfield, prevfield, thislen, prevlen));
 24.4411 + 
 24.4412 +@@ -397,6 +611,10 @@ check_file (const char *infile, const ch
 24.4413 +               SWAP_LINES (prevline, thisline);
 24.4414 +               prevfield = thisfield;
 24.4415 +               prevlen = thislen;
 24.4416 ++#if HAVE_MBRTOWC
 24.4417 ++              if (MB_CUR_MAX > 1)
 24.4418 ++                prevstate = thisstate;
 24.4419 ++#endif
 24.4420 +               first_group_printed = true;
 24.4421 +             }
 24.4422 +         }
 24.4423 +@@ -409,17 +627,26 @@ check_file (const char *infile, const ch
 24.4424 +       size_t prevlen;
 24.4425 +       uintmax_t match_count = 0;
 24.4426 +       bool first_delimiter = true;
 24.4427 ++#if HAVE_MBRTOWC
 24.4428 ++      mbstate_t prevstate;
 24.4429 ++#endif
 24.4430 + 
 24.4431 +       if (readlinebuffer_delim (prevline, stdin, delimiter) == 0)
 24.4432 +         goto closefiles;
 24.4433 +       prevfield = find_field (prevline);
 24.4434 +       prevlen = prevline->length - 1 - (prevfield - prevline->buffer);
 24.4435 ++#if HAVE_MBRTOWC
 24.4436 ++      prevstate = prevline->state;
 24.4437 ++#endif
 24.4438 + 
 24.4439 +       while (!feof (stdin))
 24.4440 +         {
 24.4441 +           bool match;
 24.4442 +           char *thisfield;
 24.4443 +           size_t thislen;
 24.4444 ++#if HAVE_MBRTOWC
 24.4445 ++          mbstate_t thisstate = thisline->state;
 24.4446 ++#endif
 24.4447 +           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 24.4448 +             {
 24.4449 +               if (ferror (stdin))
 24.4450 +@@ -428,6 +655,14 @@ check_file (const char *infile, const ch
 24.4451 +             }
 24.4452 +           thisfield = find_field (thisline);
 24.4453 +           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 24.4454 ++#if HAVE_MBRTOWC
 24.4455 ++          if (MB_CUR_MAX > 1)
 24.4456 ++            {
 24.4457 ++              match = !different_multi (thisfield, prevfield,
 24.4458 ++                                thislen, prevlen, thisstate, prevstate);
 24.4459 ++            }
 24.4460 ++          else
 24.4461 ++#endif
 24.4462 +           match = !different (thisfield, prevfield, thislen, prevlen);
 24.4463 +           match_count += match;
 24.4464 + 
 24.4465 +@@ -460,6 +695,9 @@ check_file (const char *infile, const ch
 24.4466 +               SWAP_LINES (prevline, thisline);
 24.4467 +               prevfield = thisfield;
 24.4468 +               prevlen = thislen;
 24.4469 ++#if HAVE_MBRTOWC
 24.4470 ++              prevstate = thisstate;
 24.4471 ++#endif
 24.4472 +               if (!match)
 24.4473 +                 match_count = 0;
 24.4474 +             }
 24.4475 +@@ -506,6 +744,19 @@ main (int argc, char **argv)
 24.4476 + 
 24.4477 +   atexit (close_stdout);
 24.4478 + 
 24.4479 ++#if HAVE_MBRTOWC
 24.4480 ++  if (MB_CUR_MAX > 1)
 24.4481 ++    {
 24.4482 ++      find_field = find_field_multi;
 24.4483 ++    }
 24.4484 ++  else
 24.4485 ++#endif
 24.4486 ++    {
 24.4487 ++      find_field = find_field_uni;
 24.4488 ++    }
 24.4489 ++
 24.4490 ++
 24.4491 ++
 24.4492 +   skip_chars = 0;
 24.4493 +   skip_fields = 0;
 24.4494 +   check_chars = SIZE_MAX;
 24.4495 +diff -Naurp coreutils-8.27-orig/tests/expand/mb.sh coreutils-8.27/tests/expand/mb.sh
 24.4496 +--- coreutils-8.27-orig/tests/expand/mb.sh	1969-12-31 18:00:00.000000000 -0600
 24.4497 ++++ coreutils-8.27/tests/expand/mb.sh	2017-03-11 23:49:06.759133489 -0600
 24.4498 +@@ -0,0 +1,183 @@
 24.4499 ++#!/bin/sh
 24.4500 ++
 24.4501 ++# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 24.4502 ++
 24.4503 ++# This program is free software: you can redistribute it and/or modify
 24.4504 ++# it under the terms of the GNU General Public License as published by
 24.4505 ++# the Free Software Foundation, either version 3 of the License, or
 24.4506 ++# (at your option) any later version.
 24.4507 ++
 24.4508 ++# This program is distributed in the hope that it will be useful,
 24.4509 ++# but WITHOUT ANY WARRANTY; without even the implied warranty of
 24.4510 ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 24.4511 ++# GNU General Public License for more details.
 24.4512 ++
 24.4513 ++# You should have received a copy of the GNU General Public License
 24.4514 ++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 24.4515 ++
 24.4516 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 24.4517 ++print_ver_ expand
 24.4518 ++
 24.4519 ++export LC_ALL=en_US.UTF-8
 24.4520 ++
 24.4521 ++#input containing multibyte characters
 24.4522 ++cat <<\EOF > in || framework_failure_
 24.4523 ++1234567812345678123456781
 24.4524 ++.       .       .       .
 24.4525 ++a	b	c	d
 24.4526 ++.       .       .       .
 24.4527 ++ä	ö	ü	ß
 24.4528 ++.       .       .       .
 24.4529 ++EOF
 24.4530 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 24.4531 ++
 24.4532 ++cat <<\EOF > exp || framework_failure_
 24.4533 ++1234567812345678123456781
 24.4534 ++.       .       .       .
 24.4535 ++a       b       c       d
 24.4536 ++.       .       .       .
 24.4537 ++ä       ö       ü       ß
 24.4538 ++.       .       .       .
 24.4539 ++   äöü  .    öüä.       ä xx
 24.4540 ++EOF
 24.4541 ++
 24.4542 ++expand < in > out || fail=1
 24.4543 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4544 ++
 24.4545 ++#multiple files as an input
 24.4546 ++cat <<\EOF >> exp || framework_failure_
 24.4547 ++1234567812345678123456781
 24.4548 ++.       .       .       .
 24.4549 ++a       b       c       d
 24.4550 ++.       .       .       .
 24.4551 ++ä       ö       ü       ß
 24.4552 ++.       .       .       .
 24.4553 ++   äöü  .    öüä.       ä xx
 24.4554 ++EOF
 24.4555 ++
 24.4556 ++expand ./in ./in > out || fail=1
 24.4557 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4558 ++
 24.4559 ++#test characters with display widths != 1
 24.4560 ++env printf '12345678
 24.4561 ++e\t|ascii(1)
 24.4562 ++\u00E9\t|composed(1)
 24.4563 ++e\u0301\t|decomposed(1)
 24.4564 ++\u3000\t|ideo-space(2)
 24.4565 ++\uFF0D\t|full-hypen(2)
 24.4566 ++' > in || framework_failure_
 24.4567 ++
 24.4568 ++env printf '12345678
 24.4569 ++e       |ascii(1)
 24.4570 ++\u00E9       |composed(1)
 24.4571 ++e\u0301       |decomposed(1)
 24.4572 ++\u3000      |ideo-space(2)
 24.4573 ++\uFF0D      |full-hypen(2)
 24.4574 ++' > exp || framework_failure_
 24.4575 ++
 24.4576 ++expand < in > out || fail=1
 24.4577 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4578 ++
 24.4579 ++#shouldn't fail with "input line too long"
 24.4580 ++#when a line starts with a control character
 24.4581 ++env printf '\n' > in || framework_failure_
 24.4582 ++
 24.4583 ++expand < in > out || fail=1
 24.4584 ++compare in out > /dev/null 2>&1 || fail=1
 24.4585 ++
 24.4586 ++#non-Unicode characters interspersed between Unicode ones
 24.4587 ++env printf '12345678
 24.4588 ++\t\xFF|
 24.4589 ++\xFF\t|
 24.4590 ++\t\xFFä|
 24.4591 ++ä\xFF\t|
 24.4592 ++\tä\xFF|
 24.4593 ++\xFF\tä|
 24.4594 ++äbcdef\xFF\t|
 24.4595 ++' > in || framework_failure_
 24.4596 ++
 24.4597 ++env printf '12345678
 24.4598 ++        \xFF|
 24.4599 ++\xFF       |
 24.4600 ++        \xFFä|
 24.4601 ++ä\xFF      |
 24.4602 ++        ä\xFF|
 24.4603 ++\xFF       ä|
 24.4604 ++äbcdef\xFF |
 24.4605 ++' > exp || framework_failure_
 24.4606 ++
 24.4607 ++expand < in > out || fail=1
 24.4608 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4609 ++
 24.4610 ++
 24.4611 ++
 24.4612 ++#BOM header test 1
 24.4613 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_
 24.4614 ++1234567812345678123456781
 24.4615 ++.       .       .       .
 24.4616 ++a	b	c	d
 24.4617 ++.       .       .       .
 24.4618 ++ä	ö	ü	ß
 24.4619 ++.       .       .       .
 24.4620 ++EOF
 24.4621 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 24.4622 ++
 24.4623 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 24.4624 ++1234567812345678123456781
 24.4625 ++.       .       .       .
 24.4626 ++a       b       c       d
 24.4627 ++.       .       .       .
 24.4628 ++ä       ö       ü       ß
 24.4629 ++.       .       .       .
 24.4630 ++   äöü  .    öüä.       ä xx
 24.4631 ++EOF
 24.4632 ++
 24.4633 ++
 24.4634 ++expand < in > out || fail=1
 24.4635 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4636 ++
 24.4637 ++LANG=C expand < in > out || fail=1
 24.4638 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4639 ++
 24.4640 ++LC_ALL=C expand < in > out || fail=1
 24.4641 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4642 ++
 24.4643 ++
 24.4644 ++printf '\xEF\xBB\xBF' > in1; cat <<\EOF >> in1 || framework_failure_
 24.4645 ++1234567812345678123456781
 24.4646 ++.       .       .       .
 24.4647 ++a	b	c	d
 24.4648 ++.       .       .       .
 24.4649 ++ä	ö	ü	ß
 24.4650 ++.       .       .       .
 24.4651 ++EOF
 24.4652 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in1 || framework_failure_
 24.4653 ++
 24.4654 ++
 24.4655 ++printf '\xEF\xBB\xBF' > exp; cat <<\EOF >> exp || framework_failure_
 24.4656 ++1234567812345678123456781
 24.4657 ++.       .       .       .
 24.4658 ++a       b       c       d
 24.4659 ++.       .       .       .
 24.4660 ++ä       ö       ü       ß
 24.4661 ++.       .       .       .
 24.4662 ++   äöü  .    öüä.       ä xx
 24.4663 ++1234567812345678123456781
 24.4664 ++.       .       .       .
 24.4665 ++a       b       c       d
 24.4666 ++.       .       .       .
 24.4667 ++ä       ö       ü       ß
 24.4668 ++.       .       .       .
 24.4669 ++   äöü  .    öüä.       ä xx
 24.4670 ++EOF
 24.4671 ++
 24.4672 ++expand in1 in1 > out || fail=1
 24.4673 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4674 ++
 24.4675 ++LANG=C expand in1 in1  > out || fail=1
 24.4676 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4677 ++
 24.4678 ++LC_ALL=C expand in1 in1 > out || fail=1
 24.4679 ++compare exp out > /dev/null 2>&1 || fail=1
 24.4680 ++
 24.4681 ++exit $fail
 24.4682 +diff -Naurp coreutils-8.27-orig/tests/i18n/sort.sh coreutils-8.27/tests/i18n/sort.sh
 24.4683 +--- coreutils-8.27-orig/tests/i18n/sort.sh	1969-12-31 18:00:00.000000000 -0600
 24.4684 ++++ coreutils-8.27/tests/i18n/sort.sh	2017-03-11 23:47:13.100285838 -0600
 24.4685 +@@ -0,0 +1,29 @@
 24.4686 ++#!/bin/sh
 24.4687 ++# Verify sort's multi-byte support.
 24.4688 ++
 24.4689 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 24.4690 ++print_ver_ sort
 24.4691 ++
 24.4692 ++export LC_ALL=en_US.UTF-8
 24.4693 ++locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 24.4694 ++  || skip_ "No UTF-8 locale available"
 24.4695 ++
 24.4696 ++# Enable heap consistency checkng on older systems
 24.4697 ++export MALLOC_CHECK_=2
 24.4698 ++
 24.4699 ++
 24.4700 ++# check buffer overflow issue due to
 24.4701 ++# expanding multi-byte representation due to case conversion
 24.4702 ++# https://bugzilla.suse.com/show_bug.cgi?id=928749
 24.4703 ++cat <<EOF > exp
 24.4704 ++.
 24.4705 ++ɑ
 24.4706 ++EOF
 24.4707 ++cat <<EOF | sort -f > out || fail=1
 24.4708 ++.
 24.4709 ++ɑ
 24.4710 ++EOF
 24.4711 ++compare exp out || { fail=1; cat out; }
 24.4712 ++
 24.4713 ++
 24.4714 ++Exit $fail
 24.4715 +diff -Naurp coreutils-8.27-orig/tests/local.mk coreutils-8.27/tests/local.mk
 24.4716 +--- coreutils-8.27-orig/tests/local.mk	2017-02-28 22:25:37.000000000 -0600
 24.4717 ++++ coreutils-8.27/tests/local.mk	2017-03-11 23:47:38.072058253 -0600
 24.4718 +@@ -352,6 +352,8 @@ all_tests =					\
 24.4719 +   tests/misc/sort-discrim.sh			\
 24.4720 +   tests/misc/sort-files0-from.pl		\
 24.4721 +   tests/misc/sort-float.sh			\
 24.4722 ++  tests/misc/sort-mb-tests.sh			\
 24.4723 ++  tests/i18n/sort.sh				\
 24.4724 +   tests/misc/sort-h-thousands-sep.sh		\
 24.4725 +   tests/misc/sort-merge.pl			\
 24.4726 +   tests/misc/sort-merge-fdlimit.sh		\
 24.4727 +@@ -544,6 +546,7 @@ all_tests =					\
 24.4728 +   tests/du/threshold.sh				\
 24.4729 +   tests/du/trailing-slash.sh			\
 24.4730 +   tests/du/two-args.sh				\
 24.4731 ++  tests/expand/mb.sh				\
 24.4732 +   tests/id/gnu-zero-uids.sh			\
 24.4733 +   tests/id/no-context.sh			\
 24.4734 +   tests/id/context.sh				\
 24.4735 +@@ -684,6 +687,7 @@ all_tests =					\
 24.4736 +   tests/touch/read-only.sh			\
 24.4737 +   tests/touch/relative.sh			\
 24.4738 +   tests/touch/trailing-slash.sh			\
 24.4739 ++  tests/unexpand/mb.sh				\
 24.4740 +   $(all_root_tests)
 24.4741 + 
 24.4742 + # See tests/factor/create-test.sh.
 24.4743 +diff -Naurp coreutils-8.27-orig/tests/misc/cut.pl coreutils-8.27/tests/misc/cut.pl
 24.4744 +--- coreutils-8.27-orig/tests/misc/cut.pl	2017-01-01 16:34:24.000000000 -0600
 24.4745 ++++ coreutils-8.27/tests/misc/cut.pl	2017-03-11 23:47:13.100285838 -0600
 24.4746 +@@ -23,9 +23,11 @@ use strict;
 24.4747 + # Turn off localization of executable's output.
 24.4748 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.4749 + 
 24.4750 +-my $mb_locale = $ENV{LOCALE_FR_UTF8};
 24.4751 ++my $mb_locale;
 24.4752 ++# uncommented enable multibyte paths
 24.4753 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.4754 + ! defined $mb_locale || $mb_locale eq 'none'
 24.4755 +-  and $mb_locale = 'C';
 24.4756 ++ and $mb_locale = 'C';
 24.4757 + 
 24.4758 + my $prog = 'cut';
 24.4759 + my $try = "Try '$prog --help' for more information.\n";
 24.4760 +@@ -240,6 +242,7 @@ if ($mb_locale ne 'C')
 24.4761 +         my @new_t = @$t;
 24.4762 +         my $test_name = shift @new_t;
 24.4763 + 
 24.4764 ++        next if ($test_name =~ "newline-[12][0-9]");
 24.4765 +         push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.4766 +       }
 24.4767 +     push @Tests, @new;
 24.4768 +diff -Naurp coreutils-8.27-orig/tests/misc/expand.pl coreutils-8.27/tests/misc/expand.pl
 24.4769 +--- coreutils-8.27-orig/tests/misc/expand.pl	2017-03-01 11:16:46.000000000 -0600
 24.4770 ++++ coreutils-8.27/tests/misc/expand.pl	2017-03-11 23:47:13.101285788 -0600
 24.4771 +@@ -27,6 +27,15 @@ my $prog = 'expand';
 24.4772 + # Turn off localization of executable's output.
 24.4773 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.4774 + 
 24.4775 ++#comment out next line to disable multibyte tests
 24.4776 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 24.4777 ++! defined $mb_locale || $mb_locale eq 'none'
 24.4778 ++ and $mb_locale = 'C';
 24.4779 ++
 24.4780 ++my $prog = 'expand';
 24.4781 ++my $try = "Try \`$prog --help' for more information.\n";
 24.4782 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.4783 ++
 24.4784 + my @Tests =
 24.4785 +   (
 24.4786 +    ['t1', '--tabs=3',     {IN=>"a\tb"}, {OUT=>"a  b"}],
 24.4787 +@@ -152,6 +161,8 @@ my @Tests =
 24.4788 +    ['trail9', '--tab=1,2 -t/5',{IN=>"\ta\tb\tc"}, {OUT=>" a   b    c"}],
 24.4789 + 
 24.4790 +    # Test errors
 24.4791 ++   # FIXME: The following tests contain ‘quoting’ specific to LC_MESSAGES
 24.4792 ++   # So we force LC_MESSAGES=C to make them pass.
 24.4793 +    ['e1', '--tabs="a"', {IN=>''}, {OUT=>''}, {EXIT=>1},
 24.4794 +     {ERR => "$prog: tab size contains invalid character(s): 'a'\n"}],
 24.4795 +    ['e2', "-t $UINTMAX_OFLOW", {IN=>''}, {OUT=>''}, {EXIT=>1},
 24.4796 +@@ -168,6 +179,37 @@ my @Tests =
 24.4797 +     {ERR => "$prog: '/' specifier not at start of number: '/'\n"}],
 24.4798 +   );
 24.4799 + 
 24.4800 ++if ($mb_locale ne 'C')
 24.4801 ++  {
 24.4802 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.4803 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.4804 ++    # provide coverage for the distro-added multi-byte code paths.
 24.4805 ++    my @new;
 24.4806 ++    foreach my $t (@Tests)
 24.4807 ++      {
 24.4808 ++        my @new_t = @$t;
 24.4809 ++        my $test_name = shift @new_t;
 24.4810 ++
 24.4811 ++        # Depending on whether expand is multi-byte-patched,
 24.4812 ++        # it emits different diagnostics:
 24.4813 ++        #   non-MB: invalid byte or field list
 24.4814 ++        #   MB:     invalid byte, character or field list
 24.4815 ++        # Adjust the expected error output accordingly.
 24.4816 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.4817 ++            (@new_t))
 24.4818 ++          {
 24.4819 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.4820 ++            push @new_t, $sub;
 24.4821 ++            push @$t, $sub;
 24.4822 ++          }
 24.4823 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LANG=$mb_locale LC_MESSAGES=C"}];
 24.4824 ++      }
 24.4825 ++    push @Tests, @new;
 24.4826 ++  }
 24.4827 ++
 24.4828 ++
 24.4829 ++@Tests = triple_test \@Tests;
 24.4830 ++
 24.4831 + my $save_temps = $ENV{DEBUG};
 24.4832 + my $verbose = $ENV{VERBOSE};
 24.4833 + 
 24.4834 +diff -Naurp coreutils-8.27-orig/tests/misc/fold.pl coreutils-8.27/tests/misc/fold.pl
 24.4835 +--- coreutils-8.27-orig/tests/misc/fold.pl	2017-01-01 16:34:24.000000000 -0600
 24.4836 ++++ coreutils-8.27/tests/misc/fold.pl	2017-03-11 23:47:13.101285788 -0600
 24.4837 +@@ -20,9 +20,18 @@ use strict;
 24.4838 + 
 24.4839 + (my $program_name = $0) =~ s|.*/||;
 24.4840 + 
 24.4841 ++my $prog = 'fold';
 24.4842 ++my $try = "Try \`$prog --help' for more information.\n";
 24.4843 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.4844 ++
 24.4845 + # Turn off localization of executable's output.
 24.4846 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.4847 + 
 24.4848 ++# uncommented to enable multibyte paths
 24.4849 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 24.4850 ++! defined $mb_locale || $mb_locale eq 'none'
 24.4851 ++ and $mb_locale = 'C';
 24.4852 ++
 24.4853 + my @Tests =
 24.4854 +   (
 24.4855 +    ['s1', '-w2 -s', {IN=>"a\t"}, {OUT=>"a\n\t"}],
 24.4856 +@@ -31,9 +40,48 @@ my @Tests =
 24.4857 +    ['s4', '-w4 -s', {IN=>"abc ef\n"}, {OUT=>"abc \nef\n"}],
 24.4858 +   );
 24.4859 + 
 24.4860 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 24.4861 ++# that uses an old-style option like +1.
 24.4862 ++if ($mb_locale ne 'C')
 24.4863 ++  {
 24.4864 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.4865 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.4866 ++    # provide coverage for the distro-added multi-byte code paths.
 24.4867 ++    my @new;
 24.4868 ++    foreach my $t (@Tests)
 24.4869 ++      {
 24.4870 ++        my @new_t = @$t;
 24.4871 ++        my $test_name = shift @new_t;
 24.4872 ++
 24.4873 ++        # Depending on whether fold is multi-byte-patched,
 24.4874 ++        # it emits different diagnostics:
 24.4875 ++        #   non-MB: invalid byte or field list
 24.4876 ++        #   MB:     invalid byte, character or field list
 24.4877 ++        # Adjust the expected error output accordingly.
 24.4878 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.4879 ++            (@new_t))
 24.4880 ++          {
 24.4881 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.4882 ++            push @new_t, $sub;
 24.4883 ++            push @$t, $sub;
 24.4884 ++          }
 24.4885 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.4886 ++      }
 24.4887 ++    push @Tests, @new;
 24.4888 ++  }
 24.4889 ++
 24.4890 ++@Tests = triple_test \@Tests;
 24.4891 ++
 24.4892 ++# Remember that triple_test creates from each test with exactly one "IN"
 24.4893 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 24.4894 ++# input from a file and from a pipe.  The pipe-reading test would fail
 24.4895 ++# due to a race condition about 1 in 20 times.
 24.4896 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 24.4897 ++# The others aren't susceptible because they have three inputs each.
 24.4898 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 24.4899 ++
 24.4900 + my $save_temps = $ENV{DEBUG};
 24.4901 + my $verbose = $ENV{VERBOSE};
 24.4902 + 
 24.4903 +-my $prog = 'fold';
 24.4904 + my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
 24.4905 + exit $fail;
 24.4906 +diff -Naurp coreutils-8.27-orig/tests/misc/join.pl coreutils-8.27/tests/misc/join.pl
 24.4907 +--- coreutils-8.27-orig/tests/misc/join.pl	2017-01-01 16:34:24.000000000 -0600
 24.4908 ++++ coreutils-8.27/tests/misc/join.pl	2017-03-11 23:47:13.102285737 -0600
 24.4909 +@@ -25,6 +25,15 @@ my $limits = getlimits ();
 24.4910 + 
 24.4911 + my $prog = 'join';
 24.4912 + 
 24.4913 ++my $try = "Try \`$prog --help' for more information.\n";
 24.4914 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.4915 ++
 24.4916 ++my $mb_locale;
 24.4917 ++#Comment out next line to disable multibyte tests
 24.4918 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.4919 ++! defined $mb_locale || $mb_locale eq 'none'
 24.4920 ++  and $mb_locale = 'C';
 24.4921 ++
 24.4922 + my $delim = chr 0247;
 24.4923 + sub t_subst ($)
 24.4924 + {
 24.4925 +@@ -329,8 +338,49 @@ foreach my $t (@tv)
 24.4926 +     push @Tests, $new_ent;
 24.4927 +   }
 24.4928 + 
 24.4929 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 24.4930 ++# that uses an old-style option like +1.
 24.4931 ++if ($mb_locale ne 'C')
 24.4932 ++  {
 24.4933 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.4934 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.4935 ++    # provide coverage for the distro-added multi-byte code paths.
 24.4936 ++    my @new;
 24.4937 ++    foreach my $t (@Tests)
 24.4938 ++      {
 24.4939 ++        my @new_t = @$t;
 24.4940 ++        my $test_name = shift @new_t;
 24.4941 ++
 24.4942 ++        # Depending on whether join is multi-byte-patched,
 24.4943 ++        # it emits different diagnostics:
 24.4944 ++        #   non-MB: invalid byte or field list
 24.4945 ++        #   MB:     invalid byte, character or field list
 24.4946 ++        # Adjust the expected error output accordingly.
 24.4947 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.4948 ++            (@new_t))
 24.4949 ++          {
 24.4950 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.4951 ++            push @new_t, $sub;
 24.4952 ++            push @$t, $sub;
 24.4953 ++          }
 24.4954 ++        #Adjust the output some error messages including test_name for mb
 24.4955 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR}}
 24.4956 ++             (@new_t))
 24.4957 ++          {
 24.4958 ++            my $sub2 = {ERR_SUBST => "s/$test_name-mb/$test_name/"};
 24.4959 ++            push @new_t, $sub2;
 24.4960 ++            push @$t, $sub2;
 24.4961 ++          }
 24.4962 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.4963 ++      }
 24.4964 ++    push @Tests, @new;
 24.4965 ++  }
 24.4966 ++
 24.4967 + @Tests = triple_test \@Tests;
 24.4968 + 
 24.4969 ++#skip invalid-j-mb test, it is failing because of the format
 24.4970 ++@Tests = grep {$_->[0] ne 'invalid-j-mb'} @Tests;
 24.4971 ++
 24.4972 + my $save_temps = $ENV{DEBUG};
 24.4973 + my $verbose = $ENV{VERBOSE};
 24.4974 + 
 24.4975 +diff -Naurp coreutils-8.27-orig/tests/misc/sort-mb-tests.sh coreutils-8.27/tests/misc/sort-mb-tests.sh
 24.4976 +--- coreutils-8.27-orig/tests/misc/sort-mb-tests.sh	1969-12-31 18:00:00.000000000 -0600
 24.4977 ++++ coreutils-8.27/tests/misc/sort-mb-tests.sh	2017-03-11 23:47:13.102285737 -0600
 24.4978 +@@ -0,0 +1,45 @@
 24.4979 ++#!/bin/sh
 24.4980 ++# Verify sort's multi-byte support.
 24.4981 ++
 24.4982 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 24.4983 ++print_ver_ sort
 24.4984 ++
 24.4985 ++export LC_ALL=en_US.UTF-8
 24.4986 ++locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 24.4987 ++  || skip_ "No UTF-8 locale available"
 24.4988 ++
 24.4989 ++
 24.4990 ++cat <<EOF > exp
 24.4991 ++Banana@5
 24.4992 ++Apple@10
 24.4993 ++Citrus@20
 24.4994 ++Cherry@30
 24.4995 ++EOF
 24.4996 ++
 24.4997 ++cat <<EOF | sort -t @ -k2 -n > out || fail=1
 24.4998 ++Apple@10
 24.4999 ++Banana@5
 24.5000 ++Citrus@20
 24.5001 ++Cherry@30
 24.5002 ++EOF
 24.5003 ++
 24.5004 ++compare exp out || { fail=1; cat out; }
 24.5005 ++
 24.5006 ++
 24.5007 ++cat <<EOF > exp
 24.5008 ++Citrus@AA20@@5
 24.5009 ++Cherry@AA30@@10
 24.5010 ++Apple@AA10@@20
 24.5011 ++Banana@AA5@@30
 24.5012 ++EOF
 24.5013 ++
 24.5014 ++cat <<EOF | sort -t @ -k4 -n > out || fail=1
 24.5015 ++Apple@AA10@@20
 24.5016 ++Banana@AA5@@30
 24.5017 ++Citrus@AA20@@5
 24.5018 ++Cherry@AA30@@10
 24.5019 ++EOF
 24.5020 ++
 24.5021 ++compare exp out || { fail=1; cat out; }
 24.5022 ++
 24.5023 ++Exit $fail
 24.5024 +diff -Naurp coreutils-8.27-orig/tests/misc/sort-merge.pl coreutils-8.27/tests/misc/sort-merge.pl
 24.5025 +--- coreutils-8.27-orig/tests/misc/sort-merge.pl	2017-01-01 16:34:24.000000000 -0600
 24.5026 ++++ coreutils-8.27/tests/misc/sort-merge.pl	2017-03-11 23:47:13.102285737 -0600
 24.5027 +@@ -26,6 +26,15 @@ my $prog = 'sort';
 24.5028 + # Turn off localization of executable's output.
 24.5029 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.5030 + 
 24.5031 ++my $mb_locale;
 24.5032 ++# uncommented according to upstream commit enabling multibyte paths
 24.5033 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5034 ++! defined $mb_locale || $mb_locale eq 'none'
 24.5035 ++ and $mb_locale = 'C';
 24.5036 ++
 24.5037 ++my $try = "Try \`$prog --help' for more information.\n";
 24.5038 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.5039 ++
 24.5040 + # three empty files and one that says 'foo'
 24.5041 + my @inputs = (+(map{{IN=> {"empty$_"=> ''}}}1..3), {IN=> {foo=> "foo\n"}});
 24.5042 + 
 24.5043 +@@ -77,6 +86,39 @@ my @Tests =
 24.5044 +         {OUT=>$big_input}],
 24.5045 +     );
 24.5046 + 
 24.5047 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 24.5048 ++# that uses an old-style option like +1.
 24.5049 ++if ($mb_locale ne 'C')
 24.5050 ++  {
 24.5051 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.5052 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.5053 ++    # provide coverage for the distro-added multi-byte code paths.
 24.5054 ++    my @new;
 24.5055 ++    foreach my $t (@Tests)
 24.5056 ++      {
 24.5057 ++        my @new_t = @$t;
 24.5058 ++        my $test_name = shift @new_t;
 24.5059 ++
 24.5060 ++        # Depending on whether sort is multi-byte-patched,
 24.5061 ++        # it emits different diagnostics:
 24.5062 ++        #   non-MB: invalid byte or field list
 24.5063 ++        #   MB:     invalid byte, character or field list
 24.5064 ++        # Adjust the expected error output accordingly.
 24.5065 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.5066 ++            (@new_t))
 24.5067 ++          {
 24.5068 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.5069 ++            push @new_t, $sub;
 24.5070 ++            push @$t, $sub;
 24.5071 ++          }
 24.5072 ++        next if ($test_name =~ "nmerge-.");
 24.5073 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.5074 ++      }
 24.5075 ++    push @Tests, @new;
 24.5076 ++  }
 24.5077 ++
 24.5078 ++@Tests = triple_test \@Tests;
 24.5079 ++
 24.5080 + my $save_temps = $ENV{DEBUG};
 24.5081 + my $verbose = $ENV{VERBOSE};
 24.5082 + 
 24.5083 +diff -Naurp coreutils-8.27-orig/tests/misc/sort.pl coreutils-8.27/tests/misc/sort.pl
 24.5084 +--- coreutils-8.27-orig/tests/misc/sort.pl	2017-01-21 08:53:43.000000000 -0600
 24.5085 ++++ coreutils-8.27/tests/misc/sort.pl	2017-03-11 23:47:13.103285687 -0600
 24.5086 +@@ -24,10 +24,15 @@ my $prog = 'sort';
 24.5087 + # Turn off localization of executable's output.
 24.5088 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.5089 + 
 24.5090 +-my $mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5091 ++my $mb_locale;
 24.5092 ++#Comment out next line to disable multibyte tests
 24.5093 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5094 + ! defined $mb_locale || $mb_locale eq 'none'
 24.5095 +   and $mb_locale = 'C';
 24.5096 + 
 24.5097 ++my $try = "Try \`$prog --help' for more information.\n";
 24.5098 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.5099 ++
 24.5100 + # Since each test is run with a file name and with redirected stdin,
 24.5101 + # the name in the diagnostic is either the file name or "-".
 24.5102 + # Normalize each diagnostic to use '-'.
 24.5103 +@@ -423,6 +428,38 @@ foreach my $t (@Tests)
 24.5104 +       }
 24.5105 +   }
 24.5106 + 
 24.5107 ++if ($mb_locale ne 'C')
 24.5108 ++   {
 24.5109 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.5110 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.5111 ++    # provide coverage for the distro-added multi-byte code paths.
 24.5112 ++    my @new;
 24.5113 ++    foreach my $t (@Tests)
 24.5114 ++       {
 24.5115 ++        my @new_t = @$t;
 24.5116 ++        my $test_name = shift @new_t;
 24.5117 ++
 24.5118 ++        # Depending on whether sort is multi-byte-patched,
 24.5119 ++        # it emits different diagnostics:
 24.5120 ++        #   non-MB: invalid byte or field list
 24.5121 ++        #   MB:     invalid byte, character or field list
 24.5122 ++        # Adjust the expected error output accordingly.
 24.5123 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.5124 ++            (@new_t))
 24.5125 ++          {
 24.5126 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.5127 ++            push @new_t, $sub;
 24.5128 ++            push @$t, $sub;
 24.5129 ++          }
 24.5130 ++        #disable several failing tests until investigation, disable all tests with envvars set
 24.5131 ++        next if (grep {ref $_ eq 'HASH' && exists $_->{ENV}} (@new_t));
 24.5132 ++        next if ($test_name =~ "18g" or $test_name =~ "sort-numeric" or $test_name =~ "08[ab]" or $test_name =~ "03[def]" or $test_name =~ "h4" or $test_name =~ "n1" or $test_name =~ "2[01]a");
 24.5133 ++        next if ($test_name =~ "11[ab]"); # avoid FP: expected result differs to MB result due to collation rules.
 24.5134 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.5135 ++       }
 24.5136 ++    push @Tests, @new;
 24.5137 ++   }
 24.5138 ++
 24.5139 + @Tests = triple_test \@Tests;
 24.5140 + 
 24.5141 + # Remember that triple_test creates from each test with exactly one "IN"
 24.5142 +@@ -432,6 +469,7 @@ foreach my $t (@Tests)
 24.5143 + # Remove the IN_PIPE version of the "output-is-input" test above.
 24.5144 + # The others aren't susceptible because they have three inputs each.
 24.5145 + @Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 24.5146 ++@Tests = grep {$_->[0] ne 'output-is-input-mb.p'} @Tests;
 24.5147 + 
 24.5148 + my $save_temps = $ENV{DEBUG};
 24.5149 + my $verbose = $ENV{VERBOSE};
 24.5150 +diff -Naurp coreutils-8.27-orig/tests/misc/unexpand.pl coreutils-8.27/tests/misc/unexpand.pl
 24.5151 +--- coreutils-8.27-orig/tests/misc/unexpand.pl	2017-01-01 16:34:24.000000000 -0600
 24.5152 ++++ coreutils-8.27/tests/misc/unexpand.pl	2017-03-11 23:47:13.103285687 -0600
 24.5153 +@@ -27,6 +27,14 @@ my $limits = getlimits ();
 24.5154 + 
 24.5155 + my $prog = 'unexpand';
 24.5156 + 
 24.5157 ++# comment out next line to disable multibyte tests
 24.5158 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5159 ++! defined $mb_locale || $mb_locale eq 'none'
 24.5160 ++ and $mb_locale = 'C';
 24.5161 ++
 24.5162 ++my $try = "Try \`$prog --help' for more information.\n";
 24.5163 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.5164 ++
 24.5165 + my @Tests =
 24.5166 +     (
 24.5167 +      ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}],
 24.5168 +@@ -128,6 +136,37 @@ my @Tests =
 24.5169 +      ['ts2', '-t5,8', {IN=>"x\t \t y\n"},    {OUT=>"x\t\t y\n"}],
 24.5170 +     );
 24.5171 + 
 24.5172 ++if ($mb_locale ne 'C')
 24.5173 ++  {
 24.5174 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.5175 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.5176 ++    # provide coverage for the distro-added multi-byte code paths.
 24.5177 ++    my @new;
 24.5178 ++    foreach my $t (@Tests)
 24.5179 ++      {
 24.5180 ++        my @new_t = @$t;
 24.5181 ++        my $test_name = shift @new_t;
 24.5182 ++
 24.5183 ++        # Depending on whether unexpand is multi-byte-patched,
 24.5184 ++        # it emits different diagnostics:
 24.5185 ++        #   non-MB: invalid byte or field list
 24.5186 ++        #   MB:     invalid byte, character or field list
 24.5187 ++        # Adjust the expected error output accordingly.
 24.5188 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.5189 ++            (@new_t))
 24.5190 ++          {
 24.5191 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.5192 ++            push @new_t, $sub;
 24.5193 ++            push @$t, $sub;
 24.5194 ++          }
 24.5195 ++        next if ($test_name =~ 'b-1');
 24.5196 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.5197 ++      }
 24.5198 ++    push @Tests, @new;
 24.5199 ++  }
 24.5200 ++
 24.5201 ++@Tests = triple_test \@Tests;
 24.5202 ++
 24.5203 + my $save_temps = $ENV{DEBUG};
 24.5204 + my $verbose = $ENV{VERBOSE};
 24.5205 + 
 24.5206 +diff -Naurp coreutils-8.27-orig/tests/misc/uniq.pl coreutils-8.27/tests/misc/uniq.pl
 24.5207 +--- coreutils-8.27-orig/tests/misc/uniq.pl	2017-01-01 16:34:24.000000000 -0600
 24.5208 ++++ coreutils-8.27/tests/misc/uniq.pl	2017-03-11 23:47:13.103285687 -0600
 24.5209 +@@ -23,9 +23,17 @@ my $limits = getlimits ();
 24.5210 + my $prog = 'uniq';
 24.5211 + my $try = "Try '$prog --help' for more information.\n";
 24.5212 + 
 24.5213 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.5214 ++
 24.5215 + # Turn off localization of executable's output.
 24.5216 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 24.5217 + 
 24.5218 ++my $mb_locale;
 24.5219 ++#Comment out next line to disable multibyte tests
 24.5220 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5221 ++! defined $mb_locale || $mb_locale eq 'none'
 24.5222 ++  and $mb_locale = 'C';
 24.5223 ++
 24.5224 + # When possible, create a "-z"-testing variant of each test.
 24.5225 + sub add_z_variants($)
 24.5226 + {
 24.5227 +@@ -262,6 +270,53 @@ foreach my $t (@Tests)
 24.5228 +       and push @$t, {ENV=>'_POSIX2_VERSION=199209'};
 24.5229 +   }
 24.5230 + 
 24.5231 ++if ($mb_locale ne 'C')
 24.5232 ++  {
 24.5233 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.5234 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.5235 ++    # provide coverage for the distro-added multi-byte code paths.
 24.5236 ++    my @new;
 24.5237 ++    foreach my $t (@Tests)
 24.5238 ++      {
 24.5239 ++        my @new_t = @$t;
 24.5240 ++        my $test_name = shift @new_t;
 24.5241 ++
 24.5242 ++        # Depending on whether uniq is multi-byte-patched,
 24.5243 ++        # it emits different diagnostics:
 24.5244 ++        #   non-MB: invalid byte or field list
 24.5245 ++        #   MB:     invalid byte, character or field list
 24.5246 ++        # Adjust the expected error output accordingly.
 24.5247 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.5248 ++            (@new_t))
 24.5249 ++          {
 24.5250 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.5251 ++            push @new_t, $sub;
 24.5252 ++            push @$t, $sub;
 24.5253 ++          }
 24.5254 ++        # In test #145, replace the each ‘...’ by '...'.
 24.5255 ++        if ($test_name =~ "145")
 24.5256 ++          {
 24.5257 ++            my $sub = { ERR_SUBST => "s/‘([^’]+)’/'\$1'/g"};
 24.5258 ++            push @new_t, $sub;
 24.5259 ++            push @$t, $sub;
 24.5260 ++          }
 24.5261 ++        next if (   $test_name =~ "schar"
 24.5262 ++                 or $test_name =~ "^obs-plus"
 24.5263 ++                 or $test_name =~ "119");
 24.5264 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.5265 ++      }
 24.5266 ++    push @Tests, @new;
 24.5267 ++   }
 24.5268 ++
 24.5269 ++# Remember that triple_test creates from each test with exactly one "IN"
 24.5270 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 24.5271 ++# input from a file and from a pipe.  The pipe-reading test would fail
 24.5272 ++# due to a race condition about 1 in 20 times.
 24.5273 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 24.5274 ++# The others aren't susceptible because they have three inputs each.
 24.5275 ++
 24.5276 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 24.5277 ++
 24.5278 + @Tests = add_z_variants \@Tests;
 24.5279 + @Tests = triple_test \@Tests;
 24.5280 + 
 24.5281 +diff -Naurp coreutils-8.27-orig/tests/pr/pr-tests.pl coreutils-8.27/tests/pr/pr-tests.pl
 24.5282 +--- coreutils-8.27-orig/tests/pr/pr-tests.pl	2017-01-01 16:34:24.000000000 -0600
 24.5283 ++++ coreutils-8.27/tests/pr/pr-tests.pl	2017-03-11 23:47:13.103285687 -0600
 24.5284 +@@ -24,6 +24,15 @@ use strict;
 24.5285 + my $prog = 'pr';
 24.5286 + my $normalize_strerror = "s/': .*/'/";
 24.5287 + 
 24.5288 ++my $mb_locale;
 24.5289 ++#Uncomment the following line to enable multibyte tests
 24.5290 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 24.5291 ++! defined $mb_locale || $mb_locale eq 'none'
 24.5292 ++  and $mb_locale = 'C';
 24.5293 ++
 24.5294 ++my $try = "Try \`$prog --help' for more information.\n";
 24.5295 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 24.5296 ++
 24.5297 + my @tv = (
 24.5298 + 
 24.5299 + # -b option is no longer an official option. But it's still working to
 24.5300 +@@ -474,8 +483,48 @@ push @Tests,
 24.5301 +     {IN=>{2=>"a\n"}},
 24.5302 +      {OUT=>"a\t\t\t\t  \t\t\ta\n"} ];
 24.5303 + 
 24.5304 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 24.5305 ++# that uses an old-style option like +1.
 24.5306 ++if ($mb_locale ne 'C')
 24.5307 ++  {
 24.5308 ++    # Duplicate each test vector, appending "-mb" to the test name and
 24.5309 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 24.5310 ++    # provide coverage for the distro-added multi-byte code paths.
 24.5311 ++    my @new;
 24.5312 ++    foreach my $t (@Tests)
 24.5313 ++      {
 24.5314 ++        my @new_t = @$t;
 24.5315 ++        my $test_name = shift @new_t;
 24.5316 ++
 24.5317 ++        # Depending on whether pr is multi-byte-patched,
 24.5318 ++        # it emits different diagnostics:
 24.5319 ++        #   non-MB: invalid byte or field list
 24.5320 ++        #   MB:     invalid byte, character or field list
 24.5321 ++        # Adjust the expected error output accordingly.
 24.5322 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 24.5323 ++            (@new_t))
 24.5324 ++          {
 24.5325 ++            my $sub = {ERR_SUBST => 's/, character//'};
 24.5326 ++            push @new_t, $sub;
 24.5327 ++            push @$t, $sub;
 24.5328 ++          }
 24.5329 ++        #temporarily skip some failing tests
 24.5330 ++        next if ($test_name =~ "col-0" or $test_name =~ "col-inval" or $test_name =~ "asan1");
 24.5331 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 24.5332 ++      }
 24.5333 ++    push @Tests, @new;
 24.5334 ++  }
 24.5335 ++
 24.5336 + @Tests = triple_test \@Tests;
 24.5337 + 
 24.5338 ++# Remember that triple_test creates from each test with exactly one "IN"
 24.5339 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 24.5340 ++# input from a file and from a pipe.  The pipe-reading test would fail
 24.5341 ++# due to a race condition about 1 in 20 times.
 24.5342 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 24.5343 ++# The others aren't susceptible because they have three inputs each.
 24.5344 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 24.5345 ++
 24.5346 + my $save_temps = $ENV{DEBUG};
 24.5347 + my $verbose = $ENV{VERBOSE};
 24.5348 + 
 24.5349 +diff -Naurp coreutils-8.27-orig/tests/unexpand/mb.sh coreutils-8.27/tests/unexpand/mb.sh
 24.5350 +--- coreutils-8.27-orig/tests/unexpand/mb.sh	1969-12-31 18:00:00.000000000 -0600
 24.5351 ++++ coreutils-8.27/tests/unexpand/mb.sh	2017-03-11 23:49:06.759133489 -0600
 24.5352 +@@ -0,0 +1,172 @@
 24.5353 ++#!/bin/sh
 24.5354 ++
 24.5355 ++# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 24.5356 ++
 24.5357 ++# This program is free software: you can redistribute it and/or modify
 24.5358 ++# it under the terms of the GNU General Public License as published by
 24.5359 ++# the Free Software Foundation, either version 3 of the License, or
 24.5360 ++# (at your option) any later version.
 24.5361 ++
 24.5362 ++# This program is distributed in the hope that it will be useful,
 24.5363 ++# but WITHOUT ANY WARRANTY; without even the implied warranty of
 24.5364 ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 24.5365 ++# GNU General Public License for more details.
 24.5366 ++
 24.5367 ++# You should have received a copy of the GNU General Public License
 24.5368 ++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 24.5369 ++
 24.5370 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 24.5371 ++print_ver_ unexpand
 24.5372 ++
 24.5373 ++export LC_ALL=en_US.UTF-8
 24.5374 ++
 24.5375 ++#input containing multibyte characters
 24.5376 ++cat > in <<\EOF
 24.5377 ++1234567812345678123456781
 24.5378 ++.       .       .       .
 24.5379 ++a       b       c       d
 24.5380 ++.       .       .       .
 24.5381 ++ä       ö       ü       ß
 24.5382 ++.       .       .       .
 24.5383 ++   äöü  .    öüä.       ä xx
 24.5384 ++EOF
 24.5385 ++
 24.5386 ++cat > exp <<\EOF
 24.5387 ++1234567812345678123456781
 24.5388 ++.	.	.	.
 24.5389 ++a	b	c	d
 24.5390 ++.	.	.	.
 24.5391 ++ä	ö	ü	ß
 24.5392 ++.	.	.	.
 24.5393 ++   äöü	.    öüä.	ä xx
 24.5394 ++EOF
 24.5395 ++
 24.5396 ++unexpand -a < in > out || fail=1
 24.5397 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5398 ++
 24.5399 ++
 24.5400 ++#multiple files as an input
 24.5401 ++cat >> exp <<\EOF
 24.5402 ++1234567812345678123456781
 24.5403 ++.	.	.	.
 24.5404 ++a	b	c	d
 24.5405 ++.	.	.	.
 24.5406 ++ä	ö	ü	ß
 24.5407 ++.	.	.	.
 24.5408 ++   äöü	.    öüä.	ä xx
 24.5409 ++EOF
 24.5410 ++
 24.5411 ++
 24.5412 ++unexpand -a ./in ./in > out || fail=1
 24.5413 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5414 ++
 24.5415 ++#test characters with a display width larger than 1
 24.5416 ++
 24.5417 ++env printf '12345678
 24.5418 ++e       |ascii(1)
 24.5419 ++\u00E9       |composed(1)
 24.5420 ++e\u0301       |decomposed(1)
 24.5421 ++\u3000      |ideo-space(2)
 24.5422 ++\uFF0D      |full-hypen(2)
 24.5423 ++' > in || framework_failure_
 24.5424 ++
 24.5425 ++env printf '12345678
 24.5426 ++e\t|ascii(1)
 24.5427 ++\u00E9\t|composed(1)
 24.5428 ++e\u0301\t|decomposed(1)
 24.5429 ++\u3000\t|ideo-space(2)
 24.5430 ++\uFF0D\t|full-hypen(2)
 24.5431 ++' > exp || framework_failure_
 24.5432 ++
 24.5433 ++unexpand -a < in > out || fail=1
 24.5434 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5435 ++
 24.5436 ++#test input where a blank of width > 1 is not being substituted
 24.5437 ++in="$(LC_ALL=en_US.UTF-8 printf ' \u3000  ö       ü       ß')"
 24.5438 ++exp='    ö	     ü	     ß'
 24.5439 ++
 24.5440 ++unexpand -a < in > out || fail=1
 24.5441 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5442 ++
 24.5443 ++#non-Unicode characters interspersed between Unicode ones
 24.5444 ++env printf '12345678
 24.5445 ++        \xFF|
 24.5446 ++\xFF       |
 24.5447 ++        \xFFä|
 24.5448 ++ä\xFF      |
 24.5449 ++        ä\xFF|
 24.5450 ++\xFF       ä|
 24.5451 ++äbcdef\xFF |
 24.5452 ++' > in || framework_failure_
 24.5453 ++
 24.5454 ++env printf '12345678
 24.5455 ++\t\xFF|
 24.5456 ++\xFF\t|
 24.5457 ++\t\xFFä|
 24.5458 ++ä\xFF\t|
 24.5459 ++\tä\xFF|
 24.5460 ++\xFF\tä|
 24.5461 ++äbcdef\xFF\t|
 24.5462 ++' > exp || framework_failure_
 24.5463 ++
 24.5464 ++unexpand -a < in > out || fail=1
 24.5465 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5466 ++
 24.5467 ++#BOM header test 1
 24.5468 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_
 24.5469 ++1234567812345678123456781
 24.5470 ++.       .       .       .
 24.5471 ++a       b       c       d
 24.5472 ++.       .       .       .
 24.5473 ++ä       ö       ü       ß
 24.5474 ++.       .       .       .
 24.5475 ++   äöü  .    öüä.       ä xx
 24.5476 ++EOF
 24.5477 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 24.5478 ++
 24.5479 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 24.5480 ++1234567812345678123456781
 24.5481 ++.	.	.	.
 24.5482 ++a	b	c	d
 24.5483 ++.	.	.	.
 24.5484 ++ä	ö	ü	ß
 24.5485 ++.	.	.	.
 24.5486 ++   äöü	.    öüä.	ä xx
 24.5487 ++EOF
 24.5488 ++
 24.5489 ++unexpand < in > out || fail=1
 24.5490 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5491 ++
 24.5492 ++LANG=C unexpand < in > out || fail=1
 24.5493 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5494 ++
 24.5495 ++LC_ALL=C unexpand < in > out || fail=1
 24.5496 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5497 ++
 24.5498 ++
 24.5499 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 24.5500 ++1234567812345678123456781
 24.5501 ++.	.	.	.
 24.5502 ++a	b	c	d
 24.5503 ++.	.	.	.
 24.5504 ++ä	ö	ü	ß
 24.5505 ++.	.	.	.
 24.5506 ++   äöü	.    öüä.	ä xx
 24.5507 ++1234567812345678123456781
 24.5508 ++.	.	.	.
 24.5509 ++a	b	c	d
 24.5510 ++.	.	.	.
 24.5511 ++ä	ö	ü	ß
 24.5512 ++.	.	.	.
 24.5513 ++   äöü	.    öüä.	ä xx
 24.5514 ++EOF
 24.5515 ++
 24.5516 ++
 24.5517 ++unexpand in in > out || fail=1
 24.5518 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5519 ++
 24.5520 ++LANG=C unexpand in in > out || fail=1
 24.5521 ++compare exp out > /dev/null 2>&1 || fail=1
 24.5522 ++
 24.5523 ++LC_ALL=C unexpand in in > out || fail=1
 24.5524 ++compare exp out > /dev/null 2>&1 || fail=1
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/coreutils/stuff/patches/coreutils-8.29-i18n-1.patch	Wed Feb 21 19:48:17 2018 +0200
    25.3 @@ -0,0 +1,5521 @@
    25.4 +Submitted by:            DJ Lucas (dj_AT_linuxfromscratch_DOT_org)
    25.5 +Date:                    2017-03-12
    25.6 +Initial Package Version: 8.27
    25.7 +Upstream Status:         Rejected
    25.8 +Origin:                  Based on Fedora's i18n patches at
    25.9 +                         http://pkgs.fedoraproject.org/cgit/rpms/coreutils.git/tree/
   25.10 +Description:             Fixes i18n issues with various Coreutils programs
   25.11 +
   25.12 +diff -Naurp coreutils-8.27-orig/bootstrap.conf coreutils-8.27/bootstrap.conf
   25.13 +--- coreutils-8.27-orig/bootstrap.conf	2017-03-07 23:34:06.000000000 -0600
   25.14 ++++ coreutils-8.27/bootstrap.conf	2017-03-11 23:47:38.068058445 -0600
   25.15 +@@ -152,6 +152,7 @@ gnulib_modules="
   25.16 +   maintainer-makefile
   25.17 +   malloc-gnu
   25.18 +   manywarnings
   25.19 ++  mbfile
   25.20 +   mbrlen
   25.21 +   mbrtowc
   25.22 +   mbsalign
   25.23 +diff -Naurp coreutils-8.27-orig/configure.ac coreutils-8.27/configure.ac
   25.24 +--- coreutils-8.27-orig/configure.ac	2017-02-26 08:52:29.000000000 -0600
   25.25 ++++ coreutils-8.27/configure.ac	2017-03-11 23:47:38.068058445 -0600
   25.26 +@@ -429,6 +429,8 @@ fi
   25.27 + # I'm leaving it here for now.  This whole thing needs to be modernized...
   25.28 + gl_WINSIZE_IN_PTEM
   25.29 + 
   25.30 ++gl_MBFILE
   25.31 ++
   25.32 + gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H
   25.33 + 
   25.34 + if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \
   25.35 +diff -Naurp coreutils-8.27-orig/lib/linebuffer.h coreutils-8.27/lib/linebuffer.h
   25.36 +--- coreutils-8.27-orig/lib/linebuffer.h	2017-01-01 16:35:38.000000000 -0600
   25.37 ++++ coreutils-8.27/lib/linebuffer.h	2017-03-11 23:47:13.089286391 -0600
   25.38 +@@ -21,6 +21,11 @@
   25.39 + 
   25.40 + # include <stdio.h>
   25.41 + 
   25.42 ++/* Get mbstate_t.  */
   25.43 ++# if HAVE_WCHAR_H
   25.44 ++#  include <wchar.h>
   25.45 ++# endif
   25.46 ++
   25.47 + /* A 'struct linebuffer' holds a line of text. */
   25.48 + 
   25.49 + struct linebuffer
   25.50 +@@ -28,6 +33,9 @@ struct linebuffer
   25.51 +   size_t size;                  /* Allocated. */
   25.52 +   size_t length;                /* Used. */
   25.53 +   char *buffer;
   25.54 ++# if HAVE_WCHAR_H
   25.55 ++  mbstate_t state;
   25.56 ++# endif
   25.57 + };
   25.58 + 
   25.59 + /* Initialize linebuffer LINEBUFFER for use. */
   25.60 +diff -Naurp coreutils-8.27-orig/lib/mbfile.c coreutils-8.27/lib/mbfile.c
   25.61 +--- coreutils-8.27-orig/lib/mbfile.c	1969-12-31 18:00:00.000000000 -0600
   25.62 ++++ coreutils-8.27/lib/mbfile.c	2017-03-11 23:47:38.069058397 -0600
   25.63 +@@ -0,0 +1,3 @@
   25.64 ++#include <config.h>
   25.65 ++#define MBFILE_INLINE _GL_EXTERN_INLINE
   25.66 ++#include "mbfile.h"
   25.67 +diff -Naurp coreutils-8.27-orig/lib/mbfile.h coreutils-8.27/lib/mbfile.h
   25.68 +--- coreutils-8.27-orig/lib/mbfile.h	1969-12-31 18:00:00.000000000 -0600
   25.69 ++++ coreutils-8.27/lib/mbfile.h	2017-03-11 23:47:38.069058397 -0600
   25.70 +@@ -0,0 +1,255 @@
   25.71 ++/* Multibyte character I/O: macros for multi-byte encodings.
   25.72 ++   Copyright (C) 2001, 2005, 2009-2017 Free Software Foundation, Inc.
   25.73 ++
   25.74 ++   This program is free software: you can redistribute it and/or modify
   25.75 ++   it under the terms of the GNU General Public License as published by
   25.76 ++   the Free Software Foundation; either version 3 of the License, or
   25.77 ++   (at your option) any later version.
   25.78 ++
   25.79 ++   This program is distributed in the hope that it will be useful,
   25.80 ++   but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.81 ++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.82 ++   GNU General Public License for more details.
   25.83 ++
   25.84 ++   You should have received a copy of the GNU General Public License
   25.85 ++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   25.86 ++
   25.87 ++/* Written by Mitsuru Chinen <mchinen@yamato.ibm.com>
   25.88 ++   and Bruno Haible <bruno@clisp.org>.  */
   25.89 ++
   25.90 ++/* The macros in this file implement multi-byte character input from a
   25.91 ++   stream.
   25.92 ++
   25.93 ++   mb_file_t
   25.94 ++     is the type for multibyte character input stream, usable for variable
   25.95 ++     declarations.
   25.96 ++
   25.97 ++   mbf_char_t
   25.98 ++     is the type for multibyte character or EOF, usable for variable
   25.99 ++     declarations.
  25.100 ++
  25.101 ++   mbf_init (mbf, stream)
  25.102 ++     initializes the MB_FILE for reading from stream.
  25.103 ++
  25.104 ++   mbf_getc (mbc, mbf)
  25.105 ++     reads the next multibyte character from mbf and stores it in mbc.
  25.106 ++
  25.107 ++   mb_iseof (mbc)
  25.108 ++     returns true if mbc represents the EOF value.
  25.109 ++
  25.110 ++   Here are the function prototypes of the macros.
  25.111 ++
  25.112 ++   extern void          mbf_init (mb_file_t mbf, FILE *stream);
  25.113 ++   extern void          mbf_getc (mbf_char_t mbc, mb_file_t mbf);
  25.114 ++   extern bool          mb_iseof (const mbf_char_t mbc);
  25.115 ++ */
  25.116 ++
  25.117 ++#ifndef _MBFILE_H
  25.118 ++#define _MBFILE_H 1
  25.119 ++
  25.120 ++#include <assert.h>
  25.121 ++#include <stdbool.h>
  25.122 ++#include <stdio.h>
  25.123 ++#include <string.h>
  25.124 ++
  25.125 ++/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
  25.126 ++   <wchar.h>.
  25.127 ++   BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
  25.128 ++   <wchar.h>.  */
  25.129 ++#include <stdio.h>
  25.130 ++#include <time.h>
  25.131 ++#include <wchar.h>
  25.132 ++
  25.133 ++#include "mbchar.h"
  25.134 ++
  25.135 ++#ifndef _GL_INLINE_HEADER_BEGIN
  25.136 ++ #error "Please include config.h first."
  25.137 ++#endif
  25.138 ++_GL_INLINE_HEADER_BEGIN
  25.139 ++#ifndef MBFILE_INLINE
  25.140 ++# define MBFILE_INLINE _GL_INLINE
  25.141 ++#endif
  25.142 ++
  25.143 ++struct mbfile_multi {
  25.144 ++  FILE *fp;
  25.145 ++  bool eof_seen;
  25.146 ++  bool have_pushback;
  25.147 ++  mbstate_t state;
  25.148 ++  unsigned int bufcount;
  25.149 ++  char buf[MBCHAR_BUF_SIZE];
  25.150 ++  struct mbchar pushback;
  25.151 ++};
  25.152 ++
  25.153 ++MBFILE_INLINE void
  25.154 ++mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf)
  25.155 ++{
  25.156 ++  size_t bytes;
  25.157 ++
  25.158 ++  /* If EOF has already been seen, don't use getc.  This matters if
  25.159 ++     mbf->fp is connected to an interactive tty.  */
  25.160 ++  if (mbf->eof_seen)
  25.161 ++    goto eof;
  25.162 ++
  25.163 ++  /* Return character pushed back, if there is one.  */
  25.164 ++  if (mbf->have_pushback)
  25.165 ++    {
  25.166 ++      mb_copy (mbc, &mbf->pushback);
  25.167 ++      mbf->have_pushback = false;
  25.168 ++      return;
  25.169 ++    }
  25.170 ++
  25.171 ++  /* Before using mbrtowc, we need at least one byte.  */
  25.172 ++  if (mbf->bufcount == 0)
  25.173 ++    {
  25.174 ++      int c = getc (mbf->fp);
  25.175 ++      if (c == EOF)
  25.176 ++        {
  25.177 ++          mbf->eof_seen = true;
  25.178 ++          goto eof;
  25.179 ++        }
  25.180 ++      mbf->buf[0] = (unsigned char) c;
  25.181 ++      mbf->bufcount++;
  25.182 ++    }
  25.183 ++
  25.184 ++  /* Handle most ASCII characters quickly, without calling mbrtowc().  */
  25.185 ++  if (mbf->bufcount == 1 && mbsinit (&mbf->state) && is_basic (mbf->buf[0]))
  25.186 ++    {
  25.187 ++      /* These characters are part of the basic character set.  ISO C 99
  25.188 ++         guarantees that their wide character code is identical to their
  25.189 ++         char code.  */
  25.190 ++      mbc->wc = mbc->buf[0] = mbf->buf[0];
  25.191 ++      mbc->wc_valid = true;
  25.192 ++      mbc->ptr = &mbc->buf[0];
  25.193 ++      mbc->bytes = 1;
  25.194 ++      mbf->bufcount = 0;
  25.195 ++      return;
  25.196 ++    }
  25.197 ++
  25.198 ++  /* Use mbrtowc on an increasing number of bytes.  Read only as many bytes
  25.199 ++     from mbf->fp as needed.  This is needed to give reasonable interactive
  25.200 ++     behaviour when mbf->fp is connected to an interactive tty.  */
  25.201 ++  for (;;)
  25.202 ++    {
  25.203 ++      /* We don't know whether the 'mbrtowc' function updates the state when
  25.204 ++         it returns -2, - this is the ISO C 99 and glibc-2.2 behaviour - or
  25.205 ++         not - amended ANSI C, glibc-2.1 and Solaris 2.7 behaviour.  We
  25.206 ++         don't have an autoconf test for this, yet.
  25.207 ++         The new behaviour would allow us to feed the bytes one by one into
  25.208 ++         mbrtowc.  But the old behaviour forces us to feed all bytes since
  25.209 ++         the end of the last character into mbrtowc.  Since we want to retry
  25.210 ++         with more bytes when mbrtowc returns -2, we must backup the state
  25.211 ++         before calling mbrtowc, because implementations with the new
  25.212 ++         behaviour will clobber it.  */
  25.213 ++      mbstate_t backup_state = mbf->state;
  25.214 ++
  25.215 ++      bytes = mbrtowc (&mbc->wc, &mbf->buf[0], mbf->bufcount, &mbf->state);
  25.216 ++
  25.217 ++      if (bytes == (size_t) -1)
  25.218 ++        {
  25.219 ++          /* An invalid multibyte sequence was encountered.  */
  25.220 ++          /* Return a single byte.  */
  25.221 ++          bytes = 1;
  25.222 ++          mbc->wc_valid = false;
  25.223 ++          break;
  25.224 ++        }
  25.225 ++      else if (bytes == (size_t) -2)
  25.226 ++        {
  25.227 ++          /* An incomplete multibyte character.  */
  25.228 ++          mbf->state = backup_state;
  25.229 ++          if (mbf->bufcount == MBCHAR_BUF_SIZE)
  25.230 ++            {
  25.231 ++              /* An overlong incomplete multibyte sequence was encountered.  */
  25.232 ++              /* Return a single byte.  */
  25.233 ++              bytes = 1;
  25.234 ++              mbc->wc_valid = false;
  25.235 ++              break;
  25.236 ++            }
  25.237 ++          else
  25.238 ++            {
  25.239 ++              /* Read one more byte and retry mbrtowc.  */
  25.240 ++              int c = getc (mbf->fp);
  25.241 ++              if (c == EOF)
  25.242 ++                {
  25.243 ++                  /* An incomplete multibyte character at the end.  */
  25.244 ++                  mbf->eof_seen = true;
  25.245 ++                  bytes = mbf->bufcount;
  25.246 ++                  mbc->wc_valid = false;
  25.247 ++                  break;
  25.248 ++                }
  25.249 ++              mbf->buf[mbf->bufcount] = (unsigned char) c;
  25.250 ++              mbf->bufcount++;
  25.251 ++            }
  25.252 ++        }
  25.253 ++      else
  25.254 ++        {
  25.255 ++          if (bytes == 0)
  25.256 ++            {
  25.257 ++              /* A null wide character was encountered.  */
  25.258 ++              bytes = 1;
  25.259 ++              assert (mbf->buf[0] == '\0');
  25.260 ++              assert (mbc->wc == 0);
  25.261 ++            }
  25.262 ++          mbc->wc_valid = true;
  25.263 ++          break;
  25.264 ++        }
  25.265 ++    }
  25.266 ++
  25.267 ++  /* Return the multibyte sequence mbf->buf[0..bytes-1].  */
  25.268 ++  mbc->ptr = &mbc->buf[0];
  25.269 ++  memcpy (&mbc->buf[0], &mbf->buf[0], bytes);
  25.270 ++  mbc->bytes = bytes;
  25.271 ++
  25.272 ++  mbf->bufcount -= bytes;
  25.273 ++  if (mbf->bufcount > 0)
  25.274 ++    {
  25.275 ++      /* It's not worth calling memmove() for so few bytes.  */
  25.276 ++      unsigned int count = mbf->bufcount;
  25.277 ++      char *p = &mbf->buf[0];
  25.278 ++
  25.279 ++      do
  25.280 ++        {
  25.281 ++          *p = *(p + bytes);
  25.282 ++          p++;
  25.283 ++        }
  25.284 ++      while (--count > 0);
  25.285 ++    }
  25.286 ++  return;
  25.287 ++
  25.288 ++eof:
  25.289 ++  /* An mbchar_t with bytes == 0 is used to indicate EOF.  */
  25.290 ++  mbc->ptr = NULL;
  25.291 ++  mbc->bytes = 0;
  25.292 ++  mbc->wc_valid = false;
  25.293 ++  return;
  25.294 ++}
  25.295 ++
  25.296 ++MBFILE_INLINE void
  25.297 ++mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf)
  25.298 ++{
  25.299 ++  mb_copy (&mbf->pushback, mbc);
  25.300 ++  mbf->have_pushback = true;
  25.301 ++}
  25.302 ++
  25.303 ++typedef struct mbfile_multi mb_file_t;
  25.304 ++
  25.305 ++typedef mbchar_t mbf_char_t;
  25.306 ++
  25.307 ++#define mbf_init(mbf, stream)                                           \
  25.308 ++  ((mbf).fp = (stream),                                                 \
  25.309 ++   (mbf).eof_seen = false,                                              \
  25.310 ++   (mbf).have_pushback = false,                                         \
  25.311 ++   memset (&(mbf).state, '\0', sizeof (mbstate_t)),                     \
  25.312 ++   (mbf).bufcount = 0)
  25.313 ++
  25.314 ++#define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf))
  25.315 ++
  25.316 ++#define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf))
  25.317 ++
  25.318 ++#define mb_iseof(mbc) ((mbc).bytes == 0)
  25.319 ++
  25.320 ++#ifndef _GL_INLINE_HEADER_BEGIN
  25.321 ++ #error "Please include config.h first."
  25.322 ++#endif
  25.323 ++_GL_INLINE_HEADER_BEGIN
  25.324 ++
  25.325 ++#endif /* _MBFILE_H */
  25.326 +diff -Naurp coreutils-8.27-orig/m4/mbfile.m4 coreutils-8.27/m4/mbfile.m4
  25.327 +--- coreutils-8.27-orig/m4/mbfile.m4	1969-12-31 18:00:00.000000000 -0600
  25.328 ++++ coreutils-8.27/m4/mbfile.m4	2017-03-11 23:47:38.070058349 -0600
  25.329 +@@ -0,0 +1,14 @@
  25.330 ++# mbfile.m4 serial 7
  25.331 ++dnl Copyright (C) 2005, 2008-2017 Free Software Foundation, Inc.
  25.332 ++dnl This file is free software; the Free Software Foundation
  25.333 ++dnl gives unlimited permission to copy and/or distribute it,
  25.334 ++dnl with or without modifications, as long as this notice is preserved.
  25.335 ++
  25.336 ++dnl autoconf tests required for use of mbfile.h
  25.337 ++dnl From Bruno Haible.
  25.338 ++
  25.339 ++AC_DEFUN([gl_MBFILE],
  25.340 ++[
  25.341 ++  AC_REQUIRE([AC_TYPE_MBSTATE_T])
  25.342 ++  :
  25.343 ++])
  25.344 +diff -Naurp coreutils-8.27-orig/src/cut.c coreutils-8.27/src/cut.c
  25.345 +--- coreutils-8.27-orig/src/cut.c	2017-01-01 16:34:24.000000000 -0600
  25.346 ++++ coreutils-8.27/src/cut.c	2017-03-11 23:47:59.526048471 -0600
  25.347 +@@ -28,6 +28,11 @@
  25.348 + #include <assert.h>
  25.349 + #include <getopt.h>
  25.350 + #include <sys/types.h>
  25.351 ++
  25.352 ++/* Get mbstate_t, mbrtowc().  */
  25.353 ++#if HAVE_WCHAR_H
  25.354 ++# include <wchar.h>
  25.355 ++#endif
  25.356 + #include "system.h"
  25.357 + 
  25.358 + #include "error.h"
  25.359 +@@ -38,6 +43,18 @@
  25.360 + 
  25.361 + #include "set-fields.h"
  25.362 + 
  25.363 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
  25.364 ++   installation; work around this configuration error.        */
  25.365 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
  25.366 ++# undef MB_LEN_MAX
  25.367 ++# define MB_LEN_MAX 16
  25.368 ++#endif
  25.369 ++
  25.370 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
  25.371 ++#if HAVE_MBRTOWC && defined mbstate_t
  25.372 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
  25.373 ++#endif
  25.374 ++
  25.375 + /* The official name of this program (e.g., no 'g' prefix).  */
  25.376 + #define PROGRAM_NAME "cut"
  25.377 + 
  25.378 +@@ -54,6 +71,52 @@
  25.379 +     }									\
  25.380 +   while (0)
  25.381 + 
  25.382 ++/* Refill the buffer BUF to get a multibyte character. */
  25.383 ++#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM)                        \
  25.384 ++  do                                                                        \
  25.385 ++    {                                                                        \
  25.386 ++      if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM))        \
  25.387 ++        {                                                                \
  25.388 ++          memmove (BUF, BUFPOS, BUFLEN);                                \
  25.389 ++          BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \
  25.390 ++          BUFPOS = BUF;                                                        \
  25.391 ++        }                                                                \
  25.392 ++    }                                                                        \
  25.393 ++  while (0)
  25.394 ++
  25.395 ++/* Get wide character on BUFPOS. BUFPOS is not included after that.
  25.396 ++   If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */
  25.397 ++#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \
  25.398 ++  do                                                                        \
  25.399 ++    {                                                                        \
  25.400 ++      mbstate_t state_bak;                                                \
  25.401 ++                                                                        \
  25.402 ++      if (BUFLEN < 1)                                                        \
  25.403 ++        {                                                                \
  25.404 ++          WC = WEOF;                                                        \
  25.405 ++          break;                                                        \
  25.406 ++        }                                                                \
  25.407 ++                                                                        \
  25.408 ++      /* Get a wide character. */                                        \
  25.409 ++      CONVFAIL = false;                                                        \
  25.410 ++      state_bak = STATE;                                                \
  25.411 ++      MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE);        \
  25.412 ++                                                                        \
  25.413 ++      switch (MBLENGTH)                                                        \
  25.414 ++        {                                                                \
  25.415 ++        case (size_t)-1:                                                \
  25.416 ++        case (size_t)-2:                                                \
  25.417 ++          CONVFAIL = true;                                                        \
  25.418 ++          STATE = state_bak;                                                \
  25.419 ++          /* Fall througn. */                                                \
  25.420 ++                                                                        \
  25.421 ++        case 0:                                                                \
  25.422 ++          MBLENGTH = 1;                                                        \
  25.423 ++          break;                                                        \
  25.424 ++        }                                                                \
  25.425 ++    }                                                                        \
  25.426 ++  while (0)
  25.427 ++
  25.428 + 
  25.429 + /* Pointer inside RP.  When checking if a byte or field is selected
  25.430 +    by a finite range, we check if it is between CURRENT_RP.LO
  25.431 +@@ -61,6 +124,9 @@
  25.432 +    CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */
  25.433 + static struct field_range_pair *current_rp;
  25.434 + 
  25.435 ++/* Length of the delimiter given as argument to -d.  */
  25.436 ++size_t delimlen;
  25.437 ++
  25.438 + /* This buffer is used to support the semantics of the -s option
  25.439 +    (or lack of same) when the specified field list includes (does
  25.440 +    not include) the first field.  In both of those cases, the entire
  25.441 +@@ -77,15 +143,25 @@ enum operating_mode
  25.442 +   {
  25.443 +     undefined_mode,
  25.444 + 
  25.445 +-    /* Output characters that are in the given bytes. */
  25.446 ++    /* Output bytes that are at the given positions. */
  25.447 +     byte_mode,
  25.448 + 
  25.449 ++    /* Output characters that are at the given positions. */
  25.450 ++    character_mode,
  25.451 ++
  25.452 +     /* Output the given delimiter-separated fields. */
  25.453 +     field_mode
  25.454 +   };
  25.455 + 
  25.456 + static enum operating_mode operating_mode;
  25.457 + 
  25.458 ++/* If nonzero, when in byte mode, don't split multibyte characters.  */
  25.459 ++static int byte_mode_character_aware;
  25.460 ++
  25.461 ++/* If nonzero, the function for single byte locale is work
  25.462 ++   if this program runs on multibyte locale. */
  25.463 ++static int force_singlebyte_mode;
  25.464 ++
  25.465 + /* If true do not output lines containing no delimiter characters.
  25.466 +    Otherwise, all such lines are printed.  This option is valid only
  25.467 +    with field mode.  */
  25.468 +@@ -97,6 +173,9 @@ static bool complement;
  25.469 + 
  25.470 + /* The delimiter character for field mode. */
  25.471 + static unsigned char delim;
  25.472 ++#if HAVE_WCHAR_H
  25.473 ++static wchar_t wcdelim;
  25.474 ++#endif
  25.475 + 
  25.476 + /* The delimiter for each line/record. */
  25.477 + static unsigned char line_delim = '\n';
  25.478 +@@ -164,7 +243,7 @@ Print selected parts of lines from each
  25.479 +   -f, --fields=LIST       select only these fields;  also print any line\n\
  25.480 +                             that contains no delimiter character, unless\n\
  25.481 +                             the -s option is specified\n\
  25.482 +-  -n                      (ignored)\n\
  25.483 ++  -n                      with -b: don't split multibyte characters\n\
  25.484 + "), stdout);
  25.485 +       fputs (_("\
  25.486 +       --complement        complement the set of selected bytes, characters\n\
  25.487 +@@ -280,6 +359,82 @@ cut_bytes (FILE *stream)
  25.488 +     }
  25.489 + }
  25.490 + 
  25.491 ++#if HAVE_MBRTOWC
  25.492 ++/* This function is in use for the following case.
  25.493 ++
  25.494 ++   1. Read from the stream STREAM, printing to standard output any selected
  25.495 ++   characters.
  25.496 ++
  25.497 ++   2. Read from stream STREAM, printing to standard output any selected bytes,
  25.498 ++   without splitting multibyte characters.  */
  25.499 ++
  25.500 ++static void
  25.501 ++cut_characters_or_cut_bytes_no_split (FILE *stream)
  25.502 ++{
  25.503 ++  size_t idx;                /* number of bytes or characters in the line so far. */
  25.504 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  25.505 ++  char *bufpos;                /* Next read position of BUF. */
  25.506 ++  size_t buflen;        /* The length of the byte sequence in buf. */
  25.507 ++  wint_t wc;                /* A gotten wide character. */
  25.508 ++  size_t mblength;        /* The byte size of a multibyte character which shows
  25.509 ++                           as same character as WC. */
  25.510 ++  mbstate_t state;        /* State of the stream. */
  25.511 ++  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  25.512 ++  /* Whether to begin printing delimiters between ranges for the current line.
  25.513 ++     Set after we've begun printing data corresponding to the first range.  */
  25.514 ++  bool print_delimiter = false;
  25.515 ++
  25.516 ++  idx = 0;
  25.517 ++  buflen = 0;
  25.518 ++  bufpos = buf;
  25.519 ++  memset (&state, '\0', sizeof(mbstate_t));
  25.520 ++
  25.521 ++  current_rp = frp;
  25.522 ++
  25.523 ++  while (1)
  25.524 ++    {
  25.525 ++      REFILL_BUFFER (buf, bufpos, buflen, stream);
  25.526 ++
  25.527 ++      GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail);
  25.528 ++      (void) convfail;  /* ignore unused */
  25.529 ++
  25.530 ++      if (wc == WEOF)
  25.531 ++        {
  25.532 ++          if (idx > 0)
  25.533 ++            putchar (line_delim);
  25.534 ++          break;
  25.535 ++        }
  25.536 ++      else if (wc == line_delim)
  25.537 ++        {
  25.538 ++          putchar (line_delim);
  25.539 ++          idx = 0;
  25.540 ++          print_delimiter = false;
  25.541 ++          current_rp = frp;
  25.542 ++        }
  25.543 ++      else
  25.544 ++        {
  25.545 ++          next_item (&idx);
  25.546 ++          if (print_kth (idx))
  25.547 ++            {
  25.548 ++              if (output_delimiter_specified)
  25.549 ++                {
  25.550 ++                  if (print_delimiter && is_range_start_index (idx))
  25.551 ++                    {
  25.552 ++                      fwrite (output_delimiter_string, sizeof (char),
  25.553 ++                              output_delimiter_length, stdout);
  25.554 ++                    }
  25.555 ++                  print_delimiter = true;
  25.556 ++                }
  25.557 ++              fwrite (bufpos, mblength, sizeof(char), stdout);
  25.558 ++            }
  25.559 ++        }
  25.560 ++
  25.561 ++      buflen -= mblength;
  25.562 ++      bufpos += mblength;
  25.563 ++    }
  25.564 ++}
  25.565 ++#endif
  25.566 ++
  25.567 + /* Read from stream STREAM, printing to standard output any selected fields.  */
  25.568 + 
  25.569 + static void
  25.570 +@@ -425,13 +580,211 @@ cut_fields (FILE *stream)
  25.571 +     }
  25.572 + }
  25.573 + 
  25.574 ++#if HAVE_MBRTOWC
  25.575 ++static void
  25.576 ++cut_fields_mb (FILE *stream)
  25.577 ++{
  25.578 ++  int c;
  25.579 ++  size_t field_idx;
  25.580 ++  int found_any_selected_field;
  25.581 ++  int buffer_first_field;
  25.582 ++  int empty_input;
  25.583 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  25.584 ++  char *bufpos;                /* Next read position of BUF. */
  25.585 ++  size_t buflen;        /* The length of the byte sequence in buf. */
  25.586 ++  wint_t wc = 0;        /* A gotten wide character. */
  25.587 ++  size_t mblength;        /* The byte size of a multibyte character which shows
  25.588 ++                           as same character as WC. */
  25.589 ++  mbstate_t state;        /* State of the stream. */
  25.590 ++  bool convfail = false;  /* true, when conversion failed. Otherwise false. */
  25.591 ++
  25.592 ++  current_rp = frp;
  25.593 ++
  25.594 ++  found_any_selected_field = 0;
  25.595 ++  field_idx = 1;
  25.596 ++  bufpos = buf;
  25.597 ++  buflen = 0;
  25.598 ++  memset (&state, '\0', sizeof(mbstate_t));
  25.599 ++
  25.600 ++  c = getc (stream);
  25.601 ++  empty_input = (c == EOF);
  25.602 ++  if (c != EOF)
  25.603 ++  {
  25.604 ++    ungetc (c, stream);
  25.605 ++    wc = 0;
  25.606 ++  }
  25.607 ++  else
  25.608 ++    wc = WEOF;
  25.609 ++
  25.610 ++  /* To support the semantics of the -s flag, we may have to buffer
  25.611 ++     all of the first field to determine whether it is `delimited.'
  25.612 ++     But that is unnecessary if all non-delimited lines must be printed
  25.613 ++     and the first field has been selected, or if non-delimited lines
  25.614 ++     must be suppressed and the first field has *not* been selected.
  25.615 ++     That is because a non-delimited line has exactly one field.  */
  25.616 ++  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
  25.617 ++
  25.618 ++  while (1)
  25.619 ++    {
  25.620 ++      if (field_idx == 1 && buffer_first_field)
  25.621 ++        {
  25.622 ++          int len = 0;
  25.623 ++
  25.624 ++          while (1)
  25.625 ++            {
  25.626 ++              REFILL_BUFFER (buf, bufpos, buflen, stream);
  25.627 ++
  25.628 ++              GET_NEXT_WC_FROM_BUFFER
  25.629 ++                (wc, bufpos, buflen, mblength, state, convfail);
  25.630 ++
  25.631 ++              if (wc == WEOF)
  25.632 ++                break;
  25.633 ++
  25.634 ++              field_1_buffer = xrealloc (field_1_buffer, len + mblength);
  25.635 ++              memcpy (field_1_buffer + len, bufpos, mblength);
  25.636 ++              len += mblength;
  25.637 ++              buflen -= mblength;
  25.638 ++              bufpos += mblength;
  25.639 ++
  25.640 ++              if (!convfail && (wc == line_delim || wc == wcdelim))
  25.641 ++                break;
  25.642 ++            }
  25.643 ++
  25.644 ++          if (len <= 0 && wc == WEOF)
  25.645 ++            break;
  25.646 ++
  25.647 ++          /* If the first field extends to the end of line (it is not
  25.648 ++             delimited) and we are printing all non-delimited lines,
  25.649 ++             print this one.  */
  25.650 ++          if (convfail || (!convfail && wc != wcdelim))
  25.651 ++            {
  25.652 ++              if (suppress_non_delimited)
  25.653 ++                {
  25.654 ++                  /* Empty.        */
  25.655 ++                }
  25.656 ++              else
  25.657 ++                {
  25.658 ++                  fwrite (field_1_buffer, sizeof (char), len, stdout);
  25.659 ++                  /* Make sure the output line is newline terminated.  */
  25.660 ++                  if (convfail || (!convfail && wc != line_delim))
  25.661 ++                    putchar (line_delim);
  25.662 ++                }
  25.663 ++              continue;
  25.664 ++            }
  25.665 ++
  25.666 ++          if (print_kth (1))
  25.667 ++            {
  25.668 ++              /* Print the field, but not the trailing delimiter.  */
  25.669 ++              fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
  25.670 ++              found_any_selected_field = 1;
  25.671 ++            }
  25.672 ++          next_item (&field_idx);
  25.673 ++        }
  25.674 ++
  25.675 ++      if (wc != WEOF)
  25.676 ++        {
  25.677 ++          if (print_kth (field_idx))
  25.678 ++            {
  25.679 ++              if (found_any_selected_field)
  25.680 ++                {
  25.681 ++                  fwrite (output_delimiter_string, sizeof (char),
  25.682 ++                          output_delimiter_length, stdout);
  25.683 ++                }
  25.684 ++              found_any_selected_field = 1;
  25.685 ++            }
  25.686 ++
  25.687 ++          while (1)
  25.688 ++            {
  25.689 ++              REFILL_BUFFER (buf, bufpos, buflen, stream);
  25.690 ++
  25.691 ++              GET_NEXT_WC_FROM_BUFFER
  25.692 ++                (wc, bufpos, buflen, mblength, state, convfail);
  25.693 ++
  25.694 ++              if (wc == WEOF)
  25.695 ++                break;
  25.696 ++              else if (!convfail && (wc == wcdelim || wc == line_delim))
  25.697 ++                {
  25.698 ++                  buflen -= mblength;
  25.699 ++                  bufpos += mblength;
  25.700 ++                  break;
  25.701 ++                }
  25.702 ++
  25.703 ++              if (print_kth (field_idx))
  25.704 ++                fwrite (bufpos, mblength, sizeof(char), stdout);
  25.705 ++
  25.706 ++              buflen -= mblength;
  25.707 ++              bufpos += mblength;
  25.708 ++            }
  25.709 ++        }
  25.710 ++
  25.711 ++      if ((!convfail || wc == line_delim) && buflen < 1)
  25.712 ++        wc = WEOF;
  25.713 ++
  25.714 ++      if (!convfail && wc == wcdelim)
  25.715 ++        next_item (&field_idx);
  25.716 ++      else if (wc == WEOF || (!convfail && wc == line_delim))
  25.717 ++        {
  25.718 ++          if (found_any_selected_field
  25.719 ++              || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
  25.720 ++            putchar (line_delim);
  25.721 ++          if (wc == WEOF)
  25.722 ++            break;
  25.723 ++          field_idx = 1;
  25.724 ++          current_rp = frp;
  25.725 ++          found_any_selected_field = 0;
  25.726 ++        }
  25.727 ++    }
  25.728 ++}
  25.729 ++#endif
  25.730 ++
  25.731 + static void
  25.732 + cut_stream (FILE *stream)
  25.733 + {
  25.734 +-  if (operating_mode == byte_mode)
  25.735 +-    cut_bytes (stream);
  25.736 ++#if HAVE_MBRTOWC
  25.737 ++  if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  25.738 ++    {
  25.739 ++      switch (operating_mode)
  25.740 ++        {
  25.741 ++        case byte_mode:
  25.742 ++          if (byte_mode_character_aware)
  25.743 ++            cut_characters_or_cut_bytes_no_split (stream);
  25.744 ++          else
  25.745 ++            cut_bytes (stream);
  25.746 ++          break;
  25.747 ++
  25.748 ++        case character_mode:
  25.749 ++          cut_characters_or_cut_bytes_no_split (stream);
  25.750 ++          break;
  25.751 ++
  25.752 ++        case field_mode:
  25.753 ++          if (delimlen == 1)
  25.754 ++            {
  25.755 ++              /* Check if we have utf8 multibyte locale, so we can use this
  25.756 ++                 optimization because of uniqueness of characters, which is
  25.757 ++                 not true for e.g. SJIS */
  25.758 ++              char * loc = setlocale(LC_CTYPE, NULL);
  25.759 ++              if (loc && (strstr (loc, "UTF-8") || strstr (loc, "utf-8") ||
  25.760 ++                  strstr (loc, "UTF8") || strstr (loc, "utf8")))
  25.761 ++                {
  25.762 ++                  cut_fields (stream);
  25.763 ++                  break;
  25.764 ++                }
  25.765 ++            }
  25.766 ++          cut_fields_mb (stream);
  25.767 ++          break;
  25.768 ++
  25.769 ++        default:
  25.770 ++          abort ();
  25.771 ++        }
  25.772 ++    }
  25.773 +   else
  25.774 +-    cut_fields (stream);
  25.775 ++#endif
  25.776 ++    {
  25.777 ++      if (operating_mode == field_mode)
  25.778 ++        cut_fields (stream);
  25.779 ++      else
  25.780 ++        cut_bytes (stream);
  25.781 ++    }
  25.782 + }
  25.783 + 
  25.784 + /* Process file FILE to standard output.
  25.785 +@@ -483,6 +836,7 @@ main (int argc, char **argv)
  25.786 +   bool ok;
  25.787 +   bool delim_specified = false;
  25.788 +   char *spec_list_string IF_LINT ( = NULL);
  25.789 ++  char mbdelim[MB_LEN_MAX + 1];
  25.790 + 
  25.791 +   initialize_main (&argc, &argv);
  25.792 +   set_program_name (argv[0]);
  25.793 +@@ -505,7 +859,6 @@ main (int argc, char **argv)
  25.794 +       switch (optc)
  25.795 +         {
  25.796 +         case 'b':
  25.797 +-        case 'c':
  25.798 +           /* Build the byte list. */
  25.799 +           if (operating_mode != undefined_mode)
  25.800 +             FATAL_ERROR (_("only one type of list may be specified"));
  25.801 +@@ -513,6 +866,14 @@ main (int argc, char **argv)
  25.802 +           spec_list_string = optarg;
  25.803 +           break;
  25.804 + 
  25.805 ++        case 'c':
  25.806 ++          /* Build the character list. */
  25.807 ++          if (operating_mode != undefined_mode)
  25.808 ++            FATAL_ERROR (_("only one type of list may be specified"));
  25.809 ++          operating_mode = character_mode;
  25.810 ++          spec_list_string = optarg;
  25.811 ++          break;
  25.812 ++
  25.813 +         case 'f':
  25.814 +           /* Build the field list. */
  25.815 +           if (operating_mode != undefined_mode)
  25.816 +@@ -524,10 +885,38 @@ main (int argc, char **argv)
  25.817 +         case 'd':
  25.818 +           /* New delimiter. */
  25.819 +           /* Interpret -d '' to mean 'use the NUL byte as the delimiter.'  */
  25.820 +-          if (optarg[0] != '\0' && optarg[1] != '\0')
  25.821 +-            FATAL_ERROR (_("the delimiter must be a single character"));
  25.822 +-          delim = optarg[0];
  25.823 +-          delim_specified = true;
  25.824 ++            {
  25.825 ++#if HAVE_MBRTOWC
  25.826 ++              if(MB_CUR_MAX > 1)
  25.827 ++                {
  25.828 ++                  mbstate_t state;
  25.829 ++
  25.830 ++                  memset (&state, '\0', sizeof(mbstate_t));
  25.831 ++                  delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state);
  25.832 ++
  25.833 ++                  if (delimlen == (size_t)-1 || delimlen == (size_t)-2)
  25.834 ++                    ++force_singlebyte_mode;
  25.835 ++                  else
  25.836 ++                    {
  25.837 ++                      delimlen = (delimlen < 1) ? 1 : delimlen;
  25.838 ++                      if (wcdelim != L'\0' && *(optarg + delimlen) != '\0')
  25.839 ++                        FATAL_ERROR (_("the delimiter must be a single character"));
  25.840 ++                      memcpy (mbdelim, optarg, delimlen);
  25.841 ++                      mbdelim[delimlen] = '\0';
  25.842 ++                      if (delimlen == 1)
  25.843 ++                        delim = *optarg;
  25.844 ++                    }
  25.845 ++                }
  25.846 ++
  25.847 ++              if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  25.848 ++#endif
  25.849 ++                {
  25.850 ++                  if (optarg[0] != '\0' && optarg[1] != '\0')
  25.851 ++                    FATAL_ERROR (_("the delimiter must be a single character"));
  25.852 ++                  delim = (unsigned char) optarg[0];
  25.853 ++                }
  25.854 ++            delim_specified = true;
  25.855 ++          }
  25.856 +           break;
  25.857 + 
  25.858 +         case OUTPUT_DELIMITER_OPTION:
  25.859 +@@ -540,6 +929,7 @@ main (int argc, char **argv)
  25.860 +           break;
  25.861 + 
  25.862 +         case 'n':
  25.863 ++          byte_mode_character_aware = 1;
  25.864 +           break;
  25.865 + 
  25.866 +         case 's':
  25.867 +@@ -579,15 +969,34 @@ main (int argc, char **argv)
  25.868 +               | (complement ? SETFLD_COMPLEMENT : 0) );
  25.869 + 
  25.870 +   if (!delim_specified)
  25.871 +-    delim = '\t';
  25.872 ++    {
  25.873 ++      delim = '\t';
  25.874 ++#ifdef HAVE_MBRTOWC
  25.875 ++      wcdelim = L'\t';
  25.876 ++      mbdelim[0] = '\t';
  25.877 ++      mbdelim[1] = '\0';
  25.878 ++      delimlen = 1;
  25.879 ++#endif
  25.880 ++    }
  25.881 + 
  25.882 +   if (output_delimiter_string == NULL)
  25.883 +     {
  25.884 +-      static char dummy[2];
  25.885 +-      dummy[0] = delim;
  25.886 +-      dummy[1] = '\0';
  25.887 +-      output_delimiter_string = dummy;
  25.888 +-      output_delimiter_length = 1;
  25.889 ++#ifdef HAVE_MBRTOWC
  25.890 ++      if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
  25.891 ++        {
  25.892 ++          output_delimiter_string = xstrdup(mbdelim);
  25.893 ++          output_delimiter_length = delimlen;
  25.894 ++        }
  25.895 ++
  25.896 ++      if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
  25.897 ++#endif
  25.898 ++        {
  25.899 ++          static char dummy[2];
  25.900 ++          dummy[0] = delim;
  25.901 ++          dummy[1] = '\0';
  25.902 ++          output_delimiter_string = dummy;
  25.903 ++          output_delimiter_length = 1;
  25.904 ++        }
  25.905 +     }
  25.906 + 
  25.907 +   if (optind == argc)
  25.908 +diff -Naurp coreutils-8.27-orig/src/expand.c coreutils-8.27/src/expand.c
  25.909 +--- coreutils-8.27-orig/src/expand.c	2017-02-26 15:42:25.000000000 -0600
  25.910 ++++ coreutils-8.27/src/expand.c	2017-03-11 23:49:06.758133530 -0600
  25.911 +@@ -37,6 +37,9 @@
  25.912 + #include <stdio.h>
  25.913 + #include <getopt.h>
  25.914 + #include <sys/types.h>
  25.915 ++
  25.916 ++#include <mbfile.h>
  25.917 ++
  25.918 + #include "system.h"
  25.919 + #include "die.h"
  25.920 + #include "xstrndup.h"
  25.921 +@@ -100,19 +103,41 @@ expand (void)
  25.922 + {
  25.923 +   /* Input stream.  */
  25.924 +   FILE *fp = next_file (NULL);
  25.925 ++  mb_file_t mbf;
  25.926 ++  mbf_char_t c;
  25.927 ++  /* True if the starting locale is utf8.  */
  25.928 ++  bool using_utf_locale;
  25.929 ++
  25.930 ++  /* True if the first file contains BOM header.  */
  25.931 ++  bool found_bom;
  25.932 ++  using_utf_locale=check_utf_locale();
  25.933 + 
  25.934 +   if (!fp)
  25.935 +     return;
  25.936 ++  mbf_init (mbf, fp);
  25.937 ++  found_bom=check_bom(fp,&mbf);
  25.938 + 
  25.939 +-  while (true)
  25.940 ++  if (using_utf_locale == false && found_bom == true)
  25.941 ++  {
  25.942 ++    /*try using some predefined locale */
  25.943 ++
  25.944 ++    if (set_utf_locale () != 0)
  25.945 +     {
  25.946 +-      /* Input character, or EOF.  */
  25.947 +-      int c;
  25.948 ++      error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
  25.949 ++    }
  25.950 ++  }
  25.951 ++
  25.952 + 
  25.953 ++  if (found_bom == true)
  25.954 ++  {
  25.955 ++    print_bom();
  25.956 ++  }
  25.957 ++
  25.958 ++  while (true)
  25.959 ++    {
  25.960 +       /* If true, perform translations.  */
  25.961 +       bool convert = true;
  25.962 + 
  25.963 +-
  25.964 +       /* The following variables have valid values only when CONVERT
  25.965 +          is true:  */
  25.966 + 
  25.967 +@@ -122,17 +147,48 @@ expand (void)
  25.968 +       /* Index in TAB_LIST of next tab stop to examine.  */
  25.969 +       size_t tab_index = 0;
  25.970 + 
  25.971 +-
  25.972 +       /* Convert a line of text.  */
  25.973 + 
  25.974 +       do
  25.975 +         {
  25.976 +-          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
  25.977 +-            continue;
  25.978 ++          while (true) {
  25.979 ++            mbf_getc (c, mbf);
  25.980 ++            if ((mb_iseof (c)) && (fp = next_file (fp)))
  25.981 ++              {
  25.982 ++                mbf_init (mbf, fp);
  25.983 ++                if (fp!=NULL)
  25.984 ++                {
  25.985 ++                  if (check_bom(fp,&mbf)==true)
  25.986 ++                  {
  25.987 ++                    /*Not the first file - check BOM header*/
  25.988 ++                    if (using_utf_locale==false && found_bom==false)
  25.989 ++                    {
  25.990 ++                      /*BOM header in subsequent file but not in the first one. */
  25.991 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
  25.992 ++                    }
  25.993 ++                  }
  25.994 ++                  else
  25.995 ++                  {
  25.996 ++                    if(using_utf_locale==false && found_bom==true)
  25.997 ++                    {
  25.998 ++                      /*First file conatined BOM header - locale was switched to UTF
  25.999 ++                      /*all subsequent files should contain BOM. */
 25.1000 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 25.1001 ++                    }
 25.1002 ++                  }
 25.1003 ++                }
 25.1004 ++                continue;
 25.1005 ++              }
 25.1006 ++            else
 25.1007 ++              {
 25.1008 ++                break;
 25.1009 ++              }
 25.1010 ++            }
 25.1011 ++
 25.1012 + 
 25.1013 +           if (convert)
 25.1014 +             {
 25.1015 +-              if (c == '\t')
 25.1016 ++              if (mb_iseq (c, '\t'))
 25.1017 +                 {
 25.1018 +                   /* Column the next input tab stop is on.  */
 25.1019 +                   uintmax_t next_tab_column;
 25.1020 +@@ -151,32 +207,34 @@ expand (void)
 25.1021 +                     if (putchar (' ') < 0)
 25.1022 +                       die (EXIT_FAILURE, errno, _("write error"));
 25.1023 + 
 25.1024 +-                  c = ' ';
 25.1025 ++                  mb_setascii (&c, ' ');
 25.1026 +                 }
 25.1027 +-              else if (c == '\b')
 25.1028 ++              else if (mb_iseq (c, '\b'))
 25.1029 +                 {
 25.1030 +                   /* Go back one column, and force recalculation of the
 25.1031 +                      next tab stop.  */
 25.1032 +                   column -= !!column;
 25.1033 +                   tab_index -= !!tab_index;
 25.1034 +                 }
 25.1035 +-              else
 25.1036 ++              /* A leading control character could make us trip over.  */
 25.1037 ++              else if (!mb_iscntrl (c))
 25.1038 +                 {
 25.1039 +-                  column++;
 25.1040 ++                  column += mb_width (c);
 25.1041 +                   if (!column)
 25.1042 +                     die (EXIT_FAILURE, 0, _("input line is too long"));
 25.1043 +                 }
 25.1044 + 
 25.1045 +-              convert &= convert_entire_line || !! isblank (c);
 25.1046 ++              convert &= convert_entire_line || mb_isblank (c);
 25.1047 +             }
 25.1048 + 
 25.1049 +-          if (c < 0)
 25.1050 ++          if (mb_iseof (c))
 25.1051 +             return;
 25.1052 + 
 25.1053 +-          if (putchar (c) < 0)
 25.1054 ++          mb_putc (c, stdout);
 25.1055 ++          if (ferror (stdout))
 25.1056 +             die (EXIT_FAILURE, errno, _("write error"));
 25.1057 +         }
 25.1058 +-      while (c != '\n');
 25.1059 ++      while (!mb_iseq (c, '\n'));
 25.1060 +     }
 25.1061 + }
 25.1062 + 
 25.1063 +diff -Naurp coreutils-8.27-orig/src/expand-common.c coreutils-8.27/src/expand-common.c
 25.1064 +--- coreutils-8.27-orig/src/expand-common.c	2017-03-01 11:22:55.000000000 -0600
 25.1065 ++++ coreutils-8.27/src/expand-common.c	2017-03-11 23:49:06.757133570 -0600
 25.1066 +@@ -18,6 +18,7 @@
 25.1067 + 
 25.1068 + #include <stdio.h>
 25.1069 + #include <sys/types.h>
 25.1070 ++#include <mbfile.h>
 25.1071 + #include "system.h"
 25.1072 + #include "die.h"
 25.1073 + #include "error.h"
 25.1074 +@@ -105,6 +106,119 @@ set_extend_size (uintmax_t tabval)
 25.1075 +   return ok;
 25.1076 + }
 25.1077 + 
 25.1078 ++extern int
 25.1079 ++set_utf_locale (void)
 25.1080 ++{
 25.1081 ++      /*try using some predefined locale */
 25.1082 ++      const char* predef_locales[] = {"C.UTF8","en_US.UTF8","en_GB.UTF8"};
 25.1083 ++
 25.1084 ++      const int predef_locales_count=3;
 25.1085 ++      for (int i=0;i<predef_locales_count;i++)
 25.1086 ++        {
 25.1087 ++          if (setlocale(LC_ALL,predef_locales[i])!=NULL)
 25.1088 ++          {
 25.1089 ++            break;
 25.1090 ++          }
 25.1091 ++          else if (i==predef_locales_count-1)
 25.1092 ++          {
 25.1093 ++            return 1;
 25.1094 ++            error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
 25.1095 ++          }
 25.1096 ++        }
 25.1097 ++        return 0;
 25.1098 ++}
 25.1099 ++
 25.1100 ++extern bool
 25.1101 ++check_utf_locale(void)
 25.1102 ++{
 25.1103 ++  char* locale = setlocale (LC_CTYPE , NULL);
 25.1104 ++  if (locale == NULL)
 25.1105 ++  {
 25.1106 ++    return false;
 25.1107 ++  }
 25.1108 ++  else if (strcasestr(locale, "utf8") == NULL && strcasestr(locale, "utf-8") == NULL)
 25.1109 ++  {
 25.1110 ++    return false;
 25.1111 ++  }
 25.1112 ++  return true;
 25.1113 ++}
 25.1114 ++
 25.1115 ++extern bool
 25.1116 ++check_bom(FILE* fp, mb_file_t *mbf)
 25.1117 ++{
 25.1118 ++  int c;
 25.1119 ++
 25.1120 ++
 25.1121 ++  c=fgetc(fp);
 25.1122 ++
 25.1123 ++  /*test BOM header of the first file */
 25.1124 ++  mbf->bufcount=0;
 25.1125 ++  if (c == 0xEF)
 25.1126 ++  {
 25.1127 ++    c=fgetc(fp);
 25.1128 ++  }
 25.1129 ++  else
 25.1130 ++  {
 25.1131 ++    if (c != EOF)
 25.1132 ++    {
 25.1133 ++      ungetc(c,fp);
 25.1134 ++    }
 25.1135 ++    return false;
 25.1136 ++  }
 25.1137 ++
 25.1138 ++  if (c == 0xBB)
 25.1139 ++  {
 25.1140 ++    c=fgetc(fp);
 25.1141 ++  }
 25.1142 ++  else
 25.1143 ++  {
 25.1144 ++    if ( c!= EOF )
 25.1145 ++    {
 25.1146 ++      mbf->buf[0]=(unsigned char) 0xEF;
 25.1147 ++      mbf->bufcount=1;
 25.1148 ++      ungetc(c,fp);
 25.1149 ++      return false;
 25.1150 ++    }
 25.1151 ++    else
 25.1152 ++    {
 25.1153 ++      ungetc(0xEF,fp);
 25.1154 ++      return false;
 25.1155 ++    }
 25.1156 ++  }
 25.1157 ++  if (c == 0xBF)
 25.1158 ++  {
 25.1159 ++    mbf->bufcount=0;
 25.1160 ++    return true;
 25.1161 ++  }
 25.1162 ++  else
 25.1163 ++  {
 25.1164 ++    if (c != EOF)
 25.1165 ++    {
 25.1166 ++      mbf->buf[0]=(unsigned char) 0xEF;
 25.1167 ++      mbf->buf[1]=(unsigned char) 0xBB;
 25.1168 ++      mbf->bufcount=2;
 25.1169 ++      ungetc(c,fp);
 25.1170 ++      return false;
 25.1171 ++    }
 25.1172 ++    else
 25.1173 ++    {
 25.1174 ++      mbf->buf[0]=(unsigned char) 0xEF;
 25.1175 ++      mbf->bufcount=1;
 25.1176 ++      ungetc(0xBB,fp);
 25.1177 ++      return false;
 25.1178 ++    }
 25.1179 ++  }
 25.1180 ++  return false;
 25.1181 ++}
 25.1182 ++
 25.1183 ++extern void
 25.1184 ++print_bom(void)
 25.1185 ++{
 25.1186 ++  putc (0xEF, stdout);
 25.1187 ++  putc (0xBB, stdout);
 25.1188 ++  putc (0xBF, stdout);
 25.1189 ++}
 25.1190 ++
 25.1191 + /* Add the comma or blank separated list of tab stops STOPS
 25.1192 +    to the list of tab stops.  */
 25.1193 + extern void
 25.1194 +diff -Naurp coreutils-8.27-orig/src/expand-common.h coreutils-8.27/src/expand-common.h
 25.1195 +--- coreutils-8.27-orig/src/expand-common.h	2017-01-01 16:34:24.000000000 -0600
 25.1196 ++++ coreutils-8.27/src/expand-common.h	2017-03-11 23:49:06.758133530 -0600
 25.1197 +@@ -34,6 +34,18 @@ extern size_t max_column_width;
 25.1198 + /* The desired exit status.  */
 25.1199 + extern int exit_status;
 25.1200 + 
 25.1201 ++extern int
 25.1202 ++set_utf_locale (void);
 25.1203 ++
 25.1204 ++extern bool
 25.1205 ++check_utf_locale(void);
 25.1206 ++
 25.1207 ++extern bool
 25.1208 ++check_bom(FILE* fp, mb_file_t *mbf);
 25.1209 ++
 25.1210 ++extern void
 25.1211 ++print_bom(void);
 25.1212 ++
 25.1213 + /* Add tab stop TABVAL to the end of 'tab_list'.  */
 25.1214 + extern void
 25.1215 + add_tab_stop (uintmax_t tabval);
 25.1216 +diff -Naurp coreutils-8.27-orig/src/fold.c coreutils-8.27/src/fold.c
 25.1217 +--- coreutils-8.27-orig/src/fold.c	2017-01-01 16:34:24.000000000 -0600
 25.1218 ++++ coreutils-8.27/src/fold.c	2017-03-11 23:49:30.982169404 -0600
 25.1219 +@@ -22,12 +22,34 @@
 25.1220 + #include <getopt.h>
 25.1221 + #include <sys/types.h>
 25.1222 + 
 25.1223 ++/* Get mbstate_t, mbrtowc(), wcwidth().  */
 25.1224 ++#if HAVE_WCHAR_H
 25.1225 ++# include <wchar.h>
 25.1226 ++#endif
 25.1227 ++
 25.1228 ++/* Get iswprint(), iswblank(), wcwidth().  */
 25.1229 ++#if HAVE_WCTYPE_H
 25.1230 ++# include <wctype.h>
 25.1231 ++#endif
 25.1232 ++
 25.1233 + #include "system.h"
 25.1234 + #include "die.h"
 25.1235 + #include "error.h"
 25.1236 + #include "fadvise.h"
 25.1237 + #include "xdectoint.h"
 25.1238 + 
 25.1239 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 25.1240 ++      installation; work around this configuration error.  */
 25.1241 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 25.1242 ++# undef MB_LEN_MAX
 25.1243 ++# define MB_LEN_MAX 16
 25.1244 ++#endif
 25.1245 ++
 25.1246 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 25.1247 ++#if HAVE_MBRTOWC && defined mbstate_t
 25.1248 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 25.1249 ++#endif
 25.1250 ++
 25.1251 + #define TAB_WIDTH 8
 25.1252 + 
 25.1253 + /* The official name of this program (e.g., no 'g' prefix).  */
 25.1254 +@@ -35,20 +57,41 @@
 25.1255 + 
 25.1256 + #define AUTHORS proper_name ("David MacKenzie")
 25.1257 + 
 25.1258 ++#define FATAL_ERROR(Message)                                            \
 25.1259 ++  do                                                                    \
 25.1260 ++    {                                                                   \
 25.1261 ++      error (0, 0, (Message));                                          \
 25.1262 ++      usage (2);                                                        \
 25.1263 ++    }                                                                   \
 25.1264 ++  while (0)
 25.1265 ++
 25.1266 ++enum operating_mode
 25.1267 ++{
 25.1268 ++  /* Fold texts by columns that are at the given positions. */
 25.1269 ++  column_mode,
 25.1270 ++
 25.1271 ++  /* Fold texts by bytes that are at the given positions. */
 25.1272 ++  byte_mode,
 25.1273 ++
 25.1274 ++  /* Fold texts by characters that are at the given positions. */
 25.1275 ++  character_mode,
 25.1276 ++};
 25.1277 ++
 25.1278 ++/* The argument shows current mode. (Default: column_mode) */
 25.1279 ++static enum operating_mode operating_mode;
 25.1280 ++
 25.1281 + /* If nonzero, try to break on whitespace. */
 25.1282 + static bool break_spaces;
 25.1283 + 
 25.1284 +-/* If nonzero, count bytes, not column positions. */
 25.1285 +-static bool count_bytes;
 25.1286 +-
 25.1287 + /* If nonzero, at least one of the files we read was standard input. */
 25.1288 + static bool have_read_stdin;
 25.1289 + 
 25.1290 +-static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::";
 25.1291 ++static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::";
 25.1292 + 
 25.1293 + static struct option const longopts[] =
 25.1294 + {
 25.1295 +   {"bytes", no_argument, NULL, 'b'},
 25.1296 ++  {"characters", no_argument, NULL, 'c'},
 25.1297 +   {"spaces", no_argument, NULL, 's'},
 25.1298 +   {"width", required_argument, NULL, 'w'},
 25.1299 +   {GETOPT_HELP_OPTION_DECL},
 25.1300 +@@ -76,6 +119,7 @@ Wrap input lines in each FILE, writing t
 25.1301 + 
 25.1302 +       fputs (_("\
 25.1303 +   -b, --bytes         count bytes rather than columns\n\
 25.1304 ++  -c, --characters    count characters rather than columns\n\
 25.1305 +   -s, --spaces        break at spaces\n\
 25.1306 +   -w, --width=WIDTH   use WIDTH columns instead of 80\n\
 25.1307 + "), stdout);
 25.1308 +@@ -93,7 +137,7 @@ Wrap input lines in each FILE, writing t
 25.1309 + static size_t
 25.1310 + adjust_column (size_t column, char c)
 25.1311 + {
 25.1312 +-  if (!count_bytes)
 25.1313 ++  if (operating_mode != byte_mode)
 25.1314 +     {
 25.1315 +       if (c == '\b')
 25.1316 +         {
 25.1317 +@@ -116,30 +160,14 @@ adjust_column (size_t column, char c)
 25.1318 +    to stdout, with maximum line length WIDTH.
 25.1319 +    Return true if successful.  */
 25.1320 + 
 25.1321 +-static bool
 25.1322 +-fold_file (char const *filename, size_t width)
 25.1323 ++static void
 25.1324 ++fold_text (FILE *istream, size_t width, int *saved_errno)
 25.1325 + {
 25.1326 +-  FILE *istream;
 25.1327 +   int c;
 25.1328 +   size_t column = 0;		/* Screen column where next char will go. */
 25.1329 +   size_t offset_out = 0;	/* Index in 'line_out' for next char. */
 25.1330 +   static char *line_out = NULL;
 25.1331 +   static size_t allocated_out = 0;
 25.1332 +-  int saved_errno;
 25.1333 +-
 25.1334 +-  if (STREQ (filename, "-"))
 25.1335 +-    {
 25.1336 +-      istream = stdin;
 25.1337 +-      have_read_stdin = true;
 25.1338 +-    }
 25.1339 +-  else
 25.1340 +-    istream = fopen (filename, "r");
 25.1341 +-
 25.1342 +-  if (istream == NULL)
 25.1343 +-    {
 25.1344 +-      error (0, errno, "%s", quotef (filename));
 25.1345 +-      return false;
 25.1346 +-    }
 25.1347 + 
 25.1348 +   fadvise (istream, FADVISE_SEQUENTIAL);
 25.1349 + 
 25.1350 +@@ -169,6 +197,15 @@ fold_file (char const *filename, size_t
 25.1351 +               bool found_blank = false;
 25.1352 +               size_t logical_end = offset_out;
 25.1353 + 
 25.1354 ++              /* If LINE_OUT has no wide character,
 25.1355 ++                 put a new wide character in LINE_OUT
 25.1356 ++                 if column is bigger than width. */
 25.1357 ++              if (offset_out == 0)
 25.1358 ++                {
 25.1359 ++                  line_out[offset_out++] = c;
 25.1360 ++                  continue;
 25.1361 ++                }
 25.1362 ++
 25.1363 +               /* Look for the last blank. */
 25.1364 +               while (logical_end)
 25.1365 +                 {
 25.1366 +@@ -215,11 +252,220 @@ fold_file (char const *filename, size_t
 25.1367 +       line_out[offset_out++] = c;
 25.1368 +     }
 25.1369 + 
 25.1370 +-  saved_errno = errno;
 25.1371 ++  *saved_errno = errno;
 25.1372 ++
 25.1373 ++  if (offset_out)
 25.1374 ++    fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 25.1375 ++
 25.1376 ++}
 25.1377 ++
 25.1378 ++#if HAVE_MBRTOWC
 25.1379 ++static void
 25.1380 ++fold_multibyte_text (FILE *istream, size_t width, int *saved_errno)
 25.1381 ++{
 25.1382 ++  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
 25.1383 ++  size_t buflen = 0;        /* The length of the byte sequence in buf. */
 25.1384 ++  char *bufpos = buf;         /* Next read position of BUF. */
 25.1385 ++  wint_t wc;                /* A gotten wide character. */
 25.1386 ++  size_t mblength;        /* The byte size of a multibyte character which shows
 25.1387 ++                           as same character as WC. */
 25.1388 ++  mbstate_t state, state_bak;        /* State of the stream. */
 25.1389 ++  int convfail = 0;                /* 1, when conversion is failed. Otherwise 0. */
 25.1390 ++
 25.1391 ++  static char *line_out = NULL;
 25.1392 ++  size_t offset_out = 0;        /* Index in `line_out' for next char. */
 25.1393 ++  static size_t allocated_out = 0;
 25.1394 ++
 25.1395 ++  int increment;
 25.1396 ++  size_t column = 0;
 25.1397 ++
 25.1398 ++  size_t last_blank_pos;
 25.1399 ++  size_t last_blank_column;
 25.1400 ++  int is_blank_seen;
 25.1401 ++  int last_blank_increment = 0;
 25.1402 ++  int is_bs_following_last_blank;
 25.1403 ++  size_t bs_following_last_blank_num;
 25.1404 ++  int is_cr_after_last_blank;
 25.1405 ++
 25.1406 ++#define CLEAR_FLAGS                                \
 25.1407 ++   do                                                \
 25.1408 ++     {                                                \
 25.1409 ++        last_blank_pos = 0;                        \
 25.1410 ++        last_blank_column = 0;                        \
 25.1411 ++        is_blank_seen = 0;                        \
 25.1412 ++        is_bs_following_last_blank = 0;                \
 25.1413 ++        bs_following_last_blank_num = 0;        \
 25.1414 ++        is_cr_after_last_blank = 0;                \
 25.1415 ++     }                                                \
 25.1416 ++   while (0)
 25.1417 ++
 25.1418 ++#define START_NEW_LINE                        \
 25.1419 ++   do                                        \
 25.1420 ++     {                                        \
 25.1421 ++      putchar ('\n');                        \
 25.1422 ++      column = 0;                        \
 25.1423 ++      offset_out = 0;                        \
 25.1424 ++      CLEAR_FLAGS;                        \
 25.1425 ++    }                                        \
 25.1426 ++   while (0)
 25.1427 ++
 25.1428 ++  CLEAR_FLAGS;
 25.1429 ++  memset (&state, '\0', sizeof(mbstate_t));
 25.1430 ++
 25.1431 ++  for (;; bufpos += mblength, buflen -= mblength)
 25.1432 ++    {
 25.1433 ++      if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream))
 25.1434 ++        {
 25.1435 ++          memmove (buf, bufpos, buflen);
 25.1436 ++          buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream);
 25.1437 ++          bufpos = buf;
 25.1438 ++        }
 25.1439 ++
 25.1440 ++      if (buflen < 1)
 25.1441 ++        break;
 25.1442 ++
 25.1443 ++      /* Get a wide character. */
 25.1444 ++      state_bak = state;
 25.1445 ++      mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state);
 25.1446 ++
 25.1447 ++      switch (mblength)
 25.1448 ++        {
 25.1449 ++        case (size_t)-1:
 25.1450 ++        case (size_t)-2:
 25.1451 ++          convfail++;
 25.1452 ++          state = state_bak;
 25.1453 ++          /* Fall through. */
 25.1454 ++
 25.1455 ++        case 0:
 25.1456 ++          mblength = 1;
 25.1457 ++          break;
 25.1458 ++        }
 25.1459 ++
 25.1460 ++rescan:
 25.1461 ++      if (convfail)
 25.1462 ++        increment = 1;
 25.1463 ++      else if (wc == L'\n')
 25.1464 ++        {
 25.1465 ++          /* preserve newline */
 25.1466 ++          fwrite (line_out, sizeof(char), offset_out, stdout);
 25.1467 ++          START_NEW_LINE;
 25.1468 ++          continue;
 25.1469 ++        }
 25.1470 ++      else if (operating_mode == byte_mode)                  /* byte mode */
 25.1471 ++        increment = mblength;
 25.1472 ++      else if (operating_mode == character_mode)        /* character mode */
 25.1473 ++        increment = 1;
 25.1474 ++      else                                                 /* column mode */
 25.1475 ++        {
 25.1476 ++          switch (wc)
 25.1477 ++            {
 25.1478 ++            case L'\b':
 25.1479 ++              increment = (column > 0) ? -1 : 0;
 25.1480 ++              break;
 25.1481 ++
 25.1482 ++            case L'\r':
 25.1483 ++              increment = -1 * column;
 25.1484 ++              break;
 25.1485 ++
 25.1486 ++            case L'\t':
 25.1487 ++              increment = 8 - column % 8;
 25.1488 ++              break;
 25.1489 ++
 25.1490 ++            default:
 25.1491 ++              increment = wcwidth (wc);
 25.1492 ++              increment = (increment < 0) ? 0 : increment;
 25.1493 ++            }
 25.1494 ++        }
 25.1495 ++
 25.1496 ++      if (column + increment > width && break_spaces && last_blank_pos)
 25.1497 ++        {
 25.1498 ++          fwrite (line_out, sizeof(char), last_blank_pos, stdout);
 25.1499 ++          putchar ('\n');
 25.1500 ++
 25.1501 ++          offset_out = offset_out - last_blank_pos;
 25.1502 ++          column = column - last_blank_column + ((is_cr_after_last_blank)
 25.1503 ++              ? last_blank_increment : bs_following_last_blank_num);
 25.1504 ++          memmove (line_out, line_out + last_blank_pos, offset_out);
 25.1505 ++          CLEAR_FLAGS;
 25.1506 ++          goto rescan;
 25.1507 ++        }
 25.1508 ++
 25.1509 ++      if (column + increment > width && column != 0)
 25.1510 ++        {
 25.1511 ++          fwrite (line_out, sizeof(char), offset_out, stdout);
 25.1512 ++          START_NEW_LINE;
 25.1513 ++          goto rescan;
 25.1514 ++        }
 25.1515 ++
 25.1516 ++      if (allocated_out < offset_out + mblength)
 25.1517 ++        {
 25.1518 ++          line_out = X2REALLOC (line_out, &allocated_out);
 25.1519 ++        }
 25.1520 ++
 25.1521 ++      memcpy (line_out + offset_out, bufpos, mblength);
 25.1522 ++      offset_out += mblength;
 25.1523 ++      column += increment;
 25.1524 ++
 25.1525 ++      if (is_blank_seen && !convfail && wc == L'\r')
 25.1526 ++        is_cr_after_last_blank = 1;
 25.1527 ++
 25.1528 ++      if (is_bs_following_last_blank && !convfail && wc == L'\b')
 25.1529 ++        ++bs_following_last_blank_num;
 25.1530 ++      else
 25.1531 ++        is_bs_following_last_blank = 0;
 25.1532 ++
 25.1533 ++      if (break_spaces && !convfail && iswblank (wc))
 25.1534 ++        {
 25.1535 ++          last_blank_pos = offset_out;
 25.1536 ++          last_blank_column = column;
 25.1537 ++          is_blank_seen = 1;
 25.1538 ++          last_blank_increment = increment;
 25.1539 ++          is_bs_following_last_blank = 1;
 25.1540 ++          bs_following_last_blank_num = 0;
 25.1541 ++          is_cr_after_last_blank = 0;
 25.1542 ++        }
 25.1543 ++    }
 25.1544 ++
 25.1545 ++  *saved_errno = errno;
 25.1546 + 
 25.1547 +   if (offset_out)
 25.1548 +     fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 25.1549 + 
 25.1550 ++}
 25.1551 ++#endif
 25.1552 ++
 25.1553 ++/* Fold file FILENAME, or standard input if FILENAME is "-",
 25.1554 ++   to stdout, with maximum line length WIDTH.
 25.1555 ++   Return 0 if successful, 1 if an error occurs. */
 25.1556 ++
 25.1557 ++static bool
 25.1558 ++fold_file (char const *filename, size_t width)
 25.1559 ++{
 25.1560 ++  FILE *istream;
 25.1561 ++  int saved_errno;
 25.1562 ++
 25.1563 ++  if (STREQ (filename, "-"))
 25.1564 ++    {
 25.1565 ++      istream = stdin;
 25.1566 ++      have_read_stdin = 1;
 25.1567 ++    }
 25.1568 ++  else
 25.1569 ++    istream = fopen (filename, "r");
 25.1570 ++
 25.1571 ++  if (istream == NULL)
 25.1572 ++    {
 25.1573 ++      error (0, errno, "%s", filename);
 25.1574 ++      return 1;
 25.1575 ++    }
 25.1576 ++
 25.1577 ++  /* Define how ISTREAM is being folded. */
 25.1578 ++#if HAVE_MBRTOWC
 25.1579 ++  if (MB_CUR_MAX > 1)
 25.1580 ++    fold_multibyte_text (istream, width, &saved_errno);
 25.1581 ++  else
 25.1582 ++#endif
 25.1583 ++    fold_text (istream, width, &saved_errno);
 25.1584 ++
 25.1585 +   if (ferror (istream))
 25.1586 +     {
 25.1587 +       error (0, saved_errno, "%s", quotef (filename));
 25.1588 +@@ -252,7 +498,8 @@ main (int argc, char **argv)
 25.1589 + 
 25.1590 +   atexit (close_stdout);
 25.1591 + 
 25.1592 +-  break_spaces = count_bytes = have_read_stdin = false;
 25.1593 ++  operating_mode = column_mode;
 25.1594 ++  break_spaces = have_read_stdin = false;
 25.1595 + 
 25.1596 +   while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
 25.1597 +     {
 25.1598 +@@ -261,7 +508,15 @@ main (int argc, char **argv)
 25.1599 +       switch (optc)
 25.1600 +         {
 25.1601 +         case 'b':		/* Count bytes rather than columns. */
 25.1602 +-          count_bytes = true;
 25.1603 ++          if (operating_mode != column_mode)
 25.1604 ++            FATAL_ERROR (_("only one way of folding may be specified"));
 25.1605 ++          operating_mode = byte_mode;
 25.1606 ++          break;
 25.1607 ++
 25.1608 ++        case 'c':
 25.1609 ++          if (operating_mode != column_mode)
 25.1610 ++            FATAL_ERROR (_("only one way of folding may be specified"));
 25.1611 ++          operating_mode = character_mode;
 25.1612 +           break;
 25.1613 + 
 25.1614 +         case 's':		/* Break at word boundaries. */
 25.1615 +diff -Naurp coreutils-8.27-orig/src/join.c coreutils-8.27/src/join.c
 25.1616 +--- coreutils-8.27-orig/src/join.c	2017-01-01 16:34:24.000000000 -0600
 25.1617 ++++ coreutils-8.27/src/join.c	2017-03-11 23:47:13.091286290 -0600
 25.1618 +@@ -22,19 +22,33 @@
 25.1619 + #include <sys/types.h>
 25.1620 + #include <getopt.h>
 25.1621 + 
 25.1622 ++/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth().  */
 25.1623 ++#if HAVE_WCHAR_H
 25.1624 ++# include <wchar.h>
 25.1625 ++#endif
 25.1626 ++
 25.1627 ++/* Get iswblank(), towupper.  */
 25.1628 ++#if HAVE_WCTYPE_H
 25.1629 ++# include <wctype.h>
 25.1630 ++#endif
 25.1631 ++
 25.1632 + #include "system.h"
 25.1633 + #include "die.h"
 25.1634 + #include "error.h"
 25.1635 + #include "fadvise.h"
 25.1636 + #include "hard-locale.h"
 25.1637 + #include "linebuffer.h"
 25.1638 +-#include "memcasecmp.h"
 25.1639 + #include "quote.h"
 25.1640 + #include "stdio--.h"
 25.1641 + #include "xmemcoll.h"
 25.1642 + #include "xstrtol.h"
 25.1643 + #include "argmatch.h"
 25.1644 + 
 25.1645 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 25.1646 ++#if HAVE_MBRTOWC && defined mbstate_t
 25.1647 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 25.1648 ++#endif
 25.1649 ++
 25.1650 + /* The official name of this program (e.g., no 'g' prefix).  */
 25.1651 + #define PROGRAM_NAME "join"
 25.1652 + 
 25.1653 +@@ -136,10 +150,12 @@ static struct outlist outlist_head;
 25.1654 + /* Last element in 'outlist', where a new element can be added.  */
 25.1655 + static struct outlist *outlist_end = &outlist_head;
 25.1656 + 
 25.1657 +-/* Tab character separating fields.  If negative, fields are separated
 25.1658 +-   by any nonempty string of blanks, otherwise by exactly one
 25.1659 +-   tab character whose value (when cast to unsigned char) equals TAB.  */
 25.1660 +-static int tab = -1;
 25.1661 ++/* Tab character separating fields.  If NULL, fields are separated
 25.1662 ++   by any nonempty string of blanks.  */
 25.1663 ++static char *tab = NULL;
 25.1664 ++
 25.1665 ++/* The number of bytes used for tab. */
 25.1666 ++static size_t tablen = 0;
 25.1667 + 
 25.1668 + /* If nonzero, check that the input is correctly ordered. */
 25.1669 + static enum
 25.1670 +@@ -276,13 +292,14 @@ xfields (struct line *line)
 25.1671 +   if (ptr == lim)
 25.1672 +     return;
 25.1673 + 
 25.1674 +-  if (0 <= tab && tab != '\n')
 25.1675 ++  if (tab != NULL)
 25.1676 +     {
 25.1677 ++      unsigned char t = tab[0];
 25.1678 +       char *sep;
 25.1679 +-      for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1)
 25.1680 ++      for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1)
 25.1681 +         extract_field (line, ptr, sep - ptr);
 25.1682 +     }
 25.1683 +-  else if (tab < 0)
 25.1684 ++   else
 25.1685 +     {
 25.1686 +       /* Skip leading blanks before the first field.  */
 25.1687 +       while (field_sep (*ptr))
 25.1688 +@@ -306,6 +323,147 @@ xfields (struct line *line)
 25.1689 +   extract_field (line, ptr, lim - ptr);
 25.1690 + }
 25.1691 + 
 25.1692 ++#if HAVE_MBRTOWC
 25.1693 ++static void
 25.1694 ++xfields_multibyte (struct line *line)
 25.1695 ++{
 25.1696 ++  char *ptr = line->buf.buffer;
 25.1697 ++  char const *lim = ptr + line->buf.length - 1;
 25.1698 ++  wchar_t wc = 0;
 25.1699 ++  size_t mblength = 1;
 25.1700 ++  mbstate_t state, state_bak;
 25.1701 ++
 25.1702 ++  memset (&state, 0, sizeof (mbstate_t));
 25.1703 ++
 25.1704 ++  if (ptr >= lim)
 25.1705 ++    return;
 25.1706 ++
 25.1707 ++  if (tab != NULL)
 25.1708 ++    {
 25.1709 ++      char *sep = ptr;
 25.1710 ++      for (; ptr < lim; ptr = sep + mblength)
 25.1711 ++	{
 25.1712 ++	  sep = ptr;
 25.1713 ++	  while (sep < lim)
 25.1714 ++	    {
 25.1715 ++	      state_bak = state;
 25.1716 ++	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 25.1717 ++
 25.1718 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1719 ++		{
 25.1720 ++		  mblength = 1;
 25.1721 ++		  state = state_bak;
 25.1722 ++		}
 25.1723 ++	      mblength = (mblength < 1) ? 1 : mblength;
 25.1724 ++
 25.1725 ++	      if (mblength == tablen && !memcmp (sep, tab, mblength))
 25.1726 ++		break;
 25.1727 ++	      else
 25.1728 ++		{
 25.1729 ++		  sep += mblength;
 25.1730 ++		  continue;
 25.1731 ++		}
 25.1732 ++	    }
 25.1733 ++
 25.1734 ++	  if (sep >= lim)
 25.1735 ++	    break;
 25.1736 ++
 25.1737 ++	  extract_field (line, ptr, sep - ptr);
 25.1738 ++	}
 25.1739 ++    }
 25.1740 ++  else
 25.1741 ++    {
 25.1742 ++      /* Skip leading blanks before the first field.  */
 25.1743 ++      while(ptr < lim)
 25.1744 ++      {
 25.1745 ++        state_bak = state;
 25.1746 ++        mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 25.1747 ++
 25.1748 ++        if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1749 ++          {
 25.1750 ++            mblength = 1;
 25.1751 ++            state = state_bak;
 25.1752 ++            break;
 25.1753 ++          }
 25.1754 ++        mblength = (mblength < 1) ? 1 : mblength;
 25.1755 ++
 25.1756 ++        if (!iswblank(wc) && wc != '\n')
 25.1757 ++          break;
 25.1758 ++        ptr += mblength;
 25.1759 ++      }
 25.1760 ++
 25.1761 ++      do
 25.1762 ++	{
 25.1763 ++	  char *sep;
 25.1764 ++	  state_bak = state;
 25.1765 ++	  mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 25.1766 ++	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1767 ++	    {
 25.1768 ++	      mblength = 1;
 25.1769 ++	      state = state_bak;
 25.1770 ++	      break;
 25.1771 ++	    }
 25.1772 ++	  mblength = (mblength < 1) ? 1 : mblength;
 25.1773 ++
 25.1774 ++	  sep = ptr + mblength;
 25.1775 ++	  while (sep < lim)
 25.1776 ++	    {
 25.1777 ++	      state_bak = state;
 25.1778 ++	      mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 25.1779 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1780 ++		{
 25.1781 ++		  mblength = 1;
 25.1782 ++		  state = state_bak;
 25.1783 ++		  break;
 25.1784 ++		}
 25.1785 ++	      mblength = (mblength < 1) ? 1 : mblength;
 25.1786 ++
 25.1787 ++	      if (iswblank (wc) || wc == '\n')
 25.1788 ++		break;
 25.1789 ++
 25.1790 ++	      sep += mblength;
 25.1791 ++	    }
 25.1792 ++
 25.1793 ++	  extract_field (line, ptr, sep - ptr);
 25.1794 ++	  if (sep >= lim)
 25.1795 ++	    return;
 25.1796 ++
 25.1797 ++	  state_bak = state;
 25.1798 ++	  mblength = mbrtowc (&wc, sep, lim - sep + 1, &state);
 25.1799 ++	  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1800 ++	    {
 25.1801 ++	      mblength = 1;
 25.1802 ++	      state = state_bak;
 25.1803 ++	      break;
 25.1804 ++	    }
 25.1805 ++	  mblength = (mblength < 1) ? 1 : mblength;
 25.1806 ++
 25.1807 ++	  ptr = sep + mblength;
 25.1808 ++	  while (ptr < lim)
 25.1809 ++	    {
 25.1810 ++	      state_bak = state;
 25.1811 ++	      mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state);
 25.1812 ++	      if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.1813 ++		{
 25.1814 ++		  mblength = 1;
 25.1815 ++		  state = state_bak;
 25.1816 ++		  break;
 25.1817 ++		}
 25.1818 ++	      mblength = (mblength < 1) ? 1 : mblength;
 25.1819 ++
 25.1820 ++	      if (!iswblank (wc) && wc != '\n')
 25.1821 ++		break;
 25.1822 ++
 25.1823 ++	      ptr += mblength;
 25.1824 ++	    }
 25.1825 ++	}
 25.1826 ++      while (ptr < lim);
 25.1827 ++    }
 25.1828 ++
 25.1829 ++  extract_field (line, ptr, lim - ptr);
 25.1830 ++}
 25.1831 ++#endif
 25.1832 ++
 25.1833 + static void
 25.1834 + freeline (struct line *line)
 25.1835 + {
 25.1836 +@@ -327,56 +485,133 @@ keycmp (struct line const *line1, struct
 25.1837 +         size_t jf_1, size_t jf_2)
 25.1838 + {
 25.1839 +   /* Start of field to compare in each file.  */
 25.1840 +-  char *beg1;
 25.1841 +-  char *beg2;
 25.1842 +-
 25.1843 +-  size_t len1;
 25.1844 +-  size_t len2;		/* Length of fields to compare.  */
 25.1845 ++  char *beg[2];
 25.1846 ++  char *copy[2];
 25.1847 ++  size_t len[2]; 	/* Length of fields to compare.  */
 25.1848 +   int diff;
 25.1849 ++  int i, j;
 25.1850 ++  int mallocd = 0;
 25.1851 + 
 25.1852 +   if (jf_1 < line1->nfields)
 25.1853 +     {
 25.1854 +-      beg1 = line1->fields[jf_1].beg;
 25.1855 +-      len1 = line1->fields[jf_1].len;
 25.1856 ++      beg[0] = line1->fields[jf_1].beg;
 25.1857 ++      len[0] = line1->fields[jf_1].len;
 25.1858 +     }
 25.1859 +   else
 25.1860 +     {
 25.1861 +-      beg1 = NULL;
 25.1862 +-      len1 = 0;
 25.1863 ++      beg[0] = NULL;
 25.1864 ++      len[0] = 0;
 25.1865 +     }
 25.1866 + 
 25.1867 +   if (jf_2 < line2->nfields)
 25.1868 +     {
 25.1869 +-      beg2 = line2->fields[jf_2].beg;
 25.1870 +-      len2 = line2->fields[jf_2].len;
 25.1871 ++      beg[1] = line2->fields[jf_2].beg;
 25.1872 ++      len[1] = line2->fields[jf_2].len;
 25.1873 +     }
 25.1874 +   else
 25.1875 +     {
 25.1876 +-      beg2 = NULL;
 25.1877 +-      len2 = 0;
 25.1878 ++      beg[1] = NULL;
 25.1879 ++      len[1] = 0;
 25.1880 +     }
 25.1881 + 
 25.1882 +-  if (len1 == 0)
 25.1883 +-    return len2 == 0 ? 0 : -1;
 25.1884 +-  if (len2 == 0)
 25.1885 ++  if (len[0] == 0)
 25.1886 ++    return len[1] == 0 ? 0 : -1;
 25.1887 ++  if (len[1] == 0)
 25.1888 +     return 1;
 25.1889 + 
 25.1890 +   if (ignore_case)
 25.1891 +     {
 25.1892 +-      /* FIXME: ignore_case does not work with NLS (in particular,
 25.1893 +-         with multibyte chars).  */
 25.1894 +-      diff = memcasecmp (beg1, beg2, MIN (len1, len2));
 25.1895 ++#ifdef HAVE_MBRTOWC
 25.1896 ++      if (MB_CUR_MAX > 1)
 25.1897 ++      {
 25.1898 ++        size_t mblength;
 25.1899 ++        wchar_t wc, uwc;
 25.1900 ++        mbstate_t state, state_bak;
 25.1901 ++
 25.1902 ++        memset (&state, '\0', sizeof (mbstate_t));
 25.1903 ++
 25.1904 ++        for (i = 0; i < 2; i++)
 25.1905 ++          {
 25.1906 ++            mallocd = 1;
 25.1907 ++            copy[i] = xmalloc (len[i] + 1);
 25.1908 ++            memset (copy[i], '\0',len[i] + 1);
 25.1909 ++
 25.1910 ++            for (j = 0; j < MIN (len[0], len[1]);)
 25.1911 ++              {
 25.1912 ++                state_bak = state;
 25.1913 ++                mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state);
 25.1914 ++
 25.1915 ++                switch (mblength)
 25.1916 ++                  {
 25.1917 ++                  case (size_t) -1:
 25.1918 ++                  case (size_t) -2:
 25.1919 ++                    state = state_bak;
 25.1920 ++                    /* Fall through */
 25.1921 ++                  case 0:
 25.1922 ++                    mblength = 1;
 25.1923 ++                    break;
 25.1924 ++
 25.1925 ++                  default:
 25.1926 ++                    uwc = towupper (wc);
 25.1927 ++
 25.1928 ++                    if (uwc != wc)
 25.1929 ++                      {
 25.1930 ++                        mbstate_t state_wc;
 25.1931 ++                        size_t mblen;
 25.1932 ++
 25.1933 ++                        memset (&state_wc, '\0', sizeof (mbstate_t));
 25.1934 ++                        mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 25.1935 ++                        assert (mblen != (size_t)-1);
 25.1936 ++                      }
 25.1937 ++                    else
 25.1938 ++                      memcpy (copy[i] + j, beg[i] + j, mblength);
 25.1939 ++                  }
 25.1940 ++                j += mblength;
 25.1941 ++              }
 25.1942 ++            copy[i][j] = '\0';
 25.1943 ++          }
 25.1944 ++      }
 25.1945 ++      else
 25.1946 ++#endif
 25.1947 ++      {
 25.1948 ++        for (i = 0; i < 2; i++)
 25.1949 ++          {
 25.1950 ++            mallocd = 1;
 25.1951 ++            copy[i] = xmalloc (len[i] + 1);
 25.1952 ++
 25.1953 ++            for (j = 0; j < MIN (len[0], len[1]); j++)
 25.1954 ++              copy[i][j] = toupper (beg[i][j]);
 25.1955 ++
 25.1956 ++            copy[i][j] = '\0';
 25.1957 ++          }
 25.1958 ++      }
 25.1959 +     }
 25.1960 +   else
 25.1961 +     {
 25.1962 +-      if (hard_LC_COLLATE)
 25.1963 +-        return xmemcoll (beg1, len1, beg2, len2);
 25.1964 +-      diff = memcmp (beg1, beg2, MIN (len1, len2));
 25.1965 ++      copy[0] = beg[0];
 25.1966 ++      copy[1] = beg[1];
 25.1967 +     }
 25.1968 + 
 25.1969 ++  if (hard_LC_COLLATE)
 25.1970 ++    {
 25.1971 ++      diff = xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]);
 25.1972 ++
 25.1973 ++      if (mallocd)
 25.1974 ++        for (i = 0; i < 2; i++)
 25.1975 ++          free (copy[i]);
 25.1976 ++
 25.1977 ++      return diff;
 25.1978 ++    }
 25.1979 ++  diff = memcmp (copy[0], copy[1], MIN (len[0], len[1]));
 25.1980 ++
 25.1981 ++  if (mallocd)
 25.1982 ++    for (i = 0; i < 2; i++)
 25.1983 ++      free (copy[i]);
 25.1984 ++
 25.1985 ++
 25.1986 +   if (diff)
 25.1987 +     return diff;
 25.1988 +-  return len1 < len2 ? -1 : len1 != len2;
 25.1989 ++  return len[0] - len[1];
 25.1990 + }
 25.1991 + 
 25.1992 + /* Check that successive input lines PREV and CURRENT from input file
 25.1993 +@@ -468,6 +703,11 @@ get_line (FILE *fp, struct line **linep,
 25.1994 +     }
 25.1995 +   ++line_no[which - 1];
 25.1996 + 
 25.1997 ++#if HAVE_MBRTOWC
 25.1998 ++  if (MB_CUR_MAX > 1)
 25.1999 ++    xfields_multibyte (line);
 25.2000 ++  else
 25.2001 ++#endif
 25.2002 +   xfields (line);
 25.2003 + 
 25.2004 +   if (prevline[which - 1])
 25.2005 +@@ -567,21 +807,28 @@ prfield (size_t n, struct line const *li
 25.2006 + 
 25.2007 + /* Output all the fields in line, other than the join field.  */
 25.2008 + 
 25.2009 ++#define PUT_TAB_CHAR							\
 25.2010 ++  do									\
 25.2011 ++    {									\
 25.2012 ++      (tab != NULL) ?							\
 25.2013 ++	fwrite(tab, sizeof(char), tablen, stdout) : putchar (' ');	\
 25.2014 ++    }									\
 25.2015 ++  while (0)
 25.2016 ++
 25.2017 + static void
 25.2018 + prfields (struct line const *line, size_t join_field, size_t autocount)
 25.2019 + {
 25.2020 +   size_t i;
 25.2021 +   size_t nfields = autoformat ? autocount : line->nfields;
 25.2022 +-  char output_separator = tab < 0 ? ' ' : tab;
 25.2023 + 
 25.2024 +   for (i = 0; i < join_field && i < nfields; ++i)
 25.2025 +     {
 25.2026 +-      putchar (output_separator);
 25.2027 ++      PUT_TAB_CHAR;
 25.2028 +       prfield (i, line);
 25.2029 +     }
 25.2030 +   for (i = join_field + 1; i < nfields; ++i)
 25.2031 +     {
 25.2032 +-      putchar (output_separator);
 25.2033 ++      PUT_TAB_CHAR;
 25.2034 +       prfield (i, line);
 25.2035 +     }
 25.2036 + }
 25.2037 +@@ -592,7 +839,6 @@ static void
 25.2038 + prjoin (struct line const *line1, struct line const *line2)
 25.2039 + {
 25.2040 +   const struct outlist *outlist;
 25.2041 +-  char output_separator = tab < 0 ? ' ' : tab;
 25.2042 +   size_t field;
 25.2043 +   struct line const *line;
 25.2044 + 
 25.2045 +@@ -626,7 +872,7 @@ prjoin (struct line const *line1, struct
 25.2046 +           o = o->next;
 25.2047 +           if (o == NULL)
 25.2048 +             break;
 25.2049 +-          putchar (output_separator);
 25.2050 ++          PUT_TAB_CHAR;
 25.2051 +         }
 25.2052 +       putchar (eolchar);
 25.2053 +     }
 25.2054 +@@ -1104,20 +1350,43 @@ main (int argc, char **argv)
 25.2055 + 
 25.2056 +         case 't':
 25.2057 +           {
 25.2058 +-            unsigned char newtab = optarg[0];
 25.2059 ++            char *newtab = NULL;
 25.2060 ++            size_t newtablen;
 25.2061 ++            newtab = xstrdup (optarg);
 25.2062 ++#if HAVE_MBRTOWC
 25.2063 ++            if (MB_CUR_MAX > 1)
 25.2064 ++              {
 25.2065 ++                mbstate_t state;
 25.2066 ++
 25.2067 ++                memset (&state, 0, sizeof (mbstate_t));
 25.2068 ++                newtablen = mbrtowc (NULL, newtab,
 25.2069 ++                                     strnlen (newtab, MB_LEN_MAX),
 25.2070 ++                                     &state);
 25.2071 ++                if (newtablen == (size_t) 0
 25.2072 ++                    || newtablen == (size_t) -1
 25.2073 ++                    || newtablen == (size_t) -2)
 25.2074 ++                  newtablen = 1;
 25.2075 ++              }
 25.2076 ++            else
 25.2077 ++#endif
 25.2078 ++              newtablen = 1;
 25.2079 +             if (! newtab)
 25.2080 +-              newtab = '\n'; /* '' => process the whole line.  */
 25.2081 ++              newtab = (char*)"\n"; /* '' => process the whole line.  */
 25.2082 +             else if (optarg[1])
 25.2083 +               {
 25.2084 +-                if (STREQ (optarg, "\\0"))
 25.2085 +-                  newtab = '\0';
 25.2086 +-                else
 25.2087 +-                  die (EXIT_FAILURE, 0, _("multi-character tab %s"),
 25.2088 +-                       quote (optarg));
 25.2089 ++                if (newtablen == 1 && newtab[1])
 25.2090 ++                {
 25.2091 ++                  if (STREQ (newtab, "\\0"))
 25.2092 ++                     newtab[0] = '\0';
 25.2093 ++                }
 25.2094 ++              }
 25.2095 ++            if (tab != NULL && strcmp (tab, newtab))
 25.2096 ++              {
 25.2097 ++                free (newtab);
 25.2098 ++                die (EXIT_FAILURE, 0, _("incompatible tabs"));
 25.2099 +               }
 25.2100 +-            if (0 <= tab && tab != newtab)
 25.2101 +-              die (EXIT_FAILURE, 0, _("incompatible tabs"));
 25.2102 +             tab = newtab;
 25.2103 ++            tablen = newtablen;
 25.2104 +           }
 25.2105 +           break;
 25.2106 + 
 25.2107 +diff -Naurp coreutils-8.27-orig/src/pr.c coreutils-8.27/src/pr.c
 25.2108 +--- coreutils-8.27-orig/src/pr.c	2017-01-01 16:34:24.000000000 -0600
 25.2109 ++++ coreutils-8.27/src/pr.c	2017-03-11 23:47:13.094286139 -0600
 25.2110 +@@ -311,6 +311,24 @@
 25.2111 + 
 25.2112 + #include <getopt.h>
 25.2113 + #include <sys/types.h>
 25.2114 ++
 25.2115 ++/* Get MB_LEN_MAX.  */
 25.2116 ++#include <limits.h>
 25.2117 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 25.2118 ++   installation; work around this configuration error.  */
 25.2119 ++#if !defined MB_LEN_MAX || MB_LEN_MAX == 1
 25.2120 ++# define MB_LEN_MAX 16
 25.2121 ++#endif
 25.2122 ++
 25.2123 ++/* Get MB_CUR_MAX.  */
 25.2124 ++#include <stdlib.h>
 25.2125 ++
 25.2126 ++/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
 25.2127 ++/* Get mbstate_t, mbrtowc(), wcwidth().  */
 25.2128 ++#if HAVE_WCHAR_H
 25.2129 ++# include <wchar.h>
 25.2130 ++#endif
 25.2131 ++
 25.2132 + #include "system.h"
 25.2133 + #include "die.h"
 25.2134 + #include "error.h"
 25.2135 +@@ -324,6 +342,18 @@
 25.2136 + #include "xstrtol.h"
 25.2137 + #include "xdectoint.h"
 25.2138 + 
 25.2139 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 25.2140 ++#if HAVE_MBRTOWC && defined mbstate_t
 25.2141 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 25.2142 ++#endif
 25.2143 ++
 25.2144 ++#ifndef HAVE_DECL_WCWIDTH
 25.2145 ++"this configure-time declaration test was not run"
 25.2146 ++#endif
 25.2147 ++#if !HAVE_DECL_WCWIDTH
 25.2148 ++extern int wcwidth ();
 25.2149 ++#endif
 25.2150 ++
 25.2151 + /* The official name of this program (e.g., no 'g' prefix).  */
 25.2152 + #define PROGRAM_NAME "pr"
 25.2153 + 
 25.2154 +@@ -416,7 +446,20 @@ struct COLUMN
 25.2155 + 
 25.2156 + typedef struct COLUMN COLUMN;
 25.2157 + 
 25.2158 +-static int char_to_clump (char c);
 25.2159 ++/* Funtion pointers to switch functions for single byte locale or for
 25.2160 ++   multibyte locale. If multibyte functions do not exist in your sysytem,
 25.2161 ++   these pointers always point the function for single byte locale. */
 25.2162 ++static void (*print_char) (char c);
 25.2163 ++static int (*char_to_clump) (char c);
 25.2164 ++
 25.2165 ++/* Functions for single byte locale. */
 25.2166 ++static void print_char_single (char c);
 25.2167 ++static int char_to_clump_single (char c);
 25.2168 ++
 25.2169 ++/* Functions for multibyte locale. */
 25.2170 ++static void print_char_multi (char c);
 25.2171 ++static int char_to_clump_multi (char c);
 25.2172 ++
 25.2173 + static bool read_line (COLUMN *p);
 25.2174 + static bool print_page (void);
 25.2175 + static bool print_stored (COLUMN *p);
 25.2176 +@@ -428,6 +471,7 @@ static void add_line_number (COLUMN *p);
 25.2177 + static void getoptnum (const char *n_str, int min, int *num,
 25.2178 +                        const char *errfmt);
 25.2179 + static void getoptarg (char *arg, char switch_char, char *character,
 25.2180 ++                       int *character_length, int *character_width,
 25.2181 +                        int *number);
 25.2182 + static void print_files (int number_of_files, char **av);
 25.2183 + static void init_parameters (int number_of_files);
 25.2184 +@@ -441,7 +485,6 @@ static void store_char (char c);
 25.2185 + static void pad_down (unsigned int lines);
 25.2186 + static void read_rest_of_line (COLUMN *p);
 25.2187 + static void skip_read (COLUMN *p, int column_number);
 25.2188 +-static void print_char (char c);
 25.2189 + static void cleanup (void);
 25.2190 + static void print_sep_string (void);
 25.2191 + static void separator_string (const char *optarg_S);
 25.2192 +@@ -453,7 +496,7 @@ static COLUMN *column_vector;
 25.2193 +    we store the leftmost columns contiguously in buff.
 25.2194 +    To print a line from buff, get the index of the first character
 25.2195 +    from line_vector[i], and print up to line_vector[i + 1]. */
 25.2196 +-static char *buff;
 25.2197 ++static unsigned char *buff;
 25.2198 + 
 25.2199 + /* Index of the position in buff where the next character
 25.2200 +    will be stored. */
 25.2201 +@@ -557,7 +600,7 @@ static int chars_per_column;
 25.2202 + static bool untabify_input = false;
 25.2203 + 
 25.2204 + /* (-e) The input tab character. */
 25.2205 +-static char input_tab_char = '\t';
 25.2206 ++static char input_tab_char[MB_LEN_MAX] = "\t";
 25.2207 + 
 25.2208 + /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
 25.2209 +    where the leftmost column is 1. */
 25.2210 +@@ -567,7 +610,10 @@ static int chars_per_input_tab = 8;
 25.2211 + static bool tabify_output = false;
 25.2212 + 
 25.2213 + /* (-i) The output tab character. */
 25.2214 +-static char output_tab_char = '\t';
 25.2215 ++static char output_tab_char[MB_LEN_MAX] = "\t";
 25.2216 ++
 25.2217 ++/* (-i) The byte length of output tab character. */
 25.2218 ++static int output_tab_char_length = 1;
 25.2219 + 
 25.2220 + /* (-i) The width of the output tab. */
 25.2221 + static int chars_per_output_tab = 8;
 25.2222 +@@ -637,7 +683,13 @@ static int line_number;
 25.2223 + static bool numbered_lines = false;
 25.2224 + 
 25.2225 + /* (-n) Character which follows each line number. */
 25.2226 +-static char number_separator = '\t';
 25.2227 ++static char number_separator[MB_LEN_MAX] = "\t";
 25.2228 ++
 25.2229 ++/* (-n) The byte length of the character which follows each line number. */
 25.2230 ++static int number_separator_length = 1;
 25.2231 ++
 25.2232 ++/* (-n) The character width of the character which follows each line number. */
 25.2233 ++static int number_separator_width = 0;
 25.2234 + 
 25.2235 + /* (-n) line counting starts with 1st line of input file (not with 1st
 25.2236 +    line of 1st page printed). */
 25.2237 +@@ -690,6 +742,7 @@ static bool use_col_separator = false;
 25.2238 +    -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */
 25.2239 + static char const *col_sep_string = "";
 25.2240 + static int col_sep_length = 0;
 25.2241 ++static int col_sep_width = 0;
 25.2242 + static char *column_separator = (char *) " ";
 25.2243 + static char *line_separator = (char *) "\t";
 25.2244 + 
 25.2245 +@@ -851,6 +904,13 @@ separator_string (const char *optarg_S)
 25.2246 +     integer_overflow ();
 25.2247 +   col_sep_length = len;
 25.2248 +   col_sep_string = optarg_S;
 25.2249 ++
 25.2250 ++#if HAVE_MBRTOWC
 25.2251 ++  if (MB_CUR_MAX > 1)
 25.2252 ++    col_sep_width = mbswidth (col_sep_string, 0);
 25.2253 ++  else
 25.2254 ++#endif
 25.2255 ++    col_sep_width = col_sep_length;
 25.2256 + }
 25.2257 + 
 25.2258 + int
 25.2259 +@@ -875,6 +935,21 @@ main (int argc, char **argv)
 25.2260 + 
 25.2261 +   atexit (close_stdout);
 25.2262 + 
 25.2263 ++/* Define which functions are used, the ones for single byte locale or the ones
 25.2264 ++   for multibyte locale. */
 25.2265 ++#if HAVE_MBRTOWC
 25.2266 ++  if (MB_CUR_MAX > 1)
 25.2267 ++    {
 25.2268 ++      print_char = print_char_multi;
 25.2269 ++      char_to_clump = char_to_clump_multi;
 25.2270 ++    }
 25.2271 ++  else
 25.2272 ++#endif
 25.2273 ++    {
 25.2274 ++      print_char = print_char_single;
 25.2275 ++      char_to_clump = char_to_clump_single;
 25.2276 ++    }
 25.2277 ++
 25.2278 +   n_files = 0;
 25.2279 +   file_names = (argc > 1
 25.2280 +                 ? xnmalloc (argc - 1, sizeof (char *))
 25.2281 +@@ -951,8 +1026,12 @@ main (int argc, char **argv)
 25.2282 +           break;
 25.2283 +         case 'e':
 25.2284 +           if (optarg)
 25.2285 +-            getoptarg (optarg, 'e', &input_tab_char,
 25.2286 +-                       &chars_per_input_tab);
 25.2287 ++            {
 25.2288 ++              int dummy_length, dummy_width;
 25.2289 ++
 25.2290 ++              getoptarg (optarg, 'e', input_tab_char, &dummy_length,
 25.2291 ++                         &dummy_width, &chars_per_input_tab);
 25.2292 ++            }
 25.2293 +           /* Could check tab width > 0. */
 25.2294 +           untabify_input = true;
 25.2295 +           break;
 25.2296 +@@ -965,8 +1044,12 @@ main (int argc, char **argv)
 25.2297 +           break;
 25.2298 +         case 'i':
 25.2299 +           if (optarg)
 25.2300 +-            getoptarg (optarg, 'i', &output_tab_char,
 25.2301 +-                       &chars_per_output_tab);
 25.2302 ++            {
 25.2303 ++              int dummy_width;
 25.2304 ++
 25.2305 ++              getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length,
 25.2306 ++                         &dummy_width, &chars_per_output_tab);
 25.2307 ++            }
 25.2308 +           /* Could check tab width > 0. */
 25.2309 +           tabify_output = true;
 25.2310 +           break;
 25.2311 +@@ -984,8 +1067,8 @@ main (int argc, char **argv)
 25.2312 +         case 'n':
 25.2313 +           numbered_lines = true;
 25.2314 +           if (optarg)
 25.2315 +-            getoptarg (optarg, 'n', &number_separator,
 25.2316 +-                       &chars_per_number);
 25.2317 ++            getoptarg (optarg, 'n', number_separator, &number_separator_length,
 25.2318 ++                       &number_separator_width, &chars_per_number);
 25.2319 +           break;
 25.2320 +         case 'N':
 25.2321 +           skip_count = false;
 25.2322 +@@ -1010,6 +1093,7 @@ main (int argc, char **argv)
 25.2323 +           /* Reset an additional input of -s, -S dominates -s */
 25.2324 +           col_sep_string = "";
 25.2325 +           col_sep_length = 0;
 25.2326 ++          col_sep_width = 0;
 25.2327 +           use_col_separator = true;
 25.2328 +           if (optarg)
 25.2329 +             separator_string (optarg);
 25.2330 +@@ -1166,10 +1250,45 @@ getoptnum (const char *n_str, int min, i
 25.2331 +    a number. */
 25.2332 + 
 25.2333 + static void
 25.2334 +-getoptarg (char *arg, char switch_char, char *character, int *number)
 25.2335 ++getoptarg (char *arg, char switch_char, char *character, int *character_length,
 25.2336 ++           int *character_width, int *number)
 25.2337 + {
 25.2338 +   if (!ISDIGIT (*arg))
 25.2339 +-    *character = *arg++;
 25.2340 ++    {
 25.2341 ++#ifdef HAVE_MBRTOWC
 25.2342 ++      if (MB_CUR_MAX > 1)        /* for multibyte locale. */
 25.2343 ++        {
 25.2344 ++          wchar_t wc;
 25.2345 ++          size_t mblength;
 25.2346 ++          int width;
 25.2347 ++          mbstate_t state = {'\0'};
 25.2348 ++
 25.2349 ++          mblength = mbrtowc (&wc, arg, strnlen(arg, MB_LEN_MAX), &state);
 25.2350 ++
 25.2351 ++          if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.2352 ++            {
 25.2353 ++              *character_length = 1;
 25.2354 ++              *character_width = 1;
 25.2355 ++            }
 25.2356 ++          else
 25.2357 ++            {
 25.2358 ++              *character_length = (mblength < 1) ? 1 : mblength;
 25.2359 ++              width = wcwidth (wc);
 25.2360 ++              *character_width = (width < 0) ? 0 : width;
 25.2361 ++            }
 25.2362 ++
 25.2363 ++          strncpy (character, arg, *character_length);
 25.2364 ++          arg += *character_length;
 25.2365 ++        }
 25.2366 ++      else                        /* for single byte locale. */
 25.2367 ++#endif
 25.2368 ++        {
 25.2369 ++          *character = *arg++;
 25.2370 ++          *character_length = 1;
 25.2371 ++          *character_width = 1;
 25.2372 ++        }
 25.2373 ++    }
 25.2374 ++
 25.2375 +   if (*arg)
 25.2376 +     {
 25.2377 +       long int tmp_long;
 25.2378 +@@ -1191,6 +1310,11 @@ static void
 25.2379 + init_parameters (int number_of_files)
 25.2380 + {
 25.2381 +   int chars_used_by_number = 0;
 25.2382 ++  int mb_len = 1;
 25.2383 ++#if HAVE_MBRTOWC
 25.2384 ++  if (MB_CUR_MAX > 1)
 25.2385 ++    mb_len = MB_LEN_MAX;
 25.2386 ++#endif
 25.2387 + 
 25.2388 +   lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
 25.2389 +   if (lines_per_body <= 0)
 25.2390 +@@ -1228,7 +1352,7 @@ init_parameters (int number_of_files)
 25.2391 +           else
 25.2392 +             col_sep_string = column_separator;
 25.2393 + 
 25.2394 +-          col_sep_length = 1;
 25.2395 ++          col_sep_length = col_sep_width = 1;
 25.2396 +           use_col_separator = true;
 25.2397 +         }
 25.2398 +       /* It's rather pointless to define a TAB separator with column
 25.2399 +@@ -1258,11 +1382,11 @@ init_parameters (int number_of_files)
 25.2400 +              + TAB_WIDTH (chars_per_input_tab, chars_per_number);   */
 25.2401 + 
 25.2402 +       /* Estimate chars_per_text without any margin and keep it constant. */
 25.2403 +-      if (number_separator == '\t')
 25.2404 ++      if (number_separator[0] == '\t')
 25.2405 +         number_width = (chars_per_number
 25.2406 +                         + TAB_WIDTH (chars_per_default_tab, chars_per_number));
 25.2407 +       else
 25.2408 +-        number_width = chars_per_number + 1;
 25.2409 ++        number_width = chars_per_number + number_separator_width;
 25.2410 + 
 25.2411 +       /* The number is part of the column width unless we are
 25.2412 +          printing files in parallel. */
 25.2413 +@@ -1271,7 +1395,7 @@ init_parameters (int number_of_files)
 25.2414 +     }
 25.2415 + 
 25.2416 +   int sep_chars, useful_chars;
 25.2417 +-  if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_length, &sep_chars))
 25.2418 ++  if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_width, &sep_chars))
 25.2419 +     sep_chars = INT_MAX;
 25.2420 +   if (INT_SUBTRACT_WRAPV (chars_per_line - chars_used_by_number, sep_chars,
 25.2421 +                           &useful_chars))
 25.2422 +@@ -1294,7 +1418,7 @@ init_parameters (int number_of_files)
 25.2423 +      We've to use 8 as the lower limit, if we use chars_per_default_tab = 8
 25.2424 +      to expand a tab which is not an input_tab-char. */
 25.2425 +   free (clump_buff);
 25.2426 +-  clump_buff = xmalloc (MAX (8, chars_per_input_tab));
 25.2427 ++  clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab));
 25.2428 + }
 25.2429 + 
 25.2430 + /* Open the necessary files,
 25.2431 +@@ -1402,7 +1526,7 @@ init_funcs (void)
 25.2432 + 
 25.2433 +   /* Enlarge p->start_position of first column to use the same form of
 25.2434 +      padding_not_printed with all columns. */
 25.2435 +-  h = h + col_sep_length;
 25.2436 ++  h = h + col_sep_width;
 25.2437 + 
 25.2438 +   /* This loop takes care of all but the rightmost column. */
 25.2439 + 
 25.2440 +@@ -1436,7 +1560,7 @@ init_funcs (void)
 25.2441 +         }
 25.2442 +       else
 25.2443 +         {
 25.2444 +-          h = h_next + col_sep_length;
 25.2445 ++          h = h_next + col_sep_width;
 25.2446 +           h_next = h + chars_per_column;
 25.2447 +         }
 25.2448 +     }
 25.2449 +@@ -1727,9 +1851,9 @@ static void
 25.2450 + align_column (COLUMN *p)
 25.2451 + {
 25.2452 +   padding_not_printed = p->start_position;
 25.2453 +-  if (col_sep_length < padding_not_printed)
 25.2454 ++  if (col_sep_width < padding_not_printed)
 25.2455 +     {
 25.2456 +-      pad_across_to (padding_not_printed - col_sep_length);
 25.2457 ++      pad_across_to (padding_not_printed - col_sep_width);
 25.2458 +       padding_not_printed = ANYWHERE;
 25.2459 +     }
 25.2460 + 
 25.2461 +@@ -2004,13 +2128,13 @@ store_char (char c)
 25.2462 +       /* May be too generous. */
 25.2463 +       buff = X2REALLOC (buff, &buff_allocated);
 25.2464 +     }
 25.2465 +-  buff[buff_current++] = c;
 25.2466 ++  buff[buff_current++] = (unsigned char) c;
 25.2467 + }
 25.2468 + 
 25.2469 + static void
 25.2470 + add_line_number (COLUMN *p)
 25.2471 + {
 25.2472 +-  int i;
 25.2473 ++  int i, j;
 25.2474 +   char *s;
 25.2475 +   int num_width;
 25.2476 + 
 25.2477 +@@ -2027,22 +2151,24 @@ add_line_number (COLUMN *p)
 25.2478 +       /* Tabification is assumed for multiple columns, also for n-separators,
 25.2479 +          but 'default n-separator = TAB' hasn't been given priority over
 25.2480 +          equal column_width also specified by POSIX. */
 25.2481 +-      if (number_separator == '\t')
 25.2482 ++      if (number_separator[0] == '\t')
 25.2483 +         {
 25.2484 +           i = number_width - chars_per_number;
 25.2485 +           while (i-- > 0)
 25.2486 +             (p->char_func) (' ');
 25.2487 +         }
 25.2488 +       else
 25.2489 +-        (p->char_func) (number_separator);
 25.2490 ++        for (j = 0; j < number_separator_length; j++)
 25.2491 ++          (p->char_func) (number_separator[j]);
 25.2492 +     }
 25.2493 +   else
 25.2494 +     /* To comply with POSIX, we avoid any expansion of default TAB
 25.2495 +        separator with a single column output. No column_width requirement
 25.2496 +        has to be considered. */
 25.2497 +     {
 25.2498 +-      (p->char_func) (number_separator);
 25.2499 +-      if (number_separator == '\t')
 25.2500 ++      for (j = 0; j < number_separator_length; j++)
 25.2501 ++        (p->char_func) (number_separator[j]);
 25.2502 ++      if (number_separator[0] == '\t')
 25.2503 +         output_position = POS_AFTER_TAB (chars_per_output_tab,
 25.2504 +                           output_position);
 25.2505 +     }
 25.2506 +@@ -2203,7 +2329,7 @@ print_white_space (void)
 25.2507 +   while (goal - h_old > 1
 25.2508 +          && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
 25.2509 +     {
 25.2510 +-      putchar (output_tab_char);
 25.2511 ++      fwrite (output_tab_char, sizeof(char), output_tab_char_length, stdout);
 25.2512 +       h_old = h_new;
 25.2513 +     }
 25.2514 +   while (++h_old <= goal)
 25.2515 +@@ -2223,6 +2349,7 @@ print_sep_string (void)
 25.2516 + {
 25.2517 +   char const *s = col_sep_string;
 25.2518 +   int l = col_sep_length;
 25.2519 ++  int not_space_flag;
 25.2520 + 
 25.2521 +   if (separators_not_printed <= 0)
 25.2522 +     {
 25.2523 +@@ -2234,6 +2361,7 @@ print_sep_string (void)
 25.2524 +     {
 25.2525 +       for (; separators_not_printed > 0; --separators_not_printed)
 25.2526 +         {
 25.2527 ++          not_space_flag = 0;
 25.2528 +           while (l-- > 0)
 25.2529 +             {
 25.2530 +               /* 3 types of sep_strings: spaces only, spaces and chars,
 25.2531 +@@ -2247,12 +2375,15 @@ print_sep_string (void)
 25.2532 +                 }
 25.2533 +               else
 25.2534 +                 {
 25.2535 ++                  not_space_flag = 1;
 25.2536 +                   if (spaces_not_printed > 0)
 25.2537 +                     print_white_space ();
 25.2538 +                   putchar (*s++);
 25.2539 +-                  ++output_position;
 25.2540 +                 }
 25.2541 +             }
 25.2542 ++          if (not_space_flag)
 25.2543 ++            output_position += col_sep_width;
 25.2544 ++
 25.2545 +           /* sep_string ends with some spaces */
 25.2546 +           if (spaces_not_printed > 0)
 25.2547 +             print_white_space ();
 25.2548 +@@ -2280,7 +2411,7 @@ print_clump (COLUMN *p, int n, char *clu
 25.2549 +    required number of tabs and spaces. */
 25.2550 + 
 25.2551 + static void
 25.2552 +-print_char (char c)
 25.2553 ++print_char_single (char c)
 25.2554 + {
 25.2555 +   if (tabify_output)
 25.2556 +     {
 25.2557 +@@ -2304,6 +2435,74 @@ print_char (char c)
 25.2558 +   putchar (c);
 25.2559 + }
 25.2560 + 
 25.2561 ++#ifdef HAVE_MBRTOWC
 25.2562 ++static void
 25.2563 ++print_char_multi (char c)
 25.2564 ++{
 25.2565 ++  static size_t mbc_pos = 0;
 25.2566 ++  static char mbc[MB_LEN_MAX] = {'\0'};
 25.2567 ++  static mbstate_t state = {'\0'};
 25.2568 ++  mbstate_t state_bak;
 25.2569 ++  wchar_t wc;
 25.2570 ++  size_t mblength;
 25.2571 ++  int width;
 25.2572 ++
 25.2573 ++  if (tabify_output)
 25.2574 ++    {
 25.2575 ++      state_bak = state;
 25.2576 ++      mbc[mbc_pos++] = c;
 25.2577 ++      mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 25.2578 ++
 25.2579 ++      while (mbc_pos > 0)
 25.2580 ++        {
 25.2581 ++          switch (mblength)
 25.2582 ++            {
 25.2583 ++            case (size_t)-2:
 25.2584 ++              state = state_bak;
 25.2585 ++              return;
 25.2586 ++
 25.2587 ++            case (size_t)-1:
 25.2588 ++              state = state_bak;
 25.2589 ++              ++output_position;
 25.2590 ++              putchar (mbc[0]);
 25.2591 ++              memmove (mbc, mbc + 1, MB_CUR_MAX - 1);
 25.2592 ++              --mbc_pos;
 25.2593 ++              break;
 25.2594 ++
 25.2595 ++            case 0:
 25.2596 ++              mblength = 1;
 25.2597 ++
 25.2598 ++            default:
 25.2599 ++              if (wc == L' ')
 25.2600 ++                {
 25.2601 ++                  memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 25.2602 ++                  --mbc_pos;
 25.2603 ++                  ++spaces_not_printed;
 25.2604 ++                  return;
 25.2605 ++                }
 25.2606 ++              else if (spaces_not_printed > 0)
 25.2607 ++                print_white_space ();
 25.2608 ++
 25.2609 ++              /* Nonprintables are assumed to have width 0, except L'\b'. */
 25.2610 ++              if ((width = wcwidth (wc)) < 1)
 25.2611 ++                {
 25.2612 ++                  if (wc == L'\b')
 25.2613 ++                    --output_position;
 25.2614 ++                }
 25.2615 ++              else
 25.2616 ++                output_position += width;
 25.2617 ++
 25.2618 ++              fwrite (mbc, sizeof(char), mblength, stdout);
 25.2619 ++              memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 25.2620 ++              mbc_pos -= mblength;
 25.2621 ++            }
 25.2622 ++        }
 25.2623 ++      return;
 25.2624 ++    }
 25.2625 ++  putchar (c);
 25.2626 ++}
 25.2627 ++#endif
 25.2628 ++
 25.2629 + /* Skip to page PAGE before printing.
 25.2630 +    PAGE may be larger than total number of pages. */
 25.2631 + 
 25.2632 +@@ -2483,9 +2682,9 @@ read_line (COLUMN *p)
 25.2633 +           align_empty_cols = false;
 25.2634 +         }
 25.2635 + 
 25.2636 +-      if (col_sep_length < padding_not_printed)
 25.2637 ++      if (col_sep_width < padding_not_printed)
 25.2638 +         {
 25.2639 +-          pad_across_to (padding_not_printed - col_sep_length);
 25.2640 ++          pad_across_to (padding_not_printed - col_sep_width);
 25.2641 +           padding_not_printed = ANYWHERE;
 25.2642 +         }
 25.2643 + 
 25.2644 +@@ -2555,7 +2754,7 @@ print_stored (COLUMN *p)
 25.2645 +   int i;
 25.2646 + 
 25.2647 +   int line = p->current_line++;
 25.2648 +-  char *first = &buff[line_vector[line]];
 25.2649 ++  unsigned char *first = &buff[line_vector[line]];
 25.2650 +   /* FIXME
 25.2651 +      UMR: Uninitialized memory read:
 25.2652 +      * This is occurring while in:
 25.2653 +@@ -2567,7 +2766,7 @@ print_stored (COLUMN *p)
 25.2654 +      xmalloc        [xmalloc.c:94]
 25.2655 +      init_store_cols [pr.c:1648]
 25.2656 +      */
 25.2657 +-  char *last = &buff[line_vector[line + 1]];
 25.2658 ++  unsigned char *last = &buff[line_vector[line + 1]];
 25.2659 + 
 25.2660 +   pad_vertically = true;
 25.2661 + 
 25.2662 +@@ -2586,9 +2785,9 @@ print_stored (COLUMN *p)
 25.2663 +         }
 25.2664 +     }
 25.2665 + 
 25.2666 +-  if (col_sep_length < padding_not_printed)
 25.2667 ++  if (col_sep_width < padding_not_printed)
 25.2668 +     {
 25.2669 +-      pad_across_to (padding_not_printed - col_sep_length);
 25.2670 ++      pad_across_to (padding_not_printed - col_sep_width);
 25.2671 +       padding_not_printed = ANYWHERE;
 25.2672 +     }
 25.2673 + 
 25.2674 +@@ -2601,8 +2800,8 @@ print_stored (COLUMN *p)
 25.2675 +   if (spaces_not_printed == 0)
 25.2676 +     {
 25.2677 +       output_position = p->start_position + end_vector[line];
 25.2678 +-      if (p->start_position - col_sep_length == chars_per_margin)
 25.2679 +-        output_position -= col_sep_length;
 25.2680 ++      if (p->start_position - col_sep_width == chars_per_margin)
 25.2681 ++        output_position -= col_sep_width;
 25.2682 +     }
 25.2683 + 
 25.2684 +   return true;
 25.2685 +@@ -2621,7 +2820,7 @@ print_stored (COLUMN *p)
 25.2686 +    number of characters is 1.) */
 25.2687 + 
 25.2688 + static int
 25.2689 +-char_to_clump (char c)
 25.2690 ++char_to_clump_single (char c)
 25.2691 + {
 25.2692 +   unsigned char uc = c;
 25.2693 +   char *s = clump_buff;
 25.2694 +@@ -2631,10 +2830,10 @@ char_to_clump (char c)
 25.2695 +   int chars;
 25.2696 +   int chars_per_c = 8;
 25.2697 + 
 25.2698 +-  if (c == input_tab_char)
 25.2699 ++  if (c == input_tab_char[0])
 25.2700 +     chars_per_c = chars_per_input_tab;
 25.2701 + 
 25.2702 +-  if (c == input_tab_char || c == '\t')
 25.2703 ++  if (c == input_tab_char[0] || c == '\t')
 25.2704 +     {
 25.2705 +       width = TAB_WIDTH (chars_per_c, input_position);
 25.2706 + 
 25.2707 +@@ -2715,6 +2914,164 @@ char_to_clump (char c)
 25.2708 +   return chars;
 25.2709 + }
 25.2710 + 
 25.2711 ++#ifdef HAVE_MBRTOWC
 25.2712 ++static int
 25.2713 ++char_to_clump_multi (char c)
 25.2714 ++{
 25.2715 ++  static size_t mbc_pos = 0;
 25.2716 ++  static char mbc[MB_LEN_MAX] = {'\0'};
 25.2717 ++  static mbstate_t state = {'\0'};
 25.2718 ++  mbstate_t state_bak;
 25.2719 ++  wchar_t wc;
 25.2720 ++  size_t mblength;
 25.2721 ++  int wc_width;
 25.2722 ++  register char *s = clump_buff;
 25.2723 ++  register int i, j;
 25.2724 ++  char esc_buff[4];
 25.2725 ++  int width;
 25.2726 ++  int chars;
 25.2727 ++  int chars_per_c = 8;
 25.2728 ++
 25.2729 ++  state_bak = state;
 25.2730 ++  mbc[mbc_pos++] = c;
 25.2731 ++  mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
 25.2732 ++
 25.2733 ++  width = 0;
 25.2734 ++  chars = 0;
 25.2735 ++  while (mbc_pos > 0)
 25.2736 ++    {
 25.2737 ++      switch (mblength)
 25.2738 ++        {
 25.2739 ++        case (size_t)-2:
 25.2740 ++          state = state_bak;
 25.2741 ++          return 0;
 25.2742 ++
 25.2743 ++        case (size_t)-1:
 25.2744 ++          state = state_bak;
 25.2745 ++          mblength = 1;
 25.2746 ++
 25.2747 ++          if (use_esc_sequence || use_cntrl_prefix)
 25.2748 ++            {
 25.2749 ++              width = +4;
 25.2750 ++              chars = +4;
 25.2751 ++              *s++ = '\\';
 25.2752 ++              sprintf (esc_buff, "%03o", (unsigned char) mbc[0]);
 25.2753 ++              for (i = 0; i <= 2; ++i)
 25.2754 ++                *s++ = (int) esc_buff[i];
 25.2755 ++            }
 25.2756 ++          else
 25.2757 ++            {
 25.2758 ++              width += 1;
 25.2759 ++              chars += 1;
 25.2760 ++              *s++ = mbc[0];
 25.2761 ++            }
 25.2762 ++          break;
 25.2763 ++
 25.2764 ++        case 0:
 25.2765 ++          mblength = 1;
 25.2766 ++                /* Fall through */
 25.2767 ++
 25.2768 ++        default:
 25.2769 ++          if (memcmp (mbc, input_tab_char, mblength) == 0)
 25.2770 ++            chars_per_c = chars_per_input_tab;
 25.2771 ++
 25.2772 ++          if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t')
 25.2773 ++            {
 25.2774 ++              int  width_inc;
 25.2775 ++
 25.2776 ++              width_inc = TAB_WIDTH (chars_per_c, input_position);
 25.2777 ++              width += width_inc;
 25.2778 ++
 25.2779 ++              if (untabify_input)
 25.2780 ++                {
 25.2781 ++                  for (i = width_inc; i; --i)
 25.2782 ++                    *s++ = ' ';
 25.2783 ++                  chars += width_inc;
 25.2784 ++                }
 25.2785 ++              else
 25.2786 ++                {
 25.2787 ++                  for (i = 0; i <  mblength; i++)
 25.2788 ++                    *s++ = mbc[i];
 25.2789 ++                  chars += mblength;
 25.2790 ++                }
 25.2791 ++            }
 25.2792 ++          else if ((wc_width = wcwidth (wc)) < 1)
 25.2793 ++            {
 25.2794 ++              if (use_esc_sequence)
 25.2795 ++                {
 25.2796 ++                  for (i = 0; i < mblength; i++)
 25.2797 ++                    {
 25.2798 ++                      width += 4;
 25.2799 ++                      chars += 4;
 25.2800 ++                      *s++ = '\\';
 25.2801 ++                      sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 25.2802 ++                      for (j = 0; j <= 2; ++j)
 25.2803 ++                        *s++ = (int) esc_buff[j];
 25.2804 ++                    }
 25.2805 ++                }
 25.2806 ++              else if (use_cntrl_prefix)
 25.2807 ++                {
 25.2808 ++                  if (wc < 0200)
 25.2809 ++                    {
 25.2810 ++                      width += 2;
 25.2811 ++                      chars += 2;
 25.2812 ++                      *s++ = '^';
 25.2813 ++                      *s++ = wc ^ 0100;
 25.2814 ++                    }
 25.2815 ++                  else
 25.2816 ++                    {
 25.2817 ++                      for (i = 0; i < mblength; i++)
 25.2818 ++                        {
 25.2819 ++                          width += 4;
 25.2820 ++                          chars += 4;
 25.2821 ++                          *s++ = '\\';
 25.2822 ++                          sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
 25.2823 ++                          for (j = 0; j <= 2; ++j)
 25.2824 ++                            *s++ = (int) esc_buff[j];
 25.2825 ++                        }
 25.2826 ++                    }
 25.2827 ++                }
 25.2828 ++              else if (wc == L'\b')
 25.2829 ++                {
 25.2830 ++                  width += -1;
 25.2831 ++                  chars += 1;
 25.2832 ++                  *s++ = c;
 25.2833 ++                }
 25.2834 ++              else
 25.2835 ++                {
 25.2836 ++                  width += 0;
 25.2837 ++                  chars += mblength;
 25.2838 ++                  for (i = 0; i < mblength; i++)
 25.2839 ++                    *s++ = mbc[i];
 25.2840 ++                }
 25.2841 ++            }
 25.2842 ++          else
 25.2843 ++            {
 25.2844 ++              width += wc_width;
 25.2845 ++              chars += mblength;
 25.2846 ++              for (i = 0; i < mblength; i++)
 25.2847 ++                *s++ = mbc[i];
 25.2848 ++            }
 25.2849 ++        }
 25.2850 ++      memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength);
 25.2851 ++      mbc_pos -= mblength;
 25.2852 ++    }
 25.2853 ++
 25.2854 ++  /* Too many backspaces must put us in position 0 -- never negative. */
 25.2855 ++  if (width < 0 && input_position == 0)
 25.2856 ++    {
 25.2857 ++      chars = 0;
 25.2858 ++      input_position = 0;
 25.2859 ++    }
 25.2860 ++  else if (width < 0 && input_position <= -width)
 25.2861 ++    input_position = 0;
 25.2862 ++  else
 25.2863 ++   input_position += width;
 25.2864 ++
 25.2865 ++  return chars;
 25.2866 ++}
 25.2867 ++#endif
 25.2868 ++
 25.2869 + /* We've just printed some files and need to clean up things before
 25.2870 +    looking for more options and printing the next batch of files.
 25.2871 + 
 25.2872 +diff -Naurp coreutils-8.27-orig/src/sort.c coreutils-8.27/src/sort.c
 25.2873 +--- coreutils-8.27-orig/src/sort.c	2017-01-01 16:34:24.000000000 -0600
 25.2874 ++++ coreutils-8.27/src/sort.c	2017-03-11 23:49:22.416505389 -0600
 25.2875 +@@ -29,6 +29,14 @@
 25.2876 + #include <sys/wait.h>
 25.2877 + #include <signal.h>
 25.2878 + #include <assert.h>
 25.2879 ++#if HAVE_WCHAR_H
 25.2880 ++# include <wchar.h>
 25.2881 ++#endif
 25.2882 ++/* Get isw* functions. */
 25.2883 ++#if HAVE_WCTYPE_H
 25.2884 ++# include <wctype.h>
 25.2885 ++#endif
 25.2886 ++
 25.2887 + #include "system.h"
 25.2888 + #include "argmatch.h"
 25.2889 + #include "die.h"
 25.2890 +@@ -165,14 +173,39 @@ static int decimal_point;
 25.2891 + /* Thousands separator; if -1, then there isn't one.  */
 25.2892 + static int thousands_sep;
 25.2893 + 
 25.2894 ++/* True if -f is specified.  */
 25.2895 ++static bool folding;
 25.2896 ++
 25.2897 + /* Nonzero if the corresponding locales are hard.  */
 25.2898 + static bool hard_LC_COLLATE;
 25.2899 +-#if HAVE_NL_LANGINFO
 25.2900 ++#if HAVE_LANGINFO_CODESET
 25.2901 + static bool hard_LC_TIME;
 25.2902 + #endif
 25.2903 + 
 25.2904 + #define NONZERO(x) ((x) != 0)
 25.2905 + 
 25.2906 ++/* get a multibyte character's byte length. */
 25.2907 ++#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE)                        \
 25.2908 ++  do                                                                        \
 25.2909 ++    {                                                                        \
 25.2910 ++      wchar_t wc;                                                        \
 25.2911 ++      mbstate_t state_bak;                                                \
 25.2912 ++                                                                        \
 25.2913 ++      state_bak = STATE;                                                \
 25.2914 ++      mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE);                        \
 25.2915 ++                                                                        \
 25.2916 ++      switch (MBLENGTH)                                                        \
 25.2917 ++        {                                                                \
 25.2918 ++        case (size_t)-1:                                                \
 25.2919 ++        case (size_t)-2:                                                \
 25.2920 ++          STATE = state_bak;                                                \
 25.2921 ++                /* Fall through. */                                        \
 25.2922 ++        case 0:                                                                \
 25.2923 ++          MBLENGTH = 1;                                                        \
 25.2924 ++      }                                                                        \
 25.2925 ++    }                                                                        \
 25.2926 ++  while (0)
 25.2927 ++
 25.2928 + /* The kind of blanks for '-b' to skip in various options. */
 25.2929 + enum blanktype { bl_start, bl_end, bl_both };
 25.2930 + 
 25.2931 +@@ -346,13 +379,11 @@ static bool reverse;
 25.2932 +    they were read if all keys compare equal.  */
 25.2933 + static bool stable;
 25.2934 + 
 25.2935 +-/* If TAB has this value, blanks separate fields.  */
 25.2936 +-enum { TAB_DEFAULT = CHAR_MAX + 1 };
 25.2937 +-
 25.2938 +-/* Tab character separating fields.  If TAB_DEFAULT, then fields are
 25.2939 ++/* Tab character separating fields.  If tab_length is 0, then fields are
 25.2940 +    separated by the empty string between a non-blank character and a blank
 25.2941 +    character. */
 25.2942 +-static int tab = TAB_DEFAULT;
 25.2943 ++static char tab[MB_LEN_MAX + 1];
 25.2944 ++static size_t tab_length = 0;
 25.2945 + 
 25.2946 + /* Flag to remove consecutive duplicate lines from the output.
 25.2947 +    Only the last of a sequence of equal lines will be output. */
 25.2948 +@@ -811,6 +842,46 @@ reap_all (void)
 25.2949 +     reap (-1);
 25.2950 + }
 25.2951 + 
 25.2952 ++/* Function pointers. */
 25.2953 ++static void
 25.2954 ++(*inittables) (void);
 25.2955 ++static char *
 25.2956 ++(*begfield) (const struct line*, const struct keyfield *);
 25.2957 ++static char *
 25.2958 ++(*limfield) (const struct line*, const struct keyfield *);
 25.2959 ++static void
 25.2960 ++(*skipblanks) (char **ptr, char *lim);
 25.2961 ++static int
 25.2962 ++(*getmonth) (char const *, size_t, char **);
 25.2963 ++static int
 25.2964 ++(*keycompare) (const struct line *, const struct line *);
 25.2965 ++static int
 25.2966 ++(*numcompare) (const char *, const char *);
 25.2967 ++
 25.2968 ++/* Test for white space multibyte character.
 25.2969 ++   Set LENGTH the byte length of investigated multibyte character. */
 25.2970 ++#if HAVE_MBRTOWC
 25.2971 ++static int
 25.2972 ++ismbblank (const char *str, size_t len, size_t *length)
 25.2973 ++{
 25.2974 ++  size_t mblength;
 25.2975 ++  wchar_t wc;
 25.2976 ++  mbstate_t state;
 25.2977 ++
 25.2978 ++  memset (&state, '\0', sizeof(mbstate_t));
 25.2979 ++  mblength = mbrtowc (&wc, str, len, &state);
 25.2980 ++
 25.2981 ++  if (mblength == (size_t)-1 || mblength == (size_t)-2)
 25.2982 ++    {
 25.2983 ++      *length = 1;
 25.2984 ++      return 0;
 25.2985 ++    }
 25.2986 ++
 25.2987 ++  *length = (mblength < 1) ? 1 : mblength;
 25.2988 ++  return iswblank (wc) || wc == '\n';
 25.2989 ++}
 25.2990 ++#endif
 25.2991 ++
 25.2992 + /* Clean up any remaining temporary files.  */
 25.2993 + 
 25.2994 + static void
 25.2995 +@@ -1255,7 +1326,7 @@ zaptemp (char const *name)
 25.2996 +   free (node);
 25.2997 + }
 25.2998 + 
 25.2999 +-#if HAVE_NL_LANGINFO
 25.3000 ++#if HAVE_LANGINFO_CODESET
 25.3001 + 
 25.3002 + static int
 25.3003 + struct_month_cmp (void const *m1, void const *m2)
 25.3004 +@@ -1270,7 +1341,7 @@ struct_month_cmp (void const *m1, void c
 25.3005 + /* Initialize the character class tables. */
 25.3006 + 
 25.3007 + static void
 25.3008 +-inittables (void)
 25.3009 ++inittables_uni (void)
 25.3010 + {
 25.3011 +   size_t i;
 25.3012 + 
 25.3013 +@@ -1282,7 +1353,7 @@ inittables (void)
 25.3014 +       fold_toupper[i] = toupper (i);
 25.3015 +     }
 25.3016 + 
 25.3017 +-#if HAVE_NL_LANGINFO
 25.3018 ++#if HAVE_LANGINFO_CODESET
 25.3019 +   /* If we're not in the "C" locale, read different names for months.  */
 25.3020 +   if (hard_LC_TIME)
 25.3021 +     {
 25.3022 +@@ -1364,6 +1435,84 @@ specify_nmerge (int oi, char c, char con
 25.3023 +     xstrtol_fatal (e, oi, c, long_options, s);
 25.3024 + }
 25.3025 + 
 25.3026 ++#if HAVE_MBRTOWC
 25.3027 ++static void
 25.3028 ++inittables_mb (void)
 25.3029 ++{
 25.3030 ++  int i, j, k, l;
 25.3031 ++  char *name, *s, *lc_time, *lc_ctype;
 25.3032 ++  size_t s_len, mblength;
 25.3033 ++  char mbc[MB_LEN_MAX];
 25.3034 ++  wchar_t wc, pwc;
 25.3035 ++  mbstate_t state_mb, state_wc;
 25.3036 ++
 25.3037 ++  lc_time = setlocale (LC_TIME, "");
 25.3038 ++  if (lc_time)
 25.3039 ++    lc_time = xstrdup (lc_time);
 25.3040 ++
 25.3041 ++  lc_ctype = setlocale (LC_CTYPE, "");
 25.3042 ++  if (lc_ctype)
 25.3043 ++    lc_ctype = xstrdup (lc_ctype);
 25.3044 ++
 25.3045 ++  if (lc_time && lc_ctype)
 25.3046 ++    /* temporarily set LC_CTYPE to match LC_TIME, so that we can convert
 25.3047 ++     * the names of months to upper case */
 25.3048 ++    setlocale (LC_CTYPE, lc_time);
 25.3049 ++
 25.3050 ++  for (i = 0; i < MONTHS_PER_YEAR; i++)
 25.3051 ++    {
 25.3052 ++      s = (char *) nl_langinfo (ABMON_1 + i);
 25.3053 ++      s_len = strlen (s);
 25.3054 ++      monthtab[i].name = name = (char *) xmalloc (s_len + 1);
 25.3055 ++      monthtab[i].val = i + 1;
 25.3056 ++
 25.3057 ++      memset (&state_mb, '\0', sizeof (mbstate_t));
 25.3058 ++      memset (&state_wc, '\0', sizeof (mbstate_t));
 25.3059 ++
 25.3060 ++      for (j = 0; j < s_len;)
 25.3061 ++        {
 25.3062 ++          if (!ismbblank (s + j, s_len - j, &mblength))
 25.3063 ++            break;
 25.3064 ++          j += mblength;
 25.3065 ++        }
 25.3066 ++
 25.3067 ++      for (k = 0; j < s_len;)
 25.3068 ++        {
 25.3069 ++          mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb);
 25.3070 ++          assert (mblength != (size_t)-1 && mblength != (size_t)-2);
 25.3071 ++          if (mblength == 0)
 25.3072 ++            break;
 25.3073 ++
 25.3074 ++          pwc = towupper (wc);
 25.3075 ++          if (pwc == wc)
 25.3076 ++            {
 25.3077 ++              memcpy (mbc, s + j, mblength);
 25.3078 ++              j += mblength;
 25.3079 ++            }
 25.3080 ++          else
 25.3081 ++            {
 25.3082 ++              j += mblength;
 25.3083 ++              mblength = wcrtomb (mbc, pwc, &state_wc);
 25.3084 ++              assert (mblength != (size_t)0 && mblength != (size_t)-1);
 25.3085 ++            }
 25.3086 ++
 25.3087 ++          for (l = 0; l < mblength; l++)
 25.3088 ++            name[k++] = mbc[l];
 25.3089 ++        }
 25.3090 ++      name[k] = '\0';
 25.3091 ++    }
 25.3092 ++  qsort ((void *) monthtab, MONTHS_PER_YEAR,
 25.3093 ++      sizeof (struct month), struct_month_cmp);
 25.3094 ++
 25.3095 ++  if (lc_time && lc_ctype)
 25.3096 ++    /* restore the original locales */
 25.3097 ++    setlocale (LC_CTYPE, lc_ctype);
 25.3098 ++
 25.3099 ++  free (lc_ctype);
 25.3100 ++  free (lc_time);
 25.3101 ++}
 25.3102 ++#endif
 25.3103 ++
 25.3104 + /* Specify the amount of main memory to use when sorting.  */
 25.3105 + static void
 25.3106 + specify_sort_size (int oi, char c, char const *s)
 25.3107 +@@ -1597,7 +1746,7 @@ buffer_linelim (struct buffer const *buf
 25.3108 +    by KEY in LINE. */
 25.3109 + 
 25.3110 + static char *
 25.3111 +-begfield (struct line const *line, struct keyfield const *key)
 25.3112 ++begfield_uni (const struct line *line, const struct keyfield *key)
 25.3113 + {
 25.3114 +   char *ptr = line->text, *lim = ptr + line->length - 1;
 25.3115 +   size_t sword = key->sword;
 25.3116 +@@ -1606,10 +1755,10 @@ begfield (struct line const *line, struc
 25.3117 +   /* The leading field separator itself is included in a field when -t
 25.3118 +      is absent.  */
 25.3119 + 
 25.3120 +-  if (tab != TAB_DEFAULT)
 25.3121 ++  if (tab_length)
 25.3122 +     while (ptr < lim && sword--)
 25.3123 +       {
 25.3124 +-        while (ptr < lim && *ptr != tab)
 25.3125 ++        while (ptr < lim && *ptr != tab[0])
 25.3126 +           ++ptr;
 25.3127 +         if (ptr < lim)
 25.3128 +           ++ptr;
 25.3129 +@@ -1635,11 +1784,70 @@ begfield (struct line const *line, struc
 25.3130 +   return ptr;
 25.3131 + }
 25.3132 + 
 25.3133 ++#if HAVE_MBRTOWC
 25.3134 ++static char *
 25.3135 ++begfield_mb (const struct line *line, const struct keyfield *key)
 25.3136 ++{
 25.3137 ++  int i;
 25.3138 ++  char *ptr = line->text, *lim = ptr + line->length - 1;
 25.3139 ++  size_t sword = key->sword;
 25.3140 ++  size_t schar = key->schar;
 25.3141 ++  size_t mblength;
 25.3142 ++  mbstate_t state;
 25.3143 ++
 25.3144 ++  memset (&state, '\0', sizeof(mbstate_t));
 25.3145 ++
 25.3146 ++  if (tab_length)
 25.3147 ++    while (ptr < lim && sword--)
 25.3148 ++      {
 25.3149 ++        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 25.3150 ++          {
 25.3151 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3152 ++            ptr += mblength;
 25.3153 ++          }
 25.3154 ++        if (ptr < lim)
 25.3155 ++          {
 25.3156 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3157 ++            ptr += mblength;
 25.3158 ++          }
 25.3159 ++      }
 25.3160 ++  else
 25.3161 ++    while (ptr < lim && sword--)
 25.3162 ++      {
 25.3163 ++        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 25.3164 ++          ptr += mblength;
 25.3165 ++        if (ptr < lim)
 25.3166 ++          {
 25.3167 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3168 ++            ptr += mblength;
 25.3169 ++          }
 25.3170 ++        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 25.3171 ++          ptr += mblength;
 25.3172 ++      }
 25.3173 ++
 25.3174 ++  if (key->skipsblanks)
 25.3175 ++    while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 25.3176 ++      ptr += mblength;
 25.3177 ++
 25.3178 ++  for (i = 0; i < schar; i++)
 25.3179 ++    {
 25.3180 ++      GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3181 ++
 25.3182 ++      if (ptr + mblength > lim)
 25.3183 ++        break;
 25.3184 ++      else
 25.3185 ++        ptr += mblength;
 25.3186 ++    }
 25.3187 ++
 25.3188 ++  return ptr;
 25.3189 ++}
 25.3190 ++#endif
 25.3191 ++
 25.3192 + /* Return the limit of (a pointer to the first character after) the field
 25.3193 +    in LINE specified by KEY. */
 25.3194 + 
 25.3195 + static char *
 25.3196 +-limfield (struct line const *line, struct keyfield const *key)
 25.3197 ++limfield_uni (const struct line *line, const struct keyfield *key)
 25.3198 + {
 25.3199 +   char *ptr = line->text, *lim = ptr + line->length - 1;
 25.3200 +   size_t eword = key->eword, echar = key->echar;
 25.3201 +@@ -1654,10 +1862,10 @@ limfield (struct line const *line, struc
 25.3202 +      'beginning' is the first character following the delimiting TAB.
 25.3203 +      Otherwise, leave PTR pointing at the first 'blank' character after
 25.3204 +      the preceding field.  */
 25.3205 +-  if (tab != TAB_DEFAULT)
 25.3206 ++  if (tab_length)
 25.3207 +     while (ptr < lim && eword--)
 25.3208 +       {
 25.3209 +-        while (ptr < lim && *ptr != tab)
 25.3210 ++        while (ptr < lim && *ptr != tab[0])
 25.3211 +           ++ptr;
 25.3212 +         if (ptr < lim && (eword || echar))
 25.3213 +           ++ptr;
 25.3214 +@@ -1703,10 +1911,10 @@ limfield (struct line const *line, struc
 25.3215 +      */
 25.3216 + 
 25.3217 +   /* Make LIM point to the end of (one byte past) the current field.  */
 25.3218 +-  if (tab != TAB_DEFAULT)
 25.3219 ++  if (tab_length)
 25.3220 +     {
 25.3221 +       char *newlim;
 25.3222 +-      newlim = memchr (ptr, tab, lim - ptr);
 25.3223 ++      newlim = memchr (ptr, tab[0], lim - ptr);
 25.3224 +       if (newlim)
 25.3225 +         lim = newlim;
 25.3226 +     }
 25.3227 +@@ -1737,6 +1945,130 @@ limfield (struct line const *line, struc
 25.3228 +   return ptr;
 25.3229 + }
 25.3230 + 
 25.3231 ++#if HAVE_MBRTOWC
 25.3232 ++static char *
 25.3233 ++limfield_mb (const struct line *line, const struct keyfield *key)
 25.3234 ++{
 25.3235 ++  char *ptr = line->text, *lim = ptr + line->length - 1;
 25.3236 ++  size_t eword = key->eword, echar = key->echar;
 25.3237 ++  int i;
 25.3238 ++  size_t mblength;
 25.3239 ++  mbstate_t state;
 25.3240 ++
 25.3241 ++  if (echar == 0)
 25.3242 ++    eword++; /* skip all of end field. */
 25.3243 ++
 25.3244 ++  memset (&state, '\0', sizeof(mbstate_t));
 25.3245 ++
 25.3246 ++  if (tab_length)
 25.3247 ++    while (ptr < lim && eword--)
 25.3248 ++      {
 25.3249 ++        while (ptr < lim && memcmp (ptr, tab, tab_length) != 0)
 25.3250 ++          {
 25.3251 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3252 ++            ptr += mblength;
 25.3253 ++          }
 25.3254 ++        if (ptr < lim && (eword | echar))
 25.3255 ++          {
 25.3256 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3257 ++            ptr += mblength;
 25.3258 ++          }
 25.3259 ++      }
 25.3260 ++  else
 25.3261 ++    while (ptr < lim && eword--)
 25.3262 ++      {
 25.3263 ++        while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 25.3264 ++          ptr += mblength;
 25.3265 ++        if (ptr < lim)
 25.3266 ++          {
 25.3267 ++            GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3268 ++            ptr += mblength;
 25.3269 ++          }
 25.3270 ++        while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength))
 25.3271 ++          ptr += mblength;
 25.3272 ++      }
 25.3273 ++
 25.3274 ++
 25.3275 ++# ifdef POSIX_UNSPECIFIED
 25.3276 ++  /* Make LIM point to the end of (one byte past) the current field.  */
 25.3277 ++  if (tab_length)
 25.3278 ++    {
 25.3279 ++      char *newlim, *p;
 25.3280 ++
 25.3281 ++      newlim = NULL;
 25.3282 ++      for (p = ptr; p < lim;)
 25.3283 ++         {
 25.3284 ++          if (memcmp (p, tab, tab_length) == 0)
 25.3285 ++            {
 25.3286 ++              newlim = p;
 25.3287 ++              break;
 25.3288 ++            }
 25.3289 ++
 25.3290 ++          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3291 ++          p += mblength;
 25.3292 ++        }
 25.3293 ++    }
 25.3294 ++  else
 25.3295 ++    {
 25.3296 ++      char *newlim;
 25.3297 ++      newlim = ptr;
 25.3298 ++
 25.3299 ++      while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength))
 25.3300 ++        newlim += mblength;
 25.3301 ++      if (ptr < lim)
 25.3302 ++        {
 25.3303 ++          GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3304 ++          ptr += mblength;
 25.3305 ++        }
 25.3306 ++      while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength))
 25.3307 ++        newlim += mblength;
 25.3308 ++      lim = newlim;
 25.3309 ++    }
 25.3310 ++# endif
 25.3311 ++
 25.3312 ++  if (echar != 0)
 25.3313 ++  {
 25.3314 ++    /* If we're skipping leading blanks, don't start counting characters
 25.3315 ++     *      until after skipping past any leading blanks.  */
 25.3316 ++    if (key->skipeblanks)
 25.3317 ++      while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
 25.3318 ++        ptr += mblength;
 25.3319 ++
 25.3320 ++    memset (&state, '\0', sizeof(mbstate_t));
 25.3321 ++
 25.3322 ++    /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
 25.3323 ++    for (i = 0; i < echar; i++)
 25.3324 ++     {
 25.3325 ++        GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state);
 25.3326 ++
 25.3327 ++        if (ptr + mblength > lim)
 25.3328 ++          break;
 25.3329 ++        else
 25.3330 ++          ptr += mblength;
 25.3331 ++      }
 25.3332 ++  }
 25.3333 ++
 25.3334 ++  return ptr;
 25.3335 ++}
 25.3336 ++#endif
 25.3337 ++
 25.3338 ++static void
 25.3339 ++skipblanks_uni (char **ptr, char *lim)
 25.3340 ++{
 25.3341 ++  while (*ptr < lim && blanks[to_uchar (**ptr)])
 25.3342 ++    ++(*ptr);
 25.3343 ++}
 25.3344 ++
 25.3345 ++#if HAVE_MBRTOWC
 25.3346 ++static void
 25.3347 ++skipblanks_mb (char **ptr, char *lim)
 25.3348 ++{
 25.3349 ++  size_t mblength;
 25.3350 ++  while (*ptr < lim && ismbblank (*ptr, lim - *ptr, &mblength))
 25.3351 ++    (*ptr) += mblength;
 25.3352 ++}
 25.3353 ++#endif
 25.3354 ++
 25.3355 + /* Fill BUF reading from FP, moving buf->left bytes from the end
 25.3356 +    of buf->buf to the beginning first.  If EOF is reached and the
 25.3357 +    file wasn't terminated by a newline, supply one.  Set up BUF's line
 25.3358 +@@ -1823,8 +2155,22 @@ fillbuf (struct buffer *buf, FILE *fp, c
 25.3359 +                   else
 25.3360 +                     {
 25.3361 +                       if (key->skipsblanks)
 25.3362 +-                        while (blanks[to_uchar (*line_start)])
 25.3363 +-                          line_start++;
 25.3364 ++                        {
 25.3365 ++#if HAVE_MBRTOWC
 25.3366 ++                          if (MB_CUR_MAX > 1)
 25.3367 ++                            {
 25.3368 ++                              size_t mblength;
 25.3369 ++                              while (line_start < line->keylim &&
 25.3370 ++                                     ismbblank (line_start,
 25.3371 ++                                                line->keylim - line_start,
 25.3372 ++                                                &mblength))
 25.3373 ++                                line_start += mblength;
 25.3374 ++                            }
 25.3375 ++                          else
 25.3376 ++#endif
 25.3377 ++                          while (blanks[to_uchar (*line_start)])
 25.3378 ++                            line_start++;
 25.3379 ++                        }
 25.3380 +                       line->keybeg = line_start;
 25.3381 +                     }
 25.3382 +                 }
 25.3383 +@@ -1958,12 +2304,10 @@ find_unit_order (char const *number)
 25.3384 +        <none/unknown> < K/k < M < G < T < P < E < Z < Y  */
 25.3385 + 
 25.3386 + static int
 25.3387 +-human_numcompare (char const *a, char const *b)
 25.3388 ++human_numcompare (char *a, char *b)
 25.3389 + {
 25.3390 +-  while (blanks[to_uchar (*a)])
 25.3391 +-    a++;
 25.3392 +-  while (blanks[to_uchar (*b)])
 25.3393 +-    b++;
 25.3394 ++  skipblanks(&a, a + strlen(a));
 25.3395 ++  skipblanks(&b, b + strlen(b));
 25.3396 + 
 25.3397 +   int diff = find_unit_order (a) - find_unit_order (b);
 25.3398 +   return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep));
 25.3399 +@@ -1974,7 +2318,7 @@ human_numcompare (char const *a, char co
 25.3400 +    hideously fast. */
 25.3401 + 
 25.3402 + static int
 25.3403 +-numcompare (char const *a, char const *b)
 25.3404 ++numcompare_uni (const char *a, const char *b)
 25.3405 + {
 25.3406 +   while (blanks[to_uchar (*a)])
 25.3407 +     a++;
 25.3408 +@@ -1984,6 +2328,25 @@ numcompare (char const *a, char const *b
 25.3409 +   return strnumcmp (a, b, decimal_point, thousands_sep);
 25.3410 + }
 25.3411 + 
 25.3412 ++#if HAVE_MBRTOWC
 25.3413 ++static int
 25.3414 ++numcompare_mb (const char *a, const char *b)
 25.3415 ++{
 25.3416 ++  size_t mblength, len;
 25.3417 ++  len = strlen (a); /* okay for UTF-8 */
 25.3418 ++  while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 25.3419 ++    {
 25.3420 ++      a += mblength;
 25.3421 ++      len -= mblength;
 25.3422 ++    }
 25.3423 ++  len = strlen (b); /* okay for UTF-8 */
 25.3424 ++  while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength))
 25.3425 ++    b += mblength;
 25.3426 ++
 25.3427 ++  return strnumcmp (a, b, decimal_point, thousands_sep);
 25.3428 ++}
 25.3429 ++#endif /* HAV_EMBRTOWC */
 25.3430 ++
 25.3431 + /* Work around a problem whereby the long double value returned by glibc's
 25.3432 +    strtold ("NaN", ...) contains uninitialized bits: clear all bytes of
 25.3433 +    A and B before calling strtold.  FIXME: remove this function once
 25.3434 +@@ -2034,7 +2397,7 @@ general_numcompare (char const *sa, char
 25.3435 +    Return 0 if the name in S is not recognized.  */
 25.3436 + 
 25.3437 + static int
 25.3438 +-getmonth (char const *month, char **ea)
 25.3439 ++getmonth_uni (char const *month, size_t len, char **ea)
 25.3440 + {
 25.3441 +   size_t lo = 0;
 25.3442 +   size_t hi = MONTHS_PER_YEAR;
 25.3443 +@@ -2310,15 +2673,14 @@ debug_key (struct line const *line, stru
 25.3444 +           char saved = *lim;
 25.3445 +           *lim = '\0';
 25.3446 + 
 25.3447 +-          while (blanks[to_uchar (*beg)])
 25.3448 +-            beg++;
 25.3449 ++          skipblanks (&beg, lim);
 25.3450 + 
 25.3451 +           char *tighter_lim = beg;
 25.3452 + 
 25.3453 +           if (lim < beg)
 25.3454 +             tighter_lim = lim;
 25.3455 +           else if (key->month)
 25.3456 +-            getmonth (beg, &tighter_lim);
 25.3457 ++            getmonth (beg, lim-beg, &tighter_lim);
 25.3458 +           else if (key->general_numeric)
 25.3459 +             ignore_value (strtold (beg, &tighter_lim));
 25.3460 +           else if (key->numeric || key->human_numeric)
 25.3461 +@@ -2452,7 +2814,7 @@ key_warnings (struct keyfield const *gke
 25.3462 +       /* Warn about significant leading blanks.  */
 25.3463 +       bool implicit_skip = key_numeric (key) || key->month;
 25.3464 +       bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y  */
 25.3465 +-      if (!zero_width && !gkey_only && tab == TAB_DEFAULT && !line_offset
 25.3466 ++      if (!zero_width && !gkey_only && !tab_length && !line_offset
 25.3467 +           && ((!key->skipsblanks && !implicit_skip)
 25.3468 +               || (!key->skipsblanks && key->schar)
 25.3469 +               || (!key->skipeblanks && key->echar)))
 25.3470 +@@ -2510,11 +2872,87 @@ key_warnings (struct keyfield const *gke
 25.3471 +     error (0, 0, _("option '-r' only applies to last-resort comparison"));
 25.3472 + }
 25.3473 + 
 25.3474 ++#if HAVE_MBRTOWC
 25.3475 ++static int
 25.3476 ++getmonth_mb (const char *s, size_t len, char **ea)
 25.3477 ++{
 25.3478 ++  char *month;
 25.3479 ++  register size_t i;
 25.3480 ++  register int lo = 0, hi = MONTHS_PER_YEAR, result;
 25.3481 ++  char *tmp;
 25.3482 ++  size_t wclength, mblength;
 25.3483 ++  const char *pp;
 25.3484 ++  const wchar_t *wpp;
 25.3485 ++  wchar_t *month_wcs;
 25.3486 ++  mbstate_t state;
 25.3487 ++
 25.3488 ++  while (len > 0 && ismbblank (s, len, &mblength))
 25.3489 ++    {
 25.3490 ++      s += mblength;
 25.3491 ++      len -= mblength;
 25.3492 ++    }
 25.3493 ++
 25.3494 ++  if (len == 0)
 25.3495 ++    return 0;
 25.3496 ++
 25.3497 ++  if (SIZE_MAX - len < 1)
 25.3498 ++    xalloc_die ();
 25.3499 ++
 25.3500 ++  month = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 25.3501 ++
 25.3502 ++  pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX);
 25.3503 ++  memcpy (tmp, s, len);
 25.3504 ++  tmp[len] = '\0';
 25.3505 ++  wpp = month_wcs = (wchar_t *) xnmalloc (len + 1, sizeof (wchar_t));
 25.3506 ++  memset (&state, '\0', sizeof (mbstate_t));
 25.3507 ++
 25.3508 ++  wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state);
 25.3509 ++  if (wclength == (size_t)-1 || pp != NULL)
 25.3510 ++    error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s));
 25.3511 ++
 25.3512 ++  for (i = 0; i < wclength; i++)
 25.3513 ++    {
 25.3514 ++      month_wcs[i] = towupper(month_wcs[i]);
 25.3515 ++      if (iswblank (month_wcs[i]))
 25.3516 ++        {
 25.3517 ++          month_wcs[i] = L'\0';
 25.3518 ++          break;
 25.3519 ++        }
 25.3520 ++    }
 25.3521 ++
 25.3522 ++  mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state);
 25.3523 ++  assert (mblength != (-1) && wpp == NULL);
 25.3524 ++
 25.3525 ++  do
 25.3526 ++    {
 25.3527 ++      int ix = (lo + hi) / 2;
 25.3528 ++
 25.3529 ++      if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0)
 25.3530 ++        hi = ix;
 25.3531 ++      else
 25.3532 ++        lo = ix;
 25.3533 ++    }
 25.3534 ++  while (hi - lo > 1);
 25.3535 ++
 25.3536 ++  result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name))
 25.3537 ++      ? monthtab[lo].val : 0);
 25.3538 ++
 25.3539 ++  if (ea && result)
 25.3540 ++     *ea = (char*) s + strlen (monthtab[lo].name);
 25.3541 ++
 25.3542 ++  free (month);
 25.3543 ++  free (tmp);
 25.3544 ++  free (month_wcs);
 25.3545 ++
 25.3546 ++  return result;
 25.3547 ++}
 25.3548 ++#endif
 25.3549 ++
 25.3550 + /* Compare two lines A and B trying every key in sequence until there
 25.3551 +    are no more keys or a difference is found. */
 25.3552 + 
 25.3553 + static int
 25.3554 +-keycompare (struct line const *a, struct line const *b)
 25.3555 ++keycompare_uni (const struct line *a, const struct line *b)
 25.3556 + {
 25.3557 +   struct keyfield *key = keylist;
 25.3558 + 
 25.3559 +@@ -2599,7 +3037,7 @@ keycompare (struct line const *a, struct
 25.3560 +           else if (key->human_numeric)
 25.3561 +             diff = human_numcompare (ta, tb);
 25.3562 +           else if (key->month)
 25.3563 +-            diff = getmonth (ta, NULL) - getmonth (tb, NULL);
 25.3564 ++            diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL);
 25.3565 +           else if (key->random)
 25.3566 +             diff = compare_random (ta, tlena, tb, tlenb);
 25.3567 +           else if (key->version)
 25.3568 +@@ -2715,6 +3153,211 @@ keycompare (struct line const *a, struct
 25.3569 +   return key->reverse ? -diff : diff;
 25.3570 + }
 25.3571 + 
 25.3572 ++#if HAVE_MBRTOWC
 25.3573 ++static int
 25.3574 ++keycompare_mb (const struct line *a, const struct line *b)
 25.3575 ++{
 25.3576 ++  struct keyfield *key = keylist;
 25.3577 ++
 25.3578 ++  /* For the first iteration only, the key positions have been
 25.3579 ++     precomputed for us. */
 25.3580 ++  char *texta = a->keybeg;
 25.3581 ++  char *textb = b->keybeg;
 25.3582 ++  char *lima = a->keylim;
 25.3583 ++  char *limb = b->keylim;
 25.3584 ++
 25.3585 ++  size_t mblength_a, mblength_b;
 25.3586 ++  wchar_t wc_a, wc_b;
 25.3587 ++  mbstate_t state_a, state_b;
 25.3588 ++
 25.3589 ++  int diff = 0;
 25.3590 ++
 25.3591 ++  memset (&state_a, '\0', sizeof(mbstate_t));
 25.3592 ++  memset (&state_b, '\0', sizeof(mbstate_t));
 25.3593 ++  /* Ignore keys with start after end.  */
 25.3594 ++  if (a->keybeg - a->keylim > 0)
 25.3595 ++    return 0;
 25.3596 ++
 25.3597 ++
 25.3598 ++              /* Ignore and/or translate chars before comparing.  */
 25.3599 ++# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE)        \
 25.3600 ++  do                                                                        \
 25.3601 ++    {                                                                        \
 25.3602 ++      wchar_t uwc;                                                        \
 25.3603 ++      char mbc[MB_LEN_MAX];                                                \
 25.3604 ++      mbstate_t state_wc;                                                \
 25.3605 ++                                                                        \
 25.3606 ++      for (NEW_LEN = i = 0; i < LEN;)                                        \
 25.3607 ++        {                                                                \
 25.3608 ++          mbstate_t state_bak;                                                \
 25.3609 ++                                                                        \
 25.3610 ++          state_bak = STATE;                                                \
 25.3611 ++          MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE);                \
 25.3612 ++                                                                        \
 25.3613 ++          if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1                \
 25.3614 ++              || MBLENGTH == 0)                                                \
 25.3615 ++            {                                                                \
 25.3616 ++              if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1)        \
 25.3617 ++                STATE = state_bak;                                        \
 25.3618 ++              if (!ignore)                                                \
 25.3619 ++                COPY[NEW_LEN++] = TEXT[i];                                \
 25.3620 ++              i++;                                                         \
 25.3621 ++              continue;                                                        \
 25.3622 ++            }                                                                \
 25.3623 ++                                                                        \
 25.3624 ++          if (ignore)                                                        \
 25.3625 ++            {                                                                \
 25.3626 ++              if ((ignore == nonprinting && !iswprint (WC))                \
 25.3627 ++                   || (ignore == nondictionary                                \
 25.3628 ++                       && !iswalnum (WC) && !iswblank (WC)))                \
 25.3629 ++                {                                                        \
 25.3630 ++                  i += MBLENGTH;                                        \
 25.3631 ++                  continue;                                                \
 25.3632 ++                }                                                        \
 25.3633 ++            }                                                                \
 25.3634 ++                                                                        \
 25.3635 ++          if (translate)                                                \
 25.3636 ++            {                                                                \
 25.3637 ++                                                                        \
 25.3638 ++              uwc = towupper(WC);                                        \
 25.3639 ++              if (WC == uwc)                                                \
 25.3640 ++                {                                                        \
 25.3641 ++                  memcpy (mbc, TEXT + i, MBLENGTH);                        \
 25.3642 ++                  i += MBLENGTH;                                        \
 25.3643 ++                }                                                        \
 25.3644 ++              else                                                        \
 25.3645 ++                {                                                        \
 25.3646 ++                  i += MBLENGTH;                                        \
 25.3647 ++                  WC = uwc;                                                \
 25.3648 ++                  memset (&state_wc, '\0', sizeof (mbstate_t));                \
 25.3649 ++                                                                        \
 25.3650 ++                  MBLENGTH = wcrtomb (mbc, WC, &state_wc);                \
 25.3651 ++                  assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0);        \
 25.3652 ++                }                                                        \
 25.3653 ++                                                                        \
 25.3654 ++              for (j = 0; j < MBLENGTH; j++)                                \
 25.3655 ++                COPY[NEW_LEN++] = mbc[j];                                \
 25.3656 ++            }                                                                \
 25.3657 ++          else                                                                \
 25.3658 ++            for (j = 0; j < MBLENGTH; j++)                                \
 25.3659 ++              COPY[NEW_LEN++] = TEXT[i++];                                \
 25.3660 ++        }                                                                \
 25.3661 ++      COPY[NEW_LEN] = '\0';                                                \
 25.3662 ++    }                                                                        \
 25.3663 ++  while (0)
 25.3664 ++
 25.3665 ++      /* Actually compare the fields. */
 25.3666 ++
 25.3667 ++  for (;;)
 25.3668 ++    {
 25.3669 ++      /* Find the lengths. */
 25.3670 ++      size_t lena = lima <= texta ? 0 : lima - texta;
 25.3671 ++      size_t lenb = limb <= textb ? 0 : limb - textb;
 25.3672 ++
 25.3673 ++      char enda IF_LINT (= 0);
 25.3674 ++      char endb IF_LINT (= 0);
 25.3675 ++
 25.3676 ++      char const *translate = key->translate;
 25.3677 ++      bool const *ignore = key->ignore;
 25.3678 ++
 25.3679 ++      if (ignore || translate)
 25.3680 ++        {
 25.3681 ++          if (SIZE_MAX - lenb - 2 < lena)
 25.3682 ++            xalloc_die ();
 25.3683 ++          char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX);
 25.3684 ++          char *copy_b = copy_a + lena * MB_CUR_MAX + 1;
 25.3685 ++          size_t new_len_a, new_len_b;
 25.3686 ++          size_t i, j;
 25.3687 ++
 25.3688 ++          IGNORE_CHARS (new_len_a, lena, texta, copy_a,
 25.3689 ++                        wc_a, mblength_a, state_a);
 25.3690 ++          IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
 25.3691 ++                        wc_b, mblength_b, state_b);
 25.3692 ++          texta = copy_a; textb = copy_b;
 25.3693 ++          lena = new_len_a; lenb = new_len_b;
 25.3694 ++        }
 25.3695 ++      else
 25.3696 ++        {
 25.3697 ++          /* Use the keys in-place, temporarily null-terminated.  */
 25.3698 ++          enda = texta[lena]; texta[lena] = '\0';
 25.3699 ++          endb = textb[lenb]; textb[lenb] = '\0';
 25.3700 ++        }
 25.3701 ++
 25.3702 ++      if (key->random)
 25.3703 ++        diff = compare_random (texta, lena, textb, lenb);
 25.3704 ++      else if (key->numeric | key->general_numeric | key->human_numeric)
 25.3705 ++        {
 25.3706 ++          char savea = *lima, saveb = *limb;
 25.3707 ++
 25.3708 ++          *lima = *limb = '\0';
 25.3709 ++          diff = (key->numeric ? numcompare (texta, textb)
 25.3710 ++                  : key->general_numeric ? general_numcompare (texta, textb)
 25.3711 ++                  : human_numcompare (texta, textb));
 25.3712 ++          *lima = savea, *limb = saveb;
 25.3713 ++        }
 25.3714 ++      else if (key->version)
 25.3715 ++        diff = filevercmp (texta, textb);
 25.3716 ++      else if (key->month)
 25.3717 ++        diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL);
 25.3718 ++      else if (lena == 0)
 25.3719 ++        diff = - NONZERO (lenb);
 25.3720 ++      else if (lenb == 0)
 25.3721 ++        diff = 1;
 25.3722 ++      else if (hard_LC_COLLATE && !folding)
 25.3723 ++        {
 25.3724 ++          diff = xmemcoll0 (texta, lena + 1, textb, lenb + 1);
 25.3725 ++        }
 25.3726 ++      else
 25.3727 ++        {
 25.3728 ++          diff = memcmp (texta, textb, MIN (lena, lenb));
 25.3729 ++          if (diff == 0)
 25.3730 ++            diff = lena < lenb ? -1 : lena != lenb;
 25.3731 ++        }
 25.3732 ++
 25.3733 ++      if (ignore || translate)
 25.3734 ++        free (texta);
 25.3735 ++      else
 25.3736 ++        {
 25.3737 ++          texta[lena] = enda;
 25.3738 ++          textb[lenb] = endb;
 25.3739 ++        }
 25.3740 ++
 25.3741 ++      if (diff)
 25.3742 ++        goto not_equal;
 25.3743 ++
 25.3744 ++      key = key->next;
 25.3745 ++      if (! key)
 25.3746 ++        break;
 25.3747 ++
 25.3748 ++      /* Find the beginning and limit of the next field.  */
 25.3749 ++      if (key->eword != -1)
 25.3750 ++        lima = limfield (a, key), limb = limfield (b, key);
 25.3751 ++      else
 25.3752 ++        lima = a->text + a->length - 1, limb = b->text + b->length - 1;
 25.3753 ++
 25.3754 ++      if (key->sword != -1)
 25.3755 ++        texta = begfield (a, key), textb = begfield (b, key);
 25.3756 ++      else
 25.3757 ++        {
 25.3758 ++          texta = a->text, textb = b->text;
 25.3759 ++          if (key->skipsblanks)
 25.3760 ++            {
 25.3761 ++              while (texta < lima && ismbblank (texta, lima - texta, &mblength_a))
 25.3762 ++                texta += mblength_a;
 25.3763 ++              while (textb < limb && ismbblank (textb, limb - textb, &mblength_b))
 25.3764 ++                textb += mblength_b;
 25.3765 ++            }
 25.3766 ++        }
 25.3767 ++    }
 25.3768 ++
 25.3769 ++not_equal:
 25.3770 ++  if (key && key->reverse)
 25.3771 ++    return -diff;
 25.3772 ++  else
 25.3773 ++    return diff;
 25.3774 ++}
 25.3775 ++#endif
 25.3776 ++
 25.3777 + /* Compare two lines A and B, returning negative, zero, or positive
 25.3778 +    depending on whether A compares less than, equal to, or greater than B. */
 25.3779 + 
 25.3780 +@@ -2742,7 +3385,7 @@ compare (struct line const *a, struct li
 25.3781 +     diff = - NONZERO (blen);
 25.3782 +   else if (blen == 0)
 25.3783 +     diff = 1;
 25.3784 +-  else if (hard_LC_COLLATE)
 25.3785 ++  else if (hard_LC_COLLATE && !folding)
 25.3786 +     {
 25.3787 +       /* Note xmemcoll0 is a performance enhancement as
 25.3788 +          it will not unconditionally write '\0' after the
 25.3789 +@@ -4139,6 +4782,7 @@ set_ordering (char const *s, struct keyf
 25.3790 +           break;
 25.3791 +         case 'f':
 25.3792 +           key->translate = fold_toupper;
 25.3793 ++          folding = true;
 25.3794 +           break;
 25.3795 +         case 'g':
 25.3796 +           key->general_numeric = true;
 25.3797 +@@ -4218,7 +4862,7 @@ main (int argc, char **argv)
 25.3798 +   initialize_exit_failure (SORT_FAILURE);
 25.3799 + 
 25.3800 +   hard_LC_COLLATE = hard_locale (LC_COLLATE);
 25.3801 +-#if HAVE_NL_LANGINFO
 25.3802 ++#if HAVE_LANGINFO_CODESET
 25.3803 +   hard_LC_TIME = hard_locale (LC_TIME);
 25.3804 + #endif
 25.3805 + 
 25.3806 +@@ -4239,6 +4883,29 @@ main (int argc, char **argv)
 25.3807 +       thousands_sep = -1;
 25.3808 +   }
 25.3809 + 
 25.3810 ++#if HAVE_MBRTOWC
 25.3811 ++  if (MB_CUR_MAX > 1)
 25.3812 ++    {
 25.3813 ++      inittables = inittables_mb;
 25.3814 ++      begfield = begfield_mb;
 25.3815 ++      limfield = limfield_mb;
 25.3816 ++      skipblanks = skipblanks_mb;
 25.3817 ++      getmonth = getmonth_mb;
 25.3818 ++      keycompare = keycompare_mb;
 25.3819 ++      numcompare = numcompare_mb;
 25.3820 ++    }
 25.3821 ++  else
 25.3822 ++#endif
 25.3823 ++    {
 25.3824 ++      inittables = inittables_uni;
 25.3825 ++      begfield = begfield_uni;
 25.3826 ++      limfield = limfield_uni;
 25.3827 ++      skipblanks = skipblanks_uni;
 25.3828 ++      getmonth = getmonth_uni;
 25.3829 ++      keycompare = keycompare_uni;
 25.3830 ++      numcompare = numcompare_uni;
 25.3831 ++    }
 25.3832 ++
 25.3833 +   have_read_stdin = false;
 25.3834 +   inittables ();
 25.3835 + 
 25.3836 +@@ -4513,13 +5180,34 @@ main (int argc, char **argv)
 25.3837 + 
 25.3838 +         case 't':
 25.3839 +           {
 25.3840 +-            char newtab = optarg[0];
 25.3841 +-            if (! newtab)
 25.3842 ++            char newtab[MB_LEN_MAX + 1];
 25.3843 ++            size_t newtab_length = 1;
 25.3844 ++            strncpy (newtab, optarg, MB_LEN_MAX);
 25.3845 ++            if (! newtab[0])
 25.3846 +               die (SORT_FAILURE, 0, _("empty tab"));
 25.3847 +-            if (optarg[1])
 25.3848 ++#if HAVE_MBRTOWC
 25.3849 ++            if (MB_CUR_MAX > 1)
 25.3850 ++              {
 25.3851 ++                wchar_t wc;
 25.3852 ++                mbstate_t state;
 25.3853 ++
 25.3854 ++                memset (&state, '\0', sizeof (mbstate_t));
 25.3855 ++                newtab_length = mbrtowc (&wc, newtab, strnlen (newtab,
 25.3856 ++                                                               MB_LEN_MAX),
 25.3857 ++                                         &state);
 25.3858 ++                switch (newtab_length)
 25.3859 ++                  {
 25.3860 ++                  case (size_t) -1:
 25.3861 ++                  case (size_t) -2:
 25.3862 ++                  case 0:
 25.3863 ++                    newtab_length = 1;
 25.3864 ++                  }
 25.3865 ++              }
 25.3866 ++#endif
 25.3867 ++            if (newtab_length == 1 && optarg[1])
 25.3868 +               {
 25.3869 +                 if (STREQ (optarg, "\\0"))
 25.3870 +-                  newtab = '\0';
 25.3871 ++                  newtab[0] = '\0';
 25.3872 +                 else
 25.3873 +                   {
 25.3874 +                     /* Provoke with 'sort -txx'.  Complain about
 25.3875 +@@ -4530,9 +5218,11 @@ main (int argc, char **argv)
 25.3876 +                          quote (optarg));
 25.3877 +                   }
 25.3878 +               }
 25.3879 +-            if (tab != TAB_DEFAULT && tab != newtab)
 25.3880 ++            if (tab_length && (tab_length != newtab_length
 25.3881 ++                        || memcmp (tab, newtab, tab_length) != 0))
 25.3882 +               die (SORT_FAILURE, 0, _("incompatible tabs"));
 25.3883 +-            tab = newtab;
 25.3884 ++            memcpy (tab, newtab, newtab_length);
 25.3885 ++            tab_length = newtab_length;
 25.3886 +           }
 25.3887 +           break;
 25.3888 + 
 25.3889 +@@ -4770,12 +5460,10 @@ main (int argc, char **argv)
 25.3890 +       sort (files, nfiles, outfile, nthreads);
 25.3891 +     }
 25.3892 + 
 25.3893 +-#ifdef lint
 25.3894 +   if (files_from)
 25.3895 +     readtokens0_free (&tok);
 25.3896 +   else
 25.3897 +     free (files);
 25.3898 +-#endif
 25.3899 + 
 25.3900 +   if (have_read_stdin && fclose (stdin) == EOF)
 25.3901 +     sort_die (_("close failed"), "-");
 25.3902 +diff -Naurp coreutils-8.27-orig/src/unexpand.c coreutils-8.27/src/unexpand.c
 25.3903 +--- coreutils-8.27-orig/src/unexpand.c	2017-01-01 16:34:24.000000000 -0600
 25.3904 ++++ coreutils-8.27/src/unexpand.c	2017-03-11 23:49:06.758133530 -0600
 25.3905 +@@ -38,6 +38,9 @@
 25.3906 + #include <stdio.h>
 25.3907 + #include <getopt.h>
 25.3908 + #include <sys/types.h>
 25.3909 ++
 25.3910 ++#include <mbfile.h>
 25.3911 ++
 25.3912 + #include "system.h"
 25.3913 + #include "die.h"
 25.3914 + #include "xstrndup.h"
 25.3915 +@@ -107,24 +110,47 @@ unexpand (void)
 25.3916 + {
 25.3917 +   /* Input stream.  */
 25.3918 +   FILE *fp = next_file (NULL);
 25.3919 ++  mb_file_t mbf;
 25.3920 + 
 25.3921 +   /* The array of pending blanks.  In non-POSIX locales, blanks can
 25.3922 +      include characters other than spaces, so the blanks must be
 25.3923 +      stored, not merely counted.  */
 25.3924 +-  char *pending_blank;
 25.3925 ++  mbf_char_t *pending_blank;
 25.3926 ++  /* True if the starting locale is utf8.  */
 25.3927 ++  bool using_utf_locale;
 25.3928 ++
 25.3929 ++  /* True if the first file contains BOM header.  */
 25.3930 ++  bool found_bom;
 25.3931 ++  using_utf_locale=check_utf_locale();
 25.3932 + 
 25.3933 +   if (!fp)
 25.3934 +     return;
 25.3935 ++  mbf_init (mbf, fp);
 25.3936 ++  found_bom=check_bom(fp,&mbf);
 25.3937 + 
 25.3938 ++  if (using_utf_locale == false && found_bom == true)
 25.3939 ++  {
 25.3940 ++    /*try using some predefined locale */
 25.3941 ++
 25.3942 ++    if (set_utf_locale () != 0)
 25.3943 ++    {
 25.3944 ++      error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
 25.3945 ++    }
 25.3946 ++  }
 25.3947 +   /* The worst case is a non-blank character, then one blank, then a
 25.3948 +      tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so
 25.3949 +      allocate MAX_COLUMN_WIDTH bytes to store the blanks.  */
 25.3950 +-  pending_blank = xmalloc (max_column_width);
 25.3951 ++  pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t));
 25.3952 ++
 25.3953 ++  if (found_bom == true)
 25.3954 ++  {
 25.3955 ++    print_bom();
 25.3956 ++  }
 25.3957 + 
 25.3958 +   while (true)
 25.3959 +     {
 25.3960 +       /* Input character, or EOF.  */
 25.3961 +-      int c;
 25.3962 ++      mbf_char_t c;
 25.3963 + 
 25.3964 +       /* If true, perform translations.  */
 25.3965 +       bool convert = true;
 25.3966 +@@ -158,12 +184,44 @@ unexpand (void)
 25.3967 + 
 25.3968 +       do
 25.3969 +         {
 25.3970 +-          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
 25.3971 +-            continue;
 25.3972 ++          while (true) {
 25.3973 ++            mbf_getc (c, mbf);
 25.3974 ++            if ((mb_iseof (c)) && (fp = next_file (fp)))
 25.3975 ++              {
 25.3976 ++                mbf_init (mbf, fp);
 25.3977 ++                if (fp!=NULL)
 25.3978 ++                {
 25.3979 ++                  if (check_bom(fp,&mbf)==true)
 25.3980 ++                  {
 25.3981 ++                    /*Not the first file - check BOM header*/
 25.3982 ++                    if (using_utf_locale==false && found_bom==false)
 25.3983 ++                    {
 25.3984 ++                      /*BOM header in subsequent file but not in the first one. */
 25.3985 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 25.3986 ++                    }
 25.3987 ++                  }
 25.3988 ++                  else
 25.3989 ++                  {
 25.3990 ++                    if(using_utf_locale==false && found_bom==true)
 25.3991 ++                    {
 25.3992 ++                      /*First file conatined BOM header - locale was switched to UTF
 25.3993 ++                      /*all subsequent files should contain BOM. */
 25.3994 ++                      error (EXIT_FAILURE, errno, _("combination of files with and without BOM header"));
 25.3995 ++                    }
 25.3996 ++                  }
 25.3997 ++                }
 25.3998 ++                continue;
 25.3999 ++              }
 25.4000 ++            else
 25.4001 ++              {
 25.4002 ++                break;
 25.4003 ++              }
 25.4004 ++            }
 25.4005 ++
 25.4006 + 
 25.4007 +           if (convert)
 25.4008 +             {
 25.4009 +-              bool blank = !! isblank (c);
 25.4010 ++              bool blank = mb_isblank (c);
 25.4011 + 
 25.4012 +               if (blank)
 25.4013 +                 {
 25.4014 +@@ -180,16 +238,16 @@ unexpand (void)
 25.4015 +                       if (next_tab_column < column)
 25.4016 +                         die (EXIT_FAILURE, 0, _("input line is too long"));
 25.4017 + 
 25.4018 +-                      if (c == '\t')
 25.4019 ++                      if (mb_iseq (c, '\t'))
 25.4020 +                         {
 25.4021 +                           column = next_tab_column;
 25.4022 + 
 25.4023 +                           if (pending)
 25.4024 +-                            pending_blank[0] = '\t';
 25.4025 ++                            mb_setascii (&pending_blank[0], '\t');
 25.4026 +                         }
 25.4027 +                       else
 25.4028 +                         {
 25.4029 +-                          column++;
 25.4030 ++                          column += mb_width (c);
 25.4031 + 
 25.4032 +                           if (! (prev_blank && column == next_tab_column))
 25.4033 +                             {
 25.4034 +@@ -197,13 +255,14 @@ unexpand (void)
 25.4035 +                                  will be replaced by tabs.  */
 25.4036 +                               if (column == next_tab_column)
 25.4037 +                                 one_blank_before_tab_stop = true;
 25.4038 +-                              pending_blank[pending++] = c;
 25.4039 ++                              mb_copy (&pending_blank[pending++], &c);
 25.4040 +                               prev_blank = true;
 25.4041 +                               continue;
 25.4042 +                             }
 25.4043 + 
 25.4044 +                           /* Replace the pending blanks by a tab or two.  */
 25.4045 +-                          pending_blank[0] = c = '\t';
 25.4046 ++                          mb_setascii (&c, '\t');
 25.4047 ++                          mb_setascii (&pending_blank[0], '\t');
 25.4048 +                         }
 25.4049 + 
 25.4050 +                       /* Discard pending blanks, unless it was a single
 25.4051 +@@ -211,7 +270,7 @@ unexpand (void)
 25.4052 +                       pending = one_blank_before_tab_stop;
 25.4053 +                     }
 25.4054 +                 }
 25.4055 +-              else if (c == '\b')
 25.4056 ++              else if (mb_iseq (c, '\b'))
 25.4057 +                 {
 25.4058 +                   /* Go back one column, and force recalculation of the
 25.4059 +                      next tab stop.  */
 25.4060 +@@ -219,9 +278,9 @@ unexpand (void)
 25.4061 +                   next_tab_column = column;
 25.4062 +                   tab_index -= !!tab_index;
 25.4063 +                 }
 25.4064 +-              else
 25.4065 ++              else if (!mb_iseq (c, '\n'))
 25.4066 +                 {
 25.4067 +-                  column++;
 25.4068 ++                  column += mb_width (c);
 25.4069 +                   if (!column)
 25.4070 +                     die (EXIT_FAILURE, 0, _("input line is too long"));
 25.4071 +                 }
 25.4072 +@@ -229,8 +288,11 @@ unexpand (void)
 25.4073 +               if (pending)
 25.4074 +                 {
 25.4075 +                   if (pending > 1 && one_blank_before_tab_stop)
 25.4076 +-                    pending_blank[0] = '\t';
 25.4077 +-                  if (fwrite (pending_blank, 1, pending, stdout) != pending)
 25.4078 ++                    mb_setascii (&pending_blank[0], '\t');
 25.4079 ++
 25.4080 ++                  for (int n = 0; n < pending; ++n)
 25.4081 ++                    mb_putc (pending_blank[n], stdout);
 25.4082 ++                  if (ferror (stdout))
 25.4083 +                     die (EXIT_FAILURE, errno, _("write error"));
 25.4084 +                   pending = 0;
 25.4085 +                   one_blank_before_tab_stop = false;
 25.4086 +@@ -240,16 +302,17 @@ unexpand (void)
 25.4087 +               convert &= convert_entire_line || blank;
 25.4088 +             }
 25.4089 + 
 25.4090 +-          if (c < 0)
 25.4091 ++          if (mb_iseof (c))
 25.4092 +             {
 25.4093 +               free (pending_blank);
 25.4094 +               return;
 25.4095 +             }
 25.4096 + 
 25.4097 +-          if (putchar (c) < 0)
 25.4098 ++          mb_putc (c, stdout);
 25.4099 ++          if (ferror (stdout))
 25.4100 +             die (EXIT_FAILURE, errno, _("write error"));
 25.4101 +         }
 25.4102 +-      while (c != '\n');
 25.4103 ++      while (!mb_iseq (c, '\n'));
 25.4104 +     }
 25.4105 + }
 25.4106 + 
 25.4107 +diff -Naurp coreutils-8.27-orig/src/uniq.c coreutils-8.27/src/uniq.c
 25.4108 +--- coreutils-8.27-orig/src/uniq.c	2017-01-01 16:34:24.000000000 -0600
 25.4109 ++++ coreutils-8.27/src/uniq.c	2017-03-11 23:47:13.098285938 -0600
 25.4110 +@@ -21,6 +21,17 @@
 25.4111 + #include <getopt.h>
 25.4112 + #include <sys/types.h>
 25.4113 + 
 25.4114 ++/* Get mbstate_t, mbrtowc(). */
 25.4115 ++#if HAVE_WCHAR_H
 25.4116 ++# include <wchar.h>
 25.4117 ++#endif
 25.4118 ++
 25.4119 ++/* Get isw* functions. */
 25.4120 ++#if HAVE_WCTYPE_H
 25.4121 ++# include <wctype.h>
 25.4122 ++#endif
 25.4123 ++#include <assert.h>
 25.4124 ++
 25.4125 + #include "system.h"
 25.4126 + #include "argmatch.h"
 25.4127 + #include "linebuffer.h"
 25.4128 +@@ -32,9 +43,21 @@
 25.4129 + #include "stdio--.h"
 25.4130 + #include "xmemcoll.h"
 25.4131 + #include "xstrtol.h"
 25.4132 +-#include "memcasecmp.h"
 25.4133 ++#include "xmemcoll.h"
 25.4134 + #include "quote.h"
 25.4135 + 
 25.4136 ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
 25.4137 ++   installation; work around this configuration error.  */
 25.4138 ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2
 25.4139 ++# define MB_LEN_MAX 16
 25.4140 ++#endif
 25.4141 ++
 25.4142 ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
 25.4143 ++#if HAVE_MBRTOWC && defined mbstate_t
 25.4144 ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
 25.4145 ++#endif
 25.4146 ++
 25.4147 ++
 25.4148 + /* The official name of this program (e.g., no 'g' prefix).  */
 25.4149 + #define PROGRAM_NAME "uniq"
 25.4150 + 
 25.4151 +@@ -144,6 +167,10 @@ enum
 25.4152 +   GROUP_OPTION = CHAR_MAX + 1
 25.4153 + };
 25.4154 + 
 25.4155 ++/* Function pointers. */
 25.4156 ++static char *
 25.4157 ++(*find_field) (struct linebuffer *line);
 25.4158 ++
 25.4159 + static struct option const longopts[] =
 25.4160 + {
 25.4161 +   {"count", no_argument, NULL, 'c'},
 25.4162 +@@ -260,7 +287,7 @@ size_opt (char const *opt, char const *m
 25.4163 +    return a pointer to the beginning of the line's field to be compared. */
 25.4164 + 
 25.4165 + static char * _GL_ATTRIBUTE_PURE
 25.4166 +-find_field (struct linebuffer const *line)
 25.4167 ++find_field_uni (struct linebuffer *line)
 25.4168 + {
 25.4169 +   size_t count;
 25.4170 +   char const *lp = line->buffer;
 25.4171 +@@ -280,6 +307,83 @@ find_field (struct linebuffer const *lin
 25.4172 +   return line->buffer + i;
 25.4173 + }
 25.4174 + 
 25.4175 ++#if HAVE_MBRTOWC
 25.4176 ++
 25.4177 ++# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL)  \
 25.4178 ++  do                                                                        \
 25.4179 ++    {                                                                        \
 25.4180 ++      mbstate_t state_bak;                                                \
 25.4181 ++                                                                        \
 25.4182 ++      CONVFAIL = 0;                                                        \
 25.4183 ++      state_bak = *STATEP;                                                \
 25.4184 ++                                                                        \
 25.4185 ++      MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP);                \
 25.4186 ++                                                                        \
 25.4187 ++      switch (MBLENGTH)                                                        \
 25.4188 ++        {                                                                \
 25.4189 ++        case (size_t)-2:                                                \
 25.4190 ++        case (size_t)-1:                                                \
 25.4191 ++          *STATEP = state_bak;                                                \
 25.4192 ++          CONVFAIL++;                                                        \
 25.4193 ++          /* Fall through */                                                \
 25.4194 ++        case 0:                                                                \
 25.4195 ++          MBLENGTH = 1;                                                        \
 25.4196 ++        }                                                                \
 25.4197 ++    }                                                                        \
 25.4198 ++  while (0)
 25.4199 ++
 25.4200 ++static char *
 25.4201 ++find_field_multi (struct linebuffer *line)
 25.4202 ++{
 25.4203 ++  size_t count;
 25.4204 ++  char *lp = line->buffer;
 25.4205 ++  size_t size = line->length - 1;
 25.4206 ++  size_t pos;
 25.4207 ++  size_t mblength;
 25.4208 ++  wchar_t wc;
 25.4209 ++  mbstate_t *statep;
 25.4210 ++  int convfail = 0;
 25.4211 ++
 25.4212 ++  pos = 0;
 25.4213 ++  statep = &(line->state);
 25.4214 ++
 25.4215 ++  /* skip fields. */
 25.4216 ++  for (count = 0; count < skip_fields && pos < size; count++)
 25.4217 ++    {
 25.4218 ++      while (pos < size)
 25.4219 ++        {
 25.4220 ++          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 25.4221 ++
 25.4222 ++          if (convfail || !(iswblank (wc) || wc == '\n'))
 25.4223 ++            {
 25.4224 ++              pos += mblength;
 25.4225 ++              break;
 25.4226 ++            }
 25.4227 ++          pos += mblength;
 25.4228 ++        }
 25.4229 ++
 25.4230 ++      while (pos < size)
 25.4231 ++        {
 25.4232 ++          MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 25.4233 ++
 25.4234 ++          if (!convfail && (iswblank (wc) || wc == '\n'))
 25.4235 ++            break;
 25.4236 ++
 25.4237 ++          pos += mblength;
 25.4238 ++        }
 25.4239 ++    }
 25.4240 ++
 25.4241 ++  /* skip fields. */
 25.4242 ++  for (count = 0; count < skip_chars && pos < size; count++)
 25.4243 ++    {
 25.4244 ++      MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
 25.4245 ++      pos += mblength;
 25.4246 ++    }
 25.4247 ++
 25.4248 ++  return lp + pos;
 25.4249 ++}
 25.4250 ++#endif
 25.4251 ++
 25.4252 + /* Return false if two strings OLD and NEW match, true if not.
 25.4253 +    OLD and NEW point not to the beginnings of the lines
 25.4254 +    but rather to the beginnings of the fields to compare.
 25.4255 +@@ -288,6 +392,8 @@ find_field (struct linebuffer const *lin
 25.4256 + static bool
 25.4257 + different (char *old, char *new, size_t oldlen, size_t newlen)
 25.4258 + {
 25.4259 ++  char *copy_old, *copy_new;
 25.4260 ++
 25.4261 +   if (check_chars < oldlen)
 25.4262 +     oldlen = check_chars;
 25.4263 +   if (check_chars < newlen)
 25.4264 +@@ -295,14 +401,103 @@ different (char *old, char *new, size_t
 25.4265 + 
 25.4266 +   if (ignore_case)
 25.4267 +     {
 25.4268 +-      /* FIXME: This should invoke strcoll somehow.  */
 25.4269 +-      return oldlen != newlen || memcasecmp (old, new, oldlen);
 25.4270 ++      size_t i;
 25.4271 ++
 25.4272 ++      copy_old = xmalloc (oldlen + 1);
 25.4273 ++      copy_new = xmalloc (oldlen + 1);
 25.4274 ++
 25.4275 ++      for (i = 0; i < oldlen; i++)
 25.4276 ++        {
 25.4277 ++          copy_old[i] = toupper (old[i]);
 25.4278 ++          copy_new[i] = toupper (new[i]);
 25.4279 ++        }
 25.4280 ++      bool rc = xmemcoll (copy_old, oldlen, copy_new, newlen);
 25.4281 ++      free (copy_old);
 25.4282 ++      free (copy_new);
 25.4283 ++      return rc;
 25.4284 +     }
 25.4285 +-  else if (hard_LC_COLLATE)
 25.4286 +-    return xmemcoll (old, oldlen, new, newlen) != 0;
 25.4287 +   else
 25.4288 +-    return oldlen != newlen || memcmp (old, new, oldlen);
 25.4289 ++    {
 25.4290 ++      copy_old = (char *)old;
 25.4291 ++      copy_new = (char *)new;
 25.4292 ++    }
 25.4293 ++
 25.4294 ++  return xmemcoll (copy_old, oldlen, copy_new, newlen);
 25.4295 ++
 25.4296 ++}
 25.4297 ++
 25.4298 ++#if HAVE_MBRTOWC
 25.4299 ++static int
 25.4300 ++different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate)
 25.4301 ++{
 25.4302 ++  size_t i, j, chars;
 25.4303 ++  const char *str[2];
 25.4304 ++  char *copy[2];
 25.4305 ++  size_t len[2];
 25.4306 ++  mbstate_t state[2];
 25.4307 ++  size_t mblength;
 25.4308 ++  wchar_t wc, uwc;
 25.4309 ++  mbstate_t state_bak;
 25.4310 ++
 25.4311 ++  str[0] = old;
 25.4312 ++  str[1] = new;
 25.4313 ++  len[0] = oldlen;
 25.4314 ++  len[1] = newlen;
 25.4315 ++  state[0] = oldstate;
 25.4316 ++  state[1] = newstate;
 25.4317 ++
 25.4318 ++  for (i = 0; i < 2; i++)
 25.4319 ++    {
 25.4320 ++      copy[i] = xmalloc (len[i] + 1);
 25.4321 ++      memset (copy[i], '\0', len[i] + 1);
 25.4322 ++
 25.4323 ++      for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++)
 25.4324 ++        {
 25.4325 ++          state_bak = state[i];
 25.4326 ++          mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i]));
 25.4327 ++
 25.4328 ++          switch (mblength)
 25.4329 ++            {
 25.4330 ++            case (size_t)-1:
 25.4331 ++            case (size_t)-2:
 25.4332 ++              state[i] = state_bak;
 25.4333 ++              /* Fall through */
 25.4334 ++            case 0:
 25.4335 ++              mblength = 1;
 25.4336 ++              break;
 25.4337 ++
 25.4338 ++            default:
 25.4339 ++              if (ignore_case)
 25.4340 ++                {
 25.4341 ++                  uwc = towupper (wc);
 25.4342 ++
 25.4343 ++                  if (uwc != wc)
 25.4344 ++                    {
 25.4345 ++                      mbstate_t state_wc;
 25.4346 ++                      size_t mblen;
 25.4347 ++
 25.4348 ++                      memset (&state_wc, '\0', sizeof(mbstate_t));
 25.4349 ++                      mblen = wcrtomb (copy[i] + j, uwc, &state_wc);
 25.4350 ++                      assert (mblen != (size_t)-1);
 25.4351 ++                    }
 25.4352 ++                  else
 25.4353 ++                    memcpy (copy[i] + j, str[i] + j, mblength);
 25.4354 ++                }
 25.4355 ++              else
 25.4356 ++                memcpy (copy[i] + j, str[i] + j, mblength);
 25.4357 ++            }
 25.4358 ++          j += mblength;
 25.4359 ++        }
 25.4360 ++      copy[i][j] = '\0';
 25.4361 ++      len[i] = j;
 25.4362 ++    }
 25.4363 ++  int rc = xmemcoll (copy[0], len[0], copy[1], len[1]);
 25.4364 ++  free (copy[0]);
 25.4365 ++  free (copy[1]);
 25.4366 ++  return rc;
 25.4367 ++
 25.4368 + }
 25.4369 ++#endif
 25.4370 + 
 25.4371 + /* Output the line in linebuffer LINE to standard output
 25.4372 +    provided that the switches say it should be output.
 25.4373 +@@ -367,19 +562,38 @@ check_file (const char *infile, const ch
 25.4374 +       char *prevfield IF_LINT ( = NULL);
 25.4375 +       size_t prevlen IF_LINT ( = 0);
 25.4376 +       bool first_group_printed = false;
 25.4377 ++#if HAVE_MBRTOWC
 25.4378 ++      mbstate_t prevstate;
 25.4379 ++
 25.4380 ++      memset (&prevstate, '\0', sizeof (mbstate_t));
 25.4381 ++#endif
 25.4382 + 
 25.4383 +       while (!feof (stdin))
 25.4384 +         {
 25.4385 +           char *thisfield;
 25.4386 +           size_t thislen;
 25.4387 +           bool new_group;
 25.4388 ++#if HAVE_MBRTOWC
 25.4389 ++          mbstate_t thisstate;
 25.4390 ++#endif
 25.4391 + 
 25.4392 +           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 25.4393 +             break;
 25.4394 + 
 25.4395 +           thisfield = find_field (thisline);
 25.4396 +           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 25.4397 ++#if HAVE_MBRTOWC
 25.4398 ++          if (MB_CUR_MAX > 1)
 25.4399 ++            {
 25.4400 ++              thisstate = thisline->state;
 25.4401 + 
 25.4402 ++              new_group = (prevline->length == 0
 25.4403 ++                           || different_multi (thisfield, prevfield,
 25.4404 ++                                               thislen, prevlen,
 25.4405 ++                                               thisstate, prevstate));
 25.4406 ++            }
 25.4407 ++          else
 25.4408 ++#endif
 25.4409 +           new_group = (prevline->length == 0
 25.4410 +                        || different (thisfield, prevfield, thislen, prevlen));
 25.4411 + 
 25.4412 +@@ -397,6 +611,10 @@ check_file (const char *infile, const ch
 25.4413 +               SWAP_LINES (prevline, thisline);
 25.4414 +               prevfield = thisfield;
 25.4415 +               prevlen = thislen;
 25.4416 ++#if HAVE_MBRTOWC
 25.4417 ++              if (MB_CUR_MAX > 1)
 25.4418 ++                prevstate = thisstate;
 25.4419 ++#endif
 25.4420 +               first_group_printed = true;
 25.4421 +             }
 25.4422 +         }
 25.4423 +@@ -409,17 +627,26 @@ check_file (const char *infile, const ch
 25.4424 +       size_t prevlen;
 25.4425 +       uintmax_t match_count = 0;
 25.4426 +       bool first_delimiter = true;
 25.4427 ++#if HAVE_MBRTOWC
 25.4428 ++      mbstate_t prevstate;
 25.4429 ++#endif
 25.4430 + 
 25.4431 +       if (readlinebuffer_delim (prevline, stdin, delimiter) == 0)
 25.4432 +         goto closefiles;
 25.4433 +       prevfield = find_field (prevline);
 25.4434 +       prevlen = prevline->length - 1 - (prevfield - prevline->buffer);
 25.4435 ++#if HAVE_MBRTOWC
 25.4436 ++      prevstate = prevline->state;
 25.4437 ++#endif
 25.4438 + 
 25.4439 +       while (!feof (stdin))
 25.4440 +         {
 25.4441 +           bool match;
 25.4442 +           char *thisfield;
 25.4443 +           size_t thislen;
 25.4444 ++#if HAVE_MBRTOWC
 25.4445 ++          mbstate_t thisstate = thisline->state;
 25.4446 ++#endif
 25.4447 +           if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
 25.4448 +             {
 25.4449 +               if (ferror (stdin))
 25.4450 +@@ -428,6 +655,14 @@ check_file (const char *infile, const ch
 25.4451 +             }
 25.4452 +           thisfield = find_field (thisline);
 25.4453 +           thislen = thisline->length - 1 - (thisfield - thisline->buffer);
 25.4454 ++#if HAVE_MBRTOWC
 25.4455 ++          if (MB_CUR_MAX > 1)
 25.4456 ++            {
 25.4457 ++              match = !different_multi (thisfield, prevfield,
 25.4458 ++                                thislen, prevlen, thisstate, prevstate);
 25.4459 ++            }
 25.4460 ++          else
 25.4461 ++#endif
 25.4462 +           match = !different (thisfield, prevfield, thislen, prevlen);
 25.4463 +           match_count += match;
 25.4464 + 
 25.4465 +@@ -460,6 +695,9 @@ check_file (const char *infile, const ch
 25.4466 +               SWAP_LINES (prevline, thisline);
 25.4467 +               prevfield = thisfield;
 25.4468 +               prevlen = thislen;
 25.4469 ++#if HAVE_MBRTOWC
 25.4470 ++              prevstate = thisstate;
 25.4471 ++#endif
 25.4472 +               if (!match)
 25.4473 +                 match_count = 0;
 25.4474 +             }
 25.4475 +@@ -506,6 +744,19 @@ main (int argc, char **argv)
 25.4476 + 
 25.4477 +   atexit (close_stdout);
 25.4478 + 
 25.4479 ++#if HAVE_MBRTOWC
 25.4480 ++  if (MB_CUR_MAX > 1)
 25.4481 ++    {
 25.4482 ++      find_field = find_field_multi;
 25.4483 ++    }
 25.4484 ++  else
 25.4485 ++#endif
 25.4486 ++    {
 25.4487 ++      find_field = find_field_uni;
 25.4488 ++    }
 25.4489 ++
 25.4490 ++
 25.4491 ++
 25.4492 +   skip_chars = 0;
 25.4493 +   skip_fields = 0;
 25.4494 +   check_chars = SIZE_MAX;
 25.4495 +diff -Naurp coreutils-8.27-orig/tests/expand/mb.sh coreutils-8.27/tests/expand/mb.sh
 25.4496 +--- coreutils-8.27-orig/tests/expand/mb.sh	1969-12-31 18:00:00.000000000 -0600
 25.4497 ++++ coreutils-8.27/tests/expand/mb.sh	2017-03-11 23:49:06.759133489 -0600
 25.4498 +@@ -0,0 +1,183 @@
 25.4499 ++#!/bin/sh
 25.4500 ++
 25.4501 ++# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 25.4502 ++
 25.4503 ++# This program is free software: you can redistribute it and/or modify
 25.4504 ++# it under the terms of the GNU General Public License as published by
 25.4505 ++# the Free Software Foundation, either version 3 of the License, or
 25.4506 ++# (at your option) any later version.
 25.4507 ++
 25.4508 ++# This program is distributed in the hope that it will be useful,
 25.4509 ++# but WITHOUT ANY WARRANTY; without even the implied warranty of
 25.4510 ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 25.4511 ++# GNU General Public License for more details.
 25.4512 ++
 25.4513 ++# You should have received a copy of the GNU General Public License
 25.4514 ++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 25.4515 ++
 25.4516 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 25.4517 ++print_ver_ expand
 25.4518 ++
 25.4519 ++export LC_ALL=en_US.UTF-8
 25.4520 ++
 25.4521 ++#input containing multibyte characters
 25.4522 ++cat <<\EOF > in || framework_failure_
 25.4523 ++1234567812345678123456781
 25.4524 ++.       .       .       .
 25.4525 ++a	b	c	d
 25.4526 ++.       .       .       .
 25.4527 ++ä	ö	ü	ß
 25.4528 ++.       .       .       .
 25.4529 ++EOF
 25.4530 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 25.4531 ++
 25.4532 ++cat <<\EOF > exp || framework_failure_
 25.4533 ++1234567812345678123456781
 25.4534 ++.       .       .       .
 25.4535 ++a       b       c       d
 25.4536 ++.       .       .       .
 25.4537 ++ä       ö       ü       ß
 25.4538 ++.       .       .       .
 25.4539 ++   äöü  .    öüä.       ä xx
 25.4540 ++EOF
 25.4541 ++
 25.4542 ++expand < in > out || fail=1
 25.4543 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4544 ++
 25.4545 ++#multiple files as an input
 25.4546 ++cat <<\EOF >> exp || framework_failure_
 25.4547 ++1234567812345678123456781
 25.4548 ++.       .       .       .
 25.4549 ++a       b       c       d
 25.4550 ++.       .       .       .
 25.4551 ++ä       ö       ü       ß
 25.4552 ++.       .       .       .
 25.4553 ++   äöü  .    öüä.       ä xx
 25.4554 ++EOF
 25.4555 ++
 25.4556 ++expand ./in ./in > out || fail=1
 25.4557 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4558 ++
 25.4559 ++#test characters with display widths != 1
 25.4560 ++env printf '12345678
 25.4561 ++e\t|ascii(1)
 25.4562 ++\u00E9\t|composed(1)
 25.4563 ++e\u0301\t|decomposed(1)
 25.4564 ++\u3000\t|ideo-space(2)
 25.4565 ++\uFF0D\t|full-hypen(2)
 25.4566 ++' > in || framework_failure_
 25.4567 ++
 25.4568 ++env printf '12345678
 25.4569 ++e       |ascii(1)
 25.4570 ++\u00E9       |composed(1)
 25.4571 ++e\u0301       |decomposed(1)
 25.4572 ++\u3000      |ideo-space(2)
 25.4573 ++\uFF0D      |full-hypen(2)
 25.4574 ++' > exp || framework_failure_
 25.4575 ++
 25.4576 ++expand < in > out || fail=1
 25.4577 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4578 ++
 25.4579 ++#shouldn't fail with "input line too long"
 25.4580 ++#when a line starts with a control character
 25.4581 ++env printf '\n' > in || framework_failure_
 25.4582 ++
 25.4583 ++expand < in > out || fail=1
 25.4584 ++compare in out > /dev/null 2>&1 || fail=1
 25.4585 ++
 25.4586 ++#non-Unicode characters interspersed between Unicode ones
 25.4587 ++env printf '12345678
 25.4588 ++\t\xFF|
 25.4589 ++\xFF\t|
 25.4590 ++\t\xFFä|
 25.4591 ++ä\xFF\t|
 25.4592 ++\tä\xFF|
 25.4593 ++\xFF\tä|
 25.4594 ++äbcdef\xFF\t|
 25.4595 ++' > in || framework_failure_
 25.4596 ++
 25.4597 ++env printf '12345678
 25.4598 ++        \xFF|
 25.4599 ++\xFF       |
 25.4600 ++        \xFFä|
 25.4601 ++ä\xFF      |
 25.4602 ++        ä\xFF|
 25.4603 ++\xFF       ä|
 25.4604 ++äbcdef\xFF |
 25.4605 ++' > exp || framework_failure_
 25.4606 ++
 25.4607 ++expand < in > out || fail=1
 25.4608 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4609 ++
 25.4610 ++
 25.4611 ++
 25.4612 ++#BOM header test 1
 25.4613 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_
 25.4614 ++1234567812345678123456781
 25.4615 ++.       .       .       .
 25.4616 ++a	b	c	d
 25.4617 ++.       .       .       .
 25.4618 ++ä	ö	ü	ß
 25.4619 ++.       .       .       .
 25.4620 ++EOF
 25.4621 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 25.4622 ++
 25.4623 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 25.4624 ++1234567812345678123456781
 25.4625 ++.       .       .       .
 25.4626 ++a       b       c       d
 25.4627 ++.       .       .       .
 25.4628 ++ä       ö       ü       ß
 25.4629 ++.       .       .       .
 25.4630 ++   äöü  .    öüä.       ä xx
 25.4631 ++EOF
 25.4632 ++
 25.4633 ++
 25.4634 ++expand < in > out || fail=1
 25.4635 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4636 ++
 25.4637 ++LANG=C expand < in > out || fail=1
 25.4638 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4639 ++
 25.4640 ++LC_ALL=C expand < in > out || fail=1
 25.4641 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4642 ++
 25.4643 ++
 25.4644 ++printf '\xEF\xBB\xBF' > in1; cat <<\EOF >> in1 || framework_failure_
 25.4645 ++1234567812345678123456781
 25.4646 ++.       .       .       .
 25.4647 ++a	b	c	d
 25.4648 ++.       .       .       .
 25.4649 ++ä	ö	ü	ß
 25.4650 ++.       .       .       .
 25.4651 ++EOF
 25.4652 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in1 || framework_failure_
 25.4653 ++
 25.4654 ++
 25.4655 ++printf '\xEF\xBB\xBF' > exp; cat <<\EOF >> exp || framework_failure_
 25.4656 ++1234567812345678123456781
 25.4657 ++.       .       .       .
 25.4658 ++a       b       c       d
 25.4659 ++.       .       .       .
 25.4660 ++ä       ö       ü       ß
 25.4661 ++.       .       .       .
 25.4662 ++   äöü  .    öüä.       ä xx
 25.4663 ++1234567812345678123456781
 25.4664 ++.       .       .       .
 25.4665 ++a       b       c       d
 25.4666 ++.       .       .       .
 25.4667 ++ä       ö       ü       ß
 25.4668 ++.       .       .       .
 25.4669 ++   äöü  .    öüä.       ä xx
 25.4670 ++EOF
 25.4671 ++
 25.4672 ++expand in1 in1 > out || fail=1
 25.4673 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4674 ++
 25.4675 ++LANG=C expand in1 in1  > out || fail=1
 25.4676 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4677 ++
 25.4678 ++LC_ALL=C expand in1 in1 > out || fail=1
 25.4679 ++compare exp out > /dev/null 2>&1 || fail=1
 25.4680 ++
 25.4681 ++exit $fail
 25.4682 +diff -Naurp coreutils-8.27-orig/tests/i18n/sort.sh coreutils-8.27/tests/i18n/sort.sh
 25.4683 +--- coreutils-8.27-orig/tests/i18n/sort.sh	1969-12-31 18:00:00.000000000 -0600
 25.4684 ++++ coreutils-8.27/tests/i18n/sort.sh	2017-03-11 23:47:13.100285838 -0600
 25.4685 +@@ -0,0 +1,29 @@
 25.4686 ++#!/bin/sh
 25.4687 ++# Verify sort's multi-byte support.
 25.4688 ++
 25.4689 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 25.4690 ++print_ver_ sort
 25.4691 ++
 25.4692 ++export LC_ALL=en_US.UTF-8
 25.4693 ++locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 25.4694 ++  || skip_ "No UTF-8 locale available"
 25.4695 ++
 25.4696 ++# Enable heap consistency checkng on older systems
 25.4697 ++export MALLOC_CHECK_=2
 25.4698 ++
 25.4699 ++
 25.4700 ++# check buffer overflow issue due to
 25.4701 ++# expanding multi-byte representation due to case conversion
 25.4702 ++# https://bugzilla.suse.com/show_bug.cgi?id=928749
 25.4703 ++cat <<EOF > exp
 25.4704 ++.
 25.4705 ++ɑ
 25.4706 ++EOF
 25.4707 ++cat <<EOF | sort -f > out || fail=1
 25.4708 ++.
 25.4709 ++ɑ
 25.4710 ++EOF
 25.4711 ++compare exp out || { fail=1; cat out; }
 25.4712 ++
 25.4713 ++
 25.4714 ++Exit $fail
 25.4715 +diff -Naurp coreutils-8.27-orig/tests/local.mk coreutils-8.27/tests/local.mk
 25.4716 +--- coreutils-8.27-orig/tests/local.mk	2017-02-28 22:25:37.000000000 -0600
 25.4717 ++++ coreutils-8.27/tests/local.mk	2017-03-11 23:47:38.072058253 -0600
 25.4718 +@@ -352,6 +352,8 @@ all_tests =					\
 25.4719 +   tests/misc/sort-discrim.sh			\
 25.4720 +   tests/misc/sort-files0-from.pl		\
 25.4721 +   tests/misc/sort-float.sh			\
 25.4722 ++  tests/misc/sort-mb-tests.sh			\
 25.4723 ++  tests/i18n/sort.sh				\
 25.4724 +   tests/misc/sort-h-thousands-sep.sh		\
 25.4725 +   tests/misc/sort-merge.pl			\
 25.4726 +   tests/misc/sort-merge-fdlimit.sh		\
 25.4727 +@@ -544,6 +546,7 @@ all_tests =					\
 25.4728 +   tests/du/threshold.sh				\
 25.4729 +   tests/du/trailing-slash.sh			\
 25.4730 +   tests/du/two-args.sh				\
 25.4731 ++  tests/expand/mb.sh				\
 25.4732 +   tests/id/gnu-zero-uids.sh			\
 25.4733 +   tests/id/no-context.sh			\
 25.4734 +   tests/id/context.sh				\
 25.4735 +@@ -684,6 +687,7 @@ all_tests =					\
 25.4736 +   tests/touch/read-only.sh			\
 25.4737 +   tests/touch/relative.sh			\
 25.4738 +   tests/touch/trailing-slash.sh			\
 25.4739 ++  tests/unexpand/mb.sh				\
 25.4740 +   $(all_root_tests)
 25.4741 + 
 25.4742 + # See tests/factor/create-test.sh.
 25.4743 +diff -Naurp coreutils-8.27-orig/tests/misc/cut.pl coreutils-8.27/tests/misc/cut.pl
 25.4744 +--- coreutils-8.27-orig/tests/misc/cut.pl	2017-01-01 16:34:24.000000000 -0600
 25.4745 ++++ coreutils-8.27/tests/misc/cut.pl	2017-03-11 23:47:13.100285838 -0600
 25.4746 +@@ -23,9 +23,11 @@ use strict;
 25.4747 + # Turn off localization of executable's output.
 25.4748 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.4749 + 
 25.4750 +-my $mb_locale = $ENV{LOCALE_FR_UTF8};
 25.4751 ++my $mb_locale;
 25.4752 ++# uncommented enable multibyte paths
 25.4753 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.4754 + ! defined $mb_locale || $mb_locale eq 'none'
 25.4755 +-  and $mb_locale = 'C';
 25.4756 ++ and $mb_locale = 'C';
 25.4757 + 
 25.4758 + my $prog = 'cut';
 25.4759 + my $try = "Try '$prog --help' for more information.\n";
 25.4760 +@@ -240,6 +242,7 @@ if ($mb_locale ne 'C')
 25.4761 +         my @new_t = @$t;
 25.4762 +         my $test_name = shift @new_t;
 25.4763 + 
 25.4764 ++        next if ($test_name =~ "newline-[12][0-9]");
 25.4765 +         push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.4766 +       }
 25.4767 +     push @Tests, @new;
 25.4768 +diff -Naurp coreutils-8.27-orig/tests/misc/expand.pl coreutils-8.27/tests/misc/expand.pl
 25.4769 +--- coreutils-8.27-orig/tests/misc/expand.pl	2017-03-01 11:16:46.000000000 -0600
 25.4770 ++++ coreutils-8.27/tests/misc/expand.pl	2017-03-11 23:47:13.101285788 -0600
 25.4771 +@@ -27,6 +27,15 @@ my $prog = 'expand';
 25.4772 + # Turn off localization of executable's output.
 25.4773 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.4774 + 
 25.4775 ++#comment out next line to disable multibyte tests
 25.4776 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 25.4777 ++! defined $mb_locale || $mb_locale eq 'none'
 25.4778 ++ and $mb_locale = 'C';
 25.4779 ++
 25.4780 ++my $prog = 'expand';
 25.4781 ++my $try = "Try \`$prog --help' for more information.\n";
 25.4782 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.4783 ++
 25.4784 + my @Tests =
 25.4785 +   (
 25.4786 +    ['t1', '--tabs=3',     {IN=>"a\tb"}, {OUT=>"a  b"}],
 25.4787 +@@ -152,6 +161,8 @@ my @Tests =
 25.4788 +    ['trail9', '--tab=1,2 -t/5',{IN=>"\ta\tb\tc"}, {OUT=>" a   b    c"}],
 25.4789 + 
 25.4790 +    # Test errors
 25.4791 ++   # FIXME: The following tests contain ‘quoting’ specific to LC_MESSAGES
 25.4792 ++   # So we force LC_MESSAGES=C to make them pass.
 25.4793 +    ['e1', '--tabs="a"', {IN=>''}, {OUT=>''}, {EXIT=>1},
 25.4794 +     {ERR => "$prog: tab size contains invalid character(s): 'a'\n"}],
 25.4795 +    ['e2', "-t $UINTMAX_OFLOW", {IN=>''}, {OUT=>''}, {EXIT=>1},
 25.4796 +@@ -168,6 +179,37 @@ my @Tests =
 25.4797 +     {ERR => "$prog: '/' specifier not at start of number: '/'\n"}],
 25.4798 +   );
 25.4799 + 
 25.4800 ++if ($mb_locale ne 'C')
 25.4801 ++  {
 25.4802 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.4803 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.4804 ++    # provide coverage for the distro-added multi-byte code paths.
 25.4805 ++    my @new;
 25.4806 ++    foreach my $t (@Tests)
 25.4807 ++      {
 25.4808 ++        my @new_t = @$t;
 25.4809 ++        my $test_name = shift @new_t;
 25.4810 ++
 25.4811 ++        # Depending on whether expand is multi-byte-patched,
 25.4812 ++        # it emits different diagnostics:
 25.4813 ++        #   non-MB: invalid byte or field list
 25.4814 ++        #   MB:     invalid byte, character or field list
 25.4815 ++        # Adjust the expected error output accordingly.
 25.4816 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.4817 ++            (@new_t))
 25.4818 ++          {
 25.4819 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.4820 ++            push @new_t, $sub;
 25.4821 ++            push @$t, $sub;
 25.4822 ++          }
 25.4823 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LANG=$mb_locale LC_MESSAGES=C"}];
 25.4824 ++      }
 25.4825 ++    push @Tests, @new;
 25.4826 ++  }
 25.4827 ++
 25.4828 ++
 25.4829 ++@Tests = triple_test \@Tests;
 25.4830 ++
 25.4831 + my $save_temps = $ENV{DEBUG};
 25.4832 + my $verbose = $ENV{VERBOSE};
 25.4833 + 
 25.4834 +diff -Naurp coreutils-8.27-orig/tests/misc/fold.pl coreutils-8.27/tests/misc/fold.pl
 25.4835 +--- coreutils-8.27-orig/tests/misc/fold.pl	2017-01-01 16:34:24.000000000 -0600
 25.4836 ++++ coreutils-8.27/tests/misc/fold.pl	2017-03-11 23:47:13.101285788 -0600
 25.4837 +@@ -20,9 +20,18 @@ use strict;
 25.4838 + 
 25.4839 + (my $program_name = $0) =~ s|.*/||;
 25.4840 + 
 25.4841 ++my $prog = 'fold';
 25.4842 ++my $try = "Try \`$prog --help' for more information.\n";
 25.4843 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.4844 ++
 25.4845 + # Turn off localization of executable's output.
 25.4846 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.4847 + 
 25.4848 ++# uncommented to enable multibyte paths
 25.4849 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 25.4850 ++! defined $mb_locale || $mb_locale eq 'none'
 25.4851 ++ and $mb_locale = 'C';
 25.4852 ++
 25.4853 + my @Tests =
 25.4854 +   (
 25.4855 +    ['s1', '-w2 -s', {IN=>"a\t"}, {OUT=>"a\n\t"}],
 25.4856 +@@ -31,9 +40,48 @@ my @Tests =
 25.4857 +    ['s4', '-w4 -s', {IN=>"abc ef\n"}, {OUT=>"abc \nef\n"}],
 25.4858 +   );
 25.4859 + 
 25.4860 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 25.4861 ++# that uses an old-style option like +1.
 25.4862 ++if ($mb_locale ne 'C')
 25.4863 ++  {
 25.4864 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.4865 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.4866 ++    # provide coverage for the distro-added multi-byte code paths.
 25.4867 ++    my @new;
 25.4868 ++    foreach my $t (@Tests)
 25.4869 ++      {
 25.4870 ++        my @new_t = @$t;
 25.4871 ++        my $test_name = shift @new_t;
 25.4872 ++
 25.4873 ++        # Depending on whether fold is multi-byte-patched,
 25.4874 ++        # it emits different diagnostics:
 25.4875 ++        #   non-MB: invalid byte or field list
 25.4876 ++        #   MB:     invalid byte, character or field list
 25.4877 ++        # Adjust the expected error output accordingly.
 25.4878 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.4879 ++            (@new_t))
 25.4880 ++          {
 25.4881 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.4882 ++            push @new_t, $sub;
 25.4883 ++            push @$t, $sub;
 25.4884 ++          }
 25.4885 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.4886 ++      }
 25.4887 ++    push @Tests, @new;
 25.4888 ++  }
 25.4889 ++
 25.4890 ++@Tests = triple_test \@Tests;
 25.4891 ++
 25.4892 ++# Remember that triple_test creates from each test with exactly one "IN"
 25.4893 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 25.4894 ++# input from a file and from a pipe.  The pipe-reading test would fail
 25.4895 ++# due to a race condition about 1 in 20 times.
 25.4896 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 25.4897 ++# The others aren't susceptible because they have three inputs each.
 25.4898 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 25.4899 ++
 25.4900 + my $save_temps = $ENV{DEBUG};
 25.4901 + my $verbose = $ENV{VERBOSE};
 25.4902 + 
 25.4903 +-my $prog = 'fold';
 25.4904 + my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
 25.4905 + exit $fail;
 25.4906 +diff -Naurp coreutils-8.27-orig/tests/misc/join.pl coreutils-8.27/tests/misc/join.pl
 25.4907 +--- coreutils-8.27-orig/tests/misc/join.pl	2017-01-01 16:34:24.000000000 -0600
 25.4908 ++++ coreutils-8.27/tests/misc/join.pl	2017-03-11 23:47:13.102285737 -0600
 25.4909 +@@ -25,6 +25,15 @@ my $limits = getlimits ();
 25.4910 + 
 25.4911 + my $prog = 'join';
 25.4912 + 
 25.4913 ++my $try = "Try \`$prog --help' for more information.\n";
 25.4914 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.4915 ++
 25.4916 ++my $mb_locale;
 25.4917 ++#Comment out next line to disable multibyte tests
 25.4918 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.4919 ++! defined $mb_locale || $mb_locale eq 'none'
 25.4920 ++  and $mb_locale = 'C';
 25.4921 ++
 25.4922 + my $delim = chr 0247;
 25.4923 + sub t_subst ($)
 25.4924 + {
 25.4925 +@@ -329,8 +338,49 @@ foreach my $t (@tv)
 25.4926 +     push @Tests, $new_ent;
 25.4927 +   }
 25.4928 + 
 25.4929 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 25.4930 ++# that uses an old-style option like +1.
 25.4931 ++if ($mb_locale ne 'C')
 25.4932 ++  {
 25.4933 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.4934 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.4935 ++    # provide coverage for the distro-added multi-byte code paths.
 25.4936 ++    my @new;
 25.4937 ++    foreach my $t (@Tests)
 25.4938 ++      {
 25.4939 ++        my @new_t = @$t;
 25.4940 ++        my $test_name = shift @new_t;
 25.4941 ++
 25.4942 ++        # Depending on whether join is multi-byte-patched,
 25.4943 ++        # it emits different diagnostics:
 25.4944 ++        #   non-MB: invalid byte or field list
 25.4945 ++        #   MB:     invalid byte, character or field list
 25.4946 ++        # Adjust the expected error output accordingly.
 25.4947 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.4948 ++            (@new_t))
 25.4949 ++          {
 25.4950 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.4951 ++            push @new_t, $sub;
 25.4952 ++            push @$t, $sub;
 25.4953 ++          }
 25.4954 ++        #Adjust the output some error messages including test_name for mb
 25.4955 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR}}
 25.4956 ++             (@new_t))
 25.4957 ++          {
 25.4958 ++            my $sub2 = {ERR_SUBST => "s/$test_name-mb/$test_name/"};
 25.4959 ++            push @new_t, $sub2;
 25.4960 ++            push @$t, $sub2;
 25.4961 ++          }
 25.4962 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.4963 ++      }
 25.4964 ++    push @Tests, @new;
 25.4965 ++  }
 25.4966 ++
 25.4967 + @Tests = triple_test \@Tests;
 25.4968 + 
 25.4969 ++#skip invalid-j-mb test, it is failing because of the format
 25.4970 ++@Tests = grep {$_->[0] ne 'invalid-j-mb'} @Tests;
 25.4971 ++
 25.4972 + my $save_temps = $ENV{DEBUG};
 25.4973 + my $verbose = $ENV{VERBOSE};
 25.4974 + 
 25.4975 +diff -Naurp coreutils-8.27-orig/tests/misc/sort-mb-tests.sh coreutils-8.27/tests/misc/sort-mb-tests.sh
 25.4976 +--- coreutils-8.27-orig/tests/misc/sort-mb-tests.sh	1969-12-31 18:00:00.000000000 -0600
 25.4977 ++++ coreutils-8.27/tests/misc/sort-mb-tests.sh	2017-03-11 23:47:13.102285737 -0600
 25.4978 +@@ -0,0 +1,45 @@
 25.4979 ++#!/bin/sh
 25.4980 ++# Verify sort's multi-byte support.
 25.4981 ++
 25.4982 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 25.4983 ++print_ver_ sort
 25.4984 ++
 25.4985 ++export LC_ALL=en_US.UTF-8
 25.4986 ++locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \
 25.4987 ++  || skip_ "No UTF-8 locale available"
 25.4988 ++
 25.4989 ++
 25.4990 ++cat <<EOF > exp
 25.4991 ++Banana@5
 25.4992 ++Apple@10
 25.4993 ++Citrus@20
 25.4994 ++Cherry@30
 25.4995 ++EOF
 25.4996 ++
 25.4997 ++cat <<EOF | sort -t @ -k2 -n > out || fail=1
 25.4998 ++Apple@10
 25.4999 ++Banana@5
 25.5000 ++Citrus@20
 25.5001 ++Cherry@30
 25.5002 ++EOF
 25.5003 ++
 25.5004 ++compare exp out || { fail=1; cat out; }
 25.5005 ++
 25.5006 ++
 25.5007 ++cat <<EOF > exp
 25.5008 ++Citrus@AA20@@5
 25.5009 ++Cherry@AA30@@10
 25.5010 ++Apple@AA10@@20
 25.5011 ++Banana@AA5@@30
 25.5012 ++EOF
 25.5013 ++
 25.5014 ++cat <<EOF | sort -t @ -k4 -n > out || fail=1
 25.5015 ++Apple@AA10@@20
 25.5016 ++Banana@AA5@@30
 25.5017 ++Citrus@AA20@@5
 25.5018 ++Cherry@AA30@@10
 25.5019 ++EOF
 25.5020 ++
 25.5021 ++compare exp out || { fail=1; cat out; }
 25.5022 ++
 25.5023 ++Exit $fail
 25.5024 +diff -Naurp coreutils-8.27-orig/tests/misc/sort-merge.pl coreutils-8.27/tests/misc/sort-merge.pl
 25.5025 +--- coreutils-8.27-orig/tests/misc/sort-merge.pl	2017-01-01 16:34:24.000000000 -0600
 25.5026 ++++ coreutils-8.27/tests/misc/sort-merge.pl	2017-03-11 23:47:13.102285737 -0600
 25.5027 +@@ -26,6 +26,15 @@ my $prog = 'sort';
 25.5028 + # Turn off localization of executable's output.
 25.5029 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.5030 + 
 25.5031 ++my $mb_locale;
 25.5032 ++# uncommented according to upstream commit enabling multibyte paths
 25.5033 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5034 ++! defined $mb_locale || $mb_locale eq 'none'
 25.5035 ++ and $mb_locale = 'C';
 25.5036 ++
 25.5037 ++my $try = "Try \`$prog --help' for more information.\n";
 25.5038 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.5039 ++
 25.5040 + # three empty files and one that says 'foo'
 25.5041 + my @inputs = (+(map{{IN=> {"empty$_"=> ''}}}1..3), {IN=> {foo=> "foo\n"}});
 25.5042 + 
 25.5043 +@@ -77,6 +86,39 @@ my @Tests =
 25.5044 +         {OUT=>$big_input}],
 25.5045 +     );
 25.5046 + 
 25.5047 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 25.5048 ++# that uses an old-style option like +1.
 25.5049 ++if ($mb_locale ne 'C')
 25.5050 ++  {
 25.5051 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.5052 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.5053 ++    # provide coverage for the distro-added multi-byte code paths.
 25.5054 ++    my @new;
 25.5055 ++    foreach my $t (@Tests)
 25.5056 ++      {
 25.5057 ++        my @new_t = @$t;
 25.5058 ++        my $test_name = shift @new_t;
 25.5059 ++
 25.5060 ++        # Depending on whether sort is multi-byte-patched,
 25.5061 ++        # it emits different diagnostics:
 25.5062 ++        #   non-MB: invalid byte or field list
 25.5063 ++        #   MB:     invalid byte, character or field list
 25.5064 ++        # Adjust the expected error output accordingly.
 25.5065 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.5066 ++            (@new_t))
 25.5067 ++          {
 25.5068 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.5069 ++            push @new_t, $sub;
 25.5070 ++            push @$t, $sub;
 25.5071 ++          }
 25.5072 ++        next if ($test_name =~ "nmerge-.");
 25.5073 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.5074 ++      }
 25.5075 ++    push @Tests, @new;
 25.5076 ++  }
 25.5077 ++
 25.5078 ++@Tests = triple_test \@Tests;
 25.5079 ++
 25.5080 + my $save_temps = $ENV{DEBUG};
 25.5081 + my $verbose = $ENV{VERBOSE};
 25.5082 + 
 25.5083 +diff -Naurp coreutils-8.27-orig/tests/misc/sort.pl coreutils-8.27/tests/misc/sort.pl
 25.5084 +--- coreutils-8.27-orig/tests/misc/sort.pl	2017-01-21 08:53:43.000000000 -0600
 25.5085 ++++ coreutils-8.27/tests/misc/sort.pl	2017-03-11 23:47:13.103285687 -0600
 25.5086 +@@ -24,10 +24,15 @@ my $prog = 'sort';
 25.5087 + # Turn off localization of executable's output.
 25.5088 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.5089 + 
 25.5090 +-my $mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5091 ++my $mb_locale;
 25.5092 ++#Comment out next line to disable multibyte tests
 25.5093 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5094 + ! defined $mb_locale || $mb_locale eq 'none'
 25.5095 +   and $mb_locale = 'C';
 25.5096 + 
 25.5097 ++my $try = "Try \`$prog --help' for more information.\n";
 25.5098 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.5099 ++
 25.5100 + # Since each test is run with a file name and with redirected stdin,
 25.5101 + # the name in the diagnostic is either the file name or "-".
 25.5102 + # Normalize each diagnostic to use '-'.
 25.5103 +@@ -423,6 +428,38 @@ foreach my $t (@Tests)
 25.5104 +       }
 25.5105 +   }
 25.5106 + 
 25.5107 ++if ($mb_locale ne 'C')
 25.5108 ++   {
 25.5109 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.5110 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.5111 ++    # provide coverage for the distro-added multi-byte code paths.
 25.5112 ++    my @new;
 25.5113 ++    foreach my $t (@Tests)
 25.5114 ++       {
 25.5115 ++        my @new_t = @$t;
 25.5116 ++        my $test_name = shift @new_t;
 25.5117 ++
 25.5118 ++        # Depending on whether sort is multi-byte-patched,
 25.5119 ++        # it emits different diagnostics:
 25.5120 ++        #   non-MB: invalid byte or field list
 25.5121 ++        #   MB:     invalid byte, character or field list
 25.5122 ++        # Adjust the expected error output accordingly.
 25.5123 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.5124 ++            (@new_t))
 25.5125 ++          {
 25.5126 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.5127 ++            push @new_t, $sub;
 25.5128 ++            push @$t, $sub;
 25.5129 ++          }
 25.5130 ++        #disable several failing tests until investigation, disable all tests with envvars set
 25.5131 ++        next if (grep {ref $_ eq 'HASH' && exists $_->{ENV}} (@new_t));
 25.5132 ++        next if ($test_name =~ "18g" or $test_name =~ "sort-numeric" or $test_name =~ "08[ab]" or $test_name =~ "03[def]" or $test_name =~ "h4" or $test_name =~ "n1" or $test_name =~ "2[01]a");
 25.5133 ++        next if ($test_name =~ "11[ab]"); # avoid FP: expected result differs to MB result due to collation rules.
 25.5134 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.5135 ++       }
 25.5136 ++    push @Tests, @new;
 25.5137 ++   }
 25.5138 ++
 25.5139 + @Tests = triple_test \@Tests;
 25.5140 + 
 25.5141 + # Remember that triple_test creates from each test with exactly one "IN"
 25.5142 +@@ -432,6 +469,7 @@ foreach my $t (@Tests)
 25.5143 + # Remove the IN_PIPE version of the "output-is-input" test above.
 25.5144 + # The others aren't susceptible because they have three inputs each.
 25.5145 + @Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 25.5146 ++@Tests = grep {$_->[0] ne 'output-is-input-mb.p'} @Tests;
 25.5147 + 
 25.5148 + my $save_temps = $ENV{DEBUG};
 25.5149 + my $verbose = $ENV{VERBOSE};
 25.5150 +diff -Naurp coreutils-8.27-orig/tests/misc/unexpand.pl coreutils-8.27/tests/misc/unexpand.pl
 25.5151 +--- coreutils-8.27-orig/tests/misc/unexpand.pl	2017-01-01 16:34:24.000000000 -0600
 25.5152 ++++ coreutils-8.27/tests/misc/unexpand.pl	2017-03-11 23:47:13.103285687 -0600
 25.5153 +@@ -27,6 +27,14 @@ my $limits = getlimits ();
 25.5154 + 
 25.5155 + my $prog = 'unexpand';
 25.5156 + 
 25.5157 ++# comment out next line to disable multibyte tests
 25.5158 ++my $mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5159 ++! defined $mb_locale || $mb_locale eq 'none'
 25.5160 ++ and $mb_locale = 'C';
 25.5161 ++
 25.5162 ++my $try = "Try \`$prog --help' for more information.\n";
 25.5163 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.5164 ++
 25.5165 + my @Tests =
 25.5166 +     (
 25.5167 +      ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}],
 25.5168 +@@ -128,6 +136,37 @@ my @Tests =
 25.5169 +      ['ts2', '-t5,8', {IN=>"x\t \t y\n"},    {OUT=>"x\t\t y\n"}],
 25.5170 +     );
 25.5171 + 
 25.5172 ++if ($mb_locale ne 'C')
 25.5173 ++  {
 25.5174 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.5175 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.5176 ++    # provide coverage for the distro-added multi-byte code paths.
 25.5177 ++    my @new;
 25.5178 ++    foreach my $t (@Tests)
 25.5179 ++      {
 25.5180 ++        my @new_t = @$t;
 25.5181 ++        my $test_name = shift @new_t;
 25.5182 ++
 25.5183 ++        # Depending on whether unexpand is multi-byte-patched,
 25.5184 ++        # it emits different diagnostics:
 25.5185 ++        #   non-MB: invalid byte or field list
 25.5186 ++        #   MB:     invalid byte, character or field list
 25.5187 ++        # Adjust the expected error output accordingly.
 25.5188 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.5189 ++            (@new_t))
 25.5190 ++          {
 25.5191 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.5192 ++            push @new_t, $sub;
 25.5193 ++            push @$t, $sub;
 25.5194 ++          }
 25.5195 ++        next if ($test_name =~ 'b-1');
 25.5196 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.5197 ++      }
 25.5198 ++    push @Tests, @new;
 25.5199 ++  }
 25.5200 ++
 25.5201 ++@Tests = triple_test \@Tests;
 25.5202 ++
 25.5203 + my $save_temps = $ENV{DEBUG};
 25.5204 + my $verbose = $ENV{VERBOSE};
 25.5205 + 
 25.5206 +diff -Naurp coreutils-8.27-orig/tests/misc/uniq.pl coreutils-8.27/tests/misc/uniq.pl
 25.5207 +--- coreutils-8.27-orig/tests/misc/uniq.pl	2017-01-01 16:34:24.000000000 -0600
 25.5208 ++++ coreutils-8.27/tests/misc/uniq.pl	2017-03-11 23:47:13.103285687 -0600
 25.5209 +@@ -23,9 +23,17 @@ my $limits = getlimits ();
 25.5210 + my $prog = 'uniq';
 25.5211 + my $try = "Try '$prog --help' for more information.\n";
 25.5212 + 
 25.5213 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.5214 ++
 25.5215 + # Turn off localization of executable's output.
 25.5216 + @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 25.5217 + 
 25.5218 ++my $mb_locale;
 25.5219 ++#Comment out next line to disable multibyte tests
 25.5220 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5221 ++! defined $mb_locale || $mb_locale eq 'none'
 25.5222 ++  and $mb_locale = 'C';
 25.5223 ++
 25.5224 + # When possible, create a "-z"-testing variant of each test.
 25.5225 + sub add_z_variants($)
 25.5226 + {
 25.5227 +@@ -262,6 +270,53 @@ foreach my $t (@Tests)
 25.5228 +       and push @$t, {ENV=>'_POSIX2_VERSION=199209'};
 25.5229 +   }
 25.5230 + 
 25.5231 ++if ($mb_locale ne 'C')
 25.5232 ++  {
 25.5233 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.5234 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.5235 ++    # provide coverage for the distro-added multi-byte code paths.
 25.5236 ++    my @new;
 25.5237 ++    foreach my $t (@Tests)
 25.5238 ++      {
 25.5239 ++        my @new_t = @$t;
 25.5240 ++        my $test_name = shift @new_t;
 25.5241 ++
 25.5242 ++        # Depending on whether uniq is multi-byte-patched,
 25.5243 ++        # it emits different diagnostics:
 25.5244 ++        #   non-MB: invalid byte or field list
 25.5245 ++        #   MB:     invalid byte, character or field list
 25.5246 ++        # Adjust the expected error output accordingly.
 25.5247 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.5248 ++            (@new_t))
 25.5249 ++          {
 25.5250 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.5251 ++            push @new_t, $sub;
 25.5252 ++            push @$t, $sub;
 25.5253 ++          }
 25.5254 ++        # In test #145, replace the each ‘...’ by '...'.
 25.5255 ++        if ($test_name =~ "145")
 25.5256 ++          {
 25.5257 ++            my $sub = { ERR_SUBST => "s/‘([^’]+)’/'\$1'/g"};
 25.5258 ++            push @new_t, $sub;
 25.5259 ++            push @$t, $sub;
 25.5260 ++          }
 25.5261 ++        next if (   $test_name =~ "schar"
 25.5262 ++                 or $test_name =~ "^obs-plus"
 25.5263 ++                 or $test_name =~ "119");
 25.5264 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.5265 ++      }
 25.5266 ++    push @Tests, @new;
 25.5267 ++   }
 25.5268 ++
 25.5269 ++# Remember that triple_test creates from each test with exactly one "IN"
 25.5270 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 25.5271 ++# input from a file and from a pipe.  The pipe-reading test would fail
 25.5272 ++# due to a race condition about 1 in 20 times.
 25.5273 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 25.5274 ++# The others aren't susceptible because they have three inputs each.
 25.5275 ++
 25.5276 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 25.5277 ++
 25.5278 + @Tests = add_z_variants \@Tests;
 25.5279 + @Tests = triple_test \@Tests;
 25.5280 + 
 25.5281 +diff -Naurp coreutils-8.27-orig/tests/pr/pr-tests.pl coreutils-8.27/tests/pr/pr-tests.pl
 25.5282 +--- coreutils-8.27-orig/tests/pr/pr-tests.pl	2017-01-01 16:34:24.000000000 -0600
 25.5283 ++++ coreutils-8.27/tests/pr/pr-tests.pl	2017-03-11 23:47:13.103285687 -0600
 25.5284 +@@ -24,6 +24,15 @@ use strict;
 25.5285 + my $prog = 'pr';
 25.5286 + my $normalize_strerror = "s/': .*/'/";
 25.5287 + 
 25.5288 ++my $mb_locale;
 25.5289 ++#Uncomment the following line to enable multibyte tests
 25.5290 ++$mb_locale = $ENV{LOCALE_FR_UTF8};
 25.5291 ++! defined $mb_locale || $mb_locale eq 'none'
 25.5292 ++  and $mb_locale = 'C';
 25.5293 ++
 25.5294 ++my $try = "Try \`$prog --help' for more information.\n";
 25.5295 ++my $inval = "$prog: invalid byte, character or field list\n$try";
 25.5296 ++
 25.5297 + my @tv = (
 25.5298 + 
 25.5299 + # -b option is no longer an official option. But it's still working to
 25.5300 +@@ -474,8 +483,48 @@ push @Tests,
 25.5301 +     {IN=>{2=>"a\n"}},
 25.5302 +      {OUT=>"a\t\t\t\t  \t\t\ta\n"} ];
 25.5303 + 
 25.5304 ++# Add _POSIX2_VERSION=199209 to the environment of each test
 25.5305 ++# that uses an old-style option like +1.
 25.5306 ++if ($mb_locale ne 'C')
 25.5307 ++  {
 25.5308 ++    # Duplicate each test vector, appending "-mb" to the test name and
 25.5309 ++    # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
 25.5310 ++    # provide coverage for the distro-added multi-byte code paths.
 25.5311 ++    my @new;
 25.5312 ++    foreach my $t (@Tests)
 25.5313 ++      {
 25.5314 ++        my @new_t = @$t;
 25.5315 ++        my $test_name = shift @new_t;
 25.5316 ++
 25.5317 ++        # Depending on whether pr is multi-byte-patched,
 25.5318 ++        # it emits different diagnostics:
 25.5319 ++        #   non-MB: invalid byte or field list
 25.5320 ++        #   MB:     invalid byte, character or field list
 25.5321 ++        # Adjust the expected error output accordingly.
 25.5322 ++        if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval}
 25.5323 ++            (@new_t))
 25.5324 ++          {
 25.5325 ++            my $sub = {ERR_SUBST => 's/, character//'};
 25.5326 ++            push @new_t, $sub;
 25.5327 ++            push @$t, $sub;
 25.5328 ++          }
 25.5329 ++        #temporarily skip some failing tests
 25.5330 ++        next if ($test_name =~ "col-0" or $test_name =~ "col-inval" or $test_name =~ "asan1");
 25.5331 ++        push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}];
 25.5332 ++      }
 25.5333 ++    push @Tests, @new;
 25.5334 ++  }
 25.5335 ++
 25.5336 + @Tests = triple_test \@Tests;
 25.5337 + 
 25.5338 ++# Remember that triple_test creates from each test with exactly one "IN"
 25.5339 ++# file two more tests (.p and .r suffix on name) corresponding to reading
 25.5340 ++# input from a file and from a pipe.  The pipe-reading test would fail
 25.5341 ++# due to a race condition about 1 in 20 times.
 25.5342 ++# Remove the IN_PIPE version of the "output-is-input" test above.
 25.5343 ++# The others aren't susceptible because they have three inputs each.
 25.5344 ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests;
 25.5345 ++
 25.5346 + my $save_temps = $ENV{DEBUG};
 25.5347 + my $verbose = $ENV{VERBOSE};
 25.5348 + 
 25.5349 +diff -Naurp coreutils-8.27-orig/tests/unexpand/mb.sh coreutils-8.27/tests/unexpand/mb.sh
 25.5350 +--- coreutils-8.27-orig/tests/unexpand/mb.sh	1969-12-31 18:00:00.000000000 -0600
 25.5351 ++++ coreutils-8.27/tests/unexpand/mb.sh	2017-03-11 23:49:06.759133489 -0600
 25.5352 +@@ -0,0 +1,172 @@
 25.5353 ++#!/bin/sh
 25.5354 ++
 25.5355 ++# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 25.5356 ++
 25.5357 ++# This program is free software: you can redistribute it and/or modify
 25.5358 ++# it under the terms of the GNU General Public License as published by
 25.5359 ++# the Free Software Foundation, either version 3 of the License, or
 25.5360 ++# (at your option) any later version.
 25.5361 ++
 25.5362 ++# This program is distributed in the hope that it will be useful,
 25.5363 ++# but WITHOUT ANY WARRANTY; without even the implied warranty of
 25.5364 ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 25.5365 ++# GNU General Public License for more details.
 25.5366 ++
 25.5367 ++# You should have received a copy of the GNU General Public License
 25.5368 ++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 25.5369 ++
 25.5370 ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 25.5371 ++print_ver_ unexpand
 25.5372 ++
 25.5373 ++export LC_ALL=en_US.UTF-8
 25.5374 ++
 25.5375 ++#input containing multibyte characters
 25.5376 ++cat > in <<\EOF
 25.5377 ++1234567812345678123456781
 25.5378 ++.       .       .       .
 25.5379 ++a       b       c       d
 25.5380 ++.       .       .       .
 25.5381 ++ä       ö       ü       ß
 25.5382 ++.       .       .       .
 25.5383 ++   äöü  .    öüä.       ä xx
 25.5384 ++EOF
 25.5385 ++
 25.5386 ++cat > exp <<\EOF
 25.5387 ++1234567812345678123456781
 25.5388 ++.	.	.	.
 25.5389 ++a	b	c	d
 25.5390 ++.	.	.	.
 25.5391 ++ä	ö	ü	ß
 25.5392 ++.	.	.	.
 25.5393 ++   äöü	.    öüä.	ä xx
 25.5394 ++EOF
 25.5395 ++
 25.5396 ++unexpand -a < in > out || fail=1
 25.5397 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5398 ++
 25.5399 ++
 25.5400 ++#multiple files as an input
 25.5401 ++cat >> exp <<\EOF
 25.5402 ++1234567812345678123456781
 25.5403 ++.	.	.	.
 25.5404 ++a	b	c	d
 25.5405 ++.	.	.	.
 25.5406 ++ä	ö	ü	ß
 25.5407 ++.	.	.	.
 25.5408 ++   äöü	.    öüä.	ä xx
 25.5409 ++EOF
 25.5410 ++
 25.5411 ++
 25.5412 ++unexpand -a ./in ./in > out || fail=1
 25.5413 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5414 ++
 25.5415 ++#test characters with a display width larger than 1
 25.5416 ++
 25.5417 ++env printf '12345678
 25.5418 ++e       |ascii(1)
 25.5419 ++\u00E9       |composed(1)
 25.5420 ++e\u0301       |decomposed(1)
 25.5421 ++\u3000      |ideo-space(2)
 25.5422 ++\uFF0D      |full-hypen(2)
 25.5423 ++' > in || framework_failure_
 25.5424 ++
 25.5425 ++env printf '12345678
 25.5426 ++e\t|ascii(1)
 25.5427 ++\u00E9\t|composed(1)
 25.5428 ++e\u0301\t|decomposed(1)
 25.5429 ++\u3000\t|ideo-space(2)
 25.5430 ++\uFF0D\t|full-hypen(2)
 25.5431 ++' > exp || framework_failure_
 25.5432 ++
 25.5433 ++unexpand -a < in > out || fail=1
 25.5434 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5435 ++
 25.5436 ++#test input where a blank of width > 1 is not being substituted
 25.5437 ++in="$(LC_ALL=en_US.UTF-8 printf ' \u3000  ö       ü       ß')"
 25.5438 ++exp='    ö	     ü	     ß'
 25.5439 ++
 25.5440 ++unexpand -a < in > out || fail=1
 25.5441 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5442 ++
 25.5443 ++#non-Unicode characters interspersed between Unicode ones
 25.5444 ++env printf '12345678
 25.5445 ++        \xFF|
 25.5446 ++\xFF       |
 25.5447 ++        \xFFä|
 25.5448 ++ä\xFF      |
 25.5449 ++        ä\xFF|
 25.5450 ++\xFF       ä|
 25.5451 ++äbcdef\xFF |
 25.5452 ++' > in || framework_failure_
 25.5453 ++
 25.5454 ++env printf '12345678
 25.5455 ++\t\xFF|
 25.5456 ++\xFF\t|
 25.5457 ++\t\xFFä|
 25.5458 ++ä\xFF\t|
 25.5459 ++\tä\xFF|
 25.5460 ++\xFF\tä|
 25.5461 ++äbcdef\xFF\t|
 25.5462 ++' > exp || framework_failure_
 25.5463 ++
 25.5464 ++unexpand -a < in > out || fail=1
 25.5465 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5466 ++
 25.5467 ++#BOM header test 1
 25.5468 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_
 25.5469 ++1234567812345678123456781
 25.5470 ++.       .       .       .
 25.5471 ++a       b       c       d
 25.5472 ++.       .       .       .
 25.5473 ++ä       ö       ü       ß
 25.5474 ++.       .       .       .
 25.5475 ++   äöü  .    öüä.       ä xx
 25.5476 ++EOF
 25.5477 ++env printf '   äöü\t.    öüä.   \tä xx\n' >> in || framework_failure_
 25.5478 ++
 25.5479 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 25.5480 ++1234567812345678123456781
 25.5481 ++.	.	.	.
 25.5482 ++a	b	c	d
 25.5483 ++.	.	.	.
 25.5484 ++ä	ö	ü	ß
 25.5485 ++.	.	.	.
 25.5486 ++   äöü	.    öüä.	ä xx
 25.5487 ++EOF
 25.5488 ++
 25.5489 ++unexpand < in > out || fail=1
 25.5490 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5491 ++
 25.5492 ++LANG=C unexpand < in > out || fail=1
 25.5493 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5494 ++
 25.5495 ++LC_ALL=C unexpand < in > out || fail=1
 25.5496 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5497 ++
 25.5498 ++
 25.5499 ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_
 25.5500 ++1234567812345678123456781
 25.5501 ++.	.	.	.
 25.5502 ++a	b	c	d
 25.5503 ++.	.	.	.
 25.5504 ++ä	ö	ü	ß
 25.5505 ++.	.	.	.
 25.5506 ++   äöü	.    öüä.	ä xx
 25.5507 ++1234567812345678123456781
 25.5508 ++.	.	.	.
 25.5509 ++a	b	c	d
 25.5510 ++.	.	.	.
 25.5511 ++ä	ö	ü	ß
 25.5512 ++.	.	.	.
 25.5513 ++   äöü	.    öüä.	ä xx
 25.5514 ++EOF
 25.5515 ++
 25.5516 ++
 25.5517 ++unexpand in in > out || fail=1
 25.5518 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5519 ++
 25.5520 ++LANG=C unexpand in in > out || fail=1
 25.5521 ++compare exp out > /dev/null 2>&1 || fail=1
 25.5522 ++
 25.5523 ++LC_ALL=C unexpand in in > out || fail=1
 25.5524 ++compare exp out > /dev/null 2>&1 || fail=1
    26.1 --- a/coreutils/stuff/patches/coreutils-fix-po.patch	Wed Feb 21 18:10:55 2018 +0200
    26.2 +++ b/coreutils/stuff/patches/coreutils-fix-po.patch	Wed Feb 21 19:48:17 2018 +0200
    26.3 @@ -20,8 +20,8 @@
    26.4   "  N-M  fra N'te til M'te (inklusive) byte, tegn eller felt\n"
    26.5  --- a/po/sl.po
    26.6  +++ b/po/sl.po
    26.7 -@@ -2641,7 +2641,7 @@
    26.8 - #: src/csplit.c:1299
    26.9 +@@ -2579,7 +2579,7 @@
   26.10 + #: src/csplit.c:1298
   26.11   #, c-format
   26.12   msgid "invalid conversion specifier in suffix: \\%.3o"
   26.13  -msgstr "neveljavno določilo pretvorbe v priponi: \\\\%.3o"
    27.1 --- a/coreutils/stuff/patches/series	Wed Feb 21 18:10:55 2018 +0200
    27.2 +++ b/coreutils/stuff/patches/series	Wed Feb 21 19:48:17 2018 +0200
    27.3 @@ -1,3 +1,7 @@
    27.4 -coreutils-8.25-i18n-2.patch
    27.5 +# LFS: Coreutils Internationalization Fixes Patch
    27.6 +#coreutils-8.29-i18n-1.patch
    27.7 +
    27.8 +# SliTaz: show extended info touching CPU via uname
    27.9  uname.u
   27.10 +# SliTaz: fix translations, especially deprecated symbol '\v'
   27.11  coreutils-fix-po.patch
    28.1 --- a/diffutils/receipt	Wed Feb 21 18:10:55 2018 +0200
    28.2 +++ b/diffutils/receipt	Wed Feb 21 19:48:17 2018 +0200
    28.3 @@ -1,24 +1,22 @@
    28.4  # SliTaz package receipt v2.
    28.5  
    28.6  PACKAGE="diffutils"
    28.7 -VERSION="3.5"
    28.8 +VERSION="3.6"
    28.9  CATEGORY="development"
   28.10  SHORT_DESC="Show differences between two files"
   28.11  MAINTAINER="pascal.bellard@slitaz.org"
   28.12  LICENSE="GPL3"
   28.13  WEB_SITE="https://www.gnu.org/software/diffutils/"
   28.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/diffutils.html"
   28.15  
   28.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   28.17  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   28.18  
   28.19 -# Rules to configure and make the package.
   28.20 -compile_rules()
   28.21 -{
   28.22 +compile_rules() {
   28.23  	./configure $CONFIGURE_ARGS && make && make install
   28.24  }
   28.25  
   28.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   28.27 -genpkg_rules()
   28.28 -{
   28.29 +genpkg_rules() {
   28.30  	copy @std
   28.31 +	TAGS="LFS"
   28.32  }
    29.1 --- a/e2fsprogs/receipt	Wed Feb 21 18:10:55 2018 +0200
    29.2 +++ b/e2fsprogs/receipt	Wed Feb 21 19:48:17 2018 +0200
    29.3 @@ -1,25 +1,23 @@
    29.4  # SliTaz package receipt v2.
    29.5  
    29.6  PACKAGE="e2fsprogs"
    29.7 -VERSION="1.43.4"
    29.8 +VERSION="1.43.5"
    29.9  CATEGORY="base-system"
   29.10  SHORT_DESC="Filesystem utilities for use with ext2 and ext3"
   29.11  MAINTAINER="pankso@slitaz.org"
   29.12  LICENSE="GPL2"
   29.13  WEB_SITE="http://e2fsprogs.sourceforge.net/"
   29.14 -HOST_ARCH="i486 arm"
   29.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/e2fsprogs.html"
   29.16  
   29.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   29.18  WGET_URL="$SF_MIRROR/$PACKAGE/$TARBALL"
   29.19  
   29.20 +BUILD_DEPENDS_arm=" "
   29.21  BUILD_DEPENDS="util-linux-uuid-dev util-linux-blkid-dev gettext attr-dev \
   29.22  acl-dev texinfo"
   29.23 -BUILD_DEPENDS_arm=" "
   29.24 -SPLIT="libcomerr libcomerr-dev e2fsprogs-dev e2fsprogs-fsck"
   29.25 +SPLIT="libcomerr-dev e2fsprogs-dev e2fsprogs-fsck libcomerr e2fsprogs"
   29.26  
   29.27 -# Rules to configure and make the package.
   29.28 -compile_rules()
   29.29 -{
   29.30 +compile_rules() {
   29.31  	sed -i -e 's:\[\.-\]::' tests/filter.sed
   29.32  	mkdir ../build && cd ../build
   29.33  
   29.34 @@ -33,7 +31,7 @@
   29.35  		--disable-uuidd \
   29.36  		--disable-fsck \
   29.37  		$CONFIGURE_ARGS &&
   29.38 -	make && make install && make install-libs
   29.39 +	make && make install && make install-libs || return 1
   29.40  
   29.41  	for i in libcom_err libe2p libext2fs libss; do
   29.42  		chmod u+w $install/usr/lib/$i.a
   29.43 @@ -45,7 +43,7 @@
   29.44  		$install/usr/share/info/libext2fs.info
   29.45  
   29.46  	# Additional documentation
   29.47 -	makeinfo -o      $src/doc/com_err.info $src/lib/et/com_err.texinfo
   29.48 +	makeinfo -o   $src/doc/com_err.info $src/lib/et/com_err.texinfo
   29.49  	install -m644 $src/doc/com_err.info $install/usr/share/info
   29.50  	install-info --dir-file=$install/usr/share/info/dir \
   29.51  		$install/usr/share/info/com_err.info
   29.52 @@ -55,43 +53,36 @@
   29.53  	msgfmt $src/po/de.po -o $src/po/de.gmo
   29.54  }
   29.55  
   29.56 -# Rules to gen a SliTaz package suitable for Tazpkg.
   29.57 -genpkg_rules()
   29.58 -{
   29.59 +genpkg_rules() {
   29.60  	case $PACKAGE in
   29.61 -		e2fsprogs)
   29.62 -			copy bin/ sbin/ etc/ *.so*
   29.63 -			find $fs -name '*com_err*' -delete
   29.64 -			# Remove fsck provided by Busybox.
   29.65 -			rm $fs/sbin/fsck*
   29.66 -			DEPENDS="libcomerr util-linux-blkid util-linux-uuid"
   29.67 +		libcomerr-dev)
   29.68 +			copy libcom_err.a com_err.h com_err.pc
   29.69 +			CAT="development|libcomerr development files"
   29.70 +			DEPENDS="pkg-config"
   29.71  			;;
   29.72  		e2fsprogs-dev)
   29.73 -			copy @dev *.awk *.sed
   29.74 -			find $fs \( -name com_err.h -o -name libcom_err.a -o -name com_err.pc \) -delete
   29.75 +			copy @dev *.sed *.awk @rm
   29.76  			DEPENDS="libcomerr-dev pkg-config"
   29.77  			;;
   29.78 +		e2fsprogs-fsck)
   29.79 +			copy sbin/fsck.*
   29.80 +			CAT="system-tools|fsck tools"
   29.81 +			DEPENDS="e2fsprogs libcomerr util-linux-blkid util-linux-uuid"
   29.82 +			;;
   29.83  		libcomerr)
   29.84  			copy libcom_err.so*
   29.85  			CAT="base-system|libcomerr library"
   29.86  			DEPENDS=" "
   29.87  			;;
   29.88 -		libcomerr-dev)
   29.89 -			copy libcom_err.a com_err.h com_err.pc
   29.90 -			CAT="development|libcomerr development files"
   29.91 -			DEPENDS="pkg-config"
   29.92 -			;;
   29.93 -		e2fsprogs-fsck)
   29.94 -			copy fsck.*
   29.95 -			rm -r $fs/usr
   29.96 -			CAT="system-tools|fsck tools"
   29.97 -			DEPENDS="e2fsprogs libcomerr util-linux-blkid util-linux-uuid"
   29.98 +		e2fsprogs)
   29.99 +			copy @std @rm
  29.100 +			DEPENDS="libcomerr util-linux-blkid util-linux-uuid"
  29.101 +			TAGS="LFS"
  29.102  			;;
  29.103  	esac
  29.104  }
  29.105  
  29.106  # Overlap busybox
  29.107 -pre_install_e2fsprogs()
  29.108 -{
  29.109 +pre_install_e2fsprogs() {
  29.110  	rm -f $1/sbin/tune2fs
  29.111  }
    30.1 --- a/eudev/receipt	Wed Feb 21 18:10:55 2018 +0200
    30.2 +++ b/eudev/receipt	Wed Feb 21 19:48:17 2018 +0200
    30.3 @@ -8,7 +8,6 @@
    30.4  LICENSE="GPL2"
    30.5  WEB_SITE="http://dev.gentoo.org/~blueness/eudev/"
    30.6  LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/eudev.html"
    30.7 -PROVIDE="udev"
    30.8  
    30.9  TARBALL="$PACKAGE-$VERSION.tar.gz"
   30.10  WGET_URL="${WEB_SITE}$TARBALL"
   30.11 @@ -17,9 +16,7 @@
   30.12  BUILD_DEPENDS="gobject-introspection-dev util-linux-blkid-dev gperf kmod-dev"
   30.13  SPLIT="eudev-dev"
   30.14  
   30.15 -# Rules to configure and make the package.
   30.16 -compile_rules()
   30.17 -{
   30.18 +compile_rules() {
   30.19  	sed -r -i 's|/usr(/bin/test)|\1|' test/udev-test.pl
   30.20  	sed -i '/keyboard_lookup_key/d' src/udev/udev-builtin-keyboard.c
   30.21  	cat > config.cache <<"EOF"
   30.22 @@ -58,14 +55,13 @@
   30.23  	# in /lib/udev/rules.d.
   30.24  }
   30.25  
   30.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   30.27 -genpkg_rules()
   30.28 -{
   30.29 +genpkg_rules() {
   30.30  	case $PACKAGE in
   30.31  		eudev)
   30.32  			copy @std
   30.33  			DEPENDS="kmod liblzma util-linux-blkid util-linux-uuid zlib   dbus"
   30.34  			PROVIDE="udev"
   30.35 +			TAGS="LFS"
   30.36  			;;
   30.37  		eudev-dev)
   30.38  			copy @dev
    31.1 --- a/expat/receipt	Wed Feb 21 18:10:55 2018 +0200
    31.2 +++ b/expat/receipt	Wed Feb 21 19:48:17 2018 +0200
    31.3 @@ -1,36 +1,34 @@
    31.4  # SliTaz package receipt v2.
    31.5  
    31.6  PACKAGE="expat"
    31.7 -VERSION="2.2.0"
    31.8 +VERSION="2.2.3"
    31.9  CATEGORY="x-window"
   31.10  SHORT_DESC="XML parsing C library"
   31.11  MAINTAINER="pankso@slitaz.org"
   31.12  LICENSE="MIT"
   31.13  WEB_SITE="https://libexpat.github.io/"
   31.14 -HOST_ARCH="i486 arm"
   31.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/expat.html"
   31.16  
   31.17  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   31.18  WGET_URL="$SF_MIRROR/$PACKAGE/$TARBALL"
   31.19  
   31.20  SPLIT="expat-dev"
   31.21  
   31.22 -# Rules to configure and make the package.
   31.23 -compile_rules()
   31.24 -{
   31.25 +compile_rules() {
   31.26  	./configure \
   31.27  		--disable-static \
   31.28  		$CONFIGURE_ARGS &&
   31.29 -	make && make DESTDIR=$install install
   31.30 +	make && make DESTDIR=$install install || return 1
   31.31  
   31.32 -	docdir="$install/usr/share/doc/expat-$VERSION"
   31.33 -	mkdir -p $docdir; cp doc/* $docdir; rm $docdir/*.1
   31.34 +	cook_pick_docs doc/*.html doc/*.css doc/*.png
   31.35  }
   31.36  
   31.37 -# Rules to gen a SliTaz package suitable for Tazpkg.
   31.38 -genpkg_rules()
   31.39 -{
   31.40 +genpkg_rules() {
   31.41  	case $PACKAGE in
   31.42 -		expat) copy @std ;;
   31.43 -		expat-dev) copy @dev ;;
   31.44 +		expat)
   31.45 +			copy @std
   31.46 +			TAGS="LFS"
   31.47 +			;;
   31.48 +		*-dev) copy @dev;;
   31.49  	esac
   31.50  }
    32.1 --- a/file/receipt	Wed Feb 21 18:10:55 2018 +0200
    32.2 +++ b/file/receipt	Wed Feb 21 19:48:17 2018 +0200
    32.3 @@ -7,7 +7,7 @@
    32.4  MAINTAINER="erjo@slitaz.org"
    32.5  LICENSE="BSD"
    32.6  WEB_SITE="https://github.com/file/file"
    32.7 -HOST_ARCH="i486 arm"
    32.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/file.html"
    32.9  
   32.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   32.11  WGET_URL="https://github.com/file/file/archive/FILE${VERSION/./_}.tar.gz"
   32.12 @@ -16,30 +16,31 @@
   32.13  BUILD_DEPENDS_arm=""
   32.14  SPLIT="libmagic libmagic-dev python-magic"
   32.15  
   32.16 -# Rules to configure and make the package.
   32.17 -compile_rules()
   32.18 -{
   32.19 +compile_rules() {
   32.20  	autoreconf -f -i &&
   32.21 -	./configure $CONFIGURE_ARGS && make && make install
   32.22 +	./configure \
   32.23 +		--libdir=/usr/lib \
   32.24 +		$CONFIGURE_ARGS &&
   32.25 +	make && make install || return 1
   32.26 +
   32.27 +	rmdir --ignore-fail-on-non-empty $install/usr/share/man/man5/
   32.28  
   32.29  	cd python
   32.30  	python setup.py build &&
   32.31 -	python setup.py install --root=$DESTDIR
   32.32 +	python setup.py install --root=$install
   32.33  }
   32.34  
   32.35  # Be sure it as cross compile.
   32.36 -testsuite()
   32.37 -{
   32.38 +testsuite() {
   32.39  	readelf -h $install/usr/bin/file
   32.40  }
   32.41  
   32.42 -# Rules to gen a SliTaz package suitable for Tazpkg.
   32.43 -genpkg_rules()
   32.44 -{
   32.45 +genpkg_rules() {
   32.46  	case $PACKAGE in
   32.47  		file)
   32.48  			copy file magic.mgc
   32.49  			DEPENDS="zlib libmagic"
   32.50 +			TAGS="LFS"
   32.51  			;;
   32.52  		libmagic)
   32.53  			copy *.so*
    33.1 --- a/findutils/receipt	Wed Feb 21 18:10:55 2018 +0200
    33.2 +++ b/findutils/receipt	Wed Feb 21 19:48:17 2018 +0200
    33.3 @@ -7,13 +7,12 @@
    33.4  MAINTAINER="pankso@slitaz.org"
    33.5  LICENSE="GPL3"
    33.6  WEB_SITE="https://www.gnu.org/software/findutils/"
    33.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/findutils.html"
    33.8  
    33.9  TARBALL="$PACKAGE-$VERSION.tar.gz"
   33.10  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   33.11  
   33.12 -# Rules to configure and make the package.
   33.13 -compile_rules()
   33.14 -{
   33.15 +compile_rules() {
   33.16  	./configure \
   33.17  		--localstatedir=/var/lib/locate \
   33.18  		$CONFIGURE_ARGS &&
   33.19 @@ -21,9 +20,8 @@
   33.20  	make install
   33.21  }
   33.22  
   33.23 -# Rules to gen a SliTaz package suitable for Tazpkg.
   33.24 -genpkg_rules()
   33.25 -{
   33.26 +genpkg_rules() {
   33.27  	copy @std
   33.28  	DEPENDS="glibc-base slitaz-base-files"
   33.29 +	TAGS="LFS"
   33.30  }
    34.1 --- a/flex/receipt	Wed Feb 21 18:10:55 2018 +0200
    34.2 +++ b/flex/receipt	Wed Feb 21 19:48:17 2018 +0200
    34.3 @@ -7,33 +7,31 @@
    34.4  MAINTAINER="pankso@slitaz.org"
    34.5  LICENSE="BSD"
    34.6  WEB_SITE="https://github.com/westes/flex"
    34.7 -HOST_ARCH="i486 arm"
    34.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/flex.html"
    34.9  
   34.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   34.11  WGET_URL="$WEB_SITE/releases/download/v$VERSION/$TARBALL"
   34.12 +TARBALL_MD5="2882e3179748cc9f9c23ec593d6adc8d"
   34.13  
   34.14  BUILD_DEPENDS="bison gettext help2man indent"
   34.15  
   34.16 -# Rules to configure and make the package.
   34.17 -compile_rules()
   34.18 -{
   34.19 +compile_rules() {
   34.20  	case "$ARCH" in
   34.21  		arm*)
   34.22  			export ac_cv_func_malloc_0_nonnull=yes
   34.23  			export ac_cv_func_realloc_0_nonnull=yes
   34.24  	esac
   34.25  
   34.26 -	./configure \
   34.27 -		--docdir=/usr/share/doc/flex-$VERSION \
   34.28 -		$CONFIGURE_ARGS &&
   34.29 -	make && make install
   34.30 +	# Fix a problem introduced with glibc-2.26
   34.31 +	sed -i "/math.h/a #include <malloc.h>" src/flexdef.h
   34.32 +
   34.33 +	./configure $CONFIGURE_ARGS && make && make install || return 1
   34.34  
   34.35  	ln -s flex $install/usr/bin/lex
   34.36  }
   34.37  
   34.38 -# Rules to gen a SliTaz package suitable for Tazpkg.
   34.39 -genpkg_rules()
   34.40 -{
   34.41 +genpkg_rules() {
   34.42  	copy @std @dev
   34.43  	DEPENDS="bison"
   34.44 +	TAGS="LFS"
   34.45  }
    35.1 --- a/gawk/receipt	Wed Feb 21 18:10:55 2018 +0200
    35.2 +++ b/gawk/receipt	Wed Feb 21 19:48:17 2018 +0200
    35.3 @@ -7,7 +7,7 @@
    35.4  MAINTAINER="pankso@slitaz.org"
    35.5  LICENSE="GPL3"
    35.6  WEB_SITE="http://www.gnu.org/software/gawk/"
    35.7 -HOST_ARCH="i486 arm"
    35.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gawk.html"
    35.9  
   35.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   35.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   35.12 @@ -16,25 +16,23 @@
   35.13  SPLIT="gawk-dev"
   35.14  
   35.15  # Rules to compile & install the temporary toolchain.
   35.16 -cook_tmp_toolchain()
   35.17 -{
   35.18 +cook_tmp_toolchain() {
   35.19  	cd $src
   35.20  	./configure && make && make install
   35.21  }
   35.22  
   35.23 -# Rules to configure and make the package.
   35.24 -compile_rules()
   35.25 -{
   35.26 -	./configure $CONFIGURE_ARGS && make && make install
   35.27 +compile_rules() {
   35.28 +	./configure $CONFIGURE_ARGS && make && make install || return 1
   35.29 +
   35.30 +	cook_pick_docs doc/awkforai.txt doc/*.eps doc/*.pdf doc/*.jpg
   35.31  }
   35.32  
   35.33 -# Rules to gen a SliTaz package suitable for Tazpkg.
   35.34 -genpkg_rules()
   35.35 -{
   35.36 +genpkg_rules() {
   35.37  	case $PACKAGE in
   35.38  		gawk)
   35.39  			copy @std
   35.40  			DEPENDS="readline"
   35.41 +			TAGS="LFS"
   35.42  			;;
   35.43  		*-dev) copy @dev;;
   35.44  	esac
    36.1 --- a/gcc/receipt	Wed Feb 21 18:10:55 2018 +0200
    36.2 +++ b/gcc/receipt	Wed Feb 21 19:48:17 2018 +0200
    36.3 @@ -1,87 +1,99 @@
    36.4  # SliTaz package receipt v2.
    36.5  
    36.6 +# Note, currently first pass is broken. Sorry.
    36.7  PACKAGE="gcc"
    36.8 -VERSION="6.3.0"
    36.9 +VERSION="7.3.0"
   36.10  CATEGORY="development"
   36.11  SHORT_DESC="The GNU Compiler Collection"
   36.12  MAINTAINER="pankso@slitaz.org"
   36.13  LICENSE="GPL2"
   36.14  WEB_SITE="http://gcc.gnu.org/"
   36.15 -#HOST_ARCH="i486 arm"
   36.16 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gcc.html"
   36.17  
   36.18 -TARBALL="$PACKAGE-$VERSION.tar.bz2"
   36.19 -WGET_URL="ftp://gcc.gnu.org/pub/gcc/releases/gcc-$VERSION/$TARBALL"
   36.20 +TARBALL="$PACKAGE-$VERSION.tar.xz"
   36.21 +WGET_URL="http://ftp.gnu.org/gnu/gcc/gcc-$VERSION/$TARBALL"
   36.22  
   36.23  BUILD_DEPENDS="mpc-library-dev mpfr-dev gmp-dev elfutils-dev zlib-dev"
   36.24  SPLIT="gcc-lib-base gcc-lib-math libgfortran gfortran libgomp libobjc \
   36.25  libatomic gcc"
   36.26  
   36.27 +if [ "$2" == "--first-pass" -o "$3" == "--first-pass" ]; then
   36.28 +	STAGE='first'
   36.29 +	SPLIT=''
   36.30 +fi
   36.31 +
   36.32  compile_rules() {
   36.33  	# Handle cross compilation (native i486/ARM gcc)
   36.34  	case "$ARCH" in
   36.35  		i?86)
   36.36  			ARCH_ARGS="--with-tune=$ARCH"
   36.37  			pkgversion="SliTaz"
   36.38 -			languages="c,c++,objc,fortran" ;;
   36.39 +			languages="c,c++,objc,fortran"
   36.40 +			sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in
   36.41 +			;;
   36.42 +		x86_64)
   36.43 +			ARCH_ARGS=""
   36.44 +			pkgversion="SliTaz64"
   36.45 +			languages="c,c++,objc,fortran"
   36.46 +			sed -i.orig '/m64=/ s|lib64|lib|' gcc/config/i386/t-linux64
   36.47 +			;;
   36.48  		arm*)
   36.49 +			ARCH_ARGS=""
   36.50  			pkgversion="SliTaz ARM"
   36.51 -			languages="c,c++" ;;
   36.52 +			languages="c,c++"
   36.53 +			;;
   36.54  	esac
   36.55  
   36.56 -	# Package slitaz-toolchain use 'cook --options' when rebuilding
   36.57 -	# the full SliTaz toolchain.
   36.58 -	[ "$2" == "--first-pass" ] && opt=$2
   36.59 -	[ "$3" == "--first-pass" ] && opt=$3
   36.60 -
   36.61  	# Use libiberty.a from binutils.
   36.62  	sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in || return 1
   36.63  
   36.64 -	case "$ARCH" in
   36.65 -		i?86) sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in ;;
   36.66 -	esac
   36.67 +	case "$STAGE" in
   36.68 +		first)
   36.69 +			echo "cook: configure GCC for: toolchain first pass"
   36.70  
   36.71 -	#sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in
   36.72 -
   36.73 -	mkdir -p ../gcc-build && cd ../gcc-build
   36.74 -
   36.75 -	# This is the default GCC and we want a native build to cross compile after.
   36.76 -	# SliTaz target i486 host so we need a native i486 build for GCC.
   36.77 -	case "$opt" in
   36.78 -		--first-pass)
   36.79 -			# Used by slitaz-toolchain when rebuilding the full toolchain.
   36.80 -			echo "cook: configure GCC for: toolchain first pass"
   36.81 -			$src/configure \
   36.82 -				--libexecdir=/usr/lib \
   36.83 +			mkdir build
   36.84 +			cd    build
   36.85 +			../configure \
   36.86 +				--with-newlib \
   36.87 +				--without-headers \
   36.88  				--disable-nls \
   36.89 -				--enable-shared \
   36.90 +				--disable-shared \
   36.91 +				--disable-multilib \
   36.92 +				--disable-decimal-float \
   36.93 +				--disable-threads \
   36.94 +				--disable-libatomic \
   36.95 +				--disable-libgomp \
   36.96 +				--disable-libmpx \
   36.97 +				--disable-libquadmath \
   36.98 +				--disable-libssp \
   36.99 +				--disable-libvtv \
  36.100 +				--disable-libstdcxx \
  36.101  				--enable-languages=c,c++ \
  36.102 -				--disable-libstdcxx-pch \
  36.103 -				--enable-__cxa_atexit \
  36.104 -				--enable-clocale=gnu \
  36.105 -				--enable-threads=posix \
  36.106 -				--disable-bootstrap \
  36.107 -				${CONFIGURE_ARGS}
  36.108 +				$CONFIGURE_ARGS
  36.109  				;;
  36.110  		*)
  36.111 -			# Used by default to produce a full featured X86 GCC compiler.
  36.112  			echo "cook: configure GCC for: final/full build"
  36.113 -			$src/configure \
  36.114 -				--libexecdir=/usr/lib \
  36.115 -				--enable-nls \
  36.116 -				--enable-languages=${languages} \
  36.117 -				--enable-shared \
  36.118 +
  36.119 +			mkdir build
  36.120 +			cd    build
  36.121 +			SED=sed \
  36.122 +			../configure \
  36.123 +				--enable-languages=$languages \
  36.124 +				--disable-multilib \
  36.125 +				--disable-bootstrap \
  36.126  				--with-system-zlib \
  36.127 -				--enable-clocale=gnu \
  36.128 -				--enable-objc-gc \
  36.129 -				--enable-__cxa_atexit \
  36.130 -				--enable-lto \
  36.131 -				--enable-threads=posix \
  36.132 -				--disable-bootstrap \
  36.133  				--with-pkgversion="$pkgversion" \
  36.134 -				${CONFIGURE_ARGS} ${ARCH_ARGS}
  36.135 +				$CONFIGURE_ARGS $ARCH_ARGS
  36.136  				;;
  36.137  	esac &&
  36.138 -	make && make install
  36.139 +	make && make install || return 1
  36.140 +
  36.141 +	ln -sv ../usr/bin/cpp $install/lib
  36.142 +	ln -sv gcc $install/usr/bin/cc
  36.143 +	install -v -dm755 $install/usr/lib/bfd-plugins
  36.144 +	ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/$VERSION/liblto_plugin.so \
  36.145 +		$install/usr/lib/bfd-plugins/
  36.146 +
  36.147  
  36.148  	# ARM packages use another libs...
  36.149  	case "$ARCH" in
  36.150 @@ -93,16 +105,38 @@
  36.151  			;;
  36.152  	esac
  36.153  
  36.154 -	# Remove build directory.
  36.155 -	rm -rf $WOK/$PACKAGE/source/$PACKAGE-build
  36.156 -	rm -rf $WOK/$PACKAGE/$PACKAGE-build
  36.157 +
  36.158 +	# Place the debugging symbols for selected libraries in separate files.
  36.159 +	# This debugging information is needed if running regression tests that use valgrind or gdb.
  36.160 +	# http://www.linuxfromscratch.org/lfs/view/stable/chapter06/strippingagain.html
  36.161 +
  36.162 +	[ "$STAGE" == 'first' ] ||
  36.163 +	for i in libquadmath.so.0.0.0 libstdc++.so.6.0.24 libmpx.so.2.0.1 \
  36.164 +		libmpxwrappers.so.2.0.1 libitm.so.1.0.0 libcilkrts.so.5.0.0 \
  36.165 +		libatomic.so.1.2.0; do
  36.166 +		cd $install/usr/lib/
  36.167 +		objcopy --only-keep-debug $i $i.dbg
  36.168 +		strip   --strip-unneeded  $i
  36.169 +		objcopy --add-gnu-debuglink=$i.dbg $i
  36.170 +	done
  36.171  }
  36.172  
  36.173  genpkg_rules() {
  36.174 +	case $STAGE in
  36.175 +		first)
  36.176 +			# single package 'gcc' on the first stage
  36.177 +			copy @std @dev
  36.178 +			DEPENDS="glibc-base gmp mpc-library mpfr zlib binutils elfutils"
  36.179 +			CAT="development|first pass"
  36.180 +			TAGS="LFS compiler C"
  36.181 +			return 0
  36.182 +			;;
  36.183 +	esac
  36.184 +
  36.185  	case $PACKAGE in
  36.186  		gcc-lib-base)
  36.187  			copy libgcc_s.so* libstdc++.so*
  36.188 -			rm $fs/usr/lib/*.py
  36.189 +			rm $fs/usr/lib*/*.py
  36.190  			CAT="libs|base libraries"
  36.191  			DEPENDS="glibc-base"
  36.192  			;;
  36.193 @@ -138,11 +172,11 @@
  36.194  			DEPENDS=" "
  36.195  			;;
  36.196  		gcc)
  36.197 -			copy bin/ lib/ include/ *.py @rm
  36.198 +			copy @std @dev @rm
  36.199  			DEPENDS="gcc-lib-base libgomp libobjc libatomic \
  36.200  			glibc-base gmp mpc-library mpfr zlib   binutils elfutils"
  36.201  			SUGGESTED="python"
  36.202 -			TAGS="compiler C"
  36.203 +			TAGS="LFS compiler C"
  36.204  			;;
  36.205  	esac
  36.206  }
    37.1 --- a/gdbm/receipt	Wed Feb 21 18:10:55 2018 +0200
    37.2 +++ b/gdbm/receipt	Wed Feb 21 19:48:17 2018 +0200
    37.3 @@ -1,23 +1,21 @@
    37.4  # SliTaz package receipt v2.
    37.5  
    37.6  PACKAGE="gdbm"
    37.7 -VERSION="1.12"
    37.8 +VERSION="1.13"
    37.9  CATEGORY="misc"
   37.10  SHORT_DESC="GNU database manager"
   37.11  MAINTAINER="pascal.bellard@slitaz.org"
   37.12  LICENSE="GPL3"
   37.13  WEB_SITE="https://www.gnu.org/software/gdbm"
   37.14 -HOST_ARCH="i486 arm"
   37.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gdbm.html"
   37.16  
   37.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   37.18  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   37.19  
   37.20 -BUILD_DEPENDS="gettext"
   37.21 +BUILD_DEPENDS="gettext readline-dev"
   37.22  SPLIT="gdbm-tools gdbm-dev"
   37.23  
   37.24 -# Rules to configure and make the package.
   37.25 -compile_rules()
   37.26 -{
   37.27 +compile_rules() {
   37.28  	./configure \
   37.29  		--disable-static \
   37.30  		--enable-libgdbm-compat \
   37.31 @@ -25,15 +23,15 @@
   37.32  	make && make install
   37.33  }
   37.34  
   37.35 -# Rules to gen a SliTaz package suitable for Tazpkg.
   37.36 -genpkg_rules()
   37.37 -{
   37.38 +genpkg_rules() {
   37.39  	case $PACKAGE in
   37.40  		gdbm)
   37.41  			copy *.so*
   37.42 +			TAGS="LFS"
   37.43  			;;
   37.44  		gdbm-tools)
   37.45  			copy bin/
   37.46 +			DEPENDS="gdbm ncurses readline"
   37.47  			CAT="misc|tools"
   37.48  			;;
   37.49  		*-dev) copy @dev;;
    38.1 --- a/gettext/receipt	Wed Feb 21 18:10:55 2018 +0200
    38.2 +++ b/gettext/receipt	Wed Feb 21 19:48:17 2018 +0200
    38.3 @@ -7,25 +7,24 @@
    38.4  MAINTAINER="pankso@slitaz.org"
    38.5  LICENSE="GPL3"
    38.6  WEB_SITE="https://www.gnu.org/software/gettext/"
    38.7 -HOST_ARCH="i486 arm"
    38.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gettext.html"
    38.9  
   38.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   38.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   38.12  
   38.13 +BUILD_DEPENDS_arm="attr-dev ncurses-dev libxml2-tools libxml2-dev"
   38.14  BUILD_DEPENDS="libcroco-dev libxml2-dev glib-dev acl-dev"
   38.15 -BUILD_DEPENDS_arm="attr-dev ncurses-dev libxml2-tools libxml2-dev"
   38.16  SPLIT="gettext-base gettext-tools gettext"
   38.17  
   38.18 -# Handle cross compilation. Glibc-locale are installed in cross chroot.
   38.19 -case "$ARCH" in
   38.20 -	arm) ARCH_ARGS="--disable-acl" ;;
   38.21 -esac
   38.22 +compile_rules() {
   38.23 +	case "$ARCH" in
   38.24 +		arm) ARCH_ARGS="--disable-acl";;
   38.25 +	esac
   38.26  
   38.27 -# Rules to configure and make the package.
   38.28 -compile_rules()
   38.29 -{
   38.30 -	./configure $CONFIGURE_ARGS $ARCH_ARGS &&
   38.31 -	make && make install
   38.32 +	fix ld
   38.33 +	./configure $CONFIGURE_ARGS $ARCH_ARGS && make && make install || return 1
   38.34 +
   38.35 +	chmod 0755 $install/usr/lib/preloadable_libintl.so
   38.36  
   38.37  	# stripped gettext.sh
   38.38  	rm $install/usr/bin/gettext.sh
   38.39 @@ -33,14 +32,11 @@
   38.40  }
   38.41  
   38.42  # Just to be sure when cross compiling, gettext is part of base system.
   38.43 -testsuite()
   38.44 -{
   38.45 +testsuite() {
   38.46  	readelf -h $install/usr/bin/gettext
   38.47  }
   38.48  
   38.49 -# Rules to gen a SliTaz package suitable for Tazpkg.
   38.50 -genpkg_rules()
   38.51 -{
   38.52 +genpkg_rules() {
   38.53  	case $PACKAGE in
   38.54  		gettext-base)
   38.55  			copy gettext gettext.sh envsubst ngettext
   38.56 @@ -51,13 +47,16 @@
   38.57  			copy msgcat msgfmt msgmerge xgettext \
   38.58  			libgettextlib*.so* libgettextsrc*.so*
   38.59  			CAT="libs|tools"
   38.60 -			DEPENDS="acl attr glib libcroco libgomp liblzma libxml2 pcre zlib"
   38.61 +			DEPENDS="acl attr glib libcroco libgomp liblzma libxml2 ncurses \
   38.62 +			pcre zlib"
   38.63  			;;
   38.64  		gettext)
   38.65  			copy @std @dev @rm
   38.66 +			rm -rf $fs/usr/share/doc/ # @dev files here
   38.67  			# Runtime depends, then dev-depends
   38.68  			DEPENDS="gettext-base gettext-tools libcroco liblzma libxml2 \
   38.69  			acl-dev attr-dev libcroco-dev libxml2-dev glib-dev pcre-dev m4"
   38.70 +			TAGS="LFS"
   38.71  			;;
   38.72  	esac
   38.73  }
    39.1 --- a/glibc/receipt	Wed Feb 21 18:10:55 2018 +0200
    39.2 +++ b/glibc/receipt	Wed Feb 21 19:48:17 2018 +0200
    39.3 @@ -1,18 +1,18 @@
    39.4  # SliTaz package receipt v2.
    39.5  
    39.6  PACKAGE="glibc"
    39.7 -VERSION="2.25"
    39.8 +VERSION="2.26"
    39.9  CATEGORY="meta"
   39.10  SHORT_DESC="The GNU C libraries"
   39.11  MAINTAINER="pankso@slitaz.org"
   39.12  LICENSE="GPL2"
   39.13  WEB_SITE="http://www.gnu.org/software/libc/"
   39.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/glibc.html"
   39.15  
   39.16  TARBALL="$PACKAGE-$VERSION.tar.gz"
   39.17  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   39.18  
   39.19 -BUILD_DEPENDS="linux-api-headers autoconf bash gawk gettext bison \
   39.20 -texinfo"
   39.21 +BUILD_DEPENDS="linux-api-headers autoconf bash gawk gettext bison texinfo"
   39.22  # slitaz-i18n should present in wok
   39.23  SPLIT="glibc-base glibc-locale nscd glibc-dev"
   39.24  
   39.25 @@ -21,129 +21,142 @@
   39.26  
   39.27  # Handle multiarch compilation.
   39.28  case "$ARCH" in
   39.29 -	arm*|x86_64) VERSION="2.13";;
   39.30 +	arm*) VERSION="2.13";;
   39.31  esac
   39.32  
   39.33  # Handle multiarch installation.
   39.34  case "$SLITAZ_ARCH" in
   39.35 -	arm*|x86_64) VERSION="2.13";;
   39.36 +	arm*) VERSION="2.13";;
   39.37  esac
   39.38  
   39.39  
   39.40  # Rules to compile & install the temporary toolchain.
   39.41 -cook_tmp_toolchain()
   39.42 -{
   39.43 +cook_tmp_toolchain() {
   39.44  	unset CFLAGS CXXFLAGS
   39.45 -	echo "CFLAGS += -O2 -march=${ARCH/i386/i486} -mtune=${ARCH/i386/i486}" > configparms
   39.46 +	case $ARCH in
   39.47 +		i386)   Arch='i486';;
   39.48 +		x86_64) Arch='nocona';;
   39.49 +		*)      Arch="$ARCH";;
   39.50 +	esac
   39.51 +	echo "CFLAGS += -O2 -march=$Arch -mtune=$Arch" > configparms
   39.52  
   39.53 -	{
   39.54 -		# Build in a separate directory.
   39.55 -		mkdir glibc-build
   39.56 -		cd    glibc-build
   39.57 +	# Build in a separate directory.
   39.58 +	mkdir build
   39.59 +	cd    build
   39.60  
   39.61 -		../configure \
   39.62 -			--host=$HOST_SYSTEM \
   39.63 -			--build=$($src/scripts/config.guess) \
   39.64 -			--disable-profile \
   39.65 -			--enable-add-ons \
   39.66 -			--enable-kernel=2.6.32 \
   39.67 -			--with-headers=/tools/include \
   39.68 -			libc_cv_forced_unwind=yes \
   39.69 -			libc_cv_c_cleanup=yes &&
   39.70 -		make -j1 &&
   39.71 -		make install
   39.72 -	} || return 1
   39.73 +	../configure \
   39.74 +		--host=$HOST_SYSTEM \
   39.75 +		--build=$($src/scripts/config.guess) \
   39.76 +		--disable-profile \
   39.77 +		--enable-add-ons \
   39.78 +		--enable-kernel=3.2 \
   39.79 +		--with-headers=/tools/include \
   39.80 +		libc_cv_forced_unwind=yes \
   39.81 +		libc_cv_c_cleanup=yes &&
   39.82 +	make -j1 &&
   39.83 +	make install || return 1
   39.84  
   39.85  	# Link compiler to this new glibc.
   39.86  	SPECS=$(dirname $($HOST_SYSTEM-gcc -print-libgcc-file-name))/specs
   39.87 -	$HOST_SYSTEM-gcc -dumpspecs | sed \
   39.88 +	$HOST_SYSTEM-gcc -dumpspecs \
   39.89 +	| sed \
   39.90  		-e 's@/lib\(64\)\?/ld@/tools&@g' \
   39.91  		-e "/^\*cpp:$/{n;s,$, -isystem /tools/include,}" > $SPECS
   39.92  	unset SPECS
   39.93  }
   39.94  
   39.95  # Rules to configure and make the package.
   39.96 -compile_rules()
   39.97 -{
   39.98 +compile_rules() {
   39.99  	# Glibc needs ld.so.conf in the install destdir.
  39.100  	mkdir -p $install/etc
  39.101  	touch    $install/etc/ld.so.conf
  39.102  
  39.103  	# Read the INSTALL file in glibc. Also Glibc don't build with -Os flag.
  39.104 -	# --enale-kernel use latest SliTaz Kernel version. From Glibc INSTALL:
  39.105 -	# "The higher the VERSION number is, the less compatibility code is
  39.106 -	# added, and the faster the code gets."
  39.107  	unset CFLAGS CXXFLAGS
  39.108 -	echo "CFLAGS += -O2 -march=${ARCH/i386/i486} -mtune=${ARCH/i386/i486}" > configparms
  39.109 +	case $ARCH in
  39.110 +		i386)   Arch='i486';;
  39.111 +		x86_64) Arch='nocona';;
  39.112 +		*)      Arch="$ARCH";;
  39.113 +	esac
  39.114 +	echo "CFLAGS += -O2 -march=$Arch -mtune=$Arch" > configparms
  39.115  
  39.116 -	{
  39.117 -		mkdir build
  39.118 -		cd    build
  39.119 -		$src/configure \
  39.120 -			--disable-profile \
  39.121 -			--enable-add-ons \
  39.122 -			--enable-obsolete-rpc \
  39.123 -			--enable-kernel=2.6.32 \
  39.124 -			--libexecdir=/usr/lib/glibc \
  39.125 -			--build=$HOST_SYSTEM \
  39.126 -			--host=$HOST_SYSTEM \
  39.127 -			--target=$BUILD_SYSTEM &&
  39.128 -		make -j1 && make install_root=$DESTDIR install
  39.129 -	} || return 1
  39.130 +	# Remove a file that may be left over from a previous build attempt
  39.131 +	rm -f /usr/include/limits.h 2>/dev/null
  39.132 +
  39.133 +	mkdir build
  39.134 +	cd    build
  39.135 +	# --enale-kernel: please respect Kernel version of the build host,
  39.136 +	# put the exact or lower numbers. From Glibc INSTALL:
  39.137 +	# > The higher the VERSION number is, the less compatibility code is
  39.138 +	# > added, and the faster the code gets.
  39.139 +	CC="gcc -isystem /usr/lib/gcc/$BUILD_SYSTEM/$(. $WOK/gcc/receipt; echo $VERSION)/include \
  39.140 +	-isystem /usr/include" \
  39.141 +	../configure \
  39.142 +		--disable-werror \
  39.143 +		--enable-kernel=3.2 \
  39.144 +		--enable-stack-protector=strong \
  39.145 +		libc_cv_slibdir=/lib \
  39.146 +		&&
  39.147 +	make -j1 &&
  39.148 +	touch $install/etc/ld.so.conf &&
  39.149 +	sed '/test-installation/s@$(PERL)@echo not running@' -i ../Makefile &&
  39.150 +	make install_root=$install install || return 1
  39.151  
  39.152  	# nscd
  39.153 -	mkdir -p $install/etc/init.d $install/var/db
  39.154 -	cp $stuff/nscd $install/etc/init.d
  39.155 -	chmod +x $install/etc/init.d/nscd
  39.156 +	cp ../nscd/nscd.conf $install/etc/nscd.conf
  39.157 +	mkdir -p $install/var/cache/nscd $install/var/db
  39.158 +	install -Dm755 $stuff/nscd $install/etc/init.d/nscd
  39.159  
  39.160  	# nsswitch.conf
  39.161  	cp $stuff/nsswitch.conf $install/etc
  39.162  
  39.163 +	# ld.so.conf
  39.164 +	install -Dm644 $stuff/ld.so.conf $install/etc/ld.so.conf
  39.165 +
  39.166  	# If temporary toolchain was previously used, switch to regular toolchain.
  39.167  	if [ -d /tools ]; then
  39.168  		mv /tools/bin/ld /tools/bin/ld-old
  39.169  		mv /tools/$(gcc -dumpmachine)/bin/ld /tools/$(gcc -dumpmachine)/bin/ld-old
  39.170  		mv /tools/bin/ld-new /tools/bin/ld
  39.171  		ln -s /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld
  39.172 -		gcc -dumpspecs | sed -e 's@/tools@@g' \
  39.173 +		gcc -dumpspecs \
  39.174 +		| sed -e 's@/tools@@g' \
  39.175  			-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
  39.176  			-e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
  39.177  			$(dirname $(gcc --print-libgcc-file-name))/specs
  39.178  	fi
  39.179 -}
  39.180  
  39.181 -# i18n
  39.182 -get_locales()
  39.183 -{
  39.184 -	local path=$1
  39.185 -	for i in $DEFAULT_LOCALE; do
  39.186 -		cp $install/$path/i18n/locales/$i $fs/usr/share/i18n/locales
  39.187 +	# Create symlinks to the dynamic loader for LSB compliance.
  39.188 +	case $ARCH in
  39.189 +		i?86)
  39.190 +			ln -sf ld-linux.so.2 $install/lib/ld-lsb.so.3
  39.191 +			;;
  39.192 +		x86_64)
  39.193 +			mkdir -p $install/lib64
  39.194 +			ln -sf ../lib/ld-$VERSION.so $install/lib64/ld-linux-x86-64.so.2
  39.195 +			ln -sf ../lib/ld-$VERSION.so $install/lib64/ld-lsb-x86-64.so.3
  39.196 +			;;
  39.197 +	esac
  39.198 +
  39.199 +	# Place the debugging symbols for selected libraries in separate files.
  39.200 +	# This debugging information is needed if running regression tests that use valgrind or gdb.
  39.201 +	# http://www.linuxfromscratch.org/lfs/view/stable/chapter06/strippingagain.html
  39.202 +
  39.203 +	for i in ld-$VERSION.so libc-$VERSION.so libpthread-$VERSION.so libthread_db-1.0.so; do
  39.204 +		cd $install/lib/
  39.205 +		objcopy --only-keep-debug $i $i.dbg
  39.206 +		strip   --strip-unneeded  $i
  39.207 +		objcopy --add-gnu-debuglink=$i.dbg $i
  39.208  	done
  39.209  }
  39.210  
  39.211 -mk_dirs()
  39.212 -{
  39.213 -	mkdir -p \
  39.214 -		$fs/etc \
  39.215 -		$fs/lib \
  39.216 -		$fs/usr/bin \
  39.217 -		$fs/usr/lib/gconv \
  39.218 -		$fs/usr/lib/locale \
  39.219 -		$fs/usr/share/zoneinfo/America \
  39.220 -		$fs/usr/share/zoneinfo/Europe \
  39.221 -		$fs/usr/share/i18n/locales \
  39.222 -		$fs/usr/share/i18n/charmaps \
  39.223 -		$fs/usr/share/locale
  39.224 -}
  39.225 -
  39.226 -# Rules to gen a SliTaz package suitable for Tazpkg.
  39.227 -genpkg_rules()
  39.228 -{
  39.229 +genpkg_rules() {
  39.230  	case $PACKAGE in
  39.231  		glibc)
  39.232  			LOCALE=""
  39.233  			CAT="meta|meta-package"
  39.234  			DEPENDS="glibc-base glibc-locale glibc-dev"
  39.235 +			TAGS="LFS"
  39.236  			;;
  39.237  		glibc-base)
  39.238  			case "$ARCH" in
  39.239 @@ -154,13 +167,6 @@
  39.240  					install="/cross/$ARCH/sysroot"
  39.241  					copy libc_nonshared.a libpthread_nonshared.a
  39.242  					;;
  39.243 -				x86_64)
  39.244 -					# EXPERIMENTAL: Glibc is cross compiled by cross to have a
  39.245 -					# toolchain so we can use these files instead of recooking it.
  39.246 -					echo "Using cross compiled Glibc..."
  39.247 -					install="/usr/cross/$ARCH"
  39.248 -					copy libc_nonshared.a libpthread_nonshared.a
  39.249 -					;;
  39.250  			esac
  39.251  			copy \
  39.252  				ld-*.so*            ld.so*            \
  39.253 @@ -192,20 +198,13 @@
  39.254  				nsswitch.conf \
  39.255  				$DEFAULT_LOCALE
  39.256  
  39.257 -			case "$ARCH" in
  39.258 -				x86_64)
  39.259 -					# Fix libraries search path
  39.260 -					sed -i "s|/usr/cross/$ARCH||g" $fs/lib/libc.so
  39.261 -					sed -i "s|/usr/cross/$ARCH||g" $fs/lib/libpthread.so
  39.262 -					;;
  39.263 -			esac
  39.264 +			find $fs -type f -name '*.so.dbg' -delete
  39.265 +
  39.266  			CAT="base-system|minimal libraries and UTF-8 support for SliTaz"
  39.267  			DEPENDS=" "
  39.268  			;;
  39.269  		glibc-locale)
  39.270 -			copy gconv/ locale/ i18n/ iconv tzselect
  39.271 -			# Remove glibc-base files
  39.272 -			remove_already_packed
  39.273 +			copy gconv/ locale/ i18n/ iconv tzselect @rm # Remove glibc-base files
  39.274  
  39.275  			# Remove files provided by locale-pack.
  39.276  			. $WOK/slitaz-i18n/stuff/locale-pack.conf
  39.277 @@ -219,13 +218,12 @@
  39.278  			DEPENDS="glibc-base"
  39.279  			;;
  39.280  		nscd)
  39.281 -			copy /var/db/ nscd getent nscd.conf
  39.282 +			copy /var/db/ /var/cache/nscd/ nscd getent nscd.conf
  39.283  			CAT="base-system|name-server caching daemon"
  39.284  			DEPENDS=" "
  39.285  			;;
  39.286  		glibc-dev)
  39.287 -			copy @std @dev
  39.288 -			remove_already_packed
  39.289 +			copy @std @dev @rm
  39.290  			DEPENDS="glibc-base"
  39.291  			;;
  39.292  	esac
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/glibc/stuff/ld.so.conf	Wed Feb 21 19:48:17 2018 +0200
    40.3 @@ -0,0 +1,4 @@
    40.4 +# Begin /etc/ld.so.conf
    40.5 +/usr/local/lib
    40.6 +/opt/lib
    40.7 +
    41.1 --- a/glibc/stuff/patches/glibc-2.25-fhs-1.patch	Wed Feb 21 18:10:55 2018 +0200
    41.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.3 @@ -1,72 +0,0 @@
    41.4 -Submitted By:            Armin K. <krejzi at email dot com>
    41.5 -Date:                    2013-02-11
    41.6 -Initial Package Version: 2.17
    41.7 -Upstream Status:         Not Applicable
    41.8 -Origin:                  Self
    41.9 -Description:             This patch removes references to /var/db directory which is not part
   41.10 -                         of FHS and replaces them with more suitable directories in /var
   41.11 -                         hierarchy - /var/cache/nscd for nscd and /var/lib/nss_db for nss_db.
   41.12 -
   41.13 ---- a/Makeconfig	2012-12-25 04:02:13.000000000 +0100
   41.14 -+++ b/Makeconfig	2013-02-11 01:32:32.500667439 +0100
   41.15 -@@ -250,7 +250,7 @@
   41.16 - 
   41.17 - # Directory for the database files and Makefile for nss_db.
   41.18 - ifndef vardbdir
   41.19 --vardbdir = $(localstatedir)/db
   41.20 -+vardbdir = $(localstatedir)/lib/nss_db
   41.21 - endif
   41.22 - inst_vardbdir = $(install_root)$(vardbdir)
   41.23 - 
   41.24 ---- a/nscd/nscd.h	2012-12-25 04:02:13.000000000 +0100
   41.25 -+++ b/nscd/nscd.h	2013-02-11 01:32:32.500667439 +0100
   41.26 -@@ -112,11 +112,11 @@
   41.27 - 
   41.28 - 
   41.29 - /* Paths of the file for the persistent storage.  */
   41.30 --#define _PATH_NSCD_PASSWD_DB	"/var/db/nscd/passwd"
   41.31 --#define _PATH_NSCD_GROUP_DB	"/var/db/nscd/group"
   41.32 --#define _PATH_NSCD_HOSTS_DB	"/var/db/nscd/hosts"
   41.33 --#define _PATH_NSCD_SERVICES_DB	"/var/db/nscd/services"
   41.34 --#define _PATH_NSCD_NETGROUP_DB	"/var/db/nscd/netgroup"
   41.35 -+#define _PATH_NSCD_PASSWD_DB	"/var/cache/nscd/passwd"
   41.36 -+#define _PATH_NSCD_GROUP_DB	"/var/cache/nscd/group"
   41.37 -+#define _PATH_NSCD_HOSTS_DB	"/var/cache/nscd/hosts"
   41.38 -+#define _PATH_NSCD_SERVICES_DB	"/var/cache/nscd/services"
   41.39 -+#define _PATH_NSCD_NETGROUP_DB	"/var/cache/nscd/netgroup"
   41.40 - 
   41.41 - /* Path used when not using persistent storage.  */
   41.42 - #define _PATH_NSCD_XYZ_DB_TMP	"/var/run/nscd/dbXXXXXX"
   41.43 ---- a/nss/db-Makefile	2012-12-25 04:02:13.000000000 +0100
   41.44 -+++ b/nss/db-Makefile	2013-02-11 01:32:32.500667439 +0100
   41.45 -@@ -22,7 +22,7 @@
   41.46 - 		       /etc/rpc /etc/services /etc/shadow /etc/gshadow \
   41.47 - 		       /etc/netgroup)
   41.48 - 
   41.49 --VAR_DB = /var/db
   41.50 -+VAR_DB = /var/lib/nss_db
   41.51 - 
   41.52 - AWK = awk
   41.53 - MAKEDB = makedb --quiet
   41.54 ---- a/sysdeps/generic/paths.h	2012-12-25 04:02:13.000000000 +0100
   41.55 -+++ b/sysdeps/generic/paths.h	2013-02-11 01:32:32.500667439 +0100
   41.56 -@@ -68,7 +68,7 @@
   41.57 - /* Provide trailing slash, since mostly used for building pathnames. */
   41.58 - #define	_PATH_DEV	"/dev/"
   41.59 - #define	_PATH_TMP	"/tmp/"
   41.60 --#define	_PATH_VARDB	"/var/db/"
   41.61 -+#define	_PATH_VARDB	"/var/lib/nss_db/"
   41.62 - #define	_PATH_VARRUN	"/var/run/"
   41.63 - #define	_PATH_VARTMP	"/var/tmp/"
   41.64 - 
   41.65 ---- a/sysdeps/unix/sysv/linux/paths.h	2012-12-25 04:02:13.000000000 +0100
   41.66 -+++ b/sysdeps/unix/sysv/linux/paths.h	2013-02-11 01:32:32.504000831 +0100
   41.67 -@@ -68,7 +68,7 @@
   41.68 - /* Provide trailing slash, since mostly used for building pathnames. */
   41.69 - #define	_PATH_DEV	"/dev/"
   41.70 - #define	_PATH_TMP	"/tmp/"
   41.71 --#define	_PATH_VARDB	"/var/db/"
   41.72 -+#define	_PATH_VARDB	"/var/lib/nss_db/"
   41.73 - #define	_PATH_VARRUN	"/var/run/"
   41.74 - #define	_PATH_VARTMP	"/var/tmp/"
   41.75 - 
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/glibc/stuff/patches/glibc-2.26-fhs-1.patch	Wed Feb 21 19:48:17 2018 +0200
    42.3 @@ -0,0 +1,72 @@
    42.4 +Submitted By:            Armin K. <krejzi at email dot com>
    42.5 +Date:                    2013-02-11
    42.6 +Initial Package Version: 2.17
    42.7 +Upstream Status:         Not Applicable
    42.8 +Origin:                  Self
    42.9 +Description:             This patch removes references to /var/db directory which is not part
   42.10 +                         of FHS and replaces them with more suitable directories in /var
   42.11 +                         hierarchy - /var/cache/nscd for nscd and /var/lib/nss_db for nss_db.
   42.12 +
   42.13 +--- a/Makeconfig	2012-12-25 04:02:13.000000000 +0100
   42.14 ++++ b/Makeconfig	2013-02-11 01:32:32.500667439 +0100
   42.15 +@@ -250,7 +250,7 @@
   42.16 + 
   42.17 + # Directory for the database files and Makefile for nss_db.
   42.18 + ifndef vardbdir
   42.19 +-vardbdir = $(localstatedir)/db
   42.20 ++vardbdir = $(localstatedir)/lib/nss_db
   42.21 + endif
   42.22 + inst_vardbdir = $(install_root)$(vardbdir)
   42.23 + 
   42.24 +--- a/nscd/nscd.h	2012-12-25 04:02:13.000000000 +0100
   42.25 ++++ b/nscd/nscd.h	2013-02-11 01:32:32.500667439 +0100
   42.26 +@@ -112,11 +112,11 @@
   42.27 + 
   42.28 + 
   42.29 + /* Paths of the file for the persistent storage.  */
   42.30 +-#define _PATH_NSCD_PASSWD_DB	"/var/db/nscd/passwd"
   42.31 +-#define _PATH_NSCD_GROUP_DB	"/var/db/nscd/group"
   42.32 +-#define _PATH_NSCD_HOSTS_DB	"/var/db/nscd/hosts"
   42.33 +-#define _PATH_NSCD_SERVICES_DB	"/var/db/nscd/services"
   42.34 +-#define _PATH_NSCD_NETGROUP_DB	"/var/db/nscd/netgroup"
   42.35 ++#define _PATH_NSCD_PASSWD_DB	"/var/cache/nscd/passwd"
   42.36 ++#define _PATH_NSCD_GROUP_DB	"/var/cache/nscd/group"
   42.37 ++#define _PATH_NSCD_HOSTS_DB	"/var/cache/nscd/hosts"
   42.38 ++#define _PATH_NSCD_SERVICES_DB	"/var/cache/nscd/services"
   42.39 ++#define _PATH_NSCD_NETGROUP_DB	"/var/cache/nscd/netgroup"
   42.40 + 
   42.41 + /* Path used when not using persistent storage.  */
   42.42 + #define _PATH_NSCD_XYZ_DB_TMP	"/var/run/nscd/dbXXXXXX"
   42.43 +--- a/nss/db-Makefile	2012-12-25 04:02:13.000000000 +0100
   42.44 ++++ b/nss/db-Makefile	2013-02-11 01:32:32.500667439 +0100
   42.45 +@@ -22,7 +22,7 @@
   42.46 + 		       /etc/rpc /etc/services /etc/shadow /etc/gshadow \
   42.47 + 		       /etc/netgroup)
   42.48 + 
   42.49 +-VAR_DB = /var/db
   42.50 ++VAR_DB = /var/lib/nss_db
   42.51 + 
   42.52 + AWK = awk
   42.53 + MAKEDB = makedb --quiet
   42.54 +--- a/sysdeps/generic/paths.h	2012-12-25 04:02:13.000000000 +0100
   42.55 ++++ b/sysdeps/generic/paths.h	2013-02-11 01:32:32.500667439 +0100
   42.56 +@@ -68,7 +68,7 @@
   42.57 + /* Provide trailing slash, since mostly used for building pathnames. */
   42.58 + #define	_PATH_DEV	"/dev/"
   42.59 + #define	_PATH_TMP	"/tmp/"
   42.60 +-#define	_PATH_VARDB	"/var/db/"
   42.61 ++#define	_PATH_VARDB	"/var/lib/nss_db/"
   42.62 + #define	_PATH_VARRUN	"/var/run/"
   42.63 + #define	_PATH_VARTMP	"/var/tmp/"
   42.64 + 
   42.65 +--- a/sysdeps/unix/sysv/linux/paths.h	2012-12-25 04:02:13.000000000 +0100
   42.66 ++++ b/sysdeps/unix/sysv/linux/paths.h	2013-02-11 01:32:32.504000831 +0100
   42.67 +@@ -68,7 +68,7 @@
   42.68 + /* Provide trailing slash, since mostly used for building pathnames. */
   42.69 + #define	_PATH_DEV	"/dev/"
   42.70 + #define	_PATH_TMP	"/tmp/"
   42.71 +-#define	_PATH_VARDB	"/var/db/"
   42.72 ++#define	_PATH_VARDB	"/var/lib/nss_db/"
   42.73 + #define	_PATH_VARRUN	"/var/run/"
   42.74 + #define	_PATH_VARTMP	"/var/tmp/"
   42.75 + 
    43.1 --- a/glibc/stuff/patches/glibc-po.patch	Wed Feb 21 18:10:55 2018 +0200
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,249 +0,0 @@
    43.4 -warning: internationalized messages should not contain the '\v' escape sequence
    43.5 -
    43.6 ---- a/po/cs.po
    43.7 -+++ b/po/cs.po
    43.8 -@@ -153,7 +153,8 @@
    43.9 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.10 - "is -, output is written to standard output.\n"
   43.11 - msgstr ""
   43.12 --"Generuje katalog zpráv.\vJe-li VSTUPNÍ_SOUBOR -, vstup bude načten ze standardního vstupu.\n"
   43.13 -+"Generuje katalog zpráv.\n"
   43.14 -+"Je-li VSTUPNÍ_SOUBOR -, vstup bude načten ze standardního vstupu.\n"
   43.15 - "Je-li VÝSTUPNÍ_SOUBOR -, výstup bude zapsán na standardní výstup.\n"
   43.16 - 
   43.17 - #: catgets/gencat.c:123
   43.18 ---- a/po/da.po
   43.19 -+++ b/po/da.po
   43.20 -@@ -131,7 +131,8 @@
   43.21 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.22 - "is -, output is written to standard output.\n"
   43.23 - msgstr ""
   43.24 --"Generér meddelelseskatalog.\vHvis INDFIL er '-' læses inddata fra standard ind.\n"
   43.25 -+"Generér meddelelseskatalog.\n"
   43.26 -+"Hvis INDFIL er '-' læses inddata fra standard ind.\n"
   43.27 - "Hvis UDFIL er '-' skrives uddata til standard ud.\n"
   43.28 - 
   43.29 - #: catgets/gencat.c:123
   43.30 ---- a/po/de.po
   43.31 -+++ b/po/de.po
   43.32 -@@ -131,7 +131,8 @@
   43.33 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.34 - "is -, output is written to standard output.\n"
   43.35 - msgstr ""
   43.36 --"Einen Message-Katalog generieren.\vWenn als INPUT-FILE - angegeben wird, wird\n"
   43.37 -+"Einen Message-Katalog generieren.\n"
   43.38 -+"Wenn als INPUT-FILE - angegeben wird, wird\n"
   43.39 - "von der Standardeingabe gelesen.  Wenn die OUTPUT-FILE - ist, wird auf die\n"
   43.40 - "Standardausgabe geschrieben.\n"
   43.41 - 
   43.42 ---- a/po/en_GB.po
   43.43 -+++ b/po/en_GB.po
   43.44 -@@ -1878,11 +1878,12 @@
   43.45 - 
   43.46 - #: catgets/gencat.c:116
   43.47 - msgid ""
   43.48 --"Generate message catalog.\\vIf INPUT-FILE is -, input is read from standard "
   43.49 -+"Generate message catalog.\vIf INPUT-FILE is -, input is read from standard "
   43.50 - "input.  If OUTPUT-FILE\n"
   43.51 - "is -, output is written to standard output.\n"
   43.52 - msgstr ""
   43.53 --"Generate message catalogue.\\vIf INPUT-FILE is -, input is read from standard "
   43.54 -+"Generate message catalogue.\n"
   43.55 -+"If INPUT-FILE is -, input is read from standard "
   43.56 - "input.  If OUTPUT-FILE\n"
   43.57 - "is -, output is written to standard output.\n"
   43.58 - 
   43.59 ---- a/po/eo.po
   43.60 -+++ a/po/eo.po
   43.61 -@@ -138,7 +138,8 @@
   43.62 - "is -, output is written to standard output.\n"
   43.63 - msgstr ""
   43.64 - "  \n"
   43.65 --"Generas mesaĝan katalogon.\vSe ENIGDOSIERO estas «-», ĉefenigujo legiĝas.  Se ELIGDOSIERO estas «-», la eligo skribiĝas al ĉefeligujo.\n"
   43.66 -+"Generas mesaĝan katalogon.\n"
   43.67 -+"Se ENIGDOSIERO estas «-», ĉefenigujo legiĝas.  Se ELIGDOSIERO estas «-», la eligo skribiĝas al ĉefeligujo.\n"
   43.68 - 
   43.69 - #: catgets/gencat.c:123
   43.70 - msgid ""
   43.71 ---- a/po/es.po
   43.72 -+++ b/po/es.po
   43.73 -@@ -151,7 +151,8 @@
   43.74 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.75 - "is -, output is written to standard output.\n"
   43.76 - msgstr ""
   43.77 --"Genera un catálogo de mensajes.\vSi FICHERO-ENTRADA es -, la entrada\n"
   43.78 -+"Genera un catálogo de mensajes.\n"
   43.79 -+"Si FICHERO-ENTRADA es -, la entrada\n"
   43.80 - "se lee de la entrada estándar. Si FICHERO-SALIDA es -, el resultado se\n"
   43.81 - "escribe en la salida estándar.\n"
   43.82 - 
   43.83 ---- a/po/fi.po
   43.84 -+++ b/po/fi.po
   43.85 -@@ -151,7 +151,8 @@
   43.86 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.87 - "is -, output is written to standard output.\n"
   43.88 - msgstr ""
   43.89 --"Luo viestikatalogi.\vJos SYÖTETIEDOSTO on -, syöte luetaan vakiosyötteestä.  Jos TULOSTIEDOSTO\n"
   43.90 -+"Luo viestikatalogi.\n"
   43.91 -+"Jos SYÖTETIEDOSTO on -, syöte luetaan vakiosyötteestä.  Jos TULOSTIEDOSTO\n"
   43.92 - "on -, tuloste kirjoitetaan vakiotulosteeseen.\n"
   43.93 - 
   43.94 - #: catgets/gencat.c:123
   43.95 ---- a/po/fr.po
   43.96 -+++ b/po/fr.po
   43.97 -@@ -136,7 +136,8 @@
   43.98 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
   43.99 - "is -, output is written to standard output.\n"
  43.100 - msgstr ""
  43.101 --"Génère le catalogue de messages.\vSi le FICHIER_D_ENTRÉE est -, l'entrée est lue depuis l'entrée standard.\n"
  43.102 -+"Génère le catalogue de messages.\n"
  43.103 -+"Si le FICHIER_D_ENTRÉE est -, l'entrée est lue depuis l'entrée standard.\n"
  43.104 - "Si le FICHIER_DE_SORTIE est -, la sortie est dirigée sur la sortie standard.\n"
  43.105 - 
  43.106 - #: catgets/gencat.c:123
  43.107 ---- a/po/hr.po
  43.108 -+++ b/po/hr.po
  43.109 -@@ -132,7 +132,9 @@
  43.110 - msgid ""
  43.111 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.112 - "is -, output is written to standard output.\n"
  43.113 --msgstr "Napravi katalog poruka.\vAko je ULAZNA-DATOTEKA -, ulaz se čita sa standardnog ulaza. Ako je IZLAZNA-DATOTEKA -, izlaz se ispisuje na standardni izlaz.\n"
  43.114 -+msgstr ""
  43.115 -+"Napravi katalog poruka.\n"
  43.116 -+"Ako je ULAZNA-DATOTEKA -, ulaz se čita sa standardnog ulaza. Ako je IZLAZNA-DATOTEKA -, izlaz se ispisuje na standardni izlaz.\n"
  43.117 - 
  43.118 - #: catgets/gencat.c:123
  43.119 - msgid ""
  43.120 ---- a/po/hu.po
  43.121 -+++ b/po/hu.po
  43.122 -@@ -132,7 +132,8 @@
  43.123 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.124 - "is -, output is written to standard output.\n"
  43.125 - msgstr ""
  43.126 --"Üzenetkatalógus előállítása\v Ha a BEMENETIFÁJL a -, akkor a szabványos bemenetet olvassa. Ha a \n"
  43.127 -+"Üzenetkatalógus előállítása\n"
  43.128 -+"Ha a BEMENETIFÁJL a -, akkor a szabványos bemenetet olvassa. Ha a \n"
  43.129 - "KIMENETIFÁJL a -, akkor a szabványos kimenetre ír.\n"
  43.130 - 
  43.131 - #: catgets/gencat.c:123
  43.132 ---- a/po/ia.po
  43.133 -+++ b/po/ia.po
  43.134 -@@ -131,7 +131,8 @@
  43.135 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.136 - "is -, output is written to standard output.\n"
  43.137 - msgstr ""
  43.138 --"Generar un catalogo de messages.\vSi FILE-INPUT es -, le entrata se lege del input standard.\n"
  43.139 -+"Generar un catalogo de messages.\n"
  43.140 -+"Si FILE-INPUT es -, le entrata se lege del input standard.\n"
  43.141 - "Si FILE-OUTPUT es -, le resultato se scribe al output standard.\n"
  43.142 - 
  43.143 - #: catgets/gencat.c:123
  43.144 ---- a/po/it.po
  43.145 -+++ b/po/it.po
  43.146 -@@ -143,7 +143,8 @@
  43.147 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.148 - "is -, output is written to standard output.\n"
  43.149 - msgstr ""
  43.150 --"Genera un catalogo di messaggi.\vSe FILE-INPUT è -, l'input è letto dallo standard input.\n"
  43.151 -+"Genera un catalogo di messaggi.\n"
  43.152 -+"Se FILE-INPUT è -, l'input è letto dallo standard input.\n"
  43.153 - "Se FILE-OUTPUT è -, l'output è scritto sullo standard output.\n"
  43.154 - 
  43.155 - #: catgets/gencat.c:123
  43.156 ---- a/po/nl.po
  43.157 -+++ b/po/nl.po
  43.158 -@@ -145,7 +145,8 @@
  43.159 - "is -, output is written to standard output.\n"
  43.160 - msgstr ""
  43.161 - "  \n"
  43.162 --"Een berichtencatalogus genereren.\vAls INVOERBESTAND '-' is, wordt van standaardinvoer gelezen.\n"
  43.163 -+"Een berichtencatalogus genereren.\n"
  43.164 -+"Als INVOERBESTAND '-' is, wordt van standaardinvoer gelezen.\n"
  43.165 - "Als UITVOERBESTAND '-' is, wordt naar standaarduitvoer geschreven.\n"
  43.166 - 
  43.167 - #: catgets/gencat.c:123
  43.168 ---- a/po/pl.po
  43.169 -+++ b/po/pl.po
  43.170 -@@ -131,7 +131,8 @@
  43.171 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.172 - "is -, output is written to standard output.\n"
  43.173 - msgstr ""
  43.174 --"Generowanie katalogu komunikatów.\vJeśli PLIK-WE to -, dane są czytane ze standardowego wejścia. Jeśli PLIK-WY\n"
  43.175 -+"Generowanie katalogu komunikatów.\n"
  43.176 -+"Jeśli PLIK-WE to -, dane są czytane ze standardowego wejścia. Jeśli PLIK-WY\n"
  43.177 - "to -, dane są zapisywane na standardowe wyjście.\n"
  43.178 - 
  43.179 - #: catgets/gencat.c:123
  43.180 ---- a/po/ru.po
  43.181 -+++ b/po/ru.po
  43.182 -@@ -138,7 +138,8 @@
  43.183 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.184 - "is -, output is written to standard output.\n"
  43.185 - msgstr ""
  43.186 --"Генерирует каталог сообщений.\vЕсли ВХОДНОЙ-ФАЙЛ задан как -, читает стандартный ввод.  Если\n"
  43.187 -+"Генерирует каталог сообщений.\n"
  43.188 -+"Если ВХОДНОЙ-ФАЙЛ задан как -, читает стандартный ввод.  Если\n"
  43.189 - "ВЫХОДНОЙ-ФАЙЛ задан как -, результат печатается на стандартный вывод.\n"
  43.190 - 
  43.191 - #: catgets/gencat.c:123
  43.192 ---- a/po/sl.po
  43.193 -+++ b/po/sl.po
  43.194 -@@ -131,7 +131,9 @@
  43.195 - msgid ""
  43.196 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.197 - "is -, output is written to standard output.\n"
  43.198 --msgstr "Ustvari katalog sporočil.\vČe je VHODNA_DATOTEKA enaka -, se vhod bere s standardnega vhoda. Če je IZHODNA_DATOTEKA enaka -, se izhod zapisuje na standardni izhod.\n"
  43.199 -+msgstr ""
  43.200 -+"Ustvari katalog sporočil.\n"
  43.201 -+"Če je VHODNA_DATOTEKA enaka -, se vhod bere s standardnega vhoda. Če je IZHODNA_DATOTEKA enaka -, se izhod zapisuje na standardni izhod.\n"
  43.202 - 
  43.203 - #: catgets/gencat.c:123
  43.204 - msgid ""
  43.205 ---- a/po/sv.po
  43.206 -+++ b/po/sv.po
  43.207 -@@ -131,7 +131,8 @@
  43.208 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.209 - "is -, output is written to standard output.\n"
  43.210 - msgstr ""
  43.211 --"Skapa meddelandekatalog.\vOm INFIL är - så läses standard in.  Om UTFIL\n"
  43.212 -+"Skapa meddelandekatalog.\n"
  43.213 -+"Om INFIL är - så läses standard in.  Om UTFIL\n"
  43.214 - "är - så skrivs resultatet till standard ut.\n"
  43.215 - 
  43.216 - #: catgets/gencat.c:123
  43.217 ---- a/po/uk.po
  43.218 -+++ b/po/uk.po
  43.219 -@@ -133,7 +133,8 @@
  43.220 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.221 - "is -, output is written to standard output.\n"
  43.222 - msgstr ""
  43.223 --"Створити каталог повідомлень.\vЯкщо як файл ВХІДНИЙ-ФАЙЛ\n"
  43.224 -+"Створити каталог повідомлень.\n"
  43.225 -+"Якщо як файл ВХІДНИЙ-ФАЙЛ\n"
  43.226 - "вказано -, вивід відбуватиметься у стандартний вивід.\n"
  43.227 - 
  43.228 - #: catgets/gencat.c:123
  43.229 ---- a/po/zh_CN.po
  43.230 -+++ b/po/zh_CN.po
  43.231 -@@ -137,7 +137,8 @@
  43.232 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.233 - "is -, output is written to standard output.\n"
  43.234 - msgstr ""
  43.235 --"产生消息 catelog。\\v如果输入文件名是 -, 将从标准输入读取输入。\n"
  43.236 -+"产生消息 catelog。\n"
  43.237 -+"如果输入文件名是 -, 将从标准输入读取输入。\n"
  43.238 - "如果输出文件名是 -, 则输出将写到标准输出去。\n"
  43.239 - 
  43.240 - #: catgets/gencat.c:123
  43.241 ---- a/po/zh_TW.po
  43.242 -+++ b/po/zh_TW.po
  43.243 -@@ -134,7 +134,8 @@
  43.244 - "Generate message catalog.\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n"
  43.245 - "is -, output is written to standard output.\n"
  43.246 - msgstr ""
  43.247 --"產生訊息 catelog。\\v如果輸入檔名是 -, 將從標準輸入讀取輸入。\n"
  43.248 -+"產生訊息 catelog。\n"
  43.249 -+"如果輸入檔名是 -, 將從標準輸入讀取輸入。\n"
  43.250 - "如果輸出檔名是 -, 則輸出將寫到標準輸出去。\n"
  43.251 - 
  43.252 - #: catgets/gencat.c:123
    44.1 --- a/glibc/stuff/patches/series	Wed Feb 21 18:10:55 2018 +0200
    44.2 +++ b/glibc/stuff/patches/series	Wed Feb 21 19:48:17 2018 +0200
    44.3 @@ -1,2 +1,1 @@
    44.4 -glibc-2.25-fhs-1.patch
    44.5 -glibc-po.patch
    44.6 +glibc-2.26-fhs-1.patch
    45.1 --- a/gmp/receipt	Wed Feb 21 18:10:55 2018 +0200
    45.2 +++ b/gmp/receipt	Wed Feb 21 19:48:17 2018 +0200
    45.3 @@ -7,7 +7,7 @@
    45.4  MAINTAINER="pankso@slitaz.org"
    45.5  LICENSE="GPL3"
    45.6  WEB_SITE="https://gmplib.org/"
    45.7 -HOST_ARCH="i486 arm"
    45.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gmp.html"
    45.9  
   45.10  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   45.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   45.12 @@ -15,20 +15,20 @@
   45.13  BUILD_DEPENDS="binutils m4 ncurses-dev readline-dev texinfo"
   45.14  SPLIT="gmp gmp-dev"
   45.15  
   45.16 -# Rules to configure and make the package.
   45.17 -compile_rules()
   45.18 -{
   45.19 +compile_rules() {
   45.20 +	# Create generic libraries
   45.21 +	cp -v configfsf.guess config.guess
   45.22 +	cp -v configfsf.sub   config.sub
   45.23 +
   45.24  	./configure \
   45.25  		--enable-cxx \
   45.26  		--disable-static \
   45.27 -		--docdir=/usr/share/doc/gmp-$VERSION \
   45.28  		$CONFIGURE_ARGS &&
   45.29  	# -j > 1 make install fails.
   45.30  	make && make html && make install && make install-html
   45.31  }
   45.32  
   45.33 -testsuite()
   45.34 -{
   45.35 +testsuite() {
   45.36  	checklog=$(mktemp)
   45.37  	make check 2>&1 | tee $checklog
   45.38  	pass=$(awk '/# PASS:/{total+=$3} ; END{print total}' $checklog)
   45.39 @@ -36,11 +36,12 @@
   45.40  	rm $checklog
   45.41  }
   45.42  
   45.43 -# Rules to gen a SliTaz package suitable for Tazpkg.
   45.44 -genpkg_rules()
   45.45 -{
   45.46 +genpkg_rules() {
   45.47  	case $PACKAGE in
   45.48 -		gmp)   copy @std;;
   45.49 +		gmp)
   45.50 +			copy @std
   45.51 +			TAGS="LFS"
   45.52 +			;;
   45.53  		*-dev) copy @dev;;
   45.54  	esac
   45.55  }
    46.1 --- a/gperf/receipt	Wed Feb 21 18:10:55 2018 +0200
    46.2 +++ b/gperf/receipt	Wed Feb 21 19:48:17 2018 +0200
    46.3 @@ -1,28 +1,22 @@
    46.4  # SliTaz package receipt v2.
    46.5  
    46.6  PACKAGE="gperf"
    46.7 -VERSION="3.0.4"
    46.8 +VERSION="3.1"
    46.9  CATEGORY="development"
   46.10  SHORT_DESC="GNU gperf is a perfect hash function generator"
   46.11  MAINTAINER="pankso@slitaz.org"
   46.12  LICENSE="GPL3"
   46.13  WEB_SITE="https://www.gnu.org/software/gperf/"
   46.14 -HOST_ARCH="i486 arm"
   46.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gperf.html"
   46.16  
   46.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   46.18  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   46.19  
   46.20 -# Rules to configure and make the package.
   46.21 -compile_rules()
   46.22 -{
   46.23 -	./configure \
   46.24 -		--docdir=/usr/share/doc/gperf-$VERSION \
   46.25 -		$CONFIGURE_ARGS &&
   46.26 -	make && make install
   46.27 +compile_rules() {
   46.28 +	./configure $CONFIGURE_ARGS && make && make install
   46.29  }
   46.30  
   46.31 -# Rules to gen a SliTaz package suitable for Tazpkg.
   46.32 -genpkg_rules()
   46.33 -{
   46.34 +genpkg_rules() {
   46.35  	copy @std
   46.36 +	TAGS="LFS"
   46.37  }
    47.1 --- a/grep/receipt	Wed Feb 21 18:10:55 2018 +0200
    47.2 +++ b/grep/receipt	Wed Feb 21 19:48:17 2018 +0200
    47.3 @@ -1,30 +1,28 @@
    47.4  # SliTaz package receipt v2.
    47.5  
    47.6  PACKAGE="grep"
    47.7 -VERSION="3.0"
    47.8 +VERSION="3.1"
    47.9  CATEGORY="development"
   47.10  SHORT_DESC="GNU Global Regular Expression Print"
   47.11  MAINTAINER="paul@slitaz.org"
   47.12  LICENSE="GPL3"
   47.13  WEB_SITE="https://www.gnu.org/software/grep/"
   47.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/grep.html"
   47.15  
   47.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   47.17  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   47.18  
   47.19  BUILD_DEPENDS="pcre-dev perl gettext"
   47.20  
   47.21 -# Rules to configure and make the package.
   47.22 -compile_rules()
   47.23 -{
   47.24 +compile_rules() {
   47.25  	./configure \
   47.26  		--bindir=/bin \
   47.27  		$CONFIGURE_ARGS &&
   47.28  	make && make install
   47.29  }
   47.30  
   47.31 -# Rules to gen a SliTaz package suitable for Tazpkg.
   47.32 -genpkg_rules()
   47.33 -{
   47.34 +genpkg_rules() {
   47.35  	copy @std
   47.36  	DEPENDS="pcre"
   47.37 +	TAGS="LFS"
   47.38  }
    48.1 --- a/groff/receipt	Wed Feb 21 18:10:55 2018 +0200
    48.2 +++ b/groff/receipt	Wed Feb 21 19:48:17 2018 +0200
    48.3 @@ -1,30 +1,28 @@
    48.4 -# SliTaz package receipt.
    48.5 +# SliTaz package receipt v2.
    48.6  
    48.7  PACKAGE="groff"
    48.8  VERSION="1.22.3"
    48.9  CATEGORY="utilities"
   48.10 -SHORT_DESC="The GNU troff text-formatting system."
   48.11 +SHORT_DESC="The GNU troff text-formatting system"
   48.12  MAINTAINER="rocky@slitaz.org"
   48.13  LICENSE="GPL3"
   48.14  WEB_SITE="https://www.gnu.org/software/groff/"
   48.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/groff.html"
   48.16  
   48.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   48.18  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   48.19  
   48.20 -BUILD_DEPENDS="ghostscript perl texinfo"
   48.21 +BUILD_DEPENDS="perl texinfo" # ghostscript
   48.22  
   48.23 -# Rules to configure and make the package.
   48.24 -compile_rules()
   48.25 -{
   48.26 +compile_rules() {
   48.27  	PAGE=A4 ./configure \
   48.28  		--without-x \
   48.29  		$CONFIGURE_ARGS &&
   48.30 -	PATH=$PATH:$src/src/preproc/preconv make &&
   48.31 +	PATH=$PATH:$src/src/preproc/preconv make -j1 &&
   48.32  	make install
   48.33  }
   48.34  
   48.35 -# Rules to gen a SliTaz package suitable for Tazpkg.
   48.36 -genpkg_rules()
   48.37 -{
   48.38 +genpkg_rules() {
   48.39  	copy bin/ groff/
   48.40 +	TAGS="LFS"
   48.41  }
    49.1 --- a/grub2/receipt	Wed Feb 21 18:10:55 2018 +0200
    49.2 +++ b/grub2/receipt	Wed Feb 21 19:48:17 2018 +0200
    49.3 @@ -1,23 +1,22 @@
    49.4  # SliTaz package receipt v2.
    49.5  
    49.6  PACKAGE="grub2"
    49.7 -SOURCE="grub"
    49.8  VERSION="2.02"
    49.9  CATEGORY="base-system"
   49.10  SHORT_DESC="GRUB2 boot loader"
   49.11  MAINTAINER="pascal.bellard@slitaz.org"
   49.12  LICENSE="GPL3"
   49.13 -TARBALL="$SOURCE-$VERSION.tar.xz"
   49.14  WEB_SITE="http://www.gnu.org/software/grub/"
   49.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/grub.html"
   49.16 +
   49.17 +TARBALL="grub-$VERSION.tar.xz"
   49.18  WGET_URL="ftp://ftp.gnu.org/gnu/grub/$TARBALL"
   49.19  
   49.20  BUILD_DEPENDS="flex bison zlib-dev xz-dev freetype-dev ncurses-dev \
   49.21  libusb-compat-dev libusb-dev libdevmapper-dev"
   49.22 -SPLIT="grub2 grub2-efi"
   49.23 +SPLIT="grub2 grub2-efi:efi"
   49.24  
   49.25 -# Rules to configure and make the package.
   49.26 -compile_rules()
   49.27 -{
   49.28 +compile_rules() {
   49.29  	sed -i 's|sys/types.h>|&\n#include <sys/sysmacros.h>|' \
   49.30  		util/getroot.c grub-core/kern/emu/hostdisk.c
   49.31  
   49.32 @@ -25,64 +24,73 @@
   49.33  	sed -i "s/'.b'/& \\&\\& cur_len/" grub-core/lib/crypto.c grub-core/normal/auth.c
   49.34  
   49.35  	# Fixes for flex 2.5.37
   49.36 -	export CFLAGS="-Wno-error=sign-compare -Wno-error=unused-value"       
   49.37 +	export CFLAGS="-Wno-error=sign-compare -Wno-error=unused-value"
   49.38  	sed -i '/#undef gets/{N;s/.*/#ifdef gets\n&\n#endif/}' grub-core/gnulib/stdio*h
   49.39  	sed -i 's/YY_FATAL_ERROR/REMOVED_&/' grub-core/script/yylex.l
   49.40 -	
   49.41 -	#chmod +x install-sh
   49.42 -	./configure --prefix=/usr --sysconfdir=/etc \
   49.43 -	--mandir=/usr/share/man $CONFIGURE_ARGS &&
   49.44 -	make $MAKEFLAGS &&
   49.45 -	make DESTDIR=$DESTDIR install
   49.46  
   49.47 -	export EFI_ARCH=i386
   49.48 -	./configure --prefix=/usr --sysconfdir=/etc \
   49.49 -		--with-platform=efi --target=${EFI_ARCH} --program-prefix="" \
   49.50 -		--mandir=/usr/share/man $CONFIGURE_ARGS &&
   49.51 -	make clean &&
   49.52 -	make $MAKEFLAGS
   49.53 -	cd grub-core
   49.54 -	../grub-mkimage -d . -o ../bootia32.efi -O i386-efi -p /boot/grub \
   49.55 -		ntfs hfs appleldr boot cat efi_gop efi_uga elf fat hfsplus \
   49.56 -		iso9660 linux keylayouts memdisk minicmd part_apple ext2 extcmd \
   49.57 -		xfs xnu part_bsd part_gpt search search_fs_file chain btrfs \
   49.58 -		loadbios loadenv lvm minix minix2 reiserfs memrw mmap msdospart \
   49.59 -		scsi loopback normal configfile gzio all_video efi_gop efi_uga \
   49.60 -		gfxterm gettext echo boot chain
   49.61 -}
   49.62 +	case $SET in
   49.63 +		'')
   49.64 +			#chmod +x install-sh
   49.65 +			./configure $CONFIGURE_ARGS &&
   49.66 +			make $MAKEFLAGS &&
   49.67 +			make DESTDIR=$DESTDIR install || return 1
   49.68  
   49.69 -# Rules to gen a SliTaz package suitable for Tazpkg.
   49.70 -genpkg_rules()
   49.71 -{
   49.72 -	case $PACKAGE in
   49.73 -	grub2)
   49.74 -		DEPENDS="zlib freetype ncurses libusb-compat grep libusb libdevmapper"
   49.75 -		mkdir -p $fs/boot/grub $fs/usr
   49.76 -		cp -a $install/usr/bin $fs/usr
   49.77 -		cp -a $install/usr/sbin $fs/usr
   49.78 -		cp -a $install/usr/share $fs/usr
   49.79 -		cp -a $install/usr/lib $fs/usr
   49.80 -		cp -a $install/etc $fs
   49.81 -		
   49.82 -		# Example config file (grub.cfg).
   49.83 -		cp stuff/example-grub.cfg $fs/boot/grub
   49.84 -		;;
   49.85 -	grub2-efi)
   49.86 -		mkdir -p $fs/boot/efi/boot
   49.87 -		cp $src/bootia32.efi $fs/boot/efi/boot
   49.88 -		;;
   49.89 +			# Example config file (grub.cfg)
   49.90 +			install -Dm0644 $stuff/example-grub.cfg $install/boot/grub/example-grub.cfg
   49.91 +			;;
   49.92 +		efi)
   49.93 +			export EFI_ARCH=i386
   49.94 +			./configure \
   49.95 +				--with-platform=efi \
   49.96 +				--target=$EFI_ARCH \
   49.97 +				--program-prefix="" \
   49.98 +				$CONFIGURE_ARGS &&
   49.99 +			make clean &&
  49.100 +			make $MAKEFLAGS || return 1
  49.101 +
  49.102 +			cd grub-core
  49.103 +			../grub-mkimage \
  49.104 +				-d . \
  49.105 +				-o ../bootia32.efi \
  49.106 +				-O i386-efi \
  49.107 +				-p /boot/grub \
  49.108 +				ntfs hfs appleldr boot cat efi_gop efi_uga elf fat hfsplus \
  49.109 +				iso9660 linux keylayouts memdisk minicmd part_apple ext2 extcmd \
  49.110 +				xfs xnu part_bsd part_gpt search search_fs_file chain btrfs \
  49.111 +				loadbios loadenv lvm minix minix2 reiserfs memrw mmap msdospart \
  49.112 +				scsi loopback normal configfile gzio all_video efi_gop efi_uga \
  49.113 +				gfxterm gettext echo boot chain || return 1
  49.114 +
  49.115 +				install -Dm644 $src/bootia32.efi $install/boot/efi/boot/bootia32.efi
  49.116 +				;;
  49.117  	esac
  49.118  }
  49.119  
  49.120 -post_install_grub2()
  49.121 -{
  49.122 -	cat <<EOT
  49.123 -# To install grub to your sda MBR
  49.124 -grub-install /dev/sda
  49.125 +genpkg_rules() {
  49.126 +	case $PACKAGE in
  49.127 +		grub2)
  49.128 +			copy @std
  49.129 +			DEPENDS="zlib freetype ncurses libusb-compat grep libusb libdevmapper"
  49.130 +			TAGS="LFS"
  49.131 +			;;
  49.132 +		grub2-efi)
  49.133 +			copy @std
  49.134 +			DEPENDS=" "
  49.135 +			;;
  49.136 +	esac
  49.137 +}
  49.138  
  49.139 -# To generate a configuration file
  49.140 -grub-mkconfig -o /boot/grub/grub.cfg
  49.141 +post_install_grub2() {
  49.142 +	[ -n "$quiet" ] || cat <<EOT
  49.143  
  49.144 -# You can learn from /boot/grub/example-grub.cfg too.
  49.145 +	.-------------------------------------------------------.
  49.146 +	| # To install grub to your sda MBR                     |
  49.147 +	|   grub-install /dev/sda                               |
  49.148 +	|-------------------------------------------------------|
  49.149 +	| # To generate a configuration file                    |
  49.150 +	|   grub-mkconfig -o /boot/grub/grub.cfg                |
  49.151 +	|-------------------------------------------------------|
  49.152 +	| # You can learn from /boot/grub/example-grub.cfg too. |
  49.153 +	'-------------------------------------------------------'
  49.154  EOT
  49.155  }
    50.1 --- a/gzip/receipt	Wed Feb 21 18:10:55 2018 +0200
    50.2 +++ b/gzip/receipt	Wed Feb 21 19:48:17 2018 +0200
    50.3 @@ -7,6 +7,8 @@
    50.4  MAINTAINER="erjo@slitaz.org"
    50.5  LICENSE="GPL3"
    50.6  WEB_SITE="https://www.gnu.org/software/gzip/"
    50.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/gzip.html"
    50.8 +HOST_ARCH="i486 x86_64"
    50.9  
   50.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   50.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   50.12 @@ -14,25 +16,21 @@
   50.13  BUILD_DEPENDS="glibc-dev"
   50.14  SPLIT="gzip-full"
   50.15  
   50.16 -# Rules to configure and make the package.
   50.17 -compile_rules()
   50.18 -{
   50.19 +compile_rules() {
   50.20  	./configure $CONFIGURE_ARGS && make && make install
   50.21  
   50.22  	mkdir -p $install/bin
   50.23  	mv -v $install/usr/bin/gzip $install/bin
   50.24  }
   50.25  
   50.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   50.27 -genpkg_rules()
   50.28 -{
   50.29 +genpkg_rules() {
   50.30  	case $PACKAGE in
   50.31  		gzip)
   50.32  			copy gzip gunzip zgrep
   50.33 +			TAGS="LFS"
   50.34  			;;
   50.35  		gzip-full)
   50.36 -			copy bin/
   50.37 -			remove_already_packed
   50.38 +			copy bin/ @rm
   50.39  			CAT="system-tools|full set"
   50.40  			DEPENDS="gzip"
   50.41  			;;
   50.42 @@ -41,14 +39,18 @@
   50.43  
   50.44  # Removing Busybox gunzip applet
   50.45  # as we have /usr/bin/gunzip in this package
   50.46 -pre_install_gzip()
   50.47 -{
   50.48 -	rm -f "$1/bin/gzip" "$1/bin/gunzip"
   50.49 +pre_install_gzip() {
   50.50 +	for i in gzip gunzip; do
   50.51 +		readlink "$1/bin/$i" | grep -q busybox && rm "$1/bin/$i"
   50.52 +	done
   50.53 +	:
   50.54  }
   50.55  
   50.56  # Removing Busybox uncompress and zcat applets
   50.57  # as we have /usr/bin/uncompress and /usr/bin/zcat in this package
   50.58 -pre_install_gzip_full()
   50.59 -{
   50.60 -	rm -f "$1/bin/uncompress" "$1/bin/zcat"
   50.61 +pre_install_gzip_full() {
   50.62 +	for i in uncompress zcat; do
   50.63 +		readlink "$1/bin/$i" | grep -q busybox && rm "$1/bin/$i"
   50.64 +	done
   50.65 +	:
   50.66  }
    51.1 --- a/iana-etc/receipt	Wed Feb 21 18:10:55 2018 +0200
    51.2 +++ b/iana-etc/receipt	Wed Feb 21 19:48:17 2018 +0200
    51.3 @@ -7,20 +7,18 @@
    51.4  MAINTAINER="al.bobylev@gmail.com"
    51.5  LICENSE="OSL3"
    51.6  WEB_SITE="http://freecode.com/projects/iana-etc"
    51.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/iana-etc.html"
    51.8  
    51.9  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   51.10  WGET_URL="http://anduin.linuxfromscratch.org/LFS/$TARBALL"
   51.11  
   51.12  BUILD_DEPENDS="gawk"
   51.13  
   51.14 -# Rules to configure and make the package.
   51.15 -compile_rules()
   51.16 -{
   51.17 +compile_rules() {
   51.18  	make && make DESTDIR=$install install
   51.19  }
   51.20  
   51.21 -# Rules to gen a SliTaz package suitable for Tazpkg.
   51.22 -genpkg_rules()
   51.23 -{
   51.24 +genpkg_rules() {
   51.25  	copy @std
   51.26 +	TAGS="LFS"
   51.27  }
    52.1 --- a/inetutils/receipt	Wed Feb 21 18:10:55 2018 +0200
    52.2 +++ b/inetutils/receipt	Wed Feb 21 19:48:17 2018 +0200
    52.3 @@ -7,13 +7,12 @@
    52.4  MAINTAINER="al.bobylev@gmail.com"
    52.5  LICENSE="GPL3"
    52.6  WEB_SITE="https://www.gnu.org/software/inetutils/"
    52.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/inetutils.html"
    52.8  
    52.9  TARBALL="$PACKAGE-$VERSION.tar.xz"
   52.10  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   52.11  
   52.12 -# Rules to configure and make the package.
   52.13 -compile_rules()
   52.14 -{
   52.15 +compile_rules() {
   52.16  	./configure \
   52.17  		--localstatedir=/var \
   52.18  		--disable-logger \
   52.19 @@ -33,9 +32,8 @@
   52.20  	mv $install/usr/bin/ifconfig $install/sbin
   52.21  }
   52.22  
   52.23 -# Rules to gen a SliTaz package suitable for Tazpkg.
   52.24 -genpkg_rules()
   52.25 -{
   52.26 +genpkg_rules() {
   52.27  	copy @std
   52.28  	DEPENDS="readline"
   52.29 +	TAGS="LFS"
   52.30  }
    53.1 --- a/intltool/receipt	Wed Feb 21 18:10:55 2018 +0200
    53.2 +++ b/intltool/receipt	Wed Feb 21 19:48:17 2018 +0200
    53.3 @@ -7,27 +7,23 @@
    53.4  MAINTAINER="pankso@slitaz.org"
    53.5  LICENSE="GPL2"
    53.6  WEB_SITE="https://freedesktop.org/wiki/Software/intltool/"
    53.7 -HOST_ARCH="i486 arm"
    53.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/intltool.html"
    53.9  
   53.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   53.11  WGET_URL="http://launchpad.net/intltool/trunk/$VERSION/+download/$TARBALL"
   53.12  
   53.13 -BUILD_DEPENDS="perl perl-xml-parser wget"
   53.14 +BUILD_DEPENDS="perl perl-xml-parser"
   53.15  
   53.16 -# Rules to configure and make the package.
   53.17 -compile_rules()
   53.18 -{
   53.19 +compile_rules() {
   53.20  	sed -i 's:\\\${:\\\$\\{:' intltool-update.in
   53.21  
   53.22  	./configure $CONFIGURE_ARGS && make && make install
   53.23  
   53.24 -	docdir="$install/usr/share/doc/intltool-$VERSION"
   53.25 -	mkdir -p $docdir; cp doc/I18N-HOWTO $docdir
   53.26 +	cook_pick_docs doc/I18N-HOWTO
   53.27  }
   53.28  
   53.29 -# Rules to gen a SliTaz package suitable for Tazpkg.
   53.30 -genpkg_rules()
   53.31 -{
   53.32 +genpkg_rules() {
   53.33  	copy @std @dev
   53.34  	DEPENDS="perl-xml-parser gettext"
   53.35 +	TAGS="LFS"
   53.36  }
    54.1 --- a/iproute2/receipt	Wed Feb 21 18:10:55 2018 +0200
    54.2 +++ b/iproute2/receipt	Wed Feb 21 19:48:17 2018 +0200
    54.3 @@ -1,31 +1,28 @@
    54.4  # SliTaz package receipt v2.
    54.5  
    54.6  PACKAGE="iproute2"
    54.7 -VERSION="4.9.0"
    54.8 +VERSION="4.12.0"
    54.9  CATEGORY="network"
   54.10  SHORT_DESC="Utilites for networking and traffic control"
   54.11  MAINTAINER="allan316@gmail.com"
   54.12  LICENSE="GPL2"
   54.13  WEB_SITE="http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2"
   54.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/iproute2.html"
   54.15  
   54.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   54.17  WGET_URL="https://www.kernel.org/pub/linux/utils/net/$PACKAGE/$TARBALL"
   54.18  
   54.19  BUILD_DEPENDS="bison flex iptables-dev db-dev libmnl-dev elfutils-dev"
   54.20  
   54.21 -# Rules to configure and make the package.
   54.22 -compile_rules()
   54.23 -{
   54.24 +compile_rules() {
   54.25  	./configure /usr/include $CONFIGURE_ARGS &&
   54.26  	sed -i 's|tc-skbmod\.8||' $src/man/man8/Makefile &&
   54.27  	make &&
   54.28  	make DOCDIR=/usr/share/doc/$PACKAGE-$VERSION DESTDIR=$DESTDIR install
   54.29  }
   54.30  
   54.31 -# Rules to gen a SliTaz package suitable for Tazpkg.
   54.32 -genpkg_rules()
   54.33 -{
   54.34 +genpkg_rules() {
   54.35  	copy @std
   54.36 -	TAGS="network route"
   54.37 +	TAGS="LFS network route"
   54.38  	DEPENDS="iptables db"
   54.39  }
    55.1 --- a/kbd/receipt	Wed Feb 21 18:10:55 2018 +0200
    55.2 +++ b/kbd/receipt	Wed Feb 21 19:48:17 2018 +0200
    55.3 @@ -7,18 +7,16 @@
    55.4  MAINTAINER="pankso@slitaz.org"
    55.5  LICENSE="GPL2"
    55.6  WEB_SITE="http://kbd-project.org/"
    55.7 -HOST_ARCH="i486 arm"
    55.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/kbd.html"
    55.9  
   55.10  TARBALL="kbd-$VERSION.tar.xz"
   55.11  WGET_URL="https://www.kernel.org/pub/linux/utils/kbd/$TARBALL"
   55.12  
   55.13 +BUILD_DEPENDS_arm="flex check-dev"
   55.14  BUILD_DEPENDS="check-dev bison flex gettext patch pam-dev busybox"
   55.15 -BUILD_DEPENDS_arm="flex check-dev"
   55.16  SPLIT="kbd-base kbd-vlock kbd-busybox kbd"
   55.17  
   55.18 -# Rules to configure and make the package.
   55.19 -compile_rules()
   55.20 -{
   55.21 +compile_rules() {
   55.22  	sed -i 's/\(RESIZECONS_PROGS=\)yes/\1no/g' configure
   55.23  	sed -i 's/resizecons.8 //' docs/man/man8/Makefile.in
   55.24  
   55.25 @@ -28,6 +26,11 @@
   55.26  		sed -i 's|	| |g; s|  *| |g; s|^ ||; s| $||; /^#/d; /^!/d; /^$/d' $i
   55.27  	done
   55.28  
   55.29 +	# Unicode range is limited by 0xf000 here with error "Unicode keysym out of range",
   55.30 +	# but de_alt_UTF-8.map has the symbols U+FB01, U+F8FF, U+FB02
   55.31 +	# And due to this error zero-sized file .kmap is produced.
   55.32 +	sed -i 's|0xf000|0xfffe|' src/libkeymap/analyze.c src/libkeymap/analyze.l
   55.33 +
   55.34  	./configure \
   55.35  		--datadir=/usr/share/kbd \
   55.36  		$CONFIGURE_ARGS &&
   55.37 @@ -35,8 +38,7 @@
   55.38  
   55.39  	mv $install/usr/share/kbd/locale $install/usr/share
   55.40  
   55.41 -	mkdir -p $install/usr/share/doc/kbd-$VERSION
   55.42 -	cp -R docs/doc/* $install/usr/share/doc/kbd-$VERSION
   55.43 +	cook_pick_docs docs/doc/*
   55.44  
   55.45  	# X11 keyboard aliases
   55.46  	ln -s croat.map.gz $install/usr/share/kbd/keymaps/i386/qwertz/hr.map.gz
   55.47 @@ -50,16 +52,13 @@
   55.48  	done
   55.49  }
   55.50  
   55.51 -# Make sure it will run on host or no keyboard support...
   55.52 -testsuite()
   55.53 -{
   55.54 +# Make sure it will run on target or no keyboard support...
   55.55 +testsuite() {
   55.56  	readelf -h $install/usr/bin/loadkeys
   55.57  	readelf -h $install/usr/bin/setfont
   55.58  }
   55.59  
   55.60 -# Rules to gen a SliTaz package suitable for Tazpkg.
   55.61 -genpkg_rules()
   55.62 -{
   55.63 +genpkg_rules() {
   55.64  	case $PACKAGE in
   55.65  		kbd-base)
   55.66  			copy loadkeys setfont \
   55.67 @@ -94,10 +93,9 @@
   55.68  			CAT="base-system|mappings for busybox"
   55.69  			;;
   55.70  		kbd)
   55.71 -			copy bin/ kbd/
   55.72 -			remove_already_packed
   55.73 +			copy bin/ kbd/ @rm
   55.74  			DEPENDS="kbd-base"
   55.75 -			TAGS="keyboard"
   55.76 +			TAGS="LFS keyboard"
   55.77  			;;
   55.78  	esac
   55.79  }
    56.1 --- a/kmod/receipt	Wed Feb 21 18:10:55 2018 +0200
    56.2 +++ b/kmod/receipt	Wed Feb 21 19:48:17 2018 +0200
    56.3 @@ -1,26 +1,25 @@
    56.4  # SliTaz package receipt v2.
    56.5  
    56.6  PACKAGE="kmod"
    56.7 -VERSION="23"
    56.8 +VERSION="24"
    56.9  CATEGORY="base-system"
   56.10  SHORT_DESC="Linux kernel modules tools"
   56.11  MAINTAINER="pankso@slitaz.org"
   56.12  LICENSE="GPL2"
   56.13  WEB_SITE="https://www.kernel.org/pub/linux/utils/kernel/kmod/"
   56.14 -HOST_ARCH="i486 arm"
   56.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/kmod.html"
   56.16  
   56.17  TARBALL="$PACKAGE-$VERSION.tar.xz"
   56.18  WGET_URL="$WEB_SITE$TARBALL"
   56.19  
   56.20 +BUILD_DEPENDS_arm="zlib-dev xz-dev"
   56.21  BUILD_DEPENDS="zlib-dev xz-dev tar"
   56.22 -BUILD_DEPENDS_arm="zlib-dev xz-dev"
   56.23  SPLIT="kmod-dev"
   56.24  
   56.25  compile_rules() {
   56.26  	./configure \
   56.27  		--bindir=/bin \
   56.28  		--with-rootlibdir=/lib \
   56.29 -		--sysconfdir=/etc \
   56.30  		--with-zlib \
   56.31  		--with-xz \
   56.32  		$CONFIGURE_ARGS &&
   56.33 @@ -43,6 +42,7 @@
   56.34  			# please keep glibc-base here because kmod used in the post-install
   56.35  			# of linux-* packages and will not work instead
   56.36  			DEPENDS="glibc-base zlib liblzma"
   56.37 +			TAGS="LFS"
   56.38  			;;
   56.39  		*-dev)
   56.40  			copy @dev
    57.1 --- a/less/receipt	Wed Feb 21 18:10:55 2018 +0200
    57.2 +++ b/less/receipt	Wed Feb 21 19:48:17 2018 +0200
    57.3 @@ -1,21 +1,21 @@
    57.4  # SliTaz package receipt v2.
    57.5  
    57.6  PACKAGE="less"
    57.7 -VERSION="481"
    57.8 +VERSION="487"
    57.9  CATEGORY="base-system"
   57.10  SHORT_DESC="A terminal based program for viewing text files"
   57.11  MAINTAINER="slaxemulator@gmail.com"
   57.12  LICENSE="GPL3"
   57.13  WEB_SITE="http://www.greenwoodsoftware.com/less"
   57.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/less.html"
   57.15 +HOST_ARCH="i486 x86_64"
   57.16  
   57.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   57.18  WGET_URL="$WEB_SITE/$TARBALL"
   57.19  
   57.20  BUILD_DEPENDS="ncurses-dev pcre-dev"
   57.21  
   57.22 -# Rules to configure and make the package.
   57.23 -compile_rules()
   57.24 -{
   57.25 +compile_rules() {
   57.26  	./configure \
   57.27  		--sysconfdir=/etc \
   57.28  		--with-regex=pcre \
   57.29 @@ -23,9 +23,8 @@
   57.30  	make && make DESTDIR=$install install
   57.31  }
   57.32  
   57.33 -# Rules to gen a SliTaz package suitable for Tazpkg.
   57.34 -genpkg_rules()
   57.35 -{
   57.36 +genpkg_rules() {
   57.37  	copy @std
   57.38  	DEPENDS="ncurses pcre"
   57.39 +	TAGS="LFS"
   57.40  }
    58.1 --- a/libcap/receipt	Wed Feb 21 18:10:55 2018 +0200
    58.2 +++ b/libcap/receipt	Wed Feb 21 19:48:17 2018 +0200
    58.3 @@ -7,27 +7,30 @@
    58.4  MAINTAINER="pankso@slitaz.org"
    58.5  LICENSE="BSD"
    58.6  WEB_SITE="https://sites.google.com/site/fullycapable/"
    58.7 -HOST_ARCH="i486 arm"
    58.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/libcap.html"
    58.9  
   58.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   58.11  WGET_URL="https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/$TARBALL"
   58.12  
   58.13 +BUILD_DEPENDS_arm="gperf pam-dev attr-dev"
   58.14  BUILD_DEPENDS="gperf pam-dev attr-dev perl"
   58.15 -BUILD_DEPENDS_arm="gperf pam-dev attr-dev"
   58.16 -SPLIT="libcap-pam libcap-dev"
   58.17 +SPLIT="libcap-pam libcap libcap-dev"
   58.18  
   58.19 -# Handle cross compilation.
   58.20 -case "$ARCH" in
   58.21 -	arm*) ARCH_ARGS="CC=$HOST_SYSTEM-gcc BUILD_CC=gcc" ;;
   58.22 -esac
   58.23 +compile_rules() {
   58.24 +	# Handle cross compilation.
   58.25 +	case "$ARCH" in
   58.26 +		arm*) ARCH_ARGS="CC=$HOST_SYSTEM-gcc BUILD_CC=gcc" ;;
   58.27 +	esac
   58.28  
   58.29 -# Rules to configure and make the package.
   58.30 -compile_rules()
   58.31 -{
   58.32 +	# Prevent a static library from being installed
   58.33  	sed -i '/install.*STALIBNAME/d' libcap/Makefile
   58.34  
   58.35  	make $ARCH_ARGS &&
   58.36 -	make RAISE_SETFCAP=no prefix=/usr install || return 1
   58.37 +	make \
   58.38 +		RAISE_SETFCAP=no \
   58.39 +		lib=lib \
   58.40 +		prefix=/usr \
   58.41 +		install || return 1
   58.42  
   58.43  	chmod 755 $install/usr/lib/libcap.so
   58.44  	mkdir $install/lib
   58.45 @@ -36,19 +39,18 @@
   58.46  		$install/usr/lib/libcap.so
   58.47  }
   58.48  
   58.49 -# Rules to gen a SliTaz package suitable for Tazpkg.
   58.50 -genpkg_rules()
   58.51 -{
   58.52 +genpkg_rules() {
   58.53  	case $PACKAGE in
   58.54 -		libcap)
   58.55 -			copy @std
   58.56 -			DEPENDS="attr"
   58.57 -			;;
   58.58  		libcap-pam)
   58.59 +			copy pam_cap.so
   58.60  			CAT="system-tools|PAM module"
   58.61  			PROVIDE="libcap:pam"
   58.62  			DEPENDS="libcap pam"
   58.63 -			copy pam_cap.so
   58.64 +			;;
   58.65 +		libcap)
   58.66 +			copy @std @rm
   58.67 +			DEPENDS="attr"
   58.68 +			TAGS="LFS"
   58.69  			;;
   58.70  		*-dev) copy @dev;;
   58.71  	esac
    59.1 --- a/libpipeline/receipt	Wed Feb 21 18:10:55 2018 +0200
    59.2 +++ b/libpipeline/receipt	Wed Feb 21 19:48:17 2018 +0200
    59.3 @@ -1,12 +1,13 @@
    59.4  # SliTaz package receipt v2.
    59.5  
    59.6  PACKAGE="libpipeline"
    59.7 -VERSION="1.4.1"
    59.8 +VERSION="1.4.2"
    59.9  CATEGORY="system-tools"
   59.10  SHORT_DESC="Pipeline manipulation library"
   59.11  MAINTAINER="al.bobylev@gmail.com"
   59.12  LICENSE="GPL3"
   59.13  WEB_SITE="http://libpipeline.nongnu.org/"
   59.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/libpipeline.html"
   59.15  
   59.16  TARBALL="$PACKAGE-$VERSION.tar.gz"
   59.17  WGET_URL="http://download.savannah.gnu.org/releases/$PACKAGE/$TARBALL"
   59.18 @@ -14,17 +15,16 @@
   59.19  BUILD_DEPENDS="check-dev"
   59.20  SPLIT="libpipeline-dev"
   59.21  
   59.22 -# Rules to configure and make the package.
   59.23 -compile_rules()
   59.24 -{
   59.25 +compile_rules() {
   59.26  	./configure $CONFIGURE_ARGS && make && make install
   59.27  }
   59.28  
   59.29 -# Rules to gen a SliTaz package suitable for Tazpkg.
   59.30 -genpkg_rules()
   59.31 -{
   59.32 +genpkg_rules() {
   59.33  	case $PACKAGE in
   59.34 -		libpipeline) copy @std;;
   59.35 +		libpipeline)
   59.36 +			copy @std
   59.37 +			TAGS="LFS"
   59.38 +			;;
   59.39  		*-dev) copy @dev;;
   59.40  	esac
   59.41  }
    60.1 --- a/libtool/receipt	Wed Feb 21 18:10:55 2018 +0200
    60.2 +++ b/libtool/receipt	Wed Feb 21 19:48:17 2018 +0200
    60.3 @@ -3,37 +3,34 @@
    60.4  PACKAGE="libtool"
    60.5  VERSION="2.4.6"
    60.6  CATEGORY="development"
    60.7 -SHORT_DESC="The GNU Portable Library Tool."
    60.8 +SHORT_DESC="The GNU Portable Library Tool"
    60.9  MAINTAINER="pankso@slitaz.org"
   60.10  LICENSE="GPL2"
   60.11  WEB_SITE="https://www.gnu.org/software/libtool/"
   60.12 -HOST_ARCH="i486 arm"
   60.13 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/libtool.html"
   60.14  
   60.15  TARBALL="$PACKAGE-$VERSION.tar.xz"
   60.16  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   60.17  
   60.18 +BUILD_DEPENDS_arm=" "
   60.19  BUILD_DEPENDS="automake autoconf gfortran"
   60.20 -BUILD_DEPENDS_arm=" "
   60.21 -SPLIT="libltdl"
   60.22 +SPLIT="libltdl libtool"
   60.23  
   60.24 -# Rules to configure and make the package.
   60.25 -compile_rules()
   60.26 -{
   60.27 +compile_rules() {
   60.28  	./configure $CONFIGURE_ARGS && make && make install
   60.29  }
   60.30  
   60.31 -# Rules to gen a SliTaz package suitable for Tazpkg.
   60.32 -genpkg_rules()
   60.33 -{
   60.34 +genpkg_rules() {
   60.35  	case $PACKAGE in
   60.36 -		libtool)
   60.37 -			copy bin/ include/ aclocal/ libtool/ *.*a
   60.38 -			DEPENDS="libltdl automake autoconf"
   60.39 -			;;
   60.40  		libltdl)
   60.41  			copy *.so*
   60.42  			CAT="system-tools|library"
   60.43  			DEPENDS="glibc-base"
   60.44  			;;
   60.45 +		libtool)
   60.46 +			copy @std @dev @rm
   60.47 +			DEPENDS="libltdl automake autoconf"
   60.48 +			TAGS="LFS"
   60.49 +			;;
   60.50  	esac
   60.51  }
    61.1 --- a/linux-dev/receipt	Wed Feb 21 18:10:55 2018 +0200
    61.2 +++ b/linux-dev/receipt	Wed Feb 21 19:48:17 2018 +0200
    61.3 @@ -1,33 +1,39 @@
    61.4  # SliTaz package receipt v2.
    61.5  
    61.6  PACKAGE="linux-dev"
    61.7 -VERSION="4.9.76"
    61.8 -KBASEVER="4.9"
    61.9 +VERSION="$(. $WOK/linux/receipt; echo $VERSION)"
   61.10 +KBASEVER="$(. $WOK/linux/receipt; echo $KBASEVER)"
   61.11  CATEGORY="development"
   61.12  SHORT_DESC="The Linux Kernel"
   61.13  MAINTAINER="devel@slitaz.org"
   61.14  LICENSE="GPL2"
   61.15  WEB_SITE="https://www.kernel.org/"
   61.16 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/linux-headers.html"
   61.17  
   61.18  TARBALL="linux-$KBASEVER.tar.xz"
   61.19  WGET_URL="https://www.kernel.org/pub/linux/kernel/v4.x/$TARBALL"
   61.20  
   61.21 -DEPENDS="ncurses"
   61.22 -BUILD_DEPENDS="python-sphinx perl xmlto util-linux-getopt docbook-xsl \
   61.23 -coreutils-operations findutils ncurses-dev patch bash bc"
   61.24 -SPLIT="linux-dev linux-man linux-api-headers linux-uml"
   61.25 +case $ARCH in
   61.26 +	i*86)
   61.27 +		SPLIT="linux-dev linux-api-headers linux-uml"
   61.28 +		BUILD_DEPENDS="python-sphinx perl xmlto util-linux-getopt docbook-xsl \
   61.29 +		coreutils-operations findutils ncurses-dev patch bash bc"
   61.30 +		;;
   61.31 +	x86_64)
   61.32 +		SPLIT="linux-dev linux-api-headers"
   61.33 +		BUILD_DEPENDS="perl patch ncurses-dev"
   61.34 +		;;
   61.35 +esac
   61.36  SIBLINGS="linux"
   61.37 -COOKOPTS="!pngz !svgz !uiz"
   61.38 +COOKOPTS="!pngz !svgz !uiz !strip"
   61.39  
   61.40  if [ "$KBASEVER" != "${VERSION%.0}" ]; then
   61.41  	PATCH="$(dirname $WGET_URL)/patch-$VERSION.xz"
   61.42  	EXTRA_SOURCE_FILES="$(basename $PATCH)"
   61.43  fi
   61.44  
   61.45 -# Rules to configure and make the package.
   61.46 -compile_rules()
   61.47 -{
   61.48 -	# Update sources to the $VERSION using base sources ($KBASEVER) and patch
   61.49 +compile_rules() {
   61.50 +	# Update sources to the $VERSION using base sources ($KBASEVER) and patches
   61.51  	if [ "$KBASEVER" != "${VERSION%.0}" ]; then
   61.52  		[ -s $SRC/$(basename $PATCH) ] || wget $PATCH -O $SRC/$(basename $PATCH)
   61.53  		# don't patch twice for `cook $PACKAGE --continue`
   61.54 @@ -47,7 +53,7 @@
   61.55  	. $WOK/linux/stuff/tools/aufs-patches
   61.56  
   61.57  	make defconfig
   61.58 -	sed -i 's/^menuconfig:.*/z&\n\techo menuconfig is ready\n\n&/' \
   61.59 +	sed -i 's/^menuconfig:.*/z&\n\t@echo menuconfig is ready\n\n&/' \
   61.60  		scripts/kconfig/Makefile
   61.61  	make zmenuconfig
   61.62  
   61.63 @@ -57,120 +63,44 @@
   61.64  
   61.65  	mkdir -p $install/usr/bin
   61.66  	mv $p/scripts/kconfig/mconf $install/usr/bin
   61.67 -	cat > $install/usr/bin/menuconfig <<EOT
   61.68 -#!/bin/sh
   61.69 -p=\$PWD
   61.70 -cd ../src/linux-$VERSION-slitaz
   61.71 -SRCARCH=x86 ARCH=i386 KERNELVERSION=$VERSION \$p/mconf Kconfig
   61.72 -EOT
   61.73 +	sed "s|@VERSION@|$VERSION|; s|@ARCH@|$ARCH|" $stuff/menuconfig.in \
   61.74 +		> $install/usr/bin/menuconfig
   61.75  	chmod a+x $install/usr/bin/menuconfig
   61.76  
   61.77 -	patch -p1 -i $stuff/installmandocs.patch
   61.78  
   61.79 -	make mandocs && make installmandocs
   61.80 +	if [ "$ARCH" == 'i386' ]; then
   61.81 +		sed -i 's|uname -m|echo i386|; s|/bin/bash|/bin/ash|g' Makefile
   61.82 +		make ARCH=um mrproper
   61.83 +		cp $stuff/mini.config .
   61.84 +		make ARCH=um allnoconfig KCONFIG_ALLCONFIG=mini.config &&
   61.85 +		make ARCH=um || return 1
   61.86  
   61.87 -	sed -i 's/uname -m/echo i386/;s|/bin/bash|/bin/ash|g' Makefile
   61.88 -	make ARCH=um mrproper	
   61.89 -	cat > mini.config << EOF &&
   61.90 -CONFIG_BINFMT_ELF=y
   61.91 -CONFIG_LBD=y
   61.92 -CONFIG_BLK_DEV=y
   61.93 -CONFIG_BLK_DEV_LOOP=y
   61.94 -CONFIG_STDERR_CONSOLE=y
   61.95 -CONFIG_SSL=y
   61.96 -CONFIG_UNIX98_PTYS=y
   61.97 -CONFIG_PROC_FS=y
   61.98 -CONFIG_SYSFS_FS=y
   61.99 -CONFIG_IKCONFIG=y
  61.100 -CONFIG_IKCONFIG_PROC=y
  61.101 -CONFIG_UML_NET=y
  61.102 -CONFIG_UML_NET_TUNTAP=y
  61.103 -CONFIG_BLK_DEV_INITRD=y
  61.104 -CONFIG_PTY_CHAN=y
  61.105 -CONFIG_TTY_CHAN=y
  61.106 -CONFIG_NET=y
  61.107 -CONFIG_INET=y
  61.108 -CONFIG_UML_NET=y
  61.109 -CONFIG_UML_NET_TUNTAP=y
  61.110 -CONFIG_BLK_DEV_UBD=y
  61.111 -CONFIG_EXT4_FS=y
  61.112 -CONFIG_EXT4_USE_FOR_EXT23=y
  61.113 -CONFIG_EXT4_FS_XATTR=y
  61.114 -CONFIG_EXT4_FS_POSIX_ACL=y
  61.115 -CONFIG_FUSE_FS=y
  61.116 -CONFIG_ISO9660_FS=y
  61.117 -CONFIG_VFAT_FS=y
  61.118 -CONFIG_TMPFS=y
  61.119 -CONFIG_SWAP=y
  61.120 -CONFIG_SYSVIPC=y
  61.121 -CONFIG_SYSVIPC_SYSCTL=y
  61.122 -CONFIG_SYSVIPC_COMPAT=y
  61.123 -CONFIG_PACKET=y            
  61.124 -CONFIG_UNIX=y              
  61.125 -CONFIG_NETFILTER=y        
  61.126 -CONFIG_NETFILTER_ADVANCED=y
  61.127 -CONFIG_NF_CONNTRACK=y
  61.128 -CONFIG_NETFILTER_XTABLES=y
  61.129 -CONFIG_NF_DEFRAG_IPV4=y
  61.130 -CONFIG_NF_CONNTRACK_IPV4=y
  61.131 -CONFIG_NF_CONNTRACK_PROC_COMPAT=y
  61.132 -CONFIG_IP_NF_IPTABLES=y
  61.133 -CONFIG_IP_NF_FILTER=y
  61.134 -CONFIG_IP_NF_TARGET_REJECT=y
  61.135 -CONFIG_NF_NAT=y
  61.136 -CONFIG_NF_NAT_NEEDED=y
  61.137 -CONFIG_IP_NF_TARGET_MASQUERADE=y
  61.138 -CONFIG_IP_NF_TARGET_REDIRECT=y
  61.139 -CONFIG_NETDEVICES=y
  61.140 -CONFIG_TUN=y
  61.141 -EOF
  61.142 -	make ARCH=um allnoconfig KCONFIG_ALLCONFIG=mini.config &&
  61.143 -	make ARCH=um || return 1
  61.144 -
  61.145 -	mkdir -p $install/boot
  61.146 -	cp $src/linux $install/boot/linux-uml-$VERSION
  61.147 -	cat > $install/boot/vm-uml <<EOT
  61.148 -#!/bin/sh
  61.149 -
  61.150 -# /etc/inittab: "tty21::respawn:/bin/su -c '/boot/vm-uml 1 /boot/guests/slitaz.img 2 512m' nobody"
  61.151 -n=\${1:-0}
  61.152 -tap=tap\$n
  61.153 -args="rw root=/dev/null"
  61.154 -dev="initrd=\$(ls -r /boot/rootfs*.gz | sed q)"
  61.155 -if [ -n "\$2" ]; then
  61.156 -	args="ro root=620\${3:-1} screen=text sound=noconf"
  61.157 -	dev="ubd0=\$2"
  61.158 -fi
  61.159 -
  61.160 -cd \$(dirname \$0)
  61.161 -ifconfig \$tap 192.168.\$n.1
  61.162 -./linux-uml-$VERSION \$dev mem=\${4:-512m} fakehd fake_ide ubd=3 con0=fd:0,fd:1 \\
  61.163 -	con=pts ssl=pts eth0=tuntap,\$tap,fe:f0:00:00:00:0\$n,192.168.\$n.1 \\
  61.164 -	\$args cpuinfo=\$(sed '/model name/!d;s/.*: //;s/ /_/g;q' /proc/cpuinfo)
  61.165 -EOT
  61.166 -	chmod 755 $install/boot/vm-uml
  61.167 +		mkdir -p $install/boot
  61.168 +		cp $src/linux $install/boot/linux-uml-$VERSION
  61.169 +		sed "s|@VERSION@|$VERSION|" $stuff/vm-uml.in > $install/boot/vm-uml
  61.170 +		chmod 755 $install/boot/vm-uml
  61.171 +	fi
  61.172  }
  61.173  
  61.174  
  61.175 -# Rules to gen a SliTaz package suitable for Tazpkg.
  61.176 -genpkg_rules()
  61.177 -{
  61.178 +genpkg_rules() {
  61.179  	case $PACKAGE in
  61.180 -	linux-dev)
  61.181 -		copy Kconfig* mconf menuconfig .config
  61.182 -		CAT="development|menu based configuration tool"
  61.183 -		;;
  61.184 -	linux-man)
  61.185 -		copy /usr/share/man/
  61.186 -		CAT="doc|manual pages"
  61.187 -		;;
  61.188 -	linux-api-headers)
  61.189 -		copy @dev
  61.190 -		CAT="development|headers sanitized for use in userspace"
  61.191 -		PROVIDE="linux-headers linux64-api-headers linux64-headers"
  61.192 -		;;
  61.193 -	linux-uml)
  61.194 -		copy boot/
  61.195 -		;;
  61.196 +		linux-dev)
  61.197 +			copy Kconfig* mconf menuconfig .config
  61.198 +			CAT="development|menu based configuration tool"
  61.199 +			DEPENDS="ncurses"
  61.200 +			TAGS="LFS"
  61.201 +			;;
  61.202 +		linux-api-headers)
  61.203 +			copy @dev
  61.204 +			DEPENDS=" "
  61.205 +			CAT="development|headers sanitized for use in userspace"
  61.206 +			PROVIDE="linux-headers linux64-api-headers linux64-headers"
  61.207 +			;;
  61.208 +		linux-uml)
  61.209 +			copy boot/
  61.210 +			CAT="development|UML"
  61.211 +			DEPENDS=" "
  61.212 +			;;
  61.213  	esac
  61.214  }
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/linux-dev/stuff/menuconfig.in	Wed Feb 21 19:48:17 2018 +0200
    62.3 @@ -0,0 +1,4 @@
    62.4 +#!/bin/sh
    62.5 +p=$PWD
    62.6 +cd ../src/linux-@VERSION@-slitaz
    62.7 +SRCARCH=x86 ARCH=@ARCH@ KERNELVERSION=@VERSION@ $p/mconf Kconfig
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/linux-dev/stuff/mini.config	Wed Feb 21 19:48:17 2018 +0200
    63.3 @@ -0,0 +1,51 @@
    63.4 +CONFIG_BINFMT_ELF=y
    63.5 +CONFIG_LBD=y
    63.6 +CONFIG_BLK_DEV=y
    63.7 +CONFIG_BLK_DEV_LOOP=y
    63.8 +CONFIG_STDERR_CONSOLE=y
    63.9 +CONFIG_SSL=y
   63.10 +CONFIG_UNIX98_PTYS=y
   63.11 +CONFIG_PROC_FS=y
   63.12 +CONFIG_SYSFS_FS=y
   63.13 +CONFIG_IKCONFIG=y
   63.14 +CONFIG_IKCONFIG_PROC=y
   63.15 +CONFIG_UML_NET=y
   63.16 +CONFIG_UML_NET_TUNTAP=y
   63.17 +CONFIG_BLK_DEV_INITRD=y
   63.18 +CONFIG_PTY_CHAN=y
   63.19 +CONFIG_TTY_CHAN=y
   63.20 +CONFIG_NET=y
   63.21 +CONFIG_INET=y
   63.22 +CONFIG_UML_NET=y
   63.23 +CONFIG_UML_NET_TUNTAP=y
   63.24 +CONFIG_BLK_DEV_UBD=y
   63.25 +CONFIG_EXT4_FS=y
   63.26 +CONFIG_EXT4_USE_FOR_EXT23=y
   63.27 +CONFIG_EXT4_FS_XATTR=y
   63.28 +CONFIG_EXT4_FS_POSIX_ACL=y
   63.29 +CONFIG_FUSE_FS=y
   63.30 +CONFIG_ISO9660_FS=y
   63.31 +CONFIG_VFAT_FS=y
   63.32 +CONFIG_TMPFS=y
   63.33 +CONFIG_SWAP=y
   63.34 +CONFIG_SYSVIPC=y
   63.35 +CONFIG_SYSVIPC_SYSCTL=y
   63.36 +CONFIG_SYSVIPC_COMPAT=y
   63.37 +CONFIG_PACKET=y
   63.38 +CONFIG_UNIX=y
   63.39 +CONFIG_NETFILTER=y
   63.40 +CONFIG_NETFILTER_ADVANCED=y
   63.41 +CONFIG_NF_CONNTRACK=y
   63.42 +CONFIG_NETFILTER_XTABLES=y
   63.43 +CONFIG_NF_DEFRAG_IPV4=y
   63.44 +CONFIG_NF_CONNTRACK_IPV4=y
   63.45 +CONFIG_NF_CONNTRACK_PROC_COMPAT=y
   63.46 +CONFIG_IP_NF_IPTABLES=y
   63.47 +CONFIG_IP_NF_FILTER=y
   63.48 +CONFIG_IP_NF_TARGET_REJECT=y
   63.49 +CONFIG_NF_NAT=y
   63.50 +CONFIG_NF_NAT_NEEDED=y
   63.51 +CONFIG_IP_NF_TARGET_MASQUERADE=y
   63.52 +CONFIG_IP_NF_TARGET_REDIRECT=y
   63.53 +CONFIG_NETDEVICES=y
   63.54 +CONFIG_TUN=y
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/linux-dev/stuff/vm-uml.in	Wed Feb 21 19:48:17 2018 +0200
    64.3 @@ -0,0 +1,17 @@
    64.4 +#!/bin/sh
    64.5 +
    64.6 +# /etc/inittab: "tty21::respawn:/bin/su -c '/boot/vm-uml 1 /boot/guests/slitaz.img 2 512m' nobody"
    64.7 +n=${1:-0}
    64.8 +tap=tap$n
    64.9 +args="rw root=/dev/null"
   64.10 +dev="initrd=$(ls -r /boot/rootfs*.gz | sed q)"
   64.11 +if [ -n "$2" ]; then
   64.12 +	args="ro root=620${3:-1} screen=text sound=noconf"
   64.13 +	dev="ubd0=$2"
   64.14 +fi
   64.15 +
   64.16 +cd $(dirname $0)
   64.17 +ifconfig $tap 192.168.$n.1
   64.18 +./linux-uml-@VERSION@ $dev mem=${4:-512m} fakehd fake_ide ubd=3 con0=fd:0,fd:1 \
   64.19 +	con=pts ssl=pts eth0=tuntap,$tap,fe:f0:00:00:00:0$n,192.168.$n.1 \
   64.20 +	$args cpuinfo=$(sed '/model name/!d;s/.*: //;s/ /_/g;q' /proc/cpuinfo)
    65.1 --- a/m4/receipt	Wed Feb 21 18:10:55 2018 +0200
    65.2 +++ b/m4/receipt	Wed Feb 21 19:48:17 2018 +0200
    65.3 @@ -7,22 +7,17 @@
    65.4  MAINTAINER="pankso@slitaz.org"
    65.5  LICENSE="GPL3"
    65.6  WEB_SITE="https://www.gnu.org/software/m4/m4.html"
    65.7 -HOST_ARCH="i486 arm"
    65.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/m4.html"
    65.9  
   65.10  TARBALL="$PACKAGE-$VERSION.tar.gz"
   65.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   65.12  
   65.13 -DEPENDS="glibc-base"
   65.14 -BUILD_DEPENDS=""
   65.15 -
   65.16 -# Rules to configure and make the package.
   65.17 -compile_rules()
   65.18 -{
   65.19 +compile_rules() {
   65.20  	./configure $CONFIGURE_ARGS && make && make install
   65.21  }
   65.22  
   65.23 -# Rules to gen a SliTaz package suitable for Tazpkg.
   65.24 -genpkg_rules()
   65.25 -{
   65.26 -	copy m4
   65.27 +genpkg_rules() {
   65.28 +	copy @std
   65.29 +	DEPENDS="glibc-base"
   65.30 +	TAGS="LFS"
   65.31  }
    66.1 --- a/make/receipt	Wed Feb 21 18:10:55 2018 +0200
    66.2 +++ b/make/receipt	Wed Feb 21 19:48:17 2018 +0200
    66.3 @@ -7,21 +7,18 @@
    66.4  MAINTAINER="pankso@slitaz.org"
    66.5  LICENSE="GPL3"
    66.6  WEB_SITE="https://www.gnu.org/software/make/"
    66.7 -HOST_ARCH="i486 arm x86_64"
    66.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/make.html"
    66.9  
   66.10  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   66.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   66.12  
   66.13  BUILD_DEPENDS="gettext"
   66.14  
   66.15 -# Rules to configure and make the package.
   66.16 -compile_rules()
   66.17 -{
   66.18 +compile_rules() {
   66.19  	./configure $CONFIGURE_ARGS && make && make install
   66.20  }
   66.21  
   66.22 -# Rules to gen a SliTaz package suitable for Tazpkg.
   66.23 -genpkg_rules()
   66.24 -{
   66.25 +genpkg_rules() {
   66.26  	copy @std
   66.27 +	TAGS="LFS"
   66.28  }
    67.1 --- a/man-db/receipt	Wed Feb 21 18:10:55 2018 +0200
    67.2 +++ b/man-db/receipt	Wed Feb 21 19:48:17 2018 +0200
    67.3 @@ -7,6 +7,7 @@
    67.4  MAINTAINER="al.bobylev@gmail.com"
    67.5  LICENSE="GPL2"
    67.6  WEB_SITE="http://www.nongnu.org/man-db/"
    67.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/man-db.html"
    67.8  
    67.9  TARBALL="$PACKAGE-$VERSION.tar.xz"
   67.10  WGET_URL="http://download.savannah.gnu.org/releases/man-db/$TARBALL"
   67.11 @@ -15,11 +16,8 @@
   67.12  zlib-dev"
   67.13  SPLIT="man-db-dev"
   67.14  
   67.15 -# Rules to configure and make the package.
   67.16 -compile_rules()
   67.17 -{
   67.18 +compile_rules() {
   67.19  	./configure \
   67.20 -		--docdir=/usr/share/doc/$PACKAGE-$VERSION \
   67.21  		--sysconfdir=/etc \
   67.22  		--disable-setuid \
   67.23  		--with-browser=/usr/bin/lynx \
   67.24 @@ -31,13 +29,12 @@
   67.25  	sed -i "s:man root:root root:g" $install/usr/lib/tmpfiles.d/man-db.conf
   67.26  }
   67.27  
   67.28 -# Rules to gen a SliTaz package suitable for Tazpkg.
   67.29 -genpkg_rules()
   67.30 -{
   67.31 +genpkg_rules() {
   67.32  	case $PACKAGE in
   67.33  		man-db)
   67.34  			copy @std
   67.35  			DEPENDS="gdbm libpipeline zlib"
   67.36 +			TAGS="LFS"
   67.37  			;;
   67.38  		*-dev) copy @dev;;
   67.39  	esac
    68.1 --- a/man-pages/receipt	Wed Feb 21 18:10:55 2018 +0200
    68.2 +++ b/man-pages/receipt	Wed Feb 21 19:48:17 2018 +0200
    68.3 @@ -1,24 +1,22 @@
    68.4  # SliTaz package receipt v2.
    68.5  
    68.6  PACKAGE="man-pages"
    68.7 -VERSION="4.09"
    68.8 +VERSION="$(. $WOK/linux/receipt; echo $KBASEVER)"
    68.9  CATEGORY="doc"
   68.10  SHORT_DESC="Linux manual pages"
   68.11  MAINTAINER="al.bobylev@gmail.com"
   68.12  LICENSE="unknown"
   68.13  WEB_SITE="https://www.kernel.org/doc/man-pages/"
   68.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/man-pages.html"
   68.15  
   68.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   68.17  WGET_URL="https://www.kernel.org/pub/linux/docs/man-pages/$TARBALL"
   68.18  
   68.19 -# Rules to configure and make the package.
   68.20 -compile_rules()
   68.21 -{
   68.22 +compile_rules() {
   68.23  	make DESTDIR=$install install
   68.24  }
   68.25  
   68.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   68.27 -genpkg_rules()
   68.28 -{
   68.29 +genpkg_rules() {
   68.30  	copy man/
   68.31 +	TAGS="LFS"
   68.32  }
    69.1 --- a/mpc-library/receipt	Wed Feb 21 18:10:55 2018 +0200
    69.2 +++ b/mpc-library/receipt	Wed Feb 21 19:48:17 2018 +0200
    69.3 @@ -7,7 +7,7 @@
    69.4  MAINTAINER="pankso@slitaz.org"
    69.5  LICENSE="GPL2"
    69.6  WEB_SITE="http://www.multiprecision.org/"
    69.7 -HOST_ARCH="i486 arm"
    69.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/mpc.html"
    69.9  
   69.10  TARBALL="mpc-$VERSION.tar.gz"
   69.11  WGET_URL="${WEB_SITE}mpc/download/$TARBALL"
   69.12 @@ -15,22 +15,19 @@
   69.13  BUILD_DEPENDS="mpfr-dev gmp-dev texinfo"
   69.14  SPLIT="mpc-library-dev"
   69.15  
   69.16 -compile_rules()
   69.17 -{
   69.18 +compile_rules() {
   69.19  	./configure \
   69.20  		--disable-static \
   69.21 -		--docdir=/usr/share/doc/mpc-$VERSION \
   69.22  		$CONFIGURE_ARGS &&
   69.23  	make && make html && make install && make install-html
   69.24  }
   69.25  
   69.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   69.27 -genpkg_rules()
   69.28 -{
   69.29 +genpkg_rules() {
   69.30  	case $PACKAGE in
   69.31  		mpc-library)
   69.32  			copy @std
   69.33  			DEPENDS="mpfr gmp"
   69.34 +			TAGS="LFS"
   69.35  			;;
   69.36  		*-dev)
   69.37  			copy @dev
    70.1 --- a/mpfr/receipt	Wed Feb 21 18:10:55 2018 +0200
    70.2 +++ b/mpfr/receipt	Wed Feb 21 19:48:17 2018 +0200
    70.3 @@ -7,7 +7,7 @@
    70.4  MAINTAINER="pankso@slitaz.org"
    70.5  LICENSE="GPL3"
    70.6  WEB_SITE="http://www.mpfr.org/"
    70.7 -HOST_ARCH="i486 arm"
    70.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/mpfr.html"
    70.9  
   70.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   70.11  WGET_URL="http://www.mpfr.org/$PACKAGE-$VERSION/$TARBALL"
   70.12 @@ -15,30 +15,31 @@
   70.13  BUILD_DEPENDS="gmp-dev texinfo"
   70.14  SPLIT="mpfr-dev"
   70.15  
   70.16 +compile_rules() {
   70.17  #--with-gmp-lib=/cross/$ARCH/sysroot/usr/lib
   70.18  #--with-gmp-include=/cross/$ARCH/sysroot/usr/include
   70.19  
   70.20 -# Rules to configure and make the package.
   70.21 -compile_rules()
   70.22 -{
   70.23  	./configure \
   70.24  		--disable-static \
   70.25  		--enable-thread-safe \
   70.26 -		--docdir=/usr/share/doc/mpfr-$VERSION \
   70.27  		$CONFIGURE_ARGS &&
   70.28  	make && make html && make install && make install-html
   70.29  }
   70.30  
   70.31 -testsuite()
   70.32 -{
   70.33 -	case "$ARCH" in i?86) make check;; esac
   70.34 +testsuite() {
   70.35 +	case "$ARCH" in
   70.36 +		arm*) ;;
   70.37 +		*) make check;;
   70.38 +	esac
   70.39  }
   70.40  
   70.41 -# Rules to gen a SliTaz package suitable for Tazpkg.
   70.42 -genpkg_rules()
   70.43 -{
   70.44 +genpkg_rules() {
   70.45  	case $PACKAGE in
   70.46 -		mpfr) copy @std; DEPENDS="gmp";;
   70.47 +		mpfr)
   70.48 +			copy @std
   70.49 +			DEPENDS="gmp"
   70.50 +			TAGS="LFS"
   70.51 +			;;
   70.52  		*-dev) copy @dev;;
   70.53  	esac
   70.54  }
    71.1 --- a/ncurses/receipt	Wed Feb 21 18:10:55 2018 +0200
    71.2 +++ b/ncurses/receipt	Wed Feb 21 19:48:17 2018 +0200
    71.3 @@ -7,19 +7,17 @@
    71.4  MAINTAINER="pankso@slitaz.org"
    71.5  LICENSE="MIT"
    71.6  WEB_SITE="https://www.gnu.org/software/ncurses/"
    71.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/ncurses.html"
    71.8  
    71.9  TARBALL="$PACKAGE-$VERSION.tar.gz"
   71.10  WGET_URL="http://ftp.gnu.org/gnu/ncurses/$TARBALL"
   71.11 -HOST_ARCH="i486 arm"
   71.12  
   71.13 +BUILD_DEPENDS_arm=" "
   71.14  BUILD_DEPENDS="flex"
   71.15 -BUILD_DEPENDS_arm=""
   71.16  SPLIT="ncurses-libform ncurses-libmenu ncurses-libpanel ncurses-extra \
   71.17  ncurses-dev"
   71.18  
   71.19 -# Rules to configure and make the package.
   71.20 -compile_rules()
   71.21 -{
   71.22 +compile_rules() {
   71.23  	sed -i '/LIBTOOL_INSTALL/d' c++/Makefile.in
   71.24  
   71.25  	./configure \
   71.26 @@ -61,14 +59,13 @@
   71.27  	ln -s xterm-256color $install/usr/share/terminfo/x/xterm
   71.28  }
   71.29  
   71.30 -# Rules to gen a SliTaz package suitable for Tazpkg.
   71.31 -genpkg_rules()
   71.32 -{
   71.33 +genpkg_rules() {
   71.34  	case $PACKAGE in
   71.35  		ncurses)
   71.36  			copy clear tset reset libncursesw.so* tabset/ \
   71.37  			linux xterm xterm-256color
   71.38  			# ansi rxvt vt100 vt102* xterm-color xterm-new xterm-vt220
   71.39 +			TAGS="LFS"
   71.40  			;;
   71.41  		ncurses-libform)
   71.42  			copy libformw.so*
   71.43 @@ -86,8 +83,7 @@
   71.44  			DEPENDS="ncurses"
   71.45  			;;
   71.46  		ncurses-extra)
   71.47 -			copy @std
   71.48 -			remove_already_packed
   71.49 +			copy @std @rm
   71.50  			CAT="base-system|extra files"
   71.51  			DEPENDS="ncurses"
   71.52  			;;
    72.1 --- a/patch/receipt	Wed Feb 21 18:10:55 2018 +0200
    72.2 +++ b/patch/receipt	Wed Feb 21 19:48:17 2018 +0200
    72.3 @@ -7,33 +7,19 @@
    72.4  MAINTAINER="pankso@slitaz.org"
    72.5  LICENSE="GPL3"
    72.6  WEB_SITE="http://savannah.gnu.org/projects/patch/"
    72.7 -HOST_ARCH="i486 arm"
    72.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/patch.html"
    72.9  
   72.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   72.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   72.12  
   72.13  BUILD_DEPENDS="attr-dev"
   72.14  
   72.15 -# Rules to configure and make the package.
   72.16 -compile_rules()
   72.17 -{
   72.18 +compile_rules() {
   72.19  	./configure $CONFIGURE_ARGS && make && make install
   72.20  }
   72.21  
   72.22 -# Rules to gen a SliTaz package suitable for Tazpkg.
   72.23 -genpkg_rules()
   72.24 -{
   72.25 -	copy patch
   72.26 +genpkg_rules() {
   72.27 +	copy @std
   72.28  	DEPENDS="attr"
   72.29 +	TAGS="LFS"
   72.30  }
   72.31 -
   72.32 -## Prevent erasing busybox...
   72.33 -#pre_install()
   72.34 -#{
   72.35 -#	rm -f "$1/usr/bin/patch"
   72.36 -#}
   72.37 -#
   72.38 -#post_remove()
   72.39 -#{
   72.40 -#	ln -s /bin/busybox "$1/usr/bin/patch"
   72.41 -#}
    73.1 --- a/perl-xml-parser/receipt	Wed Feb 21 18:10:55 2018 +0200
    73.2 +++ b/perl-xml-parser/receipt	Wed Feb 21 19:48:17 2018 +0200
    73.3 @@ -7,25 +7,22 @@
    73.4  MAINTAINER="pankso@slitaz.org"
    73.5  LICENSE="GPL"
    73.6  WEB_SITE="https://metacpan.org/release/XML-Parser"
    73.7 -HOST_ARCH="i486 arm"
    73.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/xml-parser.html"
    73.9  
   73.10  TARBALL="XML-Parser-$VERSION.tar.gz"
   73.11  WGET_URL="https://cpan.metacpan.org/authors/id/T/TO/TODDR/$TARBALL"
   73.12  
   73.13 -DEPENDS="perl-libwww-perl expat"
   73.14 -BUILD_DEPENDS="$DEPENDS perl-dev expat-dev"
   73.15 +BUILD_DEPENDS="perl-libwww-perl expat perl-dev expat-dev"
   73.16  
   73.17 -# Rules to configure and make the package.
   73.18 -compile_rules()
   73.19 -{
   73.20 +compile_rules() {
   73.21  	perl Makefile.PL &&
   73.22  	make && make DESTDIR=$install install &&
   73.23  
   73.24  	chmod -R u+w $install
   73.25  }
   73.26  
   73.27 -# Rules to gen a SliTaz package suitable for Tazpkg.
   73.28 -genpkg_rules()
   73.29 -{
   73.30 +genpkg_rules() {
   73.31  	copy @std
   73.32 +	DEPENDS="perl-libwww-perl expat"
   73.33 +	TAGS="LFS"
   73.34  }
    74.1 --- a/perl/receipt	Wed Feb 21 18:10:55 2018 +0200
    74.2 +++ b/perl/receipt	Wed Feb 21 19:48:17 2018 +0200
    74.3 @@ -1,68 +1,91 @@
    74.4  # SliTaz package receipt v2.
    74.5  
    74.6  PACKAGE="perl"
    74.7 -VERSION="5.24.1"
    74.8 +VERSION="5.26.1"
    74.9  CATEGORY="development"
   74.10  SHORT_DESC="Perl interpreter and modules"
   74.11  MAINTAINER="pankso@slitaz.org"
   74.12  LICENSE="GPL"
   74.13  WEB_SITE="https://www.perl.org/"
   74.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/perl.html"
   74.15  
   74.16  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   74.17  WGET_URL="http://www.cpan.org/src/5.0/$TARBALL"
   74.18  
   74.19  COOKOPTS="!perlz"
   74.20  BUILD_DEPENDS="zlib-dev bzip2-dev less gdbm-dev"
   74.21 -SPLIT="perl-core perl-dev"
   74.22 -SIBLINGS="microperl perl-thread"
   74.23 +#SPLIT="perl-core perl perl-dev microperl:micro"
   74.24 +SPLIT="perl-core perl perl-dev"
   74.25 +# microperl: waiting for 5.26.2: https://rt.perl.org/Public/Bug/Display.html?id=132255
   74.26 +# sv.c:(.text+0x1aa95): undefined reference to `Perl_fp_class_denorm'
   74.27  
   74.28  # Rules to compile & install the temporary toolchain.
   74.29 -cook_tmp_toolchain()
   74.30 -{
   74.31 +cook_tmp_toolchain() {
   74.32  	cd $src
   74.33 -	{ sh Configure -des -Dprefix=/tools \
   74.34 +	sh Configure -des \
   74.35 +		-Dprefix=/tools \
   74.36  		-Dstatic_ext='Data/Dumper Fcntl IO' &&
   74.37 -	
   74.38 +
   74.39  	# Only few tools are needed in the tmp toolchain.
   74.40 -	make perl utilities ext/Errno/pm_to_blib
   74.41 -	} || return 1
   74.42 +	make perl utilities ext/Errno/pm_to_blib || return 1
   74.43 +
   74.44  	cp perl pod/pod2man /tools/bin
   74.45  	mkdir -p /tools/lib/perl5/$VERSION
   74.46  	cp -R lib/* /tools/lib/perl5/$VERSION
   74.47  }
   74.48  
   74.49 -# Rules to configure and make the package.
   74.50 -compile_rules()
   74.51 -{
   74.52 -	export BUILD_ZLIB=False
   74.53 -	export BUILD_BZIP2=0
   74.54 -	sh Configure -des \
   74.55 -		-Dprefix=/usr \
   74.56 -		-Dvendorprefix=/usr \
   74.57 -		-Dman1dir=/usr/share/man/man1 \
   74.58 -		-Dman3dir=/usr/share/man/man3 \
   74.59 -		-Dpager="/usr/bin/less -isR" \
   74.60 -		-Duseshrplib &&
   74.61 -	make && make install
   74.62 +compile_rules() {
   74.63 +	case $SET in
   74.64 +		micro)
   74.65 +				patch -p1 -i $stuff/microperl.patch
   74.66 +				sed -i.orig "s|usr/local|usr|;
   74.67 +					s|perl5/${VERSION%.*}|perl5/$VERSION|;
   74.68 +					s|unknown|$HOST_SYSTEM|" uconfig.sh uconfig64.sh
   74.69 +
   74.70 +				case $ARCH in
   74.71 +					x86_64) make -f Makefile.micro regen_uconfig64;;
   74.72 +					*)      make -f Makefile.micro regen_uconfig;;
   74.73 +				esac &&
   74.74 +				make -f Makefile.micro &&
   74.75 +				install -Dm755 microperl $install/usr/bin/microperl
   74.76 +				;;
   74.77 +		*)
   74.78 +			export BUILD_ZLIB=False
   74.79 +			export BUILD_BZIP2=0
   74.80 +			sh Configure -des \
   74.81 +				-Dprefix=/usr \
   74.82 +				-Dvendorprefix=/usr \
   74.83 +				-Dman1dir=/usr/share/man/man1 \
   74.84 +				-Dman3dir=/usr/share/man/man3 \
   74.85 +				-Dpager="/usr/bin/less -isR" \
   74.86 +				-Duseshrplib \
   74.87 +				-Dusethreads &&
   74.88 +			make && make install
   74.89 +			;;
   74.90 +	esac
   74.91  }
   74.92  
   74.93 -# Rules to gen a SliTaz package suitable for Tazpkg.
   74.94 -genpkg_rules()
   74.95 -{
   74.96 +genpkg_rules() {
   74.97  	case $PACKAGE in
   74.98 -		perl)
   74.99 -			copy @std
  74.100 -			find $fs \( -name perl -o -name perl$VERSION -o -name libperl.so \) -delete
  74.101 -			DEPENDS="bzlib gdbm zlib perl-core"
  74.102 -			PROVIDE="microperl"
  74.103 -			;;
  74.104  		perl-core)
  74.105 -			# perl binary depends on libperl.so
  74.106  			copy perl perl$VERSION libperl.so
  74.107  			DEPENDS="glibc-base"
  74.108  			CAT="development|minimal interpreter"
  74.109  			;;
  74.110 -		*-dev) copy @dev;;
  74.111 +		perl)
  74.112 +			copy @std @rm
  74.113 +			DEPENDS="bzlib gdbm zlib perl-core"
  74.114 +			PROVIDE="microperl perl-thread"
  74.115 +			TAGS="LFS"
  74.116 +			;;
  74.117 +		*-dev)
  74.118 +			copy @dev
  74.119 +			;;
  74.120 +		microperl)
  74.121 +			copy @std
  74.122 +			CAT="development|micro version"
  74.123 +			DEPENDS="glibc-base"
  74.124 +			;;
  74.125  	esac
  74.126  }
  74.127  
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/perl/stuff/microperl.patch	Wed Feb 21 19:48:17 2018 +0200
    75.3 @@ -0,0 +1,40 @@
    75.4 +--- a/Makefile.micro
    75.5 ++++ b/Makefile.micro
    75.6 +@@ -1,7 +1,7 @@
    75.7 + LD = $(CC)
    75.8 + CCFLAGS = -c
    75.9 + DEFINES = -DPERL_CORE -DPERL_MICRO -DSTANDARD_C -DPERL_USE_SAFE_PUTENV \
   75.10 +-	  -DNO_MATHOMS
   75.11 ++	  -DNO_MATHOMS -DUSE_PERLIO
   75.12 + OPTIMIZE = 
   75.13 + CFLAGS = $(DEFINES) $(OPTIMIZE)
   75.14 + LDFLAGS = 
   75.15 +@@ -14,7 +14,7 @@
   75.16 + 
   75.17 + all:	microperl
   75.18 + 
   75.19 +-O = uav$(_O) udeb$(_O) udoio$(_O) udoop$(_O) udquote$(_O) udump$(_O) \
   75.20 ++O = uav$(_O) ucaretx$(_O) udeb$(_O) udoio$(_O) udoop$(_O) udquote$(_O) udump$(_O) \
   75.21 + 	uglobals$(_O) ugv$(_O) uhv$(_O) umro$(_O)\
   75.22 + 	umg$(_O) uperlmain$(_O) uop$(_O) ureentr$(_O) \
   75.23 + 	upad$(_O) uperl$(_O) uperlio$(_O) uperly$(_O) upp$(_O) \
   75.24 +@@ -66,6 +66,9 @@
   75.25 + 
   75.26 + uav$(_O):	$(HE) av.c
   75.27 + 	$(CC) $(CCFLAGS) -o $@ $(CFLAGS) av.c
   75.28 ++
   75.29 ++ucaretx$(_O):	$(HE) caretx.c
   75.30 ++	$(CC) $(CCFLAGS) -o $@ $(CFLAGS) caretx.c
   75.31 + 
   75.32 + udeb$(_O):	$(HE) deb.c
   75.33 + 	$(CC) $(CCFLAGS) -o $@ $(CFLAGS) deb.c
   75.34 +--- a/EXTERN.h
   75.35 ++++ b/EXTERN.h
   75.36 +@@ -57,3 +57,7 @@
   75.37 + #define INIT(x)
   75.38 + 
   75.39 + #undef DOINIT
   75.40 ++
   75.41 ++#define I_LIMITS
   75.42 ++#define I_FCNTL
   75.43 ++#define I_FLOAT
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/perl/stuff/miniperlmain.patch	Wed Feb 21 19:48:17 2018 +0200
    76.3 @@ -0,0 +1,16 @@
    76.4 +--- miniperlmain.c.orig
    76.5 ++++ miniperlmain.c
    76.6 +@@ -117,13 +117,6 @@
    76.7 +     if (!exitstatus)
    76.8 +         perl_run(my_perl);
    76.9 + 
   76.10 +-    /* Unregister our signal handler before destroying my_perl */
   76.11 +-    for (i = 0; PL_sig_name[i]; i++) {
   76.12 +-	if (rsignal_state(PL_sig_num[i]) == (Sighandler_t) PL_csighandlerp) {
   76.13 +-	    rsignal(PL_sig_num[i], (Sighandler_t) SIG_DFL);
   76.14 +-	}
   76.15 +-    }
   76.16 +-
   76.17 +     exitstatus = perl_destruct(my_perl);
   76.18 + 
   76.19 +     perl_free(my_perl);
    77.1 --- a/pkg-config/receipt	Wed Feb 21 18:10:55 2018 +0200
    77.2 +++ b/pkg-config/receipt	Wed Feb 21 19:48:17 2018 +0200
    77.3 @@ -1,23 +1,21 @@
    77.4  # SliTaz package receipt v2.
    77.5  
    77.6  PACKAGE="pkg-config"
    77.7 -VERSION="0.29.1"
    77.8 +VERSION="0.29.2"
    77.9  CATEGORY="development"
   77.10  SHORT_DESC="Free desktop packages manager"
   77.11  MAINTAINER="pankso@slitaz.org"
   77.12  LICENSE="GPL2"
   77.13  WEB_SITE="https://www.freedesktop.org/wiki/Software/pkg-config/"
   77.14 -HOST_ARCH="i486 arm"
   77.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/pkg-config.html"
   77.16  
   77.17  TARBALL="$PACKAGE-$VERSION.tar.gz"
   77.18  WGET_URL="https://pkg-config.freedesktop.org/releases/$TARBALL"
   77.19  
   77.20 +BUILD_DEPENDS_arm=" "
   77.21  BUILD_DEPENDS="gcc libtool perl"
   77.22 -BUILD_DEPENDS_arm=" "
   77.23  
   77.24 -# Rules to configure and make the package.
   77.25 -compile_rules()
   77.26 -{
   77.27 +compile_rules() {
   77.28  	case "$ARCH" in
   77.29  		arm)
   77.30  			./configure \
   77.31 @@ -27,13 +25,9 @@
   77.32  				--cache-file=arm-linux.cache ;;
   77.33  		*)
   77.34  			./configure \
   77.35 -				--prefix=/usr \
   77.36  				--with-internal-glib \
   77.37 -				--disable-compile-warnings \
   77.38  				--disable-host-tool \
   77.39 -				--docdir=/usr/share/doc/pkg-config-$VERSION \
   77.40 -				--build=$HOST_SYSTEM \
   77.41 -				--host=$HOST_SYSTEM
   77.42 +				$CONFIGURE_ARGS
   77.43  				;;
   77.44  	esac &&
   77.45  	make && make install
   77.46 @@ -43,9 +37,8 @@
   77.47  	ln -s ${TOOLPREFIX}pkg-config pkg-config
   77.48  }
   77.49  
   77.50 -# Rules to gen a SliTaz package suitable for Tazpkg.
   77.51 -genpkg_rules()
   77.52 -{
   77.53 +genpkg_rules() {
   77.54  	copy @std @dev
   77.55  	DEPENDS="glibc-base"
   77.56 +	TAGS="LFS"
   77.57  }
    78.1 --- a/procps-ng/receipt	Wed Feb 21 18:10:55 2018 +0200
    78.2 +++ b/procps-ng/receipt	Wed Feb 21 19:48:17 2018 +0200
    78.3 @@ -7,6 +7,7 @@
    78.4  MAINTAINER="al.bobylev@gmail.com"
    78.5  LICENSE="GPL2 LGPL2"
    78.6  WEB_SITE="https://gitlab.com/procps-ng/procps"
    78.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/procps-ng.html"
    78.8  
    78.9  TARBALL="$PACKAGE-$VERSION.tar.xz"
   78.10  WGET_URL="$SF_MIRROR/$PACKAGE/$TARBALL"
   78.11 @@ -14,17 +15,15 @@
   78.12  BUILD_DEPENDS="gettext ncurses-dev"
   78.13  SPLIT="procps-ng-dev"
   78.14  
   78.15 -# Rules to configure and make the package.
   78.16 -compile_rules()
   78.17 -{
   78.18 +compile_rules() {
   78.19 +#		--docdir=/usr/share/doc/procps-ng-$VERSION \
   78.20  	./configure \
   78.21  		--exec-prefix= \
   78.22  		--libdir=/usr/lib \
   78.23 -		--docdir=/usr/share/doc/procps-ng-$VERSION \
   78.24  		--disable-static \
   78.25  		--disable-kill \
   78.26  		$CONFIGURE_ARGS &&
   78.27 -	make && make install
   78.28 +	make && make install || return 1
   78.29  
   78.30  	mkdir -p $install/lib
   78.31  	mv $install/usr/lib/libprocps.so.* $install/lib
   78.32 @@ -32,13 +31,12 @@
   78.33  		$install/usr/lib/libprocps.so
   78.34  }
   78.35  
   78.36 -# Rules to gen a SliTaz package suitable for Tazpkg.
   78.37 -genpkg_rules()
   78.38 -{
   78.39 +genpkg_rules() {
   78.40  	case $PACKAGE in
   78.41  		procps-ng)
   78.42  			copy @std
   78.43  			DEPENDS="gettext-base ncurses"
   78.44 +			TAGS="LFS"
   78.45  			;;
   78.46  		*-dev) copy @dev;;
   78.47  	esac
    79.1 --- a/psmisc/receipt	Wed Feb 21 18:10:55 2018 +0200
    79.2 +++ b/psmisc/receipt	Wed Feb 21 19:48:17 2018 +0200
    79.3 @@ -1,21 +1,20 @@
    79.4  # SliTaz package receipt v2.
    79.5  
    79.6  PACKAGE="psmisc"
    79.7 -VERSION="22.21"
    79.8 +VERSION="23.1"
    79.9  CATEGORY="system-tools"
   79.10  SHORT_DESC="PSmisc - Small utilities that use the /proc filesystem"
   79.11  MAINTAINER="al.bobylev@gmail.com"
   79.12  LICENSE="GPL2"
   79.13  WEB_SITE="http://psmisc.sourceforge.net/"
   79.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/psmisc.html"
   79.15  
   79.16 -TARBALL="$PACKAGE-$VERSION.tar.gz"
   79.17 +TARBALL="$PACKAGE-$VERSION.tar.xz"
   79.18  WGET_URL="$SF_MIRROR/psmisc/$TARBALL"
   79.19  
   79.20  BUILD_DEPENDS="gettext ncurses-dev"
   79.21  
   79.22 -# Rules to configure and make the package.
   79.23 -compile_rules()
   79.24 -{
   79.25 +compile_rules() {
   79.26  	./configure $CONFIGURE_ARGS && make && make install
   79.27  
   79.28  	mkdir -p $install/bin
   79.29 @@ -23,9 +22,8 @@
   79.30  	mv $install/usr/bin/killall $install/bin
   79.31  }
   79.32  
   79.33 -# Rules to gen a SliTaz package suitable for Tazpkg.
   79.34 -genpkg_rules()
   79.35 -{
   79.36 +genpkg_rules() {
   79.37  	copy @std
   79.38  	DEPENDS="ncurses"
   79.39 +	TAGS="LFS"
   79.40  }
    80.1 --- a/readline/receipt	Wed Feb 21 18:10:55 2018 +0200
    80.2 +++ b/readline/receipt	Wed Feb 21 19:48:17 2018 +0200
    80.3 @@ -6,8 +6,8 @@
    80.4  SHORT_DESC="GNU readline"
    80.5  MAINTAINER="pankso@slitaz.org"
    80.6  LICENSE="GPL3"
    80.7 -WEB_SITE="http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html"
    80.8 -HOST_ARCH="i486 arm"
    80.9 +WEB_SITE="https://www.gnu.org/software/readline"
   80.10 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/readline.html"
   80.11  
   80.12  TARBALL="$PACKAGE-$VERSION.tar.gz"
   80.13  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   80.14 @@ -15,9 +15,7 @@
   80.15  BUILD_DEPENDS="ncurses-dev flex"
   80.16  SPLIT="readline-dev"
   80.17  
   80.18 -# Rules to configure and make the package.
   80.19 -compile_rules()
   80.20 -{
   80.21 +compile_rules() {
   80.22  	case "$ARCH" in
   80.23  		arm*) export bash_cv_wcwidth_broken=true ;;
   80.24  	esac
   80.25 @@ -27,30 +25,31 @@
   80.26  
   80.27  	./configure \
   80.28  		--disable-static \
   80.29 -		--libdir=/lib \
   80.30 -		--docdir=/usr/share/doc/readline-$VERSION \
   80.31  		$CONFIGURE_ARGS &&
   80.32 -	make SHLIB_LIBS=-lncurses &&
   80.33 -	make DESTDIR=$install install
   80.34 +	make SHLIB_LIBS="-lncursesw" &&
   80.35 +	make SHLIB_LIBS="-lncurses" DESTDIR=$install install || return 1
   80.36  
   80.37 -	# *.so.* -> /lib
   80.38 -	# *.so   -> /usr/lib
   80.39 -	mkdir -p $install/usr/lib
   80.40 -	ln -sfv ../../lib/$(readlink $install/lib/libreadline.so) \
   80.41 -		$install/usr/lib/libreadline.so
   80.42 -	ln -sfv ../../lib/$(readlink $install/lib/libhistory.so ) \
   80.43 -		$install/usr/lib/libhistory.so
   80.44 -	rm $install/lib/*.so
   80.45 +	mkdir -p $install/lib
   80.46 +	for i in readline history; do
   80.47 +		mv -v $install/usr/lib/lib$i.so.* $install/lib
   80.48 +		ln -sf ../../lib/$(readlink $install/usr/lib/lib$i.so) \
   80.49 +			$install/usr/lib/lib$i.so
   80.50 +	done
   80.51 +
   80.52 +	find $install -type f -name '*.so*' -exec chmod 755 '{}' \;
   80.53 +	rmdir --ignore-fail-on-non-empty $install/usr/bin/
   80.54  
   80.55  	# install the documentation
   80.56 -	cp doc/*.pdf doc/*.html $install/usr/share/doc/readline-7.0
   80.57 +	cook_pick_docs doc/*.pdf doc/*.html
   80.58  }
   80.59  
   80.60 -# Rules to gen a SliTaz package suitable for Tazpkg.
   80.61 -genpkg_rules()
   80.62 -{
   80.63 +genpkg_rules() {
   80.64  	case $PACKAGE in
   80.65 -		readline) copy @std; DEPENDS="ncurses";;
   80.66 +		readline)
   80.67 +			copy @std
   80.68 +			DEPENDS="ncurses"
   80.69 +			TAGS="LFS"
   80.70 +			;;
   80.71  		*-dev) copy @dev;;
   80.72  	esac
   80.73  }
    81.1 --- a/sed/receipt	Wed Feb 21 18:10:55 2018 +0200
    81.2 +++ b/sed/receipt	Wed Feb 21 19:48:17 2018 +0200
    81.3 @@ -7,29 +7,27 @@
    81.4  MAINTAINER="paul@slitaz.org"
    81.5  LICENSE="GPL3"
    81.6  WEB_SITE="https://www.gnu.org/software/sed/"
    81.7 -HOST_ARCH="i486 arm"
    81.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/sed.html"
    81.9  
   81.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   81.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   81.12  
   81.13  BUILD_DEPENDS="acl-dev gettext texinfo"
   81.14  
   81.15 -# Rules to configure and make the package.
   81.16 -compile_rules()
   81.17 -{
   81.18 +compile_rules() {
   81.19  	# Rebuild after patching
   81.20  	msgfmt po/ru.po -o po/ru.gmo
   81.21  
   81.22  	./configure \
   81.23  		--bindir=/bin \
   81.24 -		--htmldir=/usr/share/doc/sed-$VERSION \
   81.25  		$CONFIGURE_ARGS &&
   81.26 -	make $MAKEFLAGS && make html && make install && make -C doc install-html
   81.27 +	make $MAKEFLAGS && make html && make install || return 1
   81.28 +
   81.29 +	cook_pick_docs doc/sed.html
   81.30  }
   81.31  
   81.32 -# Rules to gen a SliTaz package suitable for Tazpkg.
   81.33 -genpkg_rules()
   81.34 -{
   81.35 +genpkg_rules() {
   81.36  	copy @std
   81.37  	DEPENDS="acl"
   81.38 +	TAGS="LFS"
   81.39  }
    82.1 --- a/shadow/receipt	Wed Feb 21 18:10:55 2018 +0200
    82.2 +++ b/shadow/receipt	Wed Feb 21 19:48:17 2018 +0200
    82.3 @@ -7,16 +7,21 @@
    82.4  MAINTAINER="al.bobylev@gmail.com"
    82.5  LICENSE="BSD"
    82.6  WEB_SITE="http://pkg-shadow.alioth.debian.org/"
    82.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/shadow.html"
    82.8  
    82.9  TARBALL="$PACKAGE-$VERSION.tar.xz"
   82.10  WGET_URL="https://github.com/shadow-maint/shadow/releases/download/$VERSION/$TARBALL"
   82.11  
   82.12 -DEPENDS="acl attr"
   82.13  BUILD_DEPENDS="acl-dev attr-dev gettext"
   82.14  
   82.15 -# Rules to configure and make the package.
   82.16 -compile_rules()
   82.17 -{
   82.18 +compile_rules() {
   82.19 +	# Disable the installation of the `groups` program and its man pages, as
   82.20 +	# Coreutils provides a better version.
   82.21 +	sed -i 's/groups$(EXEEXT) //' src/Makefile.in
   82.22 +	find man -name Makefile.in -exec sed -i 's/groups\.1 / /'   {} \;
   82.23 +	find man -name Makefile.in -exec sed -i 's/getspnam\.3 / /' {} \;
   82.24 +	find man -name Makefile.in -exec sed -i 's/passwd\.5 / /'   {} \;
   82.25 +
   82.26  	sed -i -e 's|#ENCRYPT_METHOD DES|ENCRYPT_METHOD SHA512|' \
   82.27  		-e 's|/var/spool/mail|/var/mail|' etc/login.defs
   82.28  	sed -i 's|bash|sh|' etc/useradd
   82.29 @@ -29,8 +34,8 @@
   82.30  	mv $install/usr/bin/passwd $install/bin
   82.31  }
   82.32  
   82.33 -# Rules to gen a SliTaz package suitable for Tazpkg.
   82.34 -genpkg_rules()
   82.35 -{
   82.36 +genpkg_rules() {
   82.37  	copy @std
   82.38 +	DEPENDS="acl attr"
   82.39 +	TAGS="LFS"
   82.40  }
    83.1 --- a/sysklogd/receipt	Wed Feb 21 18:10:55 2018 +0200
    83.2 +++ b/sysklogd/receipt	Wed Feb 21 19:48:17 2018 +0200
    83.3 @@ -7,13 +7,12 @@
    83.4  MAINTAINER="al.bobylev@gmail.com"
    83.5  LICENSE="GPL2"
    83.6  WEB_SITE="http://www.infodrom.org/projects/sysklogd/"
    83.7 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/sysklogd.html"
    83.8  
    83.9  TARBALL="$PACKAGE-$VERSION.tar.gz"
   83.10  WGET_URL="${WEB_SITE}download/$TARBALL"
   83.11  
   83.12 -# Rules to configure and make the package.
   83.13 -compile_rules()
   83.14 -{
   83.15 +compile_rules() {
   83.16  	sed -i '/Error loading kernel symbols/{n;n;d}' ksym_mod.c
   83.17  	sed -i 's/union wait/int/' syslogd.c
   83.18  	mkdir -p $install/sbin $install/usr/share/man/man5 $install/usr/share/man/man8
   83.19 @@ -24,8 +23,7 @@
   83.20  	cp $stuff/syslog.conf $install/etc
   83.21  }
   83.22  
   83.23 -# Rules to gen a SliTaz package suitable for Tazpkg.
   83.24 -genpkg_rules()
   83.25 -{
   83.26 +genpkg_rules() {
   83.27  	copy @std
   83.28 +	TAGS="LFS"
   83.29  }
    84.1 --- a/tar/receipt	Wed Feb 21 18:10:55 2018 +0200
    84.2 +++ b/tar/receipt	Wed Feb 21 19:48:17 2018 +0200
    84.3 @@ -7,16 +7,14 @@
    84.4  MAINTAINER="pankso@slitaz.org"
    84.5  LICENSE="GPL3"
    84.6  WEB_SITE="https://www.gnu.org/software/tar/"
    84.7 -HOST_ARCH="i486 arm"
    84.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/tar.html"
    84.9  
   84.10  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   84.11  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   84.12  
   84.13  BUILD_DEPENDS="acl-dev gettext texinfo"
   84.14  
   84.15 -# Rules to configure and make the package.
   84.16 -compile_rules()
   84.17 -{
   84.18 +compile_rules() {
   84.19  	FORCE_UNSAFE_CONFIGURE=1 \
   84.20  	./configure \
   84.21  		--bindir=/bin \
   84.22 @@ -25,10 +23,8 @@
   84.23  	make -C doc install-html docdir=/usr/share/doc/tar-$VERSION
   84.24  }
   84.25  
   84.26 -# Rules to gen a SliTaz package suitable for Tazpkg.
   84.27 -genpkg_rules()
   84.28 -{
   84.29 +genpkg_rules() {
   84.30  	copy @std
   84.31  	DEPENDS="acl attr"
   84.32 -	TAGS="archive compression"
   84.33 +	TAGS="LFS archive compression"
   84.34  }
    85.1 --- a/texinfo/receipt	Wed Feb 21 18:10:55 2018 +0200
    85.2 +++ b/texinfo/receipt	Wed Feb 21 19:48:17 2018 +0200
    85.3 @@ -1,31 +1,28 @@
    85.4  # SliTaz package receipt v2.
    85.5  
    85.6  PACKAGE="texinfo"
    85.7 -VERSION="6.3"
    85.8 +VERSION="6.4"
    85.9  CATEGORY="development"
   85.10  SHORT_DESC="GNU documentation tools"
   85.11  MAINTAINER="rcx@zoominternet.net"
   85.12  LICENSE="GPL3"
   85.13  WEB_SITE="https://www.gnu.org/software/texinfo/"
   85.14 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/texinfo.html"
   85.15  
   85.16  TARBALL="$PACKAGE-$VERSION.tar.xz"
   85.17  WGET_URL="$GNU_MIRROR/$PACKAGE/$TARBALL"
   85.18  
   85.19  BUILD_DEPENDS="perl-dev ncurses-dev gettext"
   85.20  
   85.21 -# Rules to configure and make the package.
   85.22 -compile_rules()
   85.23 -{
   85.24 +compile_rules() {
   85.25  	./configure \
   85.26  		--disable-static \
   85.27  		$CONFIGURE_ARGS &&
   85.28  	make && make install
   85.29  }
   85.30  
   85.31 -# Rules to gen a SliTaz package suitable for Tazpkg.
   85.32 -genpkg_rules()
   85.33 -{
   85.34 +genpkg_rules() {
   85.35  	copy @std @dev
   85.36  	DEPENDS="perl"
   85.37 -	TAGS="documentation"
   85.38 +	TAGS="LFS documentation"
   85.39  }
    86.1 --- a/util-linux/receipt	Wed Feb 21 18:10:55 2018 +0200
    86.2 +++ b/util-linux/receipt	Wed Feb 21 19:48:17 2018 +0200
    86.3 @@ -1,13 +1,13 @@
    86.4  # SliTaz package receipt v2.
    86.5  
    86.6  PACKAGE="util-linux"
    86.7 -VERSION="2.30.0"
    86.8 +VERSION="2.30.1"
    86.9  CATEGORY="meta"
   86.10  SHORT_DESC="Random collection of Linux utilities"
   86.11  MAINTAINER="pankso@slitaz.org"
   86.12  LICENSE="GPL2 LGPL2.1 BSD PublicDomain"
   86.13  WEB_SITE="https://en.wikipedia.org/wiki/Util-linux"
   86.14 -HOST_ARCH="i486 arm"
   86.15 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/util-linux.html"
   86.16  
   86.17  TARBALL="$PACKAGE-${VERSION%.0}.tar.xz"
   86.18  WGET_URL="https://www.kernel.org/pub/linux/utils/util-linux/v${VERSION%.*}/$TARBALL"
   86.19 @@ -23,9 +23,7 @@
   86.20  util-linux-sfdisk util-linux-smartcols util-linux-smartcols-dev \
   86.21  util-linux-uuid util-linux-uuid-dev util-linux-whereis util-linux-misc"
   86.22  
   86.23 -# Rules to configure and make the package.
   86.24 -compile_rules()
   86.25 -{
   86.26 +compile_rules() {
   86.27  	# Fix undeclared 'LINE_MAX'
   86.28  	case "$ARCH" in
   86.29  		arm) sed -i s'|LINE_MAX|25|' text-utils/*.c ;;
   86.30 @@ -44,9 +42,7 @@
   86.31  	cp $stuff/cfdisk.desktop $install/usr/share/applications
   86.32  }
   86.33  
   86.34 -# Rules to gen a SliTaz package suitable for Tazpkg.
   86.35 -genpkg_rules()
   86.36 -{
   86.37 +genpkg_rules() {
   86.38  	case ${PACKAGE#util-linux-} in
   86.39  		bash-completion)
   86.40  			copy bash-completion/
   86.41 @@ -182,10 +178,12 @@
   86.42  			DEPENDS="glibc-base"
   86.43  			;;
   86.44  		misc)
   86.45 -			copy @std @dev
   86.46 -			remove_already_packed
   86.47 +			copy @std @dev @rm
   86.48  			CAT="system-tools|misc utilities"
   86.49  			;;
   86.50 +		util-linux)
   86.51 +			TAGS="LFS"
   86.52 +			;;
   86.53  	esac
   86.54  
   86.55  	if [ "$PACKAGE" != 'util-linux-bash-completion' -a -d "$fs/usr/share/bash-completion" ]; then
    87.1 --- a/xz/receipt	Wed Feb 21 18:10:55 2018 +0200
    87.2 +++ b/xz/receipt	Wed Feb 21 19:48:17 2018 +0200
    87.3 @@ -7,8 +7,7 @@
    87.4  MAINTAINER="pascal.bellard@slitaz.org"
    87.5  LICENSE="PublicDomain LGPL2.1 GPL2 GPL3"
    87.6  WEB_SITE="https://tukaani.org/xz/"
    87.7 -TAGS="compression archive"
    87.8 -HOST_ARCH="i486 arm x86_64"
    87.9 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/xz.html"
   87.10  
   87.11  TARBALL="$PACKAGE-$VERSION.tar.xz"
   87.12  WGET_URL="$WEB_SITE$TARBALL"
   87.13 @@ -16,15 +15,12 @@
   87.14  BUILD_DEPENDS="gettext"
   87.15  SPLIT="xz-tools xz liblzma xz-dev"
   87.16  
   87.17 -# Rules to configure and make the package.
   87.18 -compile_rules()
   87.19 -{
   87.20 +compile_rules() {
   87.21  	./configure \
   87.22  		--disable-static \
   87.23 -		--docdir=/usr/share/doc/xz-$VERSION \
   87.24  		--enable-small \
   87.25  		$CONFIGURE_ARGS &&
   87.26 -	make && make install
   87.27 +	make && make install || return 1
   87.28  
   87.29  	mkdir -p $install/bin $install/lib
   87.30  	for i in lzma unlzma lzcat xz unxz xzcat; do
   87.31 @@ -35,9 +31,7 @@
   87.32  		$install/usr/lib/liblzma.so
   87.33  }
   87.34  
   87.35 -# Rules to gen a SliTaz package suitable for Tazpkg.
   87.36 -genpkg_rules()
   87.37 -{
   87.38 +genpkg_rules() {
   87.39  	case $PACKAGE in
   87.40  		xz-tools)
   87.41  			copy /usr/bin/
   87.42 @@ -45,9 +39,9 @@
   87.43  			DEPENDS="liblzma"
   87.44  			;;
   87.45  		xz)
   87.46 -			copy bin/
   87.47 -			remove_already_packed
   87.48 +			copy bin/ @rm
   87.49  			DEPENDS="liblzma"
   87.50 +			TAGS="LFS compression archive"
   87.51  			;;
   87.52  		liblzma)
   87.53  			copy liblzma.so*
    88.1 --- a/zlib/receipt	Wed Feb 21 18:10:55 2018 +0200
    88.2 +++ b/zlib/receipt	Wed Feb 21 19:48:17 2018 +0200
    88.3 @@ -7,19 +7,17 @@
    88.4  MAINTAINER="pankso@slitaz.org"
    88.5  LICENSE="zlib/libpng"
    88.6  WEB_SITE="http://www.zlib.net/"
    88.7 -HOST_ARCH="i486 arm x86_64"
    88.8 +LFS="http://www.linuxfromscratch.org/lfs/view/stable/chapter06/zlib.html"
    88.9  
   88.10  TARBALL="$PACKAGE-$VERSION.tar.xz"
   88.11  WGET_URL="$WEB_SITE$TARBALL"
   88.12  
   88.13  SPLIT="zlib-dev"
   88.14  
   88.15 -# Rules to configure and make the package.
   88.16 -compile_rules()
   88.17 -{
   88.18 +compile_rules() {
   88.19  	./configure \
   88.20  		--prefix=/usr &&
   88.21 -	make && make install
   88.22 +	make && make install || return 1
   88.23  
   88.24  	mkdir -p $install/lib
   88.25  	mv -v $install/usr/lib/libz.so.* $install/lib
   88.26 @@ -28,17 +26,13 @@
   88.27  }
   88.28  
   88.29  # Important cross compiled package so run readelf.
   88.30 -testsuite()
   88.31 -{
   88.32 -	cd $install
   88.33 -	readelf -h lib/*.so.$VERSION
   88.34 +testsuite() {
   88.35 +	readelf -h $install/lib/libz.so.$VERSION
   88.36  }
   88.37  
   88.38 -# Rules to gen a SliTaz package suitable for Tazpkg.
   88.39 -genpkg_rules()
   88.40 -{
   88.41 +genpkg_rules() {
   88.42  	case $PACKAGE in
   88.43 -		zlib) copy @std ;;
   88.44 -		zlib-dev) copy @dev ;;
   88.45 +		zlib)  copy @std; TAGS="LFS";;
   88.46 +		*-dev) copy @dev;;
   88.47  	esac
   88.48  }