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
12 #if defined(__cplusplus)
19 See the \ref api module.
21 @addtogroup api argpar API
24 argpar is a library which provides an iterator-based API to parse
25 command-line arguments.
27 The argpar parser supports:
31 Short options without an argument, possibly tied together:
38 Short options with arguments:
41 -b 45 -f/mein/file -xyzhello
45 Long options without an argument:
48 --five-guys --burger-king --pizza-hut --subway
52 Long options with arguments (two original arguments or a single
53 one with a <code>=</code> character):
56 --security enable --time=18.56
60 Non-option arguments (anything else, including
61 <code>-</code> and <code>\--</code>).
63 A non-option argument cannot have the form of an option, for example
64 if you need to pass the exact relative path
65 <code>\--component</code>. In that case, you would need to pass
66 <code>./\--component</code>. There's no generic way to escape
67 <code>-</code> as of this version.
70 Create a parsing iterator with argpar_iter_create(), then repeatedly
71 call argpar_iter_next() to access the parsing results (items), until one
74 - There are no more arguments.
76 - The argument parser encounters an error (for example, an unknown
81 argpar_iter_create() accepts duplicate option descriptors in
82 \p descrs (argpar_iter_next() produces one item for each
85 A parsing item (the result of argpar_iter_next()) has the type
88 Get the type (option or non-option) of an item with
89 \link argpar_item_type(const argpar_item_t *) argpar_item_type()\endlink.
90 Each item type has its set of dedicated functions
91 (\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes).
93 argpar_iter_next() produces the items in the same order that it parses
94 original arguments, including non-option arguments. This means, for
98 --hello --count=23 /path/to/file -ab --type file -- magie
101 argpar_iter_next() produces the following items, in this order:
103 -# Option item: <code>\--hello</code>.
104 -# Option item: <code>\--count</code> with argument <code>23</code>.
105 -# Non-option item: <code>/path/to/file</code>.
106 -# Option item: <code>-a</code>.
107 -# Option item: <code>-b</code>.
108 -# Option item: <code>\--type</code> with argument <code>file</code>.
109 -# Non-option item: <code>\--</code>.
110 -# Non-option item: <code>magie</code>.
113 /* Internal: `noexcept` specifier if C++ ≥ 11 */
114 #if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
115 # define ARGPAR_NOEXCEPT noexcept
117 # define ARGPAR_NOEXCEPT
120 typedef struct argpar_opt_descr argpar_opt_descr_t
;
129 Type of a parsing item, as returned by
130 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
132 typedef enum argpar_item_type
135 ARGPAR_ITEM_TYPE_OPT
,
138 ARGPAR_ITEM_TYPE_NON_OPT
,
139 } argpar_item_type_t
;
145 Opaque parsing item type
147 argpar_iter_next() sets a pointer to such a type.
149 typedef struct argpar_item argpar_item_t
;
153 Returns the type of the parsing item \p item.
156 Parsing item of which to get the type.
162 \p item is not \c NULL.
164 argpar_item_type_t
argpar_item_type(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
168 Returns the option descriptor of the option parsing item \p item.
171 Option parsing item of which to get the option descriptor.
174 Option descriptor of \p item.
177 \p item is not \c NULL.
179 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
181 const argpar_opt_descr_t
*argpar_item_opt_descr(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
185 Returns the argument of the option parsing item \p item, or
189 Option parsing item of which to get the argument.
192 Argument of \p item, or \c NULL if none.
195 \p item is not \c NULL.
197 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
199 const char *argpar_item_opt_arg(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
203 Returns the complete original argument, pointing to one of the
204 entries of the original arguments (in \p argv, as passed to
205 argpar_iter_create()), of the non-option parsing item \p item.
208 Non-option parsing item of which to get the complete original
212 Complete original argument of \p item.
215 \p item is not \c NULL.
217 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
219 const char *argpar_item_non_opt_arg(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
223 Returns the index, within \em all the original arguments (in
224 \p argv, as passed to argpar_iter_create()), of the non-option
225 parsing item \p item.
227 For example, with the following command line (all options have no
231 -f -m meow --jus mix --kilo
234 The original argument index of \c meow is 2 while the original
235 argument index of \c mix is 4.
238 Non-option parsing item of which to get the original argument index.
241 Original argument index of \p item.
244 \p item is not \c NULL.
246 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
249 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
250 of a non-option parsing item.
252 unsigned int argpar_item_non_opt_orig_index(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
256 Returns the index, within the parsed non-option parsing items, of
257 the non-option parsing item \p item.
259 For example, with the following command line (all options have no
263 -f -m meow --jus mix --kilo
266 The non-option index of \c meow is 0 while the original
267 argument index of \c mix is 1.
270 Non-option parsing item of which to get the non-option index.
273 Non-option index of \p item.
276 \p item is not \c NULL.
278 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
281 argpar_item_non_opt_orig_index() -- Returns the original argument
282 index of a non-option parsing item.
284 unsigned int argpar_item_non_opt_non_opt_index(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
288 Destroys the parsing item \p item.
291 Parsing item to destroy (may be \c NULL).
293 void argpar_item_destroy(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
296 @def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
299 Calls argpar_item_destroy() with \p _item, and then sets \p _item
303 Item to destroy and variable to reset
304 (<code>const argpar_item_t *</code> type).
306 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
308 argpar_item_destroy(_item); \
321 Parsing error type, as returned by
322 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
324 typedef enum argpar_error_type
326 /// Unknown option error
327 ARGPAR_ERROR_TYPE_UNKNOWN_OPT
,
329 /// Missing option argument error
330 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG
,
332 /// Unexpected option argument error
333 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG
,
334 } argpar_error_type_t
;
340 Opaque parsing error type
342 typedef struct argpar_error argpar_error_t
;
346 Returns the type of the parsing error object \p error.
349 Parsing error of which to get the type.
355 \p error is not \c NULL.
357 argpar_error_type_t
argpar_error_type(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
361 Returns the index of the original argument (in \p argv, as passed to
362 argpar_iter_create()) for which the parsing error described by
366 Parsing error of which to get the original argument index.
369 Original argument index of \p error.
372 \p error is not \c NULL.
374 unsigned int argpar_error_orig_index(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
378 Returns the name of the unknown option for which the parsing error
379 described by \p error occurred.
381 The returned name includes any <code>-</code> or <code>\--</code>
384 With the long option with argument form, for example
385 <code>\--mireille=deyglun</code>, this function only returns the name
386 part (<code>\--mireille</code> in the last example).
389 Parsing error of which to get the name of the unknown option.
392 Name of the unknown option of \p error.
395 \p error is not \c NULL.
397 The type of \p error, as returned by
398 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
399 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
401 const char *argpar_error_unknown_opt_name(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
405 Returns the descriptor of the option for which the parsing error
406 described by \p error occurred.
409 Parsing error of which to get the option descriptor.
412 If not \c NULL, this function sets \p *is_short to:
414 - \c true if the option for which \p error occurred is a short
417 - \c false if the option for which \p error occurred is a long
422 Descriptor of the option of \p error.
425 \p error is not \c NULL.
427 The type of \p error, as returned by
428 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
429 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
430 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
432 const argpar_opt_descr_t
*argpar_error_opt_descr(const argpar_error_t
*error
,
433 bool *is_short
) ARGPAR_NOEXCEPT
;
437 Destroys the parsing error \p error.
440 Parsing error to destroy (may be \c NULL).
442 void argpar_error_destroy(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
455 argpar_iter_create() accepts an array of instances of such a type,
456 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
458 The typical usage is, for example:
461 const argpar_opt_descr_t descrs[] = {
462 { 0, 'd', NULL, false },
463 { 1, '\0', "squeeze", true },
464 { 2, 'm', "meow", true },
465 ARGPAR_OPT_DESCR_SENTINEL,
469 typedef struct argpar_opt_descr
471 /// Numeric ID, to uniquely identify this descriptor
474 /// Short option character, or <code>'\0'</code>
475 const char short_name
;
477 /// Long option name (without the <code>\--</code> prefix), or \c NULL
478 const char * const long_name
;
480 /// \c true if this option has an argument
482 } argpar_opt_descr_t
;
486 Sentinel for an option descriptor array
488 The typical usage is, for example:
491 const argpar_opt_descr_t descrs[] = {
492 { 0, 'd', NULL, false },
493 { 1, '\0', "squeeze", true },
494 { 2, 'm', "meow", true },
495 ARGPAR_OPT_DESCR_SENTINEL,
499 #define ARGPAR_OPT_DESCR_SENTINEL \
501 -1, '\0', NULL, false \
508 Opaque argpar iterator type
510 argpar_iter_create() returns a pointer to such a type.
512 typedef struct argpar_iter argpar_iter_t
;
516 Creates and returns an argument parsing iterator to parse the
517 original arguments \p argv of which the count is \p argc using the
518 option descriptors \p descrs.
520 This function initializes the returned structure, but doesn't actually
521 start parsing the arguments.
523 argpar considers \em all the elements of \p argv, including the first
524 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
525 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
526 receives, or ignore the parsing item of the first call to
529 \p *argv and \p *descrs must \em not change for all of:
531 - The lifetime of the returned iterator (until you call
532 argpar_iter_destroy()).
534 - The lifetime of any parsing item (until you call
535 argpar_item_destroy()) which argpar_iter_next() creates from the
538 - The lifetime of any parsing error (until you call
539 argpar_error_destroy()) which argpar_iter_next() creates from the
543 Number of original arguments to parse in \p argv.
545 Original arguments to parse, of which the count is \p argc.
548 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
550 May contain duplicate entries.
554 New argument parsing iterator, or \c NULL on memory error.
557 \p argc is greater than 0.
559 \p argv is not \c NULL.
561 The first \p argc elements of \p argv are not \c NULL.
563 \p descrs is not \c NULL.
566 argpar_iter_destroy() -- Destroys an argument parsing iterator.
568 argpar_iter_t
*argpar_iter_create(unsigned int argc
, const char * const *argv
,
569 const argpar_opt_descr_t
*descrs
) ARGPAR_NOEXCEPT
;
573 Destroys the argument parsing iterator \p iter.
576 Argument parsing iterator to destroy (may be \c NULL).
579 argpar_iter_create() -- Creates an argument parsing iterator.
581 void argpar_iter_destroy(argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
585 Return type of argpar_iter_next().
587 Error status enumerators have a negative value.
589 typedef enum argpar_iter_next_status
592 ARGPAR_ITER_NEXT_STATUS_OK
,
594 /// End of iteration (no more original arguments to parse)
595 ARGPAR_ITER_NEXT_STATUS_END
,
598 ARGPAR_ITER_NEXT_STATUS_ERROR
= -1,
601 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY
= -12,
602 } argpar_iter_next_status_t
;
606 Sets \p *item to the next item of the argument parsing iterator
607 \p iter and advances \p iter.
609 If there are no more original arguments to parse, this function returns
610 #ARGPAR_ITER_NEXT_STATUS_END.
613 Argument parsing iterator from which to get the next parsing item.
616 On success, \p *item is the next parsing item of \p iter.
618 Destroy \p *item with argpar_item_destroy().
622 When this function returns #ARGPAR_ITER_NEXT_STATUS_ERROR,
623 if this parameter is not \c NULL, \p *error contains details about
626 Destroy \p *error with argpar_error_destroy().
633 \p iter is not \c NULL.
635 \p item is not \c NULL.
637 argpar_iter_next_status_t
argpar_iter_next(argpar_iter_t
*iter
, const argpar_item_t
**item
,
638 const argpar_error_t
**error
) ARGPAR_NOEXCEPT
;
641 * Returns the number of ingested elements from `argv`, as passed to
642 * argpar_iter_create() to create `*iter`, that were required to produce
643 * the previously returned items.
648 Returns the number of ingested original arguments (in
649 \p argv, as passed to argpar_iter_create() to create \p iter) that
650 the parser ingested to produce the \em previous parsing items.
653 Argument parsing iterator of which to get the number of ingested
657 Number of original arguments which \p iter ingested.
660 \p iter is not \c NULL.
662 unsigned int argpar_iter_ingested_orig_args(const argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
668 #if defined(__cplusplus)
672 #endif /* ARGPAR_ARGPAR_H */