debian: Final version of 64-bit time_t transition.
[lopsub.git] / lopsub.c
index 2ba26213c9c803f398208812b4069ea24321a3d4..b5017c32db1e45b87d3d765c19862503558421f9 100644 (file)
--- a/lopsub.c
+++ b/lopsub.c
@@ -155,7 +155,7 @@ static int xrealloc(void *p, size_t size)
        return 0;
 }
 
-/* Print a formated message to a dynamically allocated string. */
+/* Print a formatted message to a dynamically allocated string. */
 __attribute__ ((format (printf, 2, 0)))
 static int xvasprintf(char **result, const char *fmt, va_list ap)
 {
@@ -632,17 +632,23 @@ static int lls_parse_arg(struct lls_arg *la, const struct lls_option *opts,
        bool multiple;
        int idx, ret;
 
-       if (!la->arg)
-               goto success;
-       if (opt->arg_info == LLS_NO_ARGUMENT) {
+       if (la->arg && opt->arg_info == LLS_NO_ARGUMENT) {
                xasprintf(errctx, "arg: %s, option: %s", la->arg, opt->name);
                return -E_LLS_ARG_GIVEN;
        }
        multiple = opt->flags & LLS_MULTIPLE;
+       if (opt->arg_type == LLS_STRING && !opt->values && !multiple) {
+               if (lor->value) { /* discard previous value */
+                       free(lor->value[0].string_val);
+                       free(lor->value);
+                       lor->value = NULL;
+               }
+       }
+       if (!la->arg)
+               goto success;
        idx = multiple? lor->given : 0;
-       if (lor->given == 0 || multiple) {
-               ret = xrealloc(&lor->value,
-                       (lor->given + 1) * sizeof(*lor->value));
+       if (!lor->value || multiple) {
+               ret = xrealloc(&lor->value, (idx + 1) * sizeof(*lor->value));
                if (ret < 0) {
                        xasprintf(errctx, "option value array for --%s",
                                opt->name);
@@ -651,8 +657,6 @@ static int lls_parse_arg(struct lls_arg *la, const struct lls_option *opts,
        }
        switch (opt->arg_type) {
        case LLS_STRING:
-               if (lor->given > 0 && !multiple)
-                       free(lor->value[idx].string_val);
                if (opt->values) {
                        ret = check_enum_arg(la->arg, opt, errctx);
                        if (ret < 0)
@@ -724,9 +728,11 @@ int lls_check_arg_count(const struct lls_parse_result *lpr,
 {
        if (errctx)
                *errctx = NULL;
+       assert(min_argc <= max_argc);
        if (lpr->num_inputs < min_argc) {
-               xasprintf(errctx, "at least %u non-option args required, "
-                       "%u given", min_argc, lpr->num_inputs);
+               xasprintf(errctx, "%s %u non-option args required, %u given",
+                       min_argc < max_argc? "at least" : "exactly",
+                       min_argc, lpr->num_inputs);
                return -E_LLS_BAD_ARG_COUNT;
        }
        if (lpr->num_inputs > max_argc) {
@@ -734,8 +740,11 @@ int lls_check_arg_count(const struct lls_parse_result *lpr,
                        xasprintf(errctx, "no non-option args allowed, "
                                "%u given", lpr->num_inputs);
                else
-                       xasprintf(errctx, "at most %u non-option args allowed, "
-                               "%u given", max_argc, lpr->num_inputs);
+                       xasprintf(errctx, "%s %u non-option args %s, %u given",
+                               min_argc < max_argc? "at most" : "exactly",
+                               max_argc,
+                               min_argc < max_argc? "allowed" : "required",
+                               lpr->num_inputs);
                return -E_LLS_BAD_ARG_COUNT;
        }
        return 1;
@@ -1296,6 +1305,7 @@ int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd,
                                if (!lor->value[j].string_val) {
                                        for (; j >= 0; j--)
                                                free(lor->value[j].string_val);
+                                       free(lor->value);
                                        goto free_options;
                                }
                                p += strlen(lor->value[j].string_val) + 1;
@@ -1313,7 +1323,7 @@ int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd,
        *lprp = lpr;
        return 1;
 free_options:
-       for (; i >= 0; i--) {
+       for (i--; i >= 0; i--) {
                const struct lls_option *opt = cmd->options + i;
                struct lls_opt_result *lor = lpr->opt_result + i;
                unsigned num_vals = (opt->flags & LLS_MULTIPLE)? lor->given : 1;