summaryrefslogtreecommitdiffstats
path: root/util/argconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/argconfig.c')
-rw-r--r--util/argconfig.c264
1 files changed, 110 insertions, 154 deletions
diff --git a/util/argconfig.c b/util/argconfig.c
index 3eb885f..effeea2 100644
--- a/util/argconfig.c
+++ b/util/argconfig.c
@@ -42,18 +42,11 @@
#include <string.h>
#include <stdbool.h>
-#if __has_attribute(__fallthrough__)
-#define fallthrough __attribute__((__fallthrough__))
-#else
-#define fallthrough do {} while (0)
-#endif
-
-static argconfig_help_func *help_funcs[MAX_HELP_FUNC] = { NULL };
-
-static char END_DEFAULT[] = "__end_default__";
-
static const char *append_usage_str = "";
+static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option,
+ int index);
+
void argconfig_append_usage(const char *str)
{
append_usage_str = str;
@@ -168,11 +161,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
{
void *value = (void *)(char *)s->default_value;
char *endptr;
- const char *fopts = NULL;
- FILE *f;
int ret = 0;
- char **opts = ((char **)value);
- int remaining_space = CFG_MAX_SUBOPTS - 2;
switch (s->config_type) {
case CFG_STRING:
@@ -190,6 +179,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
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
@@ -201,6 +191,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
break;
case CFG_SHORT: {
unsigned long tmp = strtoul(optarg, &endptr, 0);
+
if (errno || tmp >= 1 << 16 || optarg == endptr)
ret = argconfig_error("short", option[index].name, optarg);
else
@@ -209,6 +200,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
}
case CFG_POSITIVE: {
uint32_t tmp = strtoul(optarg, &endptr, 0);
+
if (errno || optarg == endptr)
ret = argconfig_error("word", option[index].name, optarg);
else
@@ -224,7 +216,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
ret = argconfig_error("long integer", option[index].name, optarg);
break;
case CFG_LONG_SUFFIX:
- ret = suffix_binary_parse(optarg, &endptr, (uint64_t*)value);
+ ret = suffix_binary_parse(optarg, &endptr, (uint64_t *)value);
if (ret)
argconfig_error("long suffixed integer", option[index].name, optarg);
break;
@@ -233,48 +225,6 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
if (errno || optarg == endptr)
ret = argconfig_error("float", option[index].name, optarg);
break;
- case CFG_SUBOPTS:
- *opts = END_DEFAULT;
- opts += 2;
- ret = argconfig_parse_subopt_string(optarg, opts, remaining_space);
- if (ret) {
- if (ret == 2)
- fprintf(stderr, "Error Parsing Sub-Options: Too many options!\n");
- else
- fprintf(stderr, "Error Parsing Sub-Options\n");
- ret = -EINVAL;
- }
- break;
- case CFG_FILE_A:
- fopts = "a";
- fallthrough;
- case CFG_FILE_R:
- if (!fopts)
- fopts = "r";
- fallthrough;
- case CFG_FILE_W:
- if (!fopts)
- fopts = "w";
- fallthrough;
- case CFG_FILE_AP:
- if (!fopts)
- fopts = "a+";
- fallthrough;
- case CFG_FILE_RP:
- if (!fopts)
- fopts = "r+";
- fallthrough;
- case CFG_FILE_WP:
- if (!fopts)
- fopts = "w+";
- f = fopen(optarg, fopts);
- if (!f) {
- fprintf(stderr, "Unable to open %s file: %s\n", s->option, optarg);
- ret = -EINVAL;
- } else {
- *((FILE **)value) = f;
- }
- break;
case CFG_FLAG:
*((bool *)value) = true;
break;
@@ -285,9 +235,87 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
return ret;
}
+static int argconfig_get_val_len(struct argconfig_opt_val *opt_val, const char *str)
+{
+ struct argconfig_opt_val *v;
+ int len;
+ int match;
+
+ for (len = 1; len <= strlen(str); len++) {
+ match = 0;
+ for (v = opt_val; v && v->str; v++) {
+ if (!strncasecmp(str, v->str, len))
+ match++;
+ }
+ if (match == 1)
+ break;
+ }
+
+ return len;
+}
+
+static int argconfig_set_opt_val(enum argconfig_types type, union argconfig_val *opt_val, void *val)
+{
+ switch (type) {
+ case CFG_FLAG:
+ *(bool *)val = opt_val->bool_val;
+ break;
+ case CFG_LONG_SUFFIX:
+ *(uint64_t *)val = opt_val->long_suffix;
+ break;
+ case CFG_POSITIVE:
+ *(uint32_t *)val = opt_val->positive;
+ break;
+ case CFG_INT:
+ *(int *)val = opt_val->int_val;
+ break;
+ case CFG_LONG:
+ *(unsigned long *)val = opt_val->long_val;
+ break;
+ case CFG_DOUBLE:
+ *(double *)val = opt_val->double_val;
+ break;
+ case CFG_BYTE:
+ *(uint8_t *)val = opt_val->byte;
+ break;
+ case CFG_SHORT:
+ *(uint16_t *)val = opt_val->short_val;
+ break;
+ case CFG_INCREMENT:
+ *(int *)val = opt_val->increment;
+ break;
+ case CFG_STRING:
+ *(char **)val = opt_val->string;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option,
+ int index)
+{
+ const char *str = optarg;
+ void *val = s->default_value;
+ int len = strlen(optarg);
+ struct argconfig_opt_val *v;
+ int val_len;
+
+ for (v = s->opt_val; v && v->str; v++) {
+ val_len = argconfig_get_val_len(s->opt_val, v->str);
+ if (strncasecmp(str, v->str, len > val_len ? len : val_len))
+ continue;
+ return argconfig_set_opt_val(v->type, &v->val, val);
+ }
+
+ return argconfig_parse_type(s, option, index);
+}
+
bool argconfig_output_format_json(bool set)
{
- static bool output_format_json = false;
+ static bool output_format_json;
if (set)
output_format_json = true;
@@ -295,6 +323,18 @@ bool argconfig_output_format_json(bool set)
return output_format_json;
}
+static bool argconfig_check_output_format_json(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;
+ }
+
+ return false;
+}
+
int argconfig_parse(int argc, char *argv[], const char *program_desc,
struct argconfig_commandline_options *options)
{
@@ -368,94 +408,24 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
if (!s->default_value)
continue;
- ret = argconfig_parse_type(s, long_opts,option_index);
+ if (s->opt_val)
+ ret = argconfig_parse_val(s, long_opts, option_index);
+ else
+ ret = argconfig_parse_type(s, long_opts, option_index);
if (ret)
break;
}
+
+ if (argconfig_check_output_format_json(options))
+ argconfig_output_format_json(true);
+
out:
free(short_opts);
free(long_opts);
return ret;
}
-int argconfig_parse_subopt_string(char *string, char **options,
- size_t max_options)
-{
- char **o = options;
- char *tmp;
- size_t toklen;
-
- if (!string || !strlen(string)) {
- *(o++) = NULL;
- *(o++) = NULL;
- return 0;
- }
-
- tmp = calloc(strlen(string) + 2, 1);
- if (!tmp)
- return 1;
- strcpy(tmp, string);
-
- toklen = strcspn(tmp, "=");
-
- if (!toklen) {
- free(tmp);
- return 1;
- }
-
- *(o++) = tmp;
- tmp[toklen] = 0;
- tmp += toklen + 1;
-
- while (1) {
- if (*tmp == '"' || *tmp == '\'' || *tmp == '[' || *tmp == '(' ||
- *tmp == '{') {
-
- tmp++;
- toklen = strcspn(tmp, "\"'])}");
-
- if (!toklen)
- return 1;
-
- *(o++) = tmp;
- tmp[toklen] = 0;
- tmp += toklen + 1;
-
- toklen = strcspn(tmp, ";:,");
- tmp[toklen] = 0;
- tmp += toklen + 1;
- } else {
- toklen = strcspn(tmp, ";:,");
-
- if (!toklen)
- return 1;
-
- *(o++) = tmp;
- tmp[toklen] = 0;
- tmp += toklen + 1;
- }
-
- toklen = strcspn(tmp, "=");
-
- if (!toklen)
- break;
-
- *(o++) = tmp;
- tmp[toklen] = 0;
- tmp += toklen + 1;
-
- if ((o - options) > (max_options - 2))
- return 2;
- }
-
- *(o++) = NULL;
- *(o++) = NULL;
-
- return 0;
-}
-
-int argconfig_parse_comma_sep_array(char *string, int *val,
- unsigned max_length)
+int argconfig_parse_comma_sep_array(char *string, int *val, unsigned int max_length)
{
int ret = 0;
unsigned long v;
@@ -501,7 +471,7 @@ int argconfig_parse_comma_sep_array(char *string, int *val,
}
int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val,
- unsigned max_length)
+ unsigned int max_length)
{
int ret = 0;
unsigned long v;
@@ -545,9 +515,8 @@ int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val,
}
}
-int argconfig_parse_comma_sep_array_long(char *string,
- unsigned long long *val,
- unsigned max_length)
+int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val,
+ unsigned int max_length)
{
int ret = 0;
char *tmp;
@@ -580,19 +549,6 @@ int argconfig_parse_comma_sep_array_long(char *string,
}
}
-void argconfig_register_help_func(argconfig_help_func * f)
-{
- int i;
- for (i = 0; i < MAX_HELP_FUNC; i++) {
- if (help_funcs[i] == NULL) {
- help_funcs[i] = f;
- if (i < MAX_HELP_FUNC - 1)
- help_funcs[i + 1] = NULL;
- break;
- }
- }
-}
-
bool argconfig_parse_seen(struct argconfig_commandline_options *s,
const char *option)
{