diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/argconfig.c | 96 | ||||
-rw-r--r-- | util/argconfig.h | 10 | ||||
-rw-r--r-- | util/cleanup.h | 16 | ||||
-rw-r--r-- | util/json.h | 10 | ||||
-rw-r--r-- | util/types.c | 7 |
5 files changed, 96 insertions, 43 deletions
diff --git a/util/argconfig.c b/util/argconfig.c index effeea2..5ec3d6f 100644 --- a/util/argconfig.c +++ b/util/argconfig.c @@ -41,6 +41,7 @@ #include <stdarg.h> #include <string.h> #include <stdbool.h> +#include <locale.h> static const char *append_usage_str = ""; @@ -163,6 +164,8 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct char *endptr; int ret = 0; + errno = 0; /* To distinguish success/failure after strtol/stroul call */ + switch (s->config_type) { case CFG_STRING: *((char **)value) = optarg; @@ -177,15 +180,6 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct if (errno || optarg == endptr) ret = argconfig_error("integer", option[index].name, optarg); break; - case CFG_BOOL: { - int tmp = strtol(optarg, &endptr, 0); - - if (errno || tmp < 0 || tmp > 1 || optarg == endptr) - ret = argconfig_error("0 or 1", option[index].name, optarg); - else - *((int *)value) = tmp; - break; - } case CFG_BYTE: ret = argconfig_parse_byte(option[index].name, optarg, (uint8_t *)value); break; @@ -313,23 +307,11 @@ static int argconfig_parse_val(struct argconfig_commandline_options *s, struct o return argconfig_parse_type(s, option, index); } -bool argconfig_output_format_json(bool set) -{ - static bool output_format_json; - - if (set) - output_format_json = true; - - return output_format_json; -} - -static bool argconfig_check_output_format_json(struct argconfig_commandline_options *s) +static bool argconfig_check_human_readable(struct argconfig_commandline_options *s) { for (; s && s->option; s++) { - if (strcmp(s->option, "output-format") || s->config_type != CFG_STRING) - continue; - if (!strcmp(*(char **)s->default_value, "json")) - return true; + if (!strcmp(s->option, "human-readable") && s->config_type == CFG_FLAG) + return s->seen; } return false; @@ -375,14 +357,10 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, } long_opts[option_index].name = "help"; - long_opts[option_index++].val = 'h'; - - long_opts[option_index].name = "json"; - long_opts[option_index].val = 'j'; + long_opts[option_index].val = 'h'; short_opts[short_index++] = '?'; - short_opts[short_index++] = 'h'; - short_opts[short_index] = 'j'; + short_opts[short_index] = 'h'; optind = 0; while ((c = getopt_long_only(argc, argv, short_opts, long_opts, &option_index)) != -1) { @@ -392,8 +370,6 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, ret = -EINVAL; break; } - if (c == 'j') - argconfig_output_format_json(true); for (option_index = 0; option_index < options_count; option_index++) { if (c == options[option_index].short_option) break; @@ -416,8 +392,8 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, break; } - if (argconfig_check_output_format_json(options)) - argconfig_output_format_json(true); + if (!argconfig_check_human_readable(options)) + setlocale(LC_ALL, "C"); out: free(short_opts); @@ -549,6 +525,58 @@ int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val, } } +#define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(size) \ +int argconfig_parse_comma_sep_array_u##size(char *string, \ + __u##size *val, \ + unsigned int max_length) \ +{ \ + int ret = 0; \ + uintmax_t v; \ + char *tmp; \ + char *p; \ + \ + if (!string || !strlen(string)) \ + return 0; \ + \ + tmp = strtok(string, ","); \ + if (!tmp) \ + return 0; \ + \ + v = strtoumax(tmp, &p, 0); \ + if (*p != 0) \ + return -1; \ + if (v > UINT##size##_MAX) { \ + fprintf(stderr, "%s out of range\n", tmp); \ + return -1; \ + } \ + val[ret] = v; \ + \ + ret++; \ + while (1) { \ + tmp = strtok(NULL, ","); \ + \ + if (tmp == NULL) \ + return ret; \ + \ + if (ret >= max_length) \ + return -1; \ + \ + v = strtoumax(tmp, &p, 0); \ + if (*p != 0) \ + return -1; \ + if (v > UINT##size##_MAX) { \ + fprintf(stderr, "%s out of range\n", tmp); \ + return -1; \ + } \ + val[ret] = v; \ + ret++; \ + } \ +} + +DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(16); +DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(32); +DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(64); + bool argconfig_parse_seen(struct argconfig_commandline_options *s, const char *option) { diff --git a/util/argconfig.h b/util/argconfig.h index eaf8375..2a04a32 100644 --- a/util/argconfig.h +++ b/util/argconfig.h @@ -41,6 +41,8 @@ #include <stdbool.h> #include <stdint.h> +#include <linux/types.h> + enum argconfig_types { CFG_FLAG, CFG_STRING, @@ -49,7 +51,6 @@ enum argconfig_types { CFG_LONG, CFG_LONG_SUFFIX, CFG_DOUBLE, - CFG_BOOL, CFG_BYTE, CFG_SHORT, CFG_POSITIVE, @@ -174,10 +175,15 @@ int argconfig_parse_comma_sep_array_short(char *string, unsigned short *ret, unsigned int max_length); int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *ret, unsigned int max_length); +int argconfig_parse_comma_sep_array_u16(char *string, __u16 *val, + unsigned int max_length); +int argconfig_parse_comma_sep_array_u32(char *string, __u32 *val, + unsigned int max_length); +int argconfig_parse_comma_sep_array_u64(char *string, __u64 *val, + unsigned int max_length); int argconfig_parse_byte(const char *opt, const char *str, unsigned char *val); void print_word_wrapped(const char *s, int indent, int start, FILE *stream); bool argconfig_parse_seen(struct argconfig_commandline_options *options, const char *option); -bool argconfig_output_format_json(bool set); #endif diff --git a/util/cleanup.h b/util/cleanup.h index 575a25d..9227856 100644 --- a/util/cleanup.h +++ b/util/cleanup.h @@ -2,6 +2,9 @@ #ifndef __CLEANUP_H #define __CLEANUP_H +#include <unistd.h> +#include <stdlib.h> + #define __cleanup__(fn) __attribute__((cleanup(fn))) #define DECLARE_CLEANUP_FUNC(name, type) \ @@ -16,4 +19,17 @@ DECLARE_CLEANUP_FUNC(name, type) \ DECLARE_CLEANUP_FUNC(cleanup_charp, char *); +static inline void freep(void *p) +{ + free(*(void**) p); +} +#define _cleanup_free_ __cleanup__(freep) + +static inline void close_file(int *f) +{ + if (*f >= 0) + close(*f); +} +#define _cleanup_file_ __cleanup__(close_file) + #endif diff --git a/util/json.h b/util/json.h index c362408..54e33e3 100644 --- a/util/json.h +++ b/util/json.h @@ -28,16 +28,18 @@ json_object_object_add(o, k, util_json_object_new_double(v)) #define json_object_add_value_float(o, k, v) \ json_object_object_add(o, k, json_object_new_double(v)) -#define json_object_add_value_string(o, k, v) \ - json_object_object_add(o, k, json_object_new_string(v)) +static inline int json_object_add_value_string(struct json_object *o, const char *k, const char *v) { + return json_object_object_add(o, k, v ? json_object_new_string(v) : NULL); +} #define json_object_add_value_array(o, k, v) \ json_object_object_add(o, k, v) #define json_object_add_value_object(o, k, v) \ json_object_object_add(o, k, v) #define json_array_add_value_object(o, k) \ json_object_array_add(o, k) -#define json_array_add_value_string(o, v) \ - json_object_array_add(o, json_object_new_string(v)) +static inline int json_array_add_value_string(struct json_object *o, const char *v) { + return json_object_array_add(o, v ? json_object_new_string(v) : NULL); +} #define json_print_object(o, u) \ printf("%s", json_object_to_json_string_ext(o, \ JSON_C_TO_STRING_PRETTY | \ diff --git a/util/types.c b/util/types.c index 044391d..376c734 100644 --- a/util/types.c +++ b/util/types.c @@ -67,20 +67,21 @@ static char *__uint128_t_to_string(nvme_uint128_t val, bool l10n) int idx = 60; __u64 div, rem; char *sep = NULL; - int i, len = 0; + int i, len = 0, cl = 0; if (l10n) { sep = localeconv()->thousands_sep; len = strlen(sep); + cl = 1; } /* terminate at the end, and build up from the ones */ str[--idx] = '\0'; do { - if (len && !((sizeof(str) - idx) % (3 + len))) { + if (len && !((sizeof(str) - idx) % (3 + cl))) { for (i = 0; i < len; i++) - str[--idx] = sep[i]; + str[--idx] = sep[len - i - 1]; } rem = val.words[0]; |