* SOFTWARE.
*/
+#define BT_LOG_TAG "CLI-CFG-CLI-ARGS"
+#include "logging.h"
+
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <popt.h>
#include <glib.h>
#include <sys/types.h>
-#include <pwd.h>
#include "babeltrace-cfg.h"
#include "babeltrace-cfg-cli-args.h"
#include "babeltrace-cfg-cli-args-connect.h"
-
-#define BT_LOG_TAG "CLI-CFG-ARGS"
-#include "logging.h"
+#include "version.h"
/*
* Error printf() macro which prepends "Error: " the first time it's
}
/*
- * Returns the plugin and component class names, and the instance name,
- * from a command-line source/filter/sink option's argument. arg must
- * have the following format:
+ * Returns the plugin name, component class name, component class type,
+ * and component name from a command-line --component option's argument.
+ * arg must have the following format:
*
- * [NAME:]PLUGIN.CLS
+ * [NAME:]TYPE.PLUGIN.CLS
*
- * where NAME is the optional component name, PLUGIN is the plugin name,
- * and CLS is the component class name.
+ * where NAME is the optional component name, TYPE is either `source`,
+ * `filter`, or `sink`, PLUGIN is the plugin name, and CLS is the
+ * component class name.
*
* On success, both *plugin and *component are not NULL. *plugin
- * and *component are owned by the caller. On success, *name can be NULL
- * if no component name was found.
+ * and *comp_cls are owned by the caller. On success, *name can be NULL
+ * if no component class name was found, and *comp_cls_type is set.
*/
static
void plugin_comp_cls_names(const char *arg, char **name, char **plugin,
- char **comp_cls)
+ char **comp_cls, enum bt_component_class_type *comp_cls_type)
{
const char *at = arg;
GString *gs_name = NULL;
+ GString *gs_comp_cls_type = NULL;
GString *gs_plugin = NULL;
GString *gs_comp_cls = NULL;
size_t end_pos;
assert(arg);
assert(plugin);
assert(comp_cls);
+ assert(comp_cls_type);
if (!bt_common_string_is_printable(arg)) {
printf_err("Argument contains a non-printable character\n");
g_string_assign(gs_name, "");
}
+ /* Parse the component class type */
+ gs_comp_cls_type = bt_common_string_until(at, ".:\\", ".", &end_pos);
+ if (!gs_comp_cls_type || at[end_pos] == '\0') {
+ printf_err("Missing component class type (`source`, `filter`, or `sink`)\n");
+ goto error;
+ }
+
+ if (strcmp(gs_comp_cls_type->str, "source") == 0 ||
+ strcmp(gs_comp_cls_type->str, "src") == 0) {
+ *comp_cls_type = BT_COMPONENT_CLASS_TYPE_SOURCE;
+ } else if (strcmp(gs_comp_cls_type->str, "filter") == 0 ||
+ strcmp(gs_comp_cls_type->str, "flt") == 0) {
+ *comp_cls_type = BT_COMPONENT_CLASS_TYPE_FILTER;
+ } else if (strcmp(gs_comp_cls_type->str, "sink") == 0) {
+ *comp_cls_type = BT_COMPONENT_CLASS_TYPE_SINK;
+ } else {
+ printf_err("Unknown component class type: `%s`\n",
+ gs_comp_cls_type->str);
+ goto error;
+ }
+
+ at += end_pos + 1;
+
/* Parse the plugin name */
gs_plugin = bt_common_string_until(at, ".:\\", ".", &end_pos);
if (!gs_plugin || gs_plugin->len == 0 || at[end_pos] == '\0') {
+ printf_err("Missing plugin or component class name\n");
goto error;
}
/* Parse the component class name */
gs_comp_cls = bt_common_string_until(at, ".:\\", ".", &end_pos);
if (!gs_comp_cls || gs_comp_cls->len == 0) {
+ printf_err("Missing component class name\n");
goto error;
}
goto end;
error:
+ if (name) {
+ *name = NULL;
+ }
+
+ *plugin = NULL;
+ *comp_cls = NULL;
+
+end:
if (gs_name) {
g_string_free(gs_name, TRUE);
}
g_string_free(gs_comp_cls, TRUE);
}
- if (name) {
- *name = NULL;
+ if (gs_comp_cls_type) {
+ g_string_free(gs_comp_cls_type, TRUE);
}
- *plugin = NULL;
- *comp_cls = NULL;
-
-end:
return;
}
static
void print_version(void)
{
- puts("Babeltrace " VERSION);
+ if (GIT_VERSION[0] == '\0') {
+ puts("Babeltrace " VERSION);
+ } else {
+ puts("Babeltrace " VERSION " - " GIT_VERSION);
+ }
}
/*
}
/*
- * Creates a component configuration from a command-line source/sink
+ * Creates a component configuration from a command-line --component
* option's argument.
*/
static
-struct bt_config_component *bt_config_component_from_arg(
- enum bt_component_class_type type, const char *arg)
+struct bt_config_component *bt_config_component_from_arg(const char *arg)
{
struct bt_config_component *cfg_comp = NULL;
char *name = NULL;
char *plugin_name = NULL;
char *comp_cls_name = NULL;
+ enum bt_component_class_type type;
- plugin_comp_cls_names(arg, &name, &plugin_name, &comp_cls_name);
+ plugin_comp_cls_names(arg, &name, &plugin_name, &comp_cls_name, &type);
if (!plugin_name || !comp_cls_name) {
- printf_err("Cannot get plugin or component class name\n");
goto error;
}
if (cfg->cmd_data.print_ctf_metadata.path) {
g_string_free(cfg->cmd_data.print_ctf_metadata.path,
TRUE);
+ g_string_free(
+ cfg->cmd_data.print_ctf_metadata.output_path,
+ TRUE);
}
break;
case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
g_string_free(
cfg->cmd_data.print_lttng_live_sessions.url,
TRUE);
+ g_string_free(
+ cfg->cmd_data.print_lttng_live_sessions.output_path,
+ TRUE);
}
break;
default:
static
void destroy_glist_of_gstring(GList *list)
{
+ GList *at;
+
if (!list) {
return;
}
- GList *at;
-
for (at = list; at != NULL; at = g_list_next(at)) {
g_string_free(at->data, TRUE);
}
OPT_CLOCK_OFFSET_NS,
OPT_CLOCK_SECONDS,
OPT_COLOR,
+ OPT_COMPONENT,
OPT_CONNECT,
OPT_DEBUG,
+ OPT_DEBUG_INFO,
OPT_DEBUG_INFO_DIR,
OPT_DEBUG_INFO_FULL_PATH,
OPT_DEBUG_INFO_TARGET_PREFIX,
OPT_END,
OPT_FIELDS,
- OPT_FILTER,
OPT_HELP,
OPT_INPUT_FORMAT,
OPT_KEY,
OPT_LIST,
OPT_NAME,
OPT_NAMES,
- OPT_NO_DEBUG_INFO,
OPT_NO_DELTA,
OPT_OMIT_HOME_PLUGIN_PATH,
OPT_OMIT_SYSTEM_PLUGIN_PATH,
- OPT_OUTPUT_FORMAT,
OPT_OUTPUT,
+ OPT_OUTPUT_FORMAT,
OPT_PARAMS,
OPT_PATH,
OPT_PLUGIN_PATH,
OPT_RETRY_DURATION,
OPT_RUN_ARGS,
OPT_RUN_ARGS_0,
- OPT_SINK,
- OPT_SOURCE,
OPT_STREAM_INTERSECTION,
OPT_TIMERANGE,
OPT_URL,
const char *envvar;
if (bt_common_is_setuid_setgid()) {
- printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
+ BT_LOGI_STR("Skipping non-system plugin paths for setuid/setgid binary.");
goto end;
}
if (!omit_home_plugin_path) {
if (bt_common_is_setuid_setgid()) {
- printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
+ BT_LOGI_STR("Skipping non-system plugin paths for setuid/setgid binary.");
} else {
char *home_plugin_dir =
bt_common_get_home_plugin_path();
goto error;
}
+ cfg->cmd_data.print_ctf_metadata.output_path = g_string_new(NULL);
+ if (!cfg->cmd_data.print_ctf_metadata.output_path) {
+ print_err_oom();
+ goto error;
+ }
+
goto end;
error:
goto error;
}
+ cfg->cmd_data.print_lttng_live_sessions.output_path =
+ g_string_new(NULL);
+ if (!cfg->cmd_data.print_lttng_live_sessions.output_path) {
+ print_err_oom();
+ goto error;
+ }
+
goto end;
error:
int ret = 0;
if (bt_common_is_setuid_setgid()) {
- printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
+ BT_LOGI_STR("Skipping non-system plugin paths for setuid/setgid binary.");
goto end;
}
void print_help_usage(FILE *fp)
{
fprintf(fp, "Usage: babeltrace [GENERAL OPTIONS] help [OPTIONS] PLUGIN\n");
- fprintf(fp, " babeltrace [GENERAL OPTIONS] help [OPTIONS] --source=PLUGIN.CLS\n");
- fprintf(fp, " babeltrace [GENERAL OPTIONS] help [OPTIONS] --filter=PLUGIN.CLS\n");
- fprintf(fp, " babeltrace [GENERAL OPTIONS] help [OPTIONS] --sink=PLUGIN.CLS\n");
+ fprintf(fp, " babeltrace [GENERAL OPTIONS] help [OPTIONS] TYPE.PLUGIN.CLS\n");
fprintf(fp, "\n");
fprintf(fp, "Options:\n");
fprintf(fp, "\n");
- fprintf(fp, " -f, --filter=PLUGIN.CLS Get help for the filter component class\n");
- fprintf(fp, " CLS found in the plugin PLUGIN\n");
fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n");
fprintf(fp, " (~/.local/lib/babeltrace/plugins)\n");
fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search 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, " -S, --sink=PLUGIN.CLS Get help for the sink component class\n");
- fprintf(fp, " CLS found in the plugin PLUGIN\n");
- fprintf(fp, " -s, --source=PLUGIN.CLS Get help for the source component class\n");
- fprintf(fp, " CLS found in the plugin PLUGIN\n");
- fprintf(fp, " -h --help Show this help and quit\n");
+ fprintf(fp, " -h, --help Show this help and quit\n");
fprintf(fp, "\n");
fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
fprintf(fp, "\n");
static
struct poptOption help_long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
- { "filter", 'f', POPT_ARG_STRING, NULL, OPT_FILTER, NULL, NULL },
{ "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 },
- { "sink", 'S', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
- { "source", 's', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
{ NULL, 0, '\0', NULL, 0, NULL, NULL },
};
struct bt_config *cfg = NULL;
const char *leftover;
char *plugin_name = NULL, *comp_cls_name = NULL;
- char *plug_comp_cls_names = NULL;
*retcode = 0;
cfg = bt_config_help_create(initial_plugin_paths);
case OPT_OMIT_HOME_PLUGIN_PATH:
cfg->omit_home_plugin_path = true;
break;
- case OPT_SOURCE:
- case OPT_FILTER:
- case OPT_SINK:
- if (cfg->cmd_data.help.cfg_component->type !=
- BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
- printf_err("Cannot specify more than one plugin and component class:\n %s\n",
- arg);
- goto error;
- }
-
- switch (opt) {
- case OPT_SOURCE:
- cfg->cmd_data.help.cfg_component->type =
- BT_COMPONENT_CLASS_TYPE_SOURCE;
- break;
- case OPT_FILTER:
- cfg->cmd_data.help.cfg_component->type =
- BT_COMPONENT_CLASS_TYPE_FILTER;
- break;
- case OPT_SINK:
- cfg->cmd_data.help.cfg_component->type =
- BT_COMPONENT_CLASS_TYPE_SINK;
- break;
- default:
- abort();
- }
- plug_comp_cls_names = strdup(arg);
- if (!plug_comp_cls_names) {
- print_err_oom();
- goto error;
- }
- break;
case OPT_HELP:
print_help_usage(stdout);
*retcode = -1;
leftover = poptGetArg(pc);
if (leftover) {
- if (cfg->cmd_data.help.cfg_component->type !=
- BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
- printf_err("Cannot specify plugin name and --source/--filter/--sink component class:\n %s\n",
- leftover);
- goto error;
- }
-
- g_string_assign(cfg->cmd_data.help.cfg_component->plugin_name,
- leftover);
- } else {
- if (cfg->cmd_data.help.cfg_component->type ==
- BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
- print_help_usage(stdout);
- *retcode = -1;
- BT_PUT(cfg);
- goto end;
- }
-
- plugin_comp_cls_names(plug_comp_cls_names, NULL,
- &plugin_name, &comp_cls_name);
+ plugin_comp_cls_names(leftover, NULL,
+ &plugin_name, &comp_cls_name,
+ &cfg->cmd_data.help.cfg_component->type);
if (plugin_name && comp_cls_name) {
- g_string_assign(cfg->cmd_data.help.cfg_component->plugin_name,
+ /* Component class help */
+ 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,
+ g_string_assign(
+ cfg->cmd_data.help.cfg_component->comp_cls_name,
comp_cls_name);
} else {
- printf_err("Invalid --source/--filter/--sink option's argument:\n %s\n",
- plug_comp_cls_names);
- goto error;
+ /* Fall back to plugin help */
+ cfg->cmd_data.help.cfg_component->type =
+ BT_COMPONENT_CLASS_TYPE_UNKNOWN;
+ g_string_assign(
+ cfg->cmd_data.help.cfg_component->plugin_name,
+ leftover);
}
+ } else {
+ print_help_usage(stdout);
+ *retcode = -1;
+ BT_PUT(cfg);
+ goto end;
}
if (append_home_and_system_plugin_paths_cfg(cfg)) {
BT_PUT(cfg);
end:
- free(plug_comp_cls_names);
g_free(plugin_name);
g_free(comp_cls_name);
static
void print_query_usage(FILE *fp)
{
- fprintf(fp, "Usage: babeltrace [GEN OPTS] query [OPTS] OBJECT --source=PLUGIN.CLS\n");
- fprintf(fp, " babeltrace [GEN OPTS] query [OPTS] OBJECT --filter=PLUGIN.CLS\n");
- fprintf(fp, " babeltrace [GEN OPTS] query [OPTS] OBJECT --sink=PLUGIN.CLS\n");
+ fprintf(fp, "Usage: babeltrace [GEN OPTS] query [OPTS] TYPE.PLUGIN.CLS OBJECT\n");
fprintf(fp, "\n");
fprintf(fp, "Options:\n");
fprintf(fp, "\n");
- fprintf(fp, " -f. --filter=PLUGIN.CLS Query object from the filter component\n");
- fprintf(fp, " class CLS found in the plugin PLUGIN\n");
fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n");
fprintf(fp, " (~/.local/lib/babeltrace/plugins)\n");
fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n");
fprintf(fp, " (see the expected format of PARAMS below)\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, " -S, --sink=PLUGIN.CLS Query object from the sink component class\n");
- fprintf(fp, " CLS found in the plugin PLUGIN\n");
- fprintf(fp, " -s, --source=PLUGIN.CLS Query object from the source component\n");
- fprintf(fp, " class CLS found in the plugin PLUGIN\n");
- fprintf(fp, " -h --help Show this help and quit\n");
+ fprintf(fp, " -h, --help Show this help and quit\n");
fprintf(fp, "\n\n");
print_expected_params_format(fp);
}
static
struct poptOption query_long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
- { "filter", 'f', POPT_ARG_STRING, NULL, OPT_FILTER, NULL, NULL },
{ "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 },
- { "sink", 'S', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
- { "source", 's', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
{ NULL, 0, '\0', NULL, 0, NULL, NULL },
};
case OPT_OMIT_HOME_PLUGIN_PATH:
cfg->omit_home_plugin_path = true;
break;
- case OPT_SOURCE:
- case OPT_FILTER:
- case OPT_SINK:
- {
- enum bt_component_class_type type;
-
- if (cfg->cmd_data.query.cfg_component) {
- printf_err("Cannot specify more than one plugin and component class:\n %s\n",
- arg);
- goto error;
- }
-
- switch (opt) {
- case OPT_SOURCE:
- type = BT_COMPONENT_CLASS_TYPE_SOURCE;
- break;
- case OPT_FILTER:
- type = BT_COMPONENT_CLASS_TYPE_FILTER;
- break;
- case OPT_SINK:
- type = BT_COMPONENT_CLASS_TYPE_SINK;
- break;
- default:
- abort();
- }
-
- cfg->cmd_data.query.cfg_component =
- bt_config_component_from_arg(type, arg);
- if (!cfg->cmd_data.query.cfg_component) {
- printf_err("Invalid format for --source/--filter/--sink option's argument:\n %s\n",
- arg);
- goto error;
- }
-
- /* Default parameters: null */
- bt_put(cfg->cmd_data.query.cfg_component->params);
- cfg->cmd_data.query.cfg_component->params =
- bt_value_null;
- break;
- }
case OPT_PARAMS:
{
+ bt_put(params);
params = bt_value_from_arg(arg);
if (!params) {
printf_err("Invalid format for --params option's argument:\n %s\n",
arg = NULL;
}
- if (!cfg->cmd_data.query.cfg_component) {
- printf_err("No target component class specified with --source/--filter/--sink option\n");
- goto error;
- }
-
- assert(params);
- BT_MOVE(cfg->cmd_data.query.cfg_component->params, params);
-
/* Check for option parsing error */
if (opt < -1) {
printf_err("While parsing command-line options, at option %s: %s\n",
}
/*
- * We need exactly one leftover argument which is the
- * mandatory object.
+ * 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);
+ if (!cfg->cmd_data.query.cfg_component) {
+ printf_err("Invalid format for component class specification:\n %s\n",
+ leftover);
+ goto error;
+ }
+
+ assert(params);
+ BT_MOVE(cfg->cmd_data.query.cfg_component->params, params);
+ } else {
+ print_query_usage(stdout);
+ *retcode = -1;
+ BT_PUT(cfg);
+ goto end;
+ }
+
leftover = poptGetArg(pc);
if (leftover) {
if (strlen(leftover) == 0) {
poptFreeContext(pc);
}
- BT_PUT(params);
+ bt_put(params);
free(arg);
return cfg;
}
fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search 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, " -h --help Show this help and quit\n");
+ fprintf(fp, " -h, --help Show this help and quit\n");
fprintf(fp, "\n");
fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
fprintf(fp, "\n");
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, --connect=CONNECTION Connect two created components (see the\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, " -C, --connect=CONNECTION Connect two created components (see the\n");
fprintf(fp, " expected format of CONNECTION below)\n");
- fprintf(fp, " -f, --filter=[NAME:]PLUGIN.CLS Instantiate a filter component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\n");
fprintf(fp, " --key=KEY Set the current initialization string\n");
fprintf(fp, " parameter key to KEY (see --value)\n");
fprintf(fp, " -n, --name=NAME Set the name of the current component\n");
fprintf(fp, " --retry-duration=DUR When babeltrace(1) needs to retry to run\n");
fprintf(fp, " the graph later, retry in DUR µs\n");
fprintf(fp, " (default: 100000)\n");
- fprintf(fp, " -S, --sink=[NAME:]PLUGIN.CLS Instantiate a sink component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\n");
- fprintf(fp, " -s, --source=[NAME:]PLUGIN.CLS Instantiate a source component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\n");
fprintf(fp, " --value=VAL Add a string initialization parameter to\n");
fprintf(fp, " the current component with a name given by\n");
fprintf(fp, " the last argument of the --key option and a\n");
fprintf(fp, " value set to VAL\n");
- fprintf(fp, " -h --help Show this help and quit\n");
+ fprintf(fp, " -h, --help Show this help and quit\n");
fprintf(fp, "\n");
fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
fprintf(fp, "\n\n");
struct bt_value *connection_args = NULL;
GString *cur_param_key = NULL;
char error_buf[256] = { 0 };
- long long retry_duration = -1;
+ long retry_duration = -1;
struct poptOption run_long_options[] = {
{ "base-params", 'b', POPT_ARG_STRING, NULL, OPT_BASE_PARAMS, NULL, NULL },
- { "connect", 'c', POPT_ARG_STRING, NULL, OPT_CONNECT, NULL, NULL },
- { "filter", 'f', POPT_ARG_STRING, NULL, OPT_FILTER, NULL, NULL },
+ { "component", 'c', POPT_ARG_STRING, NULL, OPT_COMPONENT, NULL, NULL },
+ { "connect", 'C', POPT_ARG_STRING, NULL, OPT_CONNECT, NULL, NULL },
{ "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
{ "key", '\0', POPT_ARG_STRING, NULL, OPT_KEY, NULL, NULL },
{ "name", 'n', POPT_ARG_STRING, NULL, OPT_NAME, NULL, NULL },
{ "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
{ "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
{ "reset-base-params", 'r', POPT_ARG_NONE, NULL, OPT_RESET_BASE_PARAMS, NULL, NULL },
- { "retry-duration", '\0', POPT_ARG_LONGLONG, &retry_duration, OPT_RETRY_DURATION, NULL, NULL },
- { "sink", 'S', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
- { "source", 's', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
+ { "retry-duration", '\0', POPT_ARG_LONG, &retry_duration, OPT_RETRY_DURATION, NULL, NULL },
{ "value", '\0', POPT_ARG_STRING, NULL, OPT_VALUE, NULL, NULL },
{ NULL, 0, '\0', NULL, 0, NULL, NULL },
};
case OPT_OMIT_HOME_PLUGIN_PATH:
cfg->omit_home_plugin_path = true;
break;
- case OPT_SOURCE:
- case OPT_FILTER:
- case OPT_SINK:
+ case OPT_COMPONENT:
{
- enum bt_component_class_type new_comp_type;
enum bt_config_component_dest new_dest;
- const char *opt_name;
-
- switch (opt) {
- case OPT_SOURCE:
- new_comp_type = BT_COMPONENT_CLASS_TYPE_SOURCE;
- new_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
- opt_name = "--source";
- break;
- case OPT_FILTER:
- new_comp_type = BT_COMPONENT_CLASS_TYPE_FILTER;
- new_dest = BT_CONFIG_COMPONENT_DEST_FILTER;
- opt_name = "--filter";
- break;
- case OPT_SINK:
- new_comp_type = BT_COMPONENT_CLASS_TYPE_SINK;
- new_dest = BT_CONFIG_COMPONENT_DEST_SINK;
- opt_name = "--sink";
- break;
- default:
- abort();
- }
if (cur_cfg_comp) {
ret = add_run_cfg_comp_check_name(cfg,
}
}
- cur_cfg_comp = bt_config_component_from_arg(
- new_comp_type, arg);
+ cur_cfg_comp = bt_config_component_from_arg(arg);
if (!cur_cfg_comp) {
- printf_err("Invalid format for %s option's argument:\n %s\n",
- opt_name, arg);
+ printf_err("Invalid format for --component option's argument:\n %s\n",
+ arg);
goto error;
}
+ switch (cur_cfg_comp->type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ new_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
+ break;
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ new_dest = BT_CONFIG_COMPONENT_DEST_FILTER;
+ break;
+ case BT_COMPONENT_CLASS_TYPE_SINK:
+ new_dest = BT_CONFIG_COMPONENT_DEST_SINK;
+ break;
+ default:
+ abort();
+ }
+
assert(cur_base_params);
bt_put(cur_cfg_comp->params);
cur_cfg_comp->params = bt_value_copy(cur_base_params);
break;
case OPT_RETRY_DURATION:
if (retry_duration < 0) {
- printf_err("--retry-duration option's argument must be positive or 0: %lld\n",
+ printf_err("--retry-duration option's argument must be positive or 0: %ld\n",
retry_duration);
goto error;
}
{
struct bt_config *cfg = NULL;
const char **argv;
- size_t i;
+ int64_t i, len;
const size_t argc = bt_value_array_size(run_args) + 1;
argv = calloc(argc, sizeof(*argv));
argv[0] = "run";
- for (i = 0; i < bt_value_array_size(run_args); i++) {
+ len = bt_value_array_size(run_args);
+ if (len < 0) {
+ printf_err("Invalid executable arguments\n");
+ goto end;
+ }
+ for (i = 0; i < len; i++) {
int ret;
struct bt_value *arg_value = bt_value_array_get(run_args, i);
const char *arg;
fprintf(fp, "\n");
fprintf(fp, "Options:\n");
fprintf(fp, "\n");
- fprintf(fp, " --filter=[NAME:]PLUGIN.CLS Instantiate a filter component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\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\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=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, " --run-args-0 Print the equivalent arguments for the\n");
fprintf(fp, " `run` command to the standard output,\n");
fprintf(fp, " formatted for `xargs -0`, and quit\n");
- fprintf(fp, " --sink=[NAME:]PLUGIN.CLS Instantiate a sink component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\n");
- fprintf(fp, " --source=[NAME:]PLUGIN.CLS Instantiate a source component from plugin\n");
- fprintf(fp, " PLUGIN and component class CLS, set it as\n");
- fprintf(fp, " the current component, and if NAME is\n");
- fprintf(fp, " given, set its instance name to NAME\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, " -h, --help Show this help and quit\n");
fprintf(fp, "\n");
- fprintf(fp, "Implicit `ctf.fs` source component options:\n");
+ fprintf(fp, "Implicit `source.ctf.fs` component options:\n");
fprintf(fp, "\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, " --stream-intersection Only process events when all streams\n");
- fprintf(fp, " are active\n");
fprintf(fp, "\n");
- fprintf(fp, "Implicit `text.text` sink component options:\n");
+ fprintf(fp, "Implicit `sink.text.pretty` component options:\n");
fprintf(fp, "\n");
fprintf(fp, " --clock-cycles Print timestamps in clock cycles\n");
fprintf(fp, " --clock-date Print timestamp dates\n");
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 `utils.muxer` filter component options:\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 `utils.trimmer` filter component options:\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");
fprintf(fp, " time range to BEGIN (see the format of\n");
fprintf(fp, " BEGIN,END or [BEGIN,END] (literally `[` and\n");
fprintf(fp, " `]`) (see the format of BEGIN/END below)\n");
fprintf(fp, "\n");
- fprintf(fp, "Implicit `lttng-utils.debug-info` filter component options:\n");
+ fprintf(fp, "Implicit `filter.lttng-utils.debug-info` component options:\n");
fprintf(fp, "\n");
+ fprintf(fp, " --debug-info Create an implicit\n");
+ fprintf(fp, " `filter.lttng-utils.debug-info` component\n");
fprintf(fp, " --debug-info-dir=DIR Search for debug info in directory DIR\n");
fprintf(fp, " instead of `/usr/lib/debug`\n");
fprintf(fp, " --debug-info-full-path Show full debug info source and\n");
fprintf(fp, " Use directory DIR as a prefix when\n");
fprintf(fp, " looking up executables during debug\n");
fprintf(fp, " info analysis\n");
- fprintf(fp, " --no-debug-info Do not create an implicit\n");
- fprintf(fp, " `lttng-utils.debug-info` filter component\n");
fprintf(fp, "\n");
fprintf(fp, "Legacy options that still work:\n");
fprintf(fp, "\n");
fprintf(fp, " -i, --input-format=(ctf | lttng-live)\n");
fprintf(fp, " `ctf`:\n");
- fprintf(fp, " Create an implicit `ctf.fs` source\n");
+ fprintf(fp, " Create an implicit `source.ctf.fs`\n");
fprintf(fp, " component\n");
fprintf(fp, " `lttng-live`:\n");
- fprintf(fp, " Create an implicit `ctf.lttng-live`\n");
- fprintf(fp, " source component\n");
- fprintf(fp, " -o, --output-format=(text | dummy | ctf-metadata)\n");
+ fprintf(fp, " Create an implicit `source.ctf.lttng-live`\n");
+ fprintf(fp, " component\n");
+ fprintf(fp, " -o, --output-format=(text | ctf | dummy | ctf-metadata)\n");
fprintf(fp, " `text`:\n");
- fprintf(fp, " Create an implicit `text.text` sink\n");
+ fprintf(fp, " Create an implicit `sink.text.pretty`\n");
+ fprintf(fp, " component\n");
+ fprintf(fp, " `ctf`:\n");
+ fprintf(fp, " Create an implicit `sink.ctf.fs`\n");
fprintf(fp, " component\n");
fprintf(fp, " `dummy`:\n");
- fprintf(fp, " Create an implicit `utils.dummy` sink\n");
+ fprintf(fp, " Create an implicit `sink.utils.dummy`\n");
fprintf(fp, " component\n");
fprintf(fp, " `ctf-metadata`:\n");
- fprintf(fp, " Query the `ctf.fs` component class for\n");
- fprintf(fp, " metadata text and quit\n");
+ fprintf(fp, " Query the `source.ctf.fs` component class\n");
+ fprintf(fp, " for metadata text and quit\n");
fprintf(fp, "\n");
fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
fprintf(fp, "\n\n");
{ "clock-offset-ns", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET_NS, NULL, NULL },
{ "clock-seconds", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL },
{ "color", '\0', POPT_ARG_STRING, NULL, OPT_COLOR, NULL, NULL },
+ { "component", 'c', POPT_ARG_STRING, NULL, OPT_COMPONENT, NULL, NULL },
{ "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
{ "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
{ "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
{ "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
{ "end", 'e', POPT_ARG_STRING, NULL, OPT_END, NULL, NULL },
{ "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
- { "filter", '\0', POPT_ARG_STRING, NULL, OPT_FILTER, NULL, NULL },
{ "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
{ "input-format", 'i', POPT_ARG_STRING, NULL, OPT_INPUT_FORMAT, NULL, NULL },
{ "name", '\0', POPT_ARG_STRING, NULL, OPT_NAME, NULL, NULL },
{ "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
- { "no-debug-info", '\0', POPT_ARG_NONE, NULL, OPT_NO_DEBUG_INFO, NULL, NULL },
+ { "debug-info", '\0', POPT_ARG_NONE, NULL, OPT_DEBUG_INFO, NULL, NULL },
{ "no-delta", '\0', POPT_ARG_NONE, NULL, OPT_NO_DELTA, 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 },
{ "retry-duration", '\0', POPT_ARG_STRING, NULL, OPT_RETRY_DURATION, NULL, NULL },
{ "run-args", '\0', POPT_ARG_NONE, NULL, OPT_RUN_ARGS, NULL, NULL },
{ "run-args-0", '\0', POPT_ARG_NONE, NULL, OPT_RUN_ARGS_0, NULL, NULL },
- { "sink", '\0', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
- { "source", '\0', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
{ "stream-intersection", '\0', POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL },
{ "timerange", '\0', POPT_ARG_STRING, NULL, OPT_TIMERANGE, NULL, NULL },
{ "url", 'u', POPT_ARG_STRING, NULL, OPT_URL, NULL, NULL },
struct implicit_component_args {
bool exists;
- GString *plugin_comp_cls_arg;
+ GString *comp_arg;
GString *name_arg;
GString *params_arg;
- struct bt_value *extra_args;
+ struct bt_value *extra_params;
};
static
static
int append_run_args_for_implicit_component(
- enum bt_component_class_type type,
struct implicit_component_args *impl_args,
struct bt_value *run_args)
{
goto end;
}
- switch (type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- if (bt_value_array_append_string(run_args, "--source")) {
- print_err_oom();
- goto error;
- }
- break;
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- if (bt_value_array_append_string(run_args, "--filter")) {
- print_err_oom();
- goto error;
- }
- break;
- case BT_COMPONENT_CLASS_TYPE_SINK:
- if (bt_value_array_append_string(run_args, "--sink")) {
- print_err_oom();
- goto error;
- }
- break;
- default:
- abort();
+ if (bt_value_array_append_string(run_args, "--component")) {
+ print_err_oom();
+ goto error;
}
- if (bt_value_array_append_string(run_args,
- impl_args->plugin_comp_cls_arg->str)) {
+ if (bt_value_array_append_string(run_args, impl_args->comp_arg->str)) {
print_err_oom();
goto error;
}
}
}
- for (i = 0; i < bt_value_array_size(impl_args->extra_args); i++) {
+ for (i = 0; i < bt_value_array_size(impl_args->extra_params); i++) {
struct bt_value *elem;
const char *arg;
- elem = bt_value_array_get(impl_args->extra_args, i);
+ elem = bt_value_array_get(impl_args->extra_params, i);
if (!elem) {
goto error;
}
}
static
-void destroy_implicit_component_args(struct implicit_component_args *args)
+void finalize_implicit_component_args(struct implicit_component_args *args)
{
assert(args);
- if (args->plugin_comp_cls_arg) {
- g_string_free(args->plugin_comp_cls_arg, TRUE);
+ if (args->comp_arg) {
+ g_string_free(args->comp_arg, TRUE);
}
if (args->name_arg) {
g_string_free(args->params_arg, TRUE);
}
- bt_put(args->extra_args);
+ bt_put(args->extra_params);
+}
+
+static
+void destroy_implicit_component_args(void *args)
+{
+ if (!args) {
+ return;
+ }
+
+ finalize_implicit_component_args(args);
+ g_free(args);
}
static
int init_implicit_component_args(struct implicit_component_args *args,
- const char *plugin_comp_cls_arg, bool exists)
+ const char *comp_arg, bool exists)
{
int ret = 0;
args->exists = exists;
- args->plugin_comp_cls_arg = g_string_new(plugin_comp_cls_arg);
+ args->comp_arg = g_string_new(comp_arg);
args->name_arg = g_string_new(NULL);
args->params_arg = g_string_new(NULL);
- args->extra_args = bt_value_array_create();
+ args->extra_params = bt_value_array_create();
- if (!args->plugin_comp_cls_arg || !args->name_arg ||
- !args->params_arg || !args->extra_args) {
+ if (!args->comp_arg || !args->name_arg ||
+ !args->params_arg || !args->extra_params) {
ret = -1;
- destroy_implicit_component_args(args);
+ finalize_implicit_component_args(args);
print_err_oom();
goto end;
}
}
static
-int append_implicit_component_extra_arg(struct implicit_component_args *args,
+int append_implicit_component_extra_param(struct implicit_component_args *args,
const char *key, const char *value)
{
int ret = 0;
assert(key);
assert(value);
- if (bt_value_array_append_string(args->extra_args, "--key")) {
+ if (bt_value_array_append_string(args->extra_params, "--key")) {
print_err_oom();
ret = -1;
goto end;
}
- if (bt_value_array_append_string(args->extra_args, key)) {
+ if (bt_value_array_append_string(args->extra_params, key)) {
print_err_oom();
ret = -1;
goto end;
}
- if (bt_value_array_append_string(args->extra_args, "--value")) {
+ if (bt_value_array_append_string(args->extra_params, "--value")) {
print_err_oom();
ret = -1;
goto end;
}
- if (bt_value_array_append_string(args->extra_args, value)) {
+ if (bt_value_array_append_string(args->extra_params, value)) {
print_err_oom();
ret = -1;
goto end;
int ret = 0;
if (cur_name_prefix->len > 0) {
- /* We're after a --source/--filter/--sink */
+ /* We're after a --component option */
GString *name = NULL;
bool append_name_opt = false;
* No explicit name was provided for the user
* component.
*/
- name = get_component_auto_name(
- cur_name_prefix->str,
+ name = get_component_auto_name(cur_name_prefix->str,
all_names);
append_name_opt = true;
} else {
return ret;
}
+static
+struct implicit_component_args *create_implicit_component_args(void)
+{
+ struct implicit_component_args *impl_args =
+ g_new0(struct implicit_component_args, 1);
+
+ if (!impl_args) {
+ goto end;
+ }
+
+ if (init_implicit_component_args(impl_args, NULL, true)) {
+ destroy_implicit_component_args(impl_args);
+ impl_args = NULL;
+ goto end;
+ }
+
+end:
+ return impl_args;
+}
+
+static
+int fill_implicit_ctf_inputs_args(GPtrArray *implicit_ctf_inputs_args,
+ struct implicit_component_args *base_implicit_ctf_input_args,
+ GList *leftovers)
+{
+ int ret = 0;
+ GList *leftover;
+
+ for (leftover = leftovers; leftover != NULL;
+ leftover = g_list_next(leftover)) {
+ GString *gs_leftover = leftover->data;
+ struct implicit_component_args *impl_args =
+ create_implicit_component_args();
+
+ if (!impl_args) {
+ print_err_oom();
+ goto error;
+ }
+
+ impl_args->exists = true;
+ g_string_assign(impl_args->comp_arg,
+ base_implicit_ctf_input_args->comp_arg->str);
+ g_string_assign(impl_args->params_arg,
+ base_implicit_ctf_input_args->params_arg->str);
+
+ /*
+ * We need our own copy of the extra parameters because
+ * this is where the unique path goes.
+ */
+ BT_PUT(impl_args->extra_params);
+ impl_args->extra_params =
+ bt_value_copy(base_implicit_ctf_input_args->extra_params);
+ if (!impl_args->extra_params) {
+ print_err_oom();
+ destroy_implicit_component_args(impl_args);
+ goto error;
+ }
+
+ /* Append unique path parameter */
+ ret = append_implicit_component_extra_param(impl_args,
+ "path", gs_leftover->str);
+ if (ret) {
+ destroy_implicit_component_args(impl_args);
+ goto error;
+ }
+
+ g_ptr_array_add(implicit_ctf_inputs_args, impl_args);
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ return ret;
+}
+
/*
* Creates a Babeltrace config object from the arguments of a convert
* command.
static
struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
int *retcode, bool force_omit_system_plugin_path,
- bool force_omit_home_plugin_path, bool force_no_debug_info,
- struct bt_value *initial_plugin_paths)
+ bool force_omit_home_plugin_path,
+ struct bt_value *initial_plugin_paths, char *log_level)
{
poptContext pc = NULL;
char *arg = NULL;
BT_CONFIG_COMPONENT_DEST_UNKNOWN;
int opt, ret = 0;
struct bt_config *cfg = NULL;
- bool got_verbose_opt = false;
- bool got_debug_opt = false;
bool got_input_format_opt = false;
bool got_output_format_opt = false;
bool trimmer_has_begin = false;
bool trimmer_has_end = false;
+ bool stream_intersection_mode = false;
GString *cur_name = NULL;
GString *cur_name_prefix = NULL;
const char *leftover = NULL;
GList *source_names = NULL;
GList *filter_names = NULL;
GList *sink_names = NULL;
- struct implicit_component_args implicit_ctf_args = { 0 };
+ GList *leftovers = NULL;
+ GPtrArray *implicit_ctf_inputs_args = NULL;
+ struct implicit_component_args base_implicit_ctf_input_args = { 0 };
+ 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 };
struct implicit_component_args implicit_text_args = { 0 };
char error_buf[256] = { 0 };
size_t i;
struct bt_common_lttng_live_url_parts lttng_live_url_parts = { 0 };
+ char *output = NULL;
*retcode = 0;
goto end;
}
- if (init_implicit_component_args(&implicit_ctf_args, "ctf.fs", false)) {
+ if (init_implicit_component_args(&base_implicit_ctf_input_args,
+ "source.ctf.fs", false)) {
+ goto error;
+ }
+
+ if (init_implicit_component_args(&implicit_ctf_output_args,
+ "sink.ctf.fs", false)) {
goto error;
}
if (init_implicit_component_args(&implicit_lttng_live_args,
- "ctf.lttng-live", false)) {
+ "source.ctf.lttng-live", false)) {
goto error;
}
- if (init_implicit_component_args(&implicit_text_args, "text.pretty",
- false)) {
+ if (init_implicit_component_args(&implicit_text_args,
+ "sink.text.pretty", false)) {
goto error;
}
- if (init_implicit_component_args(&implicit_dummy_args, "utils.dummy",
- false)) {
+ if (init_implicit_component_args(&implicit_dummy_args,
+ "sink.utils.dummy", false)) {
goto error;
}
if (init_implicit_component_args(&implicit_debug_info_args,
- "lttng-utils.debug-info", !force_no_debug_info)) {
+ "filter.lttng-utils.debug-info", false)) {
goto error;
}
- if (init_implicit_component_args(&implicit_muxer_args, "utils.muxer",
- true)) {
+ if (init_implicit_component_args(&implicit_muxer_args,
+ "filter.utils.muxer", true)) {
goto error;
}
if (init_implicit_component_args(&implicit_trimmer_args,
- "utils.trimmer", false)) {
+ "filter.utils.trimmer", false)) {
+ goto error;
+ }
+
+ implicit_ctf_inputs_args = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) destroy_implicit_component_args);
+ if (!implicit_ctf_inputs_args) {
+ print_err_oom();
goto error;
}
arg = poptGetOptArg(pc);
switch (opt) {
- case OPT_SOURCE:
- case OPT_FILTER:
- case OPT_SINK:
+ case OPT_COMPONENT:
+ {
+ enum bt_component_class_type type;
+ const char *type_prefix;
+
/* Append current component's name if needed */
ret = convert_append_name_param(cur_comp_dest, cur_name,
cur_name_prefix, run_args, all_names,
/* Parse the argument */
plugin_comp_cls_names(arg, &name, &plugin_name,
- &comp_cls_name);
+ &comp_cls_name, &type);
if (!plugin_name || !comp_cls_name) {
- printf_err("Invalid format for --source/--filter/--sink option's argument:\n %s\n",
+ printf_err("Invalid format for --component option's argument:\n %s\n",
arg);
goto error;
}
g_string_assign(cur_name, "");
}
- switch (opt) {
- case OPT_SOURCE:
- cur_comp_dest =
- BT_CONFIG_COMPONENT_DEST_SOURCE;
- if (bt_value_array_append_string(run_args,
- "--source")) {
- print_err_oom();
- goto error;
- }
+ switch (type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
+ type_prefix = "source";
break;
- case OPT_FILTER:
- cur_comp_dest =
- BT_CONFIG_COMPONENT_DEST_FILTER;
- if (bt_value_array_append_string(run_args,
- "--filter")) {
- print_err_oom();
- goto error;
- }
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ cur_comp_dest = BT_CONFIG_COMPONENT_DEST_FILTER;
+ type_prefix = "filter";
break;
- case OPT_SINK:
- cur_comp_dest =
- BT_CONFIG_COMPONENT_DEST_SINK;
- if (bt_value_array_append_string(run_args,
- "--sink")) {
- print_err_oom();
- goto error;
- }
+ case BT_COMPONENT_CLASS_TYPE_SINK:
+ cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK;
+ type_prefix = "sink";
break;
default:
abort();
}
+ if (bt_value_array_append_string(run_args,
+ "--component")) {
+ print_err_oom();
+ goto error;
+ }
+
if (bt_value_array_append_string(run_args, arg)) {
print_err_oom();
goto error;
}
g_string_assign(cur_name_prefix, "");
- g_string_append(cur_name_prefix, plugin_name);
- g_string_append_c(cur_name_prefix, '.');
- g_string_append(cur_name_prefix, comp_cls_name);
+ 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);
plugin_name = NULL;
comp_cls_name = NULL;
break;
+ }
case OPT_PARAMS:
if (cur_name_prefix->len == 0) {
printf_err("No current component of which to set parameters:\n %s\n",
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_FIELDS:
case OPT_INPUT_FORMAT:
case OPT_NAMES:
- case OPT_NO_DEBUG_INFO:
case OPT_NO_DELTA:
case OPT_OUTPUT_FORMAT:
case OPT_OUTPUT:
}
trimmer_has_begin = true;
- ret = append_implicit_component_extra_arg(
+ ret = append_implicit_component_extra_param(
&implicit_trimmer_args, "begin", arg);
implicit_trimmer_args.exists = true;
if (ret) {
}
trimmer_has_end = true;
- ret = append_implicit_component_extra_arg(
+ ret = append_implicit_component_extra_param(
&implicit_trimmer_args, "end", arg);
implicit_trimmer_args.exists = true;
if (ret) {
goto error;
}
- ret = append_implicit_component_extra_arg(
+ ret = append_implicit_component_extra_param(
&implicit_trimmer_args, "begin", begin);
- ret |= append_implicit_component_extra_arg(
+ ret |= append_implicit_component_extra_param(
&implicit_trimmer_args, "end", end);
implicit_trimmer_args.exists = true;
free(begin);
break;
case OPT_CLOCK_FORCE_CORRELATE:
append_implicit_component_param(
- &implicit_muxer_args, "assume-absolute-clock-classes", "yes");
+ &implicit_muxer_args,
+ "assume-absolute-clock-classes", "yes");
break;
case OPT_CLOCK_GMT:
append_implicit_component_param(
&implicit_text_args, "clock-gmt", "yes");
+ append_implicit_component_param(
+ &implicit_trimmer_args, "clock-gmt", "yes");
implicit_text_args.exists = true;
break;
case OPT_CLOCK_OFFSET:
- ret = append_implicit_component_extra_arg(
- &implicit_ctf_args, "clock-offset-cycles", arg);
- implicit_ctf_args.exists = true;
- if (ret) {
- goto error;
- }
+ base_implicit_ctf_input_args.exists = true;
+ append_implicit_component_param(
+ &base_implicit_ctf_input_args,
+ "clock-class-offset-s", arg);
break;
case OPT_CLOCK_OFFSET_NS:
- ret = append_implicit_component_extra_arg(
- &implicit_ctf_args, "clock-offset-ns", arg);
- implicit_ctf_args.exists = true;
- if (ret) {
- goto error;
- }
+ base_implicit_ctf_input_args.exists = true;
+ append_implicit_component_param(
+ &base_implicit_ctf_input_args,
+ "clock-class-offset-ns", arg);
break;
case OPT_CLOCK_SECONDS:
append_implicit_component_param(
implicit_text_args.exists = true;
break;
case OPT_COLOR:
- ret = append_implicit_component_extra_arg(
- &implicit_text_args, "color", arg);
implicit_text_args.exists = true;
+ ret = append_implicit_component_extra_param(
+ &implicit_text_args, "color", arg);
if (ret) {
goto error;
}
break;
- case OPT_NO_DEBUG_INFO:
- implicit_debug_info_args.exists = false;
+ case OPT_DEBUG_INFO:
+ implicit_debug_info_args.exists = true;
break;
case OPT_DEBUG_INFO_DIR:
- ret = append_implicit_component_extra_arg(
- &implicit_debug_info_args, "dir", arg);
+ implicit_debug_info_args.exists = true;
+ ret = append_implicit_component_extra_param(
+ &implicit_debug_info_args, "debug-info-dir", arg);
if (ret) {
goto error;
}
break;
case OPT_DEBUG_INFO_FULL_PATH:
+ implicit_debug_info_args.exists = true;
append_implicit_component_param(
&implicit_debug_info_args, "full-path", "yes");
break;
case OPT_DEBUG_INFO_TARGET_PREFIX:
- ret = append_implicit_component_extra_arg(
+ implicit_debug_info_args.exists = true;
+ ret = append_implicit_component_extra_param(
&implicit_debug_info_args,
"target-prefix", arg);
if (ret) {
goto error;
}
+ implicit_text_args.exists = true;
ret = insert_flat_params_from_array(
implicit_text_args.params_arg,
fields, "field");
goto error;
}
+ implicit_text_args.exists = true;
ret = insert_flat_params_from_array(
implicit_text_args.params_arg,
names, "name");
got_input_format_opt = true;
if (strcmp(arg, "ctf") == 0) {
- implicit_ctf_args.exists = true;
+ base_implicit_ctf_input_args.exists = true;
} else if (strcmp(arg, "lttng-live") == 0) {
implicit_lttng_live_args.exists = true;
} else {
if (strcmp(arg, "text") == 0) {
implicit_text_args.exists = true;
+ } else if (strcmp(arg, "ctf") == 0) {
+ implicit_ctf_output_args.exists = true;
} else if (strcmp(arg, "dummy") == 0) {
implicit_dummy_args.exists = true;
} else if (strcmp(arg, "ctf-metadata") == 0) {
}
break;
case OPT_OUTPUT:
- ret = append_implicit_component_extra_arg(
- &implicit_text_args, "path", arg);
- implicit_text_args.exists = true;
- if (ret) {
+ if (output) {
+ printf_err("Duplicate --output option\n");
+ goto error;
+ }
+
+ output = strdup(arg);
+ if (!output) {
+ print_err_oom();
goto error;
}
break;
print_run_args_0 = true;
break;
case OPT_STREAM_INTERSECTION:
- append_implicit_component_param(&implicit_ctf_args,
- "stream-intersection", "yes");
- implicit_ctf_args.exists = true;
+ /*
+ * Applies to all traces implementing the trace-info
+ * query.
+ */
+ stream_intersection_mode = true;
break;
case OPT_VERBOSE:
- if (got_verbose_opt) {
- printf_err("Duplicate -v/--verbose option\n");
- goto error;
+ if (*log_level != 'V' && *log_level != 'D') {
+ *log_level = 'I';
}
-
- append_implicit_component_param(&implicit_text_args,
- "verbose", "yes");
- implicit_text_args.exists = true;
- got_verbose_opt = true;
break;
case OPT_DEBUG:
- got_debug_opt = true;
+ *log_level = 'V';
break;
}
goto error;
}
+ /*
+ * Legacy behaviour: --verbose used to make the `text` output
+ * format print more information. --verbose is now equivalent to
+ * the INFO log level, which is why we compare to 'I' here.
+ */
+ if (*log_level == 'I') {
+ append_implicit_component_param(&implicit_text_args,
+ "verbose", "yes");
+ }
+
/*
* Append home and system plugin paths now that we possibly got
* --plugin-path.
goto error;
}
- /* Consume leftover argument */
- leftover = poptGetArg(pc);
+ /* Consume and keep leftover arguments */
+ while ((leftover = poptGetArg(pc))) {
+ GString *gs_leftover = g_string_new(leftover);
- if (poptPeekArg(pc)) {
- printf_err("Unexpected argument:\n %s\n",
- poptPeekArg(pc));
- goto error;
+ if (!gs_leftover) {
+ print_err_oom();
+ goto error;
+ }
+
+ leftovers = g_list_append(leftovers, gs_leftover);
+ if (!leftovers) {
+ g_string_free(gs_leftover, TRUE);
+ print_err_oom();
+ goto error;
+ }
}
/* Print CTF metadata or print LTTng live sessions */
if (print_ctf_metadata) {
- if (!leftover) {
+ GString *gs_leftover;
+
+ if (g_list_length(leftovers) == 0) {
printf_err("--output-format=ctf-metadata specified without a path\n");
goto error;
}
+ if (g_list_length(leftovers) > 1) {
+ printf_err("Too many paths specified for --output-format=ctf-metadata\n");
+ goto error;
+ }
+
cfg = bt_config_print_ctf_metadata_create(plugin_paths);
if (!cfg) {
goto error;
}
- cfg->debug = got_debug_opt;
- cfg->verbose = got_verbose_opt;
+ gs_leftover = leftovers->data;
g_string_assign(cfg->cmd_data.print_ctf_metadata.path,
- leftover);
+ gs_leftover->str);
+
+ if (output) {
+ g_string_assign(
+ cfg->cmd_data.print_ctf_metadata.output_path,
+ output);
+ }
+
goto end;
}
/*
- * If -o dummy was not specified, and if there are no explicit
- * sink components, then use an implicit `text.text` sink.
+ * If -o ctf was specified, make sure an output path (--output)
+ * was also specified. --output does not imply -o ctf because
+ * it's also used for the default, implicit -o text if -o ctf
+ * is not specified.
*/
- if (!implicit_dummy_args.exists && !sink_names) {
+ if (implicit_ctf_output_args.exists) {
+ if (!output) {
+ printf_err("--output-format=ctf specified without --output (trace output path)\n");
+ goto error;
+ }
+
+ /*
+ * At this point we know that -o ctf AND --output were
+ * specified. Make sure that no options were specified
+ * which would imply -o text because --output would be
+ * ambiguous in this case. For example, this is wrong:
+ *
+ * babeltrace --names=all -o ctf --output=/tmp/path my-trace
+ *
+ * because --names=all implies -o text, and --output
+ * could apply to both the sink.text.pretty and
+ * sink.ctf.fs implicit components.
+ */
+ if (implicit_text_args.exists) {
+ printf_err("Ambiguous --output option: --output-format=ctf specified but another option implies --output-format=text\n");
+ goto error;
+ }
+ }
+
+ /*
+ * If -o dummy and -o ctf were not specified, and if there are
+ * no explicit sink components, then use an implicit
+ * `sink.text.pretty` component.
+ */
+ if (!implicit_dummy_args.exists && !implicit_ctf_output_args.exists &&
+ !sink_names) {
implicit_text_args.exists = true;
}
- /* Decide where the leftover argument goes */
- if (leftover) {
+ /*
+ * Set implicit `sink.text.pretty` or `sink.ctf.fs` component's
+ * `path` parameter if --output was specified.
+ */
+ if (output) {
+ if (implicit_text_args.exists) {
+ append_implicit_component_extra_param(&implicit_text_args,
+ "path", output);
+ } else if (implicit_ctf_output_args.exists) {
+ append_implicit_component_extra_param(&implicit_ctf_output_args,
+ "path", output);
+ }
+ }
+
+ /* Decide where the leftover argument(s) go */
+ if (g_list_length(leftovers) > 0) {
if (implicit_lttng_live_args.exists) {
+ GString *gs_leftover;
+
+ if (g_list_length(leftovers) > 1) {
+ printf_err("Too many URLs specified for --output-format=lttng-live\n");
+ goto error;
+ }
+
+ gs_leftover = leftovers->data;
lttng_live_url_parts =
- bt_common_parse_lttng_live_url(leftover,
+ bt_common_parse_lttng_live_url(gs_leftover->str,
error_buf, sizeof(error_buf));
if (!lttng_live_url_parts.proto) {
printf_err("Invalid LTTng live URL format: %s\n",
goto error;
}
- cfg->debug = got_debug_opt;
- cfg->verbose = got_verbose_opt;
g_string_assign(cfg->cmd_data.print_lttng_live_sessions.url,
- leftover);
+ gs_leftover->str);
+
+ if (output) {
+ g_string_assign(
+ cfg->cmd_data.print_lttng_live_sessions.output_path,
+ output);
+ }
+
goto end;
}
- ret = append_implicit_component_extra_arg(
- &implicit_lttng_live_args, "url", leftover);
+ ret = append_implicit_component_extra_param(
+ &implicit_lttng_live_args, "url",
+ gs_leftover->str);
if (ret) {
goto error;
}
} else {
- ret = append_implicit_component_extra_arg(
- &implicit_ctf_args, "path", leftover);
- implicit_ctf_args.exists = true;
+ /*
+ * Append one implicit component argument set
+ * for each leftover (souce.ctf.fs paths). Copy
+ * the base implicit component arguments.
+ * Note that they still have to be named later.
+ */
+ ret = fill_implicit_ctf_inputs_args(
+ implicit_ctf_inputs_args,
+ &base_implicit_ctf_input_args, leftovers);
if (ret) {
goto error;
}
}
/*
- * Ensure mutual exclusion between implicit `ctf.fs` and
- * `ctf.lttng-live` sources.
+ * Ensure mutual exclusion between implicit `source.ctf.fs` and
+ * `source.ctf.lttng-live` components.
*/
- if (implicit_ctf_args.exists && implicit_lttng_live_args.exists) {
- printf_err("Cannot create both implicit `%s` and `%s` source components\n",
- implicit_ctf_args.plugin_comp_cls_arg->str,
- implicit_lttng_live_args.plugin_comp_cls_arg->str);
+ if (base_implicit_ctf_input_args.exists &&
+ implicit_lttng_live_args.exists) {
+ printf_err("Cannot create both implicit `%s` and `%s` components\n",
+ base_implicit_ctf_input_args.comp_arg->str,
+ implicit_lttng_live_args.comp_arg->str);
goto error;
}
/*
- * If the implicit `ctf.fs` or `ctf.lttng-live` source exists,
- * make sure there's a leftover (which is the path or URL).
+ * If the implicit `source.ctf.fs` or `source.ctf.lttng-live`
+ * components exists, make sure there's at least one leftover
+ * (which is the path or URL).
*/
- if (implicit_ctf_args.exists && !leftover) {
- printf_err("Missing path for implicit `%s` source component\n",
- implicit_ctf_args.plugin_comp_cls_arg->str);
+ if (base_implicit_ctf_input_args.exists &&
+ g_list_length(leftovers) == 0) {
+ printf_err("Missing path for implicit `%s` component\n",
+ base_implicit_ctf_input_args.comp_arg->str);
goto error;
}
- if (implicit_lttng_live_args.exists && !leftover) {
- printf_err("Missing URL for implicit `%s` source component\n",
- implicit_lttng_live_args.plugin_comp_cls_arg->str);
+ if (implicit_lttng_live_args.exists && g_list_length(leftovers) == 0) {
+ printf_err("Missing URL for implicit `%s` component\n",
+ implicit_lttng_live_args.comp_arg->str);
goto error;
}
/* Assign names to implicit components */
- ret = assign_name_to_implicit_component(&implicit_ctf_args,
- "ctf-fs", all_names, &source_names, true);
- if (ret) {
- goto error;
+ for (i = 0; i < implicit_ctf_inputs_args->len; i++) {
+ struct implicit_component_args *impl_args =
+ g_ptr_array_index(implicit_ctf_inputs_args, i);
+
+ ret = assign_name_to_implicit_component(impl_args,
+ "source-ctf-fs", all_names, &source_names, true);
+ if (ret) {
+ goto error;
+ }
}
ret = assign_name_to_implicit_component(&implicit_lttng_live_args,
goto error;
}
+ ret = assign_name_to_implicit_component(&implicit_ctf_output_args,
+ "sink-ctf-fs", all_names, &sink_names, true);
+ if (ret) {
+ goto error;
+ }
+
ret = assign_name_to_implicit_component(&implicit_dummy_args,
"dummy", all_names, &sink_names, true);
if (ret) {
* Append the equivalent run arguments for the implicit
* components.
*/
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_SOURCE, &implicit_ctf_args, run_args);
+ for (i = 0; i < implicit_ctf_inputs_args->len; i++) {
+ struct implicit_component_args *impl_args =
+ g_ptr_array_index(implicit_ctf_inputs_args, i);
+
+ ret = append_run_args_for_implicit_component(impl_args,
+ run_args);
+ if (ret) {
+ goto error;
+ }
+ }
+
+ ret = append_run_args_for_implicit_component(&implicit_lttng_live_args,
+ run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_SOURCE, &implicit_lttng_live_args,
+ ret = append_run_args_for_implicit_component(&implicit_text_args,
run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_SINK, &implicit_text_args, run_args);
+ ret = append_run_args_for_implicit_component(&implicit_ctf_output_args,
+ run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_SINK, &implicit_dummy_args, run_args);
+ ret = append_run_args_for_implicit_component(&implicit_dummy_args,
+ run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_FILTER, &implicit_muxer_args, run_args);
+ ret = append_run_args_for_implicit_component(&implicit_muxer_args,
+ run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_FILTER, &implicit_trimmer_args,
+ ret = append_run_args_for_implicit_component(&implicit_trimmer_args,
run_args);
if (ret) {
goto error;
}
- ret = append_run_args_for_implicit_component(
- BT_COMPONENT_CLASS_TYPE_FILTER, &implicit_debug_info_args,
+ ret = append_run_args_for_implicit_component(&implicit_debug_info_args,
run_args);
if (ret) {
goto error;
* here.
*/
if (print_run_args || print_run_args_0) {
+ if (stream_intersection_mode) {
+ printf_err("Cannot specify --stream-intersection with --run-args or --run-args-0\n");
+ goto error;
+ }
+
for (i = 0; i < bt_value_array_size(run_args); i++) {
struct bt_value *arg_value =
bt_value_array_get(run_args, i);
cfg = bt_config_run_from_args_array(run_args, retcode,
force_omit_system_plugin_path, force_omit_home_plugin_path,
initial_plugin_paths);
+ if (!cfg) {
+ goto error;
+ }
+
+ cfg->cmd_data.run.stream_intersection_mode = stream_intersection_mode;
goto end;
error:
}
free(arg);
+ free(output);
if (cur_name) {
g_string_free(cur_name, TRUE);
g_string_free(cur_name_prefix, TRUE);
}
+ if (implicit_ctf_inputs_args) {
+ g_ptr_array_free(implicit_ctf_inputs_args, TRUE);
+ }
+
bt_put(run_args);
bt_put(all_names);
destroy_glist_of_gstring(source_names);
destroy_glist_of_gstring(filter_names);
destroy_glist_of_gstring(sink_names);
- destroy_implicit_component_args(&implicit_ctf_args);
- destroy_implicit_component_args(&implicit_lttng_live_args);
- destroy_implicit_component_args(&implicit_dummy_args);
- destroy_implicit_component_args(&implicit_text_args);
- destroy_implicit_component_args(&implicit_debug_info_args);
- destroy_implicit_component_args(&implicit_muxer_args);
- destroy_implicit_component_args(&implicit_trimmer_args);
+ destroy_glist_of_gstring(leftovers);
+ finalize_implicit_component_args(&base_implicit_ctf_input_args);
+ finalize_implicit_component_args(&implicit_ctf_output_args);
+ finalize_implicit_component_args(&implicit_lttng_live_args);
+ finalize_implicit_component_args(&implicit_dummy_args);
+ finalize_implicit_component_args(&implicit_text_args);
+ finalize_implicit_component_args(&implicit_debug_info_args);
+ finalize_implicit_component_args(&implicit_muxer_args);
+ finalize_implicit_component_args(&implicit_trimmer_args);
bt_put(plugin_paths);
bt_common_destroy_lttng_live_url_parts(<tng_live_url_parts);
return cfg;
fprintf(fp, "\n");
fprintf(fp, "General options:\n");
fprintf(fp, "\n");
- fprintf(fp, " -d, --debug Turn on debug mode\n");
- fprintf(fp, " -h --help Show this help and quit\n");
- fprintf(fp, " -v, --verbose Turn on verbose mode\n");
- fprintf(fp, " -V, --version Show version and quit\n");
+ fprintf(fp, " -d, --debug Enable debug mode (same as --log-level=V)\n");
+ fprintf(fp, " -h, --help Show this help and quit\n");
+ fprintf(fp, " --log-level=LVL Set all log levels to LVL (`N`, `V`, `D`,\n");
+ fprintf(fp, " `I`, `W` (default), `E`, or `F`)\n");
+ fprintf(fp, " -v, --verbose Enable verbose mode (same as --log-level=I)\n");
+ fprintf(fp, " -V, --version Show version and quit\n");
fprintf(fp, "\n");
fprintf(fp, "Available commands:\n");
fprintf(fp, "\n");
fprintf(fp, "Use `babeltrace COMMAND --help` to show the help of COMMAND.\n");
}
+static
+char log_level_from_arg(const char *arg)
+{
+ char level = 'U';
+
+ if (strcmp(arg, "VERBOSE") == 0 ||
+ strcmp(arg, "V") == 0) {
+ level = 'V';
+ } else if (strcmp(arg, "DEBUG") == 0 ||
+ strcmp(arg, "D") == 0) {
+ level = 'D';
+ } else if (strcmp(arg, "INFO") == 0 ||
+ strcmp(arg, "I") == 0) {
+ level = 'I';
+ } else if (strcmp(arg, "WARN") == 0 ||
+ strcmp(arg, "WARNING") == 0 ||
+ strcmp(arg, "W") == 0) {
+ level = 'W';
+ } else if (strcmp(arg, "ERROR") == 0 ||
+ strcmp(arg, "E") == 0) {
+ level = 'E';
+ } else if (strcmp(arg, "FATAL") == 0 ||
+ strcmp(arg, "F") == 0) {
+ level = 'F';
+ } else if (strcmp(arg, "NONE") == 0 ||
+ strcmp(arg, "N") == 0) {
+ level = 'N';
+ }
+
+ return level;
+}
+
struct bt_config *bt_config_cli_args_create(int argc, const char *argv[],
int *retcode, bool force_omit_system_plugin_path,
- bool force_omit_home_plugin_path, bool force_no_debug_info,
+ bool force_omit_home_plugin_path,
struct bt_value *initial_plugin_paths)
{
struct bt_config *config = NULL;
- bool verbose = false;
- bool debug = false;
int i;
const char **command_argv = NULL;
int command_argc = -1;
const char *command_name = NULL;
+ char log_level = 'U';
enum command_type {
COMMAND_TYPE_NONE = -1,
}
if (argc <= 1) {
+ print_version();
+ puts("");
print_gen_usage(stdout);
goto end;
}
for (i = 1; i < argc; i++) {
const char *cur_arg = argv[i];
+ const char *next_arg = i == (argc - 1) ? NULL : argv[i + 1];
if (strcmp(cur_arg, "-d") == 0 ||
strcmp(cur_arg, "--debug") == 0) {
- debug = true;
+ log_level = 'V';
} else if (strcmp(cur_arg, "-v") == 0 ||
strcmp(cur_arg, "--verbose") == 0) {
- verbose = true;
+ if (log_level != 'V' && log_level != 'D') {
+ /*
+ * Legacy: do not override a previous
+ * --debug because --verbose and --debug
+ * can be specified together (in this
+ * case we want the lowest log level to
+ * apply, VERBOSE).
+ */
+ log_level = 'I';
+ }
+ } else if (strcmp(cur_arg, "--log-level") == 0) {
+ if (!next_arg) {
+ printf_err("Missing log level value for --log-level option\n");
+ *retcode = 1;
+ goto end;
+ }
+
+ log_level = log_level_from_arg(next_arg);
+ if (log_level == 'U') {
+ printf_err("Invalid argument for --log-level option:\n %s\n",
+ next_arg);
+ *retcode = 1;
+ goto end;
+ }
+
+ i++;
+ } else if (strncmp(cur_arg, "--log-level=", 12) == 0) {
+ const char *arg = &cur_arg[12];
+
+ log_level = log_level_from_arg(arg);
+ if (log_level == 'U') {
+ printf_err("Invalid argument for --log-level option:\n %s\n",
+ arg);
+ *retcode = 1;
+ goto end;
+ }
} else if (strcmp(cur_arg, "-V") == 0 ||
strcmp(cur_arg, "--version") == 0) {
print_version();
print_gen_usage(stdout);
goto end;
} else {
- bool has_command = true;
-
/*
* First unknown argument: is it a known command
* name?
*/
+ command_argv = &argv[i];
+ command_argc = argc - i;
+
if (strcmp(cur_arg, "convert") == 0) {
command_type = COMMAND_TYPE_CONVERT;
} else if (strcmp(cur_arg, "list-plugins") == 0) {
} else {
/*
* Unknown argument, but not a known
- * command name: assume the whole
- * arguments are for the default convert
- * command.
+ * command name: assume the default
+ * `convert` command.
*/
command_type = COMMAND_TYPE_CONVERT;
- command_argv = argv;
- command_argc = argc;
- has_command = false;
- }
-
- if (has_command) {
- command_argv = &argv[i];
- command_argc = argc - i;
- command_name = cur_arg;
+ command_name = "convert";
+ command_argv = &argv[i - 1];
+ command_argc = argc - i + 1;
}
break;
}
case COMMAND_TYPE_CONVERT:
config = bt_config_convert_from_args(command_argc, command_argv,
retcode, force_omit_system_plugin_path,
- force_omit_home_plugin_path, force_no_debug_info,
- initial_plugin_paths);
+ force_omit_home_plugin_path,
+ initial_plugin_paths, &log_level);
break;
case COMMAND_TYPE_LIST_PLUGINS:
config = bt_config_list_plugins_from_args(command_argc,
}
if (config) {
- if (verbose) {
- config->verbose = true;
- }
-
- if (debug) {
- config->debug = true;
+ if (log_level == 'U') {
+ log_level = 'W';
}
+ config->log_level = log_level;
config->command_name = command_name;
}