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