2 * SPDX-License-Identifier: MIT
4 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
5 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
8 #ifndef ARGPAR_ARGPAR_H
9 #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
{
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(
182 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(
221 const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
225 Returns the index, within \em all the original arguments (in
226 \p argv, as passed to argpar_iter_create()), of the non-option
227 parsing item \p item.
229 For example, with the following command line (all options have no
233 -f -m meow --jus mix --kilo
236 The original argument index of \c meow is 2 while the original
237 argument index of \c mix is 4.
240 Non-option parsing item of which to get the original argument index.
243 Original argument index of \p item.
246 \p item is not \c NULL.
248 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
251 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
252 of a non-option parsing item.
254 unsigned int argpar_item_non_opt_orig_index(
255 const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
259 Returns the index, within the parsed non-option parsing items, of
260 the non-option parsing item \p item.
262 For example, with the following command line (all options have no
266 -f -m meow --jus mix --kilo
269 The non-option index of \c meow is 0 while the original
270 argument index of \c mix is 1.
273 Non-option parsing item of which to get the non-option index.
276 Non-option index of \p item.
279 \p item is not \c NULL.
281 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
284 argpar_item_non_opt_orig_index() -- Returns the original argument
285 index of a non-option parsing item.
287 unsigned int argpar_item_non_opt_non_opt_index(
288 const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
292 Destroys the parsing item \p item.
295 Parsing item to destroy (may be \c NULL).
297 void argpar_item_destroy(const argpar_item_t
*item
) ARGPAR_NOEXCEPT
;
300 @def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
303 Calls argpar_item_destroy() with \p _item, and then sets \p _item
307 Item to destroy and variable to reset
308 (<code>const argpar_item_t *</code> type).
310 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
312 argpar_item_destroy(_item); \
325 Parsing error type, as returned by
326 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
328 typedef enum argpar_error_type
{
329 /// Unknown option error
330 ARGPAR_ERROR_TYPE_UNKNOWN_OPT
,
332 /// Missing option argument error
333 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG
,
335 /// Unexpected option argument error
336 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG
,
337 } argpar_error_type_t
;
343 Opaque parsing error type
345 typedef struct argpar_error argpar_error_t
;
349 Returns the type of the parsing error object \p error.
352 Parsing error of which to get the type.
358 \p error is not \c NULL.
360 argpar_error_type_t
argpar_error_type(
361 const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
365 Returns the index of the original argument (in \p argv, as passed to
366 argpar_iter_create()) for which the parsing error described by
370 Parsing error of which to get the original argument index.
373 Original argument index of \p error.
376 \p error is not \c NULL.
378 unsigned int argpar_error_orig_index(
379 const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
383 Returns the name of the unknown option for which the parsing error
384 described by \p error occurred.
386 The returned name includes any <code>-</code> or <code>\--</code>
389 With the long option with argument form, for example
390 <code>\--mireille=deyglun</code>, this function only returns the name
391 part (<code>\--mireille</code> in the last example).
394 Parsing error of which to get the name of the unknown option.
397 Name of the unknown option of \p error.
400 \p error is not \c NULL.
402 The type of \p error, as returned by
403 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
404 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
406 const char *argpar_error_unknown_opt_name(
407 const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
411 Returns the descriptor of the option for which the parsing error
412 described by \p error occurred.
415 Parsing error of which to get the option descriptor.
418 If not \c NULL, this function sets \p *is_short to:
420 - \c true if the option for which \p error occurred is a short
423 - \c false if the option for which \p error occurred is a long
428 Descriptor of the option of \p error.
431 \p error is not \c NULL.
433 The type of \p error, as returned by
434 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
435 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
436 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
438 const argpar_opt_descr_t
*argpar_error_opt_descr(const argpar_error_t
*error
,
439 bool *is_short
) ARGPAR_NOEXCEPT
;
443 Destroys the parsing error \p error.
446 Parsing error to destroy (may be \c NULL).
448 void argpar_error_destroy(const argpar_error_t
*error
) ARGPAR_NOEXCEPT
;
461 argpar_iter_create() accepts an array of instances of such a type,
462 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
464 The typical usage is, for example:
467 const argpar_opt_descr_t descrs[] = {
468 { 0, 'd', NULL, false },
469 { 1, '\0', "squeeze", true },
470 { 2, 'm', "meow", true },
471 ARGPAR_OPT_DESCR_SENTINEL,
475 typedef struct argpar_opt_descr
{
476 /// Numeric ID, to uniquely identify this descriptor
479 /// Short option character, or <code>'\0'</code>
480 const char short_name
;
482 /// Long option name (without the <code>\--</code> prefix), or \c NULL
483 const char * const long_name
;
485 /// \c true if this option has an argument
487 } argpar_opt_descr_t
;
491 Sentinel for an option descriptor array
493 The typical usage is, for example:
496 const argpar_opt_descr_t descrs[] = {
497 { 0, 'd', NULL, false },
498 { 1, '\0', "squeeze", true },
499 { 2, 'm', "meow", true },
500 ARGPAR_OPT_DESCR_SENTINEL,
504 #define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false }
510 Opaque argpar iterator type
512 argpar_iter_create() returns a pointer to such a type.
514 typedef struct argpar_iter argpar_iter_t
;
518 Creates and returns an argument parsing iterator to parse the
519 original arguments \p argv of which the count is \p argc using the
520 option descriptors \p descrs.
522 This function initializes the returned structure, but doesn't actually
523 start parsing the arguments.
525 argpar considers \em all the elements of \p argv, including the first
526 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
527 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
528 receives, or ignore the parsing item of the first call to
531 \p *argv and \p *descrs must \em not change for all of:
533 - The lifetime of the returned iterator (until you call
534 argpar_iter_destroy()).
536 - The lifetime of any parsing item (until you call
537 argpar_item_destroy()) which argpar_iter_next() creates from the
540 - The lifetime of any parsing error (until you call
541 argpar_error_destroy()) which argpar_iter_next() creates from the
545 Number of original arguments to parse in \p argv.
547 Original arguments to parse, of which the count is \p argc.
550 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
552 May contain duplicate entries.
556 New argument parsing iterator, or \c NULL on memory error.
559 \p argc is greater than 0.
561 \p argv is not \c NULL.
563 The first \p argc elements of \p argv are not \c NULL.
565 \p descrs is not \c NULL.
568 argpar_iter_destroy() -- Destroys an argument parsing iterator.
570 argpar_iter_t
*argpar_iter_create(unsigned int argc
, const char * const *argv
,
571 const argpar_opt_descr_t
*descrs
) ARGPAR_NOEXCEPT
;
575 Destroys the argument parsing iterator \p iter.
578 Argument parsing iterator to destroy (may be \c NULL).
581 argpar_iter_create() -- Creates an argument parsing iterator.
583 void argpar_iter_destroy(argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
587 Return type of argpar_iter_next().
589 Error status enumerators have a negative value.
591 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
,
639 const argpar_item_t
**item
,
640 const argpar_error_t
**error
) ARGPAR_NOEXCEPT
;
643 * Returns the number of ingested elements from `argv`, as passed to
644 * argpar_iter_create() to create `*iter`, that were required to produce
645 * the previously returned items.
650 Returns the number of ingested original arguments (in
651 \p argv, as passed to argpar_iter_create() to create \p iter) that
652 the parser ingested to produce the \em previous parsing items.
655 Argument parsing iterator of which to get the number of ingested
659 Number of original arguments which \p iter ingested.
662 \p iter is not \c NULL.
664 unsigned int argpar_iter_ingested_orig_args(
665 const argpar_iter_t
*iter
) ARGPAR_NOEXCEPT
;
671 #if defined(__cplusplus)
675 #endif /* ARGPAR_ARGPAR_H */