/* Reformat numbers like 11505426432 to the more human-readable 11G This is the numfmt utility
Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/>. */ The GNUv3 license
#include <config.h> Provides system specific information
#include <float.h> ...!includes auto-comment...
#include <getopt.h> ...!includes auto-comment...
#include <stdio.h> Provides standard I/O capability
#include <sys/types.h> Provides system data types
#include <langinfo.h> ...!includes auto-comment...
#include "mbsalign.h" ...!includes auto-comment...
#include "argmatch.h" ...!includes auto-comment...
#include "c-ctype.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "system.h" ...!includes auto-comment...
#include "xstrtol.h" ...!includes auto-comment...
#include "xstrndup.h" ...!includes auto-comment...
#include "set-fields.h" ...!includes auto-comment...
#if HAVE_FPSETPREC Line 36
# include <ieeefp.h> Line 37
#endif Line 38
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "numfmt" Line 41
#define AUTHORS proper_name ("Assaf Gordon") Line 43
/* Exit code when some numbers fail to convert. */
enum { EXIT_CONVERSION_WARNINGS = 2 }; Line 46
enum Line 48
{
FROM_OPTION = CHAR_MAX + 1, Line 50
FROM_UNIT_OPTION, Line 51
TO_OPTION, Line 52
TO_UNIT_OPTION, Line 53
ROUND_OPTION, Line 54
SUFFIX_OPTION, Line 55
GROUPING_OPTION, Line 56
PADDING_OPTION, Line 57
FIELD_OPTION, Line 58
DEBUG_OPTION, Line 59
DEV_DEBUG_OPTION, Line 60
HEADER_OPTION, Line 61
FORMAT_OPTION, Line 62
INVALID_OPTION Line 63
}; Block 2
enum scale_type Line 66
{
scale_none, /* the default: no scaling. */ Line 68
scale_auto, /* --from only. */ Line 69
scale_SI, Line 70
scale_IEC, Line 71
scale_IEC_I /* 'i' suffix is required. */ Line 72
}; Block 3
static char const *const scale_from_args[] = Line 75
{
"none", "auto", "si", "iec", "iec-i", NULL Line 77
}; Block 4
static enum scale_type const scale_from_types[] = Line 80
{
scale_none, scale_auto, scale_SI, scale_IEC, scale_IEC_I Line 82
}; Block 5
static char const *const scale_to_args[] = Line 85
{
"none", "si", "iec", "iec-i", NULL Line 87
}; Block 6
static enum scale_type const scale_to_types[] = Line 90
{
scale_none, scale_SI, scale_IEC, scale_IEC_I Line 92
}; Block 7
enum round_type Line 96
{
round_ceiling, Line 98
round_floor, Line 99
round_from_zero, Line 100
round_to_zero, Line 101
round_nearest, Line 102
}; Block 8
static char const *const round_args[] = Line 105
{
"up", "down", "from-zero", "towards-zero", "nearest", NULL Line 107
}; Block 9
static enum round_type const round_types[] = Line 110
{
round_ceiling, round_floor, round_from_zero, round_to_zero, round_nearest Line 112
}; Block 10
enum inval_type Line 116
{
inval_abort, ...!common auto-comment...
inval_fail, Line 119
inval_warn, Line 120
inval_ignore Line 121
};
static char const *const inval_args[] = Line 124
{
"abort", "fail", "warn", "ignore", NULL ...!common auto-comment...
};
static enum inval_type const inval_types[] = Line 129
{
inval_abort, inval_fail, inval_warn, inval_ignore ...!common auto-comment...
};
static struct option const longopts[] = Line 134
{
{"from", required_argument, NULL, FROM_OPTION}, Line 136
{"from-unit", required_argument, NULL, FROM_UNIT_OPTION}, Line 137
{"to", required_argument, NULL, TO_OPTION}, Line 138
{"to-unit", required_argument, NULL, TO_UNIT_OPTION}, Line 139
{"round", required_argument, NULL, ROUND_OPTION}, Line 140
{"padding", required_argument, NULL, PADDING_OPTION}, Line 141
{"suffix", required_argument, NULL, SUFFIX_OPTION}, Line 142
{"grouping", no_argument, NULL, GROUPING_OPTION}, Line 143
{"delimiter", required_argument, NULL, 'd'}, Line 144
{"field", required_argument, NULL, FIELD_OPTION}, Line 145
{"debug", no_argument, NULL, DEBUG_OPTION}, Line 146
{"-debug", no_argument, NULL, DEV_DEBUG_OPTION}, Line 147
{"header", optional_argument, NULL, HEADER_OPTION}, Line 148
{"format", required_argument, NULL, FORMAT_OPTION}, Line 149
{"invalid", required_argument, NULL, INVALID_OPTION}, Line 150
{"zero-terminated", no_argument, NULL, 'z'}, Line 151
{GETOPT_HELP_OPTION_DECL}, Line 152
{GETOPT_VERSION_OPTION_DECL}, Line 153
{NULL, 0, NULL, 0} Line 154
}; Block 14
/* If delimiter has this value, blanks separate fields. */
enum { DELIMITER_DEFAULT = CHAR_MAX + 1 }; Line 158
/* Maximum number of digits we can safely handle
without precision loss, if scaling is 'none'. */
enum { MAX_UNSCALED_DIGITS = LDBL_DIG }; Line 162
/* Maximum number of digits we can work with.
This is equivalent to 999Y.
NOTE: 'long double' can handle more than that, but there's
no official suffix assigned beyond Yotta (1000^8). */
enum { MAX_ACCEPTABLE_DIGITS = 27 }; Line 168
static enum scale_type scale_from = scale_none; Line 170
static enum scale_type scale_to = scale_none; Line 171
static enum round_type round_style = round_from_zero; Line 172
static enum inval_type inval_style = inval_abort; ...!common auto-comment...
static const char *suffix = NULL; Line 174
static uintmax_t from_unit_size = 1; Line 175
static uintmax_t to_unit_size = 1; Line 176
static int grouping = 0; Line 177
static char *padding_buffer = NULL; Line 178
static size_t padding_buffer_size = 0; Line 179
static long int padding_width = 0; Line 180
static long int zero_padding_width = 0; Line 181
static long int user_precision = -1; Line 182
static const char *format_str = NULL; Line 183
static char *format_str_prefix = NULL; Line 184
static char *format_str_suffix = NULL; Line 185
/* By default, any conversion error will terminate the program. */
static int conv_exit_code = EXIT_CONVERSION_WARNINGS; Line 188
/* auto-pad each line based on skipped whitespace. */
static int auto_padding = 0; Line 192
static mbs_align_t padding_alignment = MBS_ALIGN_RIGHT; Line 193
/* field delimiter */
static int delimiter = DELIMITER_DEFAULT; Line 196
/* line delimiter. */
static unsigned char line_delim = '\n'; Line 199
/* if non-zero, the first 'header' lines from STDIN are skipped. */
static uintmax_t header = 0; Line 202
/* Debug for users: print warnings to STDERR about possible
error (similar to sort's debug). */
static bool debug; Line 206
/* will be set according to the current locale. */
static const char *decimal_point; Line 209
static int decimal_point_length; Line 210
/* debugging for developers. Enables devmsg(). */
static bool dev_debug = false; Line 213
static inline int Line 216
default_scale_base (enum scale_type scale) Line 217
{
switch (scale) Line 219
{
case scale_IEC: Line 221
case scale_IEC_I: Line 222
return 1024; Line 223
case scale_none: Line 225
case scale_auto: Line 226
case scale_SI: Line 227
default: Line 228
return 1000; Line 229
}
} Block 18
static inline int Line 233
valid_suffix (const char suf) Line 234
{
static const char *valid_suffixes = "KMGTPEZY"; Line 236
return (strchr (valid_suffixes, suf) != NULL); Line 237
} Block 19
static inline int Line 240
suffix_power (const char suf) Line 241
{
switch (suf) Line 243
{
case 'K': /* kilo or kibi. */ Line 245
return 1; Line 246
case 'M': /* mega or mebi. */ Line 248
return 2; Line 249
case 'G': /* giga or gibi. */ Line 251
return 3; Line 252
case 'T': /* tera or tebi. */ Line 254
return 4; Line 255
case 'P': /* peta or pebi. */ Line 257
return 5; Line 258
case 'E': /* exa or exbi. */ Line 260
return 6; Line 261
case 'Z': /* zetta or 2**70. */ Line 263
return 7; Line 264
case 'Y': /* yotta or 2**80. */ Line 266
return 8; Line 267
default: /* should never happen. assert? */ Line 269
return 0; Line 270
}
} Block 20
static inline const char * Line 274
suffix_power_char (unsigned int power) Line 275
{
switch (power) Line 277
{
case 0: Line 279
return ""; Line 280
case 1: Line 282
return "K"; Line 283
case 2: Line 285
return "M"; Line 286
case 3: Line 288
return "G"; Line 289
case 4: Line 291
return "T"; Line 292
case 5: Line 294
return "P"; Line 295
case 6: Line 297
return "E"; Line 298
case 7: Line 300
return "Z"; Line 301
case 8: Line 303
return "Y"; Line 304
default: Line 306
return "(error)"; Line 307
}
} Block 21
/* Similar to 'powl(3)' but without requiring 'libm'. */
static long double Line 312
powerld (long double base, unsigned int x) Line 313
{
long double result = base; Line 315
if (x == 0) Line 316
return 1; /* note for test coverage: this is never Line 317
reached, as 'powerld' won't be called if
there's no suffix, hence, no "power". */
/* TODO: check for overflow, inf? */
while (--x) Line 322
result *= base; Line 323
return result; Line 324
} Block 22
/* Similar to 'fabs(3)' but without requiring 'libm'. */
static inline long double Line 328
absld (long double val) Line 329
{
return val < 0 ? -val : val; Line 331
} Block 23
/* Scale down 'val', returns 'updated val' and 'x', such that
val*base^X = original val
Similar to "frexpl(3)" but without requiring 'libm',
allowing only integer scale, limited functionality and error checking. */
static long double Line 338
expld (long double val, unsigned int base, unsigned int /*output */ *x) Line 339
{
unsigned int power = 0; Line 341
if (val >= -LDBL_MAX && val <= LDBL_MAX) Line 343
{
while (absld (val) >= base) Line 345
{
++power; Line 347
val /= base; Line 348
}
}
if (x) Line 351
*x = power; Line 352
return val; Line 353
} Block 24
/* EXTREMELY limited 'ceil' - without 'libm'.
Assumes values that fit in intmax_t. */
static inline intmax_t Line 358
simple_round_ceiling (long double val) Line 359
{
intmax_t intval = val; Line 361
if (intval < val) Line 362
intval++; Line 363
return intval; Line 364
} Block 25
/* EXTREMELY limited 'floor' - without 'libm'.
Assumes values that fit in intmax_t. */
static inline intmax_t Line 369
simple_round_floor (long double val) Line 370
{
return -simple_round_ceiling (-val); Line 372
} Block 26
/* EXTREMELY limited 'round away from zero'.
Assumes values that fit in intmax_t. */
static inline intmax_t Line 377
simple_round_from_zero (long double val) Line 378
{
return val < 0 ? simple_round_floor (val) : simple_round_ceiling (val); Line 380
} Block 27
/* EXTREMELY limited 'round away to zero'.
Assumes values that fit in intmax_t. */
static inline intmax_t Line 385
simple_round_to_zero (long double val) Line 386
{
return val; Line 388
} Block 28
/* EXTREMELY limited 'round' - without 'libm'.
Assumes values that fit in intmax_t. */
static inline intmax_t Line 393
simple_round_nearest (long double val) Line 394
{
return val < 0 ? val - 0.5 : val + 0.5; Line 396
} Block 29
static inline long double _GL_ATTRIBUTE_CONST Line 399
simple_round (long double val, enum round_type t) Line 400
{
intmax_t rval; Line 402
intmax_t intmax_mul = val / INTMAX_MAX; Line 403
val -= (long double) INTMAX_MAX * intmax_mul; Line 404
switch (t) Line 406
{
case round_ceiling: Line 408
rval = simple_round_ceiling (val); Line 409
break; Line 410
case round_floor: Line 412
rval = simple_round_floor (val); Line 413
break; Line 414
case round_from_zero: Line 416
rval = simple_round_from_zero (val); Line 417
break; Line 418
case round_to_zero: Line 420
rval = simple_round_to_zero (val); Line 421
break; Line 422
case round_nearest: Line 424
rval = simple_round_nearest (val); Line 425
break; Line 426
default: Line 428
/* to silence the compiler - this should never happen. */
return 0; Line 430
}
return (long double) INTMAX_MAX * intmax_mul + rval; Line 433
} Block 30
enum simple_strtod_error Line 436
{
SSE_OK = 0, Line 438
SSE_OK_PRECISION_LOSS, Line 439
SSE_OVERFLOW, Line 440
SSE_INVALID_NUMBER, Line 441
/* the following are returned by 'simple_strtod_human'. */
SSE_VALID_BUT_FORBIDDEN_SUFFIX, Line 444
SSE_INVALID_SUFFIX, Line 445
SSE_MISSING_I_SUFFIX Line 446
}; Block 31
/* Read an *integer* INPUT_STR,
but return the integer value in a 'long double' VALUE
hence, no UINTMAX_MAX limitation.
NEGATIVE is updated, and is stored separately from the VALUE
so that signbit() isn't required to determine the sign of -0..
ENDPTR is required (unlike strtod) and is used to store a pointer
to the character after the last character used in the conversion.
Note locale'd grouping is not supported,
nor is skipping of white-space supported.
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_INVALID_NUMBER - if no digits were found. */
static enum simple_strtod_error Line 465
simple_strtod_int (const char *input_str, Line 466
char **endptr, long double *value, bool *negative) Line 467
{
enum simple_strtod_error e = SSE_OK; Line 469
long double val = 0; Line 471
unsigned int digits = 0; Line 472
bool found_digit = false; Line 473
if (*input_str == '-') Line 475
{
input_str++; Line 477
*negative = true; Line 478
}
else Line 480
*negative = false; Line 481
*endptr = (char *) input_str; Line 483
while (*endptr && c_isdigit (**endptr)) Line 484
{
int digit = (**endptr) - '0'; Line 486
found_digit = true; Line 488
if (val || digit) Line 490
digits++; Line 491
if (digits > MAX_UNSCALED_DIGITS) Line 493
e = SSE_OK_PRECISION_LOSS; Line 494
if (digits > MAX_ACCEPTABLE_DIGITS) Line 496
return SSE_OVERFLOW; Line 497
val *= 10; Line 499
val += digit; Line 500
++(*endptr); Line 502
}
if (! found_digit Line 504
&& ! STREQ_LEN (*endptr, decimal_point, decimal_point_length)) Line 505
return SSE_INVALID_NUMBER; Line 506
if (*negative) Line 507
val = -val; Line 508
if (value) Line 510
*value = val; Line 511
return e; Line 513
} Block 32
/* Read a floating-point INPUT_STR represented as "NNNN[.NNNNN]",
and return the value in a 'long double' VALUE.
ENDPTR is required (unlike strtod) and is used to store a pointer
to the character after the last character used in the conversion.
PRECISION is optional and used to indicate fractions are present.
Note locale'd grouping is not supported,
nor is skipping of white-space supported.
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_INVALID_NUMBER - if no digits were found. */
static enum simple_strtod_error Line 530
simple_strtod_float (const char *input_str, Line 531
char **endptr, Line 532
long double *value, Line 533
size_t *precision) Line 534
{
bool negative; Line 536
enum simple_strtod_error e = SSE_OK; Line 537
if (precision) Line 539
*precision = 0; Line 540
/* TODO: accept locale'd grouped values for the integral part. */
e = simple_strtod_int (input_str, endptr, value, &negative); Line 543
if (e != SSE_OK && e != SSE_OK_PRECISION_LOSS) Line 544
return e; Line 545
/* optional decimal point + fraction. */
if (STREQ_LEN (*endptr, decimal_point, decimal_point_length)) Line 548
{
char *ptr2; Line 550
long double val_frac = 0; Line 551
bool neg_frac; Line 552
(*endptr) += decimal_point_length; Line 554
enum simple_strtod_error e2 = Line 555
simple_strtod_int (*endptr, &ptr2, &val_frac, &neg_frac); Line 556
if (e2 != SSE_OK && e2 != SSE_OK_PRECISION_LOSS) Line 557
return e2; Line 558
if (e2 == SSE_OK_PRECISION_LOSS) Line 559
e = e2; /* propagate warning. */ Line 560
if (neg_frac) Line 561
return SSE_INVALID_NUMBER; Line 562
/* number of digits in the fractions. */
size_t exponent = ptr2 - *endptr; Line 565
val_frac = ((long double) val_frac) / powerld (10, exponent); Line 567
/* TODO: detect loss of precision (only really 18 digits
of precision across all digits (before and after '.')). */
if (value) Line 571
{
if (negative) Line 573
*value -= val_frac; Line 574
else Line 575
*value += val_frac; Line 576
}
if (precision) Line 579
*precision = exponent; Line 580
*endptr = ptr2; Line 582
}
return e; Line 584
} Block 33
/* Read a 'human' INPUT_STR represented as "NNNN[.NNNNN] + suffix",
and return the value in a 'long double' VALUE,
with the precision of the input returned in PRECISION.
ENDPTR is required (unlike strtod) and is used to store a pointer
to the character after the last character used in the conversion.
ALLOWED_SCALING determines the scaling supported.
TODO:
support locale'd grouping
accept scentific and hex floats (probably use strtold directly)
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_INVALID_NUMBER - if no digits were found.
SSE_VALID_BUT_FORBIDDEN_SUFFIX
SSE_INVALID_SUFFIX
SSE_MISSING_I_SUFFIX */
static enum simple_strtod_error Line 606
simple_strtod_human (const char *input_str, Line 607
char **endptr, long double *value, size_t *precision, Line 608
enum scale_type allowed_scaling) Line 609
{
int power = 0; Line 611
/* 'scale_auto' is checked below. */
int scale_base = default_scale_base (allowed_scaling); Line 613
devmsg ("simple_strtod_human:\n input string: %s\n" Line 615
" locale decimal-point: %s\n" Line 616
" MAX_UNSCALED_DIGITS: %d\n", Line 617
quote_n (0, input_str), Line 618
quote_n (1, decimal_point), Line 619
MAX_UNSCALED_DIGITS); Line 620
enum simple_strtod_error e = Line 622
simple_strtod_float (input_str, endptr, value, precision); Line 623
if (e != SSE_OK && e != SSE_OK_PRECISION_LOSS) Line 624
return e; Line 625
devmsg (" parsed numeric value: %Lf\n" Line 627
" input precision = %d\n", *value, (int)*precision); Line 628
if (**endptr != '\0') Line 630
{
/* process suffix. */
/* Skip any blanks between the number and suffix. */
while (isblank (to_uchar (**endptr))) Line 635
(*endptr)++; Line 636
if (!valid_suffix (**endptr)) Line 638
return SSE_INVALID_SUFFIX; Line 639
if (allowed_scaling == scale_none) Line 641
return SSE_VALID_BUT_FORBIDDEN_SUFFIX; Line 642
power = suffix_power (**endptr); Line 644
(*endptr)++; /* skip first suffix character. */ Line 645
if (allowed_scaling == scale_auto && **endptr == 'i') Line 647
{
/* auto-scaling enabled, and the first suffix character
is followed by an 'i' (e.g. Ki, Mi, Gi). */
scale_base = 1024; Line 651
(*endptr)++; /* skip second ('i') suffix character. */ Line 652
devmsg (" Auto-scaling, found 'i', switching to base %d\n", Line 653
scale_base); Line 654
}
*precision = 0; /* Reset, to select precision based on scale. */ Line 657
}
if (allowed_scaling == scale_IEC_I) Line 660
{
if (**endptr == 'i') Line 662
(*endptr)++; Line 663
else Line 664
return SSE_MISSING_I_SUFFIX; Line 665
}
long double multiplier = powerld (scale_base, power); Line 668
devmsg (" suffix power=%d^%d = %Lf\n", scale_base, power, multiplier); Line 670
/* TODO: detect loss of precision and overflows. */
(*value) = (*value) * multiplier; Line 673
devmsg (" returning value: %Lf (%LG)\n", *value, *value); Line 675
return e; Line 677
} Block 34
static void Line 681
simple_strtod_fatal (enum simple_strtod_error err, char const *input_str) Line 682
{
char const *msgid = NULL; Line 684
switch (err) Line 686
{
case SSE_OK_PRECISION_LOSS: Line 688
case SSE_OK: Line 689
/* should never happen - this function isn't called when OK. */
abort (); ...!common auto-comment...
case SSE_OVERFLOW: Line 693
msgid = N_("value too large to be converted: %s"); Line 694
break; Line 695
case SSE_INVALID_NUMBER: Line 697
msgid = N_("invalid number: %s"); Line 698
break; Line 699
case SSE_VALID_BUT_FORBIDDEN_SUFFIX: Line 701
msgid = N_("rejecting suffix in input: %s (consider using --from)"); Line 702
break; Line 703
case SSE_INVALID_SUFFIX: Line 705
msgid = N_("invalid suffix in input: %s"); Line 706
break; Line 707
case SSE_MISSING_I_SUFFIX: Line 709
msgid = N_("missing 'i' suffix in input: %s (e.g Ki/Mi/Gi)"); Line 710
break; Line 711
}
if (inval_style != inval_ignore) Line 715
error (conv_exit_code, 0, gettext (msgid), quote (input_str)); Line 716
} Block 35
/* Convert VAL to a human format string in BUF. */
static void Line 720
double_to_human (long double val, int precision, Line 721
char *buf, size_t buf_size, Line 722
enum scale_type scale, int group, enum round_type round) Line 723
{
int num_size; Line 725
char fmt[64]; Line 726
verify (sizeof (fmt) > (INT_BUFSIZE_BOUND (zero_padding_width) Line 727
+ INT_BUFSIZE_BOUND (precision) Line 728
+ 10 /* for %.Lf etc. */)); Line 729
char *pfmt = fmt; Line 731
*pfmt++ = '%'; Line 732
if (group) Line 734
*pfmt++ = '\''; Line 735
if (zero_padding_width) Line 737
pfmt += snprintf (pfmt, sizeof (fmt) - 2, "0%ld", zero_padding_width); Line 738
devmsg ("double_to_human:\n"); Line 740
if (scale == scale_none) Line 742
{
val *= powerld (10, precision); Line 744
val = simple_round (val, round); Line 745
val /= powerld (10, precision); Line 746
devmsg ((group) ? Line 748
" no scaling, returning (grouped) value: %'.*Lf\n" : Line 749
" no scaling, returning value: %.*Lf\n", precision, val); Line 750
stpcpy (pfmt, ".*Lf"); Line 752
num_size = snprintf (buf, buf_size, fmt, precision, val); Line 754
if (num_size < 0 || num_size >= (int) buf_size) Line 755
die (EXIT_FAILURE, 0, Line 756
_("failed to prepare value '%Lf' for printing"), val); Line 757
return; Line 758
}
/* Scaling requested by user. */
double scale_base = default_scale_base (scale); Line 762
/* Normalize val to scale. */
unsigned int power = 0; Line 765
val = expld (val, scale_base, &power); Line 766
devmsg (" scaled value to %Lf * %0.f ^ %u\n", val, scale_base, power); Line 767
/* Perform rounding. */
unsigned int power_adjust = 0; Line 770
if (user_precision != -1) Line 771
power_adjust = MIN (power * 3, user_precision); Line 772
else if (absld (val) < 10) Line 773
{
/* for values less than 10, we allow one decimal-point digit,
so adjust before rounding. */
power_adjust = 1; Line 777
}
val *= powerld (10, power_adjust); Line 780
val = simple_round (val, round); Line 781
val /= powerld (10, power_adjust); Line 782
/* two special cases after rounding:
1. a "999.99" can turn into 1000 - so scale down
2. a "9.99" can turn into 10 - so don't display decimal-point. */
if (absld (val) >= scale_base) Line 787
{
val /= scale_base; Line 789
power++; Line 790
}
/* should "7.0" be printed as "7" ?
if removing the ".0" is preferred, enable the fourth condition. */
int show_decimal_point = (val != 0) && (absld (val) < 10) && (power > 0); Line 795
/* && (absld (val) > simple_round_floor (val))) */
devmsg (" after rounding, value=%Lf * %0.f ^ %u\n", val, scale_base, power); Line 798
stpcpy (pfmt, ".*Lf%s"); Line 800
int prec = user_precision == -1 ? show_decimal_point : user_precision; Line 802
/* buf_size - 1 used here to ensure place for possible scale_IEC_I suffix. */
num_size = snprintf (buf, buf_size - 1, fmt, prec, val, Line 805
suffix_power_char (power)); Line 806
if (num_size < 0 || num_size >= (int) buf_size - 1) Line 807
die (EXIT_FAILURE, 0, Line 808
_("failed to prepare value '%Lf' for printing"), val); Line 809
if (scale == scale_IEC_I && power > 0) Line 811
strncat (buf, "i", buf_size - num_size - 1); Line 812
devmsg (" returning value: %s\n", quote (buf)); Line 814
return; Line 816
} Block 36
/* Convert a string of decimal digits, N_STRING, with an optional suffix
to an integral value. Suffixes are handled as with --from=auto.
Upon successful conversion, return that value.
If it cannot be converted, give a diagnostic and exit. */
static uintmax_t Line 823
unit_to_umax (const char *n_string) Line 824
{
strtol_error s_err; Line 826
const char *c_string = n_string; Line 827
char *t_string = NULL; Line 828
size_t n_len = strlen (n_string); Line 829
char *end = NULL; Line 830
uintmax_t n; Line 831
const char *suffixes = "KMGTPEZY"; Line 832
/* Adjust suffixes so K=1000, Ki=1024, KiB=invalid. */
if (n_len && ! c_isdigit (n_string[n_len - 1])) Line 835
{
t_string = xmalloc (n_len + 2); Line 837
end = t_string + n_len - 1; Line 838
memcpy (t_string, n_string, n_len); Line 839
if (*end == 'i' && 2 <= n_len && ! c_isdigit (*(end - 1))) Line 841
*end = '\0'; Line 842
else Line 843
{
*++end = 'B'; Line 845
*++end = '\0'; Line 846
suffixes = "KMGTPEZY0"; Line 847
}
c_string = t_string; Line 850
}
s_err = xstrtoumax (c_string, &end, 10, &n, suffixes); Line 853
if (s_err != LONGINT_OK || *end || n == 0) Line 855
{
free (t_string); Line 857
die (EXIT_FAILURE, 0, _("invalid unit size: %s"), quote (n_string)); Line 858
}
free (t_string); Line 861
return n; Line 863
} Block 37
static void Line 867
setup_padding_buffer (size_t min_size) Line 868
{
if (padding_buffer_size > min_size) Line 870
return; Line 871
padding_buffer_size = min_size + 1; Line 873
padding_buffer = xrealloc (padding_buffer, padding_buffer_size); Line 874
} Block 38
void Line 877
usage (int status) Line 878
{
if (status != EXIT_SUCCESS) Line 880
emit_try_help (); ...!common auto-comment...
else Line 882
{
printf (_("\ Line 884
Usage: %s [OPTION]... [NUMBER]...\n\ Line 885
"), program_name); Line 886
fputs (_("\ Line 887
Reformat NUMBER(s), or the numbers from standard input if none are specified.\n\Line 888
"), stdout); Line 889
emit_mandatory_arg_note (); ...!common auto-comment...
fputs (_("\ Line 891
--debug print warnings about invalid input\n\ Line 892
"), stdout); Line 893
fputs (_("\ Line 894
-d, --delimiter=X use X instead of whitespace for field delimiter\n\ Line 895
"), stdout); Line 896
fputs (_("\ Line 897
--field=FIELDS replace the numbers in these input fields (default=1)\n\ Line 898
see FIELDS below\n\ Line 899
"), stdout); Line 900
fputs (_("\ Line 901
--format=FORMAT use printf style floating-point FORMAT;\n\ Line 902
see FORMAT below for details\n\ Line 903
"), stdout); Line 904
fputs (_("\ Line 905
--from=UNIT auto-scale input numbers to UNITs; default is 'none';\n\ Line 906
see UNIT below\n\ Line 907
"), stdout); Line 908
fputs (_("\ Line 909
--from-unit=N specify the input unit size (instead of the default 1)\n\Line 910
"), stdout); Line 911
fputs (_("\ Line 912
--grouping use locale-defined grouping of digits, e.g. 1,000,000\n\ Line 913
(which means it has no effect in the C/POSIX locale)\n\Line 914
"), stdout); Line 915
fputs (_("\ Line 916
--header[=N] print (without converting) the first N header lines;\n\ Line 917
N defaults to 1 if not specified\n\ Line 918
"), stdout); Line 919
fputs (_("\ Line 920
--invalid=MODE failure mode for invalid numbers: MODE can be:\n\ Line 921
abort (default), fail, warn, ignore\n\ ...!common auto-comment...
"), stdout); Line 923
fputs (_("\ Line 924
--padding=N pad the output to N characters; positive N will\n\ Line 925
right-align; negative N will left-align;\n\ Line 926
padding is ignored if the output is wider than N;\n\ Line 927
the default is to automatically pad if a whitespace\n\ Line 928
is found\n\ Line 929
"), stdout); Line 930
fputs (_("\ Line 931
--round=METHOD use METHOD for rounding when scaling; METHOD can be:\n\ Line 932
up, down, from-zero (default), towards-zero, nearest\n\Line 933
"), stdout); Line 934
fputs (_("\ Line 935
--suffix=SUFFIX add SUFFIX to output numbers, and accept optional\n\ Line 936
SUFFIX in input numbers\n\ Line 937
"), stdout); Line 938
fputs (_("\ Line 939
--to=UNIT auto-scale output numbers to UNITs; see UNIT below\n\ Line 940
"), stdout); Line 941
fputs (_("\ Line 942
--to-unit=N the output unit size (instead of the default 1)\n\ Line 943
"), stdout); Line 944
fputs (_("\ Line 945
-z, --zero-terminated line delimiter is NUL, not newline\n\ Line 946
"), stdout); Line 947
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 948
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 949
fputs (_("\ Line 951
\n\
UNIT options:\n"), stdout); Line 953
fputs (_("\ Line 954
none no auto-scaling is done; suffixes will trigger an error\n\ Line 955
"), stdout); Line 956
fputs (_("\ Line 957
auto accept optional single/two letter suffix:\n\ Line 958
1K = 1000,\n\ Line 959
1Ki = 1024,\n\ Line 960
1M = 1000000,\n\ Line 961
1Mi = 1048576,\n"), stdout); Line 962
fputs (_("\ Line 963
si accept optional single letter suffix:\n\ Line 964
1K = 1000,\n\ Line 965
1M = 1000000,\n\ Line 966
...\n"), stdout); Line 967
fputs (_("\ Line 968
iec accept optional single letter suffix:\n\ Line 969
1K = 1024,\n\ Line 970
1M = 1048576,\n\ Line 971
...\n"), stdout); Line 972
fputs (_("\ Line 973
iec-i accept optional two-letter suffix:\n\ Line 974
1Ki = 1024,\n\ Line 975
1Mi = 1048576,\n\ Line 976
...\n"), stdout); Line 977
fputs (_("\n\ Line 979
FIELDS supports cut(1) style field ranges:\n\ Line 980
N N'th field, counted from 1\n\ Line 981
N- from N'th field, to end of line\n\ Line 982
N-M from N'th to M'th field (inclusive)\n\ Line 983
-M from first to M'th field (inclusive)\n\ Line 984
- all fields\n\ Line 985
Multiple fields/ranges can be separated with commas\n\ Line 986
"), stdout); Line 987
fputs (_("\n\ Line 989
FORMAT must be suitable for printing one floating-point argument '%f'.\n\ Line 990
Optional quote (%'f) will enable --grouping (if supported by current locale).\n\Line 991
Optional width value (%10f) will pad output. Optional zero (%010f) width\n\ Line 992
will zero pad the number. Optional negative values (%-10f) will left align.\n\ Line 993
Optional precision (%.1f) will override the input determined precision.\n\ Line 994
"), stdout); Line 995
printf (_("\n\ Line 997
Exit status is 0 if all input numbers were successfully converted.\n\ Line 998
By default, %s will stop at the first conversion error with exit status 2.\n\ Line 999
With --invalid='fail' a warning is printed for each conversion error\n\ Line 1000
and the exit status is 2. With --invalid='warn' each conversion error is\n\ Line 1001
diagnosed, but the exit status is 0. With --invalid='ignore' conversion\n\ Line 1002
errors are not diagnosed and the exit status is 0.\n\ Line 1003
"), program_name); Line 1004
printf (_("\n\ Line 1006
Examples:\n\ Line 1007
$ %s --to=si 1000\n\ Line 1008
-> \"1.0K\"\n\ Line 1009
$ %s --to=iec 2048\n\ Line 1010
-> \"2.0K\"\n\ Line 1011
$ %s --to=iec-i 4096\n\ Line 1012
-> \"4.0Ki\"\n\ Line 1013
$ echo 1K | %s --from=si\n\ Line 1014
-> \"1000\"\n\ Line 1015
$ echo 1K | %s --from=iec\n\ Line 1016
-> \"1024\"\n\ Line 1017
$ df -B1 | %s --header --field 2-4 --to=si\n\ Line 1018
$ ls -l | %s --header --field 5 --to=iec\n\ Line 1019
$ ls -lh | %s --header --field 5 --from=iec --padding=10\n\ Line 1020
$ ls -lh | %s --header --field 5 --from=iec --format %%10f\n"), Line 1021
program_name, program_name, program_name, Line 1022
program_name, program_name, program_name, Line 1023
program_name, program_name, program_name); Line 1024
emit_ancillary_info (PROGRAM_NAME); Line 1025
}
exit (status); Line 1027
} Block 39
/* Given 'fmt' (a printf(3) compatible format string), extracts the following:
1. padding (e.g. %20f)
2. alignment (e.g. %-20f)
3. grouping (e.g. %'f)
Only a limited subset of printf(3) syntax is supported.
TODO:
support %e %g etc. rather than just %f
NOTES:
1. This function sets the global variables:
padding_width, padding_alignment, grouping,
format_str_prefix, format_str_suffix
2. The function aborts on any errors. */
static void Line 1045
parse_format_string (char const *fmt) Line 1046
{
size_t i; Line 1048
size_t prefix_len = 0; Line 1049
size_t suffix_pos; Line 1050
long int pad = 0; Line 1051
char *endptr = NULL; Line 1052
bool zero_padding = false; Line 1053
for (i = 0; !(fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1) Line 1055
{
if (!fmt[i]) Line 1057
die (EXIT_FAILURE, 0, Line 1058
_("format %s has no %% directive"), quote (fmt)); Line 1059
prefix_len++; Line 1060
}
i++; Line 1063
while (true) Line 1064
{
size_t skip = strspn (fmt + i, " "); Line 1066
i += skip; Line 1067
if (fmt[i] == '\'') Line 1068
{
grouping = 1; Line 1070
i++; Line 1071
}
else if (fmt[i] == '0') Line 1073
{
zero_padding = true; Line 1075
i++; Line 1076
}
else if (! skip) Line 1078
break; Line 1079
}
errno = 0; Line 1082
pad = strtol (fmt + i, &endptr, 10); Line 1083
if (errno == ERANGE) Line 1084
die (EXIT_FAILURE, 0, Line 1085
_("invalid format %s (width overflow)"), quote (fmt)); Line 1086
if (endptr != (fmt + i) && pad != 0) Line 1088
{
if (debug && padding_width && !(zero_padding && pad > 0)) Line 1090
error (0, 0, _("--format padding overriding --padding")); Line 1091
if (pad < 0) Line 1093
{
padding_alignment = MBS_ALIGN_LEFT; Line 1095
padding_width = -pad; Line 1096
}
else Line 1098
{
if (zero_padding) Line 1100
zero_padding_width = pad; Line 1101
else Line 1102
padding_width = pad; Line 1103
}
}
i = endptr - fmt; Line 1107
if (fmt[i] == '\0') Line 1109
die (EXIT_FAILURE, 0, _("format %s ends in %%"), quote (fmt)); Line 1110
if (fmt[i] == '.') Line 1112
{
i++; Line 1114
errno = 0; Line 1115
user_precision = strtol (fmt + i, &endptr, 10); Line 1116
if (errno == ERANGE || user_precision < 0 || SIZE_MAX < user_precision Line 1117
|| isblank (fmt[i]) || fmt[i] == '+') Line 1118
{
/* Note we disallow negative user_precision to be
consistent with printf(1). POSIX states that
negative precision is only supported (and ignored)
when used with '.*f'. glibc at least will malform
output when passed a direct negative precision. */
die (EXIT_FAILURE, 0, Line 1125
_("invalid precision in format %s"), quote (fmt)); Line 1126
}
i = endptr - fmt; Line 1128
}
if (fmt[i] != 'f') Line 1131
die (EXIT_FAILURE, 0, _("invalid format %s," Line 1132
" directive must be %%[0]['][-][N][.][N]f"), Line 1133
quote (fmt)); Line 1134
i++; Line 1135
suffix_pos = i; Line 1136
for (; fmt[i] != '\0'; i += (fmt[i] == '%') + 1) Line 1138
if (fmt[i] == '%' && fmt[i + 1] != '%') Line 1139
die (EXIT_FAILURE, 0, _("format %s has too many %% directives"), Line 1140
quote (fmt)); Line 1141
if (prefix_len) Line 1143
format_str_prefix = xstrndup (fmt, prefix_len); Line 1144
if (fmt[suffix_pos] != '\0') Line 1145
format_str_suffix = xstrdup (fmt + suffix_pos); Line 1146
devmsg ("format String:\n input: %s\n grouping: %s\n" Line 1148
" padding width: %ld\n alignment: %s\n" Line 1149
" prefix: %s\n suffix: %s\n", Line 1150
quote_n (0, fmt), (grouping) ? "yes" : "no", Line 1151
padding_width, Line 1152
(padding_alignment == MBS_ALIGN_LEFT) ? "Left" : "Right", Line 1153
quote_n (1, format_str_prefix ? format_str_prefix : ""), Line 1154
quote_n (2, format_str_suffix ? format_str_suffix : "")); Line 1155
} Block 40
/* Parse a numeric value (with optional suffix) from a string.
Returns a long double value, with input precision.
If there's an error converting the string to value - exits with
an error.
If there are any trailing characters after the number
(besides a valid suffix) - exits with an error. */
static enum simple_strtod_error Line 1166
parse_human_number (const char *str, long double /*output */ *value, Line 1167
size_t *precision) Line 1168
{
char *ptr = NULL; Line 1170
enum simple_strtod_error e = Line 1172
simple_strtod_human (str, &ptr, value, precision, scale_from); Line 1173
if (e != SSE_OK && e != SSE_OK_PRECISION_LOSS) Line 1174
{
simple_strtod_fatal (e, str); Line 1176
return e; Line 1177
}
if (ptr && *ptr != '\0') Line 1180
{
if (inval_style != inval_ignore) Line 1182
error (conv_exit_code, 0, _("invalid suffix in input %s: %s"), Line 1183
quote_n (0, str), quote_n (1, ptr)); Line 1184
e = SSE_INVALID_SUFFIX; Line 1185
}
return e; Line 1187
} Block 41
/* Print the given VAL, using the requested representation.
The number is printed to STDOUT, with padding and alignment. */
static int Line 1193
prepare_padded_number (const long double val, size_t precision) Line 1194
{
/* Generate Output. */
char buf[128]; Line 1197
size_t precision_used = user_precision == -1 ? precision : user_precision; Line 1199
/* Can't reliably print too-large values without auto-scaling. */
unsigned int x; Line 1202
expld (val, 10, &x); Line 1203
if (scale_to == scale_none Line 1205
&& x + precision_used > MAX_UNSCALED_DIGITS) Line 1206
{
if (inval_style != inval_ignore) Line 1208
{
if (precision_used) Line 1210
error (conv_exit_code, 0, Line 1211
_("value/precision too large to be printed: '%Lg/%"PRIuMAX"'"Line 1212
" (consider using --to)"), val, (uintmax_t)precision_used);Line 1213
else Line 1214
error (conv_exit_code, 0, Line 1215
_("value too large to be printed: '%Lg'" Line 1216
" (consider using --to)"), val); Line 1217
}
return 0; Line 1219
}
if (x > MAX_ACCEPTABLE_DIGITS - 1) Line 1222
{
if (inval_style != inval_ignore) Line 1224
error (conv_exit_code, 0, _("value too large to be printed: '%Lg'" Line 1225
" (cannot handle values > 999Y)"), val); Line 1226
return 0; Line 1227
}
double_to_human (val, precision_used, buf, sizeof (buf), Line 1230
scale_to, grouping, round_style); Line 1231
if (suffix) Line 1232
strncat (buf, suffix, sizeof (buf) - strlen (buf) -1); Line 1233
devmsg ("formatting output:\n value: %Lf\n humanized: %s\n", Line 1235
val, quote (buf)); Line 1236
if (padding_width && strlen (buf) < padding_width) Line 1238
{
size_t w = padding_width; Line 1240
mbsalign (buf, padding_buffer, padding_buffer_size, &w, Line 1241
padding_alignment, MBA_UNIBYTE_ONLY); Line 1242
devmsg (" After padding: %s\n", quote (padding_buffer)); Line 1244
}
else Line 1246
{
setup_padding_buffer (strlen (buf) + 1); Line 1248
strcpy (padding_buffer, buf); Line 1249
}
return 1; Line 1252
}
static void Line 1255
print_padded_number (void) Line 1256
{
if (format_str_prefix) Line 1258
fputs (format_str_prefix, stdout); Line 1259
fputs (padding_buffer, stdout); Line 1261
if (format_str_suffix) Line 1263
fputs (format_str_suffix, stdout); Line 1264
} Block 43
/* Converts the TEXT number string to the requested representation,
and handles automatic suffix addition. */
static int Line 1269
process_suffixed_number (char *text, long double *result, Line 1270
size_t *precision, long int field) Line 1271
{
if (suffix && strlen (text) > strlen (suffix)) Line 1273
{
char *possible_suffix = text + strlen (text) - strlen (suffix); Line 1275
if (STREQ (suffix, possible_suffix)) Line 1277
{
/* trim suffix, ONLY if it's at the end of the text. */
*possible_suffix = '\0'; Line 1280
devmsg ("trimming suffix %s\n", quote (suffix)); Line 1281
}
else Line 1283
devmsg ("no valid suffix found\n"); Line 1284
}
/* Skip white space - always. */
char *p = text; Line 1288
while (*p && isblank (to_uchar (*p))) Line 1289
++p; Line 1290
const unsigned int skip_count = text - p; Line 1291
/* setup auto-padding. */
if (auto_padding) Line 1294
{
if (skip_count > 0 || field > 1) Line 1296
{
padding_width = strlen (text); Line 1298
setup_padding_buffer (padding_width); Line 1299
}
else Line 1301
{
padding_width = 0; Line 1303
}
devmsg ("setting Auto-Padding to %ld characters\n", padding_width); Line 1305
}
long double val = 0; Line 1308
enum simple_strtod_error e = parse_human_number (p, &val, precision); Line 1309
if (e == SSE_OK_PRECISION_LOSS && debug) Line 1310
error (0, 0, _("large input value %s: possible precision loss"), Line 1311
quote (p)); Line 1312
if (from_unit_size != 1 || to_unit_size != 1) Line 1314
val = (val * from_unit_size) / to_unit_size; Line 1315
*result = val; Line 1317
return (e == SSE_OK || e == SSE_OK_PRECISION_LOSS); Line 1319
} Block 44
/* Return a pointer to the beginning of the next field in line.
The line pointer is moved to the end of the next field. */
static char* Line 1324
next_field (char **line) Line 1325
{
char *field_start = *line; Line 1327
char *field_end = field_start; Line 1328
if (delimiter != DELIMITER_DEFAULT) Line 1330
{
if (*field_start != delimiter) Line 1332
{
while (*field_end && *field_end != delimiter) Line 1334
++field_end; Line 1335
}
/* else empty field */
}
else Line 1339
{
/* keep any space prefix in the returned field */
while (*field_end && field_sep (*field_end)) Line 1342
++field_end; Line 1343
while (*field_end && ! field_sep (*field_end)) Line 1345
++field_end; Line 1346
}
*line = field_end; Line 1349
return field_start; Line 1350
} Block 45
static bool _GL_ATTRIBUTE_PURE Line 1353
include_field (uintmax_t field) Line 1354
{
struct field_range_pair *p = frp; Line 1356
if (!p) Line 1357
return field == 1; Line 1358
while (p->lo != UINTMAX_MAX) Line 1360
{
if (p->lo <= field && p->hi >= field) Line 1362
return true; Line 1363
++p; Line 1364
}
return false; Line 1366
} Block 46
/* Convert and output the given field. If it is not included in the set
of fields to process just output the original */
static bool Line 1371
process_field (char *text, uintmax_t field) Line 1372
{
long double val = 0; Line 1374
size_t precision = 0; Line 1375
bool valid_number = true; Line 1376
if (include_field (field)) Line 1378
{
valid_number = Line 1380
process_suffixed_number (text, &val, &precision, field); Line 1381
if (valid_number) Line 1383
valid_number = prepare_padded_number (val, precision); Line 1384
if (valid_number) Line 1386
print_padded_number (); Line 1387
else Line 1388
fputs (text, stdout); Line 1389
}
else Line 1391
fputs (text, stdout); Line 1392
return valid_number; Line 1394
} Block 47
/* Convert number in a given line of text.
NEWLINE specifies whether to output a '\n' for this "line". */
static int Line 1399
process_line (char *line, bool newline) Line 1400
{
char *next; Line 1402
uintmax_t field = 0; Line 1403
bool valid_number = true; Line 1404
while (true) { Line 1406
++field; Line 1407
next = next_field (&line); Line 1408
if (*line != '\0') Line 1410
{
/* nul terminate the current field string and process */
*line = '\0'; Line 1413
if (! process_field (next, field)) Line 1415
valid_number = false; Line 1416
fputc ((delimiter == DELIMITER_DEFAULT) ? Line 1418
' ' : delimiter, stdout); Line 1419
++line; Line 1420
}
else Line 1422
{
/* end of the line, process the last field and finish */
if (! process_field (next, field)) Line 1425
valid_number = false; Line 1426
break; Line 1428
}
}
if (newline) Line 1432
putchar (line_delim); Line 1433
return valid_number; Line 1435
} Block 48
int
main (int argc, char **argv) Line 1439
{
int valid_numbers = 1; Line 1441
bool locale_ok; Line 1442
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
locale_ok = !!setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
#if HAVE_FPSETPREC Line 1450
/* Enabled extended precision if needed. */
fpsetprec (FP_PE); Line 1452
#endif Line 1453
decimal_point = nl_langinfo (RADIXCHAR); Line 1455
if (decimal_point == NULL || strlen (decimal_point) == 0) Line 1456
decimal_point = "."; Line 1457
decimal_point_length = strlen (decimal_point); Line 1458
atexit (close_stdout); Close stdout on exit (see gnulib)
while (true) Line 1462
{
int c = getopt_long (argc, argv, "d:z", longopts, NULL); Line 1464
if (c == -1) Line 1466
break; Line 1467
switch (c) Line 1469
{
case FROM_OPTION: Line 1471
scale_from = XARGMATCH ("--from", optarg, Line 1472
scale_from_args, scale_from_types); Line 1473
break; Line 1474
case FROM_UNIT_OPTION: Line 1476
from_unit_size = unit_to_umax (optarg); Line 1477
break; Line 1478
case TO_OPTION: Line 1480
scale_to = Line 1481
XARGMATCH ("--to", optarg, scale_to_args, scale_to_types); Line 1482
break; Line 1483
case TO_UNIT_OPTION: Line 1485
to_unit_size = unit_to_umax (optarg); Line 1486
break; Line 1487
case ROUND_OPTION: Line 1489
round_style = XARGMATCH ("--round", optarg, round_args, round_types); Line 1490
break; Line 1491
case GROUPING_OPTION: Line 1493
grouping = 1; Line 1494
break; Line 1495
case PADDING_OPTION: Line 1497
if (xstrtol (optarg, NULL, 10, &padding_width, "") != LONGINT_OK Line 1498
|| padding_width == 0) Line 1499
die (EXIT_FAILURE, 0, _("invalid padding value %s"), Line 1500
quote (optarg)); Line 1501
if (padding_width < 0) Line 1502
{
padding_alignment = MBS_ALIGN_LEFT; Line 1504
padding_width = -padding_width; Line 1505
}
/* TODO: We probably want to apply a specific --padding
to --header lines too. */
break; Line 1509
case FIELD_OPTION: Line 1511
if (n_frp) Line 1512
die (EXIT_FAILURE, 0, _("multiple field specifications")); Line 1513
set_fields (optarg, SETFLD_ALLOW_DASH); Line 1514
break; Line 1515
case 'd': Line 1517
/* Interpret -d '' to mean 'use the NUL byte as the delimiter.' */
if (optarg[0] != '\0' && optarg[1] != '\0') Line 1519
die (EXIT_FAILURE, 0, Line 1520
_("the delimiter must be a single character")); Line 1521
delimiter = optarg[0]; Line 1522
break; Line 1523
case 'z': Line 1525
line_delim = '\0'; Line 1526
break; Line 1527
case SUFFIX_OPTION: Line 1529
suffix = optarg; Line 1530
break; Line 1531
case DEBUG_OPTION: Line 1533
debug = true; Line 1534
break; Line 1535
case DEV_DEBUG_OPTION: Line 1537
dev_debug = true; Line 1538
debug = true; Line 1539
break; Line 1540
case HEADER_OPTION: Line 1542
if (optarg) Line 1543
{
if (xstrtoumax (optarg, NULL, 10, &header, "") != LONGINT_OK Line 1545
|| header == 0) Line 1546
die (EXIT_FAILURE, 0, _("invalid header value %s"), Line 1547
quote (optarg)); Line 1548
}
else Line 1550
{
header = 1; Line 1552
}
break; Line 1554
case FORMAT_OPTION: Line 1556
format_str = optarg; Line 1557
break; Line 1558
case INVALID_OPTION: Line 1560
inval_style = XARGMATCH ("--invalid", optarg, Line 1561
inval_args, inval_types); Line 1562
break; Line 1563
case_GETOPT_HELP_CHAR; Line 1565
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1566
default: Line 1568
usage (EXIT_FAILURE); Line 1569
}
}
if (format_str != NULL && grouping) Line 1573
die (EXIT_FAILURE, 0, _("--grouping cannot be combined with --format")); Line 1574
if (debug && ! locale_ok) Line 1576
error (0, 0, _("failed to set locale")); Line 1577
/* Warn about no-op. */
if (debug && scale_from == scale_none && scale_to == scale_none Line 1580
&& !grouping && (padding_width == 0) && (format_str == NULL)) Line 1581
error (0, 0, _("no conversion option specified")); Line 1582
if (format_str) Line 1584
parse_format_string (format_str); Line 1585
if (grouping) Line 1587
{
if (scale_to != scale_none) Line 1589
die (EXIT_FAILURE, 0, _("grouping cannot be combined with --to")); Line 1590
if (debug && (strlen (nl_langinfo (THOUSEP)) == 0)) Line 1591
error (0, 0, _("grouping has no effect in this locale")); Line 1592
}
setup_padding_buffer (padding_width); Line 1596
auto_padding = (padding_width == 0 && delimiter == DELIMITER_DEFAULT); Line 1597
if (inval_style != inval_abort) ...!common auto-comment...
conv_exit_code = 0; Line 1600
if (argc > optind) Line 1602
{
if (debug && header) Line 1604
error (0, 0, _("--header ignored with command-line input")); Line 1605
for (; optind < argc; optind++) Line 1607
valid_numbers &= process_line (argv[optind], true); Line 1608
}
else Line 1610
{
char *line = NULL; Line 1612
size_t line_allocated = 0; Line 1613
ssize_t len; Line 1614
while (header-- && getdelim (&line, &line_allocated, Line 1616
line_delim, stdin) > 0) Line 1617
fputs (line, stdout); Line 1618
while ((len = getdelim (&line, &line_allocated, Line 1620
line_delim, stdin)) > 0) Line 1621
{
bool newline = line[len - 1] == line_delim; Line 1623
if (newline) Line 1624
line[len - 1] = '\0'; Line 1625
valid_numbers &= process_line (line, newline); Line 1626
}
IF_LINT (free (line)); Line 1629
if (ferror (stdin)) Line 1631
error (0, errno, _("error reading input")); Line 1632
}
#ifdef lint Line 1635
free (padding_buffer); Line 1636
free (format_str_prefix); Line 1637
free (format_str_suffix); Line 1638
reset_fields (); Line 1639
#endif Line 1640
if (debug && !valid_numbers) Line 1642
error (0, 0, _("failed to convert some of the input numbers")); Line 1643
int exit_status = EXIT_SUCCESS; Line 1645
if (!valid_numbers Line 1646
&& inval_style != inval_warn && inval_style != inval_ignore) Line 1647
exit_status = EXIT_CONVERSION_WARNINGS; Line 1648
return exit_status; Line 1650
} Block 49