diff options
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/cut.c | 257 | ||||
-rw-r--r-- | src/local.mk | 3 | ||||
-rw-r--r-- | src/set-fields.c | 322 | ||||
-rw-r--r-- | src/set-fields.h | 49 | ||||
-rwxr-xr-x | tests/misc/cut.pl | 27 |
6 files changed, 403 insertions, 256 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in index abec10961..b3fe66866 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -109,6 +109,7 @@ src/rmdir.c src/runcon.c src/selinux.c src/seq.c +src/set-fields.c src/shred.c src/shuf.c src/sleep.c @@ -34,9 +34,10 @@ #include "fadvise.h" #include "getndelim2.h" #include "hash.h" -#include "quote.h" #include "xstrndup.h" +#include "set-fields.h" + /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "cut" @@ -54,41 +55,11 @@ while (0) -struct range_pair - { - size_t lo; - size_t hi; - }; - -/* Array of `struct range_pair' holding all the finite ranges. */ -static struct range_pair *rp; - /* Pointer inside RP. When checking if a byte or field is selected by a finite range, we check if it is between CURRENT_RP.LO and CURRENT_RP.HI. If the byte or field index is greater than CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */ -static struct range_pair *current_rp; - -/* Number of finite ranges specified by the user. */ -static size_t n_rp; - -/* Number of `struct range_pair's allocated. */ -static size_t n_rp_allocated; - - -/* Append LOW, HIGH to the list RP of range pairs, allocating additional - space if necessary. Update global variable N_RP. When allocating, - update global variable N_RP_ALLOCATED. */ - -static void -add_range_pair (size_t lo, size_t hi) -{ - if (n_rp == n_rp_allocated) - rp = X2NREALLOC (rp, &n_rp_allocated); - rp[n_rp].lo = lo; - rp[n_rp].hi = hi; - ++n_rp; -} +static struct field_range_pair *current_rp; /* This buffer is used to support the semantics of the -s option (or lack of same) when the specified field list includes (does @@ -221,208 +192,6 @@ Each range is one of:\n\ exit (status); } -/* Comparison function for qsort to order the list of - struct range_pairs. */ -static int -compare_ranges (const void *a, const void *b) -{ - int a_start = ((const struct range_pair *) a)->lo; - int b_start = ((const struct range_pair *) b)->lo; - return a_start < b_start ? -1 : a_start > b_start; -} - -/* Reallocate Range Pair entries, with corresponding - entries outside the range of each specified entry. */ - -static void -complement_rp (void) -{ - if (complement) - { - struct range_pair *c = rp; - size_t n = n_rp; - size_t i; - - rp = NULL; - n_rp = 0; - n_rp_allocated = 0; - - if (c[0].lo > 1) - add_range_pair (1, c[0].lo - 1); - - for (i = 1; i < n; ++i) - { - if (c[i-1].hi + 1 == c[i].lo) - continue; - - add_range_pair (c[i-1].hi + 1, c[i].lo - 1); - } - - if (c[n-1].hi < SIZE_MAX) - add_range_pair (c[n-1].hi + 1, SIZE_MAX); - - free (c); - } -} - -/* Given the list of field or byte range specifications FIELDSTR, - allocate and initialize the RP array. FIELDSTR should - be composed of one or more numbers or ranges of numbers, separated - by blanks or commas. Incomplete ranges may be given: '-m' means '1-m'; - 'n-' means 'n' through end of line. - Return true if FIELDSTR contains at least one field specification, - false otherwise. */ - -static bool -set_fields (const char *fieldstr) -{ - size_t initial = 1; /* Value of first number in a range. */ - size_t value = 0; /* If nonzero, a number being accumulated. */ - bool lhs_specified = false; - bool rhs_specified = false; - bool dash_found = false; /* True if a '-' is found in this field. */ - bool field_found = false; /* True if at least one field spec - has been processed. */ - - size_t i; - bool in_digits = false; - - /* Collect and store in RP the range end points. */ - - while (true) - { - if (*fieldstr == '-') - { - in_digits = false; - /* Starting a range. */ - if (dash_found) - FATAL_ERROR (_("invalid byte, character or field list")); - dash_found = true; - fieldstr++; - - if (lhs_specified && !value) - FATAL_ERROR (_("fields and positions are numbered from 1")); - - initial = (lhs_specified ? value : 1); - value = 0; - } - else if (*fieldstr == ',' - || isblank (to_uchar (*fieldstr)) || *fieldstr == '\0') - { - in_digits = false; - /* Ending the string, or this field/byte sublist. */ - if (dash_found) - { - dash_found = false; - - if (!lhs_specified && !rhs_specified) - FATAL_ERROR (_("invalid range with no endpoint: -")); - - /* A range. Possibilities: -n, m-n, n-. - In any case, 'initial' contains the start of the range. */ - if (!rhs_specified) - { - /* 'n-'. From 'initial' to end of line. */ - add_range_pair (initial, SIZE_MAX); - field_found = true; - } - else - { - /* 'm-n' or '-n' (1-n). */ - if (value < initial) - FATAL_ERROR (_("invalid decreasing range")); - - add_range_pair (initial, value); - field_found = true; - } - value = 0; - } - else - { - /* A simple field number, not a range. */ - if (value == 0) - FATAL_ERROR (_("fields and positions are numbered from 1")); - add_range_pair (value, value); - value = 0; - field_found = true; - } - - if (*fieldstr == '\0') - break; - - fieldstr++; - lhs_specified = false; - rhs_specified = false; - } - else if (ISDIGIT (*fieldstr)) - { - /* Record beginning of digit string, in case we have to - complain about it. */ - static char const *num_start; - if (!in_digits || !num_start) - num_start = fieldstr; - in_digits = true; - - if (dash_found) - rhs_specified = 1; - else - lhs_specified = 1; - - /* Detect overflow. */ - if (!DECIMAL_DIGIT_ACCUMULATE (value, *fieldstr - '0', size_t) - || value == SIZE_MAX) - { - /* In case the user specified -c$(echo 2^64|bc),22, - complain only about the first number. */ - /* Determine the length of the offending number. */ - size_t len = strspn (num_start, "0123456789"); - char *bad_num = xstrndup (num_start, len); - if (operating_mode == byte_mode) - error (0, 0, - _("byte offset %s is too large"), quote (bad_num)); - else - error (0, 0, - _("field number %s is too large"), quote (bad_num)); - free (bad_num); - exit (EXIT_FAILURE); - } - - fieldstr++; - } - else - FATAL_ERROR (_("invalid byte, character or field list")); - } - - qsort (rp, n_rp, sizeof (rp[0]), compare_ranges); - - /* Merge range pairs (e.g. `2-5,3-4' becomes `2-5'). */ - for (i = 0; i < n_rp; ++i) - { - for (size_t j = i + 1; j < n_rp; ++j) - { - if (rp[j].lo <= rp[i].hi) - { - rp[i].hi = MAX (rp[j].hi, rp[i].hi); - memmove (rp + j, rp + j + 1, (n_rp - j - 1) * sizeof *rp); - n_rp--; - j--; - } - else - break; - } - } - - complement_rp (); - - /* After merging, reallocate RP so we release memory to the system. - Also add a sentinel at the end of RP, to avoid out of bounds access - and for performance reasons. */ - ++n_rp; - rp = xrealloc (rp, n_rp * sizeof (struct range_pair)); - rp[n_rp - 1].lo = rp[n_rp - 1].hi = SIZE_MAX; - - return field_found; -} /* Increment *ITEM_IDX (i.e., a field or byte index), and if required CURRENT_RP. */ @@ -463,7 +232,7 @@ cut_bytes (FILE *stream) byte_idx = 0; print_delimiter = false; - current_rp = rp; + current_rp = frp; while (true) { int c; /* Each character from the file. */ @@ -475,7 +244,7 @@ cut_bytes (FILE *stream) putchar ('\n'); byte_idx = 0; print_delimiter = false; - current_rp = rp; + current_rp = frp; } else if (c == EOF) { @@ -514,7 +283,7 @@ cut_fields (FILE *stream) bool found_any_selected_field = false; bool buffer_first_field; - current_rp = rp; + current_rp = frp; c = getc (stream); if (c == EOF) @@ -642,7 +411,7 @@ cut_fields (FILE *stream) if (c == EOF) break; field_idx = 1; - current_rp = rp; + current_rp = frp; found_any_selected_field = false; } } @@ -793,13 +562,9 @@ main (int argc, char **argv) FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\ \tonly when operating on fields")); - if (! set_fields (spec_list_string)) - { - if (operating_mode == field_mode) - FATAL_ERROR (_("missing list of fields")); - else - FATAL_ERROR (_("missing list of positions")); - } + set_fields (spec_list_string, + ( (operating_mode == field_mode) ? 0 : SETFLD_ERRMSG_USE_POS) + | (complement ? SETFLD_COMPLEMENT : 0) ); if (!delim_specified) delim = '\t'; @@ -826,5 +591,7 @@ main (int argc, char **argv) ok = false; } + IF_LINT (reset_fields ()); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/local.mk b/src/local.mk index d0ceae4bd..5fb4d3733 100644 --- a/src/local.mk +++ b/src/local.mk @@ -55,6 +55,7 @@ noinst_HEADERS = \ src/operand2sig.h \ src/prog-fprintf.h \ src/remove.h \ + src/set-fields.h \ src/system.h \ src/uname.h @@ -387,6 +388,8 @@ src_stat_SOURCES = src/stat.c src/find-mount-point.c src_uname_SOURCES = src/uname.c src/uname-uname.c src_arch_SOURCES = src/uname.c src/uname-arch.c +src_cut_SOURCES = src/cut.c src/set-fields.c + src_md5sum_CPPFLAGS = -DHASH_ALGO_MD5=1 $(AM_CPPFLAGS) src_sha1sum_SOURCES = src/md5sum.c src_sha1sum_CPPFLAGS = -DHASH_ALGO_SHA1=1 $(AM_CPPFLAGS) diff --git a/src/set-fields.c b/src/set-fields.c new file mode 100644 index 000000000..847c812a5 --- /dev/null +++ b/src/set-fields.c @@ -0,0 +1,322 @@ +/* set-fields.c -- common functions for parsing field list + Copyright (C) 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 <http://www.gnu.org/licenses/>. */ + +/* Extracted from cut.c by Assaf Gordon */ + +#include <config.h> + +#include "system.h" +#include "error.h" +#include "quote.h" +#include "xstrndup.h" +#include "set-fields.h" + +/* Array of `struct field_range_pair' holding all the finite ranges. */ +struct field_range_pair *frp; + +/* Number of finite ranges specified by the user. */ +size_t n_frp; + +/* Number of `struct field_range_pair's allocated. */ +static size_t n_frp_allocated; + +#define FATAL_ERROR(Message) \ + do \ + { \ + error (0, 0, (Message)); \ + usage (EXIT_FAILURE); \ + } \ + while (0) + +/* Append LOW, HIGH to the list RP of range pairs, allocating additional + space if necessary. Update global variable N_FRP. When allocating, + update global variable N_FRP_ALLOCATED. */ +static void +add_range_pair (size_t lo, size_t hi) +{ + if (n_frp == n_frp_allocated) + frp = X2NREALLOC (frp, &n_frp_allocated); + frp[n_frp].lo = lo; + frp[n_frp].hi = hi; + ++n_frp; +} + + +/* Comparison function for qsort to order the list of + struct range_pairs. */ +static int +compare_ranges (const void *a, const void *b) +{ + int a_start = ((const struct field_range_pair *) a)->lo; + int b_start = ((const struct field_range_pair *) b)->lo; + return a_start < b_start ? -1 : a_start > b_start; +} + +/* Reallocate Range Pair entries, with corresponding + entries outside the range of each specified entry. */ + +static void +complement_rp (void) +{ + struct field_range_pair *c = frp; + size_t n = n_frp; + size_t i; + + frp = NULL; + n_frp = 0; + n_frp_allocated = 0; + + if (c[0].lo > 1) + add_range_pair (1, c[0].lo - 1); + + for (i = 1; i < n; ++i) + { + if (c[i-1].hi + 1 == c[i].lo) + continue; + + add_range_pair (c[i-1].hi + 1, c[i].lo - 1); + } + + if (c[n-1].hi < SIZE_MAX) + add_range_pair (c[n-1].hi + 1, SIZE_MAX); + + free (c); +} + +/* Given the list of field or byte range specifications FIELDSTR, + allocate and initialize the FRP array. FIELDSTR should + be composed of one or more numbers or ranges of numbers, separated + by blanks or commas. Incomplete ranges may be given: '-m' means '1-m'; + 'n-' means 'n' through end of line. + n=0 and n>=SIZE_MAX values will trigger an error. + + if SETFLD_ALLOW_DASH option is used, a single '-' means all fields + (otherwise a single dash triggers an error). + + if SETFLD_COMPLEMENT option is used, the specified field list + is complemented (e.g. '1-3' will result in fields '4-'). + + if SETFLD_ERRMSG_USE_POS option is used, error messages + will say 'position' (or 'byte/character positions') + instead of fields (used with cut -b/-c). + + The function terminates on failure. + + Upon return, the FRP array is initialized to contain + a non-overlapping, increasing list of field ranges. + + N_FRP holds the number of field ranges in the FRP array. + + The first field is stored as 1 (zero is not used). + An open-ended range (i.e., until the last field of the input line) + is indicated with hi = SIZE_MAX. + + A sentinel of SIZE_MAX/SIZE_MAX is always added as the last + field range pair. + + Examples: + given '1-2,4', frp = [ { .lo = 1, .hi = 2 }, + { .lo = 4, .hi = 4 }, + { .lo = SIZE_MAX, .hi = SIZE_MAX } ]; + + given '3-', frp = [ { .lo = 3, .hi = SIZE_MAX }, + { .lo = SIZE_MAX, .hi = SIZE_MAX } ]; +*/ +void +set_fields (const char *fieldstr, unsigned int options) +{ + size_t initial = 1; /* Value of first number in a range. */ + size_t value = 0; /* If nonzero, a number being accumulated. */ + bool lhs_specified = false; + bool rhs_specified = false; + bool dash_found = false; /* True if a '-' is found in this field. */ + + size_t i; + bool in_digits = false; + + /* Collect and store in RP the range end points. */ + + /* Special case: '--field=-' means all fields, emulate '--field=1-' . */ + if ((options & SETFLD_ALLOW_DASH) && STREQ (fieldstr,"-")) + { + value = 1; + lhs_specified = true; + dash_found = true; + fieldstr++; + } + + while (true) + { + if (*fieldstr == '-') + { + in_digits = false; + /* Starting a range. */ + if (dash_found) + FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS) + ?_("invalid byte or character range") + :_("invalid field range")); + + dash_found = true; + fieldstr++; + + if (lhs_specified && !value) + FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS) + ?_("byte/character positions are numbered from 1") + :_("fields are numbered from 1")); + + initial = (lhs_specified ? value : 1); + value = 0; + } + else if (*fieldstr == ',' + || isblank (to_uchar (*fieldstr)) || *fieldstr == '\0') + { + in_digits = false; + /* Ending the string, or this field/byte sublist. */ + if (dash_found) + { + dash_found = false; + + if (!lhs_specified && !rhs_specified) + { + /* if a lone dash is allowed, emulate '1-' for all fields */ + if (options & SETFLD_ALLOW_DASH) + initial = 1; + else + FATAL_ERROR (_("invalid range with no endpoint: -")); + } + + /* A range. Possibilities: -n, m-n, n-. + In any case, 'initial' contains the start of the range. */ + if (!rhs_specified) + { + /* 'n-'. From 'initial' to end of line. */ + add_range_pair (initial, SIZE_MAX); + } + else + { + /* 'm-n' or '-n' (1-n). */ + if (value < initial) + FATAL_ERROR (_("invalid decreasing range")); + + add_range_pair (initial, value); + } + value = 0; + } + else + { + /* A simple field number, not a range. */ + if (value == 0) + FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS) + ?_("byte/character positions are numbered from 1") + :_("fields are numbered from 1")); + + add_range_pair (value, value); + value = 0; + } + + if (*fieldstr == '\0') + break; + + fieldstr++; + lhs_specified = false; + rhs_specified = false; + } + else if (ISDIGIT (*fieldstr)) + { + /* Record beginning of digit string, in case we have to + complain about it. */ + static char const *num_start; + if (!in_digits || !num_start) + num_start = fieldstr; + in_digits = true; + + if (dash_found) + rhs_specified = 1; + else + lhs_specified = 1; + + /* Detect overflow. */ + if (!DECIMAL_DIGIT_ACCUMULATE (value, *fieldstr - '0', size_t) + || value == SIZE_MAX) + { + /* In case the user specified -c$(echo 2^64|bc),22, + complain only about the first number. */ + /* Determine the length of the offending number. */ + size_t len = strspn (num_start, "0123456789"); + char *bad_num = xstrndup (num_start, len); + error (0, 0, (options & SETFLD_ERRMSG_USE_POS) + ?_("byte/character offset %s is too large") + :_("field number %s is too large"), + quote (bad_num)); + free (bad_num); + usage (EXIT_FAILURE); + } + + fieldstr++; + } + else + { + error (0, 0, (options & SETFLD_ERRMSG_USE_POS) + ?_("invalid byte/character position %s") + :_("invalid field value %s"), + quote (fieldstr)); + usage (EXIT_FAILURE); + } + } + + if (!n_frp) + FATAL_ERROR ( (options&SETFLD_ERRMSG_USE_POS) + ?_("missing list of byte/character positions") + :_("missing list of fields")); + + qsort (frp, n_frp, sizeof (frp[0]), compare_ranges); + + /* Merge range pairs (e.g. `2-5,3-4' becomes `2-5'). */ + for (i = 0; i < n_frp; ++i) + { + for (size_t j = i + 1; j < n_frp; ++j) + { + if (frp[j].lo <= frp[i].hi) + { + frp[i].hi = MAX (frp[j].hi, frp[i].hi); + memmove (frp + j, frp + j + 1, (n_frp - j - 1) * sizeof *frp); + n_frp--; + j--; + } + else + break; + } + } + + if (options & SETFLD_COMPLEMENT) + complement_rp (); + + /* After merging, reallocate RP so we release memory to the system. + Also add a sentinel at the end of RP, to avoid out of bounds access + and for performance reasons. */ + ++n_frp; + frp = xrealloc (frp, n_frp * sizeof (struct field_range_pair)); + frp[n_frp - 1].lo = frp[n_frp - 1].hi = SIZE_MAX; +} + +void +reset_fields (void) +{ + n_frp = 0 ; + n_frp_allocated = 0; + free (frp); + frp = NULL; +} diff --git a/src/set-fields.h b/src/set-fields.h new file mode 100644 index 000000000..2c55c2984 --- /dev/null +++ b/src/set-fields.h @@ -0,0 +1,49 @@ +/* set-fields.h -- parse field list argument + + Copyright (C) 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 <http://www.gnu.org/licenses/>. */ +#ifndef SET_FIELDS_H +# define SET_FIELDS_H + +struct field_range_pair + { + size_t lo; + size_t hi; + }; + +/* Array of `struct range_pair' holding all the finite ranges. */ +extern struct field_range_pair *frp; + +/* Number of finite ranges specified by the user. */ +extern size_t n_frp; + +/* field list parsing options */ +enum +{ + SETFLD_ALLOW_DASH = 0x01, /* allow single dash meaning 'all fields' */ + SETFLD_COMPLEMENT = 0x02, /* complement the field list */ + SETFLD_ERRMSG_USE_POS = 0x04 /* when reporting errors, say 'position' instead + of 'field' (used with cut -b/-c) */ +}; + +/* allocates and initializes the FRP array and N_FRP count */ +void +set_fields (const char *fieldstr, unsigned int options); + +/* frees memory allocated by set_fields() */ +void +reset_fields (void); + +#endif diff --git a/tests/misc/cut.pl b/tests/misc/cut.pl index 23e9ce36f..a6239d629 100755 --- a/tests/misc/cut.pl +++ b/tests/misc/cut.pl @@ -29,8 +29,10 @@ my $mb_locale = $ENV{LOCALE_FR_UTF8}; my $prog = 'cut'; my $try = "Try '$prog --help' for more information.\n"; -my $from_1 = "$prog: fields and positions are numbered from 1\n$try"; -my $inval = "$prog: invalid byte, character or field list\n$try"; +my $from_field1 = "$prog: fields are numbered from 1\n$try"; +my $from_pos1 = "$prog: byte/character positions are numbered from 1\n$try"; +my $inval_fld = "$prog: invalid field range\n$try"; +my $inval_pos = "$prog: invalid byte or character range\n$try"; my $no_endpoint = "$prog: invalid range with no endpoint: -\n$try"; my $nofield = "$prog: an input delimiter may be specified only when " . "operating on fields\n$try"; @@ -42,16 +44,16 @@ my @Tests = # This failed (as it should) even before coreutils-6.9.90, # but cut from 6.9.90 produces a more useful diagnostic. - ['zero-1', '-b0', {ERR=>$from_1}, {EXIT => 1} ], + ['zero-1', '-b0', {ERR=>$from_pos1}, {EXIT => 1} ], # Up to coreutils-6.9, specifying a range of 0-2 was not an error. # It was treated just like "-2". - ['zero-2', '-f0-2', {ERR=>$from_1}, {EXIT => 1} ], + ['zero-2', '-f0-2', {ERR=>$from_field1}, {EXIT => 1} ], # Up to coreutils-8.20, specifying a range of 0- was not an error. - ['zero-3b', '-b0-', {ERR=>$from_1}, {EXIT => 1} ], - ['zero-3c', '-c0-', {ERR=>$from_1}, {EXIT => 1} ], - ['zero-3f', '-f0-', {ERR=>$from_1}, {EXIT => 1} ], + ['zero-3b', '-b0-', {ERR=>$from_pos1}, {EXIT => 1} ], + ['zero-3c', '-c0-', {ERR=>$from_pos1}, {EXIT => 1} ], + ['zero-3f', '-f0-', {ERR=>$from_field1}, {EXIT => 1} ], ['1', '-d:', '-f1,3-', {IN=>"a:b:c\n"}, {OUT=>"a:c\n"}], ['2', '-d:', '-f1,3-', {IN=>"a:b:c\n"}, {OUT=>"a:c\n"}], @@ -101,13 +103,16 @@ my @Tests = {ERR=>"$prog: you must specify a list of bytes, characters, or fields\n$try"} ], # Empty field list - ['empty-fl', qw(-f ''), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, {ERR=>$from_1}], + ['empty-fl', qw(-f ''), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, + {ERR=>$from_field1}], # Missing field list - ['missing-fl', qw(-f --), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, {ERR=>$inval}], + ['missing-fl', qw(-f --), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, + {ERR=>$inval_fld}], # Empty byte list - ['empty-bl', qw(-b ''), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, {ERR=>$from_1}], + ['empty-bl', qw(-b ''), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, {ERR=>$from_pos1}], # Missing byte list - ['missing-bl', qw(-b --), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, {ERR=>$inval}], + ['missing-bl', qw(-b --), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, + {ERR=>$inval_pos}], # This test fails with cut from textutils-1.22. ['empty-f1', '-f1', {IN=>""}, {OUT=>""}], |