Add and use type definitions for structures and enumerations
[argpar.git] / argpar / argpar.h
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
5 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
6 */
7
8 #ifndef ARGPAR_ARGPAR_H
9 #define ARGPAR_ARGPAR_H
10
11 #include <stdbool.h>
12
13 #if defined(__cplusplus)
14 extern "C" {
15 #endif
16
17 /*!
18 @mainpage
19
20 See the \ref api module.
21
22 @addtogroup api argpar API
23 @{
24
25 argpar is a library which provides an iterator-based API to parse
26 command-line arguments.
27
28 The 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
71 Create a parsing iterator with argpar_iter_create(), then repeatedly
72 call argpar_iter_next() to access the parsing results (items), until one
73 of:
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
82 argpar_iter_create() accepts duplicate option descriptors in
83 \p descrs (argpar_iter_next() produces one item for each
84 instance).
85
86 A parsing item (the result of argpar_iter_next()) has the type
87 #argpar_item.
88
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).
93
94 argpar_iter_next() produces the items in the same order that it parses
95 original arguments, including non-option arguments. This means, for
96 example, that for:
97
98 @code{.unparsed}
99 --hello --count=23 /path/to/file -ab --type file -- magie
100 @endcode
101
102 argpar_iter_next() produces the following items, in this order:
103
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>.
112 */
113
114 /*
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".
117 *
118 * On Windows, symbols are local unless explicitly exported; see
119 * <https://gcc.gnu.org/wiki/Visibility>.
120 */
121 #if defined(_WIN32) || defined(__CYGWIN__)
122 # define ARGPAR_HIDDEN
123 #else
124 # define ARGPAR_HIDDEN __attribute__((visibility("hidden")))
125 #endif
126
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
134 typedef struct argpar_opt_descr argpar_opt_descr_t;
135
136 /*!
137 @name Item API
138 @{
139 */
140
141 /*!
142 @brief
143 Type of a parsing item, as returned by
144 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
145 */
146 typedef enum argpar_item_type {
147 /// Option
148 ARGPAR_ITEM_TYPE_OPT,
149
150 /// Non-option
151 ARGPAR_ITEM_TYPE_NON_OPT,
152 } argpar_item_type_t;
153
154 /*!
155 @struct argpar_item
156
157 @brief
158 Opaque parsing item type
159
160 argpar_iter_next() sets a pointer to such a type.
161 */
162 typedef struct argpar_item argpar_item_t;
163
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
178 ARGPAR_HIDDEN
179 /// @endcond
180 argpar_item_type_t argpar_item_type(const argpar_item_t *item) ARGPAR_NOEXCEPT;
181
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
198 ARGPAR_HIDDEN
199 /// @endcond
200 const argpar_opt_descr_t *argpar_item_opt_descr(
201 const argpar_item_t *item) ARGPAR_NOEXCEPT;
202
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
220 ARGPAR_HIDDEN
221 /// @endcond
222 const char *argpar_item_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
223
224 /*!
225 @brief
226 Returns the complete original argument, pointing to one of the
227 entries of the original arguments (in \p argv, as passed to
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
243 ARGPAR_HIDDEN
244 /// @endcond
245 const char *argpar_item_non_opt_arg(
246 const argpar_item_t *item) ARGPAR_NOEXCEPT;
247
248 /*!
249 @brief
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.
253
254 For example, with the following command line (all options have no
255 argument):
256
257 @code{.unparsed}
258 -f -m meow --jus mix --kilo
259 @endcode
260
261 The original argument index of \c meow is&nbsp;2 while the original
262 argument 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
280 ARGPAR_HIDDEN
281 /// @endcond
282 unsigned int argpar_item_non_opt_orig_index(
283 const argpar_item_t *item) ARGPAR_NOEXCEPT;
284
285 /*!
286 @brief
287 Returns the index, within the parsed non-option parsing items, of
288 the non-option parsing item \p item.
289
290 For example, with the following command line (all options have no
291 argument):
292
293 @code{.unparsed}
294 -f -m meow --jus mix --kilo
295 @endcode
296
297 The non-option index of \c meow is&nbsp;0 while the original
298 argument 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
316 ARGPAR_HIDDEN
317 /// @endcond
318 unsigned int argpar_item_non_opt_non_opt_index(
319 const argpar_item_t *item) ARGPAR_NOEXCEPT;
320
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
329 ARGPAR_HIDDEN
330 /// @endcond
331 void argpar_item_destroy(const argpar_item_t *item) ARGPAR_NOEXCEPT;
332
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
342 (<code>const argpar_item_t *</code> type).
343 */
344 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
345 { \
346 argpar_item_destroy(_item); \
347 _item = NULL; \
348 }
349
350 /// @}
351
352 /*!
353 @name Error API
354 @{
355 */
356
357 /*!
358 @brief
359 Parsing error type, as returned by
360 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
361 */
362 typedef enum argpar_error_type {
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,
371 } argpar_error_type_t;
372
373 /*!
374 @struct argpar_error
375
376 @brief
377 Opaque parsing error type
378 */
379 typedef struct argpar_error argpar_error_t;
380
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
395 ARGPAR_HIDDEN
396 /// @endcond
397 argpar_error_type_t argpar_error_type(
398 const argpar_error_t *error) ARGPAR_NOEXCEPT;
399
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
416 ARGPAR_HIDDEN
417 /// @endcond
418 unsigned int argpar_error_orig_index(
419 const argpar_error_t *error) ARGPAR_NOEXCEPT;
420
421 /*!
422 @brief
423 Returns the name of the unknown option for which the parsing error
424 described by \p error occurred.
425
426 The returned name includes any <code>-</code> or <code>\--</code>
427 prefix.
428
429 With the long option with argument form, for example
430 <code>\--mireille=deyglun</code>, this function only returns the name
431 part (<code>\--mireille</code> in the last example).
432
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
442 The type of \p error, as returned by
443 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
444 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
445 */
446 /// @cond hidden_macro
447 ARGPAR_HIDDEN
448 /// @endcond
449 const char *argpar_error_unknown_opt_name(
450 const argpar_error_t *error) ARGPAR_NOEXCEPT;
451
452 /*!
453 @brief
454 Returns the descriptor of the option for which the parsing error
455 described by \p error occurred.
456
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
476 The type of \p error, as returned by
477 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
478 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
479 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
480 */
481 /// @cond hidden_macro
482 ARGPAR_HIDDEN
483 /// @endcond
484 const argpar_opt_descr_t *argpar_error_opt_descr(const argpar_error_t *error,
485 bool *is_short) ARGPAR_NOEXCEPT;
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
495 ARGPAR_HIDDEN
496 /// @endcond
497 void argpar_error_destroy(const argpar_error_t *error) ARGPAR_NOEXCEPT;
498
499 /// @}
500
501 /*!
502 @name Iterator API
503 @{
504 */
505
506 /*!
507 @brief
508 Option descriptor
509
510 argpar_iter_create() accepts an array of instances of such a type,
511 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
512
513 The typical usage is, for example:
514
515 @code
516 const argpar_opt_descr_t descrs[] = {
517 { 0, 'd', NULL, false },
518 { 1, '\0', "squeeze", true },
519 { 2, 'm', "meow", true },
520 ARGPAR_OPT_DESCR_SENTINEL,
521 };
522 @endcode
523 */
524 typedef struct argpar_opt_descr {
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;
536 } argpar_opt_descr_t;
537
538 /*!
539 @brief
540 Sentinel for an option descriptor array
541
542 The typical usage is, for example:
543
544 @code
545 const argpar_opt_descr_t descrs[] = {
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
561 argpar_iter_create() returns a pointer to such a type.
562 */
563 typedef struct argpar_iter argpar_iter_t;
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
571 This function initializes the returned structure, but doesn't actually
572 start parsing the arguments.
573
574 argpar considers \em all the elements of \p argv, including the first
575 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
576 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
577 receives, or ignore the parsing item of the first call to
578 argpar_iter_next().
579
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.
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
620 ARGPAR_HIDDEN
621 /// @endcond
622 argpar_iter_t *argpar_iter_create(unsigned int argc, const char * const *argv,
623 const argpar_opt_descr_t *descrs) ARGPAR_NOEXCEPT;
624
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
636 ARGPAR_HIDDEN
637 /// @endcond
638 void argpar_iter_destroy(argpar_iter_t *iter) ARGPAR_NOEXCEPT;
639
640 /*!
641 @brief
642 Return type of argpar_iter_next().
643
644 Error status enumerators have a negative value.
645 */
646 typedef enum argpar_iter_next_status {
647 /// Success
648 ARGPAR_ITER_NEXT_STATUS_OK,
649
650 /// End of iteration (no more original arguments to parse)
651 ARGPAR_ITER_NEXT_STATUS_END,
652
653 /// Parsing error
654 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
655
656 /// Memory error
657 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
658 } argpar_iter_next_status_t;
659
660 /*!
661 @brief
662 Sets \p *item to the next item of the argument parsing iterator
663 \p iter and advances \p iter.
664
665 If 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
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.
681
682 Destroy \p *error with argpar_error_destroy().
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
694 ARGPAR_HIDDEN
695 /// @endcond
696 argpar_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;
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 */
705
706 /*!
707 @brief
708 Returns the number of ingested original arguments (in
709 \p argv, as passed to argpar_iter_create() to create \p iter) that
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
723 ARGPAR_HIDDEN
724 /// @endcond
725 unsigned int argpar_iter_ingested_orig_args(
726 const argpar_iter_t *iter) ARGPAR_NOEXCEPT;
727
728 /// @}
729
730 /// @}
731
732 #if defined(__cplusplus)
733 }
734 #endif
735
736 #endif /* ARGPAR_ARGPAR_H */
This page took 0.044462 seconds and 5 git commands to generate.