diff --git a/coreutils-8.24-i18n-1.patch b/coreutils-8.25-i18n-1.patch similarity index 62% rename from coreutils-8.24-i18n-1.patch rename to coreutils-8.25-i18n-1.patch index 6f3c8e4..2d68d92 100644 --- a/coreutils-8.24-i18n-1.patch +++ b/coreutils-8.25-i18n-1.patch @@ -1,14 +1,37 @@ -Submitted by: Matt Burgess (matthew_at_linuxfromscratch_dot_org) -Date: 2013-12-16 -Initial Package Version: 8.22 (Rebased for version 8.24 by bdubbs@linuxfromscratch.org 2015-704) +Submitted by: DJ Lucas (dj_AT_linuxfromscratch_DOT_org) +Date: 2016-01-22 +Initial Package Version: 8.22 Upstream Status: Rejected -Origin: Based on Fedora's i18n patch at - http://pkgs.fedoraproject.org/cgit/coreutils.git/plain/coreutils-i18n.patch +Origin: Based on Fedora's i18n patches at + http://pkgs.fedoraproject.org/cgit/rpms/coreutils.git/tree/ Description: Fixes several i18n issues with various Coreutils programs -diff -Naur coreutils-8.24/lib/linebuffer.h coreutils-8.24-mod/lib/linebuffer.h ---- coreutils-8.24/lib/linebuffer.h 2015-06-16 00:00:37.000000000 -0500 -+++ coreutils-8.24-mod/lib/linebuffer.h 2015-07-04 15:08:33.513055809 -0500 +diff -Naurp coreutils-8.25-orig/bootstrap.conf coreutils-8.25/bootstrap.conf +--- coreutils-8.25-orig/bootstrap.conf 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/bootstrap.conf 2016-01-22 21:23:04.634308804 -0600 +@@ -151,6 +151,7 @@ gnulib_modules=" + maintainer-makefile + malloc-gnu + manywarnings ++ mbfile + mbrlen + mbrtowc + mbsalign +diff -Naurp coreutils-8.25-orig/configure.ac coreutils-8.25/configure.ac +--- coreutils-8.25-orig/configure.ac 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/configure.ac 2016-01-22 21:23:04.634308804 -0600 +@@ -425,6 +425,8 @@ fi + # I'm leaving it here for now. This whole thing needs to be modernized... + gl_WINSIZE_IN_PTEM + ++gl_MBFILE ++ + gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H + + if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \ +diff -Naurp coreutils-8.25-orig/lib/linebuffer.h coreutils-8.25/lib/linebuffer.h +--- coreutils-8.25-orig/lib/linebuffer.h 2016-01-01 07:45:55.000000000 -0600 ++++ coreutils-8.25/lib/linebuffer.h 2016-01-22 21:23:04.597639947 -0600 @@ -21,6 +21,11 @@ # include @@ -21,7 +44,7 @@ diff -Naur coreutils-8.24/lib/linebuffer.h coreutils-8.24-mod/lib/linebuffer.h /* A 'struct linebuffer' holds a line of text. */ struct linebuffer -@@ -28,6 +33,9 @@ +@@ -28,6 +33,9 @@ struct linebuffer size_t size; /* Allocated. */ size_t length; /* Used. */ char *buffer; @@ -31,465 +54,819 @@ diff -Naur coreutils-8.24/lib/linebuffer.h coreutils-8.24-mod/lib/linebuffer.h }; /* Initialize linebuffer LINEBUFFER for use. */ -diff -Naur coreutils-8.24/src/cut.c coreutils-8.24-mod/src/cut.c ---- coreutils-8.24/src/cut.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/cut.c 2015-07-04 15:08:33.514055775 -0500 +diff -Naurp coreutils-8.25-orig/lib/mbfile.c coreutils-8.25/lib/mbfile.c +--- coreutils-8.25-orig/lib/mbfile.c 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/lib/mbfile.c 2016-01-22 21:23:04.644309401 -0600 +@@ -0,0 +1,3 @@ ++#include ++#define MBFILE_INLINE _GL_EXTERN_INLINE ++#include "mbfile.h" +diff -Naurp coreutils-8.25-orig/lib/mbfile.h coreutils-8.25/lib/mbfile.h +--- coreutils-8.25-orig/lib/mbfile.h 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/lib/mbfile.h 2016-01-22 21:23:04.644309401 -0600 +@@ -0,0 +1,255 @@ ++/* Multibyte character I/O: macros for multi-byte encodings. ++ Copyright (C) 2001, 2005, 2009-2015 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Mitsuru Chinen ++ and Bruno Haible . */ ++ ++/* The macros in this file implement multi-byte character input from a ++ stream. ++ ++ mb_file_t ++ is the type for multibyte character input stream, usable for variable ++ declarations. ++ ++ mbf_char_t ++ is the type for multibyte character or EOF, usable for variable ++ declarations. ++ ++ mbf_init (mbf, stream) ++ initializes the MB_FILE for reading from stream. ++ ++ mbf_getc (mbc, mbf) ++ reads the next multibyte character from mbf and stores it in mbc. ++ ++ mb_iseof (mbc) ++ returns true if mbc represents the EOF value. ++ ++ Here are the function prototypes of the macros. ++ ++ extern void mbf_init (mb_file_t mbf, FILE *stream); ++ extern void mbf_getc (mbf_char_t mbc, mb_file_t mbf); ++ extern bool mb_iseof (const mbf_char_t mbc); ++ */ ++ ++#ifndef _MBFILE_H ++#define _MBFILE_H 1 ++ ++#include ++#include ++#include ++#include ++ ++/* Tru64 with Desktop Toolkit C has a bug: must be included before ++ . ++ BSD/OS 4.1 has a bug: and must be included before ++ . */ ++#include ++#include ++#include ++ ++#include "mbchar.h" ++ ++#ifndef _GL_INLINE_HEADER_BEGIN ++ #error "Please include config.h first." ++#endif ++_GL_INLINE_HEADER_BEGIN ++#ifndef MBFILE_INLINE ++# define MBFILE_INLINE _GL_INLINE ++#endif ++ ++struct mbfile_multi { ++ FILE *fp; ++ bool eof_seen; ++ bool have_pushback; ++ mbstate_t state; ++ unsigned int bufcount; ++ char buf[MBCHAR_BUF_SIZE]; ++ struct mbchar pushback; ++}; ++ ++MBFILE_INLINE void ++mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf) ++{ ++ size_t bytes; ++ ++ /* If EOF has already been seen, don't use getc. This matters if ++ mbf->fp is connected to an interactive tty. */ ++ if (mbf->eof_seen) ++ goto eof; ++ ++ /* Return character pushed back, if there is one. */ ++ if (mbf->have_pushback) ++ { ++ mb_copy (mbc, &mbf->pushback); ++ mbf->have_pushback = false; ++ return; ++ } ++ ++ /* Before using mbrtowc, we need at least one byte. */ ++ if (mbf->bufcount == 0) ++ { ++ int c = getc (mbf->fp); ++ if (c == EOF) ++ { ++ mbf->eof_seen = true; ++ goto eof; ++ } ++ mbf->buf[0] = (unsigned char) c; ++ mbf->bufcount++; ++ } ++ ++ /* Handle most ASCII characters quickly, without calling mbrtowc(). */ ++ if (mbf->bufcount == 1 && mbsinit (&mbf->state) && is_basic (mbf->buf[0])) ++ { ++ /* These characters are part of the basic character set. ISO C 99 ++ guarantees that their wide character code is identical to their ++ char code. */ ++ mbc->wc = mbc->buf[0] = mbf->buf[0]; ++ mbc->wc_valid = true; ++ mbc->ptr = &mbc->buf[0]; ++ mbc->bytes = 1; ++ mbf->bufcount = 0; ++ return; ++ } ++ ++ /* Use mbrtowc on an increasing number of bytes. Read only as many bytes ++ from mbf->fp as needed. This is needed to give reasonable interactive ++ behaviour when mbf->fp is connected to an interactive tty. */ ++ for (;;) ++ { ++ /* We don't know whether the 'mbrtowc' function updates the state when ++ it returns -2, - this is the ISO C 99 and glibc-2.2 behaviour - or ++ not - amended ANSI C, glibc-2.1 and Solaris 2.7 behaviour. We ++ don't have an autoconf test for this, yet. ++ The new behaviour would allow us to feed the bytes one by one into ++ mbrtowc. But the old behaviour forces us to feed all bytes since ++ the end of the last character into mbrtowc. Since we want to retry ++ with more bytes when mbrtowc returns -2, we must backup the state ++ before calling mbrtowc, because implementations with the new ++ behaviour will clobber it. */ ++ mbstate_t backup_state = mbf->state; ++ ++ bytes = mbrtowc (&mbc->wc, &mbf->buf[0], mbf->bufcount, &mbf->state); ++ ++ if (bytes == (size_t) -1) ++ { ++ /* An invalid multibyte sequence was encountered. */ ++ /* Return a single byte. */ ++ bytes = 1; ++ mbc->wc_valid = false; ++ break; ++ } ++ else if (bytes == (size_t) -2) ++ { ++ /* An incomplete multibyte character. */ ++ mbf->state = backup_state; ++ if (mbf->bufcount == MBCHAR_BUF_SIZE) ++ { ++ /* An overlong incomplete multibyte sequence was encountered. */ ++ /* Return a single byte. */ ++ bytes = 1; ++ mbc->wc_valid = false; ++ break; ++ } ++ else ++ { ++ /* Read one more byte and retry mbrtowc. */ ++ int c = getc (mbf->fp); ++ if (c == EOF) ++ { ++ /* An incomplete multibyte character at the end. */ ++ mbf->eof_seen = true; ++ bytes = mbf->bufcount; ++ mbc->wc_valid = false; ++ break; ++ } ++ mbf->buf[mbf->bufcount] = (unsigned char) c; ++ mbf->bufcount++; ++ } ++ } ++ else ++ { ++ if (bytes == 0) ++ { ++ /* A null wide character was encountered. */ ++ bytes = 1; ++ assert (mbf->buf[0] == '\0'); ++ assert (mbc->wc == 0); ++ } ++ mbc->wc_valid = true; ++ break; ++ } ++ } ++ ++ /* Return the multibyte sequence mbf->buf[0..bytes-1]. */ ++ mbc->ptr = &mbc->buf[0]; ++ memcpy (&mbc->buf[0], &mbf->buf[0], bytes); ++ mbc->bytes = bytes; ++ ++ mbf->bufcount -= bytes; ++ if (mbf->bufcount > 0) ++ { ++ /* It's not worth calling memmove() for so few bytes. */ ++ unsigned int count = mbf->bufcount; ++ char *p = &mbf->buf[0]; ++ ++ do ++ { ++ *p = *(p + bytes); ++ p++; ++ } ++ while (--count > 0); ++ } ++ return; ++ ++eof: ++ /* An mbchar_t with bytes == 0 is used to indicate EOF. */ ++ mbc->ptr = NULL; ++ mbc->bytes = 0; ++ mbc->wc_valid = false; ++ return; ++} ++ ++MBFILE_INLINE void ++mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf) ++{ ++ mb_copy (&mbf->pushback, mbc); ++ mbf->have_pushback = true; ++} ++ ++typedef struct mbfile_multi mb_file_t; ++ ++typedef mbchar_t mbf_char_t; ++ ++#define mbf_init(mbf, stream) \ ++ ((mbf).fp = (stream), \ ++ (mbf).eof_seen = false, \ ++ (mbf).have_pushback = false, \ ++ memset (&(mbf).state, '\0', sizeof (mbstate_t)), \ ++ (mbf).bufcount = 0) ++ ++#define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf)) ++ ++#define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf)) ++ ++#define mb_iseof(mbc) ((mbc).bytes == 0) ++ ++#ifndef _GL_INLINE_HEADER_BEGIN ++ #error "Please include config.h first." ++#endif ++_GL_INLINE_HEADER_BEGIN ++ ++#endif /* _MBFILE_H */ +diff -Naurp coreutils-8.25-orig/m4/mbfile.m4 coreutils-8.25/m4/mbfile.m4 +--- coreutils-8.25-orig/m4/mbfile.m4 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/m4/mbfile.m4 2016-01-22 21:23:04.640975869 -0600 +@@ -0,0 +1,14 @@ ++# mbfile.m4 serial 7 ++dnl Copyright (C) 2005, 2008-2015 Free Software Foundation, Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++dnl autoconf tests required for use of mbfile.h ++dnl From Bruno Haible. ++ ++AC_DEFUN([gl_MBFILE], ++[ ++ AC_REQUIRE([AC_TYPE_MBSTATE_T]) ++ : ++]) +diff -Naurp coreutils-8.25-orig/po/POTFILES.in coreutils-8.25/po/POTFILES.in +--- coreutils-8.25-orig/po/POTFILES.in 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/po/POTFILES.in 2016-01-22 21:23:04.634308804 -0600 +@@ -57,6 +57,7 @@ src/dirname.c + src/du.c + src/echo.c + src/env.c ++src/expand-core.c + src/expand.c + src/expr.c + src/factor.c +diff -Naurp coreutils-8.25-orig/src/cut.c coreutils-8.25/src/cut.c +--- coreutils-8.25-orig/src/cut.c 2016-01-13 05:08:59.000000000 -0600 ++++ coreutils-8.25/src/cut.c 2016-01-22 21:23:04.630975272 -0600 @@ -28,6 +28,11 @@ #include #include #include + -+/* Get mbstate_t, mbrtowc(). */ -+#if HAVE_WCHAR_H -+# include -+#endif ++#include ++#include ++#include ++ #include "system.h" #include "error.h" -@@ -37,6 +42,18 @@ - #include "quote.h" - #include "xstrndup.h" +@@ -61,25 +66,16 @@ + CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */ + static struct field_range_pair *current_rp; -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC -+ installation; work around this configuration error. */ -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 -+# undef MB_LEN_MAX -+# define MB_LEN_MAX 16 -+#endif -+ -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ -+#if HAVE_MBRTOWC && defined mbstate_t -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -+#endif -+ - /* The official name of this program (e.g., no 'g' prefix). */ - #define PROGRAM_NAME "cut" - -@@ -53,6 +70,52 @@ - } \ - while (0) - -+/* Refill the buffer BUF to get a multibyte character. */ -+#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM) \ -+ do \ -+ { \ -+ if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM)) \ -+ { \ -+ memmove (BUF, BUFPOS, BUFLEN); \ -+ BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \ -+ BUFPOS = BUF; \ -+ } \ -+ } \ -+ while (0) -+ -+/* Get wide character on BUFPOS. BUFPOS is not included after that. -+ If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */ -+#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \ -+ do \ -+ { \ -+ mbstate_t state_bak; \ -+ \ -+ if (BUFLEN < 1) \ -+ { \ -+ WC = WEOF; \ -+ break; \ -+ } \ -+ \ -+ /* Get a wide character. */ \ -+ CONVFAIL = false; \ -+ state_bak = STATE; \ -+ MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE); \ -+ \ -+ switch (MBLENGTH) \ -+ { \ -+ case (size_t)-1: \ -+ case (size_t)-2: \ -+ CONVFAIL = true; \ -+ STATE = state_bak; \ -+ /* Fall througn. */ \ -+ \ -+ case 0: \ -+ MBLENGTH = 1; \ -+ break; \ -+ } \ -+ } \ -+ while (0) -+ - - struct range_pair - { -@@ -75,6 +138,8 @@ - /* Number of `struct range_pair's allocated. */ - static size_t n_rp_allocated; - -+/* Length of the delimiter given as argument to -d. */ -+size_t delimlen; - - /* Append LOW, HIGH to the list RP of range pairs, allocating additional - space if necessary. Update global variable N_RP. When allocating, -@@ -106,15 +171,25 @@ +-/* This buffer is used to support the semantics of the -s option +- (or lack of same) when the specified field list includes (does +- not include) the first field. In both of those cases, the entire +- first field must be read into this buffer to determine whether it +- is followed by a delimiter or a newline before any of it may be +- output. Otherwise, cut_fields can do the job without using this +- buffer. */ +-static char *field_1_buffer; +- +-/* The number of bytes allocated for FIELD_1_BUFFER. */ +-static size_t field_1_bufsize; +- + enum operating_mode { undefined_mode, - /* Output characters that are in the given bytes. */ -+ /* Output bytes that are at the given positions. */ ++ /* Output the given bytes. */ byte_mode, -+ /* Output characters that are at the given positions. */ -+ character_mode, ++ /* Output characters that are in the given positions . */ ++ char_mode, + /* Output the given delimiter-separated fields. */ field_mode }; - - static enum operating_mode operating_mode; - -+/* If nonzero, when in byte mode, don't split multibyte characters. */ -+static int byte_mode_character_aware; -+ -+/* If nonzero, the function for single byte locale is work -+ if this program runs on multibyte locale. */ -+static int force_singlebyte_mode; -+ - /* If true do not output lines containing no delimiter characters. - Otherwise, all such lines are printed. This option is valid only +@@ -91,12 +87,16 @@ static enum operating_mode operating_mod with field mode. */ -@@ -126,6 +201,9 @@ + static bool suppress_non_delimited; + ++/* Unless true, we do not recognize multibyte characters in byte-splitting ++ mode. */ ++static bool no_break_mb_chars; ++ + /* If true, print all bytes, characters, or fields _except_ + those that were specified. */ + static bool complement; /* The delimiter character for field mode. */ - static unsigned char delim; -+#if HAVE_WCHAR_H -+static wchar_t wcdelim; -+#endif +-static unsigned char delim; ++static mbf_char_t delim; - /* True if the --output-delimiter=STRING option was specified. */ - static bool output_delimiter_specified; -@@ -189,7 +267,7 @@ + /* The delimiter for each line/record. */ + static unsigned char line_delim = '\n'; +@@ -109,7 +109,7 @@ static size_t output_delimiter_length; + + /* The output field separator string. Defaults to the 1-character + string consisting of the input delimiter. */ +-static char *output_delimiter_string; ++static char const *output_delimiter_string; + + /* True if we have ever read standard input. */ + static bool have_read_stdin; +@@ -164,7 +164,7 @@ Print selected parts of lines from each -f, --fields=LIST select only these fields; also print any line\n\ that contains no delimiter character, unless\n\ the -s option is specified\n\ - -n (ignored)\n\ -+ -n with -b: don't split multibyte characters\n\ ++ -n with -b, don't split multibyte characters\n\ "), stdout); fputs (_("\ --complement complement the set of selected bytes, characters\n\ -@@ -380,6 +458,9 @@ - if (operating_mode == byte_mode) - error (0, 0, - _("byte offset %s is too large"), quote (bad_num)); -+ else if (operating_mode == character_mode) -+ error (0, 0, -+ _("character offset %s is too large"), quote (bad_num)); - else - error (0, 0, - _("field number %s is too large"), quote (bad_num)); -@@ -504,6 +585,82 @@ - } +@@ -211,6 +211,12 @@ next_item (size_t *item_idx) + current_rp++; } -+#if HAVE_MBRTOWC -+/* This function is in use for the following case. -+ -+ 1. Read from the stream STREAM, printing to standard output any selected -+ characters. -+ -+ 2. Read from stream STREAM, printing to standard output any selected bytes, -+ without splitting multibyte characters. */ -+ -+static void -+cut_characters_or_cut_bytes_no_split (FILE *stream) ++static inline void ++next_item_n (size_t *item_idx, size_t n) +{ -+ size_t idx; /* number of bytes or characters in the line so far. */ -+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ -+ char *bufpos; /* Next read position of BUF. */ -+ size_t buflen; /* The length of the byte sequence in buf. */ -+ wint_t wc; /* A gotten wide character. */ -+ size_t mblength; /* The byte size of a multibyte character which shows -+ as same character as WC. */ -+ mbstate_t state; /* State of the stream. */ -+ bool convfail = false; /* true, when conversion failed. Otherwise false. */ -+ /* Whether to begin printing delimiters between ranges for the current line. -+ Set after we've begun printing data corresponding to the first range. */ -+ bool print_delimiter = false; -+ -+ idx = 0; -+ buflen = 0; -+ bufpos = buf; -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ current_rp = rp; -+ -+ while (1) -+ { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail); -+ (void) convfail; /* ignore unused */ -+ -+ if (wc == WEOF) -+ { -+ if (idx > 0) -+ putchar ('\n'); -+ break; -+ } -+ else if (wc == L'\n') -+ { -+ putchar ('\n'); -+ idx = 0; -+ print_delimiter = false; -+ current_rp = rp; -+ } -+ else -+ { -+ next_item (&idx); -+ if (print_kth (idx)) -+ { -+ if (output_delimiter_specified) -+ { -+ if (print_delimiter && is_range_start_index (idx)) -+ { -+ fwrite (output_delimiter_string, sizeof (char), -+ output_delimiter_length, stdout); -+ } -+ print_delimiter = true; -+ } -+ fwrite (bufpos, mblength, sizeof(char), stdout); -+ } -+ } -+ -+ buflen -= mblength; -+ bufpos += mblength; -+ } ++ while (n-- > 0) ++ next_item (item_idx); ++} + /* Return nonzero if the K'th field or byte is printable. */ + + static inline bool +@@ -219,6 +225,15 @@ print_kth (size_t k) + return current_rp->lo <= k; + } + ++/* The lo and hi params should be used for the current characters byte position ++ * and byte size, respectively. */ ++static inline bool ++rp_intersect (size_t lo, size_t hi) ++{ ++ return ((current_rp->lo <= lo && current_rp->hi >= lo) ++ || (current_rp->lo <= hi && current_rp->hi >= hi)); +} -+#endif + + /* Return nonzero if K'th byte is the beginning of a range. */ + + static inline bool +@@ -281,23 +296,216 @@ cut_bytes (FILE *stream) + } + /* Read from stream STREAM, printing to standard output any selected fields. */ - - static void -@@ -648,13 +805,211 @@ - } - } - -+#if HAVE_MBRTOWC -+static void -+cut_fields_mb (FILE *stream) ++extern ssize_t ++mb_getndelim2 (mbf_char_t **lineptr, size_t *linesize, size_t nmax, ++ mbf_char_t delim1, mbf_char_t delim2, mb_file_t *stream) +{ -+ int c; -+ size_t field_idx; -+ int found_any_selected_field; -+ int buffer_first_field; -+ int empty_input; -+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ -+ char *bufpos; /* Next read position of BUF. */ -+ size_t buflen; /* The length of the byte sequence in buf. */ -+ wint_t wc = 0; /* A gotten wide character. */ -+ size_t mblength; /* The byte size of a multibyte character which shows -+ as same character as WC. */ -+ mbstate_t state; /* State of the stream. */ -+ bool convfail = false; /* true, when conversion failed. Otherwise false. */ ++/* The maximum value that getndelim2 can return without suffering from ++ overflow problems, either internally (because of pointer ++ subtraction overflow) or due to the API (because of ssize_t). */ ++#define GETNDELIM2_MAXIMUM (PTRDIFF_MAX < SSIZE_MAX ? PTRDIFF_MAX : SSIZE_MAX) + -+ current_rp = rp; ++/* Try to add at least this many bytes when extending the buffer. ++ MIN_CHUNK must be no greater than GETNDELIM2_MAXIMUM. */ ++#define MIN_CHUNK 64 ++ size_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */ ++ mbf_char_t *read_pos; /* Where we're reading into *LINEPTR. */ ++ ssize_t chars_stored = -1; ++ mbf_char_t *ptr = *lineptr; ++ size_t size = *linesize; ++ bool found_delimiter; + -+ found_any_selected_field = 0; -+ field_idx = 1; -+ bufpos = buf; -+ buflen = 0; -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ c = getc (stream); -+ empty_input = (c == EOF); -+ if (c != EOF) -+ { -+ ungetc (c, stream); -+ wc = 0; -+ } -+ else -+ wc = WEOF; -+ -+ /* To support the semantics of the -s flag, we may have to buffer -+ all of the first field to determine whether it is `delimited.' -+ But that is unnecessary if all non-delimited lines must be printed -+ and the first field has been selected, or if non-delimited lines -+ must be suppressed and the first field has *not* been selected. -+ That is because a non-delimited line has exactly one field. */ -+ buffer_first_field = (suppress_non_delimited ^ !print_kth (1)); -+ -+ while (1) ++ if (!ptr) + { -+ if (field_idx == 1 && buffer_first_field) ++ size = nmax < MIN_CHUNK ? nmax : MIN_CHUNK; ++ ptr = malloc (size * sizeof (mbf_char_t)); ++ if (!ptr) ++ return -1; ++ } ++ ++ if (size < 0) ++ goto done; ++ ++ nchars_avail = size; ++ read_pos = ptr; ++ ++ if (nchars_avail == 0 && nmax <= size) ++ goto done; ++ ++ /* Normalize delimiters, since memchr2 doesn't handle EOF. */ ++ if (mb_iseof (delim1)) ++ mb_copy (&delim1, &delim2); ++ else if (mb_iseof (delim2)) ++ mb_copy (&delim2, &delim1); ++ ++ flockfile (stream); ++ ++ found_delimiter = false; ++ do ++ { ++ /* Here always ptr + size == read_pos + nchars_avail. ++ Also nchars_avail > 0 || size < nmax. */ ++ ++ mbf_char_t c IF_LINT (= 0); + { -+ int len = 0; -+ -+ while (1) ++ mbf_getc (c, *stream); ++ if (mb_iseof (c)) + { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER -+ (wc, bufpos, buflen, mblength, state, convfail); -+ -+ if (wc == WEOF) -+ break; -+ -+ field_1_buffer = xrealloc (field_1_buffer, len + mblength); -+ memcpy (field_1_buffer + len, bufpos, mblength); -+ len += mblength; -+ buflen -= mblength; -+ bufpos += mblength; -+ -+ if (!convfail && (wc == L'\n' || wc == wcdelim)) -+ break; -+ } -+ -+ if (len <= 0 && wc == WEOF) -+ break; -+ -+ /* If the first field extends to the end of line (it is not -+ delimited) and we are printing all non-delimited lines, -+ print this one. */ -+ if (convfail || (!convfail && wc != wcdelim)) -+ { -+ if (suppress_non_delimited) -+ { -+ /* Empty. */ -+ } ++ /* Return partial line, if any. */ ++ if (read_pos == ptr) ++ goto unlock_done; + else -+ { -+ fwrite (field_1_buffer, sizeof (char), len, stdout); -+ /* Make sure the output line is newline terminated. */ -+ if (convfail || (!convfail && wc != L'\n')) -+ putchar ('\n'); -+ } -+ continue; -+ } -+ -+ if (print_kth (1)) -+ { -+ /* Print the field, but not the trailing delimiter. */ -+ fwrite (field_1_buffer, sizeof (char), len - 1, stdout); -+ found_any_selected_field = 1; -+ } -+ next_item (&field_idx); -+ } -+ -+ if (wc != WEOF) -+ { -+ if (print_kth (field_idx)) -+ { -+ if (found_any_selected_field) -+ { -+ fwrite (output_delimiter_string, sizeof (char), -+ output_delimiter_length, stdout); -+ } -+ found_any_selected_field = 1; -+ } -+ -+ while (1) -+ { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER -+ (wc, bufpos, buflen, mblength, state, convfail); -+ -+ if (wc == WEOF) + break; -+ else if (!convfail && (wc == wcdelim || wc == L'\n')) -+ { -+ buflen -= mblength; -+ bufpos += mblength; -+ break; -+ } -+ -+ if (print_kth (field_idx)) -+ fwrite (bufpos, mblength, sizeof(char), stdout); -+ -+ buflen -= mblength; -+ bufpos += mblength; + } ++ if (mb_equal (c, delim1) || mb_equal (c, delim2)) ++ found_delimiter = true; + } + -+ if ((!convfail || wc == L'\n') && buflen < 1) -+ wc = WEOF; ++ /* We always want at least one byte left in the buffer, since we ++ always (unless we get an error while reading the first byte) ++ NUL-terminate the line buffer. */ + -+ if (!convfail && wc == wcdelim) -+ next_item (&field_idx); -+ else if (wc == WEOF || (!convfail && wc == L'\n')) ++ if (!nchars_avail) + { -+ if (found_any_selected_field -+ || (!empty_input && !(suppress_non_delimited && field_idx == 1))) -+ putchar ('\n'); -+ if (wc == WEOF) -+ break; -+ field_idx = 1; -+ current_rp = rp; -+ found_any_selected_field = 0; ++ /* Grow size proportionally, not linearly, to avoid O(n^2) ++ running time. */ ++ size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size; ++ mbf_char_t *newptr; ++ ++ /* Respect nmax. This handles possible integer overflow. */ ++ if (! (size < newsize && newsize <= nmax)) ++ newsize = nmax; ++ ++ if (GETNDELIM2_MAXIMUM < newsize) ++ { ++ size_t newsizemax = GETNDELIM2_MAXIMUM + 1; ++ if (size == newsizemax) ++ goto unlock_done; ++ newsize = newsizemax; ++ } ++ nchars_avail = newsize - (read_pos - ptr); ++ newptr = realloc (ptr, newsize * sizeof (mbf_char_t)); ++ if (!newptr) ++ goto unlock_done; ++ ptr = newptr; ++ size = newsize; ++ read_pos = size - nchars_avail + ptr; + } ++ ++ /* Here, if size < nmax, nchars_avail >= buffer_len + 1. ++ If size == nmax, nchars_avail > 0. */ ++ ++ if (1 < nchars_avail) ++ { ++ mb_copy(read_pos++, &c); ++ --nchars_avail; ++ } ++ ++ } ++ while (!found_delimiter); ++ ++ chars_stored = (read_pos - ptr); ++ ++ unlock_done: ++ funlockfile (stream); ++ ++ done: ++ *lineptr = ptr; ++ *linesize = size; ++ return chars_stored; ++} ++ ++static void ++cut_chars (FILE *stream) ++{ ++ size_t char_idx; /* Number of chars in the line so far. */ ++ bool print_delimiter; ++ mbf_char_t c; ++ mb_file_t mbf; ++ ++ print_delimiter = false; ++ char_idx = 0; ++ current_rp = frp; ++ ++ mbf_init (mbf, stream); ++ while (true) ++ { ++ mbf_getc (c, mbf); ++ ++ if (mb_iseq (c, line_delim)) ++ { ++ putc (line_delim, stdout); ++ char_idx = 0; ++ print_delimiter = false; ++ current_rp = frp; ++ } ++ else if (mb_iseof (c)) ++ { ++ if (char_idx > 0) ++ putc (line_delim, stdout); ++ break; ++ } ++ else ++ { ++ /* Forward by one byte. */ ++ next_item (&char_idx); ++ ++ /* Check if the current characters byte range is within ++ * the argument list. */ ++ if (rp_intersect (char_idx, char_idx + mb_len (c) - 1)) ++ { ++ if (output_delimiter_specified) ++ { ++ if (print_delimiter && is_range_start_index (char_idx)) ++ { ++ fwrite (output_delimiter_string, sizeof (char), ++ output_delimiter_length, stdout); ++ } ++ print_delimiter = true; ++ } ++ mb_putc (c, stdout); ++ } ++ ++ /* Byte mode with multibyte characters uncut (-b -n). */ ++ if (no_break_mb_chars) ++ /* Forward by an additional byte_length (c) - 1. */ ++ next_item_n (&char_idx, mb_len (c) - 1); ++ } + } +} -+#endif -+ + static void + cut_fields (FILE *stream) + { +- int c; ++ ++ /* This buffer is used to support the semantics of the -s option ++ (or lack of same) when the specified field list includes (does ++ not include) the first field. In both of those cases, the entire ++ first field must be read into this buffer to determine whether it ++ is followed by a delimiter or a newline before any of it may be ++ output. Otherwise, cut_fields can do the job without using this ++ buffer. */ ++ mbf_char_t *field_1_buffer = 0; ++ /* The number of bytes allocated for FIELD_1_BUFFER. */ ++ size_t field_1_bufsize; ++ ++ ++ mbf_char_t c, d; ++ mb_file_t mbf; + size_t field_idx = 1; + bool found_any_selected_field = false; + bool buffer_first_field; + + current_rp = frp; + +- c = getc (stream); +- if (c == EOF) ++ mbf_init (mbf, stream); ++ mbf_getc (c, mbf); ++ if (mb_iseof (c)) + return; + +- ungetc (c, stream); +- c = 0; ++ mbf_ungetc (c, mbf); ++ mb_setascii (&c, 0); ++ mb_copy (&d, &delim); + + /* To support the semantics of the -s flag, we may have to buffer + all of the first field to determine whether it is 'delimited.' +@@ -312,10 +520,14 @@ cut_fields (FILE *stream) + if (field_idx == 1 && buffer_first_field) + { + ssize_t len; +- size_t n_bytes; ++ size_t n_chars; ++ mbf_char_t nl; ++ mb_setascii (&nl, line_delim); ++ ++ len = mb_getndelim2 (&field_1_buffer, &field_1_bufsize, ++ GETNLINE_NO_LIMIT, d, nl, &mbf); ++ + +- len = getndelim2 (&field_1_buffer, &field_1_bufsize, 0, +- GETNLINE_NO_LIMIT, delim, line_delim, stream); + if (len < 0) + { + free (field_1_buffer); +@@ -325,15 +537,15 @@ cut_fields (FILE *stream) + xalloc_die (); + } + +- n_bytes = len; +- assert (n_bytes != 0); ++ n_chars = len; ++ //assert (n_chars != 0); + +- c = 0; ++ mb_setascii (&c, 0); + + /* If the first field extends to the end of line (it is not + delimited) and we are printing all non-delimited lines, + print this one. */ +- if (to_uchar (field_1_buffer[n_bytes - 1]) != delim) ++ if (!mb_equal (field_1_buffer[n_chars - 1], d)) + { + if (suppress_non_delimited) + { +@@ -341,26 +553,30 @@ cut_fields (FILE *stream) + } + else + { +- fwrite (field_1_buffer, sizeof (char), n_bytes, stdout); ++ for (int i = 0; i < n_chars; ++i) ++ mb_putc (field_1_buffer[i], stdout); ++ + /* Make sure the output line is newline terminated. */ +- if (field_1_buffer[n_bytes - 1] != line_delim) ++ if (!mb_iseq (field_1_buffer[n_chars - 1], line_delim)) + putchar (line_delim); +- c = line_delim; ++ mb_setascii (&c, line_delim); + } + continue; + } + if (print_kth (1)) + { + /* Print the field, but not the trailing delimiter. */ +- fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout); ++ for (int i = 0; i < n_chars - 1; ++i) ++ mb_putc (field_1_buffer[i], stdout); + + /* With -d$'\n' don't treat the last '\n' as a delimiter. */ +- if (delim == line_delim) ++ if (mb_iseq (d, line_delim)) + { +- int last_c = getc (stream); +- if (last_c != EOF) ++ mbf_char_t last_c; ++ mbf_getc (last_c, mbf); ++ if (!mb_iseof (last_c)) + { +- ungetc (last_c, stream); ++ mbf_ungetc (last_c, mbf); + found_any_selected_field = true; + } + } +@@ -370,7 +586,8 @@ cut_fields (FILE *stream) + next_item (&field_idx); + } + +- int prev_c = c; ++ mbf_char_t prev_c; ++ mb_copy (&prev_c, &c); + + if (print_kth (field_idx)) + { +@@ -381,42 +598,46 @@ cut_fields (FILE *stream) + } + found_any_selected_field = true; + +- while ((c = getc (stream)) != delim && c != line_delim && c != EOF) ++ mbf_getc (c, mbf); ++ while (!mb_equal (c, d) && !mb_iseq (c, line_delim) && !mb_iseof (c)) + { +- putchar (c); +- prev_c = c; ++ mb_putc (c, stdout); ++ mb_copy (&prev_c, &c); ++ mbf_getc (c, mbf); + } + } + else + { +- while ((c = getc (stream)) != delim && c != line_delim && c != EOF) ++ mbf_getc (c, mbf); ++ while (!mb_equal (c, d) && !mb_iseq (c, line_delim) && !mb_iseof (c)) + { +- prev_c = c; ++ mb_copy (&prev_c, &c); ++ mbf_getc (c, mbf); + } + } + + /* With -d$'\n' don't treat the last '\n' as a delimiter. */ +- if (delim == line_delim && c == delim) ++ if (mb_iseq (d, line_delim) && mb_equal (c, d)) + { +- int last_c = getc (stream); +- if (last_c != EOF) +- ungetc (last_c, stream); ++ mbf_char_t last_c; ++ mbf_getc (last_c, mbf); ++ if (!mb_iseof (last_c)) ++ mbf_ungetc (last_c, mbf); + else +- c = last_c; ++ mb_copy (&c, &last_c); + } + +- if (c == delim) ++ if (mb_equal (c, d)) + next_item (&field_idx); +- else if (c == line_delim || c == EOF) ++ else if (mb_iseq (c, line_delim) || mb_iseof (c)) + { + if (found_any_selected_field + || !(suppress_non_delimited && field_idx == 1)) + { +- if (c == line_delim || prev_c != line_delim +- || delim == line_delim) ++ if (mb_iseq (c, line_delim) || !mb_iseq (prev_c, line_delim) || mb_iseq (d, line_delim)) + putchar (line_delim); + } +- if (c == EOF) ++ if (mb_iseof (c)) + break; + field_idx = 1; + current_rp = frp; +@@ -429,7 +650,14 @@ static void cut_stream (FILE *stream) { -- if (operating_mode == byte_mode) + if (operating_mode == byte_mode) - cut_bytes (stream); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) + { -+ switch (operating_mode) -+ { -+ case byte_mode: -+ if (byte_mode_character_aware) -+ cut_characters_or_cut_bytes_no_split (stream); -+ else -+ cut_bytes (stream); -+ break; -+ -+ case character_mode: -+ cut_characters_or_cut_bytes_no_split (stream); -+ break; -+ -+ case field_mode: -+ if (delimlen == 1) -+ { -+ /* Check if we have utf8 multibyte locale, so we can use this -+ optimization because of uniqueness of characters, which is -+ not true for e.g. SJIS */ -+ char * loc = setlocale(LC_CTYPE, NULL); -+ if (loc && (strstr (loc, "UTF-8") || strstr (loc, "utf-8") || -+ strstr (loc, "UTF8") || strstr (loc, "utf8"))) -+ { -+ cut_fields (stream); -+ break; -+ } -+ } -+ cut_fields_mb (stream); -+ break; -+ -+ default: -+ abort (); -+ } -+ } - else -- cut_fields (stream); -+#endif -+ { -+ if (operating_mode == field_mode) -+ cut_fields (stream); ++ if (no_break_mb_chars) ++ cut_chars (stream); + else -+ cut_bytes (stream); ++ cut_bytes (stream); + } ++ else if (operating_mode == char_mode) ++ cut_chars (stream); + else + cut_fields (stream); } - - /* Process file FILE to standard output. -@@ -706,6 +1061,7 @@ +@@ -483,6 +711,7 @@ main (int argc, char **argv) bool ok; bool delim_specified = false; char *spec_list_string IF_LINT ( = NULL); -+ char mbdelim[MB_LEN_MAX + 1]; ++ mbi_iterator_t iter; initialize_main (&argc, &argv); set_program_name (argv[0]); -@@ -728,7 +1084,6 @@ +@@ -496,8 +725,10 @@ main (int argc, char **argv) + + /* By default, all non-delimited lines are printed. */ + suppress_non_delimited = false; ++ /* Default behaviour for -b, unless -n is also specified. */ ++ no_break_mb_chars = false; + +- delim = '\0'; ++ mb_setascii (&delim, '\0'); + have_read_stdin = false; + + while ((optc = getopt_long (argc, argv, "b:c:d:f:nsz", longopts, NULL)) != -1) +@@ -505,7 +736,6 @@ main (int argc, char **argv) switch (optc) { case 'b': @@ -497,86 +874,55 @@ diff -Naur coreutils-8.24/src/cut.c coreutils-8.24-mod/src/cut.c /* Build the byte list. */ if (operating_mode != undefined_mode) FATAL_ERROR (_("only one type of list may be specified")); -@@ -736,6 +1091,14 @@ +@@ -513,6 +743,14 @@ main (int argc, char **argv) spec_list_string = optarg; break; + case 'c': -+ /* Build the character list. */ ++ /* Build the char list. */ + if (operating_mode != undefined_mode) + FATAL_ERROR (_("only one type of list may be specified")); -+ operating_mode = character_mode; ++ operating_mode = char_mode; + spec_list_string = optarg; + break; + case 'f': /* Build the field list. */ if (operating_mode != undefined_mode) -@@ -747,10 +1110,38 @@ +@@ -524,9 +762,17 @@ main (int argc, char **argv) case 'd': /* New delimiter. */ /* Interpret -d '' to mean 'use the NUL byte as the delimiter.' */ - if (optarg[0] != '\0' && optarg[1] != '\0') -- FATAL_ERROR (_("the delimiter must be a single character")); ++ mbi_init (iter, optarg, strlen (optarg)); ++ if (!mbi_avail (iter)) ++ mb_setascii (&delim, '\0'); ++ else ++ { ++ mb_copy (&delim, &mbi_cur (iter)); ++ ++ mbi_advance (iter); ++ if (mbi_avail (iter)) + FATAL_ERROR (_("the delimiter must be a single character")); - delim = optarg[0]; -- delim_specified = true; -+ { -+#if HAVE_MBRTOWC -+ if(MB_CUR_MAX > 1) -+ { -+ mbstate_t state; -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state); -+ -+ if (delimlen == (size_t)-1 || delimlen == (size_t)-2) -+ ++force_singlebyte_mode; -+ else -+ { -+ delimlen = (delimlen < 1) ? 1 : delimlen; -+ if (wcdelim != L'\0' && *(optarg + delimlen) != '\0') -+ FATAL_ERROR (_("the delimiter must be a single character")); -+ memcpy (mbdelim, optarg, delimlen); -+ mbdelim[delimlen] = '\0'; -+ if (delimlen == 1) -+ delim = *optarg; -+ } -+ } -+ -+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) -+#endif -+ { -+ if (optarg[0] != '\0' && optarg[1] != '\0') -+ FATAL_ERROR (_("the delimiter must be a single character")); -+ delim = (unsigned char) optarg[0]; -+ } -+ delim_specified = true; -+ } ++ } + delim_specified = true; break; - case OUTPUT_DELIMITER_OPTION: -@@ -763,6 +1154,7 @@ +@@ -540,6 +786,7 @@ main (int argc, char **argv) break; case 'n': -+ byte_mode_character_aware = 1; ++ no_break_mb_chars = true; break; case 's': -@@ -802,15 +1194,34 @@ - } +@@ -579,15 +826,12 @@ main (int argc, char **argv) + | (complement ? SETFLD_COMPLEMENT : 0) ); if (!delim_specified) - delim = '\t'; -+ { -+ delim = '\t'; -+#ifdef HAVE_MBRTOWC -+ wcdelim = L'\t'; -+ mbdelim[0] = '\t'; -+ mbdelim[1] = '\0'; -+ delimlen = 1; -+#endif -+ } ++ mb_setascii (&delim, '\t'); if (output_delimiter_string == NULL) { @@ -585,227 +931,521 @@ diff -Naur coreutils-8.24/src/cut.c coreutils-8.24-mod/src/cut.c - dummy[1] = '\0'; - output_delimiter_string = dummy; - output_delimiter_length = 1; -+#ifdef HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) -+ { -+ output_delimiter_string = xstrdup(mbdelim); -+ output_delimiter_length = delimlen; -+ } -+ -+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) -+#endif -+ { -+ static char dummy[2]; -+ dummy[0] = delim; -+ dummy[1] = '\0'; -+ output_delimiter_string = dummy; -+ output_delimiter_length = 1; -+ } ++ output_delimiter_string = mb_ptr (delim); ++ output_delimiter_length = mb_len (delim); } if (optind == argc) -diff -Naur coreutils-8.24/src/expand.c coreutils-8.24-mod/src/expand.c ---- coreutils-8.24/src/expand.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/expand.c 2015-07-04 15:08:33.514055775 -0500 -@@ -37,12 +37,34 @@ +diff -Naurp coreutils-8.25-orig/src/expand.c coreutils-8.25/src/expand.c +--- coreutils-8.25-orig/src/expand.c 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/src/expand.c 2016-01-22 21:23:04.637642337 -0600 +@@ -37,12 +37,16 @@ #include #include #include + -+/* Get mbstate_t, mbrtowc(), wcwidth(). */ -+#if HAVE_WCHAR_H -+# include -+#endif -+ -+/* Get iswblank(). */ -+#if HAVE_WCTYPE_H -+# include -+#endif ++#include + #include "system.h" #include "error.h" #include "fadvise.h" - #include "quote.h" +-#include "quote.h" #include "xstrndup.h" -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC -+ installation; work around this configuration error. */ -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 -+# define MB_LEN_MAX 16 -+#endif -+ -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ -+#if HAVE_MBRTOWC && defined mbstate_t -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -+#endif ++#include "expand-core.h" + /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "expand" -@@ -357,6 +379,142 @@ +@@ -58,17 +62,17 @@ static uintmax_t tab_size; + /* Array of the explicit column numbers of the tab stops; + after 'tab_list' is exhausted, each additional tab is replaced + by a space. The first column is column 0. */ +-static uintmax_t *tab_list; ++uintmax_t *tab_list; + + /* The number of allocated entries in 'tab_list'. */ +-static size_t n_tabs_allocated; ++size_t n_tabs_allocated; + + /* The index of the first invalid element of 'tab_list', + where the next element can be added. */ +-static size_t first_free_tab; ++size_t first_free_tab; + + /* Null-terminated array of input filenames. */ +-static char **file_list; ++char **file_list; + + /* Default for 'file_list' if no files are given on the command line. */ + static char *stdin_argv[] = +@@ -77,10 +81,10 @@ static char *stdin_argv[] = + }; + + /* True if we have ever read standard input. */ +-static bool have_read_stdin; ++bool have_read_stdin; + + /* The desired exit status. */ +-static int exit_status; ++int exit_status; + + static char const shortopts[] = "it:0::1::2::3::4::5::6::7::8::9::"; + +@@ -135,128 +139,6 @@ add_tab_stop (uintmax_t tabval) + tab_list[first_free_tab++] = tabval; + } + +-/* Add the comma or blank separated list of tab stops STOPS +- to the list of tab stops. */ +- +-static void +-parse_tab_stops (char const *stops) +-{ +- bool have_tabval = false; +- uintmax_t tabval IF_LINT ( = 0); +- char const *num_start IF_LINT ( = NULL); +- bool ok = true; +- +- for (; *stops; stops++) +- { +- if (*stops == ',' || isblank (to_uchar (*stops))) +- { +- if (have_tabval) +- add_tab_stop (tabval); +- have_tabval = false; +- } +- else if (ISDIGIT (*stops)) +- { +- if (!have_tabval) +- { +- tabval = 0; +- have_tabval = true; +- num_start = stops; +- } +- +- /* Detect overflow. */ +- if (!DECIMAL_DIGIT_ACCUMULATE (tabval, *stops - '0', uintmax_t)) +- { +- size_t len = strspn (num_start, "0123456789"); +- char *bad_num = xstrndup (num_start, len); +- error (0, 0, _("tab stop is too large %s"), quote (bad_num)); +- free (bad_num); +- ok = false; +- stops = num_start + len - 1; +- } +- } +- else +- { +- error (0, 0, _("tab size contains invalid character(s): %s"), +- quote (stops)); +- ok = false; +- break; +- } +- } +- +- if (!ok) +- exit (EXIT_FAILURE); +- +- if (have_tabval) +- add_tab_stop (tabval); +-} +- +-/* Check that the list of tab stops TABS, with ENTRIES entries, +- contains only nonzero, ascending values. */ +- +-static void +-validate_tab_stops (uintmax_t const *tabs, size_t entries) +-{ +- uintmax_t prev_tab = 0; +- size_t i; +- +- for (i = 0; i < entries; i++) +- { +- if (tabs[i] == 0) +- error (EXIT_FAILURE, 0, _("tab size cannot be 0")); +- if (tabs[i] <= prev_tab) +- error (EXIT_FAILURE, 0, _("tab sizes must be ascending")); +- prev_tab = tabs[i]; +- } +-} +- +-/* Close the old stream pointer FP if it is non-NULL, +- and return a new one opened to read the next input file. +- Open a filename of '-' as the standard input. +- Return NULL if there are no more input files. */ +- +-static FILE * +-next_file (FILE *fp) +-{ +- static char *prev_file; +- char *file; +- +- if (fp) +- { +- if (ferror (fp)) +- { +- error (0, errno, "%s", quotef (prev_file)); +- exit_status = EXIT_FAILURE; +- } +- if (STREQ (prev_file, "-")) +- clearerr (fp); /* Also clear EOF. */ +- else if (fclose (fp) != 0) +- { +- error (0, errno, "%s", quotef (prev_file)); +- exit_status = EXIT_FAILURE; +- } +- } +- +- while ((file = *file_list++) != NULL) +- { +- if (STREQ (file, "-")) +- { +- have_read_stdin = true; +- fp = stdin; +- } +- else +- fp = fopen (file, "r"); +- if (fp) +- { +- prev_file = file; +- fadvise (fp, FADVISE_SEQUENTIAL); +- return fp; +- } +- error (0, errno, "%s", quotef (file)); +- exit_status = EXIT_FAILURE; +- } +- return NULL; +-} +- + /* Change tabs to spaces, writing to stdout. + Read each file in 'file_list', in order. */ + +@@ -265,19 +147,19 @@ expand (void) + { + /* Input stream. */ + FILE *fp = next_file (NULL); ++ mb_file_t mbf; ++ mbf_char_t c; + + if (!fp) + return; + ++ mbf_init (mbf, fp); ++ + while (true) + { +- /* Input character, or EOF. */ +- int c; +- + /* If true, perform translations. */ + bool convert = true; + +- + /* The following variables have valid values only when CONVERT + is true: */ + +@@ -287,17 +169,23 @@ expand (void) + /* Index in TAB_LIST of next tab stop to examine. */ + size_t tab_index = 0; + +- + /* Convert a line of text. */ + + do + { +- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) +- continue; ++ do { ++ mbf_getc (c, mbf); ++ if (mb_iseof (c)) ++ { ++ mbf_init (mbf, fp = next_file (fp)); ++ continue; ++ } ++ } ++ while (false); + + if (convert) + { +- if (c == '\t') ++ if (mb_iseq (c, '\t')) + { + /* Column the next input tab stop is on. */ + uintmax_t next_tab_column; +@@ -328,32 +216,34 @@ expand (void) + if (putchar (' ') < 0) + error (EXIT_FAILURE, errno, _("write error")); + +- c = ' '; ++ mb_setascii (&c, ' '); + } +- else if (c == '\b') ++ else if (mb_iseq (c, '\b')) + { + /* Go back one column, and force recalculation of the + next tab stop. */ + column -= !!column; + tab_index -= !!tab_index; + } +- else ++ /* A leading control character could make us trip over. */ ++ else if (!mb_iscntrl (c)) + { +- column++; ++ column += mb_width (c); + if (!column) + error (EXIT_FAILURE, 0, _("input line is too long")); + } + +- convert &= convert_entire_line || !! isblank (c); ++ convert &= convert_entire_line || mb_isblank (c); + } + +- if (c < 0) ++ if (mb_iseof (c)) + return; + +- if (putchar (c) < 0) ++ mb_putc (c, stdout); ++ if (ferror (stdout)) + error (EXIT_FAILURE, errno, _("write error")); + } +- while (c != '\n'); ++ while (!mb_iseq (c, '\n')); } } -+#if HAVE_MBRTOWC -+static void -+expand_multibyte (void) +@@ -385,19 +275,19 @@ main (int argc, char **argv) + break; + + case 't': +- parse_tab_stops (optarg); ++ parse_tab_stops (optarg, add_tab_stop); + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (optarg) +- parse_tab_stops (optarg - 1); ++ parse_tab_stops (optarg - 1, add_tab_stop); + else + { + char tab_stop[2]; + tab_stop[0] = c; + tab_stop[1] = '\0'; +- parse_tab_stops (tab_stop); ++ parse_tab_stops (tab_stop, add_tab_stop); + } + break; + +diff -Naurp coreutils-8.25-orig/src/expand-core.c coreutils-8.25/src/expand-core.c +--- coreutils-8.25-orig/src/expand-core.c 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/src/expand-core.c 2016-01-22 21:23:04.634308804 -0600 +@@ -0,0 +1,150 @@ ++/* expand-core.c - elementary functions for the expand and unexpand utilities ++ Copyright (C) 1989-2015 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++#include ++#include ++ ++#include "system.h" ++#include "error.h" ++#include "fadvise.h" ++#include "quote.h" ++#include "xstrndup.h" ++ ++#include "expand-core.h" ++ ++/* Add the comma or blank separated list of tab stops STOPS ++ to the list of tab stops. */ ++ ++extern void ++parse_tab_stops (char const *stops, void (*add_tab_stop)(uintmax_t)) +{ -+ FILE *fp; /* Input strem. */ -+ mbstate_t i_state; /* Current shift state of the input stream. */ -+ mbstate_t i_state_bak; /* Back up the I_STATE. */ -+ mbstate_t o_state; /* Current shift state of the output stream. */ -+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ -+ char *bufpos = buf; /* Next read position of BUF. */ -+ size_t buflen = 0; /* The length of the byte sequence in buf. */ -+ wchar_t wc; /* A gotten wide character. */ -+ size_t mblength; /* The byte size of a multibyte character -+ which shows as same character as WC. */ -+ int tab_index = 0; /* Index in `tab_list' of next tabstop. */ -+ int column = 0; /* Column on screen of the next char. */ -+ int next_tab_column; /* Column the next tab stop is on. */ -+ int convert = 1; /* If nonzero, perform translations. */ ++ bool have_tabval = false; ++ uintmax_t tabval IF_LINT ( = 0); ++ char const *num_start IF_LINT ( = NULL); ++ bool ok = true; + -+ fp = next_file ((FILE *) NULL); -+ if (fp == NULL) -+ return; -+ -+ memset (&o_state, '\0', sizeof(mbstate_t)); -+ memset (&i_state, '\0', sizeof(mbstate_t)); -+ -+ for (;;) ++ for (; *stops; stops++) + { -+ /* Refill the buffer BUF. */ -+ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp)) -+ { -+ memmove (buf, bufpos, buflen); -+ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp); -+ bufpos = buf; -+ } ++ if (*stops == ',' || isblank (to_uchar (*stops))) ++ { ++ if (have_tabval) ++ add_tab_stop (tabval); ++ have_tabval = false; ++ } ++ else if (ISDIGIT (*stops)) ++ { ++ if (!have_tabval) ++ { ++ tabval = 0; ++ have_tabval = true; ++ num_start = stops; ++ } + -+ /* No character is left in BUF. */ -+ if (buflen < 1) -+ { -+ fp = next_file (fp); ++ /* Detect overflow. */ ++ if (!DECIMAL_DIGIT_ACCUMULATE (tabval, *stops - '0', uintmax_t)) ++ { ++ size_t len = strspn (num_start, "0123456789"); ++ char *bad_num = xstrndup (num_start, len); ++ error (0, 0, _("tab stop is too large %s"), quote (bad_num)); ++ free (bad_num); ++ ok = false; ++ stops = num_start + len - 1; ++ } ++ } ++ else ++ { ++ error (0, 0, _("tab size contains invalid character(s): %s"), ++ quote (stops)); ++ ok = false; ++ break; ++ } ++ } + -+ if (fp == NULL) -+ break; /* No more files. */ -+ else -+ { -+ memset (&i_state, '\0', sizeof(mbstate_t)); -+ continue; -+ } -+ } ++ if (!ok) ++ exit (EXIT_FAILURE); + -+ /* Get a wide character. */ -+ i_state_bak = i_state; -+ mblength = mbrtowc (&wc, bufpos, buflen, &i_state); ++ if (have_tabval) ++ add_tab_stop (tabval); ++} + -+ switch (mblength) -+ { -+ case (size_t)-1: /* illegal byte sequence. */ -+ case (size_t)-2: -+ mblength = 1; -+ i_state = i_state_bak; -+ if (convert) -+ { -+ ++column; -+ if (convert_entire_line == 0 && !isblank(*bufpos)) -+ convert = 0; -+ } -+ putchar (*bufpos); -+ break; ++/* Check that the list of tab stops TABS, with ENTRIES entries, ++ contains only nonzero, ascending values. */ + -+ case 0: /* null. */ -+ mblength = 1; -+ if (convert && convert_entire_line == 0) -+ convert = 0; -+ putchar ('\0'); -+ break; ++extern void ++validate_tab_stops (uintmax_t const *tabs, size_t entries) ++{ ++ uintmax_t prev_tab = 0; ++ size_t i; + -+ default: -+ if (wc == L'\n') /* LF. */ -+ { -+ tab_index = 0; -+ column = 0; -+ convert = 1; -+ putchar ('\n'); -+ } -+ else if (wc == L'\t' && convert) /* Tab. */ -+ { -+ if (tab_size == 0) -+ { -+ /* Do not let tab_index == first_free_tab; -+ stop when it is 1 less. */ -+ while (tab_index < first_free_tab - 1 -+ && column >= tab_list[tab_index]) -+ tab_index++; -+ next_tab_column = tab_list[tab_index]; -+ if (tab_index < first_free_tab - 1) -+ tab_index++; -+ if (column >= next_tab_column) -+ next_tab_column = column + 1; -+ } -+ else -+ next_tab_column = column + tab_size - column % tab_size; -+ -+ while (column < next_tab_column) -+ { -+ putchar (' '); -+ ++column; -+ } -+ } -+ else /* Others. */ -+ { -+ if (convert) -+ { -+ if (wc == L'\b') -+ { -+ if (column > 0) -+ --column; -+ } -+ else -+ { -+ int width; /* The width of WC. */ -+ -+ width = wcwidth (wc); -+ column += (width > 0) ? width : 0; -+ if (convert_entire_line == 0 && !iswblank(wc)) -+ convert = 0; -+ } -+ } -+ fwrite (bufpos, sizeof(char), mblength, stdout); -+ } -+ } -+ buflen -= mblength; -+ bufpos += mblength; ++ for (i = 0; i < entries; i++) ++ { ++ if (tabs[i] == 0) ++ error (EXIT_FAILURE, 0, _("tab size cannot be 0")); ++ if (tabs[i] <= prev_tab) ++ error (EXIT_FAILURE, 0, _("tab sizes must be ascending")); ++ prev_tab = tabs[i]; + } +} -+#endif + - int - main (int argc, char **argv) - { -@@ -421,7 +579,12 @@ - - file_list = (optind < argc ? &argv[optind] : stdin_argv); - -- expand (); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ expand_multibyte (); -+ else -+#endif -+ expand (); - - if (have_read_stdin && fclose (stdin) != 0) - error (EXIT_FAILURE, errno, "-"); -diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c ---- coreutils-8.24/src/fold.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/fold.c 2015-07-04 15:15:06.645650864 -0500 -@@ -22,11 +22,32 @@ ++/* Close the old stream pointer FP if it is non-NULL, ++ and return a new one opened to read the next input file. ++ Open a filename of '-' as the standard input. ++ Return NULL if there are no more input files. */ ++ ++extern FILE * ++next_file (FILE *fp) ++{ ++ static char *prev_file; ++ char *file; ++ ++ if (fp) ++ { ++ if (ferror (fp)) ++ { ++ error (0, errno, "%s", prev_file); ++ exit_status = EXIT_FAILURE; ++ } ++ if (STREQ (prev_file, "-")) ++ clearerr (fp); /* Also clear EOF. */ ++ else if (fclose (fp) != 0) ++ { ++ error (0, errno, "%s", prev_file); ++ exit_status = EXIT_FAILURE; ++ } ++ } ++ ++ while ((file = *file_list++) != NULL) ++ { ++ if (STREQ (file, "-")) ++ { ++ have_read_stdin = true; ++ fp = stdin; ++ } ++ else ++ fp = fopen (file, "r"); ++ if (fp) ++ { ++ prev_file = file; ++ fadvise (fp, FADVISE_SEQUENTIAL); ++ return fp; ++ } ++ error (0, errno, "%s", file); ++ exit_status = EXIT_FAILURE; ++ } ++ return NULL; ++} +diff -Naurp coreutils-8.25-orig/src/expand-core.h coreutils-8.25/src/expand-core.h +--- coreutils-8.25-orig/src/expand-core.h 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/src/expand-core.h 2016-01-22 21:23:04.634308804 -0600 +@@ -0,0 +1,41 @@ ++/* expand-core.h - function prototypes for the expand and unexpand utilities ++ Copyright (C) 1989-2015 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#ifndef EXPAND_CORE_H_ ++# define EXPAND_CORE_H_ ++ ++extern size_t first_free_tab; ++ ++extern size_t n_tabs_allocated; ++ ++extern uintmax_t *tab_list; ++ ++extern int exit_status; ++ ++extern char **file_list; ++ ++extern bool have_read_stdin; ++ ++void ++parse_tab_stops (char const *stops, void (*add_tab_stop)(uintmax_t)); ++ ++void ++validate_tab_stops (uintmax_t const *tabs, size_t entries); ++ ++FILE * ++next_file (FILE *fp); ++ ++#endif /* EXPAND_CORE_H_ */ +diff -Naurp coreutils-8.25-orig/src/fold.c coreutils-8.25/src/fold.c +--- coreutils-8.25-orig/src/fold.c 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/src/fold.c 2016-01-22 21:23:04.597639947 -0600 +@@ -22,11 +22,33 @@ #include #include ++/* Get mbstate_t, mbrtowc(), wcwidth(). */ +#if HAVE_WCHAR_H +# include +#endif @@ -835,7 +1475,7 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c #define TAB_WIDTH 8 /* The official name of this program (e.g., no 'g' prefix). */ -@@ -34,20 +55,41 @@ +@@ -34,20 +56,41 @@ #define AUTHORS proper_name ("David MacKenzie") @@ -881,7 +1521,7 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c {"spaces", no_argument, NULL, 's'}, {"width", required_argument, NULL, 'w'}, {GETOPT_HELP_OPTION_DECL}, -@@ -75,6 +117,7 @@ +@@ -75,6 +118,7 @@ Wrap input lines in each FILE, writing t fputs (_("\ -b, --bytes count bytes rather than columns\n\ @@ -889,7 +1529,7 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c -s, --spaces break at spaces\n\ -w, --width=WIDTH use WIDTH columns instead of 80\n\ "), stdout); -@@ -92,7 +135,7 @@ +@@ -92,7 +136,7 @@ Wrap input lines in each FILE, writing t static size_t adjust_column (size_t column, char c) { @@ -898,7 +1538,7 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c { if (c == '\b') { -@@ -115,30 +158,14 @@ +@@ -115,30 +159,14 @@ adjust_column (size_t column, char c) to stdout, with maximum line length WIDTH. Return true if successful. */ @@ -925,13 +1565,13 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c - - if (istream == NULL) - { -- error (0, errno, "%s", filename); +- error (0, errno, "%s", quotef (filename)); - return false; - } fadvise (istream, FADVISE_SEQUENTIAL); -@@ -168,6 +195,15 @@ +@@ -168,6 +196,15 @@ fold_file (char const *filename, size_t bool found_blank = false; size_t logical_end = offset_out; @@ -947,16 +1587,16 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c /* Look for the last blank. */ while (logical_end) { -@@ -214,11 +250,221 @@ +@@ -214,11 +251,221 @@ fold_file (char const *filename, size_t line_out[offset_out++] = c; } - saved_errno = errno; + *saved_errno = errno; -+ -+ if (offset_out) -+ fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); -+ + + if (offset_out) + fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); + +} + +#if HAVE_MBRTOWC @@ -1128,10 +1768,10 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c + } + + *saved_errno = errno; - - if (offset_out) - fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); - ++ ++ if (offset_out) ++ fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); ++ +} +#endif + @@ -1169,8 +1809,8 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c + if (ferror (istream)) { - error (0, saved_errno, "%s", filename); -@@ -251,7 +497,8 @@ + error (0, saved_errno, "%s", quotef (filename)); +@@ -251,7 +498,8 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1180,7 +1820,7 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) { -@@ -260,7 +507,15 @@ +@@ -260,7 +508,15 @@ main (int argc, char **argv) switch (optc) { case 'b': /* Count bytes rather than columns. */ @@ -1197,9 +1837,9 @@ diff -Naur coreutils-8.24/src/fold.c coreutils-8.24-mod/src/fold.c break; case 's': /* Break at word boundaries. */ -diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c ---- coreutils-8.24/src/join.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/join.c 2015-07-04 15:08:33.515055741 -0500 +diff -Naurp coreutils-8.25-orig/src/join.c coreutils-8.25/src/join.c +--- coreutils-8.25-orig/src/join.c 2016-01-13 05:08:59.000000000 -0600 ++++ coreutils-8.25/src/join.c 2016-01-22 21:23:04.600973479 -0600 @@ -22,18 +22,32 @@ #include #include @@ -1234,7 +1874,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "join" -@@ -135,10 +149,12 @@ +@@ -135,10 +149,12 @@ static struct outlist outlist_head; /* Last element in 'outlist', where a new element can be added. */ static struct outlist *outlist_end = &outlist_head; @@ -1251,7 +1891,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c /* If nonzero, check that the input is correctly ordered. */ static enum -@@ -275,13 +291,14 @@ +@@ -275,13 +291,14 @@ xfields (struct line *line) if (ptr == lim) return; @@ -1268,8 +1908,8 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c + else { /* Skip leading blanks before the first field. */ - while (isblank (to_uchar (*ptr))) -@@ -305,6 +322,147 @@ + while (field_sep (*ptr)) +@@ -305,6 +322,147 @@ xfields (struct line *line) extract_field (line, ptr, lim - ptr); } @@ -1337,7 +1977,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c + } + mblength = (mblength < 1) ? 1 : mblength; + -+ if (!iswblank(wc)) ++ if (!iswblank(wc) && wc != '\n') + break; + ptr += mblength; + } @@ -1368,7 +2008,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c + } + mblength = (mblength < 1) ? 1 : mblength; + -+ if (iswblank (wc)) ++ if (iswblank (wc) || wc == '\n') + break; + + sep += mblength; @@ -1401,7 +2041,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c + } + mblength = (mblength < 1) ? 1 : mblength; + -+ if (!iswblank (wc)) ++ if (!iswblank (wc) && wc != '\n') + break; + + ptr += mblength; @@ -1417,7 +2057,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c static void freeline (struct line *line) { -@@ -326,56 +484,133 @@ +@@ -326,56 +484,133 @@ keycmp (struct line const *line1, struct size_t jf_1, size_t jf_2) { /* Start of field to compare in each file. */ @@ -1574,7 +2214,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c } /* Check that successive input lines PREV and CURRENT from input file -@@ -467,6 +702,11 @@ +@@ -467,6 +702,11 @@ get_line (FILE *fp, struct line **linep, } ++line_no[which - 1]; @@ -1586,7 +2226,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c xfields (line); if (prevline[which - 1]) -@@ -566,21 +806,28 @@ +@@ -566,21 +806,28 @@ prfield (size_t n, struct line const *li /* Output all the fields in line, other than the join field. */ @@ -1618,7 +2258,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c prfield (i, line); } } -@@ -591,7 +838,6 @@ +@@ -591,7 +838,6 @@ static void prjoin (struct line const *line1, struct line const *line2) { const struct outlist *outlist; @@ -1626,7 +2266,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c size_t field; struct line const *line; -@@ -625,7 +871,7 @@ +@@ -625,7 +871,7 @@ prjoin (struct line const *line1, struct o = o->next; if (o == NULL) break; @@ -1635,7 +2275,7 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c } putchar (eolchar); } -@@ -1103,21 +1349,46 @@ +@@ -1103,21 +1349,46 @@ main (int argc, char **argv) case 't': { @@ -1692,10 +2332,22 @@ diff -Naur coreutils-8.24/src/join.c coreutils-8.24-mod/src/join.c break; case 'z': -diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c ---- coreutils-8.24/src/pr.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/pr.c 2015-07-04 15:08:33.516055707 -0500 -@@ -312,6 +312,24 @@ +diff -Naurp coreutils-8.25-orig/src/local.mk coreutils-8.25/src/local.mk +--- coreutils-8.25-orig/src/local.mk 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/src/local.mk 2016-01-22 21:23:04.637642337 -0600 +@@ -361,6 +361,8 @@ src_coreutils_SOURCES = src/coreutils.c + + src_cp_SOURCES = src/cp.c $(copy_sources) $(selinux_sources) + src_dir_SOURCES = src/ls.c src/ls-dir.c ++src_expand_SOURCES = src/expand.c src/expand-core.c ++src_unexpand_SOURCES = src/unexpand.c src/expand-core.c + src_vdir_SOURCES = src/ls.c src/ls-vdir.c + src_id_SOURCES = src/id.c src/group-list.c + src_groups_SOURCES = src/groups.c src/group-list.c +diff -Naurp coreutils-8.25-orig/src/pr.c coreutils-8.25/src/pr.c +--- coreutils-8.25-orig/src/pr.c 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/src/pr.c 2016-01-22 21:23:04.607640544 -0600 +@@ -311,6 +311,24 @@ #include #include @@ -1720,7 +2372,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c #include "system.h" #include "error.h" #include "fadvise.h" -@@ -324,6 +342,18 @@ +@@ -323,6 +341,18 @@ #include "xstrtol.h" #include "xdectoint.h" @@ -1739,7 +2391,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "pr" -@@ -416,7 +446,20 @@ +@@ -415,7 +445,20 @@ struct COLUMN typedef struct COLUMN COLUMN; @@ -1761,7 +2413,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c static bool read_line (COLUMN *p); static bool print_page (void); static bool print_stored (COLUMN *p); -@@ -428,6 +471,7 @@ +@@ -427,6 +470,7 @@ static void add_line_number (COLUMN *p); static void getoptnum (const char *n_str, int min, int *num, const char *errfmt); static void getoptarg (char *arg, char switch_char, char *character, @@ -1769,7 +2421,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c int *number); static void print_files (int number_of_files, char **av); static void init_parameters (int number_of_files); -@@ -441,7 +485,6 @@ +@@ -440,7 +484,6 @@ static void store_char (char c); static void pad_down (unsigned int lines); static void read_rest_of_line (COLUMN *p); static void skip_read (COLUMN *p, int column_number); @@ -1777,7 +2429,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c static void cleanup (void); static void print_sep_string (void); static void separator_string (const char *optarg_S); -@@ -453,7 +496,7 @@ +@@ -452,7 +495,7 @@ static COLUMN *column_vector; we store the leftmost columns contiguously in buff. To print a line from buff, get the index of the first character from line_vector[i], and print up to line_vector[i + 1]. */ @@ -1786,7 +2438,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* Index of the position in buff where the next character will be stored. */ -@@ -557,7 +600,7 @@ +@@ -556,7 +599,7 @@ static int chars_per_column; static bool untabify_input = false; /* (-e) The input tab character. */ @@ -1795,7 +2447,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... where the leftmost column is 1. */ -@@ -567,7 +610,10 @@ +@@ -566,7 +609,10 @@ static int chars_per_input_tab = 8; static bool tabify_output = false; /* (-i) The output tab character. */ @@ -1807,7 +2459,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* (-i) The width of the output tab. */ static int chars_per_output_tab = 8; -@@ -637,7 +683,13 @@ +@@ -636,7 +682,13 @@ static int line_number; static bool numbered_lines = false; /* (-n) Character which follows each line number. */ @@ -1822,7 +2474,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* (-n) line counting starts with 1st line of input file (not with 1st line of 1st page printed). */ -@@ -690,6 +742,7 @@ +@@ -689,6 +741,7 @@ static bool use_col_separator = false; -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */ static char *col_sep_string = (char *) ""; static int col_sep_length = 0; @@ -1830,7 +2482,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c static char *column_separator = (char *) " "; static char *line_separator = (char *) "\t"; -@@ -840,6 +893,13 @@ +@@ -839,6 +892,13 @@ separator_string (const char *optarg_S) col_sep_length = (int) strlen (optarg_S); col_sep_string = xmalloc (col_sep_length + 1); strcpy (col_sep_string, optarg_S); @@ -1844,7 +2496,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c } int -@@ -864,6 +924,21 @@ +@@ -863,6 +923,21 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1866,7 +2518,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c n_files = 0; file_names = (argc > 1 ? xmalloc ((argc - 1) * sizeof (char *)) -@@ -940,8 +1015,12 @@ +@@ -939,8 +1014,12 @@ main (int argc, char **argv) break; case 'e': if (optarg) @@ -1881,7 +2533,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* Could check tab width > 0. */ untabify_input = true; break; -@@ -954,8 +1033,12 @@ +@@ -953,8 +1032,12 @@ main (int argc, char **argv) break; case 'i': if (optarg) @@ -1896,7 +2548,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* Could check tab width > 0. */ tabify_output = true; break; -@@ -973,8 +1056,8 @@ +@@ -972,8 +1055,8 @@ main (int argc, char **argv) case 'n': numbered_lines = true; if (optarg) @@ -1907,7 +2559,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c break; case 'N': skip_count = false; -@@ -998,7 +1081,7 @@ +@@ -997,7 +1080,7 @@ main (int argc, char **argv) old_s = false; /* Reset an additional input of -s, -S dominates -s */ col_sep_string = bad_cast (""); @@ -1916,7 +2568,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c use_col_separator = true; if (optarg) separator_string (optarg); -@@ -1152,10 +1235,45 @@ +@@ -1152,10 +1235,45 @@ getoptnum (const char *n_str, int min, i a number. */ static void @@ -1964,7 +2616,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c if (*arg) { long int tmp_long; -@@ -1177,6 +1295,11 @@ +@@ -1177,6 +1295,11 @@ static void init_parameters (int number_of_files) { int chars_used_by_number = 0; @@ -1976,7 +2628,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c lines_per_body = lines_per_page - lines_per_header - lines_per_footer; if (lines_per_body <= 0) -@@ -1214,7 +1337,7 @@ +@@ -1214,7 +1337,7 @@ init_parameters (int number_of_files) else col_sep_string = column_separator; @@ -1985,7 +2637,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c use_col_separator = true; } /* It's rather pointless to define a TAB separator with column -@@ -1244,11 +1367,11 @@ +@@ -1244,11 +1367,11 @@ init_parameters (int number_of_files) + TAB_WIDTH (chars_per_input_tab, chars_per_number); */ /* Estimate chars_per_text without any margin and keep it constant. */ @@ -1999,7 +2651,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* The number is part of the column width unless we are printing files in parallel. */ -@@ -1257,7 +1380,7 @@ +@@ -1257,7 +1380,7 @@ init_parameters (int number_of_files) } chars_per_column = (chars_per_line - chars_used_by_number @@ -2008,16 +2660,16 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c if (chars_per_column < 1) error (EXIT_FAILURE, 0, _("page width too narrow")); -@@ -1275,7 +1398,7 @@ +@@ -1275,7 +1398,7 @@ init_parameters (int number_of_files) We've to use 8 as the lower limit, if we use chars_per_default_tab = 8 to expand a tab which is not an input_tab-char. */ free (clump_buff); - clump_buff = xmalloc (MAX (8, chars_per_input_tab)); + clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab)); } - + /* Open the necessary files, -@@ -1383,7 +1506,7 @@ +@@ -1383,7 +1506,7 @@ init_funcs (void) /* Enlarge p->start_position of first column to use the same form of padding_not_printed with all columns. */ @@ -2026,7 +2678,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* This loop takes care of all but the rightmost column. */ -@@ -1417,7 +1540,7 @@ +@@ -1417,7 +1540,7 @@ init_funcs (void) } else { @@ -2035,7 +2687,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c h_next = h + chars_per_column; } } -@@ -1708,9 +1831,9 @@ +@@ -1708,9 +1831,9 @@ static void align_column (COLUMN *p) { padding_not_printed = p->start_position; @@ -2047,7 +2699,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c padding_not_printed = ANYWHERE; } -@@ -1981,13 +2104,13 @@ +@@ -1981,13 +2104,13 @@ store_char (char c) /* May be too generous. */ buff = X2REALLOC (buff, &buff_allocated); } @@ -2063,7 +2715,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c char *s; int num_width; -@@ -2004,22 +2127,24 @@ +@@ -2004,22 +2127,24 @@ add_line_number (COLUMN *p) /* Tabification is assumed for multiple columns, also for n-separators, but 'default n-separator = TAB' hasn't been given priority over equal column_width also specified by POSIX. */ @@ -2092,7 +2744,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c output_position = POS_AFTER_TAB (chars_per_output_tab, output_position); } -@@ -2180,7 +2305,7 @@ +@@ -2180,7 +2305,7 @@ print_white_space (void) while (goal - h_old > 1 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) { @@ -2101,7 +2753,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c h_old = h_new; } while (++h_old <= goal) -@@ -2200,6 +2325,7 @@ +@@ -2200,6 +2325,7 @@ print_sep_string (void) { char *s; int l = col_sep_length; @@ -2109,7 +2761,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c s = col_sep_string; -@@ -2213,6 +2339,7 @@ +@@ -2213,6 +2339,7 @@ print_sep_string (void) { for (; separators_not_printed > 0; --separators_not_printed) { @@ -2117,7 +2769,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c while (l-- > 0) { /* 3 types of sep_strings: spaces only, spaces and chars, -@@ -2226,12 +2353,15 @@ +@@ -2226,12 +2353,15 @@ print_sep_string (void) } else { @@ -2134,7 +2786,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* sep_string ends with some spaces */ if (spaces_not_printed > 0) print_white_space (); -@@ -2259,7 +2389,7 @@ +@@ -2259,7 +2389,7 @@ print_clump (COLUMN *p, int n, char *clu required number of tabs and spaces. */ static void @@ -2143,7 +2795,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c { if (tabify_output) { -@@ -2283,6 +2413,74 @@ +@@ -2283,6 +2413,74 @@ print_char (char c) putchar (c); } @@ -2218,7 +2870,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* Skip to page PAGE before printing. PAGE may be larger than total number of pages. */ -@@ -2462,9 +2660,9 @@ +@@ -2462,9 +2660,9 @@ read_line (COLUMN *p) align_empty_cols = false; } @@ -2230,7 +2882,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c padding_not_printed = ANYWHERE; } -@@ -2534,7 +2732,7 @@ +@@ -2534,7 +2732,7 @@ print_stored (COLUMN *p) int i; int line = p->current_line++; @@ -2239,7 +2891,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* FIXME UMR: Uninitialized memory read: * This is occurring while in: -@@ -2546,7 +2744,7 @@ +@@ -2546,7 +2744,7 @@ print_stored (COLUMN *p) xmalloc [xmalloc.c:94] init_store_cols [pr.c:1648] */ @@ -2248,7 +2900,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c pad_vertically = true; -@@ -2565,9 +2763,9 @@ +@@ -2565,9 +2763,9 @@ print_stored (COLUMN *p) } } @@ -2260,7 +2912,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c padding_not_printed = ANYWHERE; } -@@ -2580,8 +2778,8 @@ +@@ -2580,8 +2778,8 @@ print_stored (COLUMN *p) if (spaces_not_printed == 0) { output_position = p->start_position + end_vector[line]; @@ -2271,7 +2923,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c } return true; -@@ -2600,7 +2798,7 @@ +@@ -2600,7 +2798,7 @@ print_stored (COLUMN *p) number of characters is 1.) */ static int @@ -2280,7 +2932,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c { unsigned char uc = c; char *s = clump_buff; -@@ -2610,10 +2808,10 @@ +@@ -2610,10 +2808,10 @@ char_to_clump (char c) int chars; int chars_per_c = 8; @@ -2293,7 +2945,7 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c { width = TAB_WIDTH (chars_per_c, input_position); -@@ -2694,6 +2892,164 @@ +@@ -2694,6 +2892,164 @@ char_to_clump (char c) return chars; } @@ -2458,9 +3110,9 @@ diff -Naur coreutils-8.24/src/pr.c coreutils-8.24-mod/src/pr.c /* We've just printed some files and need to clean up things before looking for more options and printing the next batch of files. -diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c ---- coreutils-8.24/src/sort.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/sort.c 2015-07-04 15:08:33.517055673 -0500 +diff -Naurp coreutils-8.25-orig/src/sort.c coreutils-8.25/src/sort.c +--- coreutils-8.25-orig/src/sort.c 2016-01-16 13:09:33.000000000 -0600 ++++ coreutils-8.25/src/sort.c 2016-01-22 21:23:04.610974077 -0600 @@ -29,6 +29,14 @@ #include #include @@ -2476,7 +3128,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c #include "system.h" #include "argmatch.h" #include "error.h" -@@ -164,14 +172,39 @@ +@@ -163,14 +171,39 @@ static int decimal_point; /* Thousands separator; if -1, then there isn't one. */ static int thousands_sep; @@ -2517,7 +3169,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* The kind of blanks for '-b' to skip in various options. */ enum blanktype { bl_start, bl_end, bl_both }; -@@ -345,13 +378,11 @@ +@@ -344,13 +377,11 @@ static bool reverse; they were read if all keys compare equal. */ static bool stable; @@ -2534,7 +3186,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* Flag to remove consecutive duplicate lines from the output. Only the last of a sequence of equal lines will be output. */ -@@ -810,6 +841,46 @@ +@@ -810,6 +841,46 @@ reap_all (void) reap (-1); } @@ -2574,14 +3226,14 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c + } + + *length = (mblength < 1) ? 1 : mblength; -+ return iswblank (wc); ++ return iswblank (wc) || wc == '\n'; +} +#endif + /* Clean up any remaining temporary files. */ static void -@@ -1254,7 +1325,7 @@ +@@ -1254,7 +1325,7 @@ zaptemp (char const *name) free (node); } @@ -2590,7 +3242,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c static int struct_month_cmp (void const *m1, void const *m2) -@@ -1269,7 +1340,7 @@ +@@ -1269,7 +1340,7 @@ struct_month_cmp (void const *m1, void c /* Initialize the character class tables. */ static void @@ -2599,7 +3251,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { size_t i; -@@ -1281,7 +1352,7 @@ +@@ -1281,7 +1352,7 @@ inittables (void) fold_toupper[i] = toupper (i); } @@ -2608,7 +3260,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* If we're not in the "C" locale, read different names for months. */ if (hard_LC_TIME) { -@@ -1363,6 +1434,84 @@ +@@ -1363,6 +1434,84 @@ specify_nmerge (int oi, char c, char con xstrtol_fatal (e, oi, c, long_options, s); } @@ -2693,7 +3345,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* Specify the amount of main memory to use when sorting. */ static void specify_sort_size (int oi, char c, char const *s) -@@ -1596,7 +1745,7 @@ +@@ -1596,7 +1745,7 @@ buffer_linelim (struct buffer const *buf by KEY in LINE. */ static char * @@ -2702,7 +3354,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { char *ptr = line->text, *lim = ptr + line->length - 1; size_t sword = key->sword; -@@ -1605,10 +1754,10 @@ +@@ -1605,10 +1754,10 @@ begfield (struct line const *line, struc /* The leading field separator itself is included in a field when -t is absent. */ @@ -2715,7 +3367,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c ++ptr; if (ptr < lim) ++ptr; -@@ -1634,11 +1783,70 @@ +@@ -1634,11 +1783,70 @@ begfield (struct line const *line, struc return ptr; } @@ -2787,7 +3439,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { char *ptr = line->text, *lim = ptr + line->length - 1; size_t eword = key->eword, echar = key->echar; -@@ -1653,10 +1861,10 @@ +@@ -1653,10 +1861,10 @@ limfield (struct line const *line, struc 'beginning' is the first character following the delimiting TAB. Otherwise, leave PTR pointing at the first 'blank' character after the preceding field. */ @@ -2800,7 +3452,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c ++ptr; if (ptr < lim && (eword || echar)) ++ptr; -@@ -1702,10 +1910,10 @@ +@@ -1702,10 +1910,10 @@ limfield (struct line const *line, struc */ /* Make LIM point to the end of (one byte past) the current field. */ @@ -2813,7 +3465,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c if (newlim) lim = newlim; } -@@ -1736,6 +1944,130 @@ +@@ -1736,6 +1944,130 @@ limfield (struct line const *line, struc return ptr; } @@ -2944,7 +3596,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* Fill BUF reading from FP, moving buf->left bytes from the end of buf->buf to the beginning first. If EOF is reached and the file wasn't terminated by a newline, supply one. Set up BUF's line -@@ -1822,8 +2154,22 @@ +@@ -1822,8 +2154,22 @@ fillbuf (struct buffer *buf, FILE *fp, c else { if (key->skipsblanks) @@ -2969,7 +3621,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c line->keybeg = line_start; } } -@@ -1944,7 +2290,7 @@ +@@ -1944,7 +2290,7 @@ human_numcompare (char const *a, char co hideously fast. */ static int @@ -2978,7 +3630,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { while (blanks[to_uchar (*a)]) a++; -@@ -1954,6 +2300,25 @@ +@@ -1954,6 +2300,25 @@ numcompare (char const *a, char const *b return strnumcmp (a, b, decimal_point, thousands_sep); } @@ -3004,7 +3656,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* Work around a problem whereby the long double value returned by glibc's strtold ("NaN", ...) contains uninitialized bits: clear all bytes of A and B before calling strtold. FIXME: remove this function once -@@ -2004,7 +2369,7 @@ +@@ -2004,7 +2369,7 @@ general_numcompare (char const *sa, char Return 0 if the name in S is not recognized. */ static int @@ -3013,7 +3665,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { size_t lo = 0; size_t hi = MONTHS_PER_YEAR; -@@ -2279,15 +2644,14 @@ +@@ -2280,15 +2645,14 @@ debug_key (struct line const *line, stru char saved = *lim; *lim = '\0'; @@ -3031,7 +3683,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c else if (key->general_numeric) ignore_value (strtold (beg, &tighter_lim)); else if (key->numeric || key->human_numeric) -@@ -2431,7 +2795,7 @@ +@@ -2432,7 +2796,7 @@ key_warnings (struct keyfield const *gke bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key) && !(key->schar || key->echar); bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */ @@ -3040,7 +3692,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned)) || (!key->skipsblanks && key->schar) || (!key->skipeblanks && key->echar))) -@@ -2489,11 +2853,87 @@ +@@ -2490,11 +2854,87 @@ key_warnings (struct keyfield const *gke error (0, 0, _("option '-r' only applies to last-resort comparison")); } @@ -3053,8 +3705,8 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c + register int lo = 0, hi = MONTHS_PER_YEAR, result; + char *tmp; + size_t wclength, mblength; -+ const char **pp; -+ const wchar_t **wpp; ++ const char *pp; ++ const wchar_t *wpp; + wchar_t *month_wcs; + mbstate_t state; + @@ -3067,17 +3719,19 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c + if (len == 0) + return 0; + -+ month = (char *) xmalloc (len + 1); ++ if (SIZE_MAX - len < 1) ++ xalloc_die (); + -+ tmp = (char *) xmalloc (len + 1); ++ month = (char *) xnmalloc (len + 1, MB_CUR_MAX); ++ ++ pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX); + memcpy (tmp, s, len); + tmp[len] = '\0'; -+ pp = (const char **)&tmp; -+ month_wcs = (wchar_t *) xmalloc ((len + 1) * sizeof (wchar_t)); -+ memset (&state, '\0', sizeof(mbstate_t)); ++ wpp = month_wcs = (wchar_t *) xnmalloc (len + 1, sizeof (wchar_t)); ++ memset (&state, '\0', sizeof (mbstate_t)); + -+ wclength = mbsrtowcs (month_wcs, pp, len + 1, &state); -+ if (wclength == (size_t)-1 || *pp != NULL) ++ wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state); ++ if (wclength == (size_t)-1 || pp != NULL) + error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s)); + + for (i = 0; i < wclength; i++) @@ -3090,10 +3744,8 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c + } + } + -+ wpp = (const wchar_t **)&month_wcs; -+ -+ mblength = wcsrtombs (month, wpp, len + 1, &state); -+ assert (mblength != (-1) && *wpp == NULL); ++ mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state); ++ assert (mblength != (-1) && wpp == NULL); + + do + { @@ -3129,7 +3781,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { struct keyfield *key = keylist; -@@ -2578,7 +3018,7 @@ +@@ -2579,7 +3019,7 @@ keycompare (struct line const *a, struct else if (key->human_numeric) diff = human_numcompare (ta, tb); else if (key->month) @@ -3138,7 +3790,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c else if (key->random) diff = compare_random (ta, tlena, tb, tlenb); else if (key->version) -@@ -2694,6 +3134,209 @@ +@@ -2695,6 +3135,211 @@ keycompare (struct line const *a, struct return key->reverse ? -diff : diff; } @@ -3251,7 +3903,9 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c + + if (ignore || translate) + { -+ char *copy_a = (char *) xmalloc ((lena + lenb) * MB_CUR_MAX + 2); ++ if (SIZE_MAX - lenb - 2 < lena) ++ xalloc_die (); ++ char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX); + char *copy_b = copy_a + lena * MB_CUR_MAX + 1; + size_t new_len_a, new_len_b; + size_t i, j; @@ -3348,7 +4002,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c /* Compare two lines A and B, returning negative, zero, or positive depending on whether A compares less than, equal to, or greater than B. */ -@@ -2721,7 +3364,7 @@ +@@ -2722,7 +3367,7 @@ compare (struct line const *a, struct li diff = - NONZERO (blen); else if (blen == 0) diff = 1; @@ -3357,7 +4011,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c { /* Note xmemcoll0 is a performance enhancement as it will not unconditionally write '\0' after the -@@ -4120,6 +4763,7 @@ +@@ -4121,6 +4766,7 @@ set_ordering (char const *s, struct keyf break; case 'f': key->translate = fold_toupper; @@ -3365,7 +4019,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c break; case 'g': key->general_numeric = true; -@@ -4197,7 +4841,7 @@ +@@ -4199,7 +4845,7 @@ main (int argc, char **argv) initialize_exit_failure (SORT_FAILURE); hard_LC_COLLATE = hard_locale (LC_COLLATE); @@ -3374,7 +4028,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c hard_LC_TIME = hard_locale (LC_TIME); #endif -@@ -4218,6 +4862,29 @@ +@@ -4220,6 +4866,29 @@ main (int argc, char **argv) thousands_sep = -1; } @@ -3404,7 +4058,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c have_read_stdin = false; inittables (); -@@ -4492,13 +5159,34 @@ +@@ -4494,13 +5163,34 @@ main (int argc, char **argv) case 't': { @@ -3443,7 +4097,7 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c else { /* Provoke with 'sort -txx'. Complain about -@@ -4509,9 +5197,12 @@ +@@ -4511,9 +5201,12 @@ main (int argc, char **argv) quote (optarg)); } } @@ -3458,267 +4112,362 @@ diff -Naur coreutils-8.24/src/sort.c coreutils-8.24-mod/src/sort.c } break; -diff -Naur coreutils-8.24/src/unexpand.c coreutils-8.24-mod/src/unexpand.c ---- coreutils-8.24/src/unexpand.c 2015-06-26 12:05:22.000000000 -0500 -+++ coreutils-8.24-mod/src/unexpand.c 2015-07-04 15:08:33.517055673 -0500 -@@ -38,12 +38,29 @@ +@@ -4751,12 +5444,10 @@ main (int argc, char **argv) + sort (files, nfiles, outfile, nthreads); + } + +-#ifdef lint + if (files_from) + readtokens0_free (&tok); + else + free (files); +-#endif + + if (have_read_stdin && fclose (stdin) == EOF) + die (_("close failed"), "-"); +diff -Naurp coreutils-8.25-orig/src/unexpand.c coreutils-8.25/src/unexpand.c +--- coreutils-8.25-orig/src/unexpand.c 2016-01-01 07:48:50.000000000 -0600 ++++ coreutils-8.25/src/unexpand.c 2016-01-22 21:23:04.640975869 -0600 +@@ -38,12 +38,16 @@ #include #include #include + -+/* Get mbstate_t, mbrtowc(), wcwidth(). */ -+#if HAVE_WCHAR_H -+# include -+#endif ++#include + #include "system.h" #include "error.h" #include "fadvise.h" - #include "quote.h" +-#include "quote.h" #include "xstrndup.h" -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC -+ installation; work around this configuration error. */ -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 -+# define MB_LEN_MAX 16 -+#endif -+ -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ -+#if HAVE_MBRTOWC && defined mbstate_t -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -+#endif ++#include "expand-core.h" + /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "unexpand" -@@ -103,6 +120,210 @@ - {NULL, 0, NULL, 0} +@@ -62,17 +66,17 @@ static size_t max_column_width; + /* Array of the explicit column numbers of the tab stops; + after 'tab_list' is exhausted, the rest of the line is printed + unchanged. The first column is column 0. */ +-static uintmax_t *tab_list; ++uintmax_t *tab_list; + + /* The number of allocated entries in 'tab_list'. */ +-static size_t n_tabs_allocated; ++size_t n_tabs_allocated; + + /* The index of the first invalid element of 'tab_list', + where the next element can be added. */ +-static size_t first_free_tab; ++size_t first_free_tab; + + /* Null-terminated array of input filenames. */ +-static char **file_list; ++char **file_list; + + /* Default for 'file_list' if no files are given on the command line. */ + static char *stdin_argv[] = +@@ -81,10 +85,10 @@ static char *stdin_argv[] = }; -+static FILE *next_file (FILE *fp); -+ -+#if HAVE_MBRTOWC -+static void -+unexpand_multibyte (void) -+{ -+ FILE *fp; /* Input stream. */ -+ mbstate_t i_state; /* Current shift state of the input stream. */ -+ mbstate_t i_state_bak; /* Back up the I_STATE. */ -+ mbstate_t o_state; /* Current shift state of the output stream. */ -+ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ -+ char *bufpos = buf; /* Next read position of BUF. */ -+ size_t buflen = 0; /* The length of the byte sequence in buf. */ -+ wint_t wc; /* A gotten wide character. */ -+ size_t mblength; /* The byte size of a multibyte character -+ which shows as same character as WC. */ -+ bool prev_tab = false; -+ -+ /* Index in `tab_list' of next tabstop: */ -+ int tab_index = 0; /* For calculating width of pending tabs. */ -+ int print_tab_index = 0; /* For printing as many tabs as possible. */ -+ unsigned int column = 0; /* Column on screen of next char. */ -+ int next_tab_column; /* Column the next tab stop is on. */ -+ int convert = 1; /* If nonzero, perform translations. */ -+ unsigned int pending = 0; /* Pending columns of blanks. */ -+ -+ fp = next_file ((FILE *) NULL); -+ if (fp == NULL) -+ return; -+ -+ memset (&o_state, '\0', sizeof(mbstate_t)); -+ memset (&i_state, '\0', sizeof(mbstate_t)); -+ -+ for (;;) -+ { -+ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp)) -+ { -+ memmove (buf, bufpos, buflen); -+ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp); -+ bufpos = buf; -+ } -+ -+ /* Get a wide character. */ -+ if (buflen < 1) -+ { -+ mblength = 1; -+ wc = WEOF; -+ } -+ else -+ { -+ i_state_bak = i_state; -+ mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &i_state); -+ } -+ -+ if (mblength == (size_t)-1 || mblength == (size_t)-2) -+ { -+ i_state = i_state_bak; -+ wc = L'\0'; -+ } -+ -+ if (wc == L' ' && convert && column < INT_MAX) -+ { -+ ++pending; -+ ++column; -+ } -+ else if (wc == L'\t' && convert) -+ { -+ if (tab_size == 0) -+ { -+ /* Do not let tab_index == first_free_tab; -+ stop when it is 1 less. */ -+ while (tab_index < first_free_tab - 1 -+ && column >= tab_list[tab_index]) -+ tab_index++; -+ next_tab_column = tab_list[tab_index]; -+ if (tab_index < first_free_tab - 1) -+ tab_index++; -+ if (column >= next_tab_column) -+ { -+ convert = 0; /* Ran out of tab stops. */ -+ goto flush_pend_mb; -+ } -+ } -+ else -+ { -+ next_tab_column = column + tab_size - column % tab_size; -+ } -+ pending += next_tab_column - column; -+ column = next_tab_column; -+ } -+ else -+ { -+flush_pend_mb: -+ /* Flush pending spaces. Print as many tabs as possible, -+ then print the rest as spaces. */ -+ if (pending == 1 && column != 1 && !prev_tab) -+ { -+ putchar (' '); -+ pending = 0; -+ } -+ column -= pending; -+ while (pending > 0) -+ { -+ if (tab_size == 0) -+ { -+ /* Do not let print_tab_index == first_free_tab; -+ stop when it is 1 less. */ -+ while (print_tab_index < first_free_tab - 1 -+ && column >= tab_list[print_tab_index]) -+ print_tab_index++; -+ next_tab_column = tab_list[print_tab_index]; -+ if (print_tab_index < first_free_tab - 1) -+ print_tab_index++; -+ } -+ else -+ { -+ next_tab_column = -+ column + tab_size - column % tab_size; -+ } -+ if (next_tab_column - column <= pending) -+ { -+ putchar ('\t'); -+ pending -= next_tab_column - column; -+ column = next_tab_column; -+ } -+ else -+ { -+ --print_tab_index; -+ column += pending; -+ while (pending != 0) -+ { -+ putchar (' '); -+ pending--; -+ } -+ } -+ } -+ -+ if (wc == WEOF) -+ { -+ fp = next_file (fp); -+ if (fp == NULL) -+ break; /* No more files. */ -+ else -+ { -+ memset (&i_state, '\0', sizeof(mbstate_t)); -+ continue; -+ } -+ } -+ -+ if (mblength == (size_t)-1 || mblength == (size_t)-2) -+ { -+ if (convert) -+ { -+ ++column; -+ if (convert_entire_line == 0) -+ convert = 0; -+ } -+ mblength = 1; -+ putchar (buf[0]); -+ } -+ else if (mblength == 0) -+ { -+ if (convert && convert_entire_line == 0) -+ convert = 0; -+ mblength = 1; -+ putchar ('\0'); -+ } -+ else -+ { -+ if (convert) -+ { -+ if (wc == L'\b') -+ { -+ if (column > 0) -+ --column; -+ } -+ else -+ { -+ int width; /* The width of WC. */ -+ -+ width = wcwidth (wc); -+ column += (width > 0) ? width : 0; -+ if (convert_entire_line == 0) -+ convert = 0; -+ } -+ } -+ -+ if (wc == L'\n') -+ { -+ tab_index = print_tab_index = 0; -+ column = pending = 0; -+ convert = 1; -+ } -+ fwrite (bufpos, sizeof(char), mblength, stdout); -+ } -+ } -+ prev_tab = wc == L'\t'; -+ buflen -= mblength; -+ bufpos += mblength; -+ } -+} -+#endif -+ -+ - void - usage (int status) + /* True if we have ever read standard input. */ +-static bool have_read_stdin; ++bool have_read_stdin; + + /* The desired exit status. */ +-static int exit_status; ++int exit_status; + + /* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +@@ -154,128 +158,6 @@ add_tab_stop (uintmax_t tabval) + } + } + +-/* Add the comma or blank separated list of tab stops STOPS +- to the list of tab stops. */ +- +-static void +-parse_tab_stops (char const *stops) +-{ +- bool have_tabval = false; +- uintmax_t tabval IF_LINT ( = 0); +- char const *num_start IF_LINT ( = NULL); +- bool ok = true; +- +- for (; *stops; stops++) +- { +- if (*stops == ',' || isblank (to_uchar (*stops))) +- { +- if (have_tabval) +- add_tab_stop (tabval); +- have_tabval = false; +- } +- else if (ISDIGIT (*stops)) +- { +- if (!have_tabval) +- { +- tabval = 0; +- have_tabval = true; +- num_start = stops; +- } +- +- /* Detect overflow. */ +- if (!DECIMAL_DIGIT_ACCUMULATE (tabval, *stops - '0', uintmax_t)) +- { +- size_t len = strspn (num_start, "0123456789"); +- char *bad_num = xstrndup (num_start, len); +- error (0, 0, _("tab stop is too large %s"), quote (bad_num)); +- free (bad_num); +- ok = false; +- stops = num_start + len - 1; +- } +- } +- else +- { +- error (0, 0, _("tab size contains invalid character(s): %s"), +- quote (stops)); +- ok = false; +- break; +- } +- } +- +- if (!ok) +- exit (EXIT_FAILURE); +- +- if (have_tabval) +- add_tab_stop (tabval); +-} +- +-/* Check that the list of tab stops TABS, with ENTRIES entries, +- contains only nonzero, ascending values. */ +- +-static void +-validate_tab_stops (uintmax_t const *tabs, size_t entries) +-{ +- uintmax_t prev_tab = 0; +- size_t i; +- +- for (i = 0; i < entries; i++) +- { +- if (tabs[i] == 0) +- error (EXIT_FAILURE, 0, _("tab size cannot be 0")); +- if (tabs[i] <= prev_tab) +- error (EXIT_FAILURE, 0, _("tab sizes must be ascending")); +- prev_tab = tabs[i]; +- } +-} +- +-/* Close the old stream pointer FP if it is non-NULL, +- and return a new one opened to read the next input file. +- Open a filename of '-' as the standard input. +- Return NULL if there are no more input files. */ +- +-static FILE * +-next_file (FILE *fp) +-{ +- static char *prev_file; +- char *file; +- +- if (fp) +- { +- if (ferror (fp)) +- { +- error (0, errno, "%s", quotef (prev_file)); +- exit_status = EXIT_FAILURE; +- } +- if (STREQ (prev_file, "-")) +- clearerr (fp); /* Also clear EOF. */ +- else if (fclose (fp) != 0) +- { +- error (0, errno, "%s", quotef (prev_file)); +- exit_status = EXIT_FAILURE; +- } +- } +- +- while ((file = *file_list++) != NULL) +- { +- if (STREQ (file, "-")) +- { +- have_read_stdin = true; +- fp = stdin; +- } +- else +- fp = fopen (file, "r"); +- if (fp) +- { +- prev_file = file; +- fadvise (fp, FADVISE_SEQUENTIAL); +- return fp; +- } +- error (0, errno, "%s", quotef (file)); +- exit_status = EXIT_FAILURE; +- } +- return NULL; +-} +- + /* Change blanks to tabs, writing to stdout. + Read each file in 'file_list', in order. */ + +@@ -284,11 +166,12 @@ unexpand (void) { -@@ -523,7 +744,12 @@ + /* Input stream. */ + FILE *fp = next_file (NULL); ++ mb_file_t mbf; - file_list = (optind < argc ? &argv[optind] : stdin_argv); + /* The array of pending blanks. In non-POSIX locales, blanks can + include characters other than spaces, so the blanks must be + stored, not merely counted. */ +- char *pending_blank; ++ mbf_char_t *pending_blank; -- unexpand (); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ unexpand_multibyte (); -+ else -+#endif -+ unexpand (); + if (!fp) + return; +@@ -296,12 +179,14 @@ unexpand (void) + /* The worst case is a non-blank character, then one blank, then a + tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so + allocate MAX_COLUMN_WIDTH bytes to store the blanks. */ +- pending_blank = xmalloc (max_column_width); ++ pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t)); ++ ++ mbf_init (mbf, fp); - if (have_read_stdin && fclose (stdin) != 0) - error (EXIT_FAILURE, errno, "-"); -diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c ---- coreutils-8.24/src/uniq.c 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/src/uniq.c 2015-07-04 15:08:33.517055673 -0500 + while (true) + { + /* Input character, or EOF. */ +- int c; ++ mbf_char_t c; + + /* If true, perform translations. */ + bool convert = true; +@@ -335,12 +220,19 @@ unexpand (void) + + do + { +- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) +- continue; ++ do { ++ mbf_getc (c, mbf); ++ if (mb_iseof (c)) ++ { ++ mbf_init (mbf, fp = next_file (fp)); ++ continue; ++ } ++ } ++ while (false); + + if (convert) + { +- bool blank = !! isblank (c); ++ bool blank = mb_isblank (c); + + if (blank) + { +@@ -372,16 +264,16 @@ unexpand (void) + if (next_tab_column < column) + error (EXIT_FAILURE, 0, _("input line is too long")); + +- if (c == '\t') ++ if (mb_iseq (c, '\t')) + { + column = next_tab_column; + + if (pending) +- pending_blank[0] = '\t'; ++ mb_setascii (&pending_blank[0], '\t'); + } + else + { +- column++; ++ column += mb_width (c); + + if (! (prev_blank && column == next_tab_column)) + { +@@ -389,13 +281,14 @@ unexpand (void) + will be replaced by tabs. */ + if (column == next_tab_column) + one_blank_before_tab_stop = true; +- pending_blank[pending++] = c; ++ mb_copy (&pending_blank[pending++], &c); + prev_blank = true; + continue; + } + + /* Replace the pending blanks by a tab or two. */ +- pending_blank[0] = c = '\t'; ++ mb_setascii (&c, '\t'); ++ mb_setascii (&pending_blank[0], '\t'); + } + + /* Discard pending blanks, unless it was a single +@@ -403,7 +296,7 @@ unexpand (void) + pending = one_blank_before_tab_stop; + } + } +- else if (c == '\b') ++ else if (mb_iseq (c, '\b')) + { + /* Go back one column, and force recalculation of the + next tab stop. */ +@@ -413,7 +306,7 @@ unexpand (void) + } + else + { +- column++; ++ column += mb_width (c); + if (!column) + error (EXIT_FAILURE, 0, _("input line is too long")); + } +@@ -421,9 +314,13 @@ unexpand (void) + if (pending) + { + if (pending > 1 && one_blank_before_tab_stop) +- pending_blank[0] = '\t'; +- if (fwrite (pending_blank, 1, pending, stdout) != pending) ++ mb_setascii (&pending_blank[0], '\t'); ++ ++ for (int n = 0; n < pending; ++n) ++ mb_putc (pending_blank[n], stdout); ++ if (ferror (stdout)) + error (EXIT_FAILURE, errno, _("write error")); ++ + pending = 0; + one_blank_before_tab_stop = false; + } +@@ -432,16 +329,16 @@ unexpand (void) + convert &= convert_entire_line || blank; + } + +- if (c < 0) ++ if (mb_iseof (c)) + { + free (pending_blank); + return; + } +- +- if (putchar (c) < 0) ++ mb_putc (c, stdout); ++ if (ferror (stdout)) + error (EXIT_FAILURE, errno, _("write error")); + } +- while (c != '\n'); ++ while (!mb_iseq (c, '\n')); + } + } + +@@ -482,7 +379,7 @@ main (int argc, char **argv) + break; + case 't': + convert_entire_line = true; +- parse_tab_stops (optarg); ++ parse_tab_stops (optarg, add_tab_stop); + break; + case CONVERT_FIRST_ONLY_OPTION: + convert_first_only = true; +diff -Naurp coreutils-8.25-orig/src/uniq.c coreutils-8.25/src/uniq.c +--- coreutils-8.25-orig/src/uniq.c 2016-01-13 05:08:59.000000000 -0600 ++++ coreutils-8.25/src/uniq.c 2016-01-22 21:23:04.617641142 -0600 @@ -21,6 +21,17 @@ #include #include @@ -3737,13 +4486,14 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c #include "system.h" #include "argmatch.h" #include "linebuffer.h" -@@ -32,7 +43,19 @@ +@@ -31,9 +42,21 @@ #include "stdio--.h" #include "xmemcoll.h" #include "xstrtol.h" -#include "memcasecmp.h" +#include "xmemcoll.h" -+ + #include "quote.h" + +/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC + installation; work around this configuration error. */ +#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 @@ -3755,10 +4505,11 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) +#endif + - ++ /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "uniq" -@@ -143,6 +166,10 @@ + +@@ -143,6 +166,10 @@ enum GROUP_OPTION = CHAR_MAX + 1 }; @@ -3769,7 +4520,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c static struct option const longopts[] = { {"count", no_argument, NULL, 'c'}, -@@ -251,7 +278,7 @@ +@@ -252,7 +279,7 @@ size_opt (char const *opt, char const *m return a pointer to the beginning of the line's field to be compared. */ static char * _GL_ATTRIBUTE_PURE @@ -3778,7 +4529,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c { size_t count; char const *lp = line->buffer; -@@ -271,6 +298,83 @@ +@@ -272,6 +299,83 @@ find_field (struct linebuffer const *lin return line->buffer + i; } @@ -3829,7 +4580,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c + { + MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); + -+ if (convfail || !iswblank (wc)) ++ if (convfail || !(iswblank (wc) || wc == '\n')) + { + pos += mblength; + break; @@ -3841,7 +4592,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c + { + MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); + -+ if (!convfail && iswblank (wc)) ++ if (!convfail && (iswblank (wc) || wc == '\n')) + break; + + pos += mblength; @@ -3862,7 +4613,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c /* Return false if two strings OLD and NEW match, true if not. OLD and NEW point not to the beginnings of the lines but rather to the beginnings of the fields to compare. -@@ -279,6 +383,8 @@ +@@ -280,6 +384,8 @@ find_field (struct linebuffer const *lin static bool different (char *old, char *new, size_t oldlen, size_t newlen) { @@ -3871,7 +4622,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c if (check_chars < oldlen) oldlen = check_chars; if (check_chars < newlen) -@@ -286,15 +392,104 @@ +@@ -287,15 +393,104 @@ different (char *old, char *new, size_t if (ignore_case) { @@ -3981,7 +4732,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c /* Output the line in linebuffer LINE to standard output provided that the switches say it should be output. MATCH is true if the line matches the previous line. -@@ -358,19 +553,38 @@ +@@ -359,19 +554,38 @@ check_file (const char *infile, const ch char *prevfield IF_LINT ( = NULL); size_t prevlen IF_LINT ( = 0); bool first_group_printed = false; @@ -4020,7 +4771,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c new_group = (prevline->length == 0 || different (thisfield, prevfield, thislen, prevlen)); -@@ -388,6 +602,10 @@ +@@ -389,6 +603,10 @@ check_file (const char *infile, const ch SWAP_LINES (prevline, thisline); prevfield = thisfield; prevlen = thislen; @@ -4031,7 +4782,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c first_group_printed = true; } } -@@ -400,17 +618,26 @@ +@@ -401,17 +619,26 @@ check_file (const char *infile, const ch size_t prevlen; uintmax_t match_count = 0; bool first_delimiter = true; @@ -4058,7 +4809,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) { if (ferror (stdin)) -@@ -419,6 +646,14 @@ +@@ -420,6 +647,14 @@ check_file (const char *infile, const ch } thisfield = find_field (thisline); thislen = thisline->length - 1 - (thisfield - thisline->buffer); @@ -4073,7 +4824,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c match = !different (thisfield, prevfield, thislen, prevlen); match_count += match; -@@ -451,6 +686,9 @@ +@@ -452,6 +687,9 @@ check_file (const char *infile, const ch SWAP_LINES (prevline, thisline); prevfield = thisfield; prevlen = thislen; @@ -4083,7 +4834,7 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c if (!match) match_count = 0; } -@@ -497,6 +735,19 @@ +@@ -498,6 +736,19 @@ main (int argc, char **argv) atexit (close_stdout); @@ -4103,9 +4854,111 @@ diff -Naur coreutils-8.24/src/uniq.c coreutils-8.24-mod/src/uniq.c skip_chars = 0; skip_fields = 0; check_chars = SIZE_MAX; -diff -Naur coreutils-8.24/tests/i18n/sort.sh coreutils-8.24-mod/tests/i18n/sort.sh ---- coreutils-8.24/tests/i18n/sort.sh 1969-12-31 18:00:00.000000000 -0600 -+++ coreutils-8.24-mod/tests/i18n/sort.sh 2015-07-04 15:08:33.517055673 -0500 +diff -Naurp coreutils-8.25-orig/tests/expand/mb.sh coreutils-8.25/tests/expand/mb.sh +--- coreutils-8.25-orig/tests/expand/mb.sh 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/tests/expand/mb.sh 2016-01-22 21:23:04.640975869 -0600 +@@ -0,0 +1,98 @@ ++#!/bin/sh ++ ++# Copyright (C) 2012-2015 Free Software Foundation, Inc. ++ ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src ++print_ver_ expand ++ ++export LC_ALL=en_US.UTF-8 ++ ++#input containing multibyte characters ++cat <<\EOF > in || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++EOF ++env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ ++ ++cat <<\EOF > exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#test characters with display widths != 1 ++env printf '12345678 ++e\t|ascii(1) ++\u00E9\t|composed(1) ++e\u0301\t|decomposed(1) ++\u3000\t|ideo-space(2) ++\uFF0D\t|full-hypen(2) ++' > in || framework_failure_ ++ ++env printf '12345678 ++e |ascii(1) ++\u00E9 |composed(1) ++e\u0301 |decomposed(1) ++\u3000 |ideo-space(2) ++\uFF0D |full-hypen(2) ++' > exp || framework_failure_ ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#shouldn't fail with "input line too long" ++#when a line starts with a control character ++env printf '\n' > in || framework_failure_ ++ ++expand < in > out || fail=1 ++compare in out > /dev/null 2>&1 || fail=1 ++ ++#non-Unicode characters interspersed between Unicode ones ++env printf '12345678 ++\t\xFF| ++\xFF\t| ++\t\xFFä| ++ä\xFF\t| ++\tä\xFF| ++\xFF\tä| ++äbcdef\xFF\t| ++' > in || framework_failure_ ++ ++env printf '12345678 ++ \xFF| ++\xFF | ++ \xFFä| ++ä\xFF | ++ ä\xFF| ++\xFF ä| ++äbcdef\xFF | ++' > exp || framework_failure_ ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++exit $fail +diff -Naurp coreutils-8.25-orig/tests/i18n/sort.sh coreutils-8.25/tests/i18n/sort.sh +--- coreutils-8.25-orig/tests/i18n/sort.sh 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/tests/i18n/sort.sh 2016-01-22 21:23:04.617641142 -0600 @@ -0,0 +1,29 @@ +#!/bin/sh +# Verify sort's multi-byte support. @@ -4136,10 +4989,10 @@ diff -Naur coreutils-8.24/tests/i18n/sort.sh coreutils-8.24-mod/tests/i18n/sort. + + +Exit $fail -diff -Naur coreutils-8.24/tests/local.mk coreutils-8.24-mod/tests/local.mk ---- coreutils-8.24/tests/local.mk 2015-07-03 07:03:55.000000000 -0500 -+++ coreutils-8.24-mod/tests/local.mk 2015-07-04 15:08:33.518055639 -0500 -@@ -341,6 +341,8 @@ +diff -Naurp coreutils-8.25-orig/tests/local.mk coreutils-8.25/tests/local.mk +--- coreutils-8.25-orig/tests/local.mk 2016-01-16 12:18:13.000000000 -0600 ++++ coreutils-8.25/tests/local.mk 2016-01-22 21:23:04.640975869 -0600 +@@ -344,6 +344,8 @@ all_tests = \ tests/misc/sort-discrim.sh \ tests/misc/sort-files0-from.pl \ tests/misc/sort-float.sh \ @@ -4148,10 +5001,26 @@ diff -Naur coreutils-8.24/tests/local.mk coreutils-8.24-mod/tests/local.mk tests/misc/sort-merge.pl \ tests/misc/sort-merge-fdlimit.sh \ tests/misc/sort-month.sh \ -diff -Naur coreutils-8.24/tests/misc/cut.pl coreutils-8.24-mod/tests/misc/cut.pl ---- coreutils-8.24/tests/misc/cut.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/cut.pl 2015-07-04 15:08:33.518055639 -0500 -@@ -23,9 +23,11 @@ +@@ -534,6 +536,7 @@ all_tests = \ + tests/du/threshold.sh \ + tests/du/trailing-slash.sh \ + tests/du/two-args.sh \ ++ tests/expand/mb.sh \ + tests/id/gnu-zero-uids.sh \ + tests/id/no-context.sh \ + tests/id/context.sh \ +@@ -672,6 +675,7 @@ all_tests = \ + tests/touch/read-only.sh \ + tests/touch/relative.sh \ + tests/touch/trailing-slash.sh \ ++ tests/unexpand/mb.sh \ + $(all_root_tests) + + # See tests/factor/create-test.sh. +diff -Naurp coreutils-8.25-orig/tests/misc/cut.pl coreutils-8.25/tests/misc/cut.pl +--- coreutils-8.25-orig/tests/misc/cut.pl 2016-01-16 12:18:13.000000000 -0600 ++++ coreutils-8.25/tests/misc/cut.pl 2016-01-22 21:23:04.617641142 -0600 +@@ -23,9 +23,11 @@ use strict; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -4165,7 +5034,7 @@ diff -Naur coreutils-8.24/tests/misc/cut.pl coreutils-8.24-mod/tests/misc/cut.pl my $prog = 'cut'; my $try = "Try '$prog --help' for more information.\n"; -@@ -227,6 +229,7 @@ +@@ -240,6 +242,7 @@ if ($mb_locale ne 'C') my @new_t = @$t; my $test_name = shift @new_t; @@ -4173,10 +5042,10 @@ diff -Naur coreutils-8.24/tests/misc/cut.pl coreutils-8.24-mod/tests/misc/cut.pl push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; } push @Tests, @new; -diff -Naur coreutils-8.24/tests/misc/expand.pl coreutils-8.24-mod/tests/misc/expand.pl ---- coreutils-8.24/tests/misc/expand.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/expand.pl 2015-07-04 15:08:33.518055639 -0500 -@@ -23,6 +23,15 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/expand.pl coreutils-8.25/tests/misc/expand.pl +--- coreutils-8.25-orig/tests/misc/expand.pl 2016-01-16 12:18:13.000000000 -0600 ++++ coreutils-8.25/tests/misc/expand.pl 2016-01-22 21:23:04.620974674 -0600 +@@ -23,6 +23,15 @@ use strict; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -4192,7 +5061,7 @@ diff -Naur coreutils-8.24/tests/misc/expand.pl coreutils-8.24-mod/tests/misc/exp my @Tests = ( ['t1', '--tabs=3', {IN=>"a\tb"}, {OUT=>"a b"}], -@@ -31,6 +40,37 @@ +@@ -31,6 +40,37 @@ my @Tests = ['i2', '--tabs=3 -i', {IN=>" \ta\tb"}, {OUT=>" a\tb"}], ); @@ -4230,10 +5099,10 @@ diff -Naur coreutils-8.24/tests/misc/expand.pl coreutils-8.24-mod/tests/misc/exp my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff -Naur coreutils-8.24/tests/misc/fold.pl coreutils-8.24-mod/tests/misc/fold.pl ---- coreutils-8.24/tests/misc/fold.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/fold.pl 2015-07-04 15:08:33.518055639 -0500 -@@ -20,9 +20,18 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/fold.pl coreutils-8.25/tests/misc/fold.pl +--- coreutils-8.25-orig/tests/misc/fold.pl 2016-01-16 12:18:13.000000000 -0600 ++++ coreutils-8.25/tests/misc/fold.pl 2016-01-22 21:23:04.620974674 -0600 +@@ -20,9 +20,18 @@ use strict; (my $program_name = $0) =~ s|.*/||; @@ -4252,7 +5121,7 @@ diff -Naur coreutils-8.24/tests/misc/fold.pl coreutils-8.24-mod/tests/misc/fold. my @Tests = ( ['s1', '-w2 -s', {IN=>"a\t"}, {OUT=>"a\n\t"}], -@@ -31,9 +40,48 @@ +@@ -31,9 +40,48 @@ my @Tests = ['s4', '-w4 -s', {IN=>"abc ef\n"}, {OUT=>"abc \nef\n"}], ); @@ -4302,10 +5171,10 @@ diff -Naur coreutils-8.24/tests/misc/fold.pl coreutils-8.24-mod/tests/misc/fold. -my $prog = 'fold'; my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose); exit $fail; -diff -Naur coreutils-8.24/tests/misc/join.pl coreutils-8.24-mod/tests/misc/join.pl ---- coreutils-8.24/tests/misc/join.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/join.pl 2015-07-04 15:08:33.518055639 -0500 -@@ -25,6 +25,15 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/join.pl coreutils-8.25/tests/misc/join.pl +--- coreutils-8.25-orig/tests/misc/join.pl 2016-01-16 12:18:13.000000000 -0600 ++++ coreutils-8.25/tests/misc/join.pl 2016-01-22 21:23:04.620974674 -0600 +@@ -25,6 +25,15 @@ my $limits = getlimits (); my $prog = 'join'; @@ -4321,7 +5190,7 @@ diff -Naur coreutils-8.24/tests/misc/join.pl coreutils-8.24-mod/tests/misc/join. my $delim = chr 0247; sub t_subst ($) { -@@ -326,8 +335,49 @@ +@@ -329,8 +338,49 @@ foreach my $t (@tv) push @Tests, $new_ent; } @@ -4371,9 +5240,9 @@ diff -Naur coreutils-8.24/tests/misc/join.pl coreutils-8.24-mod/tests/misc/join. my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff -Naur coreutils-8.24/tests/misc/sort-mb-tests.sh coreutils-8.24-mod/tests/misc/sort-mb-tests.sh ---- coreutils-8.24/tests/misc/sort-mb-tests.sh 1969-12-31 18:00:00.000000000 -0600 -+++ coreutils-8.24-mod/tests/misc/sort-mb-tests.sh 2015-07-04 15:08:33.518055639 -0500 +diff -Naurp coreutils-8.25-orig/tests/misc/sort-mb-tests.sh coreutils-8.25/tests/misc/sort-mb-tests.sh +--- coreutils-8.25-orig/tests/misc/sort-mb-tests.sh 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/tests/misc/sort-mb-tests.sh 2016-01-22 21:23:04.620974674 -0600 @@ -0,0 +1,45 @@ +#!/bin/sh +# Verify sort's multi-byte support. @@ -4420,10 +5289,10 @@ diff -Naur coreutils-8.24/tests/misc/sort-mb-tests.sh coreutils-8.24-mod/tests/m +compare exp out || { fail=1; cat out; } + +Exit $fail -diff -Naur coreutils-8.24/tests/misc/sort-merge.pl coreutils-8.24-mod/tests/misc/sort-merge.pl ---- coreutils-8.24/tests/misc/sort-merge.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/sort-merge.pl 2015-07-04 15:08:33.518055639 -0500 -@@ -26,6 +26,15 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/sort-merge.pl coreutils-8.25/tests/misc/sort-merge.pl +--- coreutils-8.25-orig/tests/misc/sort-merge.pl 2016-01-16 12:18:14.000000000 -0600 ++++ coreutils-8.25/tests/misc/sort-merge.pl 2016-01-22 21:23:04.624308207 -0600 +@@ -26,6 +26,15 @@ my $prog = 'sort'; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -4439,7 +5308,7 @@ diff -Naur coreutils-8.24/tests/misc/sort-merge.pl coreutils-8.24-mod/tests/misc # three empty files and one that says 'foo' my @inputs = (+(map{{IN=> {"empty$_"=> ''}}}1..3), {IN=> {foo=> "foo\n"}}); -@@ -77,6 +86,39 @@ +@@ -77,6 +86,39 @@ my @Tests = {OUT=>$big_input}], ); @@ -4479,10 +5348,10 @@ diff -Naur coreutils-8.24/tests/misc/sort-merge.pl coreutils-8.24-mod/tests/misc my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff -Naur coreutils-8.24/tests/misc/sort.pl coreutils-8.24-mod/tests/misc/sort.pl ---- coreutils-8.24/tests/misc/sort.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/sort.pl 2015-07-04 15:08:33.519055605 -0500 -@@ -24,10 +24,15 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/sort.pl coreutils-8.25/tests/misc/sort.pl +--- coreutils-8.25-orig/tests/misc/sort.pl 2016-01-16 12:18:14.000000000 -0600 ++++ coreutils-8.25/tests/misc/sort.pl 2016-01-22 21:23:04.624308207 -0600 +@@ -24,10 +24,15 @@ my $prog = 'sort'; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -4499,18 +5368,7 @@ diff -Naur coreutils-8.24/tests/misc/sort.pl coreutils-8.24-mod/tests/misc/sort. # Since each test is run with a file name and with redirected stdin, # the name in the diagnostic is either the file name or "-". # Normalize each diagnostic to use '-'. -@@ -321,6 +326,10 @@ - ["23", '-s -k1,1 -t/', {IN=>"a b/x\na-b-c/x\n"}, {OUT=>"a b/x\na-b-c/x\n"}, - {ENV => "LC_ALL=$mb_locale"}], - -+# This fails in Fedora 20, per Göran Uddeborg in: http://bugs.gnu.org/18540 -+["23", '-s -k1,1 -t/', {IN=>"a b/x\na-b-c/x\n"}, {OUT=>"a b/x\na-b-c/x\n"}, -+ {ENV => "LC_ALL=$mb_locale"}], -+ - ["no-file1", 'no-file', {EXIT=>2}, {ERR=>$no_file}], - # This test failed until 1.22f. Sort didn't give an error. - # From Will Edgington. -@@ -419,6 +428,38 @@ +@@ -424,6 +429,38 @@ foreach my $t (@Tests) } } @@ -4549,7 +5407,7 @@ diff -Naur coreutils-8.24/tests/misc/sort.pl coreutils-8.24-mod/tests/misc/sort. @Tests = triple_test \@Tests; # Remember that triple_test creates from each test with exactly one "IN" -@@ -428,6 +469,7 @@ +@@ -433,6 +470,7 @@ foreach my $t (@Tests) # Remove the IN_PIPE version of the "output-is-input" test above. # The others aren't susceptible because they have three inputs each. @Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests; @@ -4557,10 +5415,10 @@ diff -Naur coreutils-8.24/tests/misc/sort.pl coreutils-8.24-mod/tests/misc/sort. my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff -Naur coreutils-8.24/tests/misc/unexpand.pl coreutils-8.24-mod/tests/misc/unexpand.pl ---- coreutils-8.24/tests/misc/unexpand.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/unexpand.pl 2015-07-04 15:08:33.519055605 -0500 -@@ -27,6 +27,14 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/unexpand.pl coreutils-8.25/tests/misc/unexpand.pl +--- coreutils-8.25-orig/tests/misc/unexpand.pl 2016-01-16 12:18:14.000000000 -0600 ++++ coreutils-8.25/tests/misc/unexpand.pl 2016-01-22 21:23:04.624308207 -0600 +@@ -27,6 +27,14 @@ my $limits = getlimits (); my $prog = 'unexpand'; @@ -4575,7 +5433,7 @@ diff -Naur coreutils-8.24/tests/misc/unexpand.pl coreutils-8.24-mod/tests/misc/u my @Tests = ( ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}], -@@ -92,6 +100,37 @@ +@@ -92,6 +100,37 @@ my @Tests = {EXIT => 1}, {ERR => "$prog: tab stop value is too large\n"}], ); @@ -4613,10 +5471,10 @@ diff -Naur coreutils-8.24/tests/misc/unexpand.pl coreutils-8.24-mod/tests/misc/u my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff -Naur coreutils-8.24/tests/misc/uniq.pl coreutils-8.24-mod/tests/misc/uniq.pl ---- coreutils-8.24/tests/misc/uniq.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/misc/uniq.pl 2015-07-04 15:08:33.519055605 -0500 -@@ -23,9 +23,17 @@ +diff -Naurp coreutils-8.25-orig/tests/misc/uniq.pl coreutils-8.25/tests/misc/uniq.pl +--- coreutils-8.25-orig/tests/misc/uniq.pl 2016-01-16 12:18:14.000000000 -0600 ++++ coreutils-8.25/tests/misc/uniq.pl 2016-01-22 21:23:04.627641739 -0600 +@@ -23,9 +23,17 @@ my $limits = getlimits (); my $prog = 'uniq'; my $try = "Try '$prog --help' for more information.\n"; @@ -4634,7 +5492,7 @@ diff -Naur coreutils-8.24/tests/misc/uniq.pl coreutils-8.24-mod/tests/misc/uniq. # When possible, create a "-z"-testing variant of each test. sub add_z_variants($) { -@@ -261,6 +269,53 @@ +@@ -262,6 +270,53 @@ foreach my $t (@Tests) and push @$t, {ENV=>'_POSIX2_VERSION=199209'}; } @@ -4688,10 +5546,10 @@ diff -Naur coreutils-8.24/tests/misc/uniq.pl coreutils-8.24-mod/tests/misc/uniq. @Tests = add_z_variants \@Tests; @Tests = triple_test \@Tests; -diff -Naur coreutils-8.24/tests/pr/pr-tests.pl coreutils-8.24-mod/tests/pr/pr-tests.pl ---- coreutils-8.24/tests/pr/pr-tests.pl 2015-06-26 12:04:19.000000000 -0500 -+++ coreutils-8.24-mod/tests/pr/pr-tests.pl 2015-07-04 15:08:33.519055605 -0500 -@@ -24,6 +24,15 @@ +diff -Naurp coreutils-8.25-orig/tests/pr/pr-tests.pl coreutils-8.25/tests/pr/pr-tests.pl +--- coreutils-8.25-orig/tests/pr/pr-tests.pl 2016-01-16 12:18:14.000000000 -0600 ++++ coreutils-8.25/tests/pr/pr-tests.pl 2016-01-22 21:23:04.627641739 -0600 +@@ -24,6 +24,15 @@ use strict; my $prog = 'pr'; my $normalize_strerror = "s/': .*/'/"; @@ -4707,7 +5565,7 @@ diff -Naur coreutils-8.24/tests/pr/pr-tests.pl coreutils-8.24-mod/tests/pr/pr-te my @tv = ( # -b option is no longer an official option. But it's still working to -@@ -467,8 +476,48 @@ +@@ -467,8 +476,48 @@ push @Tests, {IN=>{3=>"x\ty\tz\n"}}, {OUT=>join("\t", qw(a b c m n o x y z)) . "\n"} ]; @@ -4756,3 +5614,104 @@ diff -Naur coreutils-8.24/tests/pr/pr-tests.pl coreutils-8.24-mod/tests/pr/pr-te my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; +diff -Naurp coreutils-8.25-orig/tests/unexpand/mb.sh coreutils-8.25/tests/unexpand/mb.sh +--- coreutils-8.25-orig/tests/unexpand/mb.sh 1969-12-31 18:00:00.000000000 -0600 ++++ coreutils-8.25/tests/unexpand/mb.sh 2016-01-22 21:23:04.640975869 -0600 +@@ -0,0 +1,97 @@ ++#!/bin/sh ++ ++# Copyright (C) 2012-2015 Free Software Foundation, Inc. ++ ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src ++print_ver_ unexpand ++ ++export LC_ALL=en_US.UTF-8 ++ ++#input containing multibyte characters ++cat > in <<\EOF ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++cat > exp <<\EOF ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#test characters with a display width larger than 1 ++ ++env printf '12345678 ++e |ascii(1) ++\u00E9 |composed(1) ++e\u0301 |decomposed(1) ++\u3000 |ideo-space(2) ++\uFF0D |full-hypen(2) ++' > in || framework_failure_ ++ ++env printf '12345678 ++e\t|ascii(1) ++\u00E9\t|composed(1) ++e\u0301\t|decomposed(1) ++\u3000\t|ideo-space(2) ++\uFF0D\t|full-hypen(2) ++' > exp || framework_failure_ ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#test input where a blank of width > 1 is not being substituted ++in="$(LC_ALL=en_US.UTF-8 printf ' \u3000 ö ü ß')" ++exp='   ö ü ß' ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#non-Unicode characters interspersed between Unicode ones ++env printf '12345678 ++ \xFF| ++\xFF | ++ \xFFä| ++ä\xFF | ++ ä\xFF| ++\xFF ä| ++äbcdef\xFF | ++' > in || framework_failure_ ++ ++env printf '12345678 ++\t\xFF| ++\xFF\t| ++\t\xFFä| ++ä\xFF\t| ++\tä\xFF| ++\xFF\tä| ++äbcdef\xFF\t| ++' > exp || framework_failure_ ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 diff --git a/coreutils.spec b/coreutils.spec index c8113ec..05faa1b 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,6 +1,6 @@ %define i18npatch_version %version Name: coreutils -Version: 8.24 +Version: 8.25 Release: 1mamba Summary: A GNU set of tools commonly used in shell scripts Group: System/Tools @@ -188,6 +188,9 @@ exit 0 #%doc THANKS THANKS-to-translators THANKStt.in %changelog +* Sat Jan 23 2016 Automatic Build System 8.25-1mamba +- automatic version update by autodist + * Sun Jul 05 2015 Automatic Build System 8.24-1mamba - automatic version update by autodist