https://github.com/jibsen/parg
Parser for argv that works similarly to getopt
https://github.com/jibsen/parg
c getopt
Last synced: 10 months ago
JSON representation
Parser for argv that works similarly to getopt
- Host: GitHub
- URL: https://github.com/jibsen/parg
- Owner: jibsen
- License: mit-0
- Created: 2015-08-28T15:18:42.000Z (almost 11 years ago)
- Default Branch: master
- Last Pushed: 2023-10-31T12:22:24.000Z (over 2 years ago)
- Last Synced: 2024-07-11T14:43:43.861Z (almost 2 years ago)
- Topics: c, getopt
- Language: C
- Homepage:
- Size: 53.7 KB
- Stars: 178
- Watchers: 8
- Forks: 17
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-c - parg - A single-file reimplementation of getopt with better defaults. [CC0-1.0](https://spdx.org/licenses/CC0-1.0.html) (Utilities / YAML)
- awesome-c-zh - parg - 单文件重新实现更好的默认值。[](https://spdx.org/licenses/CC0-1.0.html) (公用事业 / YAML)
- awesome-c - parg - A single-file reimplementation of getopt with better defaults. [CC0-1.0](https://spdx.org/licenses/CC0-1.0.html) (Utilities / YAML)
README
[](https://github.com/jibsen/parg/actions) [](https://codecov.io/gh/jibsen/parg)
About
-----
Most command-line programs have to parse options, so there are a lot of
different solutions to this problem. Some offer many features, while others
are more basic.
One of the simpler solutions for C is the [getopt][] function, and its
extension `getopt_long`. They iterate over the options in `argv`, returning
them one at a time on successive calls.
One nice thing about them is that they are available on most Unix-like
operating systems (and usually accompany GCC elsewhere, like Windows).
Unfortunately, some implementation details vary between platforms.
A potential question is what license the version you get when you include
them is available under. Some are GPL, others LGPL. There are also ports of
`getopt` that use more liberal licenses.
`parg` is a parser for `argv` that works similarly to `getopt`, but does not
aim to be a direct replacement. It attempts to make some choices about how to
handle the extensions and idiosyncrasies of other `getopt` implementations,
and document them.
It consists of a single source and include file, written in portable ANSI C.
It is made available under the [MIT No Attribution License](LICENSE) (MIT-0).
[getopt]: https://en.wikipedia.org/wiki/Getopt
Usage
-----
The include file `parg.h` contains documentation in the form of [doxygen][]
comments. A configuration file is included, run `doxygen` to generate
documentation in HTML format.
You can add the source files `parg.c` and `parg.h` to your own projects.
For CI, `parg` uses [CMake][] to provide an easy way to build and test across
various platforms and toolsets. To create a build system for the tools on your
platform, and build `parg`, use something along the lines of:
~~~sh
mkdir build
cd build
cmake ..
cmake --build .
~~~
[doxygen]: http://www.doxygen.org/
[CMake]: http://www.cmake.org/
Example
-------
Here is an example that parses command-line options using `parg_getopt()`:
~~~c
#include
#include
#include "parg.h"
int main(int argc, char *argv[])
{
struct parg_state ps;
int c;
parg_init(&ps);
while ((c = parg_getopt(&ps, argc, argv, "hs:v")) != -1) {
switch (c) {
case 1:
printf("nonoption '%s'\n", ps.optarg);
break;
case 'h':
printf("Usage: testparg [-h] [-v] [-s STRING]\n");
return EXIT_SUCCESS;
break;
case 's':
printf("option -s with argument '%s'\n", ps.optarg);
break;
case 'v':
printf("testparg 1.0.0\n");
return EXIT_SUCCESS;
break;
case '?':
if (ps.optopt == 's') {
printf("option -s requires an argument\n");
}
else {
printf("unknown option -%c\n", ps.optopt);
}
return EXIT_FAILURE;
break;
default:
printf("error: unhandled option -%c\n", c);
return EXIT_FAILURE;
break;
}
}
for (c = ps.optind; c < argc; ++c) {
printf("nonoption '%s'\n", argv[c]);
}
return EXIT_SUCCESS;
}
~~~
Comparison to `getopt`
----------------------
### Use of global variables
`getopt` uses global variables to store its state between calls. `parg` uses
a struct `parg_state`, which you must pass with each call.
### Handling of nonoptions
POSIX and BSD `getopt` return `-1` on the first nonoption argument. GNU
`getopt` by default reorders `argv` (even though it is passed as const), so
all options come first.
`parg` does not change `argv`, and returns each nonoption as the option
argument of an option with value `1` (like GNU `getopt`, if `optstring` were
prefixed by '`-`').
If you wish to process all options first, and have the nonoptions ordered at
the end of `argv`, you can use `parg_reorder()`:
~~~c
optend = parg_reorder(argc, argv, optstring, NULL);
while ((c = parg_getopt(&ps, optend, argv, optstring)) != -1) {
/* ... */
}
/* elements of argv[] from optend to argc are nonoptions */
~~~
### Value of `optind` on error
When there are multiple short options in one argument, `getopt` does not
increment `optind` until the last one is processed. This makes it harder to
tell which argument an unknown option came from (if `a` is an unknown option,
`-a` and `-ab` will return '`?`' with different values in `optind`).
`parg` always increments the `optind` value in it's state so it points to the
next `argv` element to be processed. So when `parg` returns '`?`' (or '`:`'),
the element that contains the error is `argv[optind - 1]`.
### Value of `optopt` on error
With `getopt_long`, it varies what the values of `optopt` and `longindex` are
when an error is found with option arguments of long options. Sometimes these
values are not documented.
`parg` sets `optopt` to `val` if `flag` is `NULL`, and `0` otherwise (which
equals the return value on successful match), and `longindex` is set to the
index of the entry in `longopts` that matched.
### Return value on option argument error
When the first character of `optstring` is '`:`', it varies what `getopt`
returns on extraneous option arguments.
In this case, `parg` returns '`?`' if no option match is found, and '`:`' if
a match is found, but is missing a required argument, or has an extraneous
argument.
Alternatives
------------
Some ports of `getopt`:
- [Free Getopt](http://freegetopt.sourceforge.net/)
- [ya_getopt](http://github.com/kubo/ya_getopt/)
- [getopt_port](http://github.com/kimgr/getopt_port/)
Other command-line parsing libraries that support C:
- [Gengetopt](http://www.gnu.org/software/gengetopt/)
- [Argp](http://www.gnu.org/software/libc/manual/html_node/Argp.html)
- [popt](http://en.wikipedia.org/wiki/Popt)
- [argtable](https://www.argtable.org/)
- [optlist](http://michael.dipperstein.com/optlist/)
- [Arg_parser](http://www.nongnu.org/arg-parser/arg_parser.html)
- [Gopt](http://www.purposeful.co.uk/software/gopt/)
- [docopt](http://docopt.org/)
- [optparse](https://github.com/skeeto/optparse)
- [getopt](https://github.com/wc-duck/getopt)
- [argparse](https://github.com/cofyc/argparse)
A few C++ command-line parsing libraries:
- [TCLAP](http://tclap.sourceforge.net/)
- [program_options](http://www.boost.org/doc/libs/1_58_0/doc/html/program_options.html)
- [CommandLine](http://llvm.org/docs/CommandLine.html)
- [CLI11](https://github.com/CLIUtils/CLI11)
- [argparse](https://github.com/p-ranav/argparse)
- [clipp](https://github.com/muellan/clipp)
- [argh](https://github.com/adishavit/argh)