tap: import some changes
[argpar.git] / argpar / argpar.h
CommitLineData
903a5b8a 1/*
03e1579f 2 * SPDX-License-Identifier: MIT
9cc0acc6
PP
3 * SPDX-FileCopyrightText: 2019-2024 Philippe Proulx <pproulx@efficios.com>
4 * SPDX-FileCopyrightText: 2020-2024 Simon Marchi <simon.marchi@efficios.com>
903a5b8a
SM
5 */
6
fe5a18f8
PP
7#ifndef ARGPAR_ARGPAR_H
8#define ARGPAR_ARGPAR_H
03e1579f 9
903a5b8a
SM
10#include <stdbool.h>
11
6ad7927f
SM
12#if defined(__cplusplus)
13extern "C" {
14#endif
15
9e2c879b
PP
16/*!
17@mainpage
fc07e526 18
9e2c879b
PP
19See the \ref api module.
20
21@addtogroup api argpar API
22@{
23
24argpar is a library which provides an iterator-based API to parse
25command-line arguments.
26
27The argpar parser supports:
28
29<ul>
30 <li>
31 Short options without an argument, possibly tied together:
32
33 @code{.unparsed}
34 -f -auf -n
35 @endcode
36
37 <li>
38 Short options with arguments:
39
40 @code{.unparsed}
41 -b 45 -f/mein/file -xyzhello
42 @endcode
43
44 <li>
45 Long options without an argument:
46
47 @code{.unparsed}
48 --five-guys --burger-king --pizza-hut --subway
49 @endcode
50
51 <li>
52 Long options with arguments (two original arguments or a single
53 one with a <code>=</code> character):
54
55 @code{.unparsed}
56 --security enable --time=18.56
57 @endcode
58
59 <li>
60 Non-option arguments (anything else, including
61 <code>-</code> and <code>\--</code>).
62
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.
68</ul>
69
70Create a parsing iterator with argpar_iter_create(), then repeatedly
71call argpar_iter_next() to access the parsing results (items), until one
72of:
73
74- There are no more arguments.
75
76- The argument parser encounters an error (for example, an unknown
77 option).
78
79- You need to stop.
80
81argpar_iter_create() accepts duplicate option descriptors in
82\p descrs (argpar_iter_next() produces one item for each
83instance).
84
85A parsing item (the result of argpar_iter_next()) has the type
86#argpar_item.
87
88Get the type (option or non-option) of an item with
7554f0b6 89\link argpar_item_type(const argpar_item_t *) argpar_item_type()\endlink.
1c881812 90Each item type has its set of dedicated functions
9e2c879b
PP
91(\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes).
92
93argpar_iter_next() produces the items in the same order that it parses
94original arguments, including non-option arguments. This means, for
95example, that for:
96
97@code{.unparsed}
98--hello --count=23 /path/to/file -ab --type file -- magie
99@endcode
100
101argpar_iter_next() produces the following items, in this order:
102
dd21499c
PP
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>.
9e2c879b 111*/
903a5b8a 112
9b49cc18
PP
113/* Internal: `noexcept` specifier if C++ ≥ 11 */
114#if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
45ad74d3 115# define ARGPAR_NOEXCEPT noexcept
9b49cc18 116#else
45ad74d3 117# define ARGPAR_NOEXCEPT
9b49cc18
PP
118#endif
119
7554f0b6 120typedef struct argpar_opt_descr argpar_opt_descr_t;
903a5b8a 121
9e2c879b
PP
122/*!
123@name Item API
124@{
125*/
903a5b8a 126
9e2c879b
PP
127/*!
128@brief
1c881812 129 Type of a parsing item, as returned by
7554f0b6 130 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
9e2c879b 131*/
45ad74d3
SM
132typedef enum argpar_item_type
133{
134 /// Option
135 ARGPAR_ITEM_TYPE_OPT,
903a5b8a 136
45ad74d3
SM
137 /// Non-option
138 ARGPAR_ITEM_TYPE_NON_OPT,
7554f0b6 139} argpar_item_type_t;
903a5b8a 140
9e2c879b
PP
141/*!
142@struct argpar_item
143
144@brief
145 Opaque parsing item type
146
147argpar_iter_next() sets a pointer to such a type.
148*/
7554f0b6 149typedef struct argpar_item argpar_item_t;
903a5b8a 150
9e2c879b
PP
151/*!
152@brief
153 Returns the type of the parsing item \p item.
154
155@param[in] item
156 Parsing item of which to get the type.
157
158@returns
159 Type of \p item.
160
161@pre
162 \p item is not \c NULL.
163*/
7554f0b6 164argpar_item_type_t argpar_item_type(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 165
9e2c879b
PP
166/*!
167@brief
168 Returns the option descriptor of the option parsing item \p item.
169
170@param[in] item
171 Option parsing item of which to get the option descriptor.
172
173@returns
174 Option descriptor of \p item.
175
176@pre
177 \p item is not \c NULL.
178@pre
179 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
180*/
45ad74d3 181const argpar_opt_descr_t *argpar_item_opt_descr(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 182
9e2c879b
PP
183/*!
184@brief
185 Returns the argument of the option parsing item \p item, or
186 \c NULL if none.
187
188@param[in] item
189 Option parsing item of which to get the argument.
190
191@returns
192 Argument of \p item, or \c NULL if none.
193
194@pre
195 \p item is not \c NULL.
196@pre
197 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
198*/
7554f0b6 199const char *argpar_item_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 200
9e2c879b
PP
201/*!
202@brief
203 Returns the complete original argument, pointing to one of the
8b95d883 204 entries of the original arguments (in \p argv, as passed to
9e2c879b
PP
205 argpar_iter_create()), of the non-option parsing item \p item.
206
207@param[in] item
208 Non-option parsing item of which to get the complete original
209 argument.
210
211@returns
212 Complete original argument of \p item.
213
214@pre
215 \p item is not \c NULL.
216@pre
217 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
218*/
45ad74d3 219const char *argpar_item_non_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 220
9e2c879b
PP
221/*!
222@brief
8b95d883
PP
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.
9e2c879b
PP
226
227For example, with the following command line (all options have no
228argument):
229
230@code{.unparsed}
231-f -m meow --jus mix --kilo
232@endcode
233
234The original argument index of \c meow is&nbsp;2 while the original
235argument index of \c mix is&nbsp;4.
236
237@param[in] item
238 Non-option parsing item of which to get the original argument index.
239
240@returns
241 Original argument index of \p item.
242
243@pre
244 \p item is not \c NULL.
245@pre
246 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
247
248@sa
249 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
250 of a non-option parsing item.
251*/
45ad74d3 252unsigned int argpar_item_non_opt_orig_index(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 253
9e2c879b
PP
254/*!
255@brief
256 Returns the index, within the parsed non-option parsing items, of
257 the non-option parsing item \p item.
258
259For example, with the following command line (all options have no
260argument):
261
262@code{.unparsed}
263-f -m meow --jus mix --kilo
264@endcode
265
266The non-option index of \c meow is&nbsp;0 while the original
267argument index of \c mix is&nbsp;1.
268
269@param[in] item
270 Non-option parsing item of which to get the non-option index.
271
272@returns
273 Non-option index of \p item.
274
275@pre
276 \p item is not \c NULL.
277@pre
278 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
279
280@sa
281 argpar_item_non_opt_orig_index() -- Returns the original argument
282 index of a non-option parsing item.
283*/
45ad74d3 284unsigned int argpar_item_non_opt_non_opt_index(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 285
9e2c879b
PP
286/*!
287@brief
288 Destroys the parsing item \p item.
289
290@param[in] item
291 Parsing item to destroy (may be \c NULL).
292*/
7554f0b6 293void argpar_item_destroy(const argpar_item_t *item) ARGPAR_NOEXCEPT;
a473f6cb 294
9e2c879b
PP
295/*!
296@def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
297
298@brief
299 Calls argpar_item_destroy() with \p _item, and then sets \p _item
300 to \c NULL.
301
302@param[in] _item
303 Item to destroy and variable to reset
7554f0b6 304 (<code>const argpar_item_t *</code> type).
9e2c879b 305*/
45ad74d3
SM
306#define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
307 { \
308 argpar_item_destroy(_item); \
2f9b7649 309 (_item) = NULL; \
45ad74d3 310 }
9e2c879b
PP
311
312/// @}
313
8b95d883
PP
314/*!
315@name Error API
316@{
317*/
318
1c881812
PP
319/*!
320@brief
321 Parsing error type, as returned by
7554f0b6 322 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
1c881812 323*/
45ad74d3
SM
324typedef enum argpar_error_type
325{
326 /// Unknown option error
327 ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
10aefab2 328
45ad74d3
SM
329 /// Missing option argument error
330 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
10aefab2 331
45ad74d3
SM
332 /// Unexpected option argument error
333 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
7554f0b6 334} argpar_error_type_t;
10aefab2 335
8b95d883
PP
336/*!
337@struct argpar_error
338
339@brief
340 Opaque parsing error type
341*/
7554f0b6 342typedef struct argpar_error argpar_error_t;
8b95d883 343
1c881812
PP
344/*!
345@brief
346 Returns the type of the parsing error object \p error.
347
348@param[in] error
349 Parsing error of which to get the type.
350
351@returns
352 Type of \p error.
353
354@pre
355 \p error is not \c NULL.
356*/
45ad74d3 357argpar_error_type_t argpar_error_type(const argpar_error_t *error) ARGPAR_NOEXCEPT;
10aefab2 358
8b95d883
PP
359/*!
360@brief
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
363 \p error occurred.
364
365@param[in] error
366 Parsing error of which to get the original argument index.
367
368@returns
369 Original argument index of \p error.
370
371@pre
372 \p error is not \c NULL.
373*/
45ad74d3 374unsigned int argpar_error_orig_index(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
375
376/*!
377@brief
378 Returns the name of the unknown option for which the parsing error
379 described by \p error occurred.
380
381The returned name includes any <code>-</code> or <code>\--</code>
382prefix.
383
384With the long option with argument form, for example
385<code>\--mireille=deyglun</code>, this function only returns the name
386part (<code>\--mireille</code> in the last example).
387
8b95d883
PP
388@param[in] error
389 Parsing error of which to get the name of the unknown option.
390
391@returns
392 Name of the unknown option of \p error.
393
394@pre
395 \p error is not \c NULL.
396@pre
1c881812 397 The type of \p error, as returned by
7554f0b6 398 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
1c881812 399 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
8b95d883 400*/
45ad74d3 401const char *argpar_error_unknown_opt_name(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
402
403/*!
404@brief
405 Returns the descriptor of the option for which the parsing error
406 described by \p error occurred.
407
8b95d883
PP
408@param[in] error
409 Parsing error of which to get the option descriptor.
410@param[out] is_short
411 @parblock
412 If not \c NULL, this function sets \p *is_short to:
413
414 - \c true if the option for which \p error occurred is a short
415 option.
416
417 - \c false if the option for which \p error occurred is a long
418 option.
419 @endparblock
420
421@returns
422 Descriptor of the option of \p error.
423
424@pre
425 \p error is not \c NULL.
426@pre
1c881812 427 The type of \p error, as returned by
7554f0b6 428 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
1c881812
PP
429 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
430 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
8b95d883 431*/
7554f0b6 432const argpar_opt_descr_t *argpar_error_opt_descr(const argpar_error_t *error,
45ad74d3 433 bool *is_short) ARGPAR_NOEXCEPT;
8b95d883
PP
434
435/*!
436@brief
437 Destroys the parsing error \p error.
438
439@param[in] error
440 Parsing error to destroy (may be \c NULL).
441*/
7554f0b6 442void argpar_error_destroy(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
443
444/// @}
445
9e2c879b
PP
446/*!
447@name Iterator API
448@{
449*/
450
451/*!
452@brief
453 Option descriptor
454
455argpar_iter_create() accepts an array of instances of such a type,
456terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
457
458The typical usage is, for example:
459
460@code
7554f0b6 461const argpar_opt_descr_t descrs[] = {
9e2c879b
PP
462 { 0, 'd', NULL, false },
463 { 1, '\0', "squeeze", true },
464 { 2, 'm', "meow", true },
465 ARGPAR_OPT_DESCR_SENTINEL,
466};
467@endcode
468*/
45ad74d3
SM
469typedef struct argpar_opt_descr
470{
471 /// Numeric ID, to uniquely identify this descriptor
472 const int id;
9e2c879b 473
45ad74d3
SM
474 /// Short option character, or <code>'\0'</code>
475 const char short_name;
9e2c879b 476
45ad74d3
SM
477 /// Long option name (without the <code>\--</code> prefix), or \c NULL
478 const char * const long_name;
9e2c879b 479
45ad74d3
SM
480 /// \c true if this option has an argument
481 const bool with_arg;
7554f0b6 482} argpar_opt_descr_t;
9e2c879b
PP
483
484/*!
485@brief
486 Sentinel for an option descriptor array
487
488The typical usage is, for example:
489
490@code
7554f0b6 491const argpar_opt_descr_t descrs[] = {
9e2c879b
PP
492 { 0, 'd', NULL, false },
493 { 1, '\0', "squeeze", true },
494 { 2, 'm', "meow", true },
495 ARGPAR_OPT_DESCR_SENTINEL,
496};
497@endcode
498*/
45ad74d3
SM
499#define ARGPAR_OPT_DESCR_SENTINEL \
500 { \
501 -1, '\0', NULL, false \
502 }
9e2c879b
PP
503
504/*!
505@struct argpar_iter
506
507@brief
508 Opaque argpar iterator type
509
510argpar_iter_create() returns a pointer to such a type.
511*/
7554f0b6 512typedef struct argpar_iter argpar_iter_t;
9e2c879b
PP
513
514/*!
515@brief
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.
519
520This function initializes the returned structure, but doesn't actually
521start parsing the arguments.
522
523argpar considers \em all the elements of \p argv, including the first
524one, so that you would typically pass <code>(argc - 1)</code> as \p argc
525and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
526receives, or ignore the parsing item of the first call to
527argpar_iter_next().
528
8b95d883
PP
529\p *argv and \p *descrs must \em not change for all of:
530
531- The lifetime of the returned iterator (until you call
532 argpar_iter_destroy()).
533
534- The lifetime of any parsing item (until you call
535 argpar_item_destroy()) which argpar_iter_next() creates from the
536 returned iterator.
537
538- The lifetime of any parsing error (until you call
539 argpar_error_destroy()) which argpar_iter_next() creates from the
540 returned iterator.
9e2c879b
PP
541
542@param[in] argc
543 Number of original arguments to parse in \p argv.
544@param[in] argv
545 Original arguments to parse, of which the count is \p argc.
546@param[in] descrs
547 @parblock
548 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
549
550 May contain duplicate entries.
551 @endparblock
552
553@returns
554 New argument parsing iterator, or \c NULL on memory error.
555
556@pre
557 \p argc is greater than 0.
558@pre
559 \p argv is not \c NULL.
560@pre
561 The first \p argc elements of \p argv are not \c NULL.
562@pre
563 \p descrs is not \c NULL.
564
565@sa
566 argpar_iter_destroy() -- Destroys an argument parsing iterator.
567*/
7554f0b6 568argpar_iter_t *argpar_iter_create(unsigned int argc, const char * const *argv,
45ad74d3 569 const argpar_opt_descr_t *descrs) ARGPAR_NOEXCEPT;
fc07e526 570
9e2c879b
PP
571/*!
572@brief
573 Destroys the argument parsing iterator \p iter.
574
575@param[in] iter
576 Argument parsing iterator to destroy (may be \c NULL).
577
578@sa
579 argpar_iter_create() -- Creates an argument parsing iterator.
580*/
7554f0b6 581void argpar_iter_destroy(argpar_iter_t *iter) ARGPAR_NOEXCEPT;
fc07e526 582
9e2c879b
PP
583/*!
584@brief
585 Return type of argpar_iter_next().
10197dcc
PP
586
587Error status enumerators have a negative value.
9e2c879b 588*/
45ad74d3
SM
589typedef enum argpar_iter_next_status
590{
591 /// Success
592 ARGPAR_ITER_NEXT_STATUS_OK,
9e2c879b 593
45ad74d3
SM
594 /// End of iteration (no more original arguments to parse)
595 ARGPAR_ITER_NEXT_STATUS_END,
9e2c879b 596
45ad74d3
SM
597 /// Parsing error
598 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
9e2c879b 599
45ad74d3
SM
600 /// Memory error
601 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
7554f0b6 602} argpar_iter_next_status_t;
fc07e526 603
9e2c879b
PP
604/*!
605@brief
606 Sets \p *item to the next item of the argument parsing iterator
607 \p iter and advances \p iter.
608
609If there are no more original arguments to parse, this function returns
610#ARGPAR_ITER_NEXT_STATUS_END.
611
612@param[in] iter
613 Argument parsing iterator from which to get the next parsing item.
614@param[out] item
615 @parblock
616 On success, \p *item is the next parsing item of \p iter.
617
618 Destroy \p *item with argpar_item_destroy().
619 @endparblock
620@param[out] error
621 @parblock
1c881812
PP
622 When this function returns #ARGPAR_ITER_NEXT_STATUS_ERROR,
623 if this parameter is not \c NULL, \p *error contains details about
624 the error.
9e2c879b 625
8b95d883 626 Destroy \p *error with argpar_error_destroy().
9e2c879b
PP
627 @endparblock
628
629@returns
630 Status code.
631
632@pre
633 \p iter is not \c NULL.
634@pre
635 \p item is not \c NULL.
636*/
45ad74d3
SM
637argpar_iter_next_status_t argpar_iter_next(argpar_iter_t *iter, const argpar_item_t **item,
638 const argpar_error_t **error) ARGPAR_NOEXCEPT;
fc07e526
SM
639
640/*
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.
644 */
9e2c879b
PP
645
646/*!
647@brief
648 Returns the number of ingested original arguments (in
8b95d883 649 \p argv, as passed to argpar_iter_create() to create \p iter) that
9e2c879b
PP
650 the parser ingested to produce the \em previous parsing items.
651
652@param[in] iter
653 Argument parsing iterator of which to get the number of ingested
654 original arguments.
655
656@returns
657 Number of original arguments which \p iter ingested.
658
659@pre
660 \p iter is not \c NULL.
661*/
45ad74d3 662unsigned int argpar_iter_ingested_orig_args(const argpar_iter_t *iter) ARGPAR_NOEXCEPT;
fc07e526 663
9e2c879b
PP
664/// @}
665
666/// @}
fc07e526 667
6ad7927f
SM
668#if defined(__cplusplus)
669}
670#endif
671
fe5a18f8 672#endif /* ARGPAR_ARGPAR_H */
This page took 0.050796 seconds and 4 git commands to generate.