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