Add `extern "C"` to header
[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 struct argpar_item *) 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 struct argpar_opt_descr;
128
129 /*!
130 @name Item API
131 @{
132 */
133
134 /*!
135 @brief
136 Type of a parsing item, as returned by
137 \link argpar_item_type(const struct argpar_item *) argpar_item_type()\endlink.
138 */
139 enum argpar_item_type {
140 /// Option
141 ARGPAR_ITEM_TYPE_OPT,
142
143 /// Non-option
144 ARGPAR_ITEM_TYPE_NON_OPT,
145 };
146
147 /*!
148 @struct argpar_item
149
150 @brief
151 Opaque parsing item type
152
153 argpar_iter_next() sets a pointer to such a type.
154 */
155 struct argpar_item;
156
157 /*!
158 @brief
159 Returns the type of the parsing item \p item.
160
161 @param[in] item
162 Parsing item of which to get the type.
163
164 @returns
165 Type of \p item.
166
167 @pre
168 \p item is not \c NULL.
169 */
170 /// @cond hidden_macro
171 ARGPAR_HIDDEN
172 /// @endcond
173 enum argpar_item_type argpar_item_type(const struct argpar_item *item);
174
175 /*!
176 @brief
177 Returns the option descriptor of the option parsing item \p item.
178
179 @param[in] item
180 Option parsing item of which to get the option descriptor.
181
182 @returns
183 Option descriptor of \p item.
184
185 @pre
186 \p item is not \c NULL.
187 @pre
188 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
189 */
190 /// @cond hidden_macro
191 ARGPAR_HIDDEN
192 /// @endcond
193 const struct argpar_opt_descr *argpar_item_opt_descr(
194 const struct argpar_item *item);
195
196 /*!
197 @brief
198 Returns the argument of the option parsing item \p item, or
199 \c NULL if none.
200
201 @param[in] item
202 Option parsing item of which to get the argument.
203
204 @returns
205 Argument of \p item, or \c NULL if none.
206
207 @pre
208 \p item is not \c NULL.
209 @pre
210 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
211 */
212 /// @cond hidden_macro
213 ARGPAR_HIDDEN
214 /// @endcond
215 const char *argpar_item_opt_arg(const struct argpar_item *item);
216
217 /*!
218 @brief
219 Returns the complete original argument, pointing to one of the
220 entries of the original arguments (in \p argv, as passed to
221 argpar_iter_create()), of the non-option parsing item \p item.
222
223 @param[in] item
224 Non-option parsing item of which to get the complete original
225 argument.
226
227 @returns
228 Complete original argument of \p item.
229
230 @pre
231 \p item is not \c NULL.
232 @pre
233 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
234 */
235 /// @cond hidden_macro
236 ARGPAR_HIDDEN
237 /// @endcond
238 const char *argpar_item_non_opt_arg(const struct argpar_item *item);
239
240 /*!
241 @brief
242 Returns the index, within \em all the original arguments (in
243 \p argv, as passed to argpar_iter_create()), of the non-option
244 parsing item \p item.
245
246 For example, with the following command line (all options have no
247 argument):
248
249 @code{.unparsed}
250 -f -m meow --jus mix --kilo
251 @endcode
252
253 The original argument index of \c meow is&nbsp;2 while the original
254 argument index of \c mix is&nbsp;4.
255
256 @param[in] item
257 Non-option parsing item of which to get the original argument index.
258
259 @returns
260 Original argument index of \p item.
261
262 @pre
263 \p item is not \c NULL.
264 @pre
265 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
266
267 @sa
268 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
269 of a non-option parsing item.
270 */
271 /// @cond hidden_macro
272 ARGPAR_HIDDEN
273 /// @endcond
274 unsigned int argpar_item_non_opt_orig_index(const struct argpar_item *item);
275
276 /*!
277 @brief
278 Returns the index, within the parsed non-option parsing items, of
279 the non-option parsing item \p item.
280
281 For example, with the following command line (all options have no
282 argument):
283
284 @code{.unparsed}
285 -f -m meow --jus mix --kilo
286 @endcode
287
288 The non-option index of \c meow is&nbsp;0 while the original
289 argument index of \c mix is&nbsp;1.
290
291 @param[in] item
292 Non-option parsing item of which to get the non-option index.
293
294 @returns
295 Non-option index of \p item.
296
297 @pre
298 \p item is not \c NULL.
299 @pre
300 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
301
302 @sa
303 argpar_item_non_opt_orig_index() -- Returns the original argument
304 index of a non-option parsing item.
305 */
306 /// @cond hidden_macro
307 ARGPAR_HIDDEN
308 /// @endcond
309 unsigned int argpar_item_non_opt_non_opt_index(const struct argpar_item *item);
310
311 /*!
312 @brief
313 Destroys the parsing item \p item.
314
315 @param[in] item
316 Parsing item to destroy (may be \c NULL).
317 */
318 /// @cond hidden_macro
319 ARGPAR_HIDDEN
320 /// @endcond
321 void argpar_item_destroy(const struct argpar_item *item);
322
323 /*!
324 @def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
325
326 @brief
327 Calls argpar_item_destroy() with \p _item, and then sets \p _item
328 to \c NULL.
329
330 @param[in] _item
331 Item to destroy and variable to reset
332 (<code>const struct argpar_item *</code> type).
333 */
334 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
335 { \
336 argpar_item_destroy(_item); \
337 _item = NULL; \
338 }
339
340 /// @}
341
342 /*!
343 @name Error API
344 @{
345 */
346
347 /*!
348 @brief
349 Parsing error type, as returned by
350 \link argpar_error_type(const struct argpar_error *) argpar_error_type()\endlink.
351 */
352 enum argpar_error_type {
353 /// Unknown option error
354 ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
355
356 /// Missing option argument error
357 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
358
359 /// Unexpected option argument error
360 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
361 };
362
363 /*!
364 @struct argpar_error
365
366 @brief
367 Opaque parsing error type
368 */
369 struct argpar_error;
370
371 /*!
372 @brief
373 Returns the type of the parsing error object \p error.
374
375 @param[in] error
376 Parsing error of which to get the type.
377
378 @returns
379 Type of \p error.
380
381 @pre
382 \p error is not \c NULL.
383 */
384 /// @cond hidden_macro
385 ARGPAR_HIDDEN
386 /// @endcond
387 enum argpar_error_type argpar_error_type(const struct argpar_error *error);
388
389 /*!
390 @brief
391 Returns the index of the original argument (in \p argv, as passed to
392 argpar_iter_create()) for which the parsing error described by
393 \p error occurred.
394
395 @param[in] error
396 Parsing error of which to get the original argument index.
397
398 @returns
399 Original argument index of \p error.
400
401 @pre
402 \p error is not \c NULL.
403 */
404 /// @cond hidden_macro
405 ARGPAR_HIDDEN
406 /// @endcond
407 unsigned int argpar_error_orig_index(const struct argpar_error *error);
408
409 /*!
410 @brief
411 Returns the name of the unknown option for which the parsing error
412 described by \p error occurred.
413
414 The returned name includes any <code>-</code> or <code>\--</code>
415 prefix.
416
417 With the long option with argument form, for example
418 <code>\--mireille=deyglun</code>, this function only returns the name
419 part (<code>\--mireille</code> in the last example).
420
421 @param[in] error
422 Parsing error of which to get the name of the unknown option.
423
424 @returns
425 Name of the unknown option of \p error.
426
427 @pre
428 \p error is not \c NULL.
429 @pre
430 The type of \p error, as returned by
431 \link argpar_error_type(const struct argpar_error *) argpar_error_type()\endlink,
432 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
433 */
434 /// @cond hidden_macro
435 ARGPAR_HIDDEN
436 /// @endcond
437 const char *argpar_error_unknown_opt_name(const struct argpar_error *error);
438
439 /*!
440 @brief
441 Returns the descriptor of the option for which the parsing error
442 described by \p error occurred.
443
444 @param[in] error
445 Parsing error of which to get the option descriptor.
446 @param[out] is_short
447 @parblock
448 If not \c NULL, this function sets \p *is_short to:
449
450 - \c true if the option for which \p error occurred is a short
451 option.
452
453 - \c false if the option for which \p error occurred is a long
454 option.
455 @endparblock
456
457 @returns
458 Descriptor of the option of \p error.
459
460 @pre
461 \p error is not \c NULL.
462 @pre
463 The type of \p error, as returned by
464 \link argpar_error_type(const struct argpar_error *) argpar_error_type()\endlink,
465 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
466 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
467 */
468 /// @cond hidden_macro
469 ARGPAR_HIDDEN
470 /// @endcond
471 const struct argpar_opt_descr *argpar_error_opt_descr(
472 const struct argpar_error *error, bool *is_short);
473
474 /*!
475 @brief
476 Destroys the parsing error \p error.
477
478 @param[in] error
479 Parsing error to destroy (may be \c NULL).
480 */
481 /// @cond hidden_macro
482 ARGPAR_HIDDEN
483 /// @endcond
484 void argpar_error_destroy(const struct argpar_error *error);
485
486 /// @}
487
488 /*!
489 @name Iterator API
490 @{
491 */
492
493 /*!
494 @brief
495 Option descriptor
496
497 argpar_iter_create() accepts an array of instances of such a type,
498 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
499
500 The typical usage is, for example:
501
502 @code
503 const struct argpar_opt_descr descrs[] = {
504 { 0, 'd', NULL, false },
505 { 1, '\0', "squeeze", true },
506 { 2, 'm', "meow", true },
507 ARGPAR_OPT_DESCR_SENTINEL,
508 };
509 @endcode
510 */
511 struct argpar_opt_descr {
512 /// Numeric ID, to uniquely identify this descriptor
513 const int id;
514
515 /// Short option character, or <code>'\0'</code>
516 const char short_name;
517
518 /// Long option name (without the <code>\--</code> prefix), or \c NULL
519 const char * const long_name;
520
521 /// \c true if this option has an argument
522 const bool with_arg;
523 };
524
525 /*!
526 @brief
527 Sentinel for an option descriptor array
528
529 The typical usage is, for example:
530
531 @code
532 const struct argpar_opt_descr descrs[] = {
533 { 0, 'd', NULL, false },
534 { 1, '\0', "squeeze", true },
535 { 2, 'm', "meow", true },
536 ARGPAR_OPT_DESCR_SENTINEL,
537 };
538 @endcode
539 */
540 #define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false }
541
542 /*!
543 @struct argpar_iter
544
545 @brief
546 Opaque argpar iterator type
547
548 argpar_iter_create() returns a pointer to such a type.
549 */
550 struct argpar_iter;
551
552 /*!
553 @brief
554 Creates and returns an argument parsing iterator to parse the
555 original arguments \p argv of which the count is \p argc using the
556 option descriptors \p descrs.
557
558 This function initializes the returned structure, but doesn't actually
559 start parsing the arguments.
560
561 argpar considers \em all the elements of \p argv, including the first
562 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
563 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
564 receives, or ignore the parsing item of the first call to
565 argpar_iter_next().
566
567 \p *argv and \p *descrs must \em not change for all of:
568
569 - The lifetime of the returned iterator (until you call
570 argpar_iter_destroy()).
571
572 - The lifetime of any parsing item (until you call
573 argpar_item_destroy()) which argpar_iter_next() creates from the
574 returned iterator.
575
576 - The lifetime of any parsing error (until you call
577 argpar_error_destroy()) which argpar_iter_next() creates from the
578 returned iterator.
579
580 @param[in] argc
581 Number of original arguments to parse in \p argv.
582 @param[in] argv
583 Original arguments to parse, of which the count is \p argc.
584 @param[in] descrs
585 @parblock
586 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
587
588 May contain duplicate entries.
589 @endparblock
590
591 @returns
592 New argument parsing iterator, or \c NULL on memory error.
593
594 @pre
595 \p argc is greater than 0.
596 @pre
597 \p argv is not \c NULL.
598 @pre
599 The first \p argc elements of \p argv are not \c NULL.
600 @pre
601 \p descrs is not \c NULL.
602
603 @sa
604 argpar_iter_destroy() -- Destroys an argument parsing iterator.
605 */
606 /// @cond hidden_macro
607 ARGPAR_HIDDEN
608 /// @endcond
609 struct argpar_iter *argpar_iter_create(unsigned int argc,
610 const char * const *argv,
611 const struct argpar_opt_descr *descrs);
612
613 /*!
614 @brief
615 Destroys the argument parsing iterator \p iter.
616
617 @param[in] iter
618 Argument parsing iterator to destroy (may be \c NULL).
619
620 @sa
621 argpar_iter_create() -- Creates an argument parsing iterator.
622 */
623 /// @cond hidden_macro
624 ARGPAR_HIDDEN
625 /// @endcond
626 void argpar_iter_destroy(struct argpar_iter *iter);
627
628 /*!
629 @brief
630 Return type of argpar_iter_next().
631
632 Error status enumerators have a negative value.
633 */
634 enum argpar_iter_next_status {
635 /// Success
636 ARGPAR_ITER_NEXT_STATUS_OK,
637
638 /// End of iteration (no more original arguments to parse)
639 ARGPAR_ITER_NEXT_STATUS_END,
640
641 /// Parsing error
642 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
643
644 /// Memory error
645 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
646 };
647
648 /*!
649 @brief
650 Sets \p *item to the next item of the argument parsing iterator
651 \p iter and advances \p iter.
652
653 If there are no more original arguments to parse, this function returns
654 #ARGPAR_ITER_NEXT_STATUS_END.
655
656 @param[in] iter
657 Argument parsing iterator from which to get the next parsing item.
658 @param[out] item
659 @parblock
660 On success, \p *item is the next parsing item of \p iter.
661
662 Destroy \p *item with argpar_item_destroy().
663 @endparblock
664 @param[out] error
665 @parblock
666 When this function returns #ARGPAR_ITER_NEXT_STATUS_ERROR,
667 if this parameter is not \c NULL, \p *error contains details about
668 the error.
669
670 Destroy \p *error with argpar_error_destroy().
671 @endparblock
672
673 @returns
674 Status code.
675
676 @pre
677 \p iter is not \c NULL.
678 @pre
679 \p item is not \c NULL.
680 */
681 /// @cond hidden_macro
682 ARGPAR_HIDDEN
683 /// @endcond
684 enum argpar_iter_next_status argpar_iter_next(
685 struct argpar_iter *iter, const struct argpar_item **item,
686 const struct argpar_error **error);
687
688 /*
689 * Returns the number of ingested elements from `argv`, as passed to
690 * argpar_iter_create() to create `*iter`, that were required to produce
691 * the previously returned items.
692 */
693
694 /*!
695 @brief
696 Returns the number of ingested original arguments (in
697 \p argv, as passed to argpar_iter_create() to create \p iter) that
698 the parser ingested to produce the \em previous parsing items.
699
700 @param[in] iter
701 Argument parsing iterator of which to get the number of ingested
702 original arguments.
703
704 @returns
705 Number of original arguments which \p iter ingested.
706
707 @pre
708 \p iter is not \c NULL.
709 */
710 /// @cond hidden_macro
711 ARGPAR_HIDDEN
712 /// @endcond
713 unsigned int argpar_iter_ingested_orig_args(const struct argpar_iter *iter);
714
715 /// @}
716
717 /// @}
718
719 #if defined(__cplusplus)
720 }
721 #endif
722
723 #endif /* ARGPAR_ARGPAR_H */
This page took 0.067002 seconds and 4 git commands to generate.