CAPS Universe documentation  1.0.4
All you need to know to be successful
Functions
libcapscmdparser.c File Reference

Cascadeable command line parameter parser implementation. More...

Functions

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_parametershort_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_parameterlong_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])
 

Detailed Description

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:

'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.

Function Documentation

◆ is_keyword()

static bool is_keyword ( int  c)
static

Check if the given character is an allowed one for a keyword

Parameters
[in]cThe character to check
Return values
trueIf the character is allowed for a keyword
falseIf the character isn't part of the keyword

All kind of characters are allowed for a keyword. Delimiters are:

  • a space
  • '='
  • '\0' end of string

◆ adapt_string()

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]paramThe parameter to examine (keyword)
[out]keywordWhere to store the keyword
[out]valueWhere to store a possible value
[out]keyword_szWhere to store the length of the keyword
Return values
0Successfull
-EINVALBad 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,

◆ parameter_long_output()

static void parameter_long_output ( const struct caps_arg_parser_list plist,
size_t  pars_no,
size_t  param_no 
)
static

Output one possible argument as a help text

Parameters
[in]plistThe full parser list
[in]pars_noParser index
[in]param_noParameter index in the pars_no parser

◆ arguments_inside()

static unsigned arguments_inside ( const struct caps_arg_parser_list plist)
static

Check if optional and/or required arguments are part of this parser list

Parameters
[in]plistThe full parser list
Return values
0No arguments at all (should really not happen!)
1required arguments
2optional arguments
3both kind of arguments
Note
Since --help, --usage and --version are always optional, optional arguments are always present, too

◆ parameter_short_output()

static void parameter_short_output ( const struct caps_arg_parser_list plist,
size_t  pars_no,
size_t  param_no 
)
static

Output one possible argument as a parameter or option

Parameters
[in]plistThe full parser list
[in]pars_noParser index
[in]param_noParameter index in the pars_no parser

◆ parsers_parameter_output()

static void parsers_parameter_output ( const struct caps_arg_parser_list plist)
static

Create a list of supported options and parameters (for the 'usage' output)

Parameters
[in]plistThe full parser list

Create a single line with all possible parameters the program can deal with.

Todo:

Beautify the output

Sort the output. Options first, parameters second

◆ option_usage_output()

static int option_usage_output ( const struct caps_arg_parser_list plist)
static

Output a short usage information about the main program

Parameters
[in]plistThe full parser list
Return values
-EAGAINTerminate the program by intention

◆ option_version_output()

static int option_version_output ( const struct caps_arg_parser_list plist)
static

Output the version information about the main program

Parameters
[in]plistThe full parser list
Return values
-EAGAINTerminate the program by intention
-errnoAny kind of different errors which can happen when calling printf()

◆ generic_arg_process()

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]plistThe full parser list
[in]keyword_szSize of keyword
[in]keywordThe current keyword to process
[in]valKeyword's value (currently none)
Return values
0None of the generic options found. Continue parsing as usual.
-EINVALGeneric option '–version' not supported, stop parsing and terminate
-EAGAINGeneric 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

◆ short_parameter_handler_find()

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

Search for the parameter key related argument parser

Parameters
[in]plistFull parser list
[out]parserParameter's associated parser
[in]keyword_szSize of the string in keyword
[in]keywordThe key to find the parameter handler for.
Return values
PointerThe associated argument parser
NULLNo argument parser found
Attention
This string keyword points to might not be '\0' terminated
Precondition
Length of the key must be '1', e.g. keyword_sz == 1

◆ long_parameter_handler_find()

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

Search for the parameter keyword related argument parser

Parameters
[in]plistFull parser list
[out]parserParameter's associated parser
[in]keyword_szSize of the string in keyword
[in]keywordThe keyword to find the parameter handler for.
Return values
PointerThe associated argument parser
NULLNo argument parser found
Attention
This string keyword points to might not be '\0' terminated
Precondition
Length of the keyword must be greater than '1', e.g. keyword_sz > 1

◆ arg_split_and_process()

static int arg_split_and_process ( const struct caps_arg_parser_list plist,
int *  cur,
const char *  leading,
const char *  trailing 
)
static

Split one command line parameter string into its keyword and value and process it

Parameters
[in]plistFull parser list
[out]curCurrent argv index
[in]leadingLeading argument (e.g. argv[n] or argv[*cur])
[in]trailingTrailing argument (e.g. argv[n + 1]) or NULL
Return values
valueThe return value from the callback routine
-EINVALUnknown keyword, invalid argument format, missing required value, unexpected value

Examples from leading and trailing to keyword and value:

leading trailing keyword value
"-d" "--param" "d" NULL
Note
-d has no or an optional value. If -d has a required value, it ends with an error
leading trailing keyword value
"-d" "value" "d" "value"
Note
This one is ambigious, since -d might not require a value and the "value" can be a free parameter
In this case *cur is incremented by one
leading trailing keyword value
"--param" "-d" "param" NULL
leading trailing keyword value
"--param" "value" "param" "value"
Note
In this case *cur is incremented by one
leading keyword value
"--param=value" "param" "value"
"--param value" "param" "value"
"-d=value" "d" "value"
"-d value" "d" "value"

The keyword is used to select its corresponding callback and value is used when this callback is called.