aboutsummaryrefslogtreecommitdiff
path: root/arguments.c
diff options
context:
space:
mode:
Diffstat (limited to 'arguments.c')
-rw-r--r--arguments.c63
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);
+}