C command line parser API
All C type and function names described in this document are presented in their default naming style (lower_case_with_underscorces)
Generic public API
Messages
enum nsxml_message_type
{
nsxml_message_type_debug = 0,
nsxml_message_type_warning,
nsxml_message_type_error,
nsxml_message_type_fatal_error,
nsxml_message_type_count
};
struct _nsxml_message
{
int type;
int code;
char *message;
struct _nsxml_message* next_message;
};
typedef struct _nsxml_message nsxml_message;
This struct stores messages raised by the parser during the command line argument parsing process. The code member refers to the message codes defines in the specification compliance page.
Value
enum nsxml_value_type
{
nsxml_value_type_unset = -1,
nsxml_value_type_null,
nsxml_value_type_int,
nsxml_value_type_float,
nsxml_value_type_string
};
struct _nsxml_value
{
int type;
const char *string_value;
int int_value;
float float_value;
struct _nsxml_value *next_value;
};
typedef struct _nsxml_value nsxml_value;
This struct stores options argument(s) and positional arguments values.
The string_value is always filled and points to one of the command line argument item (argv[]) except if type is set to nsxml_value_type_null.
Depending on option/positional argument specifications. int_value and float_value will be set by converting the value of string_value
Utilities
Theses elements are used internally by the C parser but can be used for various purpose. See the code for more informations
String copy
int nsxml_util_strncpy(char *output, size_t output_length, const char *input, size_t input_length);
int nsxml_util_strcpy(char *output, size_t output_length, const char *input);
int nsxml_util_asnprintf(char **output, size_t *output_length, const char *format, ...);
Text wrapping
enum nsxml_util_text_indent_mode
{
nsxml_util_text_wrap_indent_none = 0,/**!< Do not indent */
nsxml_util_text_wrap_indent_first, /**!< Indent first line */
nsxml_util_text_wrap_indent_others /**!< Indent all line except the first */
};
enum nsxml_util_text_wrap_eol
{
nsxml_util_text_wrap_eol_cr = 1,
nsxml_util_text_wrap_eol_lf = 2,
nsxml_util_text_wrap_eol_crlf = 3
};
void nsxml_util_text_wrap_options_init(struct nsxml_util_text_wrap_options* options, int tab, int line, int indent_mode, int eol);
void nsxml_util_text_wrap_fprintf(FILE *stream, const char *text, const struct nsxml_util_text_wrap_options* options, int level);
Auto-generated types and functions
Here, we assume your_app as the prefix used to generate the program parser.
Structs
Program interface informations
A C representation of the program interface description is generated based on the generic
typedef struct nsxml_program_info your_app_info;
your_app_info *your_app_info_new();
void your_app_info_init(your_app_info *info);
Initialize or create a new C representation of the program interface description.
-
your_app_info_init should be used on manually created your_app_info only.
-
your_app_info_new calls your_app_info_init internally
void your_app_info_cleanup(your_app_info *info);
void your_app_info_free(your_app_info *info);
Release internal resources or completely free a your_app_info struct
-
your_app_info_cleanup should be used on manually created your_app_info only.
-
your_app_info_free calls your_app_info_cleanup internally
Parser result
The parsing result is stored in a struct where most of members depends on subcommand and variable names described in the program interface XML definition file.
Here is a sample of what you can get.
struct _your_app_result
{
/* Messages - Sorted by severity */
nsxml_message *messages[nsxml_message_type_count];
/* Messages - Sorted by apparition */
nsxml_message *first_message;
/* Subcommand */
const char *subcommand_name;
/* Values */
int value_count;
nsxml_value *values;
/* Global options */
struct
{
struct nsxml_switch_option_result displayHelp;
struct nsxml_switch_option_result verboseProgram;
struct nsxml_argument_option_result uiArg;
struct nsxml_argument_option_result standardArg;
/* ... */
} options;
/* Subcommands */
struct
{
struct your_app_sub_subcommand_result
{
/* Subcommand options */
struct nsxml_switch_option_result _switch;
} sub;
struct your_app_sub_subcommand_result
{
/* Subcommand options */
struct nsxml_argument_option_result subFile;
struct nsxml_argument_option_result subEnum;
} foo;
} subcommands;
};
typedef struct _your_app_result your_app_result;
-
result->subcommand_name points to the name of the selected subcommand (if any, otherwise NULL)
-
result->values is a list of (valid) positional arguments found on the command line
All nsxml_*_option_result structs have a is_set member. This member is set to 1 if the option is present and valid.
-
nsxml_argument_option_result adds a nsxml_value argument that store the option argument (if option is set)
-
nsxml_multiargument_option_result adds a nsxml_value arguments that store the option argument(s) (if option is set)
-
nsxml_group_option_result adds nsxml_option_result *selected_option and const char *selected_option_name set if
the group is an exclusive group and a sub option of this group is set. The selected_option_name refers to the variable name
of the sub option and selected_option points to the option's nsxml_*_option_result
Functions
your_app_result *your_app_parse(your_app_info *info, int argc, const char **argv, int start_index);
Parse the command line arguments (given by argc and argv), starting with the start_indexth argument.
The function returns a new your_app_result* described above
void your_app_usage(FILE *stream, your_app_info *info, your_app_result *result, int format, const struct nsxml_util_text_wrap_options *wrap);
Print program usage. If result is given, the function will use the result state to display contextual help (depending if a subcommand was set or not)
int your_app_result_error_count(your_app_result *result);
Return the number of errors (+ the fatal error if any) raised during the command line parsing
nsxml_message *your_app_result_get_warnings(your_app_result *result);
nsxml_message *your_app_result_get_errors(your_app_result *result);
nsxml_message *your_app_result_get_fatal_error(your_app_result *result);
Shortcuts to access your_app_result->messages[nsxml_message_type_*]
void your_app_result_display_errors(FILE *stream, your_app_result *result, const char *line_prefix);
Display errors (and fatal error) on a given output, prefixing all lines with line_prefix
void your_app_result_free(your_app_result *result);
Free a your_app_result allocated by a call to your_app_parse()
Code snippets
Display program usage
your_app_info info;
your_app_info_init(&info);
your_app_usage(stdout, &info, NULL, nsxml_usage_format_short, NULL);
your_app_info_cleanup(&info);
Or ...
your_app_info *info = your_app_info_new();
your_app_usage(stdout, info, NULL, nsxml_usage_format_short, NULL);
your_app_info_free(info);
Calling the parser
your_app_info *info = your_app_info_new();
your_app_result *result = your_app_parse(info, argc, argv, 1);
if (your_app_result_error_count(result))
{
your_app_result_display_errors(stderr, result, " - ");
your_app_result_free(result);
your_app_info_free(info);
return EXIT_FAILURE;
}
/* Dealing with a switch */
if (result.options.displayHelp.is_set)
{
your_app_usage(stdout, info, NULL, nsxml_usage_format_details, NULL);
your_app_result_free(result);
your_app_info_free(info);
return EXIT_SUCCESS;
}
/* .. with a single-argument option */
if (result.options.arg.is_set)
{
printf("Value of the single-argument option: %s\n", result.options.arg.argument.string_value);
}
/* ... with a multi-argument option */
if (result.options.multi.is_set)
{
nsxml_value *v = result.options.multi.arguments;
int i = 0;
while (v)
{
printf("Value of argument %d of multi option: %s\n", i, v->string_value);
v = v->next_value;
++i;
}
}
your_app_result_free(result);
your_app_info_free(info);
return EXIT_SUCCESS;
About memory usage
Most of all elements of the your_app_result will be valid until a call to your_app_result_free() or
-
nsxml_value->string_value points to one of the elememts of argv{} (the argument given to your_app_parse())
-
result->sub_command_name points to a string allocated in your_app_info
-
greup_result->selected_option_name points to a string allocated in your_app_info
So releasing or modifying your_app_info or argc/argv[] is not recommended before a call to your_app_result_free() or
Tweaking
Identifier naming style
The general naming style of the C parser source code is lower_case_with_underscorces. Naming style of the public API and auto-generated structs, functions and enums can be changed to CamelCase or camelCase using build-c.sh tool
build-c.sh -x myapp.xml --struct CamelCase --function camelCase -o out
-
your_app_info will be changed to YourAppInfo
-
your_app_info_init() will be change to yourAppInfoInit()
Variable names given in the program interface XML description file (<prg:databinding><prg:variable>my_option</prg:variable></prg:databinding>) and internal API structs and functions are not modified.
Code formatting
There is no parameters to change the default code formatting of the generated files. You may post process the generated files using a third party tool such as Artistic Style
See also
The program interface definition framework