unsigned int non_opt_index;
};
-static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 0)))
-char *argpar_vasprintf(const char * const fmt, va_list args)
-{
- int len1, len2;
- char *str;
- va_list args2;
-
- va_copy(args2, args);
- len1 = vsnprintf(NULL, 0, fmt, args);
- if (len1 < 0) {
- str = NULL;
- goto end;
- }
-
- str = malloc(len1 + 1);
- if (!str) {
- goto end;
- }
-
- len2 = vsnprintf(str, len1 + 1, fmt, args2);
- ARGPAR_ASSERT(len1 == len2);
-
-end:
- va_end(args2);
- return str;
-}
-
-
-static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 2)))
-char *argpar_asprintf(const char * const fmt, ...)
-{
- va_list args;
- char *str;
-
- va_start(args, fmt);
- str = argpar_vasprintf(fmt, args);
- va_end(args);
- return str;
-}
-
-static __attribute__((format(ARGPAR_PRINTF_FORMAT, 2, 3)))
-bool try_append_string_printf(char ** const str, const char *fmt, ...)
-{
- char *new_str = NULL;
- char *addendum = NULL;
- bool success;
- va_list args;
-
- if (!str) {
- success = true;
- goto end;
- }
-
- ARGPAR_ASSERT(str);
- va_start(args, fmt);
- addendum = argpar_vasprintf(fmt, args);
- va_end(args);
-
- if (!addendum) {
- success = false;
- goto end;
- }
+/* Parsing error */
+struct argpar_error {
+ /* Original argument index */
+ unsigned int orig_index;
- new_str = argpar_asprintf("%s%s", *str ? *str : "", addendum);
- if (!new_str) {
- success = false;
- goto end;
- }
+ /* Name of unknown option; owned by this */
+ char *unknown_opt_name;
- free(*str);
- *str = new_str;
- success = true;
+ /* Option descriptor */
+ const struct argpar_opt_descr *opt_descr;
-end:
- free(addendum);
- return success;
-}
+ /* `true` if a short option caused the error */
+ bool is_short;
+};
ARGPAR_HIDDEN
enum argpar_item_type argpar_item_type(const struct argpar_item * const item)
return non_opt_item;
}
+/*
+ * If `error` is not `NULL`, sets the error `error` to a new parsing
+ * error object, setting its `unknown_opt_name`, `opt_descr`, and
+ * `is_short` members from the parameters.
+ *
+ * `unknown_opt_name` is the unknown option name without any `-` or `--`
+ * prefix: `is_short` controls which type of unknown option it is.
+ *
+ * Returns 0 on success (including if `error` is `NULL`) or -1 on memory
+ * error.
+ */
+static
+int set_error(struct argpar_error ** const error,
+ const char * const unknown_opt_name,
+ const struct argpar_opt_descr * const opt_descr,
+ const bool is_short)
+{
+ int ret = 0;
+
+ if (!error) {
+ goto end;
+ }
+
+ *error = ARGPAR_ZALLOC(struct argpar_error);
+ if (!*error) {
+ goto error;
+ }
+
+ if (unknown_opt_name) {
+ (*error)->unknown_opt_name = ARGPAR_CALLOC(char,
+ strlen(unknown_opt_name) + 1 + is_short ? 1 : 2);
+ if (!(*error)->unknown_opt_name) {
+ goto error;
+ }
+
+ if (is_short) {
+ strcpy((*error)->unknown_opt_name, "-");
+ } else {
+ strcpy((*error)->unknown_opt_name, "--");
+ }
+
+ strcat((*error)->unknown_opt_name, unknown_opt_name);
+ }
+
+ (*error)->opt_descr = opt_descr;
+ (*error)->is_short = is_short;
+ goto end;
+
+error:
+ argpar_error_destroy(*error);
+ ret = -1;
+
+end:
+ return ret;
+}
+
+ARGPAR_HIDDEN
+unsigned int argpar_error_orig_index(const struct argpar_error * const error)
+{
+ ARGPAR_ASSERT(error);
+ return error->orig_index;
+}
+
+ARGPAR_HIDDEN
+const char *argpar_error_unknown_opt_name(
+ const struct argpar_error * const error)
+{
+ ARGPAR_ASSERT(error);
+ ARGPAR_ASSERT(error->unknown_opt_name);
+ return error->unknown_opt_name;
+}
+
+ARGPAR_HIDDEN
+const struct argpar_opt_descr *argpar_error_opt_descr(
+ const struct argpar_error * const error, bool * const is_short)
+{
+ ARGPAR_ASSERT(error);
+ ARGPAR_ASSERT(error->opt_descr);
+
+ if (is_short) {
+ *is_short = error->is_short;
+ }
+
+ return error->opt_descr;
+}
+
+ARGPAR_HIDDEN
+void argpar_error_destroy(const struct argpar_error * const error)
+{
+ if (error) {
+ free(error->unknown_opt_name);
+ free((void *) error);
+ }
+}
+
static
const struct argpar_opt_descr *find_descr(
const struct argpar_opt_descr * const descrs,
const char * const next_orig_arg,
const struct argpar_opt_descr * const descrs,
struct argpar_iter * const iter,
- char ** const error, struct argpar_item ** const item)
+ struct argpar_error ** const error,
+ struct argpar_item ** const item)
{
enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
bool used_next_orig_arg = false;
/* Find corresponding option descriptor */
descr = find_descr(descrs, *iter->short_opt_group_ch, NULL);
if (!descr) {
- try_append_string_printf(error, "Unknown option `-%c`",
- *iter->short_opt_group_ch);
+ const char unknown_opt_name[] =
+ {*iter->short_opt_group_ch, '\0'};
+
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
+
+ if (set_error(error, unknown_opt_name, NULL, true)) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ }
+
goto error;
}
*/
if (!opt_arg || (iter->short_opt_group_ch[1] &&
strlen(opt_arg) == 0)) {
- try_append_string_printf(error,
- "Missing required argument for option `-%c`",
- *iter->short_opt_group_ch);
- used_next_orig_arg = false;
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
+
+ if (set_error(error, NULL, descr, true)) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ }
+
goto error;
}
}
const char * const next_orig_arg,
const struct argpar_opt_descr * const descrs,
struct argpar_iter * const iter,
- char ** const error, struct argpar_item ** const item)
+ struct argpar_error ** const error,
+ struct argpar_item ** const item)
{
enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
const struct argpar_opt_descr *descr;
/* Find corresponding option descriptor */
descr = find_descr(descrs, '\0', long_opt_name);
if (!descr) {
- try_append_string_printf(error, "Unknown option `--%s`",
- long_opt_name);
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
+
+ if (set_error(error, long_opt_name, NULL, false)) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ }
+
goto error;
}
} else {
/* `--long-opt arg` style */
if (!next_orig_arg) {
- try_append_string_printf(error,
- "Missing required argument for option `--%s`",
- long_opt_name);
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
+
+ if (set_error(error, NULL, descr, false)) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ }
+
goto error;
}
* Unexpected `--opt=arg` style for a long option which
* doesn't accept an argument.
*/
- try_append_string_printf(error,
- "Unexpected argument for option `--%s`", long_opt_name);
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG;
+
+ if (set_error(error, NULL, descr, false)) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ }
+
goto error;
}
enum parse_orig_arg_opt_ret parse_orig_arg_opt(const char * const orig_arg,
const char * const next_orig_arg,
const struct argpar_opt_descr * const descrs,
- struct argpar_iter * const iter, char ** const error,
+ struct argpar_iter * const iter,
+ struct argpar_error ** const error,
struct argpar_item ** const item)
{
enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
return ret;
}
-static
-bool try_prepend_while_parsing_arg_to_error(char ** const error,
- const unsigned int i, const char * const arg)
-{
- char *new_error;
- bool success;
-
- if (!error) {
- success = true;
- goto end;
- }
-
- ARGPAR_ASSERT(*error);
- new_error = argpar_asprintf("While parsing argument #%u (`%s`): %s",
- i + 1, arg, *error);
- if (!new_error) {
- success = false;
- goto end;
- }
-
- free(*error);
- *error = new_error;
- success = true;
-
-end:
- return success;
-}
-
ARGPAR_HIDDEN
struct argpar_iter *argpar_iter_create(const unsigned int argc,
const char * const * const argv,
ARGPAR_HIDDEN
enum argpar_iter_next_status argpar_iter_next(
struct argpar_iter * const iter,
- const struct argpar_item ** const item, char ** const error)
+ const struct argpar_item ** const item,
+ const struct argpar_error ** const error)
{
enum argpar_iter_next_status status;
enum parse_orig_arg_opt_ret parse_orig_arg_opt_ret;
const char *orig_arg;
const char *next_orig_arg;
+ struct argpar_error ** const nc_error = (struct argpar_error **) error;
ARGPAR_ASSERT(iter->i <= iter->argc);
if (error) {
- *error = NULL;
+ *nc_error = NULL;
}
if (iter->i == iter->argc) {
/* Option argument */
parse_orig_arg_opt_ret = parse_orig_arg_opt(orig_arg,
- next_orig_arg, iter->descrs, iter, error,
+ next_orig_arg, iter->descrs, iter, nc_error,
(struct argpar_item **) item);
switch (parse_orig_arg_opt_ret) {
case PARSE_ORIG_ARG_OPT_RET_OK:
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:
- try_prepend_while_parsing_arg_to_error(error, iter->i,
- orig_arg);
+ 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:
/*!
@brief
Returns the complete original argument, pointing to one of the
- entries of the original arguments (\p argv as passed to
+ entries of the original arguments (in \p argv, as passed to
argpar_iter_create()), of the non-option parsing item \p item.
@param[in] item
/*!
@brief
- Returns the index, within \em all the original arguments (\p argv
- as passed to argpar_iter_create()), of the non-option parsing item
- \p item.
+ Returns the index, within \em all the original arguments (in
+ \p argv, as passed to argpar_iter_create()), of the non-option
+ parsing item \p item.
For example, with the following command line (all options have no
argument):
/// @}
+/*!
+@name Error API
+@{
+*/
+
+/*!
+@struct argpar_error
+
+@brief
+ Opaque parsing error type
+*/
+struct argpar_error;
+
+/*!
+@brief
+ Returns the index of the original argument (in \p argv, as passed to
+ argpar_iter_create()) for which the parsing error described by
+ \p error occurred.
+
+@param[in] error
+ Parsing error of which to get the original argument index.
+
+@returns
+ Original argument index of \p error.
+
+@pre
+ \p error is not \c NULL.
+*/
+/// @cond hidden_macro
+ARGPAR_HIDDEN
+/// @endcond
+unsigned int argpar_error_orig_index(const struct argpar_error *error);
+
+/*!
+@brief
+ Returns the name of the unknown option for which the parsing error
+ described by \p error occurred.
+
+The returned name includes any <code>-</code> or <code>\--</code>
+prefix.
+
+With the long option with argument form, for example
+<code>\--mireille=deyglun</code>, this function only returns the name
+part (<code>\--mireille</code> in the last example).
+
+You may only call this function if the call to argpar_iter_next() which
+set \p error returned #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT.
+
+@param[in] error
+ Parsing error of which to get the name of the unknown option.
+
+@returns
+ Name of the unknown option of \p error.
+
+@pre
+ \p error is not \c NULL.
+@pre
+ The call to argpar_iter_next() which set \p error returned
+ #ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT.
+*/
+/// @cond hidden_macro
+ARGPAR_HIDDEN
+/// @endcond
+const char *argpar_error_unknown_opt_name(const struct argpar_error *error);
+
+/*!
+@brief
+ Returns the descriptor of the option for which the parsing error
+ described by \p error occurred.
+
+You may only call this function if the call to argpar_iter_next() which
+set \p error returned #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG or
+#ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG.
+
+@param[in] error
+ Parsing error of which to get the option descriptor.
+@param[out] is_short
+ @parblock
+ If not \c NULL, this function sets \p *is_short to:
+
+ - \c true if the option for which \p error occurred is a short
+ option.
+
+ - \c false if the option for which \p error occurred is a long
+ option.
+ @endparblock
+
+@returns
+ Descriptor of the option of \p error.
+
+@pre
+ \p error is not \c NULL.
+@pre
+ The call to argpar_iter_next() which set \p error returned
+ #ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG or
+ #ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG.
+*/
+/// @cond hidden_macro
+ARGPAR_HIDDEN
+/// @endcond
+const struct argpar_opt_descr *argpar_error_opt_descr(
+ const struct argpar_error *error, bool *is_short);
+
+/*!
+@brief
+ Destroys the parsing error \p error.
+
+@param[in] error
+ Parsing error to destroy (may be \c NULL).
+*/
+/// @cond hidden_macro
+ARGPAR_HIDDEN
+/// @endcond
+void argpar_error_destroy(const struct argpar_error *error);
+
+/// @}
+
/*!
@name Iterator API
@{
receives, or ignore the parsing item of the first call to
argpar_iter_next().
-\p *argv and \p *descrs must \em not change for the lifetime of the
-returned iterator (until you call argpar_iter_destroy()) and for the
-lifetime of any parsing item (until you call argpar_item_destroy())
-which argpar_iter_next() creates from the returned iterator.
+\p *argv and \p *descrs must \em not change for all of:
+
+- The lifetime of the returned iterator (until you call
+ argpar_iter_destroy()).
+
+- The lifetime of any parsing item (until you call
+ argpar_item_destroy()) which argpar_iter_next() creates from the
+ returned iterator.
+
+- The lifetime of any parsing error (until you call
+ argpar_error_destroy()) which argpar_iter_next() creates from the
+ returned iterator.
@param[in] argc
Number of original arguments to parse in \p argv.
#ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG, or
#ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPG_ARG, if this parameter
is not \c NULL,
- \p *error is a string which explains the parsing error in English.
+ \p *error contains details about the error.
- Free \p *error with <code>free()</code>.
+ Destroy \p *error with argpar_error_destroy().
@endparblock
@returns
/// @endcond
enum argpar_iter_next_status argpar_iter_next(
struct argpar_iter *iter, const struct argpar_item **item,
- char **error);
+ const struct argpar_error **error);
/*
* Returns the number of ingested elements from `argv`, as passed to
/*!
@brief
Returns the number of ingested original arguments (in
- \p argv as passed to argpar_iter_create() to create \p iter) that
+ \p argv, as passed to argpar_iter_create() to create \p iter) that
the parser ingested to produce the \em previous parsing items.
@param[in] iter
{
struct argpar_iter *iter = NULL;
const struct argpar_item *item = NULL;
- char *error = NULL;
+ const struct argpar_error *error = NULL;
GString * const res_str = g_string_new(NULL);
gchar ** const argv = g_strsplit(cmdline, " ", 0);
unsigned int i, actual_ingested_orig_args;
status = argpar_iter_next(iter, &item, &error);
ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
- status == ARGPAR_ITER_NEXT_STATUS_END ||
- status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ status == ARGPAR_ITER_NEXT_STATUS_END,
"argpar_iter_next() returns the expected status "
"(%d) for command line `%s` (call %u)",
status, cmdline, i + 1);
+ ok(!error,
+ "argpar_iter_next() doesn't set an error for "
+ "command line `%s` (call %u)",
+ cmdline, i + 1);
- if (status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
- ok(error,
- "argpar_iter_next() sets an error for "
- "status `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
- "and command line `%s` (call %u)",
- cmdline, i + 1);
- } else {
- ok(!error,
- "argpar_iter_next() doesn't set an error "
- "for other status than "
- "`ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
- "and command line `%s` (call %u)",
- cmdline, i + 1);
- }
-
- if (status == ARGPAR_ITER_NEXT_STATUS_END ||
- status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
+ if (status == ARGPAR_ITER_NEXT_STATUS_END) {
ok(!item,
"argpar_iter_next() doesn't set an item "
"for status `ARGPAR_ITER_NEXT_STATUS_END` "
- "or `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
"and command line `%s` (call %u)",
cmdline, i + 1);
break;
argpar_item_destroy(item);
argpar_iter_destroy(iter);
+ assert(!error);
g_string_free(res_str, TRUE);
g_strfreev(argv);
- free(error);
}
static
descrs, 7);
}
- /* Unknown short option (space form) */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, 'd', NULL, true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "-d salut -e -d meow",
- "-d salut",
- descrs, 2);
- }
-
- /* Unknown short option (glued form) */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, 'd', NULL, true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "-dsalut -e -d meow",
- "-d salut",
- descrs, 1);
- }
-
- /* Unknown long option (space form) */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, '\0', "sink", true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "--sink party --food --sink impulse",
- "--sink=party",
- descrs, 2);
- }
-
- /* Unknown long option (equal form) */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, '\0', "sink", true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "--sink=party --food --sink=impulse",
- "--sink=party",
- descrs, 1);
- }
-
- /* Unknown option before non-option argument */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, '\0', "thumb", true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "--thumb=party --food bateau --thumb waves",
- "--thumb=party",
- descrs, 1);
- }
-
- /* Unknown option after non-option argument */
- {
- const struct argpar_opt_descr descrs[] = {
- { 0, '\0', "thumb", true },
- ARGPAR_OPT_DESCR_SENTINEL
- };
-
- test_succeed(
- "--thumb=party wound --food --thumb waves",
- "--thumb=party wound<1,0>",
- descrs, 2);
- }
-
/* Valid `---opt` */
{
const struct argpar_opt_descr descrs[] = {
/*
* Parses `cmdline` with the argpar API using the option descriptors
* `descrs`, and ensures that argpar_iter_next() fails with status
- * `expected_status` and that it sets an error which is equal to
- * `expected_error`.
+ * `expected_status` and that it sets an error having:
+ *
+ * * The original argument index `expected_orig_index`.
+ *
+ * * If applicable:
+ *
+ * * The unknown option name `expected_unknown_opt_name`.
+ *
+ * * The option descriptor at index `expected_opt_descr_index` of
+ * `descrs`.
+ *
+ * * The option type `expected_is_short`.
*
* This function splits `cmdline` on spaces to create an original
* argument array.
*/
static
-void test_fail(const char * const cmdline, const char * const expected_error,
+void test_fail(const char * const cmdline,
const enum argpar_iter_next_status expected_status,
+ const unsigned int expected_orig_index,
+ const char * const expected_unknown_opt_name,
+ const unsigned int expected_opt_descr_index,
+ const bool expected_is_short,
const struct argpar_opt_descr * const descrs)
{
struct argpar_iter *iter = NULL;
const struct argpar_item *item = NULL;
gchar ** const argv = g_strsplit(cmdline, " ", 0);
unsigned int i;
- char *error = NULL;
+ const struct argpar_error *error = NULL;
iter = argpar_iter_create(g_strv_length(argv),
(const char * const *) argv, descrs);
" `ARGPAR_ITER_NEXT_STATUS_OK` "
"and command line `%s` (call %u)",
cmdline, i + 1);
+ ok(argpar_error_orig_index(error) ==
+ expected_orig_index,
+ "argpar_iter_next() sets an error with "
+ "the expected original argument index "
+ "for command line `%s` (call %u)",
+ cmdline, i + 1);
+
+ if (status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
+ ok(strcmp(argpar_error_unknown_opt_name(error),
+ expected_unknown_opt_name) == 0,
+ "argpar_iter_next() sets an error with "
+ "the expected unknown option name "
+ "for command line `%s` (call %u)",
+ cmdline, i + 1);
+ } else {
+ bool is_short;
+
+ ok(argpar_error_opt_descr(error, &is_short) ==
+ &descrs[expected_opt_descr_index],
+ "argpar_iter_next() sets an error with "
+ "the expected option descriptor "
+ "for command line `%s` (call %u)",
+ cmdline, i + 1);
+ ok(is_short == expected_is_short,
+ "argpar_iter_next() sets an error with "
+ "the expected option type "
+ "for command line `%s` (call %u)",
+ cmdline, i + 1);
+ }
break;
}
cmdline, i + 1);
}
+ /*
ok(strcmp(expected_error, error) == 0,
"argpar_iter_next() sets the expected error string "
"for command line `%s`", cmdline);
diag("Expected: `%s`", expected_error);
diag("Got: `%s`", error);
}
+ */
argpar_item_destroy(item);
argpar_iter_destroy(iter);
- free(error);
+ argpar_error_destroy(error);
g_strfreev(argv);
}
static
void fail_tests(void)
{
- /* Unknown long option */
+
+ /* Unknown short option (space form) */
+ {
+ const struct argpar_opt_descr descrs[] = {
+ { 0, 'd', NULL, true },
+ ARGPAR_OPT_DESCR_SENTINEL
+ };
+
+ test_fail(
+ "-d salut -e -d meow",
+ ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 2, "-e", 0, false,
+ descrs);
+ }
+
+ /* Unknown short option (glued form) */
+ {
+ const struct argpar_opt_descr descrs[] = {
+ { 0, 'd', 0, true },
+ ARGPAR_OPT_DESCR_SENTINEL
+ };
+
+ test_fail(
+ "-dsalut -e -d meow",
+ ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 1, "-e", 0, false,
+ descrs);
+ }
+
+ /* Unknown long option (space form) */
+ {
+ const struct argpar_opt_descr descrs[] = {
+ { 0, '\0', "sink", true },
+ ARGPAR_OPT_DESCR_SENTINEL
+ };
+
+ test_fail(
+ "--sink party --food --sink impulse",
+ ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 2, "--food", 0, false,
+ descrs);
+ }
+
+ /* Unknown long option (equal form) */
+ {
+ const struct argpar_opt_descr descrs[] = {
+ { 0, '\0', "sink", true },
+ ARGPAR_OPT_DESCR_SENTINEL
+ };
+
+ test_fail(
+ "--sink=party --food --sink=impulse",
+ ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 1, "--food", 0, false,
+ descrs);
+ }
+
+ /* Unknown option before non-option argument */
{
const struct argpar_opt_descr descrs[] = {
{ 0, '\0', "thumb", true },
};
test_fail(
- "--thumb=party --meow",
- "While parsing argument #2 (`--meow`): Unknown option `--meow`",
+ "--thumb=party --food=18 bateau --thumb waves",
ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 1, "--food", 0, false,
descrs);
}
- /* Unknown short option */
+ /* Unknown option after non-option argument */
{
const struct argpar_opt_descr descrs[] = {
{ 0, '\0', "thumb", true },
};
test_fail(
- "--thumb=party -x",
- "While parsing argument #2 (`-x`): Unknown option `-x`",
+ "--thumb=party wound --food --thumb waves",
ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
+ 2, "--food", 0, false,
descrs);
}
};
test_fail(
- "--thumb",
- "While parsing argument #1 (`--thumb`): Missing required argument for option `--thumb`",
+ "allo --thumb",
ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ 1, NULL, 0, false,
descrs);
}
};
test_fail(
- "-k",
- "While parsing argument #1 (`-k`): Missing required argument for option `-k`",
+ "zoom heille -k",
ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ 2, NULL, 0, true,
descrs);
}
test_fail(
"-abc",
- "While parsing argument #1 (`-abc`): Missing required argument for option `-c`",
ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
+ 0, NULL, 2, true,
descrs);
}
};
test_fail(
- "--chevre=fromage",
- "While parsing argument #1 (`--chevre=fromage`): Unexpected argument for option `--chevre`",
+ "ambulance --chevre=fromage tar -cjv",
ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG,
+ 1, NULL, 0, false,
descrs);
}
}
int main(void)
{
- plan_tests(296);
+ plan_tests(309);
succeed_tests();
fail_tests();
return exit_status();