From e1ff4ee0f6d7490610ecc39d57c855818f6fd1f4 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 5 Jan 2023 11:42:51 -0800 Subject: [PATCH 3/3] numfmt: add support for new SI prefixes * src/dd, src/head.c, src/od.c, src/sort.c, src/stdbuf.c, src/tail.c: (usage): * src/system.h (emit_size_note): Mention new SI prefixes. * src/du.c (main): * src/head.c (head_file): * src/numfmt.c (suffix_power, suffix_power_char, prepare_padded_number): * src/shred.c (main): * src/sort.c (unit_order): * src/tail.c (parse_options): Support new SI prefixes. * src/numfmt.c (MAX_ACCEPTABLE_DIGITS): Increase to 33. (zero_and_valid_suffixes, valid_suffixes): New constants, with new SI prefixes. (valid_suffix, unit_to_umax): Use them. (prepare_padded_number): Diagnose "999Q" instead of "999Y". * tests/misc/numfmt.pl, tests/misc/sort.pl: Adjust tests to match new max. --- NEWS | 6 ++++ doc/coreutils.texi | 41 ++++++++++++++++++------ src/dd.c | 2 +- src/du.c | 2 +- src/head.c | 4 +-- src/numfmt.c | 38 +++++++++++++++------- src/od.c | 2 +- src/shred.c | 2 +- src/sort.c | 14 ++++---- src/stdbuf.c | 2 +- src/system.h | 2 +- src/tail.c | 4 +-- tests/misc/numfmt.pl | 76 ++++++++++++++++++++++++-------------------- tests/misc/sort.pl | 8 ++--- 14 files changed, 126 insertions(+), 77 deletions(-) diff --git a/NEWS b/NEWS index 04ee933c0..52c92ddb4 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,12 @@ GNU coreutils NEWS -*- outline -*- ** Changes in behavior + Programs now use the new SI prefixes R (10**27) and Q (10**30) + along with their binary counterparts Ri (2**90) and Qi (2**100). + In some cases (e.g., 'sort -h') these new prefixes simply work; + in others, where they exceed integer width limits, they now elicit + the same integer overflow diagnostics as other large prefixes. + 'cp --reflink=always A B' no longer leaves behind a newly created empty file B merely because copy-on-write clones are not supported. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index bd9e00de4..4c278bf27 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -707,7 +707,8 @@ one of the following multiplicative suffixes: @samp{GB} => 1000*1000*1000 (GigaBytes) @samp{G} => 1024*1024*1024 (GibiBytes) @end example -and so on for @samp{T}, @samp{P}, @samp{E}, @samp{Z}, and @samp{Y}. +and so on for @samp{T}, @samp{P}, @samp{E}, @samp{Z}, @samp{Y}, +@samp{R}, and @samp{Q}. Binary prefixes can be used, too: @samp{KiB}=@samp{K}, @samp{MiB}=@samp{M}, and so on. @end macro @@ -724,7 +725,8 @@ one of the following multiplicative suffixes: @samp{GB} => 1000*1000*1000 (GigaBytes) @samp{G} => 1024*1024*1024 (GibiBytes) @end example -and so on for @samp{T}, @samp{P}, @samp{E}, @samp{Z}, and @samp{Y}. +and so on for @samp{T}, @samp{P}, @samp{E}, @samp{Z}, @samp{Y}, +@samp{R}, and @samp{Q}. Binary prefixes can be used, too: @samp{KiB}=@samp{K}, @samp{MiB}=@samp{M}, and so on. @end macro @@ -982,7 +984,7 @@ prepended, except that it causes a size indication to be appended to the output. For example, @samp{--block-size="kB"} displays 3000 as @samp{3kB}. -The following suffixes are defined. Large sizes like @code{1Y} +The following suffixes are defined. Large sizes like @code{1Q} may be rejected by your computer due to limitations of its arithmetic. @table @samp @@ -1036,13 +1038,25 @@ exbibyte: @math{2^{60} = 1,152,921,504,606,846,976}. zettabyte: @math{10^{21} = 1,000,000,000,000,000,000,000} @item Z @itemx ZiB -@math{2^{70} = 1,180,591,620,717,411,303,424}. +zebibyte: @math{2^{70} = 1,180,591,620,717,411,303,424}. @item YB @cindex yottabyte, definition of yottabyte: @math{10^{24} = 1,000,000,000,000,000,000,000,000}. @item Y @itemx YiB -@math{2^{80} = 1,208,925,819,614,629,174,706,176}. +yobibyte: @math{2^{80} = 1,208,925,819,614,629,174,706,176}. +@item RB +@cindex ronnabyte, definition of +ronnabyte: @math{10^{27} = 1,000,000,000,000,000,000,000,000,000}. +@item R +@itemx RiB +robibyte: @math{2^{90} = 1,237,940,039,285,380,274,899,124,224}. +@item QB +@cindex quettabyte, definition of +quettabyte: @math{10^{30} = 1,000,000,000,000,000,000,000,000,000,000}. +@item Q +@itemx QiB +quebibyte: @math{2^{100} = 1,267,650,600,228,229,401,496,703,205,376}. @end table @opindex -k @@ -4522,7 +4536,7 @@ lexicographic sort will be faster. @vindex LC_NUMERIC Sort numerically, first by numeric sign (negative, zero, or positive); then by SI suffix (either empty, or @samp{k} or @samp{K}, or -one of @samp{MGTPEZY}, in that order; @pxref{Block size}); and finally +one of @samp{MGTPEZYRQ}, in that order; @pxref{Block size}); and finally by numeric value. For example, @samp{1023M} sorts before @samp{1G} because @samp{M} (mega) precedes @samp{G} (giga) as an SI suffix. This option sorts values that are consistently scaled to the @@ -4759,7 +4773,8 @@ Use a main-memory sort buffer of the given @var{size}. By default, @var{size} to be interpreted as a percentage of physical memory. Appending @samp{K} multiplies @var{size} by 1024 (the default), @samp{M} by 1,048,576, @samp{G} by 1,073,741,824, and so on for -@samp{T}, @samp{P}, @samp{E}, @samp{Z}, and @samp{Y}@. Appending +@samp{T}, @samp{P}, @samp{E}, @samp{Z}, @samp{Y}, @samp{R}, and @samp{Q}@. +Appending @samp{b} causes @var{size} to be interpreted as a byte count, with no multiplication. @@ -18961,6 +18976,8 @@ one of the following suffixes: @samp{E} => @math{1000^6 = 10^{18}} (Exa) @samp{Z} => @math{1000^7 = 10^{21}} (Zetta) @samp{Y} => @math{1000^8 = 10^{24}} (Yotta) +@samp{R} => @math{1000^9 = 10^{27}} (Ronna) +@samp{Q} => @math{1000^{10} = 10^{30}} (Quetta) @end example @item iec @@ -18979,6 +18996,8 @@ one of the following suffixes: @samp{E} => @math{1024^6 = 2^{60}} (Exbi) @samp{Z} => @math{1024^7 = 2^{70}} (Zebi) @samp{Y} => @math{1024^8 = 2^{80}} (Yobi) +@samp{R} => @math{1024^9 = 2^{90}} (Robi) +@samp{Q} => @math{1024^{10} = 2^{100}} (Quebi) @end example The @option{iec} option uses a single letter suffix (e.g. @samp{G}), which is @@ -19002,6 +19021,8 @@ one of the following suffixes: @samp{Ei} => @math{1024^6 = 2^{60}} (Exbi) @samp{Zi} => @math{1024^7 = 2^{70}} (Zebi) @samp{Yi} => @math{1024^8 = 2^{80}} (Yobi) +@samp{Ri} => @math{1024^9 = 2^{90}} (Robi) +@samp{Qi} => @math{1024^{10} = 2^{100}} (Quebi) @end example The @option{iec-i} option uses a two-letter suffix symbol (e.g. @samp{Gi}), @@ -19010,9 +19031,9 @@ practice. Compare with the @option{iec} option. @item auto @samp{auto} can only be used with @option{--from}. With this method, numbers -with @samp{K},@samp{M},@samp{G},@samp{T},@samp{P},@samp{E},@samp{Z},@samp{Y} -suffixes are interpreted as @emph{SI} values, and numbers with @samp{Ki}, -@samp{Mi},@samp{Gi},@samp{Ti},@samp{Pi},@samp{Ei},@samp{Zi},@samp{Yi} suffixes +with single-letter suffixes like @samp{K} +suffixes are interpreted as @emph{SI} values, and numbers with +two-letter suffixes like @samp{Ki} are interpreted as @emph{IEC} values. @end table diff --git a/src/dd.c b/src/dd.c index 190a721b3..6d448a57b 100644 --- a/src/dd.c +++ b/src/dd.c @@ -573,7 +573,7 @@ Copy a file, converting and formatting according to the operands.\n\ \n\ N and BYTES may be followed by the following multiplicative suffixes:\n\ c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024, xM=M,\n\ -GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y.\n\ +GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y, R, Q.\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ If N ends in 'B', it counts bytes not blocks.\n\ \n\ diff --git a/src/du.c b/src/du.c index 71d6edd3d..8bffc1aa7 100644 --- a/src/du.c +++ b/src/du.c @@ -840,7 +840,7 @@ main (int argc, char **argv) case 't': { enum strtol_error e; - e = xstrtoimax (optarg, NULL, 0, &opt_threshold, "kKmMGTPEZY0"); + e = xstrtoimax (optarg, NULL, 0, &opt_threshold, "kKmMGTPEZYRQ0"); if (e != LONGINT_OK) xstrtol_fatal (e, oi, c, long_options, optarg); if (opt_threshold == 0 && *optarg == '-') diff --git a/src/head.c b/src/head.c index 63674d769..c9d3b0d05 100644 --- a/src/head.c +++ b/src/head.c @@ -140,7 +140,7 @@ With more than one FILE, precede each with a header giving the file name.\n\ \n\ NUM may have a multiplier suffix:\n\ b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\ -GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\ +GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y, R, Q.\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ "), stdout); emit_ancillary_info (PROGRAM_NAME); @@ -910,7 +910,7 @@ head_file (char const *filename, uintmax_t n_units, bool count_lines, static uintmax_t string_to_integer (bool count_lines, char const *n_string) { - return xdectoumax (n_string, 0, UINTMAX_MAX, "bkKmMGTPEZY0", + return xdectoumax (n_string, 0, UINTMAX_MAX, "bkKmMGTPEZYRQ0", count_lines ? _("invalid number of lines") : _("invalid number of bytes"), 0); } diff --git a/src/numfmt.c b/src/numfmt.c index e917b0dc6..2067ca164 100644 --- a/src/numfmt.c +++ b/src/numfmt.c @@ -161,10 +161,10 @@ enum { DELIMITER_DEFAULT = CHAR_MAX + 1 }; enum { MAX_UNSCALED_DIGITS = LDBL_DIG }; /* Maximum number of digits we can work with. - This is equivalent to 999Y. + This is equivalent to 999Q. NOTE: 'long double' can handle more than that, but there's - no official suffix assigned beyond Yotta (1000^8). */ -enum { MAX_ACCEPTABLE_DIGITS = 27 }; + no official suffix assigned beyond Quetta (1000^10). */ +enum { MAX_ACCEPTABLE_DIGITS = 33 }; static enum scale_type scale_from = scale_none; static enum scale_type scale_to = scale_none; @@ -229,11 +229,13 @@ default_scale_base (enum scale_type scale) } } -static inline int +static char const zero_and_valid_suffixes[] = "0KMGTPEZYRQ"; +static char const *valid_suffixes = 1 + zero_and_valid_suffixes; + +static inline bool valid_suffix (const char suf) { - static char const *valid_suffixes = "KMGTPEZY"; - return (strchr (valid_suffixes, suf) != NULL); + return strchr (valid_suffixes, suf) != NULL; } static inline int @@ -265,6 +267,12 @@ suffix_power (const char suf) case 'Y': /* yotta or 2**80. */ return 8; + case 'R': /* ronna or 2**90. */ + return 9; + + case 'Q': /* quetta or 2**100. */ + return 10; + default: /* should never happen. assert? */ return 0; } @@ -302,6 +310,12 @@ suffix_power_char (unsigned int power) case 8: return "Y"; + case 9: + return "R"; + + case 10: + return "Q"; + default: return "(error)"; } @@ -460,7 +474,7 @@ enum simple_strtod_error Returns: SSE_OK - valid number. SSE_OK_PRECISION_LOSS - if more than 18 digits were used. - SSE_OVERFLOW - if more than 27 digits (999Y) were used. + SSE_OVERFLOW - if more than 33 digits (999Q) were used. SSE_INVALID_NUMBER - if no digits were found. */ static enum simple_strtod_error simple_strtod_int (char const *input_str, @@ -525,7 +539,7 @@ simple_strtod_int (char const *input_str, Returns: SSE_OK - valid number. SSE_OK_PRECISION_LOSS - if more than 18 digits were used. - SSE_OVERFLOW - if more than 27 digits (999Y) were used. + SSE_OVERFLOW - if more than 33 digits (999Q) were used. SSE_INVALID_NUMBER - if no digits were found. */ static enum simple_strtod_error simple_strtod_float (char const *input_str, @@ -598,7 +612,7 @@ simple_strtod_float (char const *input_str, Returns: SSE_OK - valid number. SSE_OK_PRECISION_LOSS - if more than LDBL_DIG digits were used. - SSE_OVERFLOW - if more than 27 digits (999Y) were used. + SSE_OVERFLOW - if more than 33 digits (999Q) were used. SSE_INVALID_NUMBER - if no digits were found. SSE_VALID_BUT_FORBIDDEN_SUFFIX SSE_INVALID_SUFFIX @@ -830,7 +844,7 @@ unit_to_umax (char const *n_string) size_t n_len = strlen (n_string); char *end = NULL; uintmax_t n; - char const *suffixes = "KMGTPEZY"; + char const *suffixes = valid_suffixes; /* Adjust suffixes so K=1000, Ki=1024, KiB=invalid. */ if (n_len && ! c_isdigit (n_string[n_len - 1])) @@ -845,7 +859,7 @@ unit_to_umax (char const *n_string) { *++end = 'B'; *++end = '\0'; - suffixes = "KMGTPEZY0"; + suffixes = zero_and_valid_suffixes; } c_string = t_string; @@ -1224,7 +1238,7 @@ prepare_padded_number (const long double val, size_t precision) { if (inval_style != inval_ignore) error (conv_exit_code, 0, _("value too large to be printed: '%Lg'" - " (cannot handle values > 999Y)"), val); + " (cannot handle values > 999Q)"), val); return 0; } diff --git a/src/od.c b/src/od.c index e3f21b3cb..9e9142760 100644 --- a/src/od.c +++ b/src/od.c @@ -419,7 +419,7 @@ BYTES is hex with 0x or 0X prefix, and may have a multiplier suffix:\n\ K 1024\n\ MB 1000*1000\n\ M 1024*1024\n\ -and so on for G, T, P, E, Z, Y.\n\ +and so on for G, T, P, E, Z, Y, R, Q.\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ "), stdout); emit_ancillary_info (PROGRAM_NAME); diff --git a/src/shred.c b/src/shred.c index b4f885cd4..3ec8fe1f0 100644 --- a/src/shred.c +++ b/src/shred.c @@ -1216,7 +1216,7 @@ main (int argc, char **argv) break; case 's': - flags.size = xnumtoumax (optarg, 0, 0, OFF_T_MAX, "cbBkKMGTPEZY0", + flags.size = xnumtoumax (optarg, 0, 0, OFF_T_MAX, "cbBkKMGTPEZYRQ0", _("invalid file size"), 0); break; diff --git a/src/sort.c b/src/sort.c index a99f01072..5f159374b 100644 --- a/src/sort.c +++ b/src/sort.c @@ -519,7 +519,7 @@ the entire line as the key. Use --debug to diagnose incorrect key usage.\n\ SIZE may be followed by the following multiplicative suffixes:\n\ "), stdout); fputs (_("\ -% 1% of memory, b 1, K 1024 (default), and so on for M, G, T, P, E, Z, Y.\n\ +% 1% of memory, b 1, K 1024 (default), and so on for M, G, T, P, E, Z, Y, R, Q.\n\ \n\ *** WARNING ***\n\ The locale specified by the environment affects sort order.\n\ @@ -1877,28 +1877,30 @@ fillbuf (struct buffer *buf, FILE *fp, char const *file) static char const unit_order[UCHAR_LIM] = { #if ! ('K' == 75 && 'M' == 77 && 'G' == 71 && 'T' == 84 && 'P' == 80 \ - && 'E' == 69 && 'Z' == 90 && 'Y' == 89 && 'k' == 107) + && 'E' == 69 && 'Z' == 90 && 'Y' == 89 && 'R' == 82 && 'Q' == 81 \ + && 'k' == 107) /* This initializer syntax works on all C99 hosts. For now, use it only on non-ASCII hosts, to ease the pain of porting to pre-C99 ASCII hosts. */ ['K']=1, ['M']=2, ['G']=3, ['T']=4, ['P']=5, ['E']=6, ['Z']=7, ['Y']=8, + ['R']=9, ['Q']=10, ['k']=1, #else /* Generate the following table with this command: - perl -e 'my %a=(k=>1, K=>1, M=>2, G=>3, T=>4, P=>5, E=>6, Z=>7, Y=>8); + perl -e 'my %a=(k=>1,K=>1,M=>2,G=>3,T=>4,P=>5,E=>6,Z=>7,Y=>8,R=>9,Q=>10); foreach my $i (0..255) {my $c=chr($i); $a{$c} ||= 0;print "$a{$c}, "}'\ |fmt */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, - 0, 0, 0, 1, 0, 2, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 2, 0, 0, 5, 10, 9, 0, 4, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif }; @@ -1972,7 +1974,7 @@ find_unit_order (char const *number) } /* Compare numbers A and B ending in units with SI or IEC prefixes - < K/k < M < G < T < P < E < Z < Y */ + < K/k < M < G < T < P < E < Z < Y < R < Q */ ATTRIBUTE_PURE static int diff --git a/src/stdbuf.c b/src/stdbuf.c index f3eb9b016..2d7aec28c 100644 --- a/src/stdbuf.c +++ b/src/stdbuf.c @@ -110,7 +110,7 @@ If MODE is '0' the corresponding stream will be unbuffered.\n\ "), stdout); fputs (_("\n\ Otherwise MODE is a number which may be followed by one of the following:\n\ -KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\ +KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G,T,P,E,Z,Y,R,Q.\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ In this case the corresponding stream will be fully buffered with the buffer\n\ size set to MODE bytes.\n\ diff --git a/src/system.h b/src/system.h index 52ed378d1..2aa5d6978 100644 --- a/src/system.h +++ b/src/system.h @@ -593,7 +593,7 @@ emit_size_note (void) { fputs (_("\n\ The SIZE argument is an integer and optional unit (example: 10K is 10*1024).\n\ -Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).\n\ +Units are K,M,G,T,P,E,Z,Y,R,Q (powers of 1024) or KB,MB,... (powers of 1000).\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ "), stdout); } diff --git a/src/tail.c b/src/tail.c index 35bc55130..2244509dd 100644 --- a/src/tail.c +++ b/src/tail.c @@ -319,7 +319,7 @@ With more than one FILE, precede each with a header giving the file name.\n\ \n\ NUM may have a multiplier suffix:\n\ b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\ -GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\ +GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y, R, Q.\n\ Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ \n\ "), stdout); @@ -2194,7 +2194,7 @@ parse_options (int argc, char **argv, else if (*optarg == '-') ++optarg; - *n_units = xdectoumax (optarg, 0, UINTMAX_MAX, "bkKmMGTPEZY0", + *n_units = xdectoumax (optarg, 0, UINTMAX_MAX, "bkKmMGTPEZYRQ0", count_lines ? _("invalid number of lines") : _("invalid number of bytes"), 0); diff --git a/tests/misc/numfmt.pl b/tests/misc/numfmt.pl index 06df09a44..31a87dc14 100755 --- a/tests/misc/numfmt.pl +++ b/tests/misc/numfmt.pl @@ -116,29 +116,29 @@ my @Tests = # Test Suffix logic ['suf-1', '4000', {OUT=>'4000'}], - ['suf-2', '4Q', - {ERR => "$prog: invalid suffix in input: '4Q'\n"}, + ['suf-2', '4J', + {ERR => "$prog: invalid suffix in input: '4J'\n"}, {EXIT => '2'}], ['suf-2.1', '4M', {ERR => "$prog: rejecting suffix " . "in input: '4M' (consider using --from)\n"}, {EXIT => '2'}], ['suf-3', '--from=si 4M', {OUT=>'4000000'}], - ['suf-4', '--from=si 4Q', - {ERR => "$prog: invalid suffix in input: '4Q'\n"}, + ['suf-4', '--from=si 4J', + {ERR => "$prog: invalid suffix in input: '4J'\n"}, {EXIT => '2'}], - ['suf-5', '--from=si 4MQ', - {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"}, + ['suf-5', '--from=si 4MJ', + {ERR => "$prog: invalid suffix in input '4MJ': 'J'\n"}, {EXIT => '2'}], ['suf-6', '--from=iec 4M', {OUT=>'4194304'}], ['suf-7', '--from=auto 4M', {OUT=>'4000000'}], ['suf-8', '--from=auto 4Mi', {OUT=>'4194304'}], - ['suf-9', '--from=auto 4MiQ', - {ERR => "$prog: invalid suffix in input '4MiQ': 'Q'\n"}, + ['suf-9', '--from=auto 4MiJ', + {ERR => "$prog: invalid suffix in input '4MiJ': 'J'\n"}, {EXIT => '2'}], - ['suf-10', '--from=auto 4QiQ', - {ERR => "$prog: invalid suffix in input: '4QiQ'\n"}, + ['suf-10', '--from=auto 4JiJ', + {ERR => "$prog: invalid suffix in input: '4JiJ'\n"}, {EXIT => '2'}], # characters after a white space are OK - printed as-is @@ -443,8 +443,8 @@ my @Tests = {EXIT=>2}], # INVALID_SUFFIX - ['strtod-9', '--from=si 12.2Q', - {ERR=>"$prog: invalid suffix in input: '12.2Q'\n"}, + ['strtod-9', '--from=si 12.2J', + {ERR=>"$prog: invalid suffix in input: '12.2J'\n"}, {EXIT=>2}], # VALID_BUT_FORBIDDEN_SUFFIX @@ -731,18 +731,18 @@ my @Tests = ## Check all errors again, this time with --invalid=fail ## Input will be printed without conversion, ## and exit code will be 2 - ['ign-err-1', '--invalid=fail 4Q', - {ERR => "$prog: invalid suffix in input: '4Q'\n"}, - {OUT => "4Q\n"}, + ['ign-err-1', '--invalid=fail 4J', + {ERR => "$prog: invalid suffix in input: '4J'\n"}, + {OUT => "4J\n"}, {EXIT => 2}], ['ign-err-2', '--invalid=fail 4M', {ERR => "$prog: rejecting suffix " . "in input: '4M' (consider using --from)\n"}, {OUT => "4M\n"}, {EXIT => 2}], - ['ign-err-3', '--invalid=fail --from=si 4MQ', - {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"}, - {OUT => "4MQ\n"}, + ['ign-err-3', '--invalid=fail --from=si 4MJ', + {ERR => "$prog: invalid suffix in input '4MJ': 'J'\n"}, + {OUT => "4MJ\n"}, {EXIT => 2}], ['ign-err-4', '--invalid=fail --suffix=Foo --to=si 7000FooF', {ERR => "$prog: invalid suffix in input: '7000FooF'\n"}, @@ -851,7 +851,7 @@ my @Limit_Tests = # Test input: - # Up to 27 digits is OK. + # Up to 33 digits is OK. ['large-3.1', '--to=si 1', {OUT=> "1"}], ['large-3.2', '--to=si 10', {OUT=> "10"}], ['large-3.3', '--to=si 100', {OUT=> "100"}], @@ -879,11 +879,17 @@ my @Limit_Tests = ['large-3.25','--to=si 6543210000000000000000000', {OUT=>"6.6Y"}], ['large-3.26','--to=si 76543210000000000000000000', {OUT=> "77Y"}], ['large-3.27','--to=si 876543210000000000000000000', {OUT=>"877Y"}], - - # More than 27 digits is not OK - ['large-3.28','--to=si 9876543210000000000000000000', + ['large-3.28','--to=si 9876543210000000000000000000', {OUT=>"9.9R"}], + ['large-3.29','--to=si 19876543210000000000000000000', {OUT=> "20R"}], + ['large-3.30','--to=si 219876543210000000000000000000', {OUT=>"220R"}], + ['large-3.31','--to=si 3219876543210000000000000000000', {OUT=>"3.3Q"}], + ['large-3.32','--to=si 43219876543210000000000000000000', {OUT=> "44Q"}], + ['large-3.33','--to=si 543219876543210000000000000000000', {OUT=>"544Q"}], + + # More than 33 digits is not OK + ['large-3.34','--to=si 6543219876543210000000000000000000', {ERR => "$prog: value too large to be converted: " . - "'9876543210000000000000000000'\n"}, + "'6543219876543210000000000000000000'\n"}, {EXIT => 2}], # Test Output @@ -952,15 +958,15 @@ my @Limit_Tests = {EXIT => 2}], ['large-13.1','--from=si --from-unit=1000000 --to=si 9P', {OUT=>"9.0Z"}], - # Numbers>999Y are never acceptable, regardless of scaling - ['large-14','--from=si --to=si 999Y', {OUT=>"999Y"}], - ['large-14.1','--from=si --to=si 1000Y', - {ERR => "$prog: value too large to be printed: '1e+27' " . - "(cannot handle values > 999Y)\n"}, + # Numbers>999Q are never acceptable, regardless of scaling + ['large-14','--from=si --to=si 999Q', {OUT=>"999Q"}], + ['large-14.1','--from=si --to=si 1000Q', + {ERR => "$prog: value too large to be printed: '1e+33' " . + "(cannot handle values > 999Q)\n"}, {EXIT => 2}], - ['large-14.2','--from=si --to=si --from-unit=10000 1Y', - {ERR => "$prog: value too large to be printed: '1e+28' " . - "(cannot handle values > 999Y)\n"}, + ['large-14.2','--from=si --to=si --from-unit=10000 1Q', + {ERR => "$prog: value too large to be printed: '1e+34' " . + "(cannot handle values > 999Q)\n"}, {EXIT => 2}], # intmax_t overflow when rounding caused this to fail before 8.24 @@ -999,10 +1005,10 @@ my @Limit_Tests = "(consider using --to)\n"}, {OUT => "10000000000000000000\n"}, {EXIT=>2}], - ['ign-err-11','--invalid=fail --to=si 9876543210000000000000000000', + ['ign-err-11','--invalid=fail --to=si 6543219876543210000000000000000000', {ERR => "$prog: value too large to be converted: " . - "'9876543210000000000000000000'\n"}, - {OUT => "9876543210000000000000000000\n"}, + "'6543219876543210000000000000000000'\n"}, + {OUT => "6543219876543210000000000000000000\n"}, {EXIT => 2}], ); # Restrict these tests to systems with LDBL_DIG == 18 @@ -1067,7 +1073,7 @@ push @Tests, @Locale_Tests if $locale ne 'C'; ## Check all valid/invalid suffixes foreach my $suf ( 'A' .. 'Z', 'a' .. 'z' ) { - if ( $suf =~ /^[KMGTPEZY]$/ ) + if ( $suf =~ /^[KMGTPEZYRQ]$/ ) { push @Tests, ["auto-suf-si-$suf","--from=si --to=si 1$suf", {OUT=>"1.0$suf"}]; diff --git a/tests/misc/sort.pl b/tests/misc/sort.pl index 0cd2340a2..46f1d7acd 100755 --- a/tests/misc/sort.pl +++ b/tests/misc/sort.pl @@ -56,10 +56,10 @@ my @Tests = # human readable suffixes ["h1", '-h', - {IN=>"1Y\n1Z\n1E\n1P\n1T\n1G\n1M\n1K\n02\n1\nY\n-1k\n-1M\n-1G\n-1T\n" - . "-1P\n-1E\n-1Z\n-1Y\n"}, - {OUT=>"-1Y\n-1Z\n-1E\n-1P\n-1T\n-1G\n-1M\n-1k\nY\n1\n02\n1K\n1M\n1G\n1T\n" - . "1P\n1E\n1Z\n1Y\n"}], + {IN=>"1Q\n1R\n1Y\n1Z\n1E\n1P\n1T\n1G\n1M\n1K\n02\n1\nY\n-1k\n-1M\n-1G\n-1T\n" + . "-1P\n-1E\n-1Z\n-1Y\n-1Q\n-1R\n"}, + {OUT=>"-1Q\n-1R\n-1Y\n-1Z\n-1E\n-1P\n-1T\n-1G\n-1M\n-1k\n" + . "Y\n1\n02\n1K\n1M\n1G\n1T\n1P\n1E\n1Z\n1Y\n1R\n1Q\n"}], ["h2", '-h', {IN=>"1M\n-2G\n-3K"}, {OUT=>"-2G\n-3K\n1M\n"}], # check that it works with powers of 1024 ["h3", '-k 2,2h -k 1,1', {IN=>"a 1G\nb 1023M\n"}, {OUT=>"b 1023M\na 1G\n"}], -- 2.37.2