~brenns10/sc-argparse

8cc1d555fd95fee49dacf478384b4637f7138fdc — Stephen Brennan 4 months ago 24abec4 master
docs: Add api documentation
7 files changed, 131 insertions(+), 49 deletions(-)

M README.md
A doc/api.rst
R src/example.c => doc/example.c
M doc/index.rst
M doc/meson.build
M include/sc-argparse.h
M meson.build
M README.md => README.md +1 -1
@@ 1,7 1,7 @@
sc-argparse
===========

This is a simple argument parsing library. See `src/example.c` for an example of
This is a simple argument parsing library. See `doc/example.c` for an example of
using it. The library is somewhat limited as of now.

Development

A doc/api.rst => doc/api.rst +38 -0
@@ 0,0 1,38 @@
Argument Parsing API
====================

Overview
--------

This library loosely models its API on the Python argparse library. Ahead of
time, the programmer prepares an array of structs, each one specifying an
argument to the program. The sc_argparse() function examines the command-line
args and fills out the specification, validating any assumptions and returning
any errors. After this single function call, the programmer may retrieve all
argument values directly from the specification array.

A simple example is shown here:

.. literalinclude:: example.c
   :language: c
   :linenos:

API
---

Argument Specifications
^^^^^^^^^^^^^^^^^^^^^^^

.. doxygendefine:: SC_ARG_DEF_STRING
.. doxygendefine:: SC_ARG_STRING
.. doxygendefine:: SC_ARG_DEF_INT
.. doxygendefine:: SC_ARG_INT
.. doxygendefine:: SC_ARG_COUNT
.. doxygendefine:: SC_ARG_END
.. doxygenstruct:: sc_arg
.. doxygenenum:: sc_arg_type

Functions
^^^^^^^^^

.. doxygenfunction:: sc_argparse

R src/example.c => doc/example.c +0 -0
M doc/index.rst => doc/index.rst +11 -3
@@ 1,14 1,22 @@
Welcome to sc-template documentation!
Welcome to sc-argparse documentation!
=====================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

sc-template
   api

sc-argparse
-----------

You should use this as a starting point for your documentation.
sc-argparse is a tiny library that aims to make a very simple but generalizable
argument parsing system. While the Unix ``getopt(3)`` is standard, it does not
support ``--long flags``. The non-standard extension ``getopt_long(3)`` supports
both short and long flags, but is a GNU extension. For both functions, the usage
is a bit confusing, requiring multiple function calls and magic state being held
within the function.


Indices and tables
==================

M doc/meson.build => doc/meson.build +2 -0
@@ 74,6 74,8 @@ doxygen_target = custom_target(
# meson.build file
sphinx_files = [
	'index.rst',
	'api.rst',
	'example.c',
]
foreach file : sphinx_files
	configure_file(input: file, output: file, copy: true)

M include/sc-argparse.h => include/sc-argparse.h +72 -44
@@ 1,5 1,5 @@
/**
 * sc-argparse.h: simple argument parsing library
 * @file sc-argparse.h  simple argument parsing library
 *
 * This library aims to make a very simple but generalizable argument parsing
 * system. While the Unix getopt(3) is simple, it does not support --long


@@ 10,9 10,9 @@
 *
 * This library loosely models its API on the Python argparse library. Ahead of
 * time, the programmer prepares an array of structs, each one specifying an
 * argument to the program. The `sc_argparse()` function examines the
 * command-line args and fills out the specification, validating any assumptions
 * and returning any errors. After this single function call, the programmer may
 * argument to the program. The sc_argparse() function examines the command-line
 * args and fills out the specification, validating any assumptions and
 * returning any errors. After this single function call, the programmer may
 * retrieve all argument values directly from the specification array.
 */



@@ 22,33 22,32 @@
#include <stdbool.h>

/**
 * Types of arguments recognized by sc_argparse.
 * @brief Types of arguments recognized by sc_argparse.
 */
enum sc_arg_type {
	/**
	 * A special argument type to signal the end of the argument list. Do
	 * not use this.
	 * @brief A special argument type to signal the end of the argument list.
	 */
	SC_ARG_TYPE_END = 0,
	/**
	 * An argument type which will count the occurrences of the long or
	 * short flag in the command line arguments.
	 * @brief An argument type which will count the occurrences of the long
	 * or short flag in the command line arguments.
	 */
	SC_ARG_TYPE_COUNT,
	/**
	 * An argument which takes a single string value. EG:
	 * --foo=bar, --foo bar, or -f bar.
	 * @brief An argument which takes a single string value. EG:
	 * `--foo=bar`, `--foo bar`, or `-f bar`.
	 *
	 * NOTE: This argument type cannot handle multiple occurrences in the
	 * @note This argument type cannot handle multiple occurrences in the
	 * command line. If this arg appears multiple times, the value reported
	 * will be the last one.
	 */
	SC_ARG_TYPE_STRING,
	/**
	 * An argument which takes an integer. EG:
	 * --foo=1, --foo 1, or -f 1.
	 * @brief An argument which takes an integer. EG:
	 * `--foo=1`, `--foo 1`, or `-f 1`.
	 *
	 * NOTE: This argument type cannot handle multiple occurrences in the
	 * @note This argument type cannot handle multiple occurrences in the
	 * command line. If this arg appears multiple times, the value reported
	 * will be the last one.
	 */


@@ 56,67 55,80 @@ enum sc_arg_type {
};

/**
 * A static descriptor for an argument, which encodes all information about the
 * arg, as well as any output from the argument parsing process.
 * @brief A static descriptor for an argument, which encodes all information
 * about the arg, as well as any output from the argument parsing process.
 *
 * @note This struct should not be populated directly, instead it should be
 * created using macros starting with SC_ARG
 * created using macros starting with `SC_ARG_`
 */
struct sc_arg {
	/**
	 * The "short" flag (e.g. -a) of this argument; a single character.
	 * @brief The "short" flag of this argument; a single character.
	 */
	char flag;
	/**
	 * Set to true when the flag is required to be seen in the args.
	 * @brief Set to true when the flag is required to be seen in the args.
	 */
	bool required;
	/**
	 * The argument type
	 * @brief The argument type
	 */
	enum sc_arg_type type;
	/**
	 * The "long" flag name of this argument, e.g. --foo
	 * @brief The "long" flag name of this argument, e.g. `--foo`.
	 *
	 * This string should include two leading hyphens.
	 */
	char *name;
	/**
	 * A short text describing the purpose of the argument
	 * @brief A short text describing the purpose of the argument
	 */
	char *help;

	/**
	 * (Output by sc_argparse) The value of the argument, if it is a string.
	 * @brief The value of the argument, if it is a string.
	 *
	 * This value is output by sc_argparse(), and need not be initialized.
	 */
	char *val_string;
	/**
	 * (Output by sc_argparse) The value of the argument, if it is a count
	 * or int arg.
	 * @brief The value of the argument, if it is a count or int arg.
	 *
	 * This value is output by sc_argparse(), and need not be initialized.
	 */
	int val_int;
	/**
	 * (Output by sc_argparse) Tracks whether the argument appeared in the
	 * command line.
	 * @brief Tracks whether the argument has appeared in the command line.
	 *
	 * This value is output by sc_argparse(), and need not be initialized.
	 */
	bool seen;
};

/** @brief Parse command line arguments
 *
 * Given a specification of arguments (@a argspec), and the command line
 * argument list (@a argc and @a argv) -- excluding the program name -- parse
 * all arguments and fill out the "output" fields of the argument spec. Return
 * the number of positional arguments which were found. Positional arguments are
 * moved to the beginning of the @a argv array, and their order is the same as
 * they originally appeared.
 *
 * @param argspec An array of sc_arg structures describing arguments
 * @param argc The count of arguments (should not include program name)
 * @param argv Array of arguments (should not include program name)
 * @returns The number of positional arguments (in the array @a argv)
 *
 * Given a specification of arguments (@a argspec), and the command line
 * argument list (@a argc and @a argv) parse all arguments and fill out the
 * "output" fields of the argument spec. Return the number of positional
 * arguments which were found. Positional arguments are moved to the beginning
 * of the @a argv array, and their order is the same as they originally
 * appeared.
 *
 * @warning The argc and argv values ought to skip past the program name. Thus,
 * a typical call would be: `sc_argparse(&argspec, argc - 1, argv + 1)`.
 */
int sc_argparse(struct sc_arg argspec[], int argc, char **argv);

/**
 * @brief Define a string argument with a default value.
 * @param flag a single character flag
 * @param name a string flag name (includes prefixing `--`)
 * @param help short help text describing the argument
 *
 * Define a string argument with a default value. It is not required to appear
 * on the command line.
 */


@@ 124,34 136,50 @@ int sc_argparse(struct sc_arg argspec[], int argc, char **argv);
	((struct sc_arg){ flag, false, SC_ARG_TYPE_STRING, name, help,         \
	                  default_ })
/**
 * Define a string argument without a default value. It is required to appear on
 * the command line.
 * @brief Define a required string argument without a default value.
 * @param flag a single character flag
 * @param name a string flag name (includes prefixing `--`)
 * @param help short help text describing the argument
 */
#define SC_ARG_STRING(flag, name, help)                                        \
	((struct sc_arg){ flag, true, SC_ARG_TYPE_STRING, name, help })

/**
 * Define an integer argument with a default value. It is not required to appear
 * on the command line.
 * @brief Define an integer argument with a default value.
 * @param flag a single character flag
 * @param name a string flag name (includes prefixing `--`)
 * @param default_ the default value (integer)
 * @param help short help text describing the argument
 *
 * The argument is not required to appear on the command line.
 */
#define SC_ARG_DEF_INT(flag, name, default_, help)                             \
	((struct sc_arg){ flag, false, SC_ARG_TYPE_INT, name, help, NULL,      \
	                  default_ })
/**
 * Define an integer argument without a default value. It is required to appear
 * on the command line.
 * @brief Define an integer argument without a default value.
 * @param flag a single character flag
 * @param name a string flag name (includes prefixing `--`)
 * @param help short help text describing the argument
 *
 * This argument is not required to appear on the command line.
 */
#define SC_ARG_INT(flag, name, help)                                           \
	((struct sc_arg){ flag, true, SC_ARG_TYPE_INT, name, help })

/**
 * Define an count argument. It is not required to appear on the command line.
 * @brief Define an count argument.
 * @param flag a single character flag
 * @param name a string flag name (includes prefixing `--`)
 * @param help short help text describing the argument
 *
 * Tthe argument is not required to appear on the command line.
 */
#define SC_ARG_COUNT(flag, name, help)                                         \
	((struct sc_arg){ flag, false, SC_ARG_TYPE_COUNT, name, help })

/**
 * Signals the end of the argument specification.
 * @brief Signals the end of the argument specification.
 */
#define SC_ARG_END() ((struct sc_arg){ 0 })


M meson.build => meson.build +7 -1
@@ 38,7 38,7 @@ pkg.generate(

executable(
  'argument-tester',
  ['src/example.c'],
  ['doc/example.c'],
  dependencies: libsc_argparse_dep,
)



@@ 51,3 51,9 @@ test('unit test', tests)

# For each public header in "include/":
install_headers('include/sc-argparse.h', subdir : 'sc-argparse')

if get_option('doc')
	subdir('doc')
else
	message('Documentation will not be built. Use -Ddoc to build it.')
endif