aboutsummaryrefslogtreecommitdiff
path: root/arguments.c
diff options
context:
space:
mode:
Diffstat (limited to 'arguments.c')
-rw-r--r--arguments.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/arguments.c b/arguments.c
index 4b08de2c..46777f7f 100644
--- a/arguments.c
+++ b/arguments.c
@@ -108,6 +108,7 @@ args_value_as_string(struct args_value *value)
case ARGS_STRING:
return (value->string);
}
+ fatalx("unexpected argument type");
}
/* Create an empty arguments set. */
@@ -130,8 +131,9 @@ args_parse(const struct args_parse *parse, struct args_value *values,
u_int i;
enum args_parse_type type;
struct args_value *value, *new;
- u_char flag, argument;
+ u_char flag;
const char *found, *string, *s;
+ int optional_argument;
if (count == 0)
return (args_create());
@@ -168,18 +170,27 @@ args_parse(const struct args_parse *parse, struct args_value *values,
args_free(args);
return (NULL);
}
- argument = *++found;
- if (argument != ':') {
+ if (*++found != ':') {
log_debug("%s: -%c", __func__, flag);
args_set(args, flag, NULL);
continue;
}
+ if (*found == ':') {
+ optional_argument = 1;
+ found++;
+ }
new = xcalloc(1, sizeof *new);
if (*string != '\0') {
new->type = ARGS_STRING;
new->string = xstrdup(string);
} else {
if (i == count) {
+ if (optional_argument) {
+ log_debug("%s: -%c", __func__,
+ flag);
+ args_set(args, flag, NULL);
+ continue;
+ }
xasprintf(cause,
"-%c expects an argument",
flag);
@@ -753,6 +764,7 @@ args_make_commands(struct args_command_state *state, int argc, char **argv,
case CMD_PARSE_SUCCESS:
return (pr->cmdlist);
}
+ fatalx("invalid parse return state");
}
/* Free commands state. */
@@ -819,6 +831,12 @@ args_strtonum(struct args *args, u_char flag, long long minval,
return (0);
}
value = TAILQ_LAST(&entry->values, args_values);
+ if (value == NULL ||
+ value->type != ARGS_STRING ||
+ value->string == NULL) {
+ *cause = xstrdup("missing");
+ return (0);
+ }
ll = strtonum(value->string, minval, maxval, &errstr);
if (errstr != NULL) {
@@ -830,6 +848,41 @@ args_strtonum(struct args *args, u_char flag, long long minval,
return (ll);
}
+/* Convert an argument value to a number, and expand formats. */
+long long
+args_strtonum_and_expand(struct args *args, u_char flag, long long minval,
+ long long maxval, struct cmdq_item *item, char **cause)
+{
+ const char *errstr;
+ char *formatted;
+ long long ll;
+ struct args_entry *entry;
+ struct args_value *value;
+
+ if ((entry = args_find(args, flag)) == NULL) {
+ *cause = xstrdup("missing");
+ return (0);
+ }
+ value = TAILQ_LAST(&entry->values, args_values);
+ if (value == NULL ||
+ value->type != ARGS_STRING ||
+ value->string == NULL) {
+ *cause = xstrdup("missing");
+ return (0);
+ }
+
+ formatted = format_single_from_target(item, value->string);
+ ll = strtonum(formatted, minval, maxval, &errstr);
+ free(formatted);
+ if (errstr != NULL) {
+ *cause = xstrdup(errstr);
+ return (0);
+ }
+
+ *cause = NULL;
+ return (ll);
+}
+
/* Convert an argument to a number which may be a percentage. */
long long
args_percentage(struct args *args, u_char flag, long long minval,
@@ -886,3 +939,70 @@ args_string_percentage(const char *value, long long minval, long long maxval,
*cause = NULL;
return (ll);
}
+
+/*
+ * Convert an argument to a number which may be a percentage, and expand
+ * formats.
+ */
+long long
+args_percentage_and_expand(struct args *args, u_char flag, long long minval,
+ long long maxval, long long curval, struct cmdq_item *item, char **cause)
+{
+ const char *value;
+ struct args_entry *entry;
+
+ if ((entry = args_find(args, flag)) == NULL) {
+ *cause = xstrdup("missing");
+ return (0);
+ }
+ value = TAILQ_LAST(&entry->values, args_values)->string;
+ return (args_string_percentage_and_expand(value, minval, maxval, curval,
+ item, cause));
+}
+
+/*
+ * Convert a string to a number which may be a percentage, and expand formats.
+ */
+long long
+args_string_percentage_and_expand(const char *value, long long minval,
+ long long maxval, long long curval, struct cmdq_item *item, char **cause)
+{
+ const char *errstr;
+ long long ll;
+ size_t valuelen = strlen(value);
+ char *copy, *f;
+
+ if (value[valuelen - 1] == '%') {
+ copy = xstrdup(value);
+ copy[valuelen - 1] = '\0';
+
+ f = format_single_from_target(item, copy);
+ ll = strtonum(f, 0, 100, &errstr);
+ free(f);
+ free(copy);
+ if (errstr != NULL) {
+ *cause = xstrdup(errstr);
+ return (0);
+ }
+ ll = (curval * ll) / 100;
+ if (ll < minval) {
+ *cause = xstrdup("too small");
+ return (0);
+ }
+ if (ll > maxval) {
+ *cause = xstrdup("too large");
+ return (0);
+ }
+ } else {
+ f = format_single_from_target(item, value);
+ ll = strtonum(f, minval, maxval, &errstr);
+ free(f);
+ if (errstr != NULL) {
+ *cause = xstrdup(errstr);
+ return (0);
+ }
+ }
+
+ *cause = NULL;
+ return (ll);
+}