cmd: add functions to report option/arg errors to the public API
This commit is contained in:
240
cmd/arglist.c
240
cmd/arglist.c
@@ -65,6 +65,7 @@ struct b_arglist *b_arglist_create(void)
|
||||
static void move_to_subcommand(struct argv_parser *parser, struct b_command *cmd)
|
||||
{
|
||||
parser->cmd = cmd;
|
||||
parser->arglist->list_command = cmd;
|
||||
b_queue_iterator_begin(&cmd->b_arg, &parser->arg_it);
|
||||
parser->nr_values_cur_arg = 0;
|
||||
}
|
||||
@@ -84,48 +85,6 @@ static b_status set_opt(struct b_arglist *args, struct b_command_option *opt)
|
||||
return B_SUCCESS;
|
||||
}
|
||||
|
||||
static void report_invalid_arg_value(
|
||||
struct argv_parser *parser, struct b_command_option *opt,
|
||||
struct b_command_arg *arg, const char *value)
|
||||
{
|
||||
struct b_string *usage
|
||||
= z__b_command_default_usage_string(parser->cmd, opt);
|
||||
struct b_string *opt_string = b_string_create();
|
||||
|
||||
if (opt) {
|
||||
z__b_get_option_usage_string(opt, 0, opt_string);
|
||||
} else {
|
||||
z__b_get_arg_usage_string(arg, 0, opt_string);
|
||||
}
|
||||
|
||||
b_err("invalid value '" F_YELLOW "%s" F_RESET "' for '" F_YELLOW
|
||||
"%s" F_RESET "'.",
|
||||
value, b_string_ptr(opt_string));
|
||||
|
||||
if (opt) {
|
||||
b_i("'" F_YELLOW "%s" F_RESET
|
||||
"' accepts the following values for '" F_YELLOW "%s" F_RESET
|
||||
"':",
|
||||
b_string_ptr(opt_string), arg->arg_name);
|
||||
} else {
|
||||
b_i("'" F_YELLOW "%s" F_RESET "' accepts the following values:",
|
||||
b_string_ptr(opt_string));
|
||||
}
|
||||
|
||||
for (int i = 0; arg->arg_allowed_values[i]; i++) {
|
||||
b_printf(
|
||||
" * " F_GREEN "%s" F_RESET "\n",
|
||||
arg->arg_allowed_values[i]);
|
||||
}
|
||||
|
||||
b_printf("\n");
|
||||
b_i("usage: %s", b_string_ptr(usage));
|
||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET);
|
||||
|
||||
b_string_release(usage);
|
||||
b_string_release(opt_string);
|
||||
}
|
||||
|
||||
static b_status put_arg(
|
||||
struct b_arglist *args, struct b_command_arg *arg, const char *value)
|
||||
{
|
||||
@@ -209,70 +168,17 @@ static b_status put_opt_arg(
|
||||
return B_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void report_missing_args(
|
||||
struct argv_parser *parser, struct b_command_option *opt,
|
||||
struct b_command_arg *arg, int args_supplied)
|
||||
{
|
||||
struct b_string *usage
|
||||
= z__b_command_default_usage_string(parser->cmd, opt);
|
||||
struct b_string *opt_string = b_string_create();
|
||||
|
||||
if (opt) {
|
||||
z__b_get_option_usage_string(opt, 0, opt_string);
|
||||
} else {
|
||||
z__b_get_arg_usage_string(arg, 0, opt_string);
|
||||
}
|
||||
|
||||
char supplied_arg_str[64];
|
||||
if (args_supplied == 0) {
|
||||
snprintf(
|
||||
supplied_arg_str, sizeof supplied_arg_str,
|
||||
F_RED_BOLD "none" F_RESET " were provided");
|
||||
} else if (args_supplied == 1) {
|
||||
snprintf(
|
||||
supplied_arg_str, sizeof supplied_arg_str,
|
||||
"only " F_YELLOW_BOLD "%d" F_RESET " was provided",
|
||||
args_supplied);
|
||||
} else {
|
||||
snprintf(
|
||||
supplied_arg_str, sizeof supplied_arg_str,
|
||||
"only " F_YELLOW_BOLD "%d" F_RESET " were provided",
|
||||
args_supplied);
|
||||
}
|
||||
|
||||
char required_arg_count[64];
|
||||
switch (arg->arg_nr_values) {
|
||||
case B_ARG_1_OR_MORE_VALUES:
|
||||
snprintf(
|
||||
required_arg_count, sizeof required_arg_count,
|
||||
"one or more");
|
||||
break;
|
||||
default:
|
||||
snprintf(
|
||||
required_arg_count, sizeof required_arg_count, "%d",
|
||||
arg->arg_nr_values);
|
||||
}
|
||||
|
||||
b_err("argument '" F_YELLOW "%s" F_RESET "' requires " F_GREEN_BOLD
|
||||
"%s" F_RESET " `" F_YELLOW "%s" F_RESET "` values, but %s.\n\n",
|
||||
b_string_ptr(opt_string), required_arg_count, arg->arg_name,
|
||||
supplied_arg_str);
|
||||
b_i("usage: %s", b_string_ptr(usage));
|
||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||
|
||||
b_string_release(usage);
|
||||
b_string_release(opt_string);
|
||||
}
|
||||
|
||||
static void report_unexpected_arg(struct argv_parser *parser, const char *value)
|
||||
{
|
||||
struct b_string *usage
|
||||
= z__b_command_default_usage_string(parser->cmd, NULL);
|
||||
|
||||
b_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
|
||||
b_i("usage: %s", b_string_ptr(usage));
|
||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||
}
|
||||
#endif
|
||||
|
||||
static b_status check_required_args(struct argv_parser *parser)
|
||||
{
|
||||
@@ -295,12 +201,16 @@ static b_status check_required_args(struct argv_parser *parser)
|
||||
return B_SUCCESS;
|
||||
}
|
||||
|
||||
report_missing_args(parser, NULL, arg, parser->nr_values_cur_arg);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, B_COMMAND_INVALID_ID, arg->arg_id,
|
||||
parser->nr_values_cur_arg);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
if (parser->nr_values_cur_arg != arg->arg_nr_values) {
|
||||
report_missing_args(parser, NULL, arg, parser->nr_values_cur_arg);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, B_COMMAND_INVALID_ID, arg->arg_id,
|
||||
parser->nr_values_cur_arg);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
@@ -327,7 +237,7 @@ static b_status parse_arg(struct argv_parser *parser)
|
||||
struct b_command_arg, parser->arg_it.entry, arg_entry);
|
||||
|
||||
if (!arg) {
|
||||
report_unexpected_arg(parser, value);
|
||||
b_arglist_report_unexpected_arg(parser->arglist, value);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
@@ -336,7 +246,9 @@ static b_status parse_arg(struct argv_parser *parser)
|
||||
advance(parser);
|
||||
|
||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||
report_invalid_arg_value(parser, NULL, arg, value);
|
||||
b_arglist_report_invalid_arg_value(
|
||||
parser->arglist, B_COMMAND_INVALID_ID,
|
||||
arg->arg_id, value);
|
||||
}
|
||||
|
||||
if (B_ERR(status)) {
|
||||
@@ -471,7 +383,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
||||
nr_args_cur_opt++;
|
||||
|
||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||
report_invalid_arg_value(parser, NULL, arg, value);
|
||||
b_arglist_report_invalid_arg_value(
|
||||
parser->arglist, B_COMMAND_INVALID_ID,
|
||||
arg->arg_id, value);
|
||||
}
|
||||
|
||||
if (B_ERR(status)) {
|
||||
@@ -498,7 +412,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
||||
goto next_value;
|
||||
}
|
||||
|
||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, opt->opt_id, arg->arg_id,
|
||||
nr_args_cur_opt);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
@@ -509,7 +425,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, opt->opt_id, arg->arg_id,
|
||||
nr_args_cur_opt);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
next_value:
|
||||
@@ -594,7 +512,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
||||
advance(parser);
|
||||
|
||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||
report_invalid_arg_value(parser, NULL, arg, value);
|
||||
b_arglist_report_invalid_arg_value(
|
||||
parser->arglist, B_COMMAND_INVALID_ID,
|
||||
arg->arg_id, value);
|
||||
}
|
||||
|
||||
if (B_ERR(status)) {
|
||||
@@ -621,7 +541,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
||||
continue;
|
||||
}
|
||||
|
||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, opt->opt_id, arg->arg_id,
|
||||
nr_args_cur_opt);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
@@ -632,7 +554,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
||||
b_arglist_report_missing_args(
|
||||
parser->arglist, opt->opt_id, arg->arg_id,
|
||||
nr_args_cur_opt);
|
||||
return B_ERR_BAD_FORMAT;
|
||||
}
|
||||
}
|
||||
@@ -882,6 +806,8 @@ b_status b_arglist_option_get_value(
|
||||
return B_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
/************************ arglist iterator functions **************************/
|
||||
|
||||
static bool arglist_iterator_next(struct b_iterator *it)
|
||||
{
|
||||
return b_arglist_iterator_next((struct b_arglist_iterator *)it);
|
||||
@@ -1043,3 +969,103 @@ bool b_arglist_iterator_is_valid(const struct b_arglist_iterator *it)
|
||||
{
|
||||
return it->opt_id != B_COMMAND_INVALID_ID || it->value != NULL;
|
||||
}
|
||||
|
||||
/********************* arglist option iterator functions **********************/
|
||||
|
||||
static bool arglist_option_iterator_next(struct b_iterator *it)
|
||||
{
|
||||
return b_arglist_option_iterator_next(
|
||||
(struct b_arglist_option_iterator *)it);
|
||||
}
|
||||
|
||||
static bool arglist_option_iterator_is_valid(const struct b_iterator *it)
|
||||
{
|
||||
return b_arglist_option_iterator_is_valid(
|
||||
(const struct b_arglist_option_iterator *)it);
|
||||
}
|
||||
|
||||
static struct b_arglist_option *advance_to_next_opt2(
|
||||
struct b_arglist_option_iterator *it)
|
||||
{
|
||||
struct b_arglist_option *opt;
|
||||
|
||||
// b_btree_iterator_next(&it->_opt_it);
|
||||
|
||||
while (b_btree_iterator_is_valid(&it->_opt_it)) {
|
||||
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node);
|
||||
if (opt
|
||||
&& (opt->opt_id == it->_opt_filter
|
||||
|| it->_opt_filter == B_COMMAND_INVALID_ID)) {
|
||||
it->opt_id = opt->opt_id;
|
||||
return opt;
|
||||
}
|
||||
|
||||
b_btree_iterator_next(&it->_opt_it);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static b_iterator_ops option_it_ops = {
|
||||
.it_next = arglist_option_iterator_next,
|
||||
.it_is_valid = arglist_option_iterator_is_valid,
|
||||
};
|
||||
|
||||
int b_arglist_option_iterator_begin(
|
||||
const struct b_arglist *args, unsigned int opt_filter,
|
||||
struct b_arglist_option_iterator *it)
|
||||
{
|
||||
memset(it, 0x0, sizeof *it);
|
||||
|
||||
it->opt_id = B_COMMAND_INVALID_ID;
|
||||
|
||||
it->_base.it_ops = &it_ops;
|
||||
it->_opt_filter = opt_filter;
|
||||
|
||||
b_btree_iterator_begin(&args->list_options, &it->_opt_it);
|
||||
struct b_arglist_option *opt = NULL;
|
||||
struct b_arglist_value *val = NULL;
|
||||
|
||||
while (1) {
|
||||
if (!b_btree_iterator_is_valid(&it->_opt_it)) {
|
||||
opt = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node);
|
||||
if (opt
|
||||
&& (opt_filter == opt->opt_id
|
||||
|| opt_filter == B_COMMAND_INVALID_ID)) {
|
||||
break;
|
||||
}
|
||||
b_btree_iterator_next(&it->_opt_it);
|
||||
}
|
||||
|
||||
it->opt_id = opt->opt_id;
|
||||
it->opt = opt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool b_arglist_option_iterator_next(struct b_arglist_option_iterator *it)
|
||||
{
|
||||
struct b_arglist_option *opt;
|
||||
struct b_arglist_value *val;
|
||||
|
||||
b_btree_iterator_next(&it->_opt_it);
|
||||
opt = advance_to_next_opt2(it);
|
||||
if (!opt) {
|
||||
it->opt = NULL;
|
||||
it->opt_id = B_COMMAND_INVALID_ID;
|
||||
return false;
|
||||
}
|
||||
|
||||
it->opt = opt;
|
||||
it->opt_id = opt->opt_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool b_arglist_option_iterator_is_valid(const struct b_arglist_option_iterator *it)
|
||||
{
|
||||
return it->opt_id != B_COMMAND_INVALID_ID || it->opt != NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user