Encode error type in argpar_error
[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 argpar_item_type(). Each item type has its set of dedicated functions
87 (\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes).
88
89 argpar_iter_next() produces the items in the same order that it parses
90 original arguments, including non-option arguments. This means, for
91 example, that for:
92
93 @code{.unparsed}
94 --hello --count=23 /path/to/file -ab --type file -- magie
95 @endcode
96
97 argpar_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 */
108
109 /*
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".
112 *
113 * On Windows, symbols are local unless explicitly exported; see
114 * <https://gcc.gnu.org/wiki/Visibility>.
115 */
116 #if defined(_WIN32) || defined(__CYGWIN__)
117 # define ARGPAR_HIDDEN
118 #else
119 # define ARGPAR_HIDDEN __attribute__((visibility("hidden")))
120 #endif
121
122 struct argpar_opt_descr;
123
124 /*!
125 @name Item API
126 @{
127 */
128
129 /*!
130 @brief
131 Type of a parsing item, as returned by argpar_item_type().
132 */
133 enum argpar_item_type {
134 /// Option
135 ARGPAR_ITEM_TYPE_OPT,
136
137 /// Non-option
138 ARGPAR_ITEM_TYPE_NON_OPT,
139 };
140
141 /*!
142 @struct argpar_item
143
144 @brief
145 Opaque parsing item type
146
147 argpar_iter_next() sets a pointer to such a type.
148 */
149 struct argpar_item;
150
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
165 ARGPAR_HIDDEN
166 /// @endcond
167 enum argpar_item_type argpar_item_type(const struct argpar_item *item);
168
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
185 ARGPAR_HIDDEN
186 /// @endcond
187 const struct argpar_opt_descr *argpar_item_opt_descr(
188 const struct argpar_item *item);
189
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
207 ARGPAR_HIDDEN
208 /// @endcond
209 const char *argpar_item_opt_arg(const struct argpar_item *item);
210
211 /*!
212 @brief
213 Returns the complete original argument, pointing to one of the
214 entries of the original arguments (in \p argv, as passed to
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
230 ARGPAR_HIDDEN
231 /// @endcond
232 const char *argpar_item_non_opt_arg(const struct argpar_item *item);
233
234 /*!
235 @brief
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.
239
240 For example, with the following command line (all options have no
241 argument):
242
243 @code{.unparsed}
244 -f -m meow --jus mix --kilo
245 @endcode
246
247 The original argument index of \c meow is&nbsp;2 while the original
248 argument 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
266 ARGPAR_HIDDEN
267 /// @endcond
268 unsigned int argpar_item_non_opt_orig_index(const struct argpar_item *item);
269
270 /*!
271 @brief
272 Returns the index, within the parsed non-option parsing items, of
273 the non-option parsing item \p item.
274
275 For example, with the following command line (all options have no
276 argument):
277
278 @code{.unparsed}
279 -f -m meow --jus mix --kilo
280 @endcode
281
282 The non-option index of \c meow is&nbsp;0 while the original
283 argument 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
301 ARGPAR_HIDDEN
302 /// @endcond
303 unsigned int argpar_item_non_opt_non_opt_index(const struct argpar_item *item);
304
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
313 ARGPAR_HIDDEN
314 /// @endcond
315 void argpar_item_destroy(const struct argpar_item *item);
316
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
336 /*!
337 @name Error API
338 @{
339 */
340
341 enum argpar_error_type {
342 /// Unknown option error
343 ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
344
345 /// Missing option argument error
346 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
347
348 /// Unexpected option argument error
349 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
350 };
351
352 /*!
353 @struct argpar_error
354
355 @brief
356 Opaque parsing error type
357 */
358 struct argpar_error;
359
360 ARGPAR_HIDDEN
361 enum argpar_error_type argpar_error_type(
362 const struct argpar_error *error);
363
364 /*!
365 @brief
366 Returns the index of the original argument (in \p argv, as passed to
367 argpar_iter_create()) for which the parsing error described by
368 \p error occurred.
369
370 @param[in] error
371 Parsing error of which to get the original argument index.
372
373 @returns
374 Original argument index of \p error.
375
376 @pre
377 \p error is not \c NULL.
378 */
379 /// @cond hidden_macro
380 ARGPAR_HIDDEN
381 /// @endcond
382 unsigned int argpar_error_orig_index(const struct argpar_error *error);
383
384 /*!
385 @brief
386 Returns the name of the unknown option for which the parsing error
387 described by \p error occurred.
388
389 The returned name includes any <code>-</code> or <code>\--</code>
390 prefix.
391
392 With the long option with argument form, for example
393 <code>\--mireille=deyglun</code>, this function only returns the name
394 part (<code>\--mireille</code> in the last example).
395
396 You may only call this function if the call to argpar_iter_next() which
397 set \p error returned #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT.
398
399 @param[in] error
400 Parsing error of which to get the name of the unknown option.
401
402 @returns
403 Name of the unknown option of \p error.
404
405 @pre
406 \p error is not \c NULL.
407 @pre
408 The call to argpar_iter_next() which set \p error returned
409 #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT.
410 */
411 /// @cond hidden_macro
412 ARGPAR_HIDDEN
413 /// @endcond
414 const char *argpar_error_unknown_opt_name(const struct argpar_error *error);
415
416 /*!
417 @brief
418 Returns the descriptor of the option for which the parsing error
419 described by \p error occurred.
420
421 You may only call this function if the call to argpar_iter_next() which
422 set \p error returned #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG or
423 #ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG.
424
425 @param[in] error
426 Parsing error of which to get the option descriptor.
427 @param[out] is_short
428 @parblock
429 If not \c NULL, this function sets \p *is_short to:
430
431 - \c true if the option for which \p error occurred is a short
432 option.
433
434 - \c false if the option for which \p error occurred is a long
435 option.
436 @endparblock
437
438 @returns
439 Descriptor of the option of \p error.
440
441 @pre
442 \p error is not \c NULL.
443 @pre
444 The call to argpar_iter_next() which set \p error returned
445 #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG or
446 #ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG.
447 */
448 /// @cond hidden_macro
449 ARGPAR_HIDDEN
450 /// @endcond
451 const struct argpar_opt_descr *argpar_error_opt_descr(
452 const struct argpar_error *error, bool *is_short);
453
454 /*!
455 @brief
456 Destroys the parsing error \p error.
457
458 @param[in] error
459 Parsing error to destroy (may be \c NULL).
460 */
461 /// @cond hidden_macro
462 ARGPAR_HIDDEN
463 /// @endcond
464 void argpar_error_destroy(const struct argpar_error *error);
465
466 /// @}
467
468 /*!
469 @name Iterator API
470 @{
471 */
472
473 /*!
474 @brief
475 Option descriptor
476
477 argpar_iter_create() accepts an array of instances of such a type,
478 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
479
480 The typical usage is, for example:
481
482 @code
483 const struct argpar_opt_descr descrs[] = {
484 { 0, 'd', NULL, false },
485 { 1, '\0', "squeeze", true },
486 { 2, 'm', "meow", true },
487 ARGPAR_OPT_DESCR_SENTINEL,
488 };
489 @endcode
490 */
491 struct argpar_opt_descr {
492 /// Numeric ID, to uniquely identify this descriptor
493 const int id;
494
495 /// Short option character, or <code>'\0'</code>
496 const char short_name;
497
498 /// Long option name (without the <code>\--</code> prefix), or \c NULL
499 const char * const long_name;
500
501 /// \c true if this option has an argument
502 const bool with_arg;
503 };
504
505 /*!
506 @brief
507 Sentinel for an option descriptor array
508
509 The typical usage is, for example:
510
511 @code
512 const struct argpar_opt_descr descrs[] = {
513 { 0, 'd', NULL, false },
514 { 1, '\0', "squeeze", true },
515 { 2, 'm', "meow", true },
516 ARGPAR_OPT_DESCR_SENTINEL,
517 };
518 @endcode
519 */
520 #define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false }
521
522 /*!
523 @struct argpar_iter
524
525 @brief
526 Opaque argpar iterator type
527
528 argpar_iter_create() returns a pointer to such a type.
529 */
530 struct argpar_iter;
531
532 /*!
533 @brief
534 Creates and returns an argument parsing iterator to parse the
535 original arguments \p argv of which the count is \p argc using the
536 option descriptors \p descrs.
537
538 This function initializes the returned structure, but doesn't actually
539 start parsing the arguments.
540
541 argpar considers \em all the elements of \p argv, including the first
542 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
543 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
544 receives, or ignore the parsing item of the first call to
545 argpar_iter_next().
546
547 \p *argv and \p *descrs must \em not change for all of:
548
549 - The lifetime of the returned iterator (until you call
550 argpar_iter_destroy()).
551
552 - The lifetime of any parsing item (until you call
553 argpar_item_destroy()) which argpar_iter_next() creates from the
554 returned iterator.
555
556 - The lifetime of any parsing error (until you call
557 argpar_error_destroy()) which argpar_iter_next() creates from the
558 returned iterator.
559
560 @param[in] argc
561 Number of original arguments to parse in \p argv.
562 @param[in] argv
563 Original arguments to parse, of which the count is \p argc.
564 @param[in] descrs
565 @parblock
566 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
567
568 May contain duplicate entries.
569 @endparblock
570
571 @returns
572 New argument parsing iterator, or \c NULL on memory error.
573
574 @pre
575 \p argc is greater than 0.
576 @pre
577 \p argv is not \c NULL.
578 @pre
579 The first \p argc elements of \p argv are not \c NULL.
580 @pre
581 \p descrs is not \c NULL.
582
583 @sa
584 argpar_iter_destroy() -- Destroys an argument parsing iterator.
585 */
586 /// @cond hidden_macro
587 ARGPAR_HIDDEN
588 /// @endcond
589 struct argpar_iter *argpar_iter_create(unsigned int argc,
590 const char * const *argv,
591 const struct argpar_opt_descr *descrs);
592
593 /*!
594 @brief
595 Destroys the argument parsing iterator \p iter.
596
597 @param[in] iter
598 Argument parsing iterator to destroy (may be \c NULL).
599
600 @sa
601 argpar_iter_create() -- Creates an argument parsing iterator.
602 */
603 /// @cond hidden_macro
604 ARGPAR_HIDDEN
605 /// @endcond
606 void argpar_iter_destroy(struct argpar_iter *iter);
607
608 /*!
609 @brief
610 Return type of argpar_iter_next().
611
612 Error status enumerators have a negative value.
613 */
614 enum argpar_iter_next_status {
615 /// Success
616 ARGPAR_ITER_NEXT_STATUS_OK,
617
618 /// End of iteration (no more original arguments to parse)
619 ARGPAR_ITER_NEXT_STATUS_END,
620
621 /// Argument error
622 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
623
624 /// Memory error
625 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
626 };
627
628 /*!
629 @brief
630 Sets \p *item to the next item of the argument parsing iterator
631 \p iter and advances \p iter.
632
633 If there are no more original arguments to parse, this function returns
634 #ARGPAR_ITER_NEXT_STATUS_END.
635
636 @param[in] iter
637 Argument parsing iterator from which to get the next parsing item.
638 @param[out] item
639 @parblock
640 On success, \p *item is the next parsing item of \p iter.
641
642 Destroy \p *item with argpar_item_destroy().
643 @endparblock
644 @param[out] error
645 @parblock
646 When this function returns
647 #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
648 #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG, or
649 #ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG, if this parameter
650 is not \c NULL,
651 \p *error contains details about the error.
652
653 Destroy \p *error with argpar_error_destroy().
654 @endparblock
655
656 @returns
657 Status code.
658
659 @pre
660 \p iter is not \c NULL.
661 @pre
662 \p item is not \c NULL.
663 */
664 /// @cond hidden_macro
665 ARGPAR_HIDDEN
666 /// @endcond
667 enum argpar_iter_next_status argpar_iter_next(
668 struct argpar_iter *iter, const struct argpar_item **item,
669 const struct argpar_error **error);
670
671 /*
672 * Returns the number of ingested elements from `argv`, as passed to
673 * argpar_iter_create() to create `*iter`, that were required to produce
674 * the previously returned items.
675 */
676
677 /*!
678 @brief
679 Returns the number of ingested original arguments (in
680 \p argv, as passed to argpar_iter_create() to create \p iter) that
681 the parser ingested to produce the \em previous parsing items.
682
683 @param[in] iter
684 Argument parsing iterator of which to get the number of ingested
685 original arguments.
686
687 @returns
688 Number of original arguments which \p iter ingested.
689
690 @pre
691 \p iter is not \c NULL.
692 */
693 /// @cond hidden_macro
694 ARGPAR_HIDDEN
695 /// @endcond
696 unsigned int argpar_iter_ingested_orig_args(const struct argpar_iter *iter);
697
698 /// @}
699
700 /// @}
701
702 #endif /* ARGPAR_ARGPAR_H */
This page took 0.069379 seconds and 4 git commands to generate.