X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fopt%2Fhelpers.c;h=48f4fa45991ed1809438f55ae4f840485b0d3946;hp=a27be22f3d1a6475221a1b7fa86756f148fa68b9;hb=2179b06e713677476a5a37acbf179b8d5be8693b;hpb=babb23101ae447aefb65284b8f535f84e6a35008 diff --git a/ccan/opt/helpers.c b/ccan/opt/helpers.c index a27be22f..48f4fa45 100644 --- a/ccan/opt/helpers.c +++ b/ccan/opt/helpers.c @@ -1,6 +1,9 @@ /* Licensed under GPLv3+ - see LICENSE file for details */ #include +#include +#include #include +#include #include #include #include @@ -52,7 +55,7 @@ char *opt_set_invbool_arg(const char *arg, bool *b) /* Set a char *. */ char *opt_set_charp(const char *arg, char **p) { - *p = (char *)arg; + *p = cast_const(char *, arg); return NULL; } @@ -66,8 +69,8 @@ char *opt_set_intval(const char *arg, int *i) if (err) return err; *i = l; - /* Beware truncation... */ - if (*i != l) + /* Beware truncation, but don't generate untestable code. */ + if (sizeof(*i) != sizeof(l) && *i != l) return arg_bad("value '%s' does not fit into an integer", arg); return err; } @@ -123,12 +126,18 @@ char *opt_inc_intval(int *i) char *opt_version_and_exit(const char *version) { printf("%s\n", version); + /* Don't have valgrind complain! */ + opt_free_table(); exit(0); } char *opt_usage_and_exit(const char *extra) { - printf("%s", opt_usage(opt_argv0, extra)); + char *usage = opt_usage(opt_argv0, extra); + printf("%s", usage); + /* Don't have valgrind complain! */ + opt_alloc.free(usage); + opt_free_table(); exit(0); } @@ -258,7 +267,8 @@ static char * set_long_with_suffix(const char *arg, long *l, const long base) return err; *l = ll; - if (*l != ll) + /* Beware truncation, but don't generate untestable code. */ + if (sizeof(*l) != sizeof(ll) && *l != ll) return arg_bad("value '%s' does not fit into a long", arg); return NULL; } @@ -272,7 +282,8 @@ static char * set_ulong_with_suffix(const char *arg, unsigned long *ul, const lo if (ll < 0) return arg_bad("'%s' is negative but destination is unsigned", arg); *ul = ll; - if (*ul != ll) + /* Beware truncation, but don't generate untestable code. */ + if (sizeof(*ul) != sizeof(ll) && *ul != ll) return arg_bad("value '%s' does not fit into an unsigned long", arg); return NULL; } @@ -370,3 +381,116 @@ char * opt_set_uintval_si(const char *arg, unsigned int *u) { return set_uint_with_suffix(arg, u, 1000); } + +/*static helpers for showing values with kMGTPE suffixes. In this case there + are separate but essentially identical functions for signed and unsigned + values, so that unsigned values greater than LLONG_MAX get suffixes. + */ +static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll, + const long long base) +{ + const char *suffixes = "kMGTPE"; + int i; + if (ll == 0){ + /*zero is special because everything divides it (you'd get "0E")*/ + snprintf(buf, OPT_SHOW_LEN, "0"); + return; + } + for (i = 0; i < strlen(suffixes); i++){ + long long tmp = ll / base; + if (tmp * base != ll) + break; + ll = tmp; + } + if (i == 0) + snprintf(buf, OPT_SHOW_LEN, "%"PRId64, (int64_t)ll); + else + snprintf(buf, OPT_SHOW_LEN, "%"PRId64"%c", (int64_t)ll, suffixes[i - 1]); +} + +static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull, + const unsigned base) +{ + const char *suffixes = "kMGTPE"; + int i; + if (ull == 0){ + /*zero is special because everything divides it (you'd get "0E")*/ + snprintf(buf, OPT_SHOW_LEN, "0"); + return; + } + for (i = 0; i < strlen(suffixes); i++){ + unsigned long long tmp = ull / base; + if (tmp * base != ull) + break; + ull = tmp; + } + if (i == 0) + snprintf(buf, OPT_SHOW_LEN, "%"PRIu64, (uint64_t)ull); + else + snprintf(buf, OPT_SHOW_LEN, "%"PRIu64"%c", (uint64_t)ull, suffixes[i - 1]); +} + +/* _bi, signed */ +void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x) +{ + show_llong_with_suffix(buf, *x, 1024); +} + +void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x) +{ + show_llong_with_suffix(buf, *x, 1024); +} + +void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x) +{ + show_llong_with_suffix(buf, *x, 1024); +} + +/* _bi, unsigned */ +void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1024); +} + +void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1024); +} + +void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1024); +} + +/* _si, signed */ +void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x) +{ + show_llong_with_suffix(buf, (long long) *x, 1000); +} + +void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x) +{ + show_llong_with_suffix(buf, (long long) *x, 1000); +} + +void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x) +{ + show_llong_with_suffix(buf, *x, 1000); +} + +/* _si, unsigned */ +void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1000); +} + +void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1000); +} + +void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x) +{ + show_ullong_with_suffix(buf, (unsigned long long) *x, 1000); +} +