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