]> git.tuebingen.mpg.de Git - lopsub.git/blob - lopsub.c
debian: Final version of 64-bit time_t transition.
[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 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)
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 && opt->arg_info == LLS_NO_ARGUMENT) {
636                 xasprintf(errctx, "arg: %s, option: %s", la->arg, opt->name);
637                 return -E_LLS_ARG_GIVEN;
638         }
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);
643                         free(lor->value);
644                         lor->value = NULL;
645                 }
646         }
647         if (!la->arg)
648                 goto success;
649         idx = multiple? lor->given : 0;
650         if (!lor->value || multiple) {
651                 ret = xrealloc(&lor->value, (idx + 1) * sizeof(*lor->value));
652                 if (ret < 0) {
653                         xasprintf(errctx, "option value array for --%s",
654                                 opt->name);
655                         return ret;
656                 }
657         }
658         switch (opt->arg_type) {
659         case LLS_STRING:
660                 if (opt->values) {
661                         ret = check_enum_arg(la->arg, opt, errctx);
662                         if (ret < 0)
663                                 return ret;
664                         lor->value[idx].uint32_val = ret;
665                 } else {
666                         lor->value[idx].string_val = strdup(la->arg);
667                         if (!lor->value[idx].string_val) {
668                                 xasprintf(errctx, "string value for %s",
669                                         opt->name);
670                                 return -E_LLS_NOMEM;
671                         }
672                 }
673                 break;
674         case LLS_INT32:
675                 ret = atoi32(la->arg, &lor->value[idx].int32_val);
676                 if (ret < 0)
677                         goto atoi_error;
678                 break;
679         case LLS_UINT32:
680                 ret = atou32(la->arg, &lor->value[idx].uint32_val);
681                 if (ret < 0)
682                         goto atoi_error;
683                 break;
684         case LLS_INT64:
685                 ret = atoi64(la->arg, &lor->value[idx].int64_val);
686                 if (ret < 0)
687                         goto atoi_error;
688                 break;
689         case LLS_UINT64:
690                 ret = atou64(la->arg, &lor->value[idx].uint64_val);
691                 if (ret < 0)
692                         goto atoi_error;
693                 break;
694         default:
695                 assert(false);
696         }
697 success:
698         lor->given++;
699         return 1;
700 atoi_error:
701         assert(ret < 0);
702         xasprintf(errctx, "conversion error for argument \"%s\" to option --%s",
703                 la->arg, opt->name);
704         return ret;
705 }
706
707 static int copy_val(union lls_val *dst, const union lls_val *src,
708                 const struct lls_option *opt, char **errctx)
709 {
710         if (opt->arg_type != LLS_STRING || opt->values) {
711                 *dst = *src;
712                 return 0;
713         }
714         if (!src->string_val) {
715                 dst->string_val = NULL;
716                 return 0;
717         }
718         dst->string_val = strdup(src->string_val);
719         if (!dst->string_val) {
720                 xasprintf(errctx, "copy value for --%s", opt->name);
721                 return -E_LLS_NOMEM;
722         }
723         return 1;
724 }
725
726 int lls_check_arg_count(const struct lls_parse_result *lpr,
727                 int min_argc, int max_argc, char **errctx)
728 {
729         if (errctx)
730                 *errctx = NULL;
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;
737         }
738         if (lpr->num_inputs > max_argc) {
739                 if (max_argc == 0)
740                         xasprintf(errctx, "no non-option args allowed, "
741                                 "%u given", lpr->num_inputs);
742                 else
743                         xasprintf(errctx, "%s %u non-option args %s, %u given",
744                                 min_argc < max_argc? "at most" : "exactly",
745                                 max_argc,
746                                 min_argc < max_argc? "allowed" : "required",
747                                 lpr->num_inputs);
748                 return -E_LLS_BAD_ARG_COUNT;
749         }
750         return 1;
751 }
752
753 /*
754  * Unlike getopt(3) this implementation can not resume the scan where it left
755  * off.
756  */
757 int lls_parse(int argc, char **argv, const struct lls_command *cmd,
758                 struct lls_parse_result **lprp, char **errctx)
759 {
760         const struct lls_option *opts = cmd->options;
761         struct lls_data *d = NULL;
762         int i, ret;
763         struct lls_arg la;
764         struct lls_parse_result *lpr;
765
766         if (errctx)
767                 *errctx = NULL;
768         lpr = calloc(1, sizeof(*lpr));
769         if (!lpr) {
770                 xasprintf(errctx, "log parse result");
771                 ret = -E_LLS_NOMEM;
772                 goto out;
773         }
774         d = init_lls_data(opts, argc, argv);
775         if (!d) {
776                 xasprintf(errctx, "init_lls_data()");
777                 ret = -E_LLS_NOMEM;
778                 goto out;
779         }
780         if (cmd->num_options == 0) {
781                 la.idx = 0;
782                 lpr->opt_result = NULL;
783         } else {
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",
788                                 cmd->name);
789                         ret = -E_LLS_NOMEM;
790                         goto out;
791                 }
792                 for (;;) {
793                         ret = parse_option(d, &la, errctx);
794                         if (ret < 0)
795                                 goto out;
796                         if (ret == 0)
797                                 break;
798                         ret = lls_parse_arg(&la, opts, lpr, errctx);
799                         if (ret < 0)
800                                 goto out;
801                 }
802         }
803         lpr->num_inputs = argc - la.idx - 1;
804         if (!cmd->non_opts_name) {
805                 ret = lls_check_arg_count(lpr, 0, 0, errctx);
806                 if (ret < 0) {
807                         /* needed for lls_free_parse_result() */
808                         lpr->inputs = NULL;
809                         goto out;
810                 }
811         }
812         /* We always make a copy of the elements of argv[] */
813         lpr->inputs = malloc((lpr->num_inputs + 1) * sizeof(char *));
814         if (!lpr->inputs) {
815                 xasprintf(errctx, "inputs array for %s", cmd->name);
816                 ret = -E_LLS_NOMEM;
817                 goto out;
818         }
819         for (i = 0; i < lpr->num_inputs; i++) {
820                 char *arg = argv[i + la.idx + 1];
821                 lpr->inputs[i] = strdup(arg);
822                 if (lpr->inputs[i])
823                         continue;
824                 xasprintf(errctx, "option #%d (%s) of %s", i, arg, cmd->name);
825                 ret = -E_LLS_NOMEM;
826                 goto out;
827         }
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;
835
836                 if (lor->given == 0 && required) {
837                         xasprintf(errctx, "--%s", opt->name);
838                         ret = -E_LLS_OPT_MANDATORY;
839                         goto out;
840                 }
841                 if (lor->value)
842                         continue;
843                 if (!has_arg)
844                         continue;
845                 /*
846                  * allocate space for the default value, even if there is no
847                  * default given in the .suite file
848                  */
849                 lor->value = malloc(sizeof(*lor->value));
850                 if (!lor->value) {
851                         xasprintf(errctx, "value array for --%s", opt->name);
852                         ret = -E_LLS_NOMEM;
853                         goto out;
854                 }
855                 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
856                 if (ret < 0)
857                         goto out;
858         }
859         ret = 1;
860 out:
861         free(d);
862         check_errctx(errctx, ret);
863         if (ret < 0) {
864                 lls_free_parse_result(lpr, cmd);
865                 *lprp = NULL;
866         } else
867                 *lprp = lpr;
868         return ret;
869 }
870
871 #define MAX_OPTION_LEN 30
872 #define HELP_INDENT 6
873 static const char space[MAX_OPTION_LEN + 1] = "                              ";
874
875 static int short_option_help(const struct lls_option *opt, char **result)
876 {
877         int ret = 0;
878         char *opt_names = NULL;
879         bool overlong, has_short = opt->short_opt;
880         const char *typestr;
881
882         *result = NULL;
883         if (opt->flags & LLS_IGNORED)
884                 return xasprintf(result, "%s", opt->summary);
885         if (opt->arg_info == LLS_NO_ARGUMENT)
886                 typestr = "";
887         else
888                 typestr = opt->typestr? opt->typestr : "val";
889
890         ret = xasprintf(&opt_names,
891                 "%s%c%s"
892                 " --%s"
893                 "%s%s%s%s%s"
894                 ,
895                 has_short? "  -" : "   ",
896                 has_short? opt->short_opt : ' ',
897                 has_short? "," : " ",
898                 opt->name,
899                 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "[" : "",
900                 opt->arg_info == LLS_NO_ARGUMENT? "" : "=<",
901                 typestr,
902                 opt->arg_info == LLS_NO_ARGUMENT? "" : ">",
903                 opt->arg_info == LLS_OPTIONAL_ARGUMENT? "]" : ""
904         );
905         if (ret < 0)
906                 return ret;
907         overlong = ret >= MAX_OPTION_LEN;
908         ret = xasprintf(result,
909                 "%s"
910                 "%s"
911                 "%s"
912                 "%s"
913                 ,
914                 opt_names,
915                 overlong? "\n" : "",
916                 overlong? space : space + ret,
917                 opt->summary? opt->summary : ""
918         );
919         free(opt_names);
920         return ret;
921 }
922
923 static int format_default_val(const struct lls_option *opt, char **result)
924 {
925         const union lls_val *val = &opt->default_val;
926
927         *result = NULL;
928         if (opt->arg_info == LLS_NO_ARGUMENT)
929                 return 0;
930         if (!(opt->flags & LLS_HAS_DEFAULT))
931                 return 0;
932         switch (opt->arg_type) {
933         case LLS_STRING:
934                 if (opt->values)
935                         return 0;
936                 return xasprintf(result, "(string, default: %s)",
937                         val->string_val? val->string_val : "[NULL]");
938         case LLS_INT32:
939                 return xasprintf(result, "(int32, default: %" PRId32 ")",
940                         val->int32_val);
941         case LLS_UINT32:
942                 return xasprintf(result, "(uint32, default: %" PRIu32 ")",
943                         val->uint32_val);
944         case LLS_INT64:
945                 return xasprintf(result, "(int64, default: %" PRId64 ")",
946                         val->int64_val);
947         case LLS_UINT64:
948                 return xasprintf(result, "(uint64, default: %" PRIu64 ")",
949                         val->uint64_val);
950         default:
951                 assert(0);
952         }
953         return 1;
954 }
955
956 static int format_values(const struct lls_option *opt, char **result)
957 {
958         int i;
959         uint32_t dflt_idx;
960         const char *val, *pfx = "values: ";
961         size_t len, line_len;
962         const int indent_len = 6, max_len = 75, pfx_len = 8;
963         char *p;
964
965         *result = NULL;
966         if (!opt->values)
967                 return 0;
968         assert(opt->arg_type == LLS_STRING);
969         dflt_idx = opt->default_val.uint32_val;
970         line_len = indent_len + pfx_len;
971         len = line_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;
977                 if (cr) {
978                         line_len = indent_len + pfx_len;
979                         len += 1 + indent_len + pfx_len; /* +1 for \n */
980                 }
981                 len += val_len + extra_len;
982                 line_len += val_len + extra_len;
983         }
984         *result = malloc(len + 1); /* +1 for terminating zero byte */
985         if (!*result)
986                 return -E_LLS_NOMEM;
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;
993                 p += sprintf(p,
994                         "%s"
995                         "%s"
996                         "%.*s"
997                         "%s%s%s",
998                         i == 0? "" : ", ",
999                         cr? "\n" : "",
1000                         cr? pfx_len + indent_len : 0, cr? space : "",
1001                         i == dflt_idx? "[" : "", val, i == dflt_idx? "]" : ""
1002                 );
1003                 if (cr)
1004                         line_len = indent_len + pfx_len;
1005                 line_len += val_len + extra_len;
1006         }
1007         return 1;
1008 }
1009
1010 static char *create_help_buf(const struct lls_command *cmd, bool long_help)
1011 {
1012         char *header, *option_help, *result;
1013         const struct lls_option *opt;
1014         int ret;
1015         const char *desc = (long_help && cmd->description)?
1016                 cmd->description : "";
1017         const char *closing = (long_help && cmd->closing)? cmd->closing : NULL;
1018
1019         result = NULL;
1020         header = NULL;
1021         ret = xasprintf(&header,
1022                 "%s - %s\n\n"
1023                 "Usage: %s %s\n"
1024                 "%s%s"
1025         ,
1026                 cmd->name, cmd->purpose,
1027                 cmd->name, cmd->synopsis,
1028                 desc,
1029                 cmd->options? "\n" : ""
1030         );
1031         if (ret < 0)
1032                 return NULL;
1033         if (!cmd->options)
1034                 return header;
1035         option_help = NULL;
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;
1039
1040                 ret = short_option_help(opt, &soh);
1041                 if (ret < 0)
1042                         goto out;
1043                 if (long_help && opt->help) {
1044                         const char *p, *q;
1045                         for (p = opt->help; (q = strchr(p, '\n')); p = q + 1) {
1046                                 tmp = NULL;
1047                                 ret = xasprintf(&tmp, "%s%.*s%.*s",
1048                                         loh? loh : "\n", indent, space,
1049                                         (int)(q - p + 1), p);
1050                                 free(loh);
1051                                 if (ret < 0) {
1052                                         free(soh);
1053                                         goto out;
1054                                 }
1055                                 loh = tmp;
1056                         }
1057                 }
1058                 ret = format_default_val(opt, &dflt);
1059                 if (ret < 0) {
1060                         free(soh);
1061                         free(loh);
1062                         goto out;
1063                 }
1064                 if (long_help) {
1065                         ret = format_values(opt, &values);
1066                         if (ret < 0) {
1067                                 free(dflt);
1068                                 free(soh);
1069                                 free(loh);
1070                                 goto out;
1071                         }
1072                 } else
1073                         values = NULL;
1074                 tmp = NULL;
1075                 ret = xasprintf(&tmp,
1076                         "%s"
1077                         "%s"
1078                         "%s%s%s"
1079                         "%s%s"
1080                         "%s\n",
1081                         option_help? option_help : "",
1082                         soh ? soh : "",
1083                         dflt? "\n" : "", dflt? space : "", dflt? dflt : "",
1084                         values? "\n" : "", values? values : "",
1085                         loh? loh : ""
1086                 );
1087                 free(values);
1088                 free(dflt);
1089                 free(soh);
1090                 free(loh);
1091                 if (ret < 0)
1092                         goto out;
1093                 free(option_help);
1094                 option_help = tmp;
1095         }
1096         ret = xasprintf(&result, "%s%s%s%s", header, option_help,
1097                 closing? "\n" : "", closing? closing : "");
1098 out:
1099         free(header);
1100         free(option_help);
1101         return ret < 0? NULL : result;
1102 }
1103
1104 char *lls_long_help(const struct lls_command *cmd)
1105 {
1106         return create_help_buf(cmd, true /* include help */);
1107 }
1108
1109 char *lls_short_help(const struct lls_command *cmd)
1110 {
1111         return create_help_buf(cmd, false /* only options */);
1112 }
1113
1114 static int partial_match(const char *arg, const char *name)
1115 {
1116         size_t arglen = strlen(arg);
1117
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 */
1123 }
1124
1125 int lls_lookup_subcmd(const char *string, const struct lls_suite *suite,
1126                 char **errctx)
1127 {
1128         int i, ret;
1129
1130         if (errctx)
1131                 *errctx = NULL;
1132         if (!string) {
1133                 xasprintf(errctx, "nothing to look up");
1134                 return -E_LLS_BAD_SUBCMD;
1135         }
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 */
1140                         continue;
1141                 case 0: /* exact match */
1142                         return i;
1143                 case -1: /* partial match */
1144                         if (ret > 0) {
1145                                 ret = -E_LLS_AMBIG_SUBCMD;
1146                                 goto fail;
1147                         }
1148                         ret = i;
1149                 }
1150         }
1151         if (ret > 0) /* unique partial match */
1152                 return ret;
1153         ret = -E_LLS_BAD_SUBCMD;
1154 fail:
1155         xasprintf(errctx, "%s", string);
1156         return ret;
1157 }
1158
1159 static size_t get_opt_result_pointer(const struct lls_option *opt, int val_num,
1160                 struct lls_opt_result *lor, void **result)
1161 {
1162         union lls_val *val = lor->value + val_num;
1163
1164         switch (opt->arg_type) {
1165         case LLS_INT32:
1166                 *result = &val->int32_val;
1167                 return 4;
1168         case LLS_UINT32:
1169                 *result = &val->uint32_val;
1170                 return 4;
1171         case LLS_INT64:
1172                 *result = &val->int64_val;
1173                 return 8;
1174         case LLS_UINT64:
1175                 *result = &val->uint64_val;
1176                 return 8;
1177         default:
1178                 assert(0);
1179         }
1180 }
1181
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)
1185 {
1186         int i, j;
1187         size_t nbytes;
1188
1189         /* num_inputs */
1190         if (result)
1191                 memcpy(result, &lpr->num_inputs, 4);
1192         nbytes = 4;
1193
1194         /* inputs */
1195         for (i = 0; i < lpr->num_inputs; i++) {
1196                 if (result)
1197                         strcpy(result + nbytes, lpr->inputs[i]);
1198                 nbytes += strlen(lpr->inputs[i]) + 1;
1199         }
1200         /* options */
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;
1204                 unsigned num_vals;
1205
1206                 if (result)
1207                         memcpy(result + nbytes, &lor->given, 4);
1208                 nbytes += 4;
1209                 if (opt->arg_info == LLS_NO_ARGUMENT)
1210                         continue;
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++) {
1214                                 if (result)
1215                                         strcpy(result + nbytes,
1216                                                 lor->value[j].string_val);
1217                                 nbytes += strlen(lor->value[j].string_val) + 1;
1218                         }
1219                 } else {
1220                         for (j = 0; j < num_vals; j++) {
1221                                 size_t bytes;
1222                                 void *p;
1223                                 bytes = get_opt_result_pointer(opt, j, lor, &p);
1224                                 if (result)
1225                                         memcpy(result + nbytes, p, bytes);
1226                                 nbytes += bytes;
1227                         }
1228                 }
1229         }
1230         return nbytes;
1231 }
1232
1233 int lls_serialize_parse_result(const struct lls_parse_result *lpr,
1234         const struct lls_command *cmd, char **result, size_t *nbytes)
1235 {
1236         size_t sz;
1237         int ret;
1238
1239         if (!result || !*result) { /* need to compute needed space */
1240                 sz = serialize_parse_result(lpr, cmd, NULL);
1241                 if (!result) { /* just report needed space */
1242                         ret = 0;
1243                         goto out;
1244                 }
1245                 *result = malloc(sz);
1246                 if (!*result) {
1247                         sz = 0;
1248                         ret = -E_LLS_NOMEM;
1249                         goto out;
1250                 }
1251         }
1252         /* serialize it */
1253         sz = serialize_parse_result(lpr, cmd, *result);
1254         ret = 1;
1255 out:
1256         if (nbytes)
1257                 *nbytes = sz;
1258         return ret;
1259 }
1260
1261 int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd,
1262                 struct lls_parse_result **lprp)
1263 {
1264         int i, j;
1265         const char *p = buf;
1266         struct lls_parse_result *lpr;
1267
1268         *lprp = NULL;
1269         lpr = malloc(sizeof(*lpr));
1270         if (!lpr)
1271                 return -E_LLS_NOMEM;
1272         memcpy(&lpr->num_inputs, p, 4);
1273         p += 4;
1274         if (lpr->num_inputs > 0) {
1275                 lpr->inputs = malloc(lpr->num_inputs * sizeof(char *));
1276                 if (!lpr->inputs)
1277                         goto free_lpr;
1278         } else
1279                 lpr->inputs = NULL;
1280         for (i = 0; i < lpr->num_inputs; i++) {
1281                 lpr->inputs[i] = strdup(p);
1282                 if (!lpr->inputs[i])
1283                         goto free_inputs;
1284                 p += strlen(p) + 1;
1285         }
1286         lpr->opt_result = malloc(cmd->num_options * sizeof(*lpr->opt_result));
1287         if (!lpr->opt_result)
1288                 goto free_inputs;
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;
1292                 uint32_t num_vals;
1293
1294                 memcpy(&lor->given, p, 4);
1295                 p += 4;
1296                 if (opt->arg_info == LLS_NO_ARGUMENT)
1297                         continue;
1298                 num_vals = num_vals_in_parse_result(cmd, i, lpr);
1299                 lor->value = malloc(num_vals * sizeof(*lor->value));
1300                 if (!lor->value)
1301                         goto free_options;
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) {
1306                                         for (; j >= 0; j--)
1307                                                 free(lor->value[j].string_val);
1308                                         free(lor->value);
1309                                         goto free_options;
1310                                 }
1311                                 p += strlen(lor->value[j].string_val) + 1;
1312                         }
1313                 } else {
1314                         for (j = 0; j < num_vals; j++) {
1315                                 size_t bytes;
1316                                 void *q;
1317                                 bytes = get_opt_result_pointer(opt, j, lor, &q);
1318                                 memcpy(q, p, bytes);
1319                                 p += bytes;
1320                         }
1321                 }
1322         }
1323         *lprp = lpr;
1324         return 1;
1325 free_options:
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);
1333                 free(lor->value);
1334         }
1335         free(lpr->opt_result);
1336 free_inputs:
1337         for (; i >= 0; i--)
1338                 free(lpr->inputs[i]);
1339         free(lpr->inputs);
1340 free_lpr:
1341         free(lpr);
1342         return -E_LLS_NOMEM;
1343 }
1344
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,
1348                 char **errctx)
1349 {
1350         int l, m, ret;
1351         const struct lls_option *opt = cmd->options + opt_num;
1352         struct lls_opt_result *lor1, *lor2, *lor;
1353
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)
1359                 return 0;
1360         if (lor->given > 0 && (opt->flags & LLS_MULTIPLE)) {
1361                 lor->value = malloc(lor->given * sizeof(*lor->value));
1362                 if (!lor->value) {
1363                         xasprintf(errctx, "value array for option %s", opt->name);
1364                         goto fail;
1365                 }
1366                 for (l = 0; l < lor1->given; l++) {
1367                         ret = copy_val(lor->value + l, lor1->value + l,
1368                                 opt, errctx);
1369                         if (ret < 0)
1370                                 goto free_primary_options;
1371                 }
1372                 for (m = 0; m < lor2->given; m++) {
1373                         ret = copy_val(lor->value + l + m, lor2->value + m,
1374                                 opt, errctx);
1375                         if (ret < 0)
1376                                 goto free_secondary_options;
1377                 }
1378                 return 1;
1379         }
1380         lor->value = malloc(sizeof(*lor->value)); /* one value only */
1381         if (!lor->value) {
1382                 xasprintf(errctx, "(single) value for option %s", opt->name);
1383                 goto fail;
1384         }
1385         if (lor1->given) {
1386                 ret = copy_val(lor->value, lor1->value, opt, errctx);
1387                 if (ret < 0)
1388                         goto free_value;
1389         } else if (lor2->given) {
1390                 ret = copy_val(lor->value, lor2->value, opt, errctx);
1391                 if (ret < 0)
1392                         goto free_value;
1393         } else {
1394                 ret = copy_val(lor->value, &opt->default_val, opt, errctx);
1395                 if (ret < 0)
1396                         goto free_value;
1397         }
1398         return 1;
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);
1407 free_value:
1408         free(lor->value);
1409 fail:
1410         return -E_LLS_NOMEM;
1411 }
1412
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,
1416                 char **errctx)
1417 {
1418         int i, j, k, ret;
1419         unsigned num = primary->num_inputs + secondary->num_inputs;
1420         struct lls_parse_result *result;
1421
1422         if (errctx)
1423                 *errctx = NULL;
1424         result = malloc(sizeof(*result));
1425         if (!result) {
1426                 ret = -E_LLS_NOMEM;
1427                 xasprintf(errctx, "parse result");
1428                 goto fail;
1429         }
1430         result->inputs = malloc((num + 1) * sizeof(char *));
1431         if (!result->inputs) {
1432                 ret = -E_LLS_NOMEM;
1433                 xasprintf(errctx, "inputs array of size %u", num);
1434                 goto free_parse_result;
1435         }
1436         for (i = 0; i < primary->num_inputs; i++) {
1437                 result->inputs[i] = strdup(primary->inputs[i]);
1438                 if (!result->inputs[i]) {
1439                         ret = -E_LLS_NOMEM;
1440                         xasprintf(errctx, "primary input #%d", i);
1441                         goto free_primary_inputs;
1442                 }
1443         }
1444         for (j = 0; j < secondary->num_inputs; j++) {
1445                 result->inputs[i + j] = strdup(secondary->inputs[j]);
1446                 if (!result->inputs[i + j]) {
1447                         ret = -E_LLS_NOMEM;
1448                         xasprintf(errctx, "secondary input #%d", i);
1449                         goto free_secondary_inputs;
1450                 }
1451         }
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);
1459                 if (ret < 0)
1460                         goto free_opt_results;
1461         }
1462         result->num_inputs = num;
1463         *lprp = result;
1464         ret = 1;
1465         goto out;
1466 free_opt_results:
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);
1476 free_parse_result:
1477         free(result);
1478 fail:
1479         assert(ret < 0);
1480         *lprp = NULL;
1481 out:
1482         check_errctx(errctx, ret);
1483         return ret;
1484 }
1485
1486 static bool is_default_val(const union lls_val *val,
1487                 const struct lls_option *opt)
1488 {
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;
1492
1493         if (!has_arg)
1494                 return false;
1495         if (!has_default)
1496                 return false;
1497         dflt = &opt->default_val;
1498         switch (opt->arg_type) {
1499         case LLS_INT32:
1500                 return val->int32_val == dflt->int32_val;
1501         case LLS_UINT32:
1502                 return val->uint32_val == dflt->uint32_val;
1503         case LLS_INT64:
1504                 return val->int64_val == dflt->int64_val;
1505         case LLS_UINT64:
1506                 return val->uint64_val == dflt->uint64_val;
1507         case LLS_STRING:
1508                 {
1509                 const char *s1, *s2;
1510
1511                 if (opt->values)
1512                         return val->uint32_val == dflt->uint32_val;
1513                 s1 = val->string_val;
1514                 s2 = dflt->string_val;
1515                 if (!s1 && !s2)
1516                         return true;
1517                 if (!s1 || !s2)
1518                         return false;
1519                 return !strcmp(s1, s2);
1520                 }
1521         default:
1522                 assert(0);
1523         }
1524 }
1525
1526 static char *append_opt_val(const union lls_val *val,
1527                 const struct lls_option *opt, char *result)
1528 {
1529         char *line = NULL, *tmp = NULL;
1530
1531         switch (opt->arg_type) {
1532         case LLS_INT32:
1533                 xasprintf(&line, "%" PRId32, val->int32_val);
1534                 break;
1535         case LLS_UINT32:
1536                 xasprintf(&line, "%" PRIu32, val->uint32_val);
1537                 break;
1538         case LLS_INT64:
1539                 xasprintf(&line, "%" PRId64, val->int64_val);
1540                 break;
1541         case LLS_UINT64:
1542                 xasprintf(&line, "%" PRIu64, val->uint64_val);
1543                 break;
1544         case LLS_STRING:
1545                 {
1546                 const char *s, *p;
1547                 char *q;
1548
1549                 if (opt->values)
1550                         s = lls_enum_string_val(val->uint32_val, opt);
1551                 else {
1552                         s = val->string_val;
1553                         if (!s)
1554                                 return result;
1555                 }
1556                 line = malloc(2 * strlen(s) + 3);
1557                 if (!line) {
1558                         free(result);
1559                         return NULL;
1560                 }
1561                 line[0] = '"';
1562                 for (p = s, q = line + 1; *p; p++, q++) {
1563                         if (*p == '\\' || *p == '\n' || *p == '\t' || *p == '"') {
1564                                 *q = '\\';
1565                                 q++;
1566                         }
1567                         *q = *p;
1568                 }
1569                 q[0] = '"';
1570                 q[1] = '\0';
1571                 break;
1572                 }
1573         default:
1574                 assert(0);
1575         }
1576         xasprintf(&tmp, "%s%s=%s\n", result? result : "", opt->name, line);
1577         free(line);
1578         free(result);
1579         return tmp;
1580 }
1581
1582 char *lls_dump_parse_result(const struct lls_parse_result *lpr,
1583                 const struct lls_command *cmd, bool non_default_only)
1584 {
1585         int i;
1586         char *result = NULL;
1587
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;
1592                 int j, n;
1593
1594                 if (!given && non_default_only)
1595                         continue;
1596                 if (opt->arg_info == LLS_NO_ARGUMENT) {
1597                         char *tmp = NULL;
1598                         if (!given)
1599                                 continue;
1600                         xasprintf(&tmp, "%s%s\n", result? result : "",
1601                                 opt->name);
1602                         free(result);
1603                         result = tmp;
1604                         continue;
1605                 }
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))
1610                                 continue;
1611                         result = append_opt_val(val, opt, result);
1612                 }
1613         }
1614         if (!result) { /* empty dump */
1615                 result = malloc(1);
1616                 if (result)
1617                         result[0] = '\0';
1618         }
1619         return result;
1620 }