2 * Copyright (C) 2016 Andre Noll <maan@tuebingen.mpg.de>
4 * Licensed under the LGPL v3, see https://www.gnu.org/licenses/lgpl-3.0.html
16 #include "lopsub-internal.h"
19 /* For detecting version mismatches, see lopsub-internal.h. */
20 const unsigned LLS_ABI_VERSION_VAR = 0;
22 #define FOR_EACH_OPTION(_i, _opts) \
23 for (_i = 0; (_opts) && (_opts)[(_i)].name; (_i)++)
25 #define FOR_EACH_OPTION_IN_COMMAND(_opt, _cmd) \
27 (_opt) = (_cmd)->options; \
28 (_opt) && (_opt) < (_cmd)->options + (_cmd)->num_options; \
32 /* The result of parsing one option and its arguments. */
34 int idx; /* index into either argv[] or the lls_option array. */
35 const char *arg; /* NULL if option has no argument. */
39 * This structure, and the exchange_args(), decode_option() and parse_option()
40 * functions below are inspired by the glibc implementation of getopt.c,
41 * Copyright (C) 1987-2015 Free Software Foundation, Inc.
44 const struct lls_option *opts;
48 int optind; /* index into argv[] which we are parsing. */
49 const char *next_char;
51 * These describe the part of argv[] that contains non-options that
52 * have been skipped. first_nonopt is the index in argv[] of the first
53 * of them, last_nonopt is the index after the last of them. Initially
54 * both indices are zero.
60 const struct lls_command *lls_cmd(unsigned cmd_num,
61 const struct lls_suite *suite)
63 if (cmd_num > suite->num_subcommands)
65 return suite->commands + cmd_num;
68 const char *lls_command_name(const struct lls_command *cmd)
73 const void *lls_user_data(const struct lls_command *cmd)
75 return cmd->user_data;
78 const struct lls_option *lls_opt(unsigned opt_num,
79 const struct lls_command *cmd)
81 return cmd->options + opt_num;
84 const struct lls_opt_result *lls_opt_result(unsigned opt_num,
85 const struct lls_parse_result *lpr)
87 return lpr->opt_result + opt_num;
90 unsigned lls_opt_given(const struct lls_opt_result *r)
95 const char *lls_enum_string_val(unsigned idx, const struct lls_option *opt)
97 return opt->values[idx].string_val;
100 const char *lls_string_val(unsigned idx, const struct lls_opt_result *r)
102 return r->value[idx].string_val;
105 int32_t lls_int32_val(unsigned idx, const struct lls_opt_result *r)
107 return r->value[idx].int32_val;
110 uint32_t lls_uint32_val(unsigned idx, const struct lls_opt_result *r)
112 return r->value[idx].uint32_val;
115 int64_t lls_int64_val(unsigned idx, const struct lls_opt_result *r)
117 return r->value[idx].int64_val;
120 uint64_t lls_uint64_val(unsigned idx, const struct lls_opt_result *r)
122 return r->value[idx].uint64_val;
125 unsigned lls_num_inputs(const struct lls_parse_result *lpr)
127 return lpr->num_inputs;
130 const char *lls_purpose(const struct lls_command *cmd)
135 const char *lls_input(unsigned input_num, const struct lls_parse_result *lpr)
137 return lpr->inputs[input_num];
140 const char *lls_strerror(int lss_errno)
142 #define LLS_ERROR(_n, _s) _s,
143 static const char * const error_string[] = {LLS_ERRORS NULL};
145 return error_string[lss_errno];
148 static int xrealloc(void *p, size_t size)
150 void **pp = p, *newp = realloc(*pp, size);
158 /* Print a formatted message to a dynamically allocated string. */
159 __attribute__ ((format (printf, 2, 0)))
160 static int xvasprintf(char **result, const char *fmt, va_list ap)
170 *result = malloc(size + 1);
174 ret = vsnprintf(*result, size, fmt, aq);
177 if (ret < size) /* OK */
180 ret = xrealloc(result, size);
187 ret = vsnprintf(*result, size, fmt, aq);
189 assert(ret >= 0 && ret < size);
193 /* Print to a dynamically allocated string, variable number of arguments. */
194 __attribute__ ((format (printf, 2, 3)))
195 static int xasprintf(char **result, const char *fmt, ...)
201 ret = xvasprintf(result, fmt, ap);
206 static inline unsigned num_vals_in_parse_result(const struct lls_command *cmd,
207 int opt_num, const struct lls_parse_result *lpr)
209 const struct lls_option *opt = cmd->options + opt_num;
210 struct lls_opt_result *lor = lpr->opt_result + opt_num;
212 if (opt->arg_info == LLS_NO_ARGUMENT)
215 return 1; /* for the default value */
216 if (!(opt->flags & LLS_MULTIPLE))
228 enum atoi_mode {ATOI_INT32, ATOI_UINT32, ATOI_INT64, ATOI_UINT64};
231 * Convert a string to a 32 or 64 bit signed or unsigned integer value.
233 * For conversions to unsigned integers, negative values are considered valid
234 * input and are silently converted.
236 static int lls_atoi(const char *str, enum atoi_mode mode, union atoi_result *value)
239 union atoi_result result;
241 memset(value, 0, sizeof(*value));
242 errno = 0; /* To distinguish success/failure after call */
244 * We pass zero as the base to strtoll(3) and strtoull(3) to let the
245 * function recognize an optional base prefix like "0x".
247 if (mode == ATOI_UINT64) {
248 unsigned long long tmp = strtoull(str, &endptr, 0);
249 if (errno == ERANGE && tmp == ULLONG_MAX)
250 return -E_LLS_OVERFLOW;
252 } else { /* parse as signed 64 bit and check range */
253 long long tmp = strtoll(str, &endptr, 0);
254 if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN))
255 return -E_LLS_OVERFLOW;
257 case ATOI_INT64: /* no additional range check necessary */
261 if (tmp < INT_MIN || tmp > INT_MAX)
262 return -E_LLS_OVERFLOW;
267 return -E_LLS_OVERFLOW;
275 * If there were no digits at all, strtol() and friends store the
276 * original value of str in *endptr.
279 return -E_LLS_NO_DIGITS;
281 * The implementation may also set errno (and return 0) in case no
282 * conversion was performed.
285 return -E_LLS_NO_DIGITS;
286 if (*endptr != '\0') /* Further characters after number */
287 return -E_LLS_TRAILING_GARBAGE;
292 static int atoi32(const char *str, int32_t *result)
294 union atoi_result ar;
295 int ret = lls_atoi(str, ATOI_INT32, &ar);
300 static int atou32(const char *str, uint32_t *result)
302 union atoi_result ar;
303 int ret = lls_atoi(str, ATOI_UINT32, &ar);
308 static int atoi64(const char *str, int64_t *result)
310 union atoi_result ar;
311 int ret = lls_atoi(str, ATOI_INT64, &ar);
316 static int atou64(const char *str, uint64_t *result)
318 union atoi_result ar;
319 int ret = lls_atoi(str, ATOI_UINT64, &ar);
324 static void free_opt_result(int opt_num, struct lls_parse_result *lpr,
325 const struct lls_command *cmd)
327 const struct lls_option *opt = cmd->options + opt_num;
329 if (opt->arg_type == LLS_STRING && !opt->values) {
330 unsigned num_vals = num_vals_in_parse_result(cmd, opt_num, lpr);
332 for (j = 0; j < num_vals; j++)
333 if (lpr->opt_result[opt_num].value)
334 free(lpr->opt_result[opt_num].value[j].string_val);
336 if (opt->arg_info != LLS_NO_ARGUMENT)
337 free(lpr->opt_result[opt_num].value);
340 void lls_free_parse_result(struct lls_parse_result *lpr,
341 const struct lls_command *cmd)
348 for (i = 0; i < lpr->num_inputs; i++)
349 free(lpr->inputs[i]);
352 FOR_EACH_OPTION(i, cmd->options)
353 free_opt_result(i, lpr, cmd);
354 free(lpr->opt_result);
358 static struct lls_data *init_lls_data(const struct lls_option *opts,
359 int argc, char *const *argv)
361 struct lls_data *d = malloc(sizeof(*d));
366 /* start with an empty non-option list */
367 d->first_nonopt = d->last_nonopt = d->optind;
376 * Exchange two adjacent subsets of argv[].
378 * One subset is given by indices {first_nonopt, ..., last_nonopt - 1}. It
379 * contains all the non-options that have been skipped so far. The other subset
380 * corresponds to indices {last_nonopt, ... optind - 1} which contains all the
381 * options processed since those non-options were skipped.
383 * Before the function returns, ->first_nonopt and ->last_nonopt are updated to
384 * describe the new set of non-options in argv[].
386 static void exchange_args(struct lls_data *d)
388 int bottom = d->first_nonopt;
389 int middle = d->last_nonopt;
391 char **argv = (char **)d->argv;
394 * Exchange the shorter segment with the far end of the longer segment.
395 * That puts the shorter segment into the right place. It leaves the
396 * longer segment in the right place overall, but it consists of two
397 * parts that need to be swapped next.
399 while (top > middle && middle > bottom) {
400 if (top - middle > middle - bottom) {
401 /* Bottom segment is the short one. */
402 int i, len = middle - bottom;
404 /* Swap it with the top part of the top segment. */
405 for (i = 0; i < len; i++) {
406 char *tmp = argv[bottom + i];
407 argv[bottom + i] = argv[top - (middle - bottom) + i];
408 argv[top - (middle - bottom) + i] = tmp;
410 /* Exclude the moved bottom segment from further swapping. */
413 /* Top segment is the short one. */
414 int i, len = top - middle;
415 /* Swap it with the bottom part of the bottom segment. */
416 for (i = 0; i < len; i++) {
417 char *tmp = argv[bottom + i];
418 argv[bottom + i] = argv[middle + i];
419 argv[middle + i] = tmp;
421 /* Exclude the moved top segment from further swapping. */
425 /* Update records for the slots the non-options now occupy. */
426 d->first_nonopt += d->optind - d->last_nonopt;
427 d->last_nonopt = d->optind;
430 /* whether arg points to an option argument */
431 static inline bool is_option(const char *arg)
433 return arg[0] == '-' && arg[1] != '\0';
436 static void check_errctx(char **errctx, int ret)
441 assert(!*errctx); /* memory leak/uninitialized pointer */
442 else if (ret != -E_LLS_NOMEM)
443 assert(*errctx); /* we must provide an error message */
447 * Decode the current option. On success, set result->idx to the index in the
448 * ->options array which was decoded successfully. On failure, result->idx is
449 * the index in argv[] which could not be parsed.
451 static int decode_option(struct lls_data *d, struct lls_arg *result,
454 const char *word = d->argv[d->optind], *cur, *end;
457 const struct lls_option *match = NULL;
458 bool ambig = false, shortopt;
460 assert(word[0] != '\0');
461 shortopt = word[1] != '-';
462 result->idx = d->optind;
468 cur = word + 1 + !shortopt; /* skip dash(es) */
469 for (end = cur; *end && *end != '='; end++)
473 /* test all options for exact or abbreviated matches */
474 FOR_EACH_OPTION(i, d->opts) {
475 const struct lls_option *opt = d->opts + i;
476 if (opt->flags & LLS_IGNORED)
479 if (*cur != opt->short_opt)
482 d->next_char = cur + 1;
483 if (d->next_char[0] == '\0' || d->next_char[0] == '=')
487 if (strncmp(opt->name, cur, len) != 0)
489 if (strlen(opt->name) == len) { /* exact match */
493 if (match) { /* second non-exact match */
497 /* first non-exact match */
500 if (!match) { /* option not found */
501 xasprintf(errctx, "error token: %s", cur);
502 return -E_LLS_BAD_OPTION;
505 xasprintf(errctx, "%s", word);
506 return -E_LLS_AMBIG_OPTION;
509 if (match->arg_info == LLS_REQUIRED_ARGUMENT) {
510 xasprintf(errctx, "--%s", match->name);
511 return -E_LLS_NO_ARG_GIVEN;
518 if (match->arg_info == LLS_NO_ARGUMENT) {
519 xasprintf(errctx, "--%s", match->name);
520 return -E_LLS_ARG_GIVEN;
522 result->arg = end + 1;
523 } else if (match->arg_info == LLS_REQUIRED_ARGUMENT) {
524 if (d->optind >= d->argc) {
525 xasprintf(errctx, "--%s", match->name);
526 return -E_LLS_NO_ARG_GIVEN;
528 result->arg = d->argv[d->optind++];
532 result->idx = match - d->opts;
537 * Parse one option, including its argument (if any).
539 * We permute the contents of ARGV as we scan, so that eventually all the
540 * non-options are at the end. This allows options to be given in any order.
542 * Returns zero on end-of-argv, negative on errors, one if an option was parsed
543 * successfully. The structure pointed to by result is initialized as follows:
545 * end-of-args case: ->idx is the index of first non-option in argv[], ->arg is
548 * error case: ->idx is the index of the first problematic option in argv. ->arg is
549 * argv[result->idx] as in the end-of-args case.
551 * success case: ->idx is the index into the option array which corresponds to
552 * the option that was parsed successfully, ->arg its argument, or NULL if no
553 * argument was given.
555 * After this function returned non-positive, it must not be called again.
557 static int parse_option(struct lls_data *d, struct lls_arg *result, char **errctx)
559 assert(d->last_nonopt <= d->optind);
560 assert(d->first_nonopt <= d->optind);
563 return decode_option(d, result, errctx);
565 * If we have just processed some options following some non-options,
566 * exchange them so that the options come first.
568 if (d->first_nonopt != d->last_nonopt && d->last_nonopt != d->optind)
570 else if (d->last_nonopt != d->optind)
571 d->first_nonopt = d->optind;
573 * Skip any additional non-options and extend the range of non-options
574 * previously skipped.
576 while (d->optind < d->argc && !is_option(d->argv[d->optind]))
578 d->last_nonopt = d->optind;
580 * The special argument `--' forces an end of option-scanning. We skip
581 * it like a null option, then exchange it with previous non-options as
582 * if it were an option. Then we skip everything else like a non-option.
584 if (d->optind != d->argc && !strcmp(d->argv[d->optind], "--")) {
586 if (d->first_nonopt != d->last_nonopt && d->last_nonopt != d->optind)
588 else if (d->first_nonopt == d->last_nonopt)
589 d->first_nonopt = d->optind;
590 d->last_nonopt = d->argc;
594 * If we have done all the argv elements, stop the scan and back over
595 * any non-options that we skipped and permuted.
597 if (d->optind == d->argc) {
599 * Set the index to point at the non-options that we
600 * previously skipped.
602 result->idx = d->first_nonopt;
603 result->arg = d->argv[result->idx];
606 assert(is_option(d->argv[d->optind]));
607 return decode_option(d, result, errctx);
610 static int check_enum_arg(const char *arg, const struct lls_option *opt,
616 for (i = 0; (val = opt->values[i].string_val); i++)
617 if (!strcmp(arg, val))
619 xasprintf(errctx, "arg: %s, option: %s", arg, opt->name);
624 * Increase the "given" count and store argument if the option takes one.
625 * Allocates or reallocates the ->value array of struct lls_opt_result in lpr.
627 static int lls_parse_arg(struct lls_arg *la, const struct lls_option *opts,
628 struct lls_parse_result *lpr, char **errctx)
630 const struct lls_option *opt = opts + la->idx;
631 struct lls_opt_result *lor = lpr->opt_result + la->idx;
635 if (la->arg && opt->arg_info == LLS_NO_ARGUMENT) {
636 xasprintf(errctx, "arg: %s, option: %s", la->arg, opt->name);
637 return -E_LLS_ARG_GIVEN;
639 multiple = opt->flags & LLS_MULTIPLE;
640 if (opt->arg_type == LLS_STRING && !opt->values && !multiple) {
641 if (lor->value) { /* discard previous value */
642 free(lor->value[0].string_val);
649 idx = multiple? lor->given : 0;
650 if (!lor->value || multiple) {
651 ret = xrealloc(&lor->value, (idx + 1) * sizeof(*lor->value));
653 xasprintf(errctx, "option value array for --%s",
658 switch (opt->arg_type) {
661 ret = check_enum_arg(la->arg, opt, errctx);
664 lor->value[idx].uint32_val = ret;
666 lor->value[idx].string_val = strdup(la->arg);
667 if (!lor->value[idx].string_val) {
668 xasprintf(errctx, "string value for %s",
675 ret = atoi32(la->arg, &lor->value[idx].int32_val);
680 ret = atou32(la->arg, &lor->value[idx].uint32_val);
685 ret = atoi64(la->arg, &lor->value[idx].int64_val);
690 ret = atou64(la->arg, &lor->value[idx].uint64_val);
702 xasprintf(errctx, "conversion error for argument \"%s\" to option --%s",
707 static int copy_val(union lls_val *dst, const union lls_val *src,
708 const struct lls_option *opt, char **errctx)
710 if (opt->arg_type != LLS_STRING || opt->values) {
714 if (!src->string_val) {
715 dst->string_val = NULL;
718 dst->string_val = strdup(src->string_val);
719 if (!dst->string_val) {
720 xasprintf(errctx, "copy value for --%s", opt->name);
726 int lls_check_arg_count(const struct lls_parse_result *lpr,
727 int min_argc, int max_argc, char **errctx)
731 assert(min_argc <= max_argc);
732 if (lpr->num_inputs < min_argc) {
733 xasprintf(errctx, "%s %u non-option args required, %u given",
734 min_argc < max_argc? "at least" : "exactly",
735 min_argc, lpr->num_inputs);
736 return -E_LLS_BAD_ARG_COUNT;
738 if (lpr->num_inputs > max_argc) {
740 xasprintf(errctx, "no non-option args allowed, "
741 "%u given", lpr->num_inputs);
743 xasprintf(errctx, "%s %u non-option args %s, %u given",
744 min_argc < max_argc? "at most" : "exactly",
746 min_argc < max_argc? "allowed" : "required",
748 return -E_LLS_BAD_ARG_COUNT;
754 * Unlike getopt(3) this implementation can not resume the scan where it left
757 int lls_parse(int argc, char **argv, const struct lls_command *cmd,
758 struct lls_parse_result **lprp, char **errctx)
760 const struct lls_option *opts = cmd->options;
761 struct lls_data *d = NULL;
764 struct lls_parse_result *lpr;
768 lpr = calloc(1, sizeof(*lpr));
770 xasprintf(errctx, "log parse result");
774 d = init_lls_data(opts, argc, argv);
776 xasprintf(errctx, "init_lls_data()");
780 if (cmd->num_options == 0) {
782 lpr->opt_result = NULL;
784 lpr->opt_result = calloc(cmd->num_options,
785 sizeof(*lpr->opt_result));
786 if (!lpr->opt_result) {
787 xasprintf(errctx, "option result array for %s",
793 ret = parse_option(d, &la, errctx);
798 ret = lls_parse_arg(&la, opts, lpr, errctx);
803 lpr->num_inputs = argc - la.idx - 1;
804 if (!cmd->non_opts_name) {
805 ret = lls_check_arg_count(lpr, 0, 0, errctx);
807 /* needed for lls_free_parse_result() */
812 /* We always make a copy of the elements of argv[] */
813 lpr->inputs = malloc((lpr->num_inputs + 1) * sizeof(char *));
815 xasprintf(errctx, "inputs array for %s", cmd->name);
819 for (i = 0; i < lpr->num_inputs; i++) {
820 char *arg = argv[i + la.idx + 1];
821 lpr->inputs[i] = strdup(arg);
824 xasprintf(errctx, "option #%d (%s) of %s", i, arg, cmd->name);
828 lpr->inputs[lpr->num_inputs] = NULL;
829 /* initialize default values */
830 FOR_EACH_OPTION(i, opts) {
831 const struct lls_option *opt = opts + i;
832 struct lls_opt_result *lor = lpr->opt_result + i;
833 bool required = opt->flags & LLS_REQUIRED;
834 bool has_arg = opt->arg_info != LLS_NO_ARGUMENT;
836 if (lor->given == 0 && required) {
837 xasprintf(errctx, "--%s", opt->name);
838 ret = -E_LLS_OPT_MANDATORY;
846 * allocate space for the default value, even if there is no
847 * default given in the .suite file
849 lor->value = malloc(sizeof(*lor->value));
851 xasprintf(errctx, "value array for --%s", opt->name);
855 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
862 check_errctx(errctx, ret);
864 lls_free_parse_result(lpr, cmd);
871 #define MAX_OPTION_LEN 30
872 #define HELP_INDENT 6
873 static const char space[MAX_OPTION_LEN + 1] = " ";
875 static int short_option_help(const struct lls_option *opt, char **result)
878 char *opt_names = NULL;
879 bool overlong, has_short = opt->short_opt;
883 if (opt->flags & LLS_IGNORED)
884 return xasprintf(result, "%s", opt->summary);
885 if (opt->arg_info == LLS_NO_ARGUMENT)
888 typestr = opt->typestr? opt->typestr : "val";
890 ret = xasprintf(&opt_names,
895 has_short? " -" : " ",
896 has_short? opt->short_opt : ' ',
897 has_short? "," : " ",
899 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "[" : "",
900 opt->arg_info == LLS_NO_ARGUMENT? "" : "=<",
902 opt->arg_info == LLS_NO_ARGUMENT? "" : ">",
903 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "]" : ""
907 overlong = ret >= MAX_OPTION_LEN;
908 ret = xasprintf(result,
916 overlong? space : space + ret,
917 opt->summary? opt->summary : ""
923 static int format_default_val(const struct lls_option *opt, char **result)
925 const union lls_val *val = &opt->default_val;
928 if (opt->arg_info == LLS_NO_ARGUMENT)
930 if (!(opt->flags & LLS_HAS_DEFAULT))
932 switch (opt->arg_type) {
936 return xasprintf(result, "(string, default: %s)",
937 val->string_val? val->string_val : "[NULL]");
939 return xasprintf(result, "(int32, default: %" PRId32 ")",
942 return xasprintf(result, "(uint32, default: %" PRIu32 ")",
945 return xasprintf(result, "(int64, default: %" PRId64 ")",
948 return xasprintf(result, "(uint64, default: %" PRIu64 ")",
956 static int format_values(const struct lls_option *opt, char **result)
960 const char *val, *pfx = "values: ";
961 size_t len, line_len;
962 const int indent_len = 6, max_len = 75, pfx_len = 8;
968 assert(opt->arg_type == LLS_STRING);
969 dflt_idx = opt->default_val.uint32_val;
970 line_len = indent_len + pfx_len;
972 for (i = 0; (val = opt->values[i].string_val); i++) {
973 size_t val_len = strlen(val);
974 /* comma and space, and [] around default val */
975 int extra_len = 2 * (i != 0) + 2 * (i == dflt_idx);
976 bool cr = line_len + val_len + extra_len > max_len;
978 line_len = indent_len + pfx_len;
979 len += 1 + indent_len + pfx_len; /* +1 for \n */
981 len += val_len + extra_len;
982 line_len += val_len + extra_len;
984 *result = malloc(len + 1); /* +1 for terminating zero byte */
987 p = *result + sprintf(*result, "%.*s%s", indent_len, space, pfx);
988 line_len = p - *result;
989 for (i = 0; (val = opt->values[i].string_val); i++) {
990 size_t val_len = strlen(val);
991 int extra_len = 2 * (i != 0) + 2 * (i == dflt_idx);
992 bool cr = line_len + val_len + extra_len > max_len;
1000 cr? pfx_len + indent_len : 0, cr? space : "",
1001 i == dflt_idx? "[" : "", val, i == dflt_idx? "]" : ""
1004 line_len = indent_len + pfx_len;
1005 line_len += val_len + extra_len;
1010 static char *create_help_buf(const struct lls_command *cmd, bool long_help)
1012 char *header, *option_help, *result;
1013 const struct lls_option *opt;
1015 const char *desc = (long_help && cmd->description)?
1016 cmd->description : "";
1017 const char *closing = (long_help && cmd->closing)? cmd->closing : NULL;
1021 ret = xasprintf(&header,
1026 cmd->name, cmd->purpose,
1027 cmd->name, cmd->synopsis,
1029 cmd->options? "\n" : ""
1036 FOR_EACH_OPTION_IN_COMMAND(opt, cmd) {
1037 char *tmp, *soh, *loh = NULL, *dflt, *values;
1038 int indent = (opt->flags & LLS_IGNORED)? 0 : HELP_INDENT;
1040 ret = short_option_help(opt, &soh);
1043 if (long_help && opt->help) {
1045 for (p = opt->help; (q = strchr(p, '\n')); p = q + 1) {
1047 ret = xasprintf(&tmp, "%s%.*s%.*s",
1048 loh? loh : "\n", indent, space,
1049 (int)(q - p + 1), p);
1058 ret = format_default_val(opt, &dflt);
1065 ret = format_values(opt, &values);
1075 ret = xasprintf(&tmp,
1081 option_help? option_help : "",
1083 dflt? "\n" : "", dflt? space : "", dflt? dflt : "",
1084 values? "\n" : "", values? values : "",
1096 ret = xasprintf(&result, "%s%s%s%s", header, option_help,
1097 closing? "\n" : "", closing? closing : "");
1101 return ret < 0? NULL : result;
1104 char *lls_long_help(const struct lls_command *cmd)
1106 return create_help_buf(cmd, true /* include help */);
1109 char *lls_short_help(const struct lls_command *cmd)
1111 return create_help_buf(cmd, false /* only options */);
1114 static int partial_match(const char *arg, const char *name)
1116 size_t arglen = strlen(arg);
1118 if (strncmp(arg, name, arglen) != 0)
1119 return 1; /* no match */
1120 if (name[arglen] == '\0')
1121 return 0; /* exact match */
1122 return -1; /* partial match */
1125 int lls_lookup_subcmd(const char *string, const struct lls_suite *suite,
1133 xasprintf(errctx, "nothing to look up");
1134 return -E_LLS_BAD_SUBCMD;
1136 ret = 0; /* no match so far */
1137 for (i = 1; i <= suite->num_subcommands; i++) {
1138 switch (partial_match(string, suite->commands[i].name)) {
1139 case 1: /* no match */
1141 case 0: /* exact match */
1143 case -1: /* partial match */
1145 ret = -E_LLS_AMBIG_SUBCMD;
1151 if (ret > 0) /* unique partial match */
1153 ret = -E_LLS_BAD_SUBCMD;
1155 xasprintf(errctx, "%s", string);
1159 static size_t get_opt_result_pointer(const struct lls_option *opt, int val_num,
1160 struct lls_opt_result *lor, void **result)
1162 union lls_val *val = lor->value + val_num;
1164 switch (opt->arg_type) {
1166 *result = &val->int32_val;
1169 *result = &val->uint32_val;
1172 *result = &val->int64_val;
1175 *result = &val->uint64_val;
1182 /* never fails, returns number of bytes needed/written */
1183 static size_t serialize_parse_result(const struct lls_parse_result *lpr,
1184 const struct lls_command *cmd, char *result)
1191 memcpy(result, &lpr->num_inputs, 4);
1195 for (i = 0; i < lpr->num_inputs; i++) {
1197 strcpy(result + nbytes, lpr->inputs[i]);
1198 nbytes += strlen(lpr->inputs[i]) + 1;
1201 FOR_EACH_OPTION(i, cmd->options) {
1202 const struct lls_option *opt = cmd->options + i;
1203 struct lls_opt_result *lor = lpr->opt_result + i;
1207 memcpy(result + nbytes, &lor->given, 4);
1209 if (opt->arg_info == LLS_NO_ARGUMENT)
1211 num_vals = num_vals_in_parse_result(cmd, i, lpr);
1212 if (opt->arg_type == LLS_STRING && !opt->values) {
1213 for (j = 0; j < num_vals; j++) {
1215 strcpy(result + nbytes,
1216 lor->value[j].string_val);
1217 nbytes += strlen(lor->value[j].string_val) + 1;
1220 for (j = 0; j < num_vals; j++) {
1223 bytes = get_opt_result_pointer(opt, j, lor, &p);
1225 memcpy(result + nbytes, p, bytes);
1233 int lls_serialize_parse_result(const struct lls_parse_result *lpr,
1234 const struct lls_command *cmd, char **result, size_t *nbytes)
1239 if (!result || !*result) { /* need to compute needed space */
1240 sz = serialize_parse_result(lpr, cmd, NULL);
1241 if (!result) { /* just report needed space */
1245 *result = malloc(sz);
1253 sz = serialize_parse_result(lpr, cmd, *result);
1261 int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd,
1262 struct lls_parse_result **lprp)
1265 const char *p = buf;
1266 struct lls_parse_result *lpr;
1269 lpr = malloc(sizeof(*lpr));
1271 return -E_LLS_NOMEM;
1272 memcpy(&lpr->num_inputs, p, 4);
1274 if (lpr->num_inputs > 0) {
1275 lpr->inputs = malloc(lpr->num_inputs * sizeof(char *));
1280 for (i = 0; i < lpr->num_inputs; i++) {
1281 lpr->inputs[i] = strdup(p);
1282 if (!lpr->inputs[i])
1286 lpr->opt_result = malloc(cmd->num_options * sizeof(*lpr->opt_result));
1287 if (!lpr->opt_result)
1289 FOR_EACH_OPTION(i, cmd->options) {
1290 const struct lls_option *opt = cmd->options + i;
1291 struct lls_opt_result *lor = lpr->opt_result + i;
1294 memcpy(&lor->given, p, 4);
1296 if (opt->arg_info == LLS_NO_ARGUMENT)
1298 num_vals = num_vals_in_parse_result(cmd, i, lpr);
1299 lor->value = malloc(num_vals * sizeof(*lor->value));
1302 if (opt->arg_type == LLS_STRING && !opt->values) {
1303 for (j = 0; j < num_vals; j++) {
1304 lor->value[j].string_val = strdup(p);
1305 if (!lor->value[j].string_val) {
1307 free(lor->value[j].string_val);
1311 p += strlen(lor->value[j].string_val) + 1;
1314 for (j = 0; j < num_vals; j++) {
1317 bytes = get_opt_result_pointer(opt, j, lor, &q);
1318 memcpy(q, p, bytes);
1326 for (i--; i >= 0; i--) {
1327 const struct lls_option *opt = cmd->options + i;
1328 struct lls_opt_result *lor = lpr->opt_result + i;
1329 unsigned num_vals = (opt->flags & LLS_MULTIPLE)? lor->given : 1;
1330 for (j = 0; j < num_vals; j++)
1331 if (opt->arg_type == LLS_STRING && !opt->values)
1332 free(lor->value[j].string_val);
1335 free(lpr->opt_result);
1338 free(lpr->inputs[i]);
1342 return -E_LLS_NOMEM;
1345 static int merge_option(int opt_num, const struct lls_parse_result *primary,
1346 const struct lls_parse_result *secondary,
1347 const struct lls_command *cmd, struct lls_parse_result *result,
1351 const struct lls_option *opt = cmd->options + opt_num;
1352 struct lls_opt_result *lor1, *lor2, *lor;
1354 lor1 = primary->opt_result + opt_num;
1355 lor2 = secondary->opt_result + opt_num;
1356 lor = result->opt_result + opt_num;
1357 lor->given = lor1->given + lor2->given;
1358 if (opt->arg_info == LLS_NO_ARGUMENT)
1360 if (lor->given > 0 && (opt->flags & LLS_MULTIPLE)) {
1361 lor->value = malloc(lor->given * sizeof(*lor->value));
1363 xasprintf(errctx, "value array for option %s", opt->name);
1366 for (l = 0; l < lor1->given; l++) {
1367 ret = copy_val(lor->value + l, lor1->value + l,
1370 goto free_primary_options;
1372 for (m = 0; m < lor2->given; m++) {
1373 ret = copy_val(lor->value + l + m, lor2->value + m,
1376 goto free_secondary_options;
1380 lor->value = malloc(sizeof(*lor->value)); /* one value only */
1382 xasprintf(errctx, "(single) value for option %s", opt->name);
1386 ret = copy_val(lor->value, lor1->value, opt, errctx);
1389 } else if (lor2->given) {
1390 ret = copy_val(lor->value, lor2->value, opt, errctx);
1394 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
1399 free_secondary_options:
1400 if (opt->arg_type == LLS_STRING && !opt->values)
1401 for (m--; m >= 0; m--)
1402 free(lor->value[l + m].string_val);
1403 free_primary_options:
1404 if (opt->arg_type == LLS_STRING && !opt->values)
1405 for (l--; l >= 0; l--)
1406 free(lor->value[l].string_val);
1410 return -E_LLS_NOMEM;
1413 int lls_merge(const struct lls_parse_result *primary,
1414 const struct lls_parse_result *secondary,
1415 const struct lls_command *cmd, struct lls_parse_result **lprp,
1419 unsigned num = primary->num_inputs + secondary->num_inputs;
1420 struct lls_parse_result *result;
1424 result = malloc(sizeof(*result));
1427 xasprintf(errctx, "parse result");
1430 result->inputs = malloc((num + 1) * sizeof(char *));
1431 if (!result->inputs) {
1433 xasprintf(errctx, "inputs array of size %u", num);
1434 goto free_parse_result;
1436 for (i = 0; i < primary->num_inputs; i++) {
1437 result->inputs[i] = strdup(primary->inputs[i]);
1438 if (!result->inputs[i]) {
1440 xasprintf(errctx, "primary input #%d", i);
1441 goto free_primary_inputs;
1444 for (j = 0; j < secondary->num_inputs; j++) {
1445 result->inputs[i + j] = strdup(secondary->inputs[j]);
1446 if (!result->inputs[i + j]) {
1448 xasprintf(errctx, "secondary input #%d", i);
1449 goto free_secondary_inputs;
1452 result->inputs[i + j] = NULL;
1453 result->opt_result = malloc(cmd->num_options
1454 * sizeof(*result->opt_result));
1455 if (!result->opt_result)
1456 goto free_secondary_inputs;
1457 FOR_EACH_OPTION(k, cmd->options) {
1458 ret = merge_option(k, primary, secondary, cmd, result, errctx);
1460 goto free_opt_results;
1462 result->num_inputs = num;
1467 for (k--; k >= 0; k--)
1468 free_opt_result(k, result, cmd);
1469 free_secondary_inputs:
1470 for (j--; j >= 0; j--)
1471 free(result->inputs[i + j]);
1472 free_primary_inputs:
1473 for (i--; i >= 0; i--)
1474 free(result->inputs[i]);
1475 free(result->inputs);
1482 check_errctx(errctx, ret);
1486 static bool is_default_val(const union lls_val *val,
1487 const struct lls_option *opt)
1489 bool has_default = opt->flags & LLS_HAS_DEFAULT;
1490 bool has_arg = opt->arg_info != LLS_NO_ARGUMENT;
1491 const union lls_val *dflt;
1497 dflt = &opt->default_val;
1498 switch (opt->arg_type) {
1500 return val->int32_val == dflt->int32_val;
1502 return val->uint32_val == dflt->uint32_val;
1504 return val->int64_val == dflt->int64_val;
1506 return val->uint64_val == dflt->uint64_val;
1509 const char *s1, *s2;
1512 return val->uint32_val == dflt->uint32_val;
1513 s1 = val->string_val;
1514 s2 = dflt->string_val;
1519 return !strcmp(s1, s2);
1526 static char *append_opt_val(const union lls_val *val,
1527 const struct lls_option *opt, char *result)
1529 char *line = NULL, *tmp = NULL;
1531 switch (opt->arg_type) {
1533 xasprintf(&line, "%" PRId32, val->int32_val);
1536 xasprintf(&line, "%" PRIu32, val->uint32_val);
1539 xasprintf(&line, "%" PRId64, val->int64_val);
1542 xasprintf(&line, "%" PRIu64, val->uint64_val);
1550 s = lls_enum_string_val(val->uint32_val, opt);
1552 s = val->string_val;
1556 line = malloc(2 * strlen(s) + 3);
1562 for (p = s, q = line + 1; *p; p++, q++) {
1563 if (*p == '\\' || *p == '\n' || *p == '\t' || *p == '"') {
1576 xasprintf(&tmp, "%s%s=%s\n", result? result : "", opt->name, line);
1582 char *lls_dump_parse_result(const struct lls_parse_result *lpr,
1583 const struct lls_command *cmd, bool non_default_only)
1586 char *result = NULL;
1588 FOR_EACH_OPTION(i, cmd->options) {
1589 const struct lls_option *opt = cmd->options + i;
1590 struct lls_opt_result *lor = lpr->opt_result + i;
1591 bool given = lor->given;
1594 if (!given && non_default_only)
1596 if (opt->arg_info == LLS_NO_ARGUMENT) {
1600 xasprintf(&tmp, "%s%s\n", result? result : "",
1606 n = num_vals_in_parse_result(cmd, i, lpr);
1607 for (j = 0; j < n; j++) {
1608 union lls_val *val = lor->value + j;
1609 if (non_default_only && is_default_val(val, opt))
1611 result = append_opt_val(val, opt, result);
1614 if (!result) { /* empty dump */