|
static bool | is_keyword (int c) |
|
static int | adapt_string (const char *param, const char **keyword, const char **value, size_t *keyword_sz) |
|
static void | parameter_long_output (const struct caps_arg_parser_list *plist, size_t pars_no, size_t param_no) |
|
static unsigned | arguments_inside (const struct caps_arg_parser_list *plist) |
|
int | caps_arg_parser_help (const struct caps_arg_parser_list *plist) |
|
static void | parameter_short_output (const struct caps_arg_parser_list *plist, size_t pars_no, size_t param_no) |
|
static void | parsers_parameter_output (const struct caps_arg_parser_list *plist) |
|
static int | option_usage_output (const struct caps_arg_parser_list *plist) |
|
static int | option_version_output (const struct caps_arg_parser_list *plist) |
|
static int | generic_arg_process (const struct caps_arg_parser_list *plist, size_t keyword_sz, const char keyword[keyword_sz], const char *val) |
|
static const struct caps_arg_parameter * | short_parameter_handler_find (const struct caps_arg_parser_list *plist, const struct caps_arg_parser **parser, size_t keyword_sz, const char keyword[keyword_sz]) |
|
static const struct caps_arg_parameter * | long_parameter_handler_find (const struct caps_arg_parser_list *plist, const struct caps_arg_parser **parser, size_t keyword_sz, const char keyword[keyword_sz]) |
|
static int | arg_split_and_process (const struct caps_arg_parser_list *plist, int *cur, const char *leading, const char *trailing) |
|
int | caps_arg_parser_process (const struct caps_arg_parser_list *plist, int argc, char *argv[argc]) |
|
- Author
- Jürgen Borleis
- Warning
- Use as experimental
I started with getopt_long()
and it worked a little bit. But when it comes to process command line parameters at different and independent layers in one single application, it was a very ugly implementation. Then I stumbled across argp. Nice approach to cascade parsers of different layers into one parser for all. But its implementation still drives me crazy:
- global variables for version and bug report email strings. Ouch!
- NLS support works only partially. Some strings are translated, some aren't, depending on some unknown defaults. No way to get valid translations for all cascaded parsers at once.
- the callbacks per parser are a nice idea, but they don't have a context. So they rely on global variables to store their values. Ouch! Ouch!
- the library just terminates the whole application in a hard way if parameters like
--version
, --help
and --usage
are given. It is possible to change this behaviour into a return - but there is no way to detect this special case. Ouch! Ouch! Ouch!
'popt' is a different nice approach to cascade parsers. But again NLS is a mess in this lib.
So I wrote my own little approach for the CAPS universe.
static int adapt_string |
( |
const char * |
param, |
|
|
const char ** |
keyword, |
|
|
const char ** |
value, |
|
|
size_t * |
keyword_sz |
|
) |
| |
|
static |
Split the parameter keyword and its (possible) value
- Parameters
-
[in] | param | The parameter to examine (keyword) |
[out] | keyword | Where to store the keyword |
[out] | value | Where to store a possible value |
[out] | keyword_sz | Where to store the length of the keyword |
- Return values
-
0 | Successfull |
-EINVAL | Bad short parameter or value expected, bot not given. |
- Attention
- keyword, value and sz aren't touched if the routine returns an error.
- Todo:
- How to return a free parameter (without '-' or '–')?
It also deals with "-d param" and "--long param", e.g. if the keyword and its parameter is in one argv instead of two.
TODO We always expect a string in the format:
- <at-least-one-char>\0 A boolean argument without a value
- <at-least-one-char> <value>\0 An argument with a value
- <at-least-one-char>=<value>\0 An argument with a value
In case of failure, key and value are undefined!
- Precondition
- A parameter must start with an alpha character
- Note
- *value will be NULL if the parameter has no value,
static int generic_arg_process |
( |
const struct caps_arg_parser_list * |
plist, |
|
|
size_t |
keyword_sz, |
|
|
const char |
keyword[keyword_sz], |
|
|
const char * |
val |
|
) |
| |
|
static |
Deal with the generic options like –version, –help and –usage
- Parameters
-
[in] | plist | The full parser list |
[in] | keyword_sz | Size of keyword |
[in] | keyword | The current keyword to process |
[in] | val | Keyword's value (currently none) |
- Return values
-
0 | None of the generic options found. Continue parsing as usual. |
-EINVAL | Generic option '–version' not supported, stop parsing and terminate |
-EAGAIN | Generic help or usage or version call, terminate now |
If one of the generic options was found, it will be processed accordingly and the caller should terminate. To detect this case it returns with a -EAGAIN.
This call returns with a '0' and did nothing, if the option isn't one of the generic ones. In this case it means: continue with the other parsers