Add internal command-line argument parser API
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sun, 7 Jul 2019 03:15:58 +0000 (23:15 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 2 Aug 2019 15:46:54 +0000 (11:46 -0400)
commitfac21c8788e860accfc1f3e2b519d355283b1fb5
tree095bf4e08df7d315470f10b5b1fbabf9f309c8d7
parente071d36f57dc014a7892fe603cab7e7a36bf348c
Add internal command-line argument parser API

This patch adds an internal command-line argument parser API.

The exact API is well documented in `src/argpar/argpar.h`.

The features that I'm looking for are:

* C API.

* Support for ordered arguments in the results, even between options and
  non-option arguments (sometimes called positional arguments).

* Support for GNU-style arguments, including "glued" short options and
  long options with `=` to set the option's argument.

* Portable.

* Compatible license.

* No global variables (we're trying to avoid that programming style
  throughout the project).

* Easy to use.

None of the popular libraries I looked at, including popt of course, met
all those specifications.

The goal of this is:

1. To simplify the parsing of general options (before the command name)
   in bt_config_cli_args_create(). It is currently hard-coded.

   This is not possible with popt because it would fail with an unknown
   option, and you would not know the position of the command name's
   argument within the array.

   This is possible with g_option_context_parse().

2. To make it possible, in the `convert` command, to assign parameters
   and other position-specific options to a non-option argument, for
   example:

       babeltrace2 /path/to/trace --params=some=param \
                   mein-other-trace --name=travel

   This is not possible with popt as it collects all the non-option
   arguments as an array of leftover arguments.

   This is also not possible with g_option_context_parse() for the same
   reasons as with popt.

getopt_long() could satisfy both 1. and 2., but it's somewhat a pain to
use and to maintain the available options, as you need to specify the
long options in a table and the equivalent short options as a single
string with a special encoding (the `convert` command's option string
would be particularily ugly). Also: getopt_long() plays a lot with
global variables; it's not thread-safe: the parser's state is global.
Also: the upstream getopt_long()'s (glibc) license is LGPL, which is
more restrictive than our MIT license, so I think we want to avoid that.

I believe having our own (tested) CLI argument parser is beneficial,
especially in the long term: we can drop a direct dependency (and popt
is getting old), not introduce a new one, it's about 450 lines of
documented C code, and if we ever need something very specific in the
argument parsing strategy in the future, we can add it directly. As a
reference, FFmpeg, a project which has complex argument parsing, similar
to Babeltrace's `convert` and `run` commands, has its own argument
parser (see parse_options() in [1]).

Only the CLI will use the bt_argpar_*() API, but to make the unit tests
simpler, I put it in its own convenience library.

[1]: https://github.com/FFmpeg/FFmpeg/blob/b7b6ddd59693008c35b3247496ecc946331d0856/fftools/cmdutils.c

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Iff4fc305b9e9171c694e1e79428bd3838ddd989d
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1646
CI-Build: Simon Marchi <simon.marchi@efficios.com>
Tested-by: jenkins <jenkins@lttng.org>
.gitignore
configure.ac
src/Makefile.am
src/argpar/Makefile.am [new file with mode: 0644]
src/argpar/argpar.c [new file with mode: 0644]
src/argpar/argpar.h [new file with mode: 0644]
tests/Makefile.am
tests/argpar/Makefile.am [new file with mode: 0644]
tests/argpar/test_argpar.c [new file with mode: 0644]
This page took 0.024954 seconds and 4 git commands to generate.