summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
0a02479)
With the current API, when encountering an argument parsing error, the
error type (unknown option, missing option argument, unexpected option
argument) is encoded in the returned argpar_iter_next_status value.
In my experience it would be more useful if that information was encoded
in the argpar_error instead.
Imagine a helper function `format_arg_error` that formats an argument
parsing error based on a particular project's needs. That function
needs to take the argpar_iter_next_status along with the argpar_error:
char *format_arg_error(enum argpar_iter_next_status status,
const struct argpar_error *error);
It would be simpler to have the argpar_error object know what type of
error was returned. That makes the argpar_error contain all the
necessary information about the error.
So, the proposed changes are:
- Replace ARGPAR_ITER_NEXT_STATUS_ERROR_* with a single
ARGPAR_ITER_NEXT_STATUS_ERROR, indicating that an argument parsing
error happened.
- Add a new `enum argpar_error_type` type, to represent the 3 argument
parsing error types.
- Add a new `type` property to argpar_error, obtained through
`argpar_error_get_type`.
Note that the argpar_error out parameter of the argpar_iter_next
function is optional. This means that the user can currently receive an
error status (ARGPAR_ITER_NEXT_STATUS_ERROR_{UNKNOWN_OPT,
UNEXPECTED_OPT_ARG,MISSING_OP_ARG}) but not have any more details about
the error. I don't think this is really useful, because the user of the
API wouldn't be able to do make a useful error message by knowing the
type of error but not having the corresponding argpar_error object.
API documentation left to Philippe Proulx.
Change-Id: Ice4db8852030ccd3ba9cbdf3717d9850b8ee7935
/* Parsing error */
struct argpar_error {
/* Parsing error */
struct argpar_error {
+ /* Error type */
+ enum argpar_error_type type;
+
/* Original argument index */
unsigned int orig_index;
/* Original argument index */
unsigned int orig_index;
*/
static
int set_error(struct argpar_error ** const error,
*/
static
int set_error(struct argpar_error ** const error,
+ enum argpar_error_type type,
const char * const unknown_opt_name,
const struct argpar_opt_descr * const opt_descr,
const bool is_short)
const char * const unknown_opt_name,
const struct argpar_opt_descr * const opt_descr,
const bool is_short)
+ (*error)->type = type;
+
if (unknown_opt_name) {
(*error)->unknown_opt_name = ARGPAR_CALLOC(char,
strlen(unknown_opt_name) + 1 + (is_short ? 1 : 2));
if (unknown_opt_name) {
(*error)->unknown_opt_name = ARGPAR_CALLOC(char,
strlen(unknown_opt_name) + 1 + (is_short ? 1 : 2));
+ARGPAR_HIDDEN
+enum argpar_error_type argpar_error_type(
+ const struct argpar_error * const error)
+{
+ ARGPAR_ASSERT(error);
+ return error->type;
+}
+
ARGPAR_HIDDEN
unsigned int argpar_error_orig_index(const struct argpar_error * const error)
{
ARGPAR_HIDDEN
unsigned int argpar_error_orig_index(const struct argpar_error * const error)
{
const struct argpar_error * const error)
{
ARGPAR_ASSERT(error);
const struct argpar_error * const error)
{
ARGPAR_ASSERT(error);
+ ARGPAR_ASSERT(error->type == ARGPAR_ERROR_TYPE_UNKNOWN_OPT);
ARGPAR_ASSERT(error->unknown_opt_name);
return error->unknown_opt_name;
}
ARGPAR_ASSERT(error->unknown_opt_name);
return error->unknown_opt_name;
}
const struct argpar_error * const error, bool * const is_short)
{
ARGPAR_ASSERT(error);
const struct argpar_error * const error, bool * const is_short)
{
ARGPAR_ASSERT(error);
+ ARGPAR_ASSERT(error->type == ARGPAR_ERROR_TYPE_MISSING_OPT_ARG ||
+ error->type == ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG);
ARGPAR_ASSERT(error->opt_descr);
if (is_short) {
ARGPAR_ASSERT(error->opt_descr);
if (is_short) {
/* Return type of parse_short_opt_group() and parse_long_opt() */
enum parse_orig_arg_opt_ret {
PARSE_ORIG_ARG_OPT_RET_OK,
/* Return type of parse_short_opt_group() and parse_long_opt() */
enum parse_orig_arg_opt_ret {
PARSE_ORIG_ARG_OPT_RET_OK,
- PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT = -1,
- PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG = -2,
- PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG = -4,
- PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY = -5,
+ PARSE_ORIG_ARG_OPT_RET_ERROR = -1,
+ PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY = -2,
const char unknown_opt_name[] =
{*iter->short_opt_group_ch, '\0'};
const char unknown_opt_name[] =
{*iter->short_opt_group_ch, '\0'};
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR;
- if (set_error(error, unknown_opt_name, NULL, true)) {
+ if (set_error(error, ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
+ unknown_opt_name, NULL, true)) {
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
*/
if (!opt_arg || (iter->short_opt_group_ch[1] &&
strlen(opt_arg) == 0)) {
*/
if (!opt_arg || (iter->short_opt_group_ch[1] &&
strlen(opt_arg) == 0)) {
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR;
- if (set_error(error, NULL, descr, true)) {
+ if (set_error(error, ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
+ NULL, descr, true)) {
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
/* Find corresponding option descriptor */
descr = find_descr(descrs, '\0', long_opt_name);
if (!descr) {
/* Find corresponding option descriptor */
descr = find_descr(descrs, '\0', long_opt_name);
if (!descr) {
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR;
- if (set_error(error, long_opt_name, NULL, false)) {
+ if (set_error(error, ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
+ long_opt_name, NULL, false)) {
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
} else {
/* `--long-opt arg` style */
if (!next_orig_arg) {
} else {
/* `--long-opt arg` style */
if (!next_orig_arg) {
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR;
- if (set_error(error, NULL, descr, false)) {
+ if (set_error(error, ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
+ NULL, descr, false)) {
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
* Unexpected `--opt=arg` style for a long option which
* doesn't accept an argument.
*/
* Unexpected `--opt=arg` style for a long option which
* doesn't accept an argument.
*/
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG;
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR;
- if (set_error(error, NULL, descr, false)) {
+ if (set_error(error, ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
+ NULL, descr, false)) {
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
}
case PARSE_ORIG_ARG_OPT_RET_OK:
status = ARGPAR_ITER_NEXT_STATUS_OK;
break;
case PARSE_ORIG_ARG_OPT_RET_OK:
status = ARGPAR_ITER_NEXT_STATUS_OK;
break;
- case PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT:
- case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
- case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
+ case PARSE_ORIG_ARG_OPT_RET_ERROR:
if (error) {
ARGPAR_ASSERT(*error);
(*nc_error)->orig_index = iter->i;
}
if (error) {
ARGPAR_ASSERT(*error);
(*nc_error)->orig_index = iter->i;
}
-
- switch (parse_orig_arg_opt_ret) {
- case PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT:
- status = ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT;
- break;
- case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
- status = ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG;
- break;
- case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
- status = ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG;
- break;
- default:
- abort();
- }
-
+ status = ARGPAR_ITER_NEXT_STATUS_ERROR;
break;
case PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY:
status = ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY;
break;
case PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY:
status = ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY;
+enum argpar_error_type {
+ /// Unknown option error
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
+
+ /// Missing option argument error
+ ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
+
+ /// Unexpected option argument error
+ ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
+};
+
+ARGPAR_HIDDEN
+enum argpar_error_type argpar_error_type(
+ const struct argpar_error *error);
+
/*!
@brief
Returns the index of the original argument (in \p argv, as passed to
/*!
@brief
Returns the index of the original argument (in \p argv, as passed to
/// End of iteration (no more original arguments to parse)
ARGPAR_ITER_NEXT_STATUS_END,
/// End of iteration (no more original arguments to parse)
ARGPAR_ITER_NEXT_STATUS_END,
- /// Unknown option error
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT = -1,
-
- /// Missing option argument error
- ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG = -2,
-
- /// Unexpected option argument error
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG = -3,
+ /// Argument error
+ ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
/// Memory error
ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
/// Memory error
ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
*/
static
void test_fail(const char * const cmdline,
*/
static
void test_fail(const char * const cmdline,
- const enum argpar_iter_next_status expected_status,
+ const enum argpar_error_type expected_error_type,
const unsigned int expected_orig_index,
const char * const expected_unknown_opt_name,
const unsigned int expected_opt_descr_index,
const unsigned int expected_orig_index,
const char * const expected_unknown_opt_name,
const unsigned int expected_opt_descr_index,
ARGPAR_ITEM_DESTROY_AND_RESET(item);
status = argpar_iter_next(iter, &item, &error);
ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
ARGPAR_ITEM_DESTROY_AND_RESET(item);
status = argpar_iter_next(iter, &item, &error);
ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
- status == expected_status,
+ (status == ARGPAR_ITER_NEXT_STATUS_ERROR &&
+ argpar_error_type(error) == expected_error_type),
"argpar_iter_next() returns the expected status "
"argpar_iter_next() returns the expected status "
- "(%d) for command line `%s` (call %u)",
- status, cmdline, i + 1);
+ "and error type (%d) for command line `%s` (call %u)",
+ expected_error_type, cmdline, i + 1);
if (status != ARGPAR_ITER_NEXT_STATUS_OK) {
ok(!item,
if (status != ARGPAR_ITER_NEXT_STATUS_OK) {
ok(!item,
"for command line `%s` (call %u)",
cmdline, i + 1);
"for command line `%s` (call %u)",
cmdline, i + 1);
- if (status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
+ if (argpar_error_type(error) == ARGPAR_ERROR_TYPE_UNKNOWN_OPT) {
ok(strcmp(argpar_error_unknown_opt_name(error),
expected_unknown_opt_name) == 0,
"argpar_iter_next() sets an error with "
ok(strcmp(argpar_error_unknown_opt_name(error),
expected_unknown_opt_name) == 0,
"argpar_iter_next() sets an error with "
test_fail(
"-d salut -e -d meow",
test_fail(
"-d salut -e -d meow",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
2, "-e", 0, false,
descrs);
}
2, "-e", 0, false,
descrs);
}
test_fail(
"-dsalut -e -d meow",
test_fail(
"-dsalut -e -d meow",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
1, "-e", 0, false,
descrs);
}
1, "-e", 0, false,
descrs);
}
test_fail(
"--sink party --food --sink impulse",
test_fail(
"--sink party --food --sink impulse",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
2, "--food", 0, false,
descrs);
}
2, "--food", 0, false,
descrs);
}
test_fail(
"--sink=party --food --sink=impulse",
test_fail(
"--sink=party --food --sink=impulse",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
1, "--food", 0, false,
descrs);
}
1, "--food", 0, false,
descrs);
}
test_fail(
"--thumb=party --food=18 bateau --thumb waves",
test_fail(
"--thumb=party --food=18 bateau --thumb waves",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
1, "--food", 0, false,
descrs);
}
1, "--food", 0, false,
descrs);
}
test_fail(
"--thumb=party wound --food --thumb waves",
test_fail(
"--thumb=party wound --food --thumb waves",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
2, "--food", 0, false,
descrs);
}
2, "--food", 0, false,
descrs);
}
test_fail(
"allo --thumb",
test_fail(
"allo --thumb",
- ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
1, NULL, 0, false,
descrs);
}
1, NULL, 0, false,
descrs);
}
test_fail(
"zoom heille -k",
test_fail(
"zoom heille -k",
- ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
2, NULL, 0, true,
descrs);
}
2, NULL, 0, true,
descrs);
}
- ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
0, NULL, 2, true,
descrs);
}
0, NULL, 2, true,
descrs);
}
test_fail(
"ambulance --chevre=fromage tar -cjv",
test_fail(
"ambulance --chevre=fromage tar -cjv",
- ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG,
+ ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
1, NULL, 0, false,
descrs);
}
1, NULL, 0, false,
descrs);
}