summaryrefslogtreecommitdiff
path: root/lib/human.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-01-20 10:55:18 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-01-20 10:55:18 +0000
commit70e9163c9c18e995515598085cb824e554eb7ae7 (patch)
treea42dc8b2a6c031354bf31472de888bfc8a060132 /lib/human.c
parentcbf5993c43f49281173f185863577d86bfac6eae (diff)
downloadcoreutils-tarball-70e9163c9c18e995515598085cb824e554eb7ae7.tar.gz
Diffstat (limited to 'lib/human.c')
-rw-r--r--lib/human.c354
1 files changed, 173 insertions, 181 deletions
diff --git a/lib/human.c b/lib/human.c
index ecf4c97..7fc0bf2 100644
--- a/lib/human.c
+++ b/lib/human.c
@@ -1,12 +1,11 @@
/* human.c -- print human readable file size
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009-2016 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ 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 2, or (at your option)
- any later version.
+ 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
@@ -14,8 +13,7 @@
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, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and Larry McVoy. */
@@ -28,28 +26,24 @@
#include <stdlib.h>
#include <string.h>
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
#include <argmatch.h>
#include <error.h>
#include <intprops.h>
-#include <xstrtol.h>
/* The maximum length of a suffix like "KiB". */
#define HUMAN_READABLE_SUFFIX_LENGTH_MAX 3
static const char power_letter[] =
{
- 0, /* not used */
- 'K', /* kibi ('k' for kilo is a special case) */
- 'M', /* mega or mebi */
- 'G', /* giga or gibi */
- 'T', /* tera or tebi */
- 'P', /* peta or pebi */
- 'E', /* exa or exbi */
- 'Z', /* zetta or 2**70 */
- 'Y' /* yotta or 2**80 */
+ 0, /* not used */
+ 'K', /* kibi ('k' for kilo is a special case) */
+ 'M', /* mega or mebi */
+ 'G', /* giga or gibi */
+ 'T', /* tera or tebi */
+ 'P', /* peta or pebi */
+ 'E', /* exa or exbi */
+ 'Z', /* zetta or 2**70 */
+ 'Y' /* yotta or 2**80 */
};
@@ -78,12 +72,12 @@ adjust_value (int inexact_style, long double value)
each byte inserted. Return the starting address of the modified
number.
- To group the digits, use GROUPING and THOUSANDS_SEP as in `struct
+ To group the digits, use GROUPING and THOUSANDS_SEP as in 'struct
lconv' from <locale.h>. */
static char *
group_number (char *number, size_t numberlen,
- char const *grouping, char const *thousands_sep)
+ char const *grouping, char const *thousands_sep)
{
register char *d;
size_t grouplen = SIZE_MAX;
@@ -102,19 +96,19 @@ group_number (char *number, size_t numberlen,
unsigned char g = *grouping;
if (g)
- {
- grouplen = g < CHAR_MAX ? g : i;
- grouping++;
- }
+ {
+ grouplen = g < CHAR_MAX ? g : i;
+ grouping++;
+ }
if (i < grouplen)
- grouplen = i;
+ grouplen = i;
d -= grouplen;
i -= grouplen;
memcpy (d, buf + i, grouplen);
if (i == 0)
- return d;
+ return d;
d -= thousands_seplen;
memcpy (d, thousands_sep, thousands_seplen);
@@ -134,7 +128,7 @@ group_number (char *number, size_t numberlen,
that cannot be expressed exactly.
If (OPTS & human_group_digits), group the thousands digits
- according to the locale, e.g., `1,000,000' in an American English
+ according to the locale, e.g., "1,000,000" in an American English
locale.
If (OPTS & human_autoscale), deduce the output block size
@@ -157,7 +151,7 @@ group_number (char *number, size_t numberlen,
char *
human_readable (uintmax_t n, char *buf, int opts,
- uintmax_t from_block_size, uintmax_t to_block_size)
+ uintmax_t from_block_size, uintmax_t to_block_size)
{
int inexact_style =
opts & (human_round_to_nearest | human_floor | human_ceiling);
@@ -191,7 +185,8 @@ human_readable (uintmax_t n, char *buf, int opts,
if (strlen (l->thousands_sep) <= MB_LEN_MAX)
thousands_sep = l->thousands_sep;
- psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
+ /* Leave room for a trailing space and following suffix. */
+ psuffix = buf + LONGEST_HUMAN_READABLE - 1 - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
p = psuffix;
/* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE
@@ -200,16 +195,16 @@ human_readable (uintmax_t n, char *buf, int opts,
if (to_block_size <= from_block_size)
{
if (from_block_size % to_block_size == 0)
- {
- uintmax_t multiplier = from_block_size / to_block_size;
- amt = n * multiplier;
- if (amt / multiplier == n)
- {
- tenths = 0;
- rounding = 0;
- goto use_integer_arithmetic;
- }
- }
+ {
+ uintmax_t multiplier = from_block_size / to_block_size;
+ amt = n * multiplier;
+ if (amt / multiplier == n)
+ {
+ tenths = 0;
+ rounding = 0;
+ goto use_integer_arithmetic;
+ }
+ }
}
else if (from_block_size != 0 && to_block_size % from_block_size == 0)
{
@@ -234,37 +229,37 @@ human_readable (uintmax_t n, char *buf, int opts,
if (! (opts & human_autoscale))
{
- sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt));
- buflen = strlen (buf);
- nonintegerlen = 0;
+ sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt));
+ buflen = strlen (buf);
+ nonintegerlen = 0;
}
else
{
- long double e = 1;
- exponent = 0;
-
- do
- {
- e *= base;
- exponent++;
- }
- while (e * base <= damt && exponent < exponent_max);
-
- damt /= e;
-
- sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt));
- buflen = strlen (buf);
- nonintegerlen = decimal_pointlen + 1;
-
- if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen
- || ((opts & human_suppress_point_zero)
- && buf[buflen - 1] == '0'))
- {
- sprintf (buf, "%.0Lf",
- adjust_value (inexact_style, damt * 10) / 10);
- buflen = strlen (buf);
- nonintegerlen = 0;
- }
+ long double e = 1;
+ exponent = 0;
+
+ do
+ {
+ e *= base;
+ exponent++;
+ }
+ while (e * base <= damt && exponent < exponent_max);
+
+ damt /= e;
+
+ sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt));
+ buflen = strlen (buf);
+ nonintegerlen = decimal_pointlen + 1;
+
+ if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen
+ || ((opts & human_suppress_point_zero)
+ && buf[buflen - 1] == '0'))
+ {
+ sprintf (buf, "%.0Lf",
+ adjust_value (inexact_style, damt * 10) / 10);
+ buflen = strlen (buf);
+ nonintegerlen = 0;
+ }
}
p = psuffix - buflen;
@@ -282,77 +277,77 @@ human_readable (uintmax_t n, char *buf, int opts,
if (opts & human_autoscale)
{
- exponent = 0;
-
- if (base <= amt)
- {
- do
- {
- unsigned int r10 = (amt % base) * 10 + tenths;
- unsigned int r2 = (r10 % base) * 2 + (rounding >> 1);
- amt /= base;
- tenths = r10 / base;
- rounding = (r2 < base
- ? (r2 + rounding) != 0
- : 2 + (base < r2 + rounding));
- exponent++;
- }
- while (base <= amt && exponent < exponent_max);
-
- if (amt < 10)
- {
- if (inexact_style == human_round_to_nearest
- ? 2 < rounding + (tenths & 1)
- : inexact_style == human_ceiling && 0 < rounding)
- {
- tenths++;
- rounding = 0;
-
- if (tenths == 10)
- {
- amt++;
- tenths = 0;
- }
- }
-
- if (amt < 10
- && (tenths || ! (opts & human_suppress_point_zero)))
- {
- *--p = '0' + tenths;
- p -= decimal_pointlen;
- memcpy (p, decimal_point, decimal_pointlen);
- tenths = rounding = 0;
- }
- }
- }
+ exponent = 0;
+
+ if (base <= amt)
+ {
+ do
+ {
+ unsigned int r10 = (amt % base) * 10 + tenths;
+ unsigned int r2 = (r10 % base) * 2 + (rounding >> 1);
+ amt /= base;
+ tenths = r10 / base;
+ rounding = (r2 < base
+ ? (r2 + rounding) != 0
+ : 2 + (base < r2 + rounding));
+ exponent++;
+ }
+ while (base <= amt && exponent < exponent_max);
+
+ if (amt < 10)
+ {
+ if (inexact_style == human_round_to_nearest
+ ? 2 < rounding + (tenths & 1)
+ : inexact_style == human_ceiling && 0 < rounding)
+ {
+ tenths++;
+ rounding = 0;
+
+ if (tenths == 10)
+ {
+ amt++;
+ tenths = 0;
+ }
+ }
+
+ if (amt < 10
+ && (tenths || ! (opts & human_suppress_point_zero)))
+ {
+ *--p = '0' + tenths;
+ p -= decimal_pointlen;
+ memcpy (p, decimal_point, decimal_pointlen);
+ tenths = rounding = 0;
+ }
+ }
+ }
}
if (inexact_style == human_round_to_nearest
- ? 5 < tenths + (0 < rounding + (amt & 1))
- : inexact_style == human_ceiling && 0 < tenths + rounding)
+ ? 5 < tenths + (0 < rounding + (amt & 1))
+ : inexact_style == human_ceiling && 0 < tenths + rounding)
{
- amt++;
-
- if ((opts & human_autoscale)
- && amt == base && exponent < exponent_max)
- {
- exponent++;
- if (! (opts & human_suppress_point_zero))
- {
- *--p = '0';
- p -= decimal_pointlen;
- memcpy (p, decimal_point, decimal_pointlen);
- }
- amt = 1;
- }
+ amt++;
+
+ if ((opts & human_autoscale)
+ && amt == base && exponent < exponent_max)
+ {
+ exponent++;
+ if (! (opts & human_suppress_point_zero))
+ {
+ *--p = '0';
+ p -= decimal_pointlen;
+ memcpy (p, decimal_point, decimal_pointlen);
+ }
+ amt = 1;
+ }
}
integerlim = p;
do
{
- int digit = amt % 10;
- *--p = digit + '0';
+ int digit = amt % 10;
+ *--p = digit + '0';
}
while ((amt /= 10) != 0);
}
@@ -364,28 +359,28 @@ human_readable (uintmax_t n, char *buf, int opts,
if (opts & human_SI)
{
if (exponent < 0)
- {
- uintmax_t power;
- exponent = 0;
- for (power = 1; power < to_block_size; power *= base)
- if (++exponent == exponent_max)
- break;
- }
+ {
+ uintmax_t power;
+ exponent = 0;
+ for (power = 1; power < to_block_size; power *= base)
+ if (++exponent == exponent_max)
+ break;
+ }
if ((exponent | (opts & human_B)) && (opts & human_space_before_unit))
- *psuffix++ = ' ';
+ *psuffix++ = ' ';
if (exponent)
- *psuffix++ = (! (opts & human_base_1024) && exponent == 1
- ? 'k'
- : power_letter[exponent]);
+ *psuffix++ = (! (opts & human_base_1024) && exponent == 1
+ ? 'k'
+ : power_letter[exponent]);
if (opts & human_B)
- {
- if ((opts & human_base_1024) && exponent)
- *psuffix++ = 'i';
- *psuffix++ = 'B';
- }
+ {
+ if ((opts & human_base_1024) && exponent)
+ *psuffix++ = 'i';
+ *psuffix++ = 'B';
+ }
}
*psuffix = '\0';
@@ -426,54 +421,51 @@ humblock (char const *spec, uintmax_t *block_size, int *options)
else
{
if (*spec == '\'')
- {
- opts |= human_group_digits;
- spec++;
- }
+ {
+ opts |= human_group_digits;
+ spec++;
+ }
if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_opts)))
- {
- opts |= block_size_opts[i];
- *block_size = 1;
- }
+ {
+ opts |= block_size_opts[i];
+ *block_size = 1;
+ }
else
- {
- char *ptr;
- strtol_error e = xstrtoumax (spec, &ptr, 0, block_size,
- "eEgGkKmMpPtTyYzZ0");
- if (e != LONGINT_OK)
- {
- *options = 0;
- return e;
- }
- for (; ! ('0' <= *spec && *spec <= '9'); spec++)
- if (spec == ptr)
- {
- opts |= human_SI;
- if (ptr[-1] == 'B')
- opts |= human_B;
- if (ptr[-1] != 'B' || ptr[-2] == 'i')
- opts |= human_base_1024;
- break;
- }
- }
+ {
+ char *ptr;
+ strtol_error e = xstrtoumax (spec, &ptr, 0, block_size,
+ "eEgGkKmMpPtTyYzZ0");
+ if (e != LONGINT_OK)
+ {
+ *options = 0;
+ return e;
+ }
+ for (; ! ('0' <= *spec && *spec <= '9'); spec++)
+ if (spec == ptr)
+ {
+ opts |= human_SI;
+ if (ptr[-1] == 'B')
+ opts |= human_B;
+ if (ptr[-1] != 'B' || ptr[-2] == 'i')
+ opts |= human_base_1024;
+ break;
+ }
+ }
}
*options = opts;
return LONGINT_OK;
}
-int
-human_options (char const *spec, bool report_errors, uintmax_t *block_size)
+enum strtol_error
+human_options (char const *spec, int *opts, uintmax_t *block_size)
{
- int opts;
- strtol_error e = humblock (spec, block_size, &opts);
+ strtol_error e = humblock (spec, block_size, opts);
if (*block_size == 0)
{
*block_size = default_block_size ();
e = LONGINT_INVALID;
}
- if (e != LONGINT_OK && report_errors)
- STRTOL_FATAL_ERROR (spec, _("block size"), e);
- return opts;
+ return e;
}