From 9e2c879bb10c35749cab090dbc89161698caf4e5 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 1 Jun 2021 14:37:58 -0400 Subject: [PATCH] argpar.h: Doxygenize This patch documents the argpar API with Doxygen, reusing most of the existing unformatted documentation, and adding more details. The configuration script generates `Doxyfile` from `Doxyfile.in` to include the version number of the project. If you have the Doxygen tool, you can then generate the HTML documentation as such: $ doxygen The output is `api-doc/html/index.html`. Signed-off-by: Philippe Proulx Change-Id: I73e5edf4adb5e0d4af8ecd08417362b9df4d53db --- .gitignore | 1 + Doxyfile.in | 17 ++ argpar/argpar.h | 661 ++++++++++++++++++++++++++++++++++-------------- configure.ac | 1 + 4 files changed, 495 insertions(+), 185 deletions(-) create mode 100644 Doxyfile.in diff --git a/.gitignore b/.gitignore index 21bb97e..ee42aaa 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ test-driver Makefile Makefile.in tests/test_argpar +Doxyfile diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 0000000..20133bd --- /dev/null +++ b/Doxyfile.in @@ -0,0 +1,17 @@ +PROJECT_NAME = argpar +PROJECT_NUMBER = @PACKAGE_VERSION@ +PROJECT_BRIEF = "Position-aware command-line argument parsing library" +OUTPUT_DIRECTORY = api-doc +OPTIMIZE_OUTPUT_FOR_C = YES +HIDE_SCOPE_NAMES = YES +INPUT = argpar +FILE_PATTERNS = *.h +HTML_COLORSTYLE_HUE = 336 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 100 +GENERATE_LATEX = NO +CLASS_DIAGRAMS = NO +HIDE_UNDOC_MEMBERS = YES +MULTILINE_CPP_IS_BRIEF = YES +ALWAYS_DETAILED_SEC = YES +MAX_INITIALIZER_LINES = 0 diff --git a/argpar/argpar.h b/argpar/argpar.h index 89b96e6..22ecaab 100644 --- a/argpar/argpar.h +++ b/argpar/argpar.h @@ -10,82 +10,101 @@ #include -/* - * argpar is a library which provides facilities for command-line - * argument parsing. - * - * Create a parsing iterator with argpar_iter_create(), then - * repeatedly call argpar_iter_next() to access the parsing results, - * until one of: - * - * * There are no more arguments. - * - * * The argument parser encounters an error (for example, an unknown - * option). - * - * * You need to stop. - * - * The argpar parser parses the original arguments `argv` of which the - * count is `argc` using the sentinel-terminated (use - * `ARGPAR_OPT_DESCR_SENTINEL`) option descriptor array `descrs`. - * - * argpar considers ALL the elements of `argv`, including the first one, - * so that you would typically pass `argc - 1` and `&argv[1]` from what - * main() receives. - * - * The argpar parser supports: - * - * * Short options without an argument, possibly tied together: - * - * -f -auf -n - * - * * Short options with argument: - * - * -b 45 -f/mein/file -xyzhello - * - * * Long options without an argument: - * - * --five-guys --burger-king --pizza-hut --subway - * - * * Long options with arguments: - * - * --security enable --time=18.56 - * - * * Non-option arguments (anything else). - * - * The argpar parser parses `-` and `--` as non-option arguments. A - * non-option argument cannot have the form of an option, for example if - * you need to pass the exact relative path `--component`. In that case, - * you would need to pass `./--component`. There's no generic way to - * escape `-` as of this version. - * - * argpar_iter_create() accepts duplicate options in `descrs` (it - * produces one item for each instance). - * - * A returned parsing item has the type `const struct argpar_item *`. - * Get the type (option or non-option) of an item with - * argpar_item_type(). Each item type has its set of dedicated methods - * (`argpar_item_opt_` and `argpar_item_non_opt_` prefixes). - * - * argpar_iter_next() produces the items in the same order that the - * original arguments were parsed, including non-option arguments. This - * means, for example, that for: - * - * --hello --count=23 /path/to/file -ab --type file magie - * - * argpar_iter_next() produces the following items, in this order: - * - * 1. Option item (`--hello`). - * 2. Option item (`--count` with argument `23`). - * 3. Non-option item (`/path/to/file`). - * 4. Option item (`-a`). - * 5. Option item (`-b`). - * 6. Option item (`--type` with argument `file`). - * 7. Non-option item (`magie`). - */ +/*! +@mainpage -/* Sentinel for an option descriptor array */ -#define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false } +See the \ref api module. + +@addtogroup api argpar API +@{ + +argpar is a library which provides an iterator-based API to parse +command-line arguments. + +The argpar parser supports: + +
    +
  • + Short options without an argument, possibly tied together: + + @code{.unparsed} + -f -auf -n + @endcode + +
  • + Short options with arguments: + + @code{.unparsed} + -b 45 -f/mein/file -xyzhello + @endcode + +
  • + Long options without an argument: + + @code{.unparsed} + --five-guys --burger-king --pizza-hut --subway + @endcode + +
  • + Long options with arguments (two original arguments or a single + one with a = character): + + @code{.unparsed} + --security enable --time=18.56 + @endcode + +
  • + Non-option arguments (anything else, including + - and \--). + + A non-option argument cannot have the form of an option, for example + if you need to pass the exact relative path + \--component. In that case, you would need to pass + ./\--component. There's no generic way to escape + - as of this version. +
+ +Create a parsing iterator with argpar_iter_create(), then repeatedly +call argpar_iter_next() to access the parsing results (items), until one +of: + +- There are no more arguments. + +- The argument parser encounters an error (for example, an unknown + option). + +- You need to stop. + +argpar_iter_create() accepts duplicate option descriptors in +\p descrs (argpar_iter_next() produces one item for each +instance). + +A parsing item (the result of argpar_iter_next()) has the type +#argpar_item. + +Get the type (option or non-option) of an item with +argpar_item_type(). Each item type has its set of dedicated functions +(\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes). + +argpar_iter_next() produces the items in the same order that it parses +original arguments, including non-option arguments. This means, for +example, that for: + +@code{.unparsed} +--hello --count=23 /path/to/file -ab --type file -- magie +@endcode + +argpar_iter_next() produces the following items, in this order: + +-# Option item (\--hello). +-# Option item (\--count with argument 23). +-# Non-option item (/path/to/file). +-# Option item (-a). +-# Option item (-b). +-# Option item (\--type with argument file). +-# Non-option item (\--). +-# Non-option item (magie). +*/ /* * If argpar is used in some shared library, we don't want said library @@ -100,156 +119,415 @@ # define ARGPAR_HIDDEN __attribute__((visibility("hidden"))) #endif -/* Forward-declaration for the opaque argpar iterator type */ -struct argpar_iter; - -/* Option descriptor */ -struct argpar_opt_descr { - /* Numeric ID for this option */ - const int id; - - /* Short option character, or `\0` */ - const char short_name; - - /* Long option name (without the `--` prefix), or `NULL` */ - const char * const long_name; +struct argpar_opt_descr; - /* True if this option has an argument */ - const bool with_arg; -}; +/*! +@name Item API +@{ +*/ -/* Item type */ +/*! +@brief + Type of a parsing item, as returned by argpar_item_type(). +*/ enum argpar_item_type { - /* Option */ + /// Option ARGPAR_ITEM_TYPE_OPT, - /* Non-option */ + /// Non-option ARGPAR_ITEM_TYPE_NON_OPT, }; -/* Forward-declaration for the opaque argpar parsing item type */ +/*! +@struct argpar_item + +@brief + Opaque parsing item type + +argpar_iter_next() sets a pointer to such a type. +*/ struct argpar_item; -/* - * Returns the type of the parsing item `item`. - */ +/*! +@brief + Returns the type of the parsing item \p item. + +@param[in] item + Parsing item of which to get the type. + +@returns + Type of \p item. + +@pre + \p item is not \c NULL. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond enum argpar_item_type argpar_item_type(const struct argpar_item *item); -/* - * Returns the option descriptor of the option parsing item `item`. - */ +/*! +@brief + Returns the option descriptor of the option parsing item \p item. + +@param[in] item + Option parsing item of which to get the option descriptor. + +@returns + Option descriptor of \p item. + +@pre + \p item is not \c NULL. +@pre + \p item has the type #ARGPAR_ITEM_TYPE_OPT. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond const struct argpar_opt_descr *argpar_item_opt_descr( const struct argpar_item *item); -/* - * Returns the argument of the option parsing item `item`, or `NULL` if - * none. - */ +/*! +@brief + Returns the argument of the option parsing item \p item, or + \c NULL if none. + +@param[in] item + Option parsing item of which to get the argument. + +@returns + Argument of \p item, or \c NULL if none. + +@pre + \p item is not \c NULL. +@pre + \p item has the type #ARGPAR_ITEM_TYPE_OPT. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond const char *argpar_item_opt_arg(const struct argpar_item *item); -/* - * Returns the complete argument, pointing to one of the entries of the - * original arguments (`argv`), of the non-option parsing item `item`. - */ +/*! +@brief + Returns the complete original argument, pointing to one of the + entries of the original arguments (\p argv as passed to + argpar_iter_create()), of the non-option parsing item \p item. + +@param[in] item + Non-option parsing item of which to get the complete original + argument. + +@returns + Complete original argument of \p item. + +@pre + \p item is not \c NULL. +@pre + \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond const char *argpar_item_non_opt_arg(const struct argpar_item *item); -/* - * Returns the original index, within ALL the original arguments - * (`argv`), of the non-option parsing item `item`. - */ +/*! +@brief + Returns the index, within \em all the original arguments (\p argv + as passed to argpar_iter_create()), of the non-option parsing item + \p item. + +For example, with the following command line (all options have no +argument): + +@code{.unparsed} +-f -m meow --jus mix --kilo +@endcode + +The original argument index of \c meow is 2 while the original +argument index of \c mix is 4. + +@param[in] item + Non-option parsing item of which to get the original argument index. + +@returns + Original argument index of \p item. + +@pre + \p item is not \c NULL. +@pre + \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT. + +@sa + argpar_item_non_opt_non_opt_index() -- Returns the non-option index + of a non-option parsing item. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond unsigned int argpar_item_non_opt_orig_index(const struct argpar_item *item); -/* - * Returns the index, within the non-option arguments, of the non-option - * parsing item `item`. - */ +/*! +@brief + Returns the index, within the parsed non-option parsing items, of + the non-option parsing item \p item. + +For example, with the following command line (all options have no +argument): + +@code{.unparsed} +-f -m meow --jus mix --kilo +@endcode + +The non-option index of \c meow is 0 while the original +argument index of \c mix is 1. + +@param[in] item + Non-option parsing item of which to get the non-option index. + +@returns + Non-option index of \p item. + +@pre + \p item is not \c NULL. +@pre + \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT. + +@sa + argpar_item_non_opt_orig_index() -- Returns the original argument + index of a non-option parsing item. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond unsigned int argpar_item_non_opt_non_opt_index(const struct argpar_item *item); -/* - * Destroys `item`, as created by argpar_iter_next(). - */ +/*! +@brief + Destroys the parsing item \p item. + +@param[in] item + Parsing item to destroy (may be \c NULL). +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond void argpar_item_destroy(const struct argpar_item *item); -/* - * Creates an argument parsing iterator. - * - * This function initializes the returned structure, but doesn't - * actually start parsing the arguments. - * - * `*argv` and `*descrs` must NOT change for the lifetime of the - * returned iterator (until you call argpar_iter_destroy()) and for the - * lifetime of any parsing item (until you call argpar_item_destroy()) - * argpar_iter_next() creates for the returned iterator. - * - * Call argpar_iter_next() with the returned iterator to obtain the next - * parsing result (item). - */ +/*! +@def ARGPAR_ITEM_DESTROY_AND_RESET(_item) + +@brief + Calls argpar_item_destroy() with \p _item, and then sets \p _item + to \c NULL. + +@param[in] _item + Item to destroy and variable to reset + (const struct argpar_item * type). +*/ +#define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \ + { \ + argpar_item_destroy(_item); \ + _item = NULL; \ + } + +/// @} + +/*! +@name Iterator API +@{ +*/ + +/*! +@brief + Option descriptor + +argpar_iter_create() accepts an array of instances of such a type, +terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter. + +The typical usage is, for example: + +@code +const struct argpar_opt_descr descrs[] = { + { 0, 'd', NULL, false }, + { 1, '\0', "squeeze", true }, + { 2, 'm', "meow", true }, + ARGPAR_OPT_DESCR_SENTINEL, +}; +@endcode +*/ +struct argpar_opt_descr { + /// Numeric ID, to uniquely identify this descriptor + const int id; + + /// Short option character, or '\0' + const char short_name; + + /// Long option name (without the \-- prefix), or \c NULL + const char * const long_name; + + /// \c true if this option has an argument + const bool with_arg; +}; + +/*! +@brief + Sentinel for an option descriptor array + +The typical usage is, for example: + +@code +const struct argpar_opt_descr descrs[] = { + { 0, 'd', NULL, false }, + { 1, '\0', "squeeze", true }, + { 2, 'm', "meow", true }, + ARGPAR_OPT_DESCR_SENTINEL, +}; +@endcode +*/ +#define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false } + +/*! +@struct argpar_iter + +@brief + Opaque argpar iterator type + +argpar_iter_create() returns a pointer to such a type. +*/ +struct argpar_iter; + +/*! +@brief + Creates and returns an argument parsing iterator to parse the + original arguments \p argv of which the count is \p argc using the + option descriptors \p descrs. + +This function initializes the returned structure, but doesn't actually +start parsing the arguments. + +argpar considers \em all the elements of \p argv, including the first +one, so that you would typically pass (argc - 1) as \p argc +and \&argv[1] as \p argv from what main() +receives, or ignore the parsing item of the first call to +argpar_iter_next(). + +\p *argv and \p *descrs must \em not change for the lifetime of the +returned iterator (until you call argpar_iter_destroy()) and for the +lifetime of any parsing item (until you call argpar_item_destroy()) +which argpar_iter_next() creates from the returned iterator. + +@param[in] argc + Number of original arguments to parse in \p argv. +@param[in] argv + Original arguments to parse, of which the count is \p argc. +@param[in] descrs + @parblock + Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL. + + May contain duplicate entries. + @endparblock + +@returns + New argument parsing iterator, or \c NULL on memory error. + +@pre + \p argc is greater than 0. +@pre + \p argv is not \c NULL. +@pre + The first \p argc elements of \p argv are not \c NULL. +@pre + \p descrs is not \c NULL. + +@sa + argpar_iter_destroy() -- Destroys an argument parsing iterator. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond struct argpar_iter *argpar_iter_create(unsigned int argc, const char * const *argv, const struct argpar_opt_descr *descrs); -/* - * Destroys `iter`, as returned by argpar_iter_create(). - */ +/*! +@brief + Destroys the argument parsing iterator \p iter. + +@param[in] iter + Argument parsing iterator to destroy (may be \c NULL). + +@sa + argpar_iter_create() -- Creates an argument parsing iterator. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond void argpar_iter_destroy(struct argpar_iter *iter); -/* - * Return type of argpar_iter_next(). - */ +/*! +@brief + Return type of argpar_iter_next(). +*/ enum argpar_iter_next_status { + /// Success ARGPAR_ITER_NEXT_STATUS_OK, + + /// End of iteration (no more original arguments to parse) ARGPAR_ITER_NEXT_STATUS_END, + + /// Unknown option error ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT, + + /// Missing option argument error ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG, + + /// Unexpected option argument error ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG, + + /// Memory error ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY, }; -/* - * Parses and returns the next item from `iter`. - * - * On success, this function: - * - * * Sets `*item` to a parsing item which describes the next option - * or non-option argument. - * - * Destroy `*item` with argpar_item_destroy(). - * - * * Returns `ARGPAR_ITER_NEXT_STATUS_OK`. - * - * If there are no more items to return, this function returns - * `ARGPAR_ITER_NEXT_STATUS_END`. - * - * On failure, this function: - * - * * Returns one of: - * - * `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT`: - * Unknown option (not found in `descrs` as passed to - * argpar_iter_create() to create `iter`). - * - * `ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG`: - * Missing option argument. - * - * `ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG`: - * Unexpected option argument. - * - * `ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY`: - * Memory error. - * - * * Except for the `ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY` status, - * sets `*error`, if not `NULL`, to a descriptive error string. - * Free `*error` with free(). - */ +/*! +@brief + Sets \p *item to the next item of the argument parsing iterator + \p iter and advances \p iter. + +If there are no more original arguments to parse, this function returns +#ARGPAR_ITER_NEXT_STATUS_END. + +@param[in] iter + Argument parsing iterator from which to get the next parsing item. +@param[out] item + @parblock + On success, \p *item is the next parsing item of \p iter. + + Destroy \p *item with argpar_item_destroy(). + @endparblock +@param[out] error + @parblock + When this function returns + #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT, + #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG, or + #ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG, if this parameter + is not \c NULL, + \p *error is a string which explains the parsing error in English. + + Free \p *error with free(). + @endparblock + +@returns + Status code. + +@pre + \p iter is not \c NULL. +@pre + \p item is not \c NULL. +*/ +/// @cond hidden_macro +ARGPAR_HIDDEN +/// @endcond enum argpar_iter_next_status argpar_iter_next( struct argpar_iter *iter, const struct argpar_item **item, char **error); @@ -259,17 +537,30 @@ enum argpar_iter_next_status argpar_iter_next( * argpar_iter_create() to create `*iter`, that were required to produce * the previously returned items. */ + +/*! +@brief + Returns the number of ingested original arguments (in + \p argv as passed to argpar_iter_create() to create \p iter) that + the parser ingested to produce the \em previous parsing items. + +@param[in] iter + Argument parsing iterator of which to get the number of ingested + original arguments. + +@returns + Number of original arguments which \p iter ingested. + +@pre + \p iter is not \c NULL. +*/ +/// @cond hidden_macro ARGPAR_HIDDEN +/// @endcond unsigned int argpar_iter_ingested_orig_args(const struct argpar_iter *iter); -/* - * Destroys `_item` (`const struct argpar_item *`) and sets it to - * `NULL`. - */ -#define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \ - { \ - argpar_item_destroy(_item); \ - _item = NULL; \ - } +/// @} + +/// @} #endif /* ARGPAR_ARGPAR_H */ diff --git a/configure.ac b/configure.ac index 8464b8c..0aa3829 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,7 @@ AM_CFLAGS="${AM_CFLAGS} ${WARN_CFLAGS}" AC_SUBST(AM_CFLAGS) AC_CONFIG_FILES([ + Doxyfile Makefile argpar/Makefile tests/Makefile -- 2.34.1