Eric Blake <ebb9 <at> byu.net> writes: > > Gary noticed an issue with the indentation of multi-specifier od: > > $ od -t cx1 abc.txt > ~ 0000000 T h i s i s a b c f i l e > ~ 54 68 69 73 20 69 73 20 61 62 63 20 66 69 6c 65 > ~ 0000020 \n > ~ 0a > ~ 0000021 > > |> | That looks horrible! > |> > |> Not a compliance bug, but you are certainly welcome to report it upstream > |> as an QoI enhancement request. > > I gave this more thought. Since od enforces that each output line consume > a multiple of the lcm of input bytes per field, and it already knows how > many bytes are output per field, then it should be possible to compute the > amount of padding per field necessary to make all fields right-justified. > ~ I'm working on a patch for this. > > In looking at the code, there are also some simplifications when we heed > autoconf's advice that HAVE_LONG_DOUBLE is an obsolete construct (ie. all > reasonable porting targets support compilation of long double, and we use > gnulib's printf to make up for libc deficiencies in printing long double, > so that code does not need to be conditionally compiled). I'll include a > patch for that in my series. > > -- > Don't work too hard, make some time for fun as well! > > Eric Blake ebb9 <at> byu.net >
Here's my attempt at a series to address this: Eric Blake (3): od defaults to -toS, not -td2. Align multiple od -t specs. Simplify long double support. NEWS | 1 + THANKS | 1 + m4/jm-macros.m4 | 1 - src/od.c | 150 ++++++++++++++++++++++++++++------------------ tests/Makefile.am | 1 + tests/misc/od-multiple-t | 47 ++++++++++++++ 6 files changed, 142 insertions(+), 59 deletions(-) create mode 100755 tests/misc/od-multiple-t I chose to use fixed-width padding for every field, rather than trying to be even more complicated by using variable-width padding to minimize the overall resulting line length. The result thus has a lot of consecutive spaces for certain combinations of -t, but at least things are consistently aligned: $ src/od -An -N48 configure -tx8 -tfL 2f6e69622f202123 65754720230a6873 65756c6176207373 0.000000000000000000e+9999 0.000000000000000000e+9999 797320726f662073 7065642d6d657473 7620746e65646e65 0.000000000000000000e+9999 0.000000000000000000e+9999 $ src/od -An -N48 configure -tx8 2f6e69622f202123 65754720230a6873 65756c6176207373 797320726f662073 7065642d6d657473 7620746e65646e65 $ src/od -An -N48 configure -tfL 0.000000000000000000e+9999 0.000000000000000000e+9999 0.000000000000000000e+9999 0.000000000000000000e+9999 I'm not sure why cygwin is printing such a weird value for (invalid) long doubles, but this patch didn't change the situation. It seems like a NaN might be better than 0.0...e+9999 if the random 12-byte sequence can't be converted to a valid 10-byte register long double on x86. Perhaps this is a bug in gnulib's printf replacement? In case gmane botches this patch with line wraps, you could try the original file from here: http://home.comcast.net/~ericblake/coreutils.patch7 From: Eric Blake <[EMAIL PROTECTED]> Date: Wed, 11 Jun 2008 08:01:31 -0600 Subject: [PATCH] od defaults to -toS, not -td2. * src/od.c (usage): Correct description of default. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- src/od.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/od.c b/src/od.c index 4df8e7d..97e43ea 100644 --- a/src/od.c +++ b/src/od.c @@ -382,7 +382,7 @@ output line. \ "), stdout); fputs (_("\ --string without a number implies 3. --width without a number\n\ -implies 32. By default, od uses -A o -t d2 -w16.\n\ +implies 32. By default, od uses -A o -t oS -w16.\n\ "), stdout); emit_bug_reporting_address (); } -- 1.5.5.1 >From 5700d58ce428655c7560c83249e971c90971ee28 Mon Sep 17 00:00:00 2001 From: Eric Blake <[EMAIL PROTECTED]> Date: Wed, 11 Jun 2008 09:14:26 -0600 Subject: [PATCH] Align multiple od -t specs. * src/od.c (struct tspec): Add pad_width field, and adjust print_function prototype. (decode_one_format): Default to pad width of 1, and rewrite all fmt_string to account for pad width. (FMT_BYTES_ALLOCATED): Adjust to new format style. (main): Compute pad width per spec. (write_block): Account for pad width. (print_s_char, print_char, print_s_short, print_short, print_int) (print_long, print_long_long, print_float, print_double) (print_long_double, print_named_ascii, print_ascii): All print functions adjusted to use pad width. * tests/Makefile.am (TESTS): Add test. * tests/misc/od-multiple-t: New file. * THANKS: Update. * NEWS: Mention the improvement. Reported by Gary Johnson. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- NEWS | 1 + THANKS | 1 + src/od.c | 124 +++++++++++++++++++++++++++++++--------------- tests/Makefile.am | 1 + tests/misc/od-multiple-t | 47 +++++++++++++++++ 5 files changed, 134 insertions(+), 40 deletions(-) create mode 100755 tests/misc/od-multiple-t diff --git a/NEWS b/NEWS index 97f3162..cfaa3e6 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ GNU coreutils NEWS HP-UX 11, Tru64, AIX, IRIX 6.5, and Cygwin, "ls -l" now displays the presence of an ACL on a file via a '+' sign after the mode, and "cp -p" copies ACLs. + od now aligns fields across lines when printing multiple -t specifiers. * Noteworthy changes in release 6.12 (2008-05-31) [stable] diff --git a/THANKS b/THANKS index cb9b098..a9bb12f 100644 --- a/THANKS +++ b/THANKS @@ -182,6 +182,7 @@ Gabor Z. Papp [EMAIL PROTECTED] Gaël Quéri [EMAIL PROTECTED] Galen Hazelwood [EMAIL PROTECTED] Gary Anderson [EMAIL PROTECTED] +Gary Johnson [EMAIL PROTECTED] Gary V. Vaughan [EMAIL PROTECTED] Gaute Hvoslef Kvalnes [EMAIL PROTECTED] Geoff Collyer geoff at collyer.net diff --git a/src/od.c b/src/od.c index 97e43ea..c0f06a7 100644 --- a/src/od.c +++ b/src/od.c @@ -92,13 +92,13 @@ enum output_format enum { FMT_BYTES_ALLOCATED = - MAX ((sizeof " %0" - 1 + INT_STRLEN_BOUND (int) + MAX ((sizeof "%*s%0" - 1 + INT_STRLEN_BOUND (int) + MAX (sizeof "ld", MAX (sizeof PRIdMAX, MAX (sizeof PRIoMAX, MAX (sizeof PRIuMAX, sizeof PRIxMAX))))), - sizeof " %.Le" + 2 * INT_STRLEN_BOUND (int)) + sizeof "%*s%.Le" + 2 * INT_STRLEN_BOUND (int)) }; /* Each output format specification (from `-t spec' or from @@ -107,10 +107,11 @@ struct tspec { enum output_format fmt; enum size_spec size; - void (*print_function) (size_t, void const *, char const *); + void (*print_function) (size_t, void const *, char const *, int); char fmt_string[FMT_BYTES_ALLOCATED]; bool hexl_mode_trailer; int field_width; + int pad_width; }; /* Convert the number of 8-bit bytes of a binary representation to @@ -392,94 +393,101 @@ implies 32. By default, od uses /* Define the print functions. */ static void -print_s_char (size_t n_bytes, void const *block, char const *fmt_string) +print_s_char (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { signed char const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_char (size_t n_bytes, void const *block, char const *fmt_string) +print_char (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { unsigned char const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_s_short (size_t n_bytes, void const *block, char const *fmt_string) +print_s_short (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { short int const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_short (size_t n_bytes, void const *block, char const *fmt_string) +print_short (size_t n_bytes, void const *block, char const *fmt_string, int pad) { unsigned short int const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_int (size_t n_bytes, void const *block, char const *fmt_string) +print_int (size_t n_bytes, void const *block, char const *fmt_string, int pad) { unsigned int const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_long (size_t n_bytes, void const *block, char const *fmt_string) +print_long (size_t n_bytes, void const *block, char const *fmt_string, int pad) { unsigned long int const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_long_long (size_t n_bytes, void const *block, char const *fmt_string) +print_long_long (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { unsigned_long_long_int const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_float (size_t n_bytes, void const *block, char const *fmt_string) +print_float (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { float const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } static void -print_double (size_t n_bytes, void const *block, char const *fmt_string) +print_double (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { double const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } #ifdef HAVE_LONG_DOUBLE static void -print_long_double (size_t n_bytes, void const *block, char const *fmt_string) +print_long_double (size_t n_bytes, void const *block, char const *fmt_string, + int pad) { long double const *p = block; size_t i; for (i = n_bytes / sizeof *p; i != 0; i--) - printf (fmt_string, *p++); + printf (fmt_string, pad, "", *p++); } #endif @@ -499,7 +507,7 @@ dump_hexl_mode_trailer (size_t n_bytes, static void print_named_ascii (size_t n_bytes, void const *block, - const char *unused_fmt_string ATTRIBUTE_UNUSED) + const char *unused_fmt_string ATTRIBUTE_UNUSED, int pad) { unsigned char const *p = block; size_t i; @@ -519,13 +527,13 @@ print_named_ascii (size_t n_bytes, void const *block, s = buf; } - printf (" %3s", s); + printf ("%*s%3s", pad, "", s); } } static void print_ascii (size_t n_bytes, void const *block, - const char *unused_fmt_string ATTRIBUTE_UNUSED) + const char *unused_fmt_string ATTRIBUTE_UNUSED, int pad) { unsigned char const *p = block; size_t i; @@ -574,7 +582,7 @@ print_ascii (size_t n_bytes, void const *block, s = buf; } - printf (" %3s", s); + printf ("%*s%3s", pad, "", s); } } @@ -614,7 +622,8 @@ simple_strtoul (const char *s, const char **p, fmt = SIGNED_DECIMAL; size = INT or LONG; (whichever integral_type_size[4] resolves to) print_function = print_int; (assuming size == INT) - fmt_string = "%011d%c"; + fmt_string = "%*s%011d"; + pad_width = 1; (but may be increased later) } S_ORIG is solely for reporting errors. It should be the full format string argument. @@ -628,7 +637,7 @@ decode_one_format (const char *s_orig, const unsigned long int size; enum output_format fmt; const char *pre_fmt_string; - void (*print_function) (size_t, void const *, char const *); + void (*print_function) (size_t, void const *, char const *, int); const char *p; char c; int field_width; @@ -702,28 +711,28 @@ this system doesn't provide a %lu-byte { case 'd': fmt = SIGNED_DECIMAL; - sprintf (tspec->fmt_string, " %%%d%s", + sprintf (tspec->fmt_string, "%%*s%%%d%s", (field_width = bytes_to_signed_dec_digits[size]), ISPEC_TO_FORMAT (size_spec, "d", "ld", PRIdMAX)); break; case 'o': fmt = OCTAL; - sprintf (tspec->fmt_string, " %%0%d%s", + sprintf (tspec->fmt_string, "%%*s%%0%d%s", (field_width = bytes_to_oct_digits[size]), ISPEC_TO_FORMAT (size_spec, "o", "lo", PRIoMAX)); break; case 'u': fmt = UNSIGNED_DECIMAL; - sprintf (tspec->fmt_string, " %%%d%s", + sprintf (tspec->fmt_string, "%%*s%%%d%s", (field_width = bytes_to_unsigned_dec_digits[size]), ISPEC_TO_FORMAT (size_spec, "u", "lu", PRIuMAX)); break; case 'x': fmt = HEXADECIMAL; - sprintf (tspec->fmt_string, " %%0%d%s", + sprintf (tspec->fmt_string, "%%*s%%0%d%s", (field_width = bytes_to_hex_digits[size]), ISPEC_TO_FORMAT (size_spec, "x", "lx", PRIxMAX)); break; @@ -817,20 +826,20 @@ this system doesn't provide a %lu-byte floating case FLOAT_SINGLE: print_function = print_float; /* Don't use %#e; not all systems support it. */ - pre_fmt_string = " %%%d.%de"; + pre_fmt_string = "%%*s%%%d.%de"; precision = FLT_DIG; break; case FLOAT_DOUBLE: print_function = print_double; - pre_fmt_string = " %%%d.%de"; + pre_fmt_string = "%%*s%%%d.%de"; precision = DBL_DIG; break; #ifdef HAVE_LONG_DOUBLE case FLOAT_LONG_DOUBLE: print_function = print_long_double; - pre_fmt_string = " %%%d.%dLe"; + pre_fmt_string = "%%*s%%%d.%dLe"; precision = LDBL_DIG; break; #endif @@ -870,6 +879,7 @@ this system doesn't provide a %lu-byte floating tspec->print_function = print_function; tspec->field_width = field_width; + tspec->pad_width = 1; tspec->hexl_mode_trailer = (*s == 'z'); if (tspec->hexl_mode_trailer) s++; @@ -1198,13 +1208,14 @@ write_block (uintmax_t current_offset, size_t n_bytes, format_address (current_offset, '\0'); else printf ("%*s", address_pad_len, ""); - (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string); + (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string, + spec[i].pad_width); if (spec[i].hexl_mode_trailer) { /* space-pad out to full line width, then dump the trailer */ int datum_width = width_bytes[spec[i].size]; int blank_fields = (bytes_per_block - n_bytes) / datum_width; - int field_width = spec[i].field_width + 1; + int field_width = spec[i].field_width + spec[i].pad_width; printf ("%*s", blank_fields * field_width, ""); dump_hexl_mode_trailer (n_bytes, curr_block); } @@ -1555,6 +1566,7 @@ main (int argc, char **argv) bool modern = false; bool width_specified = false; bool ok = true; + size_t width_per_lcm = 0; static char const multipliers[] = "bEGKkMmPTYZ0"; /* The old-style `pseudo starting address' to be printed in parentheses @@ -1915,11 +1927,43 @@ it must be one character from [doxn]"), bytes_per_block = l_c_m; } + /* Compute padding necessary to align output block. */ + if (1 < n_specs) + { + for (i = 0; i < n_specs; i++) + { + int fields_per_lcm = l_c_m / width_bytes[spec[i].size]; + int lcm_width = (spec[i].field_width + 1) * fields_per_lcm; + if (width_per_lcm < lcm_width) + { + width_per_lcm = lcm_width; + if (width_per_lcm % l_c_m) + width_per_lcm = ((width_per_lcm / l_c_m) + 1) * l_c_m; + } + } + for (i = 0; i < n_specs; i++) + { + int fields_per_block = bytes_per_block / width_bytes[spec[i].size]; + int block_width = spec[i].field_width * fields_per_block; + spec[i].pad_width = ((width_per_lcm * (bytes_per_block / l_c_m) + - block_width) / fields_per_block); + } + } + #ifdef DEBUG + else + width_per_lcm = spec[0].field_width + 1; + printf (_("lcm=%d, width_per_lcm=%zu\n"), l_c_m, width_per_lcm); for (i = 0; i < n_specs; i++) { - printf (_("%d: fmt=\"%s\" width=%d\n"), - i, spec[i].fmt_string, width_bytes[spec[i].size]); + int fields_per_lcm = l_c_m / width_bytes[spec[i].size]; + assert (bytes_per_block % width_bytes[spec[i].size] == 0); + assert (width_per_lcm == ((spec[i].field_width + spec[i].pad_width) + * fields_per_lcm)); + assert (spec[i].pad_width && spec[i].pad_width < width_per_lcm); + printf (_("%d: fmt=\"%s\" in_width=%d out_width=%d pad=%d\n"), + i, spec[i].fmt_string, width_bytes[spec[i].size], + spec[i].field_width, spec[i].pad_width); } #endif diff --git a/tests/Makefile.am b/tests/Makefile.am index bc17299..d09e451 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -171,6 +171,7 @@ TESTS = \ misc/nl \ misc/nohup \ misc/od-N \ + misc/od-multiple-t \ misc/od-x8 \ misc/paste \ misc/pathchk1 \ diff --git a/tests/misc/od-multiple-t b/tests/misc/od-multiple-t new file mode 100755 index 0000000..63fb7e4 --- /dev/null +++ b/tests/misc/od-multiple-t @@ -0,0 +1,47 @@ +#!/bin/sh +# verify that multiple -t specifiers to od align well +# This would fail before coreutils-6.13. + +# Copyright (C) 2008 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 <http://www.gnu.org/licenses/>. + +if test "$VERBOSE" = yes; then + set -x + od --version +fi + +. $srcdir/test-lib.sh + +# Choose 48 bytes for the input, as that is lcm for 1, 2, 4, 8, 12, 16; +# we don't anticipate any other native object size on modern hardware. +seq 19 > in || framework_failure +test `wc -c < in` -eq 48 || framework_failure + +fail=0 + +list='a c dC dS dI dL oC oS oI oL uC uS uI uL xC xS xI xL fF fD fL' +for format1 in $list; do + for format2 in $list; do + od -An -t${format1}z -t${format2}z in > out-raw || fail=1 + linewidth=`head -n1 out-raw | wc -c` + linecount=`wc -l < out-raw` + echo $format1 $format2 `wc -c < out-raw` >> out + echo $format1 $format2 `expr $linewidth '*' $linecount` >> exp + done +done + +compare out exp || fail=1 + +(exit $fail); exit $fail -- 1.5.5.1 >From 79c3502e37ec5d898ceb1cc8bf13cac9fb9c9591 Mon Sep 17 00:00:00 2001 From: Eric Blake <[EMAIL PROTECTED]> Date: Wed, 11 Jun 2008 11:45:16 -0600 Subject: [PATCH] Simplify long double support. * m4/jm-macros.m4 (gl_CHECK_ALL_TYPES): Remove obsolete check for AC_C_LONG_DOUBLE. * src/od.c (LONG_DOUBLE): Delete. (width_bytes, MAX_FP_TYPE_SIZE, decode_one_format, main): Just use 'long double' directly. (print_long_double): No longer protect by HAVE_LONG_DOUBLE. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- m4/jm-macros.m4 | 1 - src/od.c | 24 +++++++----------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/m4/jm-macros.m4 b/m4/jm-macros.m4 index cf1f2f0..9680e95 100644 --- a/m4/jm-macros.m4 +++ b/m4/jm-macros.m4 @@ -140,7 +140,6 @@ AC_DEFUN([gl_CHECK_ALL_TYPES], AC_REQUIRE([AC_C_BIGENDIAN]) AC_REQUIRE([AC_C_VOLATILE]) AC_REQUIRE([AC_C_INLINE]) - AC_REQUIRE([AC_C_LONG_DOUBLE]) AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) AC_REQUIRE([gl_CHECK_ALL_HEADERS]) diff --git a/src/od.c b/src/od.c index c0f06a7..1d8b369 100644 --- a/src/od.c +++ b/src/od.c @@ -34,12 +34,6 @@ #include <float.h> -#ifdef HAVE_LONG_DOUBLE -typedef long double LONG_DOUBLE; -#else -typedef double LONG_DOUBLE; -#endif - /* The default number of input bytes per output line. */ #define DEFAULT_BYTES_PER_BLOCK 16 @@ -160,7 +154,7 @@ static const int width_bytes[] = sizeof (unsigned_long_long_int), sizeof (float), sizeof (double), - sizeof (LONG_DOUBLE) + sizeof (long double) }; /* Ensure that for each member of `enum size_spec' there is an @@ -260,7 +254,7 @@ static bool have_read_stdin; /* Map the size in bytes to a type identifier. */ static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1]; -#define MAX_FP_TYPE_SIZE sizeof (LONG_DOUBLE) +#define MAX_FP_TYPE_SIZE sizeof (long double) static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1]; static char const short_options[] = "A:aBbcDdeFfHhIij:LlN:OoS:st:vw::Xx"; @@ -479,7 +473,6 @@ print_double (size_t n_bytes, void const *block, printf (fmt_string, pad, "", *p++); } -#ifdef HAVE_LONG_DOUBLE static void print_long_double (size_t n_bytes, void const *block, char const *fmt_string, int pad) @@ -489,7 +482,6 @@ print_long_double (size_t n_bytes, void const for (i = n_bytes / sizeof *p; i != 0; i--) printf (fmt_string, pad, "", *p++); } -#endif static void dump_hexl_mode_trailer (size_t n_bytes, const char *block) @@ -791,7 +783,7 @@ this system doesn't provide a %lu-byte case 'L': ++s; - size = sizeof (LONG_DOUBLE); + size = sizeof (long double); break; default: @@ -836,13 +828,11 @@ this system doesn't provide a %lu-byte precision = DBL_DIG; break; -#ifdef HAVE_LONG_DOUBLE case FLOAT_LONG_DOUBLE: print_function = print_long_double; pre_fmt_string = "%%*s%%%d.%dLe"; precision = LDBL_DIG; break; -#endif default: abort (); @@ -1598,10 +1588,10 @@ main (int argc, char **argv) fp_type_size[i] = NO_SIZE; fp_type_size[sizeof (float)] = FLOAT_SINGLE; - /* The array entry for `double' is filled in after that for LONG_DOUBLE - so that if `long double' is the same type or if long double isn't - supported FLOAT_LONG_DOUBLE will never be used. */ - fp_type_size[sizeof (LONG_DOUBLE)] = FLOAT_LONG_DOUBLE; + /* The array entry for `double' is filled in after that for `long double' + so that if they are the same size, we avoid any overhead of + long double computation in libc. */ + fp_type_size[sizeof (long double)] = FLOAT_LONG_DOUBLE; fp_type_size[sizeof (double)] = FLOAT_DOUBLE; n_specs = 0; -- 1.5.5.1 _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils