diff options
Diffstat (limited to 'arguments.c')
-rw-r--r-- | arguments.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/arguments.c b/arguments.c index e2d18980..e1956ace 100644 --- a/arguments.c +++ b/arguments.c @@ -215,8 +215,10 @@ args_escape(const char *s) char *escaped, *result; int flags; - if (*s == '\0') - return (xstrdup(s)); + if (*s == '\0') { + xasprintf(&result, "''"); + return (result); + } if (s[0] != ' ' && (strchr(quoted, s[0]) != NULL || s[0] == '~') && s[1] == '\0') { @@ -343,3 +345,60 @@ args_strtonum(struct args *args, u_char ch, long long minval, long long maxval, *cause = NULL; return (ll); } + +/* Convert an argument to a number which may be a percentage. */ +long long +args_percentage(struct args *args, u_char ch, long long minval, + long long maxval, long long curval, char **cause) +{ + const char *value; + struct args_entry *entry; + + if ((entry = args_find(args, ch)) == NULL) { + *cause = xstrdup("missing"); + return (0); + } + value = TAILQ_LAST(&entry->values, args_values)->value; + return (args_string_percentage(value, minval, maxval, curval, cause)); +} + +/* Convert a string to a number which may be a percentage. */ +long long +args_string_percentage(const char *value, long long minval, long long maxval, + long long curval, char **cause) +{ + const char *errstr; + long long ll; + size_t valuelen = strlen(value); + char *copy; + + if (value[valuelen - 1] == '%') { + copy = xstrdup(value); + copy[valuelen - 1] = '\0'; + + ll = strtonum(copy, 0, 100, &errstr); + free(copy); + if (errstr != NULL) { + *cause = xstrdup(errstr); + return (0); + } + ll = (curval * ll) / 100; + if (ll < minval) { + *cause = xstrdup("too large"); + return (0); + } + if (ll > maxval) { + *cause = xstrdup("too small"); + return (0); + } + } else { + ll = strtonum(value, minval, maxval, &errstr); + if (errstr != NULL) { + *cause = xstrdup(errstr); + return (0); + } + } + + *cause = NULL; + return (ll); +} |