2 * SPDX-License-Identifier: MIT
3 * SPDX-FileCopyrightText: 2019-2024 Philippe Proulx <pproulx@efficios.com>
4 * SPDX-FileCopyrightText: 2020-2024 Simon Marchi <simon.marchi@efficios.com>
7 #ifndef ARGPAR_ARGPAR_H
8 #define ARGPAR_ARGPAR_H
13 #if defined(__cplusplus)
20 See the \ref api module.
22 @addtogroup api argpar API
25 argpar is a library which provides an iterator-based API to parse
26 command-line arguments.
28 The argpar parser supports:
32 Short options without an argument, possibly tied together:
39 Short options with arguments:
42 -b 45 -f/mein/file -xyzhello
46 Long options without an argument:
49 --five-guys --burger-king --pizza-hut --subway
53 Long options with arguments (two original arguments or a single
54 one with a <code>=</code> character):
57 --security enable --time=18.56
61 Non-option arguments (anything else, including
62 <code>-</code> and <code>\--</code>).
64 A non-option argument cannot have the form of an option, for example
65 if you need to pass the exact relative path
66 <code>\--component</code>. In that case, you would need to pass
67 <code>./\--component</code>. There's no generic way to escape
68 <code>-</code> as of this version.
71 Create a parsing iterator with argpar_iter_create(), then repeatedly
72 call argpar_iter_next() to access the parsing results (items), until one
75 - There are no more arguments.
77 - The argument parser encounters an error (for example, an unknown
82 argpar_iter_create() accepts duplicate option descriptors in
83 \p descrs (argpar_iter_next() produces one item for each
86 A parsing item (the result of argpar_iter_next()) has the type
89 Get the type (option or non-option) of an item with
90 \link argpar_item_type(const argpar_item_t *) argpar_item_type()\endlink.
91 Each item type has its set of dedicated functions
92 (\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes).
94 argpar_iter_next() produces the items in the same order that it parses
95 original arguments, including non-option arguments. This means, for
99 --hello --count=23 /path/to/file -ab --type file -- magie
102 argpar_iter_next() produces the following items, in this order:
104 -# Option item: <code>\--hello</code>.
105 -# Option item: <code>\--count</code> with argument <code>23</code>.
106 -# Non-option item: <code>/path/to/file</code>.
107 -# Option item: <code>-a</code>.
108 -# Option item: <code>-b</code>.
109 -# Option item: <code>\--type</code> with argument <code>file</code>.
110 -# Non-option item: <code>\--</code>.
111 -# Non-option item: <code>magie</code>.
114 /* Internal: `noexcept` specifier if C++ ≥ 11 */
115 #if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
116 # define ARGPAR_NOEXCEPT noexcept
118 # define ARGPAR_NOEXCEPT
121 typedef struct argpar_opt_descr argpar_opt_descr_t
;
130 Type of a parsing item, as returned by
131 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
133 typedef enum argpar_item_type
136 ARGPAR_ITEM_TYPE_OPT
,
139 ARGPAR_ITEM_TYPE_NON_OPT
,
140 } argpar_item_type_t
;
146 Opaque parsing item type
148 argpar_iter_next() sets a pointer to such a type.
150 typedef struct argpar_item argpar_item_t
;
154 Returns the type of the parsing item \p item.
157 Parsing item of which to get the type.
163 \p item is not \c NULL.
165 argpar_item_type_t
argpar_item_type(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
169 Returns the option descriptor of the option parsing item \p item.
172 Option parsing item of which to get the option descriptor.
175 Option descriptor of \p item.
178 \p item is not \c NULL.
180 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
182 const argpar_opt_descr_t
*argpar_item_opt_descr(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
186 Returns the argument of the option parsing item \p item, or
190 Option parsing item of which to get the argument.
193 Argument of \p item, or \c NULL if none.
196 \p item is not \c NULL.
198 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
200 const char *argpar_item_opt_arg(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
204 Returns the complete original argument, pointing to one of the
205 entries of the original arguments (in \p argv, as passed to
206 argpar_iter_create()), of the non-option parsing item \p item.
209 Non-option parsing item of which to get the complete original
213 Complete original argument of \p item.
216 \p item is not \c NULL.
218 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
220 const char *argpar_item_non_opt_arg(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
224 Returns the index, within \em all the original arguments (in
225 \p argv, as passed to argpar_iter_create()), of the non-option
226 parsing item \p item.
228 For example, with the following command line (all options have no
232 -f -m meow --jus mix --kilo
235 The original argument index of \c meow is 2 while the original
236 argument index of \c mix is 4.
239 Non-option parsing item of which to get the original argument index.
242 Original argument index of \p item.
245 \p item is not \c NULL.
247 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
250 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
251 of a non-option parsing item.
253 unsigned int argpar_item_non_opt_orig_index(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
257 Returns the index, within the parsed non-option parsing items, of
258 the non-option parsing item \p item.
260 For example, with the following command line (all options have no
264 -f -m meow --jus mix --kilo
267 The non-option index of \c meow is 0 while the original
268 argument index of \c mix is 1.
271 Non-option parsing item of which to get the non-option index.
274 Non-option index of \p item.
277 \p item is not \c NULL.
279 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
282 argpar_item_non_opt_orig_index() -- Returns the original argument
283 index of a non-option parsing item.
285 unsigned int argpar_item_non_opt_non_opt_index(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
289 Destroys the parsing item \p item.
292 Parsing item to destroy (may be \c NULL).
294 void argpar_item_destroy(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
297 @def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
300 Calls argpar_item_destroy() with \p _item, and then sets \p _item
304 Item to destroy and variable to reset
305 (<code>const argpar_item_t *</code> type).
307 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
309 argpar_item_destroy(_item); \
322 Parsing error type, as returned by
323 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
325 typedef enum argpar_error_type
327 /// Unknown option error
328 ARGPAR_ERROR_TYPE_UNKNOWN_OPT
,
330 /// Missing option argument error
331 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG
,
333 /// Unexpected option argument error
334 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG
,
335 } argpar_error_type_t
;
341 Opaque parsing error type
343 typedef struct argpar_error argpar_error_t
;
347 Returns the type of the parsing error object \p error.
350 Parsing error of which to get the type.
356 \p error is not \c NULL.
358 argpar_error_type_t
argpar_error_type(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
362 Returns the index of the original argument (in \p argv, as passed to
363 argpar_iter_create()) for which the parsing error described by
367 Parsing error of which to get the original argument index.
370 Original argument index of \p error.
373 \p error is not \c NULL.
375 unsigned int argpar_error_orig_index(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
379 Returns the name of the unknown option for which the parsing error
380 described by \p error occurred.
382 The returned name includes any <code>-</code> or <code>\--</code>
385 With the long option with argument form, for example
386 <code>\--mireille=deyglun</code>, this function only returns the name
387 part (<code>\--mireille</code> in the last example).
390 Parsing error of which to get the name of the unknown option.
393 Name of the unknown option of \p error.
396 \p error is not \c NULL.
398 The type of \p error, as returned by
399 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
400 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
402 const char *argpar_error_unknown_opt_name(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
406 Returns the descriptor of the option for which the parsing error
407 described by \p error occurred.
410 Parsing error of which to get the option descriptor.
413 If not \c NULL, this function sets \p *is_short to:
415 - \c true if the option for which \p error occurred is a short
418 - \c false if the option for which \p error occurred is a long
423 Descriptor of the option of \p error.
426 \p error is not \c NULL.
428 The type of \p error, as returned by
429 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
430 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
431 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
433 const argpar_opt_descr_t
*argpar_error_opt_descr(const argpar_error_t
*error
,
434 bool *is_short
) ARGPAR_NOEXCEPT
;
438 Destroys the parsing error \p error.
441 Parsing error to destroy (may be \c NULL).
443 void argpar_error_destroy(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
456 argpar_iter_create() accepts an array of instances of such a type,
457 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
459 The typical usage is, for example:
462 const argpar_opt_descr_t descrs[] = {
463 { 0, 'd', NULL, false },
464 { 1, '\0', "squeeze", true },
465 { 2, 'm', "meow", true },
466 ARGPAR_OPT_DESCR_SENTINEL,
470 typedef struct argpar_opt_descr
472 /// Numeric ID, to uniquely identify this descriptor
475 /// Short option character, or <code>'\0'</code>
476 const char short_name
;
478 /// Long option name (without the <code>\--</code> prefix), or \c NULL
479 const char * const long_name
;
481 /// \c true if this option has an argument
483 } argpar_opt_descr_t
;
487 Sentinel for an option descriptor array
489 The typical usage is, for example:
492 const argpar_opt_descr_t descrs[] = {
493 { 0, 'd', NULL, false },
494 { 1, '\0', "squeeze", true },
495 { 2, 'm', "meow", true },
496 ARGPAR_OPT_DESCR_SENTINEL,
500 #define ARGPAR_OPT_DESCR_SENTINEL \
502 -1, '\0', NULL, false \
509 Opaque argpar iterator type
511 argpar_iter_create() returns a pointer to such a type.
513 typedef struct argpar_iter argpar_iter_t
;
517 Creates and returns an argument parsing iterator to parse the
518 original arguments \p argv of which the count is \p argc using the
519 option descriptors \p descrs.
521 This function initializes the returned structure, but doesn't actually
522 start parsing the arguments.
524 argpar considers \em all the elements of \p argv, including the first
525 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
526 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
527 receives, or ignore the parsing item of the first call to
530 \p *argv and \p *descrs must \em not change for all of:
532 - The lifetime of the returned iterator (until you call
533 argpar_iter_destroy()).
535 - The lifetime of any parsing item (until you call
536 argpar_item_destroy()) which argpar_iter_next() creates from the
539 - The lifetime of any parsing error (until you call
540 argpar_error_destroy()) which argpar_iter_next() creates from the
544 Number of original arguments to parse in \p argv.
546 Original arguments to parse, of which the count is \p argc.
549 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
551 May contain duplicate entries.
555 New argument parsing iterator, or \c NULL on memory error.
558 \p argc is greater than 0.
560 \p argv is not \c NULL.
562 The first \p argc elements of \p argv are not \c NULL.
564 \p descrs is not \c NULL.
567 argpar_iter_destroy() -- Destroys an argument parsing iterator.
569 argpar_iter_t
*argpar_iter_create(unsigned int argc
, const char * const *argv
,
570 const argpar_opt_descr_t
*descrs
) ARGPAR_NOEXCEPT
;
574 Destroys the argument parsing iterator \p iter.
577 Argument parsing iterator to destroy (may be \c NULL).
580 argpar_iter_create() -- Creates an argument parsing iterator.
582 void argpar_iter_destroy(argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
586 Return type of argpar_iter_next().
588 Error status enumerators have a negative value.
590 typedef enum argpar_iter_next_status
593 ARGPAR_ITER_NEXT_STATUS_OK
,
595 /// End of iteration (no more original arguments to parse)
596 ARGPAR_ITER_NEXT_STATUS_END
,
599 ARGPAR_ITER_NEXT_STATUS_ERROR
= -1,
602 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY
= -12,
603 } argpar_iter_next_status_t
;
607 Sets \p *item to the next item of the argument parsing iterator
608 \p iter and advances \p iter.
610 If there are no more original arguments to parse, this function returns
611 #ARGPAR_ITER_NEXT_STATUS_END.
614 Argument parsing iterator from which to get the next parsing item.
617 On success, \p *item is the next parsing item of \p iter.
619 Destroy \p *item with argpar_item_destroy().
623 When this function returns #ARGPAR_ITER_NEXT_STATUS_ERROR,
624 if this parameter is not \c NULL, \p *error contains details about
627 Destroy \p *error with argpar_error_destroy().
634 \p iter is not \c NULL.
636 \p item is not \c NULL.
638 argpar_iter_next_status_t
argpar_iter_next(argpar_iter_t
*iter
, const argpar_item_t
**item
,
639 const argpar_error_t
**error
) ARGPAR_NOEXCEPT
;
642 * Returns the number of ingested elements from `argv`, as passed to
643 * argpar_iter_create() to create `*iter`, that were required to produce
644 * the previously returned items.
649 Returns the number of ingested original arguments (in
650 \p argv, as passed to argpar_iter_create() to create \p iter) that
651 the parser ingested to produce the \em previous parsing items.
654 Argument parsing iterator of which to get the number of ingested
658 Number of original arguments which \p iter ingested.
661 \p iter is not \c NULL.
663 unsigned int argpar_iter_ingested_orig_args(const argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
669 #if defined(__cplusplus)
673 #endif /* ARGPAR_ARGPAR_H */