Fix unknown option name length computation in set_error
[argpar.git] / argpar / argpar.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
5 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
6 */
7
8 #include <assert.h>
9 #include <stdarg.h>
10 #include <stdbool.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "argpar.h"
16
17 #define ARGPAR_REALLOC(_ptr, _type, _nmemb) \
18 ((_type *) realloc(_ptr, (_nmemb) * sizeof(_type)))
19
20 #define ARGPAR_CALLOC(_type, _nmemb) \
21 ((_type *) calloc((_nmemb), sizeof(_type)))
22
23 #define ARGPAR_ZALLOC(_type) ARGPAR_CALLOC(_type, 1)
24
25 #define ARGPAR_ASSERT(_cond) assert(_cond)
26
27 #ifdef __MINGW_PRINTF_FORMAT
28 # define ARGPAR_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
29 #else
30 # define ARGPAR_PRINTF_FORMAT printf
31 #endif
32
33 /*
34 * An argpar iterator.
35 *
36 * Such a structure contains the state of an iterator between calls to
37 * argpar_iter_next().
38 */
39 struct argpar_iter {
40 /*
41 * Data provided by the user to argpar_iter_create(); immutable
42 * afterwards.
43 */
44 struct {
45 unsigned int argc;
46 const char * const *argv;
47 const struct argpar_opt_descr *descrs;
48 } user;
49
50 /*
51 * Index of the argument to process in the next
52 * argpar_iter_next() call.
53 */
54 unsigned int i;
55
56 /* Counter of non-option arguments */
57 int non_opt_index;
58
59 /*
60 * Current character within the current short option group: if
61 * it's not `NULL`, the parser is within a short option group,
62 * therefore it must resume there in the next argpar_iter_next()
63 * call.
64 */
65 const char *short_opt_group_ch;
66
67 /* Temporary character buffer which only grows */
68 struct {
69 size_t size;
70 char *data;
71 } tmp_buf;
72 };
73
74 /* Base parsing item */
75 struct argpar_item {
76 enum argpar_item_type type;
77 };
78
79 /* Option parsing item */
80 struct argpar_item_opt {
81 struct argpar_item base;
82
83 /* Corresponding descriptor */
84 const struct argpar_opt_descr *descr;
85
86 /* Argument, or `NULL` if none; owned by this */
87 char *arg;
88 };
89
90 /* Non-option parsing item */
91 struct argpar_item_non_opt {
92 struct argpar_item base;
93
94 /*
95 * Complete argument, pointing to one of the entries of the
96 * original arguments (`argv`).
97 */
98 const char *arg;
99
100 /*
101 * Index of this argument amongst all original arguments
102 * (`argv`).
103 */
104 unsigned int orig_index;
105
106 /* Index of this argument amongst other non-option arguments */
107 unsigned int non_opt_index;
108 };
109
110 /* Parsing error */
111 struct argpar_error {
112 /* Original argument index */
113 unsigned int orig_index;
114
115 /* Name of unknown option; owned by this */
116 char *unknown_opt_name;
117
118 /* Option descriptor */
119 const struct argpar_opt_descr *opt_descr;
120
121 /* `true` if a short option caused the error */
122 bool is_short;
123 };
124
125 ARGPAR_HIDDEN
126 enum argpar_item_type argpar_item_type(const struct argpar_item * const item)
127 {
128 ARGPAR_ASSERT(item);
129 return item->type;
130 }
131
132 ARGPAR_HIDDEN
133 const struct argpar_opt_descr *argpar_item_opt_descr(
134 const struct argpar_item * const item)
135 {
136 ARGPAR_ASSERT(item);
137 ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_OPT);
138 return ((const struct argpar_item_opt *) item)->descr;
139 }
140
141 ARGPAR_HIDDEN
142 const char *argpar_item_opt_arg(const struct argpar_item * const item)
143 {
144 ARGPAR_ASSERT(item);
145 ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_OPT);
146 return ((const struct argpar_item_opt *) item)->arg;
147 }
148
149 ARGPAR_HIDDEN
150 const char *argpar_item_non_opt_arg(const struct argpar_item * const item)
151 {
152 ARGPAR_ASSERT(item);
153 ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
154 return ((const struct argpar_item_non_opt *) item)->arg;
155 }
156
157 ARGPAR_HIDDEN
158 unsigned int argpar_item_non_opt_orig_index(
159 const struct argpar_item * const item)
160 {
161 ARGPAR_ASSERT(item);
162 ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
163 return ((const struct argpar_item_non_opt *) item)->orig_index;
164 }
165
166 ARGPAR_HIDDEN
167 unsigned int argpar_item_non_opt_non_opt_index(
168 const struct argpar_item * const item)
169 {
170 ARGPAR_ASSERT(item);
171 ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
172 return ((const struct argpar_item_non_opt *) item)->non_opt_index;
173 }
174
175 ARGPAR_HIDDEN
176 void argpar_item_destroy(const struct argpar_item * const item)
177 {
178 if (!item) {
179 goto end;
180 }
181
182 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
183 struct argpar_item_opt * const opt_item =
184 (struct argpar_item_opt *) item;
185
186 free(opt_item->arg);
187 }
188
189 free((void *) item);
190
191 end:
192 return;
193 }
194
195 /*
196 * Creates and returns an option parsing item for the descriptor `descr`
197 * and having the argument `arg` (copied; may be `NULL`).
198 *
199 * Returns `NULL` on memory error.
200 */
201 static
202 struct argpar_item_opt *create_opt_item(
203 const struct argpar_opt_descr * const descr,
204 const char * const arg)
205 {
206 struct argpar_item_opt *opt_item =
207 ARGPAR_ZALLOC(struct argpar_item_opt);
208
209 if (!opt_item) {
210 goto end;
211 }
212
213 opt_item->base.type = ARGPAR_ITEM_TYPE_OPT;
214 opt_item->descr = descr;
215
216 if (arg) {
217 opt_item->arg = strdup(arg);
218 if (!opt_item->arg) {
219 goto error;
220 }
221 }
222
223 goto end;
224
225 error:
226 argpar_item_destroy(&opt_item->base);
227 opt_item = NULL;
228
229 end:
230 return opt_item;
231 }
232
233 /*
234 * Creates and returns a non-option parsing item for the original
235 * argument `arg` having the original index `orig_index` and the
236 * non-option index `non_opt_index`.
237 *
238 * Returns `NULL` on memory error.
239 */
240 static
241 struct argpar_item_non_opt *create_non_opt_item(const char * const arg,
242 const unsigned int orig_index,
243 const unsigned int non_opt_index)
244 {
245 struct argpar_item_non_opt * const non_opt_item =
246 ARGPAR_ZALLOC(struct argpar_item_non_opt);
247
248 if (!non_opt_item) {
249 goto end;
250 }
251
252 non_opt_item->base.type = ARGPAR_ITEM_TYPE_NON_OPT;
253 non_opt_item->arg = arg;
254 non_opt_item->orig_index = orig_index;
255 non_opt_item->non_opt_index = non_opt_index;
256
257 end:
258 return non_opt_item;
259 }
260
261 /*
262 * If `error` is not `NULL`, sets the error `error` to a new parsing
263 * error object, setting its `unknown_opt_name`, `opt_descr`, and
264 * `is_short` members from the parameters.
265 *
266 * `unknown_opt_name` is the unknown option name without any `-` or `--`
267 * prefix: `is_short` controls which type of unknown option it is.
268 *
269 * Returns 0 on success (including if `error` is `NULL`) or -1 on memory
270 * error.
271 */
272 static
273 int set_error(struct argpar_error ** const error,
274 const char * const unknown_opt_name,
275 const struct argpar_opt_descr * const opt_descr,
276 const bool is_short)
277 {
278 int ret = 0;
279
280 if (!error) {
281 goto end;
282 }
283
284 *error = ARGPAR_ZALLOC(struct argpar_error);
285 if (!*error) {
286 goto error;
287 }
288
289 if (unknown_opt_name) {
290 (*error)->unknown_opt_name = ARGPAR_CALLOC(char,
291 strlen(unknown_opt_name) + 1 + (is_short ? 1 : 2));
292 if (!(*error)->unknown_opt_name) {
293 goto error;
294 }
295
296 if (is_short) {
297 strcpy((*error)->unknown_opt_name, "-");
298 } else {
299 strcpy((*error)->unknown_opt_name, "--");
300 }
301
302 strcat((*error)->unknown_opt_name, unknown_opt_name);
303 }
304
305 (*error)->opt_descr = opt_descr;
306 (*error)->is_short = is_short;
307 goto end;
308
309 error:
310 argpar_error_destroy(*error);
311 ret = -1;
312
313 end:
314 return ret;
315 }
316
317 ARGPAR_HIDDEN
318 unsigned int argpar_error_orig_index(const struct argpar_error * const error)
319 {
320 ARGPAR_ASSERT(error);
321 return error->orig_index;
322 }
323
324 ARGPAR_HIDDEN
325 const char *argpar_error_unknown_opt_name(
326 const struct argpar_error * const error)
327 {
328 ARGPAR_ASSERT(error);
329 ARGPAR_ASSERT(error->unknown_opt_name);
330 return error->unknown_opt_name;
331 }
332
333 ARGPAR_HIDDEN
334 const struct argpar_opt_descr *argpar_error_opt_descr(
335 const struct argpar_error * const error, bool * const is_short)
336 {
337 ARGPAR_ASSERT(error);
338 ARGPAR_ASSERT(error->opt_descr);
339
340 if (is_short) {
341 *is_short = error->is_short;
342 }
343
344 return error->opt_descr;
345 }
346
347 ARGPAR_HIDDEN
348 void argpar_error_destroy(const struct argpar_error * const error)
349 {
350 if (error) {
351 free(error->unknown_opt_name);
352 free((void *) error);
353 }
354 }
355
356 /*
357 * Finds and returns the _first_ descriptor having the short option name
358 * `short_name` or the long option name `long_name` within the option
359 * descriptors `descrs`.
360 *
361 * `short_name` may be `'\0'` to not consider it.
362 *
363 * `long_name` may be `NULL` to not consider it.
364 *
365 * Returns `NULL` if no descriptor is found.
366 */
367 static
368 const struct argpar_opt_descr *find_descr(
369 const struct argpar_opt_descr * const descrs,
370 const char short_name, const char * const long_name)
371 {
372 const struct argpar_opt_descr *descr;
373
374 for (descr = descrs; descr->short_name || descr->long_name; descr++) {
375 if (short_name && descr->short_name &&
376 short_name == descr->short_name) {
377 goto end;
378 }
379
380 if (long_name && descr->long_name &&
381 strcmp(long_name, descr->long_name) == 0) {
382 goto end;
383 }
384 }
385
386 end:
387 return !descr->short_name && !descr->long_name ? NULL : descr;
388 }
389
390 /* Return type of parse_short_opt_group() and parse_long_opt() */
391 enum parse_orig_arg_opt_ret {
392 PARSE_ORIG_ARG_OPT_RET_OK,
393 PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT = -1,
394 PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG = -2,
395 PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG = -4,
396 PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY = -5,
397 };
398
399 /*
400 * Parses the short option group argument `short_opt_group`, starting
401 * where needed depending on the state of `iter`.
402 *
403 * On success, sets `*item`.
404 *
405 * On error (except for `PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY`), sets
406 * `*error`.
407 */
408 static
409 enum parse_orig_arg_opt_ret parse_short_opt_group(
410 const char * const short_opt_group,
411 const char * const next_orig_arg,
412 const struct argpar_opt_descr * const descrs,
413 struct argpar_iter * const iter,
414 struct argpar_error ** const error,
415 struct argpar_item ** const item)
416 {
417 enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
418 bool used_next_orig_arg = false;
419 const char *opt_arg = NULL;
420 const struct argpar_opt_descr *descr;
421 struct argpar_item_opt *opt_item;
422
423 ARGPAR_ASSERT(strlen(short_opt_group) != 0);
424
425 if (!iter->short_opt_group_ch) {
426 iter->short_opt_group_ch = short_opt_group;
427 }
428
429 /* Find corresponding option descriptor */
430 descr = find_descr(descrs, *iter->short_opt_group_ch, NULL);
431 if (!descr) {
432 const char unknown_opt_name[] =
433 {*iter->short_opt_group_ch, '\0'};
434
435 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
436
437 if (set_error(error, unknown_opt_name, NULL, true)) {
438 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
439 }
440
441 goto error;
442 }
443
444 if (descr->with_arg) {
445 if (iter->short_opt_group_ch[1]) {
446 /* `-oarg` form */
447 opt_arg = &iter->short_opt_group_ch[1];
448 } else {
449 /* `-o arg` form */
450 opt_arg = next_orig_arg;
451 used_next_orig_arg = true;
452 }
453
454 /*
455 * We accept `-o ''` (empty option argument), but not
456 * `-o` alone if an option argument is expected.
457 */
458 if (!opt_arg || (iter->short_opt_group_ch[1] &&
459 strlen(opt_arg) == 0)) {
460 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
461
462 if (set_error(error, NULL, descr, true)) {
463 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
464 }
465
466 goto error;
467 }
468 }
469
470 /* Create and append option argument */
471 opt_item = create_opt_item(descr, opt_arg);
472 if (!opt_item) {
473 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
474 goto error;
475 }
476
477 *item = &opt_item->base;
478 iter->short_opt_group_ch++;
479
480 if (descr->with_arg || !*iter->short_opt_group_ch) {
481 /* Option has an argument: no more options */
482 iter->short_opt_group_ch = NULL;
483
484 if (used_next_orig_arg) {
485 iter->i += 2;
486 } else {
487 iter->i++;
488 }
489 }
490
491 goto end;
492
493 error:
494 ARGPAR_ASSERT(ret != PARSE_ORIG_ARG_OPT_RET_OK);
495
496 end:
497 return ret;
498 }
499
500 /*
501 * Parses the long option argument `long_opt_arg`.
502 *
503 * On success, sets `*item`.
504 *
505 * On error (except for `PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY`), sets
506 * `*error`.
507 */
508 static
509 enum parse_orig_arg_opt_ret parse_long_opt(const char * const long_opt_arg,
510 const char * const next_orig_arg,
511 const struct argpar_opt_descr * const descrs,
512 struct argpar_iter * const iter,
513 struct argpar_error ** const error,
514 struct argpar_item ** const item)
515 {
516 enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
517 const struct argpar_opt_descr *descr;
518 struct argpar_item_opt *opt_item;
519 bool used_next_orig_arg = false;
520
521 /* Option's argument, if any */
522 const char *opt_arg = NULL;
523
524 /* Position of first `=`, if any */
525 const char *eq_pos;
526
527 /* Option name */
528 const char *long_opt_name = long_opt_arg;
529
530 ARGPAR_ASSERT(strlen(long_opt_arg) != 0);
531
532 /* Find the first `=` in original argument */
533 eq_pos = strchr(long_opt_arg, '=');
534 if (eq_pos) {
535 const size_t long_opt_name_size = eq_pos - long_opt_arg;
536
537 /* Isolate the option name */
538 while (long_opt_name_size > iter->tmp_buf.size - 1) {
539 iter->tmp_buf.size *= 2;
540 iter->tmp_buf.data = ARGPAR_REALLOC(iter->tmp_buf.data,
541 char, iter->tmp_buf.size);
542 if (!iter->tmp_buf.data) {
543 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
544 goto error;
545 }
546 }
547
548 memcpy(iter->tmp_buf.data, long_opt_arg, long_opt_name_size);
549 iter->tmp_buf.data[long_opt_name_size] = '\0';
550 long_opt_name = iter->tmp_buf.data;
551 }
552
553 /* Find corresponding option descriptor */
554 descr = find_descr(descrs, '\0', long_opt_name);
555 if (!descr) {
556 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
557
558 if (set_error(error, long_opt_name, NULL, false)) {
559 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
560 }
561
562 goto error;
563 }
564
565 /* Find option's argument if any */
566 if (descr->with_arg) {
567 if (eq_pos) {
568 /* `--long-opt=arg` style */
569 opt_arg = eq_pos + 1;
570 } else {
571 /* `--long-opt arg` style */
572 if (!next_orig_arg) {
573 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
574
575 if (set_error(error, NULL, descr, false)) {
576 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
577 }
578
579 goto error;
580 }
581
582 opt_arg = next_orig_arg;
583 used_next_orig_arg = true;
584 }
585 } else if (eq_pos) {
586 /*
587 * Unexpected `--opt=arg` style for a long option which
588 * doesn't accept an argument.
589 */
590 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG;
591
592 if (set_error(error, NULL, descr, false)) {
593 ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
594 }
595
596 goto error;
597 }
598
599 /* Create and append option argument */
600 opt_item = create_opt_item(descr, opt_arg);
601 if (!opt_item) {
602 goto error;
603 }
604
605 if (used_next_orig_arg) {
606 iter->i += 2;
607 } else {
608 iter->i++;
609 }
610
611 *item = &opt_item->base;
612 goto end;
613
614 error:
615 ARGPAR_ASSERT(ret != PARSE_ORIG_ARG_OPT_RET_OK);
616
617 end:
618 return ret;
619 }
620
621 /*
622 * Parses the original argument `orig_arg`.
623 *
624 * On success, sets `*item`.
625 *
626 * On error (except for `PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY`), sets
627 * `*error`.
628 */
629 static
630 enum parse_orig_arg_opt_ret parse_orig_arg_opt(const char * const orig_arg,
631 const char * const next_orig_arg,
632 const struct argpar_opt_descr * const descrs,
633 struct argpar_iter * const iter,
634 struct argpar_error ** const error,
635 struct argpar_item ** const item)
636 {
637 enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
638
639 ARGPAR_ASSERT(orig_arg[0] == '-');
640
641 if (orig_arg[1] == '-') {
642 /* Long option */
643 ret = parse_long_opt(&orig_arg[2],
644 next_orig_arg, descrs, iter, error, item);
645 } else {
646 /* Short option */
647 ret = parse_short_opt_group(&orig_arg[1],
648 next_orig_arg, descrs, iter, error, item);
649 }
650
651 return ret;
652 }
653
654 ARGPAR_HIDDEN
655 struct argpar_iter *argpar_iter_create(const unsigned int argc,
656 const char * const * const argv,
657 const struct argpar_opt_descr * const descrs)
658 {
659 struct argpar_iter *iter = ARGPAR_ZALLOC(struct argpar_iter);
660
661 if (!iter) {
662 goto end;
663 }
664
665 iter->user.argc = argc;
666 iter->user.argv = argv;
667 iter->user.descrs = descrs;
668 iter->tmp_buf.size = 128;
669 iter->tmp_buf.data = ARGPAR_CALLOC(char, iter->tmp_buf.size);
670 if (!iter->tmp_buf.data) {
671 argpar_iter_destroy(iter);
672 iter = NULL;
673 goto end;
674 }
675
676 end:
677 return iter;
678 }
679
680 ARGPAR_HIDDEN
681 void argpar_iter_destroy(struct argpar_iter * const iter)
682 {
683 if (iter) {
684 free(iter->tmp_buf.data);
685 free(iter);
686 }
687 }
688
689 ARGPAR_HIDDEN
690 enum argpar_iter_next_status argpar_iter_next(
691 struct argpar_iter * const iter,
692 const struct argpar_item ** const item,
693 const struct argpar_error ** const error)
694 {
695 enum argpar_iter_next_status status;
696 enum parse_orig_arg_opt_ret parse_orig_arg_opt_ret;
697 const char *orig_arg;
698 const char *next_orig_arg;
699 struct argpar_error ** const nc_error = (struct argpar_error **) error;
700
701 ARGPAR_ASSERT(iter->i <= iter->user.argc);
702
703 if (error) {
704 *nc_error = NULL;
705 }
706
707 if (iter->i == iter->user.argc) {
708 status = ARGPAR_ITER_NEXT_STATUS_END;
709 goto end;
710 }
711
712 orig_arg = iter->user.argv[iter->i];
713 next_orig_arg =
714 iter->i < (iter->user.argc - 1) ?
715 iter->user.argv[iter->i + 1] : NULL;
716
717 if (strcmp(orig_arg, "-") == 0 || strcmp(orig_arg, "--") == 0 ||
718 orig_arg[0] != '-') {
719 /* Non-option argument */
720 const struct argpar_item_non_opt * const non_opt_item =
721 create_non_opt_item(orig_arg, iter->i,
722 iter->non_opt_index);
723
724 if (!non_opt_item) {
725 status = ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY;
726 goto end;
727 }
728
729 iter->non_opt_index++;
730 iter->i++;
731 *item = &non_opt_item->base;
732 status = ARGPAR_ITER_NEXT_STATUS_OK;
733 goto end;
734 }
735
736 /* Option argument */
737 parse_orig_arg_opt_ret = parse_orig_arg_opt(orig_arg,
738 next_orig_arg, iter->user.descrs, iter, nc_error,
739 (struct argpar_item **) item);
740 switch (parse_orig_arg_opt_ret) {
741 case PARSE_ORIG_ARG_OPT_RET_OK:
742 status = ARGPAR_ITER_NEXT_STATUS_OK;
743 break;
744 case PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT:
745 case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
746 case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
747 if (error) {
748 ARGPAR_ASSERT(*error);
749 (*nc_error)->orig_index = iter->i;
750 }
751
752 switch (parse_orig_arg_opt_ret) {
753 case PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT:
754 status = ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT;
755 break;
756 case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
757 status = ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG;
758 break;
759 case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
760 status = ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG;
761 break;
762 default:
763 abort();
764 }
765
766 break;
767 case PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY:
768 status = ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY;
769 break;
770 default:
771 abort();
772 }
773
774 end:
775 return status;
776 }
777
778 ARGPAR_HIDDEN
779 unsigned int argpar_iter_ingested_orig_args(
780 const struct argpar_iter * const iter)
781 {
782 return iter->i;
783 }
This page took 0.044045 seconds and 4 git commands to generate.