-
Notifications
You must be signed in to change notification settings - Fork 1
CAPI
All C type and function names described in this document are presented in their default naming style (lower_case_with_underscorces
)
- [C command line parser API](#C command line parser API)
- [Generic public API](#Generic public API)
- [Auto-generated types and functions](#Auto-generated types and functions)
- [Code snippets](#Code snippets)
- [Display program usage](#Display program usage)
- [Calling the parser](#Calling the parser)
- [About memory usage](#About memory usage)
-
Tweaking
- [Identifier naming style](#Identifier naming style)
- [Code formatting](#Code formatting)
- [See also](#See also)
#!cpp
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.
#!cpp
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
Theses elements are used internally by the C parser but can be used for various purpose. See the code for more informations
#!cpp
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, ...);
#!cpp
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);
Here, we assume your_app
as the prefix used to generate the program parser.
A C representation of the program interface description is generated based on the generic nsxml_*_info
structures (internal API)
#!cpp
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 createdyour_app_info
only. -
your_app_info_new
callsyour_app_info_init
internally#!cpp 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 createdyour_app_info
only. -
your_app_info_free
callsyour_app_info_cleanup
internally
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.
#!cpp
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, otherwiseNULL
) -
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 ansxml_value argument
that store the option argument (if option is set) -
nsxml_multiargument_option_result
adds ansxml_value arguments
that store the option argument(s) (if option is set) -
nsxml_group_option_result
addsnsxml_option_result *selected_option
andconst char *selected_option_name
set if the group is an exclusive group and a sub option of this group is set. Theselected_option_name
refers to the variable name of the sub option andselected_option
points to the option'snsxml_*_option_result
#!cpp
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_index
th argument.
The function returns a new your_app_result*
described above
#!cpp
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)
#!cpp
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
#!cpp
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_*]
#!cpp
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
#!cpp
void your_app_result_free(your_app_result *result);
Free a your_app_result
allocated by a call to your_app_parse()
#!cpp
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 ...
#!cpp
your_app_info *info = your_app_info_new();
your_app_usage(stdout, info, NULL, nsxml_usage_format_short, NULL);
your_app_info_free(info);
#!cpp
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;
Most of all elements of the your_app_result
will be valid until a call to your_app_result_free()
or your_app_cleanup()
. However some string values refers to data allocated by foreign objects.
-
nsxml_value->string_value
points to one of the elememts ofargv{}
(the argument given toyour_app_parse()
) -
result->sub_command_name
points to a string allocated inyour_app_info
-
greup_result->selected_option_name
points to a string allocated inyour_app_info
So releasing or modifying your_app_info
or argc
/argv[]
is not recommended before a call to your_app_result_free()
or your_app_cleanup()
.
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](https://github.com/noresources/ns-xml/wiki/build-c)
tool
#!bash
build-c.sh -x myapp.xml --struct CamelCase --function camelCase -o out
-
your_app_info
will be changed toYourAppInfo
-
your_app_info_init()
will be change toyourAppInfoInit()
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.
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
- build-c.sh command line utility