From 13ae36e10129c4d2dfb2da6b08faf5dd9065f4c3 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Fri, 26 Jul 2019 23:37:22 -0400 Subject: [PATCH] cli: use argpar for parsing help command's arguments All straightforward, except that there is a functional change as part of this patch. It was possible to pass multiple leftovers, and only the first one was considered. babeltrace2 help ctf tintin did the same as babeltrace2 help ctf It now prints a beautiful error: ./src/cli/babeltrace2 help ctf tintin ERROR: [Babeltrace CLI] (/home/smarchi/src/babeltrace/src/cli/babeltrace2.c:2564) Command-line error: retcode=1 CAUSED BY [Babeltrace CLI] (/home/smarchi/src/babeltrace/src/cli/babeltrace2-cfg-cli-args.c:1461) Extraneous command-line argument specified to `help` command: `tintin`. Change-Id: I2c8f8610004d60a0844d18c9d622037cc7c1c04c Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/1792 Tested-by: jenkins Reviewed-by: Philippe Proulx --- src/cli/babeltrace2-cfg-cli-args.c | 110 +++++++++++++++-------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 351ccaa5..975fc489 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -1394,13 +1394,13 @@ void print_help_usage(FILE *fp) } static -struct poptOption help_long_options[] = { - /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ - { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL }, - { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL }, - { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL }, - { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL }, - { NULL, 0, '\0', NULL, 0, NULL, NULL }, +const struct bt_argpar_opt_descr help_options[] = { + /* id, short_name, long_name, with_arg */ + { OPT_HELP, 'h', "help", false }, + { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false }, + { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false }, + { OPT_PLUGIN_PATH, '\0', "plugin-path", true }, + BT_ARGPAR_OPT_DESCR_SENTINEL }; /* @@ -1415,13 +1415,11 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], bool force_omit_home_plugin_path, const bt_value *initial_plugin_paths, int default_log_level) { - poptContext pc = NULL; - char *arg = NULL; - int opt; - int ret; + int ret, i; struct bt_config *cfg = NULL; - const char *leftover; + const char *leftover = NULL; char *plugin_name = NULL, *comp_cls_name = NULL; + struct bt_argpar_parse_ret argpar_parse_ret; *retcode = 0; cfg = bt_config_help_create(initial_plugin_paths, default_log_level); @@ -1437,54 +1435,63 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], } /* Parse options */ - pc = poptGetContext(NULL, argc, (const char **) argv, - help_long_options, POPT_CONTEXT_KEEP_FIRST); - if (!pc) { - BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context."); + argpar_parse_ret = bt_argpar_parse(argc, argv, help_options, true); + if (argpar_parse_ret.error) { + BT_CLI_LOGE_APPEND_CAUSE( + "While parsing `help` command's command-line arguments: %s", + argpar_parse_ret.error->str); goto error; } - poptReadDefaultConfig(pc, 0); + if (help_option_is_specified(&argpar_parse_ret)) { + print_help_usage(stdout); + *retcode = -1; + BT_OBJECT_PUT_REF_AND_RESET(cfg); + goto end; + } - while ((opt = poptGetNextOpt(pc)) > 0) { - arg = poptGetOptArg(pc); + for (i = 0; i < argpar_parse_ret.items->len; i++) { + struct bt_argpar_item *argpar_item = + g_ptr_array_index(argpar_parse_ret.items, i); - switch (opt) { - case OPT_PLUGIN_PATH: - if (bt_config_append_plugin_paths_check_setuid_setgid( - cfg->plugin_paths, arg)) { + if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) { + struct bt_argpar_item_opt *argpar_item_opt; + const char *arg; + argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; + arg = argpar_item_opt->arg; + + switch (argpar_item_opt->descr->id) { + case OPT_PLUGIN_PATH: + if (bt_config_append_plugin_paths_check_setuid_setgid( + cfg->plugin_paths, arg)) { + goto error; + } + break; + case OPT_OMIT_SYSTEM_PLUGIN_PATH: + cfg->omit_system_plugin_path = true; + break; + case OPT_OMIT_HOME_PLUGIN_PATH: + cfg->omit_home_plugin_path = true; + break; + default: + BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).", + argpar_item_opt->descr->id); goto error; } - break; - case OPT_OMIT_SYSTEM_PLUGIN_PATH: - cfg->omit_system_plugin_path = true; - break; - case OPT_OMIT_HOME_PLUGIN_PATH: - cfg->omit_home_plugin_path = true; - break; - case OPT_HELP: - print_help_usage(stdout); - *retcode = -1; - BT_OBJECT_PUT_REF_AND_RESET(cfg); - goto end; - default: - BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).", - opt); - goto error; - } + } else { + struct bt_argpar_item_non_opt *argpar_item_non_opt + = (struct bt_argpar_item_non_opt *) argpar_item; - free(arg); - arg = NULL; - } + if (leftover) { + BT_CLI_LOGE_APPEND_CAUSE("Extraneous command-line argument specified to `help` command: `%s`.", + argpar_item_non_opt->arg); + goto error; + } - /* Check for option parsing error */ - if (opt < -1) { - BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: `%s`.", - poptBadOption(pc, 0), poptStrerror(opt)); - goto error; + leftover = argpar_item_non_opt->arg; + } } - leftover = poptGetArg(pc); if (leftover) { plugin_comp_cls_names(leftover, NULL, &plugin_name, &comp_cls_name, @@ -1524,11 +1531,8 @@ end: g_free(plugin_name); g_free(comp_cls_name); - if (pc) { - poptFreeContext(pc); - } + bt_argpar_parse_ret_fini(&argpar_parse_ret); - free(arg); return cfg; } -- 2.34.1