X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fcli%2Fbabeltrace2-cfg-cli-args.c;h=e962ff361dfe48370f07ab5d33a0b09750300d02;hb=2459461134ddc04f5eca4251d780c4249d3f4020;hp=351ccaa50d72ec63ed9edbf2f9c50be66fb9d8fb;hpb=ca60bbc338aa007b446caf11d0abecb7bb7d2bcb;p=babeltrace.git diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 351ccaa5..e962ff36 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -34,7 +34,6 @@ #include #include #include "common/common.h" -#include #include #include #include "argpar/argpar.h" @@ -856,7 +855,7 @@ end: return ret; } -/* popt options */ +/* argpar options */ enum { OPT_NONE = 0, OPT_BASE_PARAMS, @@ -882,7 +881,6 @@ enum { OPT_INPUT_FORMAT, OPT_LIST, OPT_LOG_LEVEL, - OPT_NAME, OPT_NAMES, OPT_NO_DELTA, OPT_OMIT_HOME_PLUGIN_PATH, @@ -890,7 +888,6 @@ enum { OPT_OUTPUT, OPT_OUTPUT_FORMAT, OPT_PARAMS, - OPT_PATH, OPT_PLUGIN_PATH, OPT_RESET_BASE_PARAMS, OPT_RETRY_DURATION, @@ -898,7 +895,6 @@ enum { OPT_RUN_ARGS_0, OPT_STREAM_INTERSECTION, OPT_TIMERANGE, - OPT_URL, OPT_VERBOSE, OPT_VERSION, }; @@ -1394,13 +1390,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 +1411,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 *non_opt = 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,56 +1431,65 @@ 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; + } + + 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); - while ((opt = poptGetNextOpt(pc)) > 0) { - arg = poptGetOptArg(pc); + 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 (opt) { - case OPT_PLUGIN_PATH: - if (bt_config_append_plugin_paths_check_setuid_setgid( - cfg->plugin_paths, 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 (non_opt) { + 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; + non_opt = argpar_item_non_opt->arg; + } } - leftover = poptGetArg(pc); - if (leftover) { - plugin_comp_cls_names(leftover, NULL, + if (non_opt) { + plugin_comp_cls_names(non_opt, NULL, &plugin_name, &comp_cls_name, &cfg->cmd_data.help.cfg_component->type); if (plugin_name && comp_cls_name) { @@ -1501,7 +1504,7 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], /* Fall back to plugin help */ g_string_assign( cfg->cmd_data.help.cfg_component->plugin_name, - leftover); + non_opt); } } else { print_help_usage(stdout); @@ -1524,11 +1527,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; } @@ -1555,14 +1555,14 @@ void print_query_usage(FILE *fp) } static -struct poptOption query_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 }, - { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, 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 query_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_PARAMS, 'p', "params", true }, + { OPT_PLUGIN_PATH, '\0', "plugin-path", true }, + BT_ARGPAR_OPT_DESCR_SENTINEL }; /* @@ -1578,14 +1578,13 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[], 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 *component_class_spec = NULL; + const char *query_object = NULL; bt_value *params; GString *error_str = NULL; + struct bt_argpar_parse_ret argpar_parse_ret; params = bt_value_null; bt_value_get_ref(bt_value_null); @@ -1610,110 +1609,106 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[], } /* Parse options */ - pc = poptGetContext(NULL, argc, (const char **) argv, - query_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, query_options, true); + if (argpar_parse_ret.error) { + BT_CLI_LOGE_APPEND_CAUSE( + "While parsing `query` 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_query_usage(stdout); + *retcode = -1; + BT_OBJECT_PUT_REF_AND_RESET(cfg); + goto end; + } + + 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); - while ((opt = poptGetNextOpt(pc)) > 0) { - arg = poptGetOptArg(pc); + if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) { + struct bt_argpar_item_opt *argpar_item_opt = + (struct bt_argpar_item_opt *) argpar_item; + const char *arg = argpar_item_opt->arg; - switch (opt) { - case OPT_PLUGIN_PATH: - if (bt_config_append_plugin_paths_check_setuid_setgid( - cfg->plugin_paths, 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; + case OPT_PARAMS: + { + bt_value_put_ref(params); + params = cli_value_from_arg(arg, error_str); + if (!params) { + BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n %s", + error_str->str); + goto error; + } + 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_PARAMS: - { - bt_value_put_ref(params); - params = cli_value_from_arg(arg, error_str); - if (!params) { - BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n %s", - error_str->str); + } else { + struct bt_argpar_item_non_opt *argpar_item_non_opt + = (struct bt_argpar_item_non_opt *) argpar_item; + + /* + * We need exactly two non-option arguments + * which are the mandatory component class + * specification and query object. + */ + if (!component_class_spec) { + component_class_spec = argpar_item_non_opt->arg; + } else if (!query_object) { + query_object = argpar_item_non_opt->arg; + } else { + BT_CLI_LOGE_APPEND_CAUSE("Extraneous command-line argument specified to `query` command: `%s`.", + argpar_item_non_opt->arg); goto error; } - break; - } - case OPT_HELP: - print_query_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; } - - free(arg); - arg = NULL; - } - - /* 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; } - /* - * We need exactly two leftover arguments which are the - * mandatory component class specification and query object. - */ - leftover = poptGetArg(pc); - if (leftover) { - cfg->cmd_data.query.cfg_component = - bt_config_component_from_arg(leftover, - default_log_level); - if (!cfg->cmd_data.query.cfg_component) { - BT_CLI_LOGE_APPEND_CAUSE("Invalid format for component class specification:\n %s", - leftover); - goto error; - } - - BT_ASSERT(params); - BT_OBJECT_MOVE_REF(cfg->cmd_data.query.cfg_component->params, - params); - } else { + if (!component_class_spec || !query_object) { print_query_usage(stdout); *retcode = -1; BT_OBJECT_PUT_REF_AND_RESET(cfg); goto end; } - leftover = poptGetArg(pc); - if (leftover) { - if (strlen(leftover) == 0) { - BT_CLI_LOGE_APPEND_CAUSE("Invalid empty object."); - goto error; - } - - g_string_assign(cfg->cmd_data.query.object, leftover); - } else { - print_query_usage(stdout); - *retcode = -1; - BT_OBJECT_PUT_REF_AND_RESET(cfg); - goto end; + cfg->cmd_data.query.cfg_component = + bt_config_component_from_arg(component_class_spec, + default_log_level); + if (!cfg->cmd_data.query.cfg_component) { + BT_CLI_LOGE_APPEND_CAUSE("Invalid format for component class specification:\n %s", + component_class_spec); + goto error; } - leftover = poptGetArg(pc); - if (leftover) { - BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.", leftover); + BT_ASSERT(params); + BT_OBJECT_MOVE_REF(cfg->cmd_data.query.cfg_component->params, params); + + if (strlen(query_object) == 0) { + BT_CLI_LOGE_APPEND_CAUSE("Invalid empty object."); goto error; } + g_string_assign(cfg->cmd_data.query.object, query_object); + if (append_home_and_system_plugin_paths_cfg(cfg)) { goto error; } @@ -1725,16 +1720,13 @@ error: BT_OBJECT_PUT_REF_AND_RESET(cfg); end: - if (pc) { - poptFreeContext(pc); - } + bt_argpar_parse_ret_fini(&argpar_parse_ret); if (error_str) { g_string_free(error_str, TRUE); } bt_value_put_ref(params); - free(arg); return cfg; } @@ -1761,13 +1753,13 @@ void print_list_plugins_usage(FILE *fp) } static -struct poptOption list_plugins_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 list_plugins_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 }; /* @@ -1782,12 +1774,9 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[], bool force_omit_home_plugin_path, const bt_value *initial_plugin_paths) { - poptContext pc = NULL; - char *arg = NULL; - int opt; - int ret; + int ret, i; struct bt_config *cfg = NULL; - const char *leftover; + struct bt_argpar_parse_ret argpar_parse_ret = { 0 }; *retcode = 0; cfg = bt_config_list_plugins_create(initial_plugin_paths); @@ -1803,19 +1792,40 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[], } /* Parse options */ - pc = poptGetContext(NULL, argc, (const char **) argv, - list_plugins_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, list_plugins_options, true); + if (argpar_parse_ret.error) { + BT_CLI_LOGE_APPEND_CAUSE( + "While parsing `list-plugins` 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_list_plugins_usage(stdout); + *retcode = -1; + BT_OBJECT_PUT_REF_AND_RESET(cfg); + goto end; + } + + 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); + struct bt_argpar_item_opt *argpar_item_opt; + const char *arg; + + if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) { + struct bt_argpar_item_non_opt *argpar_item_non_opt + = (struct bt_argpar_item_non_opt *) argpar_item; + + BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.", + argpar_item_non_opt->arg); + goto error; + } - while ((opt = poptGetNextOpt(pc)) > 0) { - arg = poptGetOptArg(pc); + argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; + arg = argpar_item_opt->arg; - switch (opt) { + switch (argpar_item_opt->descr->id) { case OPT_PLUGIN_PATH: if (bt_config_append_plugin_paths_check_setuid_setgid( cfg->plugin_paths, arg)) { @@ -1828,32 +1838,11 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[], case OPT_OMIT_HOME_PLUGIN_PATH: cfg->omit_home_plugin_path = true; break; - case OPT_HELP: - print_list_plugins_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); + argpar_item_opt->descr->id); goto error; } - - free(arg); - arg = NULL; - } - - /* 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 = poptGetArg(pc); - if (leftover) { - BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.", leftover); - goto error; } if (append_home_and_system_plugin_paths_cfg(cfg)) { @@ -1867,11 +1856,8 @@ error: BT_OBJECT_PUT_REF_AND_RESET(cfg); end: - if (pc) { - poptFreeContext(pc); - } + bt_argpar_parse_ret_fini(&argpar_parse_ret); - free(arg); return cfg; } @@ -1889,19 +1875,15 @@ void print_run_usage(FILE *fp) fprintf(fp, " for all the following components until\n"); fprintf(fp, " --reset-base-params is encountered\n"); fprintf(fp, " (see the expected format of PARAMS below)\n"); - fprintf(fp, " -c, --component=[NAME:]TYPE.PLUGIN.CLS\n"); + fprintf(fp, " -c, --component=NAME:TYPE.PLUGIN.CLS\n"); fprintf(fp, " Instantiate the component class CLS of type\n"); fprintf(fp, " TYPE (`source`, `filter`, or `sink`) found\n"); fprintf(fp, " in the plugin PLUGIN, add it to the graph,\n"); - fprintf(fp, " and optionally name it NAME (you can also\n"); - fprintf(fp, " specify the name with --name)\n"); + fprintf(fp, " and name it NAME"); fprintf(fp, " -x, --connect=CONNECTION Connect two created components (see the\n"); fprintf(fp, " expected format of CONNECTION below)\n"); fprintf(fp, " -l, --log-level=LVL Set the log level of the current component to LVL\n"); fprintf(fp, " (`N`, `V`, `D`, `I`, `W`, `E`, or `F`)\n"); - fprintf(fp, " -n, --name=NAME Set the name of the current component\n"); - fprintf(fp, " to NAME (must be unique amongst all the\n"); - fprintf(fp, " names of the created components)\n"); fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " (~/.local/lib/babeltrace2/plugins)\n"); fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); @@ -1926,8 +1908,8 @@ void print_run_usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "UPSTREAM and DOWNSTREAM are names of the upstream and downstream\n"); fprintf(fp, "components to connect together. You must escape the following characters\n\n"); - fprintf(fp, "with `\\`: `\\`, `.`, and `:`. You can set the name of the current\n"); - fprintf(fp, "component with the --name option.\n"); + fprintf(fp, "with `\\`: `\\`, `.`, and `:`. You must set the name of the current\n"); + fprintf(fp, "component using the NAME prefix of the --component option.\n"); fprintf(fp, "\n"); fprintf(fp, "UPSTREAM-PORT and DOWNSTREAM-PORT are optional globbing patterns to\n"); fprintf(fp, "identify the upstream and downstream ports to use for the connection.\n"); @@ -1969,8 +1951,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], const bt_value *initial_plugin_paths, int default_log_level) { struct bt_config_component *cur_cfg_comp = NULL; - enum bt_config_component_dest cur_cfg_comp_dest = - BT_CONFIG_COMPONENT_DEST_UNKNOWN; bt_value *cur_base_params = NULL; int ret = 0; struct bt_config *cfg = NULL; @@ -1989,7 +1969,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], { OPT_CONNECT, 'x', "connect", true }, { OPT_HELP, 'h', "help", false }, { OPT_LOG_LEVEL, 'l', "log-level", true }, - { OPT_NAME, 'n', "name", true }, { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false }, { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false }, { OPT_PARAMS, 'p', "params", true }, @@ -2066,7 +2045,7 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], struct bt_argpar_item_opt *argpar_item_opt; const char *arg; - /* This command does not accept leftover arguments. */ + /* This command does not accept non-option arguments.*/ if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) { struct bt_argpar_item_non_opt *argpar_nonopt_item = (struct bt_argpar_item_non_opt *) argpar_item; @@ -2094,18 +2073,9 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], break; case OPT_COMPONENT: { - enum bt_config_component_dest new_dest; - - if (cur_cfg_comp) { - ret = add_run_cfg_comp_check_name(cfg, - cur_cfg_comp, cur_cfg_comp_dest, - instance_names); - BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); - if (ret) { - goto error; - } - } + enum bt_config_component_dest dest; + BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); cur_cfg_comp = bt_config_component_from_arg(arg, default_log_level); if (!cur_cfg_comp) { @@ -2116,13 +2086,13 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], switch (cur_cfg_comp->type) { case BT_COMPONENT_CLASS_TYPE_SOURCE: - new_dest = BT_CONFIG_COMPONENT_DEST_SOURCE; + dest = BT_CONFIG_COMPONENT_DEST_SOURCE; break; case BT_COMPONENT_CLASS_TYPE_FILTER: - new_dest = BT_CONFIG_COMPONENT_DEST_FILTER; + dest = BT_CONFIG_COMPONENT_DEST_FILTER; break; case BT_COMPONENT_CLASS_TYPE_SINK: - new_dest = BT_CONFIG_COMPONENT_DEST_SINK; + dest = BT_CONFIG_COMPONENT_DEST_SINK; break; default: abort(); @@ -2136,7 +2106,13 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], goto error; } - cur_cfg_comp_dest = new_dest; + ret = add_run_cfg_comp_check_name(cfg, + cur_cfg_comp, dest, + instance_names); + if (ret) { + goto error; + } + break; } case OPT_PARAMS: @@ -2169,15 +2145,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], BT_OBJECT_MOVE_REF(cur_cfg_comp->params, params_to_set); break; } - case OPT_NAME: - if (!cur_cfg_comp) { - BT_CLI_LOGE_APPEND_CAUSE("Cannot set the name of unavailable component:\n %s", - arg); - goto error; - } - - g_string_assign(cur_cfg_comp->instance_name, arg); - break; case OPT_LOG_LEVEL: if (!cur_cfg_comp) { BT_CLI_LOGE_APPEND_CAUSE("Cannot set the log level of unavailable component:\n %s", @@ -2251,15 +2218,7 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], } } - /* Add current component */ - if (cur_cfg_comp) { - ret = add_run_cfg_comp_check_name(cfg, cur_cfg_comp, - cur_cfg_comp_dest, instance_names); - BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); - if (ret) { - goto error; - } - } + BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); if (cfg->cmd_data.run.sources->len == 0) { BT_CLI_LOGE_APPEND_CAUSE("Incomplete graph: no source component."); @@ -2360,21 +2319,15 @@ void print_convert_usage(FILE *fp) fprintf(fp, " TYPE (`source`, `filter`, or `sink`) found\n"); fprintf(fp, " in the plugin PLUGIN, add it to the\n"); fprintf(fp, " conversion graph, and optionally name it\n"); - fprintf(fp, " NAME (you can also specify the name with\n"); - fprintf(fp, " --name)\n"); + fprintf(fp, " NAME\n"); fprintf(fp, " -l, --log-level=LVL Set the log level of the current component to LVL\n"); fprintf(fp, " (`N`, `V`, `D`, `I`, `W`, `E`, or `F`)\n"); - fprintf(fp, " --name=NAME Set the name of the current component\n"); - fprintf(fp, " to NAME (must be unique amongst all the\n"); - fprintf(fp, " names of the created components)\n"); fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " (~/.local/lib/babeltrace2/plugins)\n"); fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); fprintf(fp, " -p, --params=PARAMS Add initialization parameters PARAMS to the\n"); fprintf(fp, " current component (see the expected format\n"); fprintf(fp, " of PARAMS below)\n"); - fprintf(fp, " -P, --path=PATH Set the `path` string parameter of the\n"); - fprintf(fp, " current component to PATH\n"); fprintf(fp, " --plugin-path=PATH[:PATH]... Add PATH to the list of paths from which\n"); fprintf(fp, " dynamic plugins can be loaded\n"); fprintf(fp, " --retry-duration=DUR When babeltrace2(1) needs to retry to run\n"); @@ -2389,8 +2342,6 @@ void print_convert_usage(FILE *fp) fprintf(fp, " formatted for `xargs -0`, and quit\n"); fprintf(fp, " --stream-intersection Only process events when all streams\n"); fprintf(fp, " are active\n"); - fprintf(fp, " -u, --url=URL Set the `url` string parameter of the\n"); - fprintf(fp, " current component to URL\n"); fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "Implicit `source.ctf.fs` component options:\n"); @@ -2506,7 +2457,6 @@ const struct bt_argpar_opt_descr convert_options[] = { { OPT_HELP, 'h', "help", false }, { OPT_INPUT_FORMAT, 'i', "input-format", true }, { OPT_LOG_LEVEL, 'l', "log-level", true }, - { OPT_NAME, '\0', "name", true }, { OPT_NAMES, 'n', "names", true }, { OPT_DEBUG_INFO, '\0', "debug-info", false }, { OPT_NO_DELTA, '\0', "no-delta", false }, @@ -2515,14 +2465,12 @@ const struct bt_argpar_opt_descr convert_options[] = { { OPT_OUTPUT, 'w', "output", true }, { OPT_OUTPUT_FORMAT, 'o', "output-format", true }, { OPT_PARAMS, 'p', "params", true }, - { OPT_PATH, 'P', "path", true }, { OPT_PLUGIN_PATH, '\0', "plugin-path", true }, { OPT_RETRY_DURATION, '\0', "retry-duration", true }, { OPT_RUN_ARGS, '\0', "run-args", false }, { OPT_RUN_ARGS_0, '\0', "run-args-0", false }, { OPT_STREAM_INTERSECTION, '\0', "stream-intersection", false }, { OPT_TIMERANGE, '\0', "timerange", true }, - { OPT_URL, 'u', "url", true }, { OPT_VERBOSE, 'v', "verbose", false }, BT_ARGPAR_OPT_DESCR_SENTINEL }; @@ -2615,27 +2563,31 @@ int append_run_args_for_implicit_component( { int ret = 0; size_t i; + GString *component_arg_for_run = NULL; if (!impl_args->exists) { goto end; } - if (bt_value_array_append_string_element(run_args, "--component")) { + component_arg_for_run = g_string_new(NULL); + if (!component_arg_for_run) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, impl_args->comp_arg->str)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + /* Build the full `name:type.plugin.cls`. */ + BT_ASSERT(!strchr(impl_args->name_arg->str, '\\')); + BT_ASSERT(!strchr(impl_args->name_arg->str, ':')); + g_string_printf(component_arg_for_run, "%s:%s", + impl_args->name_arg->str, impl_args->comp_arg->str); - if (bt_value_array_append_string_element(run_args, "--name")) { + if (bt_value_array_append_string_element(run_args, "--component")) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, impl_args->name_arg->str)) { + if (bt_value_array_append_string_element(run_args, + component_arg_for_run->str)) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } @@ -2679,6 +2631,10 @@ error: ret = -1; end: + if (component_arg_for_run) { + g_string_free(component_arg_for_run, TRUE); + } + return ret; } @@ -3003,142 +2959,45 @@ int append_implicit_component_extra_param(struct implicit_component_args *args, return append_string_parameter_to_args(args->extra_params, key, value); } +/* + * Escapes `.`, `:`, and `\` of `input` with `\`. + */ static -int convert_append_name_param(enum bt_config_component_dest dest, - GString *cur_name, GString *cur_name_prefix, - bt_value *run_args, - bt_value *all_names, - GList **source_names, GList **filter_names, - GList **sink_names) +GString *escape_dot_colon(const char *input) { - int ret = 0; - - if (cur_name_prefix->len > 0) { - /* We're after a --component option */ - GString *name = NULL; - bool append_name_opt = false; + GString *output = g_string_new(NULL); + const char *ch; - if (cur_name->len == 0) { - /* - * No explicit name was provided for the user - * component. - */ - name = get_component_auto_name(cur_name_prefix->str, - all_names); - append_name_opt = true; - } else { - /* - * An explicit name was provided for the user - * component. - */ - if (bt_value_map_has_entry(all_names, - cur_name->str)) { - BT_CLI_LOGE_APPEND_CAUSE("Duplicate component instance name:\n %s", - cur_name->str); - goto error; - } + if (!output) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto end; + } - name = g_string_new(cur_name->str); + for (ch = input; *ch != '\0'; ch++) { + if (*ch == '\\' || *ch == '.' || *ch == ':') { + g_string_append_c(output, '\\'); } - if (!name) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + g_string_append_c(output, *ch); + } - /* - * Remember this name globally, for the uniqueness of - * all component names. - */ - if (bt_value_map_insert_entry(all_names, name->str, bt_value_null)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } +end: + return output; +} - /* - * Append the --name option if necessary. - */ - if (append_name_opt) { - if (bt_value_array_append_string_element(run_args, "--name")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - - if (bt_value_array_append_string_element(run_args, name->str)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - } - - /* - * Remember this name specifically for the type of the - * component. This is to create connection arguments. - */ - switch (dest) { - case BT_CONFIG_COMPONENT_DEST_SOURCE: - *source_names = g_list_append(*source_names, name); - break; - case BT_CONFIG_COMPONENT_DEST_FILTER: - *filter_names = g_list_append(*filter_names, name); - break; - case BT_CONFIG_COMPONENT_DEST_SINK: - *sink_names = g_list_append(*sink_names, name); - break; - default: - abort(); - } - - g_string_assign(cur_name_prefix, ""); - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - -/* - * Escapes `.`, `:`, and `\` of `input` with `\`. - */ -static -GString *escape_dot_colon(const char *input) -{ - GString *output = g_string_new(NULL); - const char *ch; - - if (!output) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto end; - } - - for (ch = input; *ch != '\0'; ch++) { - if (*ch == '\\' || *ch == '.' || *ch == ':') { - g_string_append_c(output, '\\'); - } - - g_string_append_c(output, *ch); - } - -end: - return output; -} - -/* - * Appends a --connect option to a list of arguments. `upstream_name` - * and `downstream_name` are escaped with escape_dot_colon() in this - * function. - */ -static -int append_connect_arg(bt_value *run_args, - const char *upstream_name, const char *downstream_name) -{ - int ret = 0; - GString *e_upstream_name = escape_dot_colon(upstream_name); - GString *e_downstream_name = escape_dot_colon(downstream_name); - GString *arg = g_string_new(NULL); +/* + * Appends a --connect option to a list of arguments. `upstream_name` + * and `downstream_name` are escaped with escape_dot_colon() in this + * function. + */ +static +int append_connect_arg(bt_value *run_args, + const char *upstream_name, const char *downstream_name) +{ + int ret = 0; + GString *e_upstream_name = escape_dot_colon(upstream_name); + GString *e_downstream_name = escape_dot_colon(downstream_name); + GString *arg = g_string_new(NULL); if (!e_upstream_name || !e_downstream_name || !arg) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); @@ -3317,13 +3176,27 @@ end: } /* - * Create `struct implicit_component_args` structures for each of the source - * components we identified. Add them to `component_args`. + * Create `struct implicit_component_args` structures for each of the + * source components we identified. Add them to `component_args`. + * + * `non_opt_params` is an array where each element is an array of + * strings containing all the arguments to `--params` that apply to the + * non-option argument at the same index. For example, if, for a + * non-option argument, the following `--params` options applied: + * + * --params=a=2 --params=b=3,c=4 + * + * its entry in `non_opt_params` would contain + * + * ["a=2", "b=3,c=4"] */ static -void create_implicit_component_args_from_auto_discovered_sources( - const struct auto_source_discovery *auto_disc, GPtrArray *component_args) +int create_implicit_component_args_from_auto_discovered_sources( + const struct auto_source_discovery *auto_disc, + const bt_value *non_opt_params, + const bt_value *non_opt_loglevels, + GPtrArray *component_args) { gchar *cc_name = NULL; struct implicit_component_args *comp = NULL; @@ -3335,36 +3208,123 @@ void create_implicit_component_args_from_auto_discovered_sources( for (i = 0; i < len; i++) { struct auto_source_discovery_result *res = g_ptr_array_index(auto_disc->results, i); + uint64_t orig_indices_i, orig_indices_count; g_free(cc_name); cc_name = g_strdup_printf("source.%s.%s", res->plugin_name, res->source_cc_name); if (!cc_name) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto end; + goto error; } comp = create_implicit_component_args(cc_name); if (!comp) { - goto end; + goto error; + } + + /* + * Append parameters and log levels of all the + * non-option arguments that contributed to this + * component instance coming into existence. + */ + orig_indices_count = bt_value_array_get_size(res->original_input_indices); + for (orig_indices_i = 0; orig_indices_i < orig_indices_count; orig_indices_i++) { + const bt_value *orig_idx_value = + bt_value_array_borrow_element_by_index( + res->original_input_indices, orig_indices_i); + uint64_t orig_idx = bt_value_integer_unsigned_get(orig_idx_value); + const bt_value *params_array = + bt_value_array_borrow_element_by_index_const( + non_opt_params, orig_idx); + uint64_t params_i, params_count; + const bt_value *loglevel_value; + + params_count = bt_value_array_get_size(params_array); + for (params_i = 0; params_i < params_count; params_i++) { + const bt_value *params_value = + bt_value_array_borrow_element_by_index_const( + params_array, params_i); + const char *params = bt_value_string_get(params_value); + bt_value_array_append_element_status append_status; + + append_status = bt_value_array_append_string_element( + comp->extra_params, "--params"); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + + append_status = bt_value_array_append_string_element( + comp->extra_params, params); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + } + + loglevel_value = bt_value_array_borrow_element_by_index_const( + non_opt_loglevels, orig_idx); + if (bt_value_get_type(loglevel_value) == BT_VALUE_TYPE_STRING) { + const char *loglevel = bt_value_string_get(loglevel_value); + bt_value_array_append_element_status append_status; + + append_status = bt_value_array_append_string_element( + comp->extra_params, "--log-level"); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + + append_status = bt_value_array_append_string_element( + comp->extra_params, loglevel); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + } } status = append_parameter_to_args(comp->extra_params, "inputs", res->inputs); if (status != 0) { - goto end; + goto error; } g_ptr_array_add(component_args, comp); comp = NULL; } + status = 0; + goto end; + +error: + status = -1; + end: g_free(cc_name); if (comp) { destroy_implicit_component_args(comp); } + + return status; } +/* + * As we iterate the arguments to the convert command, this tracks what is the + * type of the current item, to which some contextual options (e.g. --params) + * apply to. + */ +enum convert_current_item_type { + /* There is no current item. */ + CONVERT_CURRENT_ITEM_TYPE_NONE, + + /* Current item is a component. */ + CONVERT_CURRENT_ITEM_TYPE_COMPONENT, + + /* Current item is a non-option argument. */ + CONVERT_CURRENT_ITEM_TYPE_NON_OPT, +}; + /* * Creates a Babeltrace config object from the arguments of a convert * command. @@ -3377,8 +3337,8 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], bool force_omit_home_plugin_path, const bt_value *initial_plugin_paths, int *default_log_level) { - enum bt_config_component_dest cur_comp_dest = - BT_CONFIG_COMPONENT_DEST_UNKNOWN; + enum convert_current_item_type current_item_type = + CONVERT_CURRENT_ITEM_TYPE_NONE; int ret = 0; struct bt_config *cfg = NULL; bool got_input_format_opt = false; @@ -3386,8 +3346,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], bool trimmer_has_begin = false; bool trimmer_has_end = false; bool stream_intersection_mode = false; - GString *cur_name = NULL; - GString *cur_name_prefix = NULL; bool print_run_args = false; bool print_run_args_0 = false; bool print_ctf_metadata = false; @@ -3396,7 +3354,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], GList *source_names = NULL; GList *filter_names = NULL; GList *sink_names = NULL; - bt_value *leftovers = NULL; + bt_value *non_opts = NULL; + bt_value *non_opt_params = NULL; + bt_value *non_opt_loglevels = NULL; struct implicit_component_args implicit_ctf_output_args = { 0 }; struct implicit_component_args implicit_lttng_live_args = { 0 }; struct implicit_component_args implicit_dummy_args = { 0 }; @@ -3412,6 +3372,8 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], struct auto_source_discovery auto_disc = { NULL }; GString *auto_disc_comp_name = NULL; struct bt_argpar_parse_ret argpar_parse_ret = { 0 }; + GString *name_gstr = NULL; + GString *component_arg_for_run = NULL; /* * Array of `struct implicit_component_args *` created for the sources @@ -3486,25 +3448,31 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - cur_name = g_string_new(NULL); - if (!cur_name) { + component_arg_for_run = g_string_new(NULL); + if (!component_arg_for_run) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - cur_name_prefix = g_string_new(NULL); - if (!cur_name_prefix) { + ret = append_env_var_plugin_paths(plugin_paths); + if (ret) { + goto error; + } + + non_opts = bt_value_array_create(); + if (!non_opts) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - ret = append_env_var_plugin_paths(plugin_paths); - if (ret) { + non_opt_params = bt_value_array_create(); + if (!non_opt_params) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - leftovers = bt_value_array_create(); - if (!leftovers) { + non_opt_loglevels = bt_value_array_create(); + if (!non_opt_loglevels) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } @@ -3530,10 +3498,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], * First pass: collect all arguments which need to be passed * as is to the run command. This pass can also add --name * arguments if needed to automatically name unnamed component - * instances. Also it does the following transformations: - * - * --path=PATH -> --params=path="PATH" - * --url=URL -> --params=url="URL" + * instances. * * Also it appends the plugin paths of --plugin-path to * `plugin_paths`. @@ -3562,250 +3527,288 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], char *comp_cls_name = NULL; const char *arg; - if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_OPT) { - continue; - } + if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) { + argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; + arg = argpar_item_opt->arg; - argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; - arg = argpar_item_opt->arg; + switch (argpar_item_opt->descr->id) { + case OPT_COMPONENT: + { + bt_component_class_type type; - switch (argpar_item_opt->descr->id) { - case OPT_COMPONENT: - { - bt_component_class_type type; - const char *type_prefix; + current_item_type = CONVERT_CURRENT_ITEM_TYPE_COMPONENT; - /* Append current component's name if needed */ - ret = convert_append_name_param(cur_comp_dest, cur_name, - cur_name_prefix, run_args, all_names, - &source_names, &filter_names, &sink_names); - if (ret) { - goto error; - } + /* Parse the argument */ + plugin_comp_cls_names(arg, &name, &plugin_name, + &comp_cls_name, &type); + if (!plugin_name || !comp_cls_name) { + BT_CLI_LOGE_APPEND_CAUSE( + "Invalid format for --component option's argument:\n %s", + arg); + goto error; + } - /* Parse the argument */ - plugin_comp_cls_names(arg, &name, &plugin_name, - &comp_cls_name, &type); - if (!plugin_name || !comp_cls_name) { - BT_CLI_LOGE_APPEND_CAUSE( - "Invalid format for --component option's argument:\n %s", - arg); - goto error; - } + if (name) { + /* + * Name was given by the user, verify it isn't + * taken. + */ + if (bt_value_map_has_entry(all_names, name)) { + BT_CLI_LOGE_APPEND_CAUSE( + "Duplicate component instance name:\n %s", + name); + goto error; + } - if (name) { - g_string_assign(cur_name, name); - } else { - g_string_assign(cur_name, ""); - } + name_gstr = g_string_new(name); + if (!name_gstr) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - switch (type) { - case BT_COMPONENT_CLASS_TYPE_SOURCE: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE; - type_prefix = "source"; - break; - case BT_COMPONENT_CLASS_TYPE_FILTER: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_FILTER; - type_prefix = "filter"; - break; - case BT_COMPONENT_CLASS_TYPE_SINK: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK; - type_prefix = "sink"; - break; - default: - abort(); - } + g_string_assign(component_arg_for_run, arg); + } else { + /* Name not given by user, generate one. */ + name_gstr = get_component_auto_name(arg, all_names); + if (!name_gstr) { + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--component")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + g_string_printf(component_arg_for_run, "%s:%s", + name_gstr->str, arg); + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--component")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - g_string_assign(cur_name_prefix, ""); - g_string_append_printf(cur_name_prefix, "%s.%s.%s", - type_prefix, plugin_name, comp_cls_name); - free(name); - free(plugin_name); - free(comp_cls_name); - name = NULL; - plugin_name = NULL; - comp_cls_name = NULL; - break; - } - case OPT_PARAMS: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set parameters:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, + component_arg_for_run->str)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--params")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + /* + * Remember this name globally, for the uniqueness of + * all component names. + */ + if (bt_value_map_insert_entry(all_names, + name_gstr->str, bt_value_null)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - break; - case OPT_PATH: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set `path` parameter:\n %s", - arg); - goto error; + /* + * Remember this name specifically for the type of the + * component. This is to create connection arguments. + * + * The list takes ownership of `name_gstr`. + */ + switch (type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + source_names = g_list_append(source_names, name_gstr); + break; + case BT_COMPONENT_CLASS_TYPE_FILTER: + filter_names = g_list_append(filter_names, name_gstr); + break; + case BT_COMPONENT_CLASS_TYPE_SINK: + sink_names = g_list_append(sink_names, name_gstr); + break; + default: + abort(); + } + name_gstr = NULL; + + free(name); + free(plugin_name); + free(comp_cls_name); + name = NULL; + plugin_name = NULL; + comp_cls_name = NULL; + break; } + case OPT_PARAMS: + if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_COMPONENT) { + /* + * The current item is a component (--component option), + * pass it directly to the run args. + */ + if (bt_value_array_append_string_element(run_args, + "--params")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (append_string_parameter_to_args(run_args, "path", arg)) { - goto error; - } - break; - case OPT_URL: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set `url` parameter:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_NON_OPT) { + /* + * The current item is a + * non-option argument, record + * it in `non_opt_params`. + */ + bt_value *array; + uint64_t idx = bt_value_array_get_size(non_opt_params) - 1; + array = bt_value_array_borrow_element_by_index(non_opt_params, idx); + bt_value_array_append_string_element(array, arg); + } else { + BT_CLI_LOGE_APPEND_CAUSE( + "No current component (--component option) or non-option argument of which to set parameters:\n %s", + arg); + goto error; + } + break; + case OPT_LOG_LEVEL: + if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_COMPONENT) { + if (bt_value_array_append_string_element(run_args, "--log-level")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (append_string_parameter_to_args(run_args, "url", arg)) { - goto error; - } - break; - case OPT_NAME: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component to name:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_NON_OPT) { + uint64_t idx = bt_value_array_get_size(non_opt_loglevels) - 1; + bt_value *log_level_str_value; - if (bt_value_array_append_string_element(run_args, "--name")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + log_level_str_value = bt_value_string_create_init(arg); + if (!log_level_str_value) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_set_element_by_index(non_opt_loglevels, idx, + log_level_str_value)) { + bt_value_put_ref(log_level_str_value); + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else { + BT_CLI_LOGE_APPEND_CAUSE( + "No current component (--component option) or non-option argument to assign a log level to:\n %s", + arg); + goto error; + } - g_string_assign(cur_name, arg); - break; - case OPT_LOG_LEVEL: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component to assign a log level to:\n %s", - arg); - goto error; - } + break; + case OPT_OMIT_HOME_PLUGIN_PATH: + force_omit_home_plugin_path = true; - if (bt_value_array_append_string_element(run_args, "--log-level")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--omit-home-plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_RETRY_DURATION: + if (bt_value_array_append_string_element(run_args, + "--retry-duration")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_OMIT_SYSTEM_PLUGIN_PATH: + force_omit_system_plugin_path = true; - break; - case OPT_OMIT_HOME_PLUGIN_PATH: - force_omit_home_plugin_path = true; + if (bt_value_array_append_string_element(run_args, + "--omit-system-plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_PLUGIN_PATH: + if (bt_config_append_plugin_paths_check_setuid_setgid( + plugin_paths, arg)) { + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--omit-home-plugin-path")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - break; - case OPT_RETRY_DURATION: - if (bt_value_array_append_string_element(run_args, - "--retry-duration")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_BEGIN: + case OPT_CLOCK_CYCLES: + case OPT_CLOCK_DATE: + case OPT_CLOCK_FORCE_CORRELATE: + case OPT_CLOCK_GMT: + case OPT_CLOCK_OFFSET: + case OPT_CLOCK_OFFSET_NS: + case OPT_CLOCK_SECONDS: + case OPT_COLOR: + case OPT_DEBUG: + case OPT_DEBUG_INFO: + case OPT_DEBUG_INFO_DIR: + case OPT_DEBUG_INFO_FULL_PATH: + case OPT_DEBUG_INFO_TARGET_PREFIX: + case OPT_END: + case OPT_FIELDS: + case OPT_INPUT_FORMAT: + case OPT_NAMES: + case OPT_NO_DELTA: + case OPT_OUTPUT_FORMAT: + case OPT_OUTPUT: + case OPT_RUN_ARGS: + case OPT_RUN_ARGS_0: + case OPT_STREAM_INTERSECTION: + case OPT_TIMERANGE: + case OPT_VERBOSE: + /* Ignore in this pass */ + 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: - force_omit_system_plugin_path = true; + } else if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) { + struct bt_argpar_item_non_opt *argpar_item_non_opt; + bt_value_array_append_element_status append_status; + + current_item_type = CONVERT_CURRENT_ITEM_TYPE_NON_OPT; + + argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item; - if (bt_value_array_append_string_element(run_args, - "--omit-system-plugin-path")) { + append_status = bt_value_array_append_string_element(non_opts, + argpar_item_non_opt->arg); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - break; - case OPT_PLUGIN_PATH: - if (bt_config_append_plugin_paths_check_setuid_setgid( - plugin_paths, arg)) { - goto error; - } - if (bt_value_array_append_string_element(run_args, - "--plugin-path")) { + append_status = bt_value_array_append_empty_array_element(non_opt_params); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, arg)) { + append_status = bt_value_array_append_element(non_opt_loglevels, bt_value_null); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - break; - case OPT_BEGIN: - case OPT_CLOCK_CYCLES: - case OPT_CLOCK_DATE: - case OPT_CLOCK_FORCE_CORRELATE: - case OPT_CLOCK_GMT: - case OPT_CLOCK_OFFSET: - case OPT_CLOCK_OFFSET_NS: - case OPT_CLOCK_SECONDS: - case OPT_COLOR: - case OPT_DEBUG: - case OPT_DEBUG_INFO: - case OPT_DEBUG_INFO_DIR: - case OPT_DEBUG_INFO_FULL_PATH: - case OPT_DEBUG_INFO_TARGET_PREFIX: - case OPT_END: - case OPT_FIELDS: - case OPT_INPUT_FORMAT: - case OPT_NAMES: - case OPT_NO_DELTA: - case OPT_OUTPUT_FORMAT: - case OPT_OUTPUT: - case OPT_RUN_ARGS: - case OPT_RUN_ARGS_0: - case OPT_STREAM_INTERSECTION: - case OPT_TIMERANGE: - case OPT_VERBOSE: - /* Ignore in this pass */ - break; - default: - BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).", - argpar_item_opt->descr->id); - goto error; + } else { + abort(); } } - /* Append current component's name if needed */ - ret = convert_append_name_param(cur_comp_dest, cur_name, - cur_name_prefix, run_args, all_names, &source_names, - &filter_names, &sink_names); - if (ret) { - goto error; - } - /* * Second pass: transform the convert-specific options and * arguments into implicit component instances for the run @@ -4123,35 +4126,16 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - /* Consume and keep leftover arguments */ - 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); - struct bt_argpar_item_non_opt *argpar_item_non_opt; - - if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_NON_OPT) { - continue; - } - - argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item; - - if (bt_value_array_append_string_element(leftovers, argpar_item_non_opt->arg) != - BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - } - /* Print CTF metadata or print LTTng live sessions */ if (print_ctf_metadata) { - const bt_value *bt_val_leftover; + const bt_value *bt_val_non_opt; - if (bt_value_array_is_empty(leftovers)) { + if (bt_value_array_is_empty(non_opts)) { BT_CLI_LOGE_APPEND_CAUSE("--output-format=ctf-metadata specified without a path."); goto error; } - if (bt_value_array_get_size(leftovers) > 1) { + if (bt_value_array_get_size(non_opts) > 1) { BT_CLI_LOGE_APPEND_CAUSE("Too many paths specified for --output-format=ctf-metadata."); goto error; } @@ -4161,9 +4145,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - bt_val_leftover = bt_value_array_borrow_element_by_index_const(leftovers, 0); + bt_val_non_opt = bt_value_array_borrow_element_by_index_const(non_opts, 0); g_string_assign(cfg->cmd_data.print_ctf_metadata.path, - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (output) { g_string_assign( @@ -4228,19 +4212,19 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } } - /* Decide where the leftover argument(s) go */ - if (bt_value_array_get_size(leftovers) > 0) { + /* Decide where the non-option argument(s) go */ + if (bt_value_array_get_size(non_opts) > 0) { if (implicit_lttng_live_args.exists) { - const bt_value *bt_val_leftover; + const bt_value *bt_val_non_opt; - if (bt_value_array_get_size(leftovers) > 1) { + if (bt_value_array_get_size(non_opts) > 1) { BT_CLI_LOGE_APPEND_CAUSE("Too many URLs specified for --input-format=lttng-live."); goto error; } - bt_val_leftover = bt_value_array_borrow_element_by_index_const(leftovers, 0); + bt_val_non_opt = bt_value_array_borrow_element_by_index_const(non_opts, 0); lttng_live_url_parts = - bt_common_parse_lttng_live_url(bt_value_string_get(bt_val_leftover), + bt_common_parse_lttng_live_url(bt_value_string_get(bt_val_non_opt), error_buf, sizeof(error_buf)); if (!lttng_live_url_parts.proto) { BT_CLI_LOGE_APPEND_CAUSE("Invalid LTTng live URL format: %s.", @@ -4257,7 +4241,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } g_string_assign(cfg->cmd_data.print_lttng_live_sessions.url, - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (output) { g_string_assign( @@ -4270,7 +4254,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], ret = append_implicit_component_extra_param( &implicit_lttng_live_args, "url", - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (ret) { goto error; } @@ -4284,7 +4268,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } else { int status; - status = auto_discover_source_components(plugin_paths, leftovers, + status = auto_discover_source_components(plugin_paths, non_opts, auto_source_discovery_restrict_plugin_name, auto_source_discovery_restrict_component_class_name, *default_log_level >= 0 ? *default_log_level : cli_default_log_level, @@ -4294,8 +4278,12 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - create_implicit_component_args_from_auto_discovered_sources( - &auto_disc, discovered_source_args); + status = create_implicit_component_args_from_auto_discovered_sources( + &auto_disc, non_opt_params, non_opt_loglevels, + discovered_source_args); + if (status != 0) { + goto error; + } } } @@ -4328,10 +4316,11 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } /* - * If the implicit `source.ctf.lttng-live` component exists, make sure - * there's at least one leftover (which is the URL). + * If the implicit `source.ctf.lttng-live` component exists, + * make sure there's at least one non-option argument (which is + * the URL). */ - if (implicit_lttng_live_args.exists && bt_value_array_is_empty(leftovers)) { + if (implicit_lttng_live_args.exists && bt_value_array_is_empty(non_opts)) { BT_CLI_LOGE_APPEND_CAUSE("Missing URL for implicit `%s` component.", implicit_lttng_live_args.comp_arg->str); goto error; @@ -4592,12 +4581,12 @@ end: free(output); - if (cur_name) { - g_string_free(cur_name, TRUE); + if (component_arg_for_run) { + g_string_free(component_arg_for_run, TRUE); } - if (cur_name_prefix) { - g_string_free(cur_name_prefix, TRUE); + if (name_gstr) { + g_string_free(name_gstr, TRUE); } bt_value_put_ref(run_args); @@ -4605,7 +4594,9 @@ end: destroy_glist_of_gstring(source_names); destroy_glist_of_gstring(filter_names); destroy_glist_of_gstring(sink_names); - bt_value_put_ref(leftovers); + bt_value_put_ref(non_opt_params); + bt_value_put_ref(non_opt_loglevels); + bt_value_put_ref(non_opts); finalize_implicit_component_args(&implicit_ctf_output_args); finalize_implicit_component_args(&implicit_lttng_live_args); finalize_implicit_component_args(&implicit_dummy_args);