Make the build reproducible.
[lopsub.git] / lopsub.c
1 /*
2 * Copyright (C) 2016 Andre Noll <maan@tuebingen.mpg.de>
3 *
4 * Licensed under the LGPL v3, see http://www.gnu.org/licenses/lgpl-3.0.html
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdbool.h>
10 #include <assert.h>
11 #include <stdarg.h>
12 #include <inttypes.h>
13 #include <errno.h>
14 #include <limits.h>
15
16 #include "lopsub-internal.h"
17 #include "lopsub.h"
18
19 /* For detecting version mismatches, see lopsub-internal.h. */
20 const unsigned LLS_ABI_VERSION_VAR = 0;
21
22 #define FOR_EACH_OPTION(_i, _opts) \
23 for (_i = 0; (_opts) && (_opts)[(_i)].name; (_i)++)
24
25 #define FOR_EACH_OPTION_IN_COMMAND(_opt, _cmd) \
26 for ( \
27 (_opt) = (_cmd)->options; \
28 (_opt) && (_opt) < (_cmd)->options + (_cmd)->num_options; \
29 (opt)++ \
30 )
31
32 /* The result of parsing one option and its arguments. */
33 struct lls_arg {
34 int idx; /* index into either argv[] or the lls_option array. */
35 const char *arg; /* NULL if option has no argument. */
36 };
37
38 /*
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.
42 */
43 struct lls_data {
44 const struct lls_option *opts;
45 int argc;
46 char *const *argv;
47
48 int optind; /* index into argv[] which we are parsing. */
49 const char *next_char;
50 /*
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.
55 */
56 int first_nonopt;
57 int last_nonopt;
58 };
59
60 const struct lls_command *lls_cmd(unsigned cmd_num,
61 const struct lls_suite *suite)
62 {
63 if (cmd_num > suite->num_subcommands)
64 return NULL;
65 return suite->commands + cmd_num;
66 }
67
68 const char *lls_command_name(const struct lls_command *cmd)
69 {
70 return cmd->name;
71 }
72
73 const void *lls_user_data(const struct lls_command *cmd)
74 {
75 return cmd->user_data;
76 }
77
78 const struct lls_option *lls_opt(unsigned opt_num,
79 const struct lls_command *cmd)
80 {
81 return cmd->options + opt_num;
82 }
83
84 const struct lls_opt_result *lls_opt_result(unsigned opt_num,
85 const struct lls_parse_result *lpr)
86 {
87 return lpr->opt_result + opt_num;
88 }
89
90 unsigned lls_opt_given(const struct lls_opt_result *r)
91 {
92 return r->given;
93 }
94
95 const char *lls_enum_string_val(unsigned idx, const struct lls_option *opt)
96 {
97 return opt->values[idx].string_val;
98 }
99
100 const char *lls_string_val(unsigned idx, const struct lls_opt_result *r)
101 {
102 return r->value[idx].string_val;
103 }
104
105 int32_t lls_int32_val(unsigned idx, const struct lls_opt_result *r)
106 {
107 return r->value[idx].int32_val;
108 }
109
110 uint32_t lls_uint32_val(unsigned idx, const struct lls_opt_result *r)
111 {
112 return r->value[idx].uint32_val;
113 }
114
115 int64_t lls_int64_val(unsigned idx, const struct lls_opt_result *r)
116 {
117 return r->value[idx].int64_val;
118 }
119
120 uint64_t lls_uint64_val(unsigned idx, const struct lls_opt_result *r)
121 {
122 return r->value[idx].uint64_val;
123 }
124
125 unsigned lls_num_inputs(const struct lls_parse_result *lpr)
126 {
127 return lpr->num_inputs;
128 }
129
130 const char *lls_purpose(const struct lls_command *cmd)
131 {
132 return cmd->purpose;
133 }
134
135 const char *lls_input(unsigned input_num, const struct lls_parse_result *lpr)
136 {
137 return lpr->inputs[input_num];
138 }
139
140 const char *lls_strerror(int lss_errno)
141 {
142 #define LLS_ERROR(_n, _s) _s,
143 static const char * const error_string[] = {LLS_ERRORS NULL};
144 #undef LLS_ERROR
145 return error_string[lss_errno];
146 }
147
148 static int xrealloc(void *p, size_t size)
149 {
150 void **pp = p, *newp = realloc(*pp, size);
151
152 if (!newp)
153 return -E_LLS_NOMEM;
154 *pp = newp;
155 return 0;
156 }
157
158 /* Print a formated message to a dynamically allocated string. */
159 __attribute__ ((format (printf, 2, 0)))
160 static int xvasprintf(char **result, const char *fmt, va_list ap)
161 {
162 int ret;
163 size_t size = 150;
164 va_list aq;
165
166 if (!result)
167 return 0;
168 if (*result)
169 free(*result);
170 *result = malloc(size + 1);
171 if (!*result)
172 return -E_LLS_NOMEM;
173 va_copy(aq, ap);
174 ret = vsnprintf(*result, size, fmt, aq);
175 va_end(aq);
176 assert(ret >= 0);
177 if (ret < size) /* OK */
178 return ret;
179 size = ret + 1;
180 ret = xrealloc(result, size);
181 if (ret < 0) {
182 free(*result);
183 *result = NULL;
184 return ret;
185 }
186 va_copy(aq, ap);
187 ret = vsnprintf(*result, size, fmt, aq);
188 va_end(aq);
189 assert(ret >= 0 && ret < size);
190 return ret;
191 }
192
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, ...)
196 {
197 va_list ap;
198 unsigned ret;
199
200 va_start(ap, fmt);
201 ret = xvasprintf(result, fmt, ap);
202 va_end(ap);
203 return ret;
204 }
205
206 static inline unsigned num_vals_in_parse_result(const struct lls_command *cmd,
207 int opt_num, const struct lls_parse_result *lpr)
208 {
209 const struct lls_option *opt = cmd->options + opt_num;
210 struct lls_opt_result *lor = lpr->opt_result + opt_num;
211
212 if (opt->arg_info == LLS_NO_ARGUMENT)
213 return 0;
214 if (lor->given == 0)
215 return 1; /* for the default value */
216 if (!(opt->flags & LLS_MULTIPLE))
217 return 1;
218 return lor->given;
219 }
220
221 union atoi_result {
222 int32_t int32;
223 uint32_t uint32;
224 int64_t int64;
225 uint64_t uint64;
226 };
227
228 enum atoi_mode {ATOI_INT32, ATOI_UINT32, ATOI_INT64, ATOI_UINT64};
229
230 /*
231 * Convert a string to a 32 or 64 bit signed or unsigned integer value.
232 *
233 * For conversions to unsigned integers, negative values are considered valid
234 * input and are silently converted.
235 */
236 static int lls_atoi(const char *str, enum atoi_mode mode, union atoi_result *value)
237 {
238 char *endptr;
239 union atoi_result result;
240
241 memset(value, 0, sizeof(*value));
242 errno = 0; /* To distinguish success/failure after call */
243 /*
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".
246 */
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;
251 result.uint64 = tmp;
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;
256 switch (mode) {
257 case ATOI_INT64: /* no additional range check necessary */
258 result.int64 = tmp;
259 break;
260 case ATOI_INT32:
261 if (tmp < INT_MIN || tmp > INT_MAX)
262 return -E_LLS_OVERFLOW;
263 result.int32 = tmp;
264 break;
265 case ATOI_UINT32:
266 if (tmp > UINT_MAX)
267 return -E_LLS_OVERFLOW;
268 result.uint32 = tmp;
269 break;
270 default:
271 assert(0);
272 }
273 }
274 /*
275 * If there were no digits at all, strtol() and friends store the
276 * original value of str in *endptr.
277 */
278 if (endptr == str)
279 return -E_LLS_NO_DIGITS;
280 /*
281 * The implementation may also set errno (and return 0) in case no
282 * conversion was performed.
283 */
284 if (errno != 0)
285 return -E_LLS_NO_DIGITS;
286 if (*endptr != '\0') /* Further characters after number */
287 return -E_LLS_TRAILING_GARBAGE;
288 *value = result;
289 return 1;
290 }
291
292 static int atoi32(const char *str, int32_t *result)
293 {
294 union atoi_result ar;
295 int ret = lls_atoi(str, ATOI_INT32, &ar);
296 *result = ar.int32;
297 return ret;
298 }
299
300 static int atou32(const char *str, uint32_t *result)
301 {
302 union atoi_result ar;
303 int ret = lls_atoi(str, ATOI_UINT32, &ar);
304 *result = ar.uint32;
305 return ret;
306 }
307
308 static int atoi64(const char *str, int64_t *result)
309 {
310 union atoi_result ar;
311 int ret = lls_atoi(str, ATOI_INT64, &ar);
312 *result = ar.int64;
313 return ret;
314 }
315
316 static int atou64(const char *str, uint64_t *result)
317 {
318 union atoi_result ar;
319 int ret = lls_atoi(str, ATOI_UINT64, &ar);
320 *result = ar.uint64;
321 return ret;
322 }
323
324 static void free_opt_result(int opt_num, struct lls_parse_result *lpr,
325 const struct lls_command *cmd)
326 {
327 const struct lls_option *opt = cmd->options + opt_num;
328
329 if (opt->arg_type == LLS_STRING && !opt->values) {
330 unsigned num_vals = num_vals_in_parse_result(cmd, opt_num, lpr);
331 int j;
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);
335 }
336 if (opt->arg_info != LLS_NO_ARGUMENT)
337 free(lpr->opt_result[opt_num].value);
338 }
339
340 void lls_free_parse_result(struct lls_parse_result *lpr,
341 const struct lls_command *cmd)
342 {
343 int i;
344
345 if (!lpr)
346 return;
347 if (lpr->inputs)
348 for (i = 0; i < lpr->num_inputs; i++)
349 free(lpr->inputs[i]);
350 free(lpr->inputs);
351 if (lpr->opt_result)
352 FOR_EACH_OPTION(i, cmd->options)
353 free_opt_result(i, lpr, cmd);
354 free(lpr->opt_result);
355 free(lpr);
356 }
357
358 static struct lls_data *init_lls_data(const struct lls_option *opts,
359 int argc, char *const *argv)
360 {
361 struct lls_data *d = malloc(sizeof(*d));
362
363 if (!d)
364 return NULL;
365 d->optind = 0;
366 /* start with an empty non-option list */
367 d->first_nonopt = d->last_nonopt = d->optind;
368 d->opts = opts;
369 d->argc = argc;
370 d->argv = argv;
371 d->next_char = NULL;
372 return d;
373 }
374
375 /*
376 * Exchange two adjacent subsets of argv[].
377 *
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.
382 *
383 * Before the function returns, ->first_nonopt and ->last_nonopt are updated to
384 * describe the new set of non-options in argv[].
385 */
386 static void exchange_args(struct lls_data *d)
387 {
388 int bottom = d->first_nonopt;
389 int middle = d->last_nonopt;
390 int top = d->optind;
391 char **argv = (char **)d->argv;
392
393 /*
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.
398 */
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;
403
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;
409 }
410 /* Exclude the moved bottom segment from further swapping. */
411 top -= len;
412 } else {
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;
420 }
421 /* Exclude the moved top segment from further swapping. */
422 bottom += len;
423 }
424 }
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;
428 }
429
430 /* whether arg points to an option argument */
431 static inline bool is_option(const char *arg)
432 {
433 return arg[0] == '-' && arg[1] != '\0';
434 }
435
436 static void check_errctx(char **errctx, int ret)
437 {
438 if (!errctx)
439 return;
440 if (ret >= 0)
441 assert(!*errctx); /* memory leak/uninitialized pointer */
442 else if (ret != -E_LLS_NOMEM)
443 assert(*errctx); /* we must provide an error message */
444 }
445
446 /*
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.
450 */
451 static int decode_option(struct lls_data *d, struct lls_arg *result,
452 char **errctx)
453 {
454 const char *word = d->argv[d->optind], *cur, *end;
455 size_t len;
456 int i;
457 const struct lls_option *match = NULL;
458 bool ambig = false, shortopt;
459
460 assert(word[0] != '\0');
461 shortopt = word[1] != '-';
462 result->idx = d->optind;
463 result->arg = word;
464
465 if (d->next_char)
466 cur = d->next_char;
467 else
468 cur = word + 1 + !shortopt; /* skip dash(es) */
469 for (end = cur; *end && *end != '='; end++)
470 ; /* nothing */
471 len = end - cur;
472
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)
477 continue;
478 if (shortopt) {
479 if (*cur != opt->short_opt)
480 continue;
481 match = opt;
482 d->next_char = cur + 1;
483 if (d->next_char[0] == '\0' || d->next_char[0] == '=')
484 d->next_char = NULL;
485 break;
486 }
487 if (strncmp(opt->name, cur, len) != 0)
488 continue;
489 if (strlen(opt->name) == len) { /* exact match */
490 match = opt;
491 break;
492 }
493 if (match) { /* second non-exact match */
494 ambig = true;
495 break;
496 }
497 /* first non-exact match */
498 match = opt;
499 }
500 if (!match) { /* option not found */
501 xasprintf(errctx, "error token: %s", cur);
502 return -E_LLS_BAD_OPTION;
503 }
504 if (ambig) {
505 xasprintf(errctx, "%s", word);
506 return -E_LLS_AMBIG_OPTION;
507 }
508 if (d->next_char) {
509 if (match->arg_info == LLS_REQUIRED_ARGUMENT) {
510 xasprintf(errctx, "--%s", match->name);
511 return -E_LLS_NO_ARG_GIVEN;
512 }
513 result->arg = NULL;
514 goto success;
515 }
516 d->optind++;
517 if (*end == '=') {
518 if (match->arg_info == LLS_NO_ARGUMENT) {
519 xasprintf(errctx, "--%s", match->name);
520 return -E_LLS_ARG_GIVEN;
521 }
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;
527 }
528 result->arg = d->argv[d->optind++];
529 } else
530 result->arg = NULL;
531 success:
532 result->idx = match - d->opts;
533 return 1;
534 }
535
536 /*
537 * Parse one option, including its argument (if any).
538 *
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.
541 *
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:
544 *
545 * end-of-args case: ->idx is the index of first non-option in argv[], ->arg is
546 * argv[result->idx].
547 *
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.
550 *
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.
554 *
555 * After this function returned non-positive, it must not be called again.
556 */
557 static int parse_option(struct lls_data *d, struct lls_arg *result, char **errctx)
558 {
559 assert(d->last_nonopt <= d->optind);
560 assert(d->first_nonopt <= d->optind);
561
562 if (d->next_char)
563 return decode_option(d, result, errctx);
564 /*
565 * If we have just processed some options following some non-options,
566 * exchange them so that the options come first.
567 */
568 if (d->first_nonopt != d->last_nonopt && d->last_nonopt != d->optind)
569 exchange_args(d);
570 else if (d->last_nonopt != d->optind)
571 d->first_nonopt = d->optind;
572 /*
573 * Skip any additional non-options and extend the range of non-options
574 * previously skipped.
575 */
576 while (d->optind < d->argc && !is_option(d->argv[d->optind]))
577 d->optind++;
578 d->last_nonopt = d->optind;
579 /*
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.
583 */
584 if (d->optind != d->argc && !strcmp(d->argv[d->optind], "--")) {
585 d->optind++;
586 if (d->first_nonopt != d->last_nonopt && d->last_nonopt != d->optind)
587 exchange_args(d);
588 else if (d->first_nonopt == d->last_nonopt)
589 d->first_nonopt = d->optind;
590 d->last_nonopt = d->argc;
591 d->optind = d->argc;
592 }
593 /*
594 * If we have done all the argv elements, stop the scan and back over
595 * any non-options that we skipped and permuted.
596 */
597 if (d->optind == d->argc) {
598 /*
599 * Set the index to point at the non-options that we
600 * previously skipped.
601 */
602 result->idx = d->first_nonopt;
603 result->arg = d->argv[result->idx];
604 return 0;
605 }
606 assert(is_option(d->argv[d->optind]));
607 return decode_option(d, result, errctx);
608 }
609
610 static int check_enum_arg(const char *arg, const struct lls_option *opt,
611 char **errctx)
612 {
613 int i;
614 char *val;
615
616 for (i = 0; (val = opt->values[i].string_val); i++)
617 if (!strcmp(arg, val))
618 return i;
619 xasprintf(errctx, "arg: %s, option: %s", arg, opt->name);
620 return -E_LLS_ENUM;
621 }
622
623 /*
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.
626 */
627 static int lls_parse_arg(struct lls_arg *la, const struct lls_option *opts,
628 struct lls_parse_result *lpr, char **errctx)
629 {
630 const struct lls_option *opt = opts + la->idx;
631 struct lls_opt_result *lor = lpr->opt_result + la->idx;
632 bool multiple;
633 int idx, ret;
634
635 if (!la->arg)
636 goto success;
637 if (opt->arg_info == LLS_NO_ARGUMENT) {
638 xasprintf(errctx, "arg: %s, option: %s", la->arg, opt->name);
639 return -E_LLS_ARG_GIVEN;
640 }
641 multiple = opt->flags & LLS_MULTIPLE;
642 idx = multiple? lor->given : 0;
643 if (lor->given == 0 || multiple) {
644 ret = xrealloc(&lor->value,
645 (lor->given + 1) * sizeof(*lor->value));
646 if (ret < 0) {
647 xasprintf(errctx, "option value array for --%s",
648 opt->name);
649 return ret;
650 }
651 }
652 switch (opt->arg_type) {
653 case LLS_STRING:
654 if (!opt->values && lor->given > 0 && !multiple)
655 free(lor->value[idx].string_val);
656 if (opt->values) {
657 ret = check_enum_arg(la->arg, opt, errctx);
658 if (ret < 0)
659 return ret;
660 lor->value[idx].uint32_val = ret;
661 } else {
662 lor->value[idx].string_val = strdup(la->arg);
663 if (!lor->value[idx].string_val) {
664 xasprintf(errctx, "string value for %s",
665 opt->name);
666 return -E_LLS_NOMEM;
667 }
668 }
669 break;
670 case LLS_INT32:
671 ret = atoi32(la->arg, &lor->value[idx].int32_val);
672 if (ret < 0)
673 goto atoi_error;
674 break;
675 case LLS_UINT32:
676 ret = atou32(la->arg, &lor->value[idx].uint32_val);
677 if (ret < 0)
678 goto atoi_error;
679 break;
680 case LLS_INT64:
681 ret = atoi64(la->arg, &lor->value[idx].int64_val);
682 if (ret < 0)
683 goto atoi_error;
684 break;
685 case LLS_UINT64:
686 ret = atou64(la->arg, &lor->value[idx].uint64_val);
687 if (ret < 0)
688 goto atoi_error;
689 break;
690 default:
691 assert(false);
692 }
693 success:
694 lor->given++;
695 return 1;
696 atoi_error:
697 assert(ret < 0);
698 xasprintf(errctx, "conversion error for argument \"%s\" to option --%s",
699 la->arg, opt->name);
700 return ret;
701 }
702
703 static int copy_val(union lls_val *dst, const union lls_val *src,
704 const struct lls_option *opt, char **errctx)
705 {
706 if (opt->arg_type != LLS_STRING || opt->values) {
707 *dst = *src;
708 return 0;
709 }
710 if (!src->string_val) {
711 dst->string_val = NULL;
712 return 0;
713 }
714 dst->string_val = strdup(src->string_val);
715 if (!dst->string_val) {
716 xasprintf(errctx, "copy value for --%s", opt->name);
717 return -E_LLS_NOMEM;
718 }
719 return 1;
720 }
721
722 int lls_check_arg_count(const struct lls_parse_result *lpr,
723 int min_argc, int max_argc, char **errctx)
724 {
725 if (errctx)
726 *errctx = NULL;
727 assert(min_argc <= max_argc);
728 if (lpr->num_inputs < min_argc) {
729 xasprintf(errctx, "%s %u non-option args required, %u given",
730 min_argc < max_argc? "at least" : "exactly",
731 min_argc, lpr->num_inputs);
732 return -E_LLS_BAD_ARG_COUNT;
733 }
734 if (lpr->num_inputs > max_argc) {
735 if (max_argc == 0)
736 xasprintf(errctx, "no non-option args allowed, "
737 "%u given", lpr->num_inputs);
738 else
739 xasprintf(errctx, "%s %u non-option args allowed, "
740 "%u given", min_argc < max_argc?
741 "at most" : "exactly",
742 max_argc, lpr->num_inputs);
743 return -E_LLS_BAD_ARG_COUNT;
744 }
745 return 1;
746 }
747
748 /*
749 * Unlike getopt(3) this implementation can not resume the scan where it left
750 * off.
751 */
752 int lls_parse(int argc, char **argv, const struct lls_command *cmd,
753 struct lls_parse_result **lprp, char **errctx)
754 {
755 const struct lls_option *opts = cmd->options;
756 struct lls_data *d = NULL;
757 int i, ret;
758 struct lls_arg la;
759 struct lls_parse_result *lpr;
760
761 if (errctx)
762 *errctx = NULL;
763 lpr = calloc(1, sizeof(*lpr));
764 if (!lpr) {
765 xasprintf(errctx, "log parse result");
766 ret = -E_LLS_NOMEM;
767 goto out;
768 }
769 d = init_lls_data(opts, argc, argv);
770 if (!d) {
771 xasprintf(errctx, "init_lls_data()");
772 ret = -E_LLS_NOMEM;
773 goto out;
774 }
775 if (cmd->num_options == 0) {
776 la.idx = 0;
777 lpr->opt_result = NULL;
778 } else {
779 lpr->opt_result = calloc(cmd->num_options,
780 sizeof(*lpr->opt_result));
781 if (!lpr->opt_result) {
782 xasprintf(errctx, "option result array for %s",
783 cmd->name);
784 ret = -E_LLS_NOMEM;
785 goto out;
786 }
787 for (;;) {
788 ret = parse_option(d, &la, errctx);
789 if (ret < 0)
790 goto out;
791 if (ret == 0)
792 break;
793 ret = lls_parse_arg(&la, opts, lpr, errctx);
794 if (ret < 0)
795 goto out;
796 }
797 }
798 lpr->num_inputs = argc - la.idx - 1;
799 if (!cmd->non_opts_name) {
800 ret = lls_check_arg_count(lpr, 0, 0, errctx);
801 if (ret < 0) {
802 /* needed for lls_free_parse_result() */
803 lpr->inputs = NULL;
804 goto out;
805 }
806 }
807 /* We always make a copy of the elements of argv[] */
808 lpr->inputs = malloc((lpr->num_inputs + 1) * sizeof(char *));
809 if (!lpr->inputs) {
810 xasprintf(errctx, "inputs array for %s", cmd->name);
811 ret = -E_LLS_NOMEM;
812 goto out;
813 }
814 for (i = 0; i < lpr->num_inputs; i++) {
815 char *arg = argv[i + la.idx + 1];
816 lpr->inputs[i] = strdup(arg);
817 if (lpr->inputs[i])
818 continue;
819 xasprintf(errctx, "option #%d (%s) of %s", i, arg, cmd->name);
820 ret = -E_LLS_NOMEM;
821 goto out;
822 }
823 lpr->inputs[lpr->num_inputs] = NULL;
824 /* initialize default values */
825 FOR_EACH_OPTION(i, opts) {
826 const struct lls_option *opt = opts + i;
827 struct lls_opt_result *lor = lpr->opt_result + i;
828 bool required = opt->flags & LLS_REQUIRED;
829 bool has_arg = opt->arg_info != LLS_NO_ARGUMENT;
830
831 if (lor->given == 0 && required) {
832 xasprintf(errctx, "--%s", opt->name);
833 ret = -E_LLS_OPT_MANDATORY;
834 goto out;
835 }
836 if (lor->value)
837 continue;
838 if (!has_arg)
839 continue;
840 /*
841 * allocate space for the default value, even if there is no
842 * default given in the .suite file
843 */
844 lor->value = malloc(sizeof(*lor->value));
845 if (!lor->value) {
846 xasprintf(errctx, "value array for --%s", opt->name);
847 ret = -E_LLS_NOMEM;
848 goto out;
849 }
850 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
851 if (ret < 0)
852 goto out;
853 }
854 ret = 1;
855 out:
856 free(d);
857 check_errctx(errctx, ret);
858 if (ret < 0) {
859 lls_free_parse_result(lpr, cmd);
860 *lprp = NULL;
861 } else
862 *lprp = lpr;
863 return ret;
864 }
865
866 #define MAX_OPTION_LEN 30
867 #define HELP_INDENT 6
868 static const char space[MAX_OPTION_LEN + 1] = " ";
869
870 static int short_option_help(const struct lls_option *opt, char **result)
871 {
872 int ret = 0;
873 char *opt_names = NULL;
874 bool overlong, has_short = opt->short_opt;
875 const char *typestr;
876
877 *result = NULL;
878 if (opt->flags & LLS_IGNORED)
879 return xasprintf(result, "%s", opt->summary);
880 if (opt->arg_info == LLS_NO_ARGUMENT)
881 typestr = "";
882 else
883 typestr = opt->typestr? opt->typestr : "val";
884
885 ret = xasprintf(&opt_names,
886 "%s%c%s"
887 " --%s"
888 "%s%s%s%s%s"
889 ,
890 has_short? " -" : " ",
891 has_short? opt->short_opt : ' ',
892 has_short? "," : " ",
893 opt->name,
894 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "[" : "",
895 opt->arg_info == LLS_NO_ARGUMENT? "" : "=<",
896 typestr,
897 opt->arg_info == LLS_NO_ARGUMENT? "" : ">",
898 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "]" : ""
899 );
900 if (ret < 0)
901 return ret;
902 overlong = ret >= MAX_OPTION_LEN;
903 ret = xasprintf(result,
904 "%s"
905 "%s"
906 "%s"
907 "%s"
908 ,
909 opt_names,
910 overlong? "\n" : "",
911 overlong? space : space + ret,
912 opt->summary? opt->summary : ""
913 );
914 free(opt_names);
915 return ret;
916 }
917
918 static int format_default_val(const struct lls_option *opt, char **result)
919 {
920 const union lls_val *val = &opt->default_val;
921
922 *result = NULL;
923 if (opt->arg_info == LLS_NO_ARGUMENT)
924 return 0;
925 if (!(opt->flags & LLS_HAS_DEFAULT))
926 return 0;
927 switch (opt->arg_type) {
928 case LLS_STRING:
929 if (opt->values)
930 return 0;
931 return xasprintf(result, "(string, default: %s)",
932 val->string_val? val->string_val : "[NULL]");
933 case LLS_INT32:
934 return xasprintf(result, "(int32, default: %" PRId32 ")",
935 val->int32_val);
936 case LLS_UINT32:
937 return xasprintf(result, "(uint32, default: %" PRIu32 ")",
938 val->uint32_val);
939 case LLS_INT64:
940 return xasprintf(result, "(int64, default: %" PRId64 ")",
941 val->int64_val);
942 case LLS_UINT64:
943 return xasprintf(result, "(uint64, default: %" PRIu64 ")",
944 val->uint64_val);
945 default:
946 assert(0);
947 }
948 return 1;
949 }
950
951 static int format_values(const struct lls_option *opt, char **result)
952 {
953 int i;
954 uint32_t dflt_idx;
955 const char *val, *pfx = "values: ";
956 size_t len, line_len;
957 const int indent_len = 6, max_len = 75, pfx_len = 8;
958 char *p;
959
960 *result = NULL;
961 if (!opt->values)
962 return 0;
963 assert(opt->arg_type == LLS_STRING);
964 dflt_idx = opt->default_val.uint32_val;
965 line_len = indent_len + pfx_len;
966 len = line_len;
967 for (i = 0; (val = opt->values[i].string_val); i++) {
968 size_t val_len = strlen(val);
969 /* comma and space, and [] around default val */
970 int extra_len = 2 * (i != 0) + 2 * (i == dflt_idx);
971 bool cr = line_len + val_len + extra_len > max_len;
972 if (cr) {
973 line_len = indent_len + pfx_len;
974 len += 1 + indent_len + pfx_len; /* +1 for \n */
975 }
976 len += val_len + extra_len;
977 line_len += val_len + extra_len;
978 }
979 *result = malloc(len + 1); /* +1 for terminating zero byte */
980 if (!*result)
981 return -E_LLS_NOMEM;
982 p = *result + sprintf(*result, "%.*s%s", indent_len, space, pfx);
983 line_len = p - *result;
984 for (i = 0; (val = opt->values[i].string_val); i++) {
985 size_t val_len = strlen(val);
986 int extra_len = 2 * (i != 0) + 2 * (i == dflt_idx);
987 bool cr = line_len + val_len + extra_len > max_len;
988 p += sprintf(p,
989 "%s"
990 "%s"
991 "%.*s"
992 "%s%s%s",
993 i == 0? "" : ", ",
994 cr? "\n" : "",
995 cr? pfx_len + indent_len : 0, cr? space : "",
996 i == dflt_idx? "[" : "", val, i == dflt_idx? "]" : ""
997 );
998 if (cr)
999 line_len = indent_len + pfx_len;
1000 line_len += val_len + extra_len;
1001 }
1002 return 1;
1003 }
1004
1005 static char *create_help_buf(const struct lls_command *cmd, bool long_help)
1006 {
1007 char *header, *option_help, *result;
1008 const struct lls_option *opt;
1009 int ret;
1010 const char *desc = (long_help && cmd->description)?
1011 cmd->description : "";
1012 const char *closing = (long_help && cmd->closing)? cmd->closing : NULL;
1013
1014 result = NULL;
1015 header = NULL;
1016 ret = xasprintf(&header,
1017 "%s - %s\n\n"
1018 "Usage: %s %s\n"
1019 "%s%s"
1020 ,
1021 cmd->name, cmd->purpose,
1022 cmd->name, cmd->synopsis,
1023 desc,
1024 cmd->options? "\n" : ""
1025 );
1026 if (ret < 0)
1027 return NULL;
1028 if (!cmd->options)
1029 return header;
1030 option_help = NULL;
1031 FOR_EACH_OPTION_IN_COMMAND(opt, cmd) {
1032 char *tmp, *soh, *loh = NULL, *dflt, *values;
1033 int indent = (opt->flags & LLS_IGNORED)? 0 : HELP_INDENT;
1034
1035 ret = short_option_help(opt, &soh);
1036 if (ret < 0)
1037 goto out;
1038 if (long_help && opt->help) {
1039 const char *p, *q;
1040 for (p = opt->help; (q = strchr(p, '\n')); p = q + 1) {
1041 tmp = NULL;
1042 ret = xasprintf(&tmp, "%s%.*s%.*s",
1043 loh? loh : "\n", indent, space,
1044 (int)(q - p + 1), p);
1045 free(loh);
1046 if (ret < 0) {
1047 free(soh);
1048 goto out;
1049 }
1050 loh = tmp;
1051 }
1052 }
1053 ret = format_default_val(opt, &dflt);
1054 if (ret < 0) {
1055 free(soh);
1056 free(loh);
1057 goto out;
1058 }
1059 if (long_help) {
1060 ret = format_values(opt, &values);
1061 if (ret < 0) {
1062 free(dflt);
1063 free(soh);
1064 free(loh);
1065 goto out;
1066 }
1067 } else
1068 values = NULL;
1069 tmp = NULL;
1070 ret = xasprintf(&tmp,
1071 "%s"
1072 "%s"
1073 "%s%s%s"
1074 "%s%s"
1075 "%s\n",
1076 option_help? option_help : "",
1077 soh ? soh : "",
1078 dflt? "\n" : "", dflt? space : "", dflt? dflt : "",
1079 values? "\n" : "", values? values : "",
1080 loh? loh : ""
1081 );
1082 free(values);
1083 free(dflt);
1084 free(soh);
1085 free(loh);
1086 if (ret < 0)
1087 goto out;
1088 free(option_help);
1089 option_help = tmp;
1090 }
1091 ret = xasprintf(&result, "%s%s%s%s", header, option_help,
1092 closing? "\n" : "", closing? closing : "");
1093 out:
1094 free(header);
1095 free(option_help);
1096 return ret < 0? NULL : result;
1097 }
1098
1099 char *lls_long_help(const struct lls_command *cmd)
1100 {
1101 return create_help_buf(cmd, true /* include help */);
1102 }
1103
1104 char *lls_short_help(const struct lls_command *cmd)
1105 {
1106 return create_help_buf(cmd, false /* only options */);
1107 }
1108
1109 static int partial_match(const char *arg, const char *name)
1110 {
1111 size_t arglen = strlen(arg);
1112
1113 if (strncmp(arg, name, arglen) != 0)
1114 return 1; /* no match */
1115 if (name[arglen] == '\0')
1116 return 0; /* exact match */
1117 return -1; /* partial match */
1118 }
1119
1120 int lls_lookup_subcmd(const char *string, const struct lls_suite *suite,
1121 char **errctx)
1122 {
1123 int i, ret;
1124
1125 if (errctx)
1126 *errctx = NULL;
1127 if (!string) {
1128 xasprintf(errctx, "nothing to look up");
1129 return -E_LLS_BAD_SUBCMD;
1130 }
1131 ret = 0; /* no match so far */
1132 for (i = 1; i <= suite->num_subcommands; i++) {
1133 switch (partial_match(string, suite->commands[i].name)) {
1134 case 1: /* no match */
1135 continue;
1136 case 0: /* exact match */
1137 return i;
1138 case -1: /* partial match */
1139 if (ret > 0) {
1140 ret = -E_LLS_AMBIG_SUBCMD;
1141 goto fail;
1142 }
1143 ret = i;
1144 }
1145 }
1146 if (ret > 0) /* unique partial match */
1147 return ret;
1148 ret = -E_LLS_BAD_SUBCMD;
1149 fail:
1150 xasprintf(errctx, "%s", string);
1151 return ret;
1152 }
1153
1154 static size_t get_opt_result_pointer(const struct lls_option *opt, int val_num,
1155 struct lls_opt_result *lor, void **result)
1156 {
1157 union lls_val *val = lor->value + val_num;
1158
1159 switch (opt->arg_type) {
1160 case LLS_INT32:
1161 *result = &val->int32_val;
1162 return 4;
1163 case LLS_UINT32:
1164 *result = &val->uint32_val;
1165 return 4;
1166 case LLS_INT64:
1167 *result = &val->int64_val;
1168 return 8;
1169 case LLS_UINT64:
1170 *result = &val->uint64_val;
1171 return 8;
1172 default:
1173 assert(0);
1174 }
1175 }
1176
1177 /* never fails, returns number of bytes needed/written */
1178 static size_t serialize_parse_result(const struct lls_parse_result *lpr,
1179 const struct lls_command *cmd, char *result)
1180 {
1181 int i, j;
1182 size_t nbytes;
1183
1184 /* num_inputs */
1185 if (result)
1186 memcpy(result, &lpr->num_inputs, 4);
1187 nbytes = 4;
1188
1189 /* inputs */
1190 for (i = 0; i < lpr->num_inputs; i++) {
1191 if (result)
1192 strcpy(result + nbytes, lpr->inputs[i]);
1193 nbytes += strlen(lpr->inputs[i]) + 1;
1194 }
1195 /* options */
1196 FOR_EACH_OPTION(i, cmd->options) {
1197 const struct lls_option *opt = cmd->options + i;
1198 struct lls_opt_result *lor = lpr->opt_result + i;
1199 unsigned num_vals;
1200
1201 if (result)
1202 memcpy(result + nbytes, &lor->given, 4);
1203 nbytes += 4;
1204 if (opt->arg_info == LLS_NO_ARGUMENT)
1205 continue;
1206 num_vals = num_vals_in_parse_result(cmd, i, lpr);
1207 if (opt->arg_type == LLS_STRING && !opt->values) {
1208 for (j = 0; j < num_vals; j++) {
1209 if (result)
1210 strcpy(result + nbytes,
1211 lor->value[j].string_val);
1212 nbytes += strlen(lor->value[j].string_val) + 1;
1213 }
1214 } else {
1215 for (j = 0; j < num_vals; j++) {
1216 size_t bytes;
1217 void *p;
1218 bytes = get_opt_result_pointer(opt, j, lor, &p);
1219 if (result)
1220 memcpy(result + nbytes, p, bytes);
1221 nbytes += bytes;
1222 }
1223 }
1224 }
1225 return nbytes;
1226 }
1227
1228 int lls_serialize_parse_result(const struct lls_parse_result *lpr,
1229 const struct lls_command *cmd, char **result, size_t *nbytes)
1230 {
1231 size_t sz;
1232 int ret;
1233
1234 if (!result || !*result) { /* need to compute needed space */
1235 sz = serialize_parse_result(lpr, cmd, NULL);
1236 if (!result) { /* just report needed space */
1237 ret = 0;
1238 goto out;
1239 }
1240 *result = malloc(sz);
1241 if (!*result) {
1242 sz = 0;
1243 ret = -E_LLS_NOMEM;
1244 goto out;
1245 }
1246 }
1247 /* serialize it */
1248 sz = serialize_parse_result(lpr, cmd, *result);
1249 ret = 1;
1250 out:
1251 if (nbytes)
1252 *nbytes = sz;
1253 return ret;
1254 }
1255
1256 int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd,
1257 struct lls_parse_result **lprp)
1258 {
1259 int i, j;
1260 const char *p = buf;
1261 struct lls_parse_result *lpr;
1262
1263 *lprp = NULL;
1264 lpr = malloc(sizeof(*lpr));
1265 if (!lpr)
1266 return -E_LLS_NOMEM;
1267 memcpy(&lpr->num_inputs, p, 4);
1268 p += 4;
1269 if (lpr->num_inputs > 0) {
1270 lpr->inputs = malloc(lpr->num_inputs * sizeof(char *));
1271 if (!lpr->inputs)
1272 goto free_lpr;
1273 } else
1274 lpr->inputs = NULL;
1275 for (i = 0; i < lpr->num_inputs; i++) {
1276 lpr->inputs[i] = strdup(p);
1277 if (!lpr->inputs[i])
1278 goto free_inputs;
1279 p += strlen(p) + 1;
1280 }
1281 lpr->opt_result = malloc(cmd->num_options * sizeof(*lpr->opt_result));
1282 if (!lpr->opt_result)
1283 goto free_inputs;
1284 FOR_EACH_OPTION(i, cmd->options) {
1285 const struct lls_option *opt = cmd->options + i;
1286 struct lls_opt_result *lor = lpr->opt_result + i;
1287 uint32_t num_vals;
1288
1289 memcpy(&lor->given, p, 4);
1290 p += 4;
1291 if (opt->arg_info == LLS_NO_ARGUMENT)
1292 continue;
1293 num_vals = num_vals_in_parse_result(cmd, i, lpr);
1294 lor->value = malloc(num_vals * sizeof(*lor->value));
1295 if (!lor->value)
1296 goto free_options;
1297 if (opt->arg_type == LLS_STRING && !opt->values) {
1298 for (j = 0; j < num_vals; j++) {
1299 lor->value[j].string_val = strdup(p);
1300 if (!lor->value[j].string_val) {
1301 for (; j >= 0; j--)
1302 free(lor->value[j].string_val);
1303 free(lor->value);
1304 goto free_options;
1305 }
1306 p += strlen(lor->value[j].string_val) + 1;
1307 }
1308 } else {
1309 for (j = 0; j < num_vals; j++) {
1310 size_t bytes;
1311 void *q;
1312 bytes = get_opt_result_pointer(opt, j, lor, &q);
1313 memcpy(q, p, bytes);
1314 p += bytes;
1315 }
1316 }
1317 }
1318 *lprp = lpr;
1319 return 1;
1320 free_options:
1321 for (i--; i >= 0; i--) {
1322 const struct lls_option *opt = cmd->options + i;
1323 struct lls_opt_result *lor = lpr->opt_result + i;
1324 unsigned num_vals = (opt->flags & LLS_MULTIPLE)? lor->given : 1;
1325 for (j = 0; j < num_vals; j++)
1326 if (opt->arg_type == LLS_STRING && !opt->values)
1327 free(lor->value[j].string_val);
1328 free(lor->value);
1329 }
1330 free(lpr->opt_result);
1331 free_inputs:
1332 for (; i >= 0; i--)
1333 free(lpr->inputs[i]);
1334 free(lpr->inputs);
1335 free_lpr:
1336 free(lpr);
1337 return -E_LLS_NOMEM;
1338 }
1339
1340 static int merge_option(int opt_num, const struct lls_parse_result *primary,
1341 const struct lls_parse_result *secondary,
1342 const struct lls_command *cmd, struct lls_parse_result *result,
1343 char **errctx)
1344 {
1345 int l, m, ret;
1346 const struct lls_option *opt = cmd->options + opt_num;
1347 struct lls_opt_result *lor1, *lor2, *lor;
1348
1349 lor1 = primary->opt_result + opt_num;
1350 lor2 = secondary->opt_result + opt_num;
1351 lor = result->opt_result + opt_num;
1352 lor->given = lor1->given + lor2->given;
1353 if (opt->arg_info == LLS_NO_ARGUMENT)
1354 return 0;
1355 if (lor->given > 0 && (opt->flags & LLS_MULTIPLE)) {
1356 lor->value = malloc(lor->given * sizeof(*lor->value));
1357 if (!lor->value) {
1358 xasprintf(errctx, "value array for option %s", opt->name);
1359 goto fail;
1360 }
1361 for (l = 0; l < lor1->given; l++) {
1362 ret = copy_val(lor->value + l, lor1->value + l,
1363 opt, errctx);
1364 if (ret < 0)
1365 goto free_primary_options;
1366 }
1367 for (m = 0; m < lor2->given; m++) {
1368 ret = copy_val(lor->value + l + m, lor2->value + m,
1369 opt, errctx);
1370 if (ret < 0)
1371 goto free_secondary_options;
1372 }
1373 return 1;
1374 }
1375 lor->value = malloc(sizeof(*lor->value)); /* one value only */
1376 if (!lor->value) {
1377 xasprintf(errctx, "(single) value for option %s", opt->name);
1378 goto fail;
1379 }
1380 if (lor1->given) {
1381 ret = copy_val(lor->value, lor1->value, opt, errctx);
1382 if (ret < 0)
1383 goto free_value;
1384 } else if (lor2->given) {
1385 ret = copy_val(lor->value, lor2->value, opt, errctx);
1386 if (ret < 0)
1387 goto free_value;
1388 } else {
1389 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
1390 if (ret < 0)
1391 goto free_value;
1392 }
1393 return 1;
1394 free_secondary_options:
1395 if (opt->arg_type == LLS_STRING && !opt->values)
1396 for (m--; m >= 0; m--)
1397 free(lor->value[l + m].string_val);
1398 free_primary_options:
1399 if (opt->arg_type == LLS_STRING && !opt->values)
1400 for (l--; l >= 0; l--)
1401 free(lor->value[l].string_val);
1402 free_value:
1403 free(lor->value);
1404 fail:
1405 return -E_LLS_NOMEM;
1406 }
1407
1408 int lls_merge(const struct lls_parse_result *primary,
1409 const struct lls_parse_result *secondary,
1410 const struct lls_command *cmd, struct lls_parse_result **lprp,
1411 char **errctx)
1412 {
1413 int i, j, k, ret;
1414 unsigned num = primary->num_inputs + secondary->num_inputs;
1415 struct lls_parse_result *result;
1416
1417 if (errctx)
1418 *errctx = NULL;
1419 result = malloc(sizeof(*result));
1420 if (!result) {
1421 ret = -E_LLS_NOMEM;
1422 xasprintf(errctx, "parse result");
1423 goto fail;
1424 }
1425 result->inputs = malloc((num + 1) * sizeof(char *));
1426 if (!result->inputs) {
1427 ret = -E_LLS_NOMEM;
1428 xasprintf(errctx, "inputs array of size %u", num);
1429 goto free_parse_result;
1430 }
1431 for (i = 0; i < primary->num_inputs; i++) {
1432 result->inputs[i] = strdup(primary->inputs[i]);
1433 if (!result->inputs[i]) {
1434 ret = -E_LLS_NOMEM;
1435 xasprintf(errctx, "primary input #%d", i);
1436 goto free_primary_inputs;
1437 }
1438 }
1439 for (j = 0; j < secondary->num_inputs; j++) {
1440 result->inputs[i + j] = strdup(secondary->inputs[j]);
1441 if (!result->inputs[i + j]) {
1442 ret = -E_LLS_NOMEM;
1443 xasprintf(errctx, "secondary input #%d", i);
1444 goto free_secondary_inputs;
1445 }
1446 }
1447 result->inputs[i + j] = NULL;
1448 result->opt_result = malloc(cmd->num_options
1449 * sizeof(*result->opt_result));
1450 if (!result->opt_result)
1451 goto free_secondary_inputs;
1452 FOR_EACH_OPTION(k, cmd->options) {
1453 ret = merge_option(k, primary, secondary, cmd, result, errctx);
1454 if (ret < 0)
1455 goto free_opt_results;
1456 }
1457 result->num_inputs = num;
1458 *lprp = result;
1459 ret = 1;
1460 goto out;
1461 free_opt_results:
1462 for (k--; k >= 0; k--)
1463 free_opt_result(k, result, cmd);
1464 free_secondary_inputs:
1465 for (j--; j >= 0; j--)
1466 free(result->inputs[i + j]);
1467 free_primary_inputs:
1468 for (i--; i >= 0; i--)
1469 free(result->inputs[i]);
1470 free(result->inputs);
1471 free_parse_result:
1472 free(result);
1473 fail:
1474 assert(ret < 0);
1475 *lprp = NULL;
1476 out:
1477 check_errctx(errctx, ret);
1478 return ret;
1479 }
1480
1481 static bool is_default_val(const union lls_val *val,
1482 const struct lls_option *opt)
1483 {
1484 bool has_default = opt->flags & LLS_HAS_DEFAULT;
1485 bool has_arg = opt->arg_info != LLS_NO_ARGUMENT;
1486 const union lls_val *dflt;
1487
1488 if (!has_arg)
1489 return false;
1490 if (!has_default)
1491 return false;
1492 dflt = &opt->default_val;
1493 switch (opt->arg_type) {
1494 case LLS_INT32:
1495 return val->int32_val == dflt->int32_val;
1496 case LLS_UINT32:
1497 return val->uint32_val == dflt->uint32_val;
1498 case LLS_INT64:
1499 return val->int64_val == dflt->int64_val;
1500 case LLS_UINT64:
1501 return val->uint64_val == dflt->uint64_val;
1502 case LLS_STRING:
1503 {
1504 const char *s1, *s2;
1505
1506 if (opt->values)
1507 return val->uint32_val == dflt->uint32_val;
1508 s1 = val->string_val;
1509 s2 = dflt->string_val;
1510 if (!s1 && !s2)
1511 return true;
1512 if (!s1 || !s2)
1513 return false;
1514 return !strcmp(s1, s2);
1515 }
1516 default:
1517 assert(0);
1518 }
1519 }
1520
1521 static char *append_opt_val(const union lls_val *val,
1522 const struct lls_option *opt, char *result)
1523 {
1524 char *line = NULL, *tmp = NULL;
1525
1526 switch (opt->arg_type) {
1527 case LLS_INT32:
1528 xasprintf(&line, "%" PRId32, val->int32_val);
1529 break;
1530 case LLS_UINT32:
1531 xasprintf(&line, "%" PRIu32, val->uint32_val);
1532 break;
1533 case LLS_INT64:
1534 xasprintf(&line, "%" PRId64, val->int64_val);
1535 break;
1536 case LLS_UINT64:
1537 xasprintf(&line, "%" PRIu64, val->uint64_val);
1538 break;
1539 case LLS_STRING:
1540 {
1541 const char *s, *p;
1542 char *q;
1543
1544 if (opt->values)
1545 s = lls_enum_string_val(val->uint32_val, opt);
1546 else {
1547 s = val->string_val;
1548 if (!s)
1549 return result;
1550 }
1551 line = malloc(2 * strlen(s) + 3);
1552 if (!line) {
1553 free(result);
1554 return NULL;
1555 }
1556 line[0] = '"';
1557 for (p = s, q = line + 1; *p; p++, q++) {
1558 if (*p == '\\' || *p == '\n' || *p == '\t' || *p == '"') {
1559 *q = '\\';
1560 q++;
1561 }
1562 *q = *p;
1563 }
1564 q[0] = '"';
1565 q[1] = '\0';
1566 break;
1567 }
1568 default:
1569 assert(0);
1570 }
1571 xasprintf(&tmp, "%s%s=%s\n", result? result : "", opt->name, line);
1572 free(line);
1573 free(result);
1574 return tmp;
1575 }
1576
1577 char *lls_dump_parse_result(const struct lls_parse_result *lpr,
1578 const struct lls_command *cmd, bool non_default_only)
1579 {
1580 int i;
1581 char *result = NULL;
1582
1583 FOR_EACH_OPTION(i, cmd->options) {
1584 const struct lls_option *opt = cmd->options + i;
1585 struct lls_opt_result *lor = lpr->opt_result + i;
1586 bool given = lor->given;
1587 int j, n;
1588
1589 if (!given && non_default_only)
1590 continue;
1591 if (opt->arg_info == LLS_NO_ARGUMENT) {
1592 char *tmp = NULL;
1593 if (!given)
1594 continue;
1595 xasprintf(&tmp, "%s%s\n", result? result : "",
1596 opt->name);
1597 free(result);
1598 result = tmp;
1599 continue;
1600 }
1601 n = num_vals_in_parse_result(cmd, i, lpr);
1602 for (j = 0; j < n; j++) {
1603 union lls_val *val = lor->value + j;
1604 if (non_default_only && is_default_val(val, opt))
1605 continue;
1606 result = append_opt_val(val, opt, result);
1607 }
1608 }
1609 if (!result) { /* empty dump */
1610 result = malloc(1);
1611 if (result)
1612 result[0] = '\0';
1613 }
1614 return result;
1615 }