X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fcli%2Fbabeltrace2-cfg-cli-args.c;h=ae8e8eef3f2fe9d3bae984e06007b9b2e18383c7;hb=502332367236f0cc3bf05dc3c2c34ca48f3e2a2f;hp=1bc0aade21ea532c25e8c511cbde92d3b067e858;hpb=3971c70163bbc4056e285932580e0e731b40a151;p=babeltrace.git diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 1bc0aade..ae8e8eef 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -40,49 +40,13 @@ #include "babeltrace2-cfg.h" #include "babeltrace2-cfg-cli-args.h" #include "babeltrace2-cfg-cli-args-connect.h" -#include "babeltrace2-cfg-cli-params-arg.h" +#include "param-parse/param-parse.h" #include "babeltrace2-log-level.h" #include "babeltrace2-plugins.h" #include "babeltrace2-query.h" #include "autodisc/autodisc.h" #include "common/version.h" -/* INI-style parsing FSM states */ -enum ini_parsing_fsm_state { - /* Expect a map key (identifier) */ - INI_EXPECT_MAP_KEY, - - /* Expect an equal character ('=') */ - INI_EXPECT_EQUAL, - - /* Expect a value */ - INI_EXPECT_VALUE, - - /* Expect a comma character (',') */ - INI_EXPECT_COMMA, -}; - -/* INI-style parsing state variables */ -struct ini_parsing_state { - /* Lexical scanner (owned by this) */ - GScanner *scanner; - - /* Output map value object being filled (owned by this) */ - bt_value *params; - - /* Next expected FSM state */ - enum ini_parsing_fsm_state expecting; - - /* Last decoded map key (owned by this) */ - char *last_map_key; - - /* Complete INI-style string to parse (not owned by this) */ - const char *arg; - - /* Error buffer (not owned by this) */ - GString *ini_error; -}; - /* Offset option with "is set" boolean */ struct offset_opt { int64_t value; @@ -1382,6 +1346,8 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], char *plugin_name = NULL, *comp_cls_name = NULL; struct bt_argpar_parse_ret argpar_parse_ret = { 0 }; struct bt_argpar_item_non_opt *non_opt; + GString *substring = NULL; + size_t end_pos; *retcode = 0; cfg = bt_config_help_create(plugin_paths, default_log_level); @@ -1423,18 +1389,36 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], } non_opt = argpar_parse_ret.items->pdata[0]; - plugin_comp_cls_names(non_opt->arg, NULL, &plugin_name, &comp_cls_name, - &cfg->cmd_data.help.cfg_component->type); - if (plugin_name && comp_cls_name) { - /* Component class help */ + + /* Look for unescaped dots in the argument. */ + substring = bt_common_string_until(non_opt->arg, ".\\", ".", &end_pos); + if (!substring) { + BT_CLI_LOGE_APPEND_CAUSE("Could not consume argument: arg=%s", + non_opt->arg); + goto error; + } + + if (end_pos == strlen(non_opt->arg)) { + /* Didn't find an unescaped dot, treat it as a plugin name. */ + g_string_assign(cfg->cmd_data.help.cfg_component->plugin_name, + non_opt->arg); + } else { + /* + * Found an unescaped dot, treat it as a component class name. + */ + plugin_comp_cls_names(non_opt->arg, NULL, &plugin_name, &comp_cls_name, + &cfg->cmd_data.help.cfg_component->type); + if (!plugin_name || !comp_cls_name) { + BT_CLI_LOGE_APPEND_CAUSE( + "Could not parse argument as a component class name: arg=%s", + non_opt->arg); + goto error; + } + g_string_assign(cfg->cmd_data.help.cfg_component->plugin_name, plugin_name); g_string_assign(cfg->cmd_data.help.cfg_component->comp_cls_name, comp_cls_name); - } else { - /* Fall back to plugin help */ - g_string_assign(cfg->cmd_data.help.cfg_component->plugin_name, - non_opt->arg); } goto end; @@ -1447,6 +1431,10 @@ end: g_free(plugin_name); g_free(comp_cls_name); + if (substring) { + g_string_free(substring, TRUE); + } + bt_argpar_parse_ret_fini(&argpar_parse_ret); return cfg; @@ -1492,12 +1480,14 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[], struct bt_config *cfg = NULL; 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 = { 0 }; - params = bt_value_null; - bt_value_get_ref(bt_value_null); + bt_value *params = bt_value_map_create(); + if (!params) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } *retcode = 0; cfg = bt_config_query_create(plugin_paths); @@ -1539,13 +1529,21 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[], switch (argpar_item_opt->descr->id) { case OPT_PARAMS: { - bt_value_put_ref(params); - params = cli_value_from_arg(arg, error_str); - if (!params) { + bt_value *parsed_params = bt_param_parse(arg, error_str); + bt_value_map_extend_status extend_status; + if (!parsed_params) { BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n %s", error_str->str); goto error; } + + extend_status = bt_value_map_extend(params, parsed_params); + BT_VALUE_PUT_REF_AND_RESET(parsed_params); + if (extend_status) { + BT_CLI_LOGE_APPEND_CAUSE("Cannot extend current parameters with --params option's argument:\n %s", + arg); + goto error; + } break; } default: @@ -1724,7 +1722,7 @@ void print_run_usage(FILE *fp) 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`, `T`, `D`, `I`, `W`, `E`, or `F`)\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"); @@ -1931,7 +1929,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], case OPT_PARAMS: { bt_value *params; - bt_value *params_to_set; if (!cur_cfg_comp) { BT_CLI_LOGE_APPEND_CAUSE("Cannot add parameters to unavailable component:\n %s", @@ -1939,15 +1936,15 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], goto error; } - params = cli_value_from_arg(arg, error_str); + params = bt_param_parse(arg, error_str); if (!params) { BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n %s", error_str->str); goto error; } - extend_status = bt_value_map_extend( - cur_cfg_comp->params, params, ¶ms_to_set); + extend_status = bt_value_map_extend(cur_cfg_comp->params, + params); BT_VALUE_PUT_REF_AND_RESET(params); if (extend_status != BT_VALUE_MAP_EXTEND_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE("Cannot extend current component parameters with --params option's argument:\n %s", @@ -1955,7 +1952,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], goto error; } - BT_OBJECT_MOVE_REF(cur_cfg_comp->params, params_to_set); break; } case OPT_LOG_LEVEL: @@ -1975,7 +1971,7 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], break; case OPT_BASE_PARAMS: { - bt_value *params = cli_value_from_arg(arg, error_str); + bt_value *params = bt_param_parse(arg, error_str); if (!params) { BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --base-params option's argument:\n %s", @@ -2128,7 +2124,7 @@ void print_convert_usage(FILE *fp) fprintf(fp, " conversion graph, and optionally name it\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, " (`N`, `T`, `D`, `I`, `W`, `E`, or `F`)\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"); @@ -2148,6 +2144,8 @@ void print_convert_usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "Implicit `source.ctf.fs` component options:\n"); fprintf(fp, "\n"); + fprintf(fp, " --clock-force-correlate Force the origin of all clocks\n"); + fprintf(fp, " to the Unix epoch\n"); fprintf(fp, " --clock-offset=SEC Set clock offset to SEC seconds\n"); fprintf(fp, " --clock-offset-ns=NS Set clock offset to NS ns\n"); fprintf(fp, "\n"); @@ -2175,11 +2173,6 @@ void print_convert_usage(FILE *fp) fprintf(fp, " -w, --output=PATH Write output text to PATH instead of\n"); fprintf(fp, " the standard output\n"); fprintf(fp, "\n"); - fprintf(fp, "Implicit `filter.utils.muxer` component options:\n"); - fprintf(fp, "\n"); - fprintf(fp, " --clock-force-correlate Assume that clocks are inherently\n"); - fprintf(fp, " correlated across traces\n"); - fprintf(fp, "\n"); fprintf(fp, "Implicit `filter.utils.trimmer` component options:\n"); fprintf(fp, "\n"); fprintf(fp, " -b, --begin=BEGIN Set the beginning time of the conversion\n"); @@ -2618,7 +2611,6 @@ int bt_value_to_cli_param_value_append(const bt_value *value, GString *buf) uint64_t sz = bt_value_array_get_length(value); for (uint64_t i = 0; i < sz; i++) { const bt_value *item; - int ret; if (i > 0) { g_string_append(buf, ", "); @@ -2981,6 +2973,9 @@ end: * Create `struct implicit_component_args` structures for each of the * source components we identified. Add them to `component_args`. * + * `non_opts` is an array of the non-option arguments passed on the command + * line. + * * `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 @@ -2996,6 +2991,7 @@ end: static int create_implicit_component_args_from_auto_discovered_sources( const struct auto_source_discovery *auto_disc, + const bt_value *non_opts, const bt_value *non_opt_params, const bt_value *non_opt_loglevels, GPtrArray *component_args) @@ -3086,6 +3082,42 @@ int create_implicit_component_args_from_auto_discovered_sources( } } + /* + * If single input and a src.ctf.fs component, provide the + * relative path from the path passed on the command line to the + * found trace. + */ + if (bt_value_array_get_length(res->inputs) == 1 && + strcmp(res->plugin_name, "ctf") == 0 && + strcmp(res->source_cc_name, "fs") == 0) { + const bt_value *orig_idx_value = + bt_value_array_borrow_element_by_index( + res->original_input_indices, 0); + uint64_t orig_idx = bt_value_integer_unsigned_get(orig_idx_value); + const bt_value *non_opt_value = + bt_value_array_borrow_element_by_index_const( + non_opts, orig_idx); + const char *non_opt = bt_value_string_get(non_opt_value); + const bt_value *input_value = + bt_value_array_borrow_element_by_index_const( + res->inputs, 0); + const char *input = bt_value_string_get(input_value); + + BT_ASSERT(orig_indices_count == 1); + BT_ASSERT(g_str_has_prefix(input, non_opt)); + + input += strlen(non_opt); + + while (G_IS_DIR_SEPARATOR(*input)) { + input++; + } + + if (strlen(input) > 0) { + append_string_parameter_to_args(comp->extra_params, + "trace-name", input); + } + } + status = append_parameter_to_args(comp->extra_params, "inputs", res->inputs); if (status != 0) { goto error; @@ -3136,7 +3168,7 @@ enum convert_current_item_type { static struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], int *retcode, const bt_value *plugin_paths, - int *default_log_level) + int *default_log_level, const bt_interrupter *interrupter) { enum convert_current_item_type current_item_type = CONVERT_CURRENT_ITEM_TYPE_NONE; @@ -3174,6 +3206,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], struct bt_argpar_parse_ret argpar_parse_ret = { 0 }; GString *name_gstr = NULL; GString *component_arg_for_run = NULL; + bt_value *live_inputs_array_val = NULL; /* * Array of `struct implicit_component_args *` created for the sources @@ -3188,6 +3221,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], const char *auto_source_discovery_restrict_plugin_name = NULL; const char *auto_source_discovery_restrict_component_class_name = NULL; + bool ctf_fs_source_force_clock_class_unix_epoch_origin = false; gchar *ctf_fs_source_clock_class_offset_arg = NULL; gchar *ctf_fs_source_clock_class_offset_ns_arg = NULL; *retcode = 0; @@ -3441,10 +3475,16 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], * it in `non_opt_params`. */ bt_value *array; + bt_value_array_append_element_status append_element_status; uint64_t idx = bt_value_array_get_length(non_opt_params) - 1; array = bt_value_array_borrow_element_by_index(non_opt_params, idx); - bt_value_array_append_string_element(array, arg); + + append_element_status = bt_value_array_append_string_element(array, arg); + if (append_element_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } } else { BT_CLI_LOGE_APPEND_CAUSE( "No current component (--component option) or non-option argument of which to set parameters:\n %s", @@ -3654,9 +3694,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], implicit_text_args.exists = true; break; case OPT_CLOCK_FORCE_CORRELATE: - append_implicit_component_param( - &implicit_muxer_args, - "assume-absolute-clock-classes", "yes"); + ctf_fs_source_force_clock_class_unix_epoch_origin = true; break; case OPT_CLOCK_GMT: append_implicit_component_param( @@ -3842,7 +3880,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], case OPT_STREAM_INTERSECTION: /* * Applies to all traces implementing the - * babeltrace.trace-info query. + * babeltrace.trace-infos query. */ stream_intersection_mode = true; break; @@ -3998,9 +4036,22 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto end; } - ret = append_implicit_component_extra_param( - &implicit_lttng_live_args, "url", - bt_value_string_get(bt_val_non_opt)); + live_inputs_array_val = bt_value_array_create(); + if (!live_inputs_array_val) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + + if (bt_value_array_append_string_element( + live_inputs_array_val, + bt_value_string_get(bt_val_non_opt))) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + + ret = append_parameter_to_args( + implicit_lttng_live_args.extra_params, + "inputs", live_inputs_array_val); if (ret) { goto error; } @@ -4033,14 +4084,18 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], status = auto_discover_source_components(non_opts, plugins, plugin_count, auto_source_discovery_restrict_component_class_name, - *default_log_level, &auto_disc); + *default_log_level, &auto_disc, interrupter); if (status != 0) { + if (status == AUTO_SOURCE_DISCOVERY_STATUS_INTERRUPTED) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( + "Babeltrace CLI", "Automatic source discovery interrupted by the user"); + } goto error; } status = create_implicit_component_args_from_auto_discovered_sources( - &auto_disc, non_opt_params, non_opt_loglevels, + &auto_disc, non_opts, non_opt_params, non_opt_loglevels, discovered_source_args); if (status != 0) { goto error; @@ -4048,6 +4103,23 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } } + + /* + * If --clock-force-correlated was given, apply it to any src.ctf.fs + * component. + */ + if (ctf_fs_source_force_clock_class_unix_epoch_origin) { + int n; + + n = append_multiple_implicit_components_param( + discovered_source_args, "source.ctf.fs", "force-clock-class-origin-unix-epoch", + "yes"); + if (n == 0) { + BT_CLI_LOGE_APPEND_CAUSE("--clock-force-correlate specified, but no source.ctf.fs component instantiated."); + goto error; + } + } + /* If --clock-offset was given, apply it to any src.ctf.fs component. */ if (ctf_fs_source_clock_class_offset_arg) { int n; @@ -4339,6 +4411,7 @@ end: g_string_free(name_gstr, TRUE); } + bt_value_put_ref(live_inputs_array_val); bt_value_put_ref(run_args); bt_value_put_ref(all_names); destroy_glist_of_gstring(source_names); @@ -4381,9 +4454,9 @@ void print_gen_usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "General options:\n"); fprintf(fp, "\n"); - fprintf(fp, " -d, --debug Enable debug mode (same as --log-level=V)\n"); + fprintf(fp, " -d, --debug Enable debug mode (same as --log-level=T)\n"); fprintf(fp, " -h, --help Show this help and quit\n"); - fprintf(fp, " -l, --log-level=LVL Set the default log level to LVL (`N`, `V`, `D`,\n"); + fprintf(fp, " -l, --log-level=LVL Set the default log level to LVL (`N`, `T`, `D`,\n"); fprintf(fp, " `I`, `W` (default), `E`, or `F`)\n"); fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " (~/.local/lib/babeltrace2/plugins)\n"); @@ -4407,7 +4480,8 @@ void print_gen_usage(FILE *fp) struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], int *retcode, bool omit_system_plugin_path, bool omit_home_plugin_path, - const bt_value *initial_plugin_paths) + const bt_value *initial_plugin_paths, + const bt_interrupter *interrupter) { struct bt_config *config = NULL; int i; @@ -4637,7 +4711,7 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], break; case COMMAND_TYPE_CONVERT: config = bt_config_convert_from_args(command_argc, command_argv, - retcode, plugin_paths, &default_log_level); + retcode, plugin_paths, &default_log_level, interrupter); break; case COMMAND_TYPE_LIST_PLUGINS: config = bt_config_list_plugins_from_args(command_argc,