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