From: Philippe Proulx Date: Tue, 4 Apr 2017 22:04:44 +0000 (-0400) Subject: Rename text.text sink CC to text.pretty X-Git-Tag: v2.0.0-pre1~380 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=3228cc1db0ba3ff2b9007de3872fe61b66502493 Rename text.text sink CC to text.pretty The `text` plugin is expected to contain more than the `text` sink: it could eventually read and write many plain text formats. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/configure.ac b/configure.ac index 18335bd5..753a7778 100644 --- a/configure.ac +++ b/configure.ac @@ -499,6 +499,7 @@ AC_CONFIG_FILES([ plugins/ctf/lttng-live/Makefile plugins/muxer/Makefile plugins/text/Makefile + plugins/text/pretty/Makefile plugins/writer/Makefile plugins/utils/Makefile plugins/utils/dummy/Makefile diff --git a/plugins/text/Makefile.am b/plugins/text/Makefile.am index ecf82367..105742b6 100644 --- a/plugins/text/Makefile.am +++ b/plugins/text/Makefile.am @@ -1,19 +1,13 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins -SUBDIRS = . +SUBDIRS = pretty . plugindir = "$(PLUGINSDIR)" -plugin_LTLIBRARIES = libbabeltrace-plugin-ctf-text.la +plugin_LTLIBRARIES = libbabeltrace-plugin-text.la -# ctf-text plugin -libbabeltrace_plugin_ctf_text_la_SOURCES = \ - text.c \ - print.c \ - text.h - -libbabeltrace_plugin_ctf_text_la_LDFLAGS = \ +libbabeltrace_plugin_text_la_SOURCES = plugin.c +libbabeltrace_plugin_text_la_LDFLAGS = \ -version-info $(BABELTRACE_LIBRARY_VERSION) - -libbabeltrace_plugin_ctf_text_la_LIBADD = \ +libbabeltrace_plugin_text_la_LIBADD = \ $(top_builddir)/lib/libbabeltrace.la \ - $(top_builddir)/common/libbabeltrace-common.la + pretty/libbabeltrace-plugin-text-pretty-cc.la diff --git a/plugins/text/plugin.c b/plugins/text/plugin.c new file mode 100644 index 00000000..a7691019 --- /dev/null +++ b/plugins/text/plugin.c @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include "pretty/pretty.h" + +BT_PLUGIN(text); +BT_PLUGIN_DESCRIPTION("Plain text component classes"); +BT_PLUGIN_AUTHOR("Julien Desfossez, Mathieu Desnoyers, Philippe Proulx"); +BT_PLUGIN_LICENSE("MIT"); + +/* pretty sink */ +BT_PLUGIN_SINK_COMPONENT_CLASS(pretty, pretty_consume); +BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(pretty, pretty_init); +BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(pretty, pretty_finalize); +BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(pretty, + pretty_accept_port_connection); +BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty, + "Pretty-printing text output (`text` format of Babeltrace 1)"); diff --git a/plugins/text/pretty/Makefile.am b/plugins/text/pretty/Makefile.am new file mode 100644 index 00000000..badc92a9 --- /dev/null +++ b/plugins/text/pretty/Makefile.am @@ -0,0 +1,14 @@ +AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins + +SUBDIRS = . + +noinst_LTLIBRARIES = libbabeltrace-plugin-text-pretty-cc.la + +# ctf-text plugin +libbabeltrace_plugin_text_pretty_cc_la_SOURCES = \ + pretty.c \ + print.c \ + pretty.h + +libbabeltrace_plugin_text_pretty_cc_la_LIBADD = \ + $(top_builddir)/common/libbabeltrace-common.la diff --git a/plugins/text/pretty/pretty.c b/plugins/text/pretty/pretty.c new file mode 100644 index 00000000..48a71472 --- /dev/null +++ b/plugins/text/pretty/pretty.c @@ -0,0 +1,787 @@ +/* + * pretty.c + * + * Babeltrace CTF Text Output Plugin + * + * Copyright 2016 Jérémie Galarneau + * Copyright 2016 Mathieu Desnoyers + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pretty.h" + +static +const char *plugin_options[] = { + "color", + "output-path", + "debug-info-dir", + "debug-info-target-prefix", + "debug-info-full-path", + "no-delta", + "clock-cycles", + "clock-seconds", + "clock-date", + "clock-gmt", + "verbose", + "name-default", /* show/hide */ + "name-payload", + "name-context", + "name-scope", + "name-header", + "field-default", /* show/hide */ + "field-trace", + "field-trace:hostname", + "field-trace:domain", + "field-trace:procname", + "field-trace:vpid", + "field-loglevel", + "field-emf", + "field-callsite", +}; + +static +void destroy_pretty_data(struct pretty_component *pretty) +{ + bt_put(pretty->input_iterator); + (void) g_string_free(pretty->string, TRUE); + if (pretty->out != stdout) { + int ret; + + ret = fclose(pretty->out); + if (ret) { + perror("close output file"); + } + } + g_free(pretty->options.output_path); + g_free(pretty->options.debug_info_dir); + g_free(pretty->options.debug_info_target_prefix); + g_free(pretty); +} + +static +struct pretty_component *create_pretty(void) +{ + struct pretty_component *pretty; + + pretty = g_new0(struct pretty_component, 1); + if (!pretty) { + goto end; + } + pretty->string = g_string_new(""); + if (!pretty->string) { + goto error; + } +end: + return pretty; + +error: + g_free(pretty); + return NULL; +} + +BT_HIDDEN +void pretty_finalize(struct bt_private_component *component) +{ + void *data = bt_private_component_get_user_data(component); + + destroy_pretty_data(data); +} + +static +enum bt_component_status handle_notification(struct pretty_component *pretty, + struct bt_notification *notification) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + + if (!pretty) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + switch (bt_notification_get_type(notification)) { + case BT_NOTIFICATION_TYPE_PACKET_BEGIN: + break; + case BT_NOTIFICATION_TYPE_PACKET_END: + break; + case BT_NOTIFICATION_TYPE_EVENT: + { + struct bt_ctf_event *event = bt_notification_event_get_event( + notification); + + if (!event) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = pretty_print_event(pretty, event); + bt_put(event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + break; + } + case BT_NOTIFICATION_TYPE_STREAM_END: + break; + default: + puts("Unhandled notification type"); + } +end: + return ret; +} + +BT_HIDDEN +enum bt_component_status pretty_accept_port_connection( + struct bt_private_component *component, + struct bt_private_port *self_port, + struct bt_port *other_port) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_private_connection *connection; + struct pretty_component *pretty; + + pretty = bt_private_component_get_user_data(component); + assert(pretty); + assert(!pretty->input_iterator); + connection = bt_private_port_get_private_connection(self_port); + assert(connection); + pretty->input_iterator = + bt_private_connection_create_notification_iterator(connection); + + if (!pretty->input_iterator) { + ret = BT_COMPONENT_STATUS_ERROR; + } + + bt_put(connection); + return ret; +} + +BT_HIDDEN +enum bt_component_status pretty_consume(struct bt_private_component *component) +{ + enum bt_component_status ret; + struct bt_notification *notification = NULL; + struct bt_notification_iterator *it; + struct pretty_component *pretty = + bt_private_component_get_user_data(component); + enum bt_notification_iterator_status it_ret; + + it = pretty->input_iterator; + + it_ret = bt_notification_iterator_next(it); + switch (it_ret) { + case BT_NOTIFICATION_ITERATOR_STATUS_ERROR: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + case BT_NOTIFICATION_ITERATOR_STATUS_END: + ret = BT_COMPONENT_STATUS_END; + BT_PUT(pretty->input_iterator); + goto end; + default: + break; + } + + notification = bt_notification_iterator_get_notification(it); + assert(notification); + ret = handle_notification(pretty, notification); + pretty->processed_first_event = true; +end: + bt_put(notification); + return ret; +} + +static +enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + unsigned int i; + + for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) { + const char *key = plugin_options[i]; + enum bt_value_status status; + + status = bt_value_map_insert(plugin_opt_map, key, bt_value_null); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + } +end: + return ret; +} + +static +bool check_param_exists(const char *key, struct bt_value *object, void *data) +{ + struct pretty_component *pretty = data; + struct bt_value *plugin_opt_map = pretty->plugin_opt_map; + + if (!bt_value_map_get(plugin_opt_map, key)) { + fprintf(pretty->err, + "[warning] Parameter \"%s\" unknown to \"text.pretty\" sink component\n", key); + } + return true; +} + +static +enum bt_component_status apply_one_string(const char *key, + struct bt_value *params, + char **option) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_value *value = NULL; + enum bt_value_status status; + const char *str; + + value = bt_value_map_get(params, key); + if (!value) { + goto end; + } + if (bt_value_is_null(value)) { + goto end; + } + status = bt_value_string_get(value, &str); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + *option = g_strdup(str); +end: + bt_put(value); + return ret; +} + +static +enum bt_component_status apply_one_bool(const char *key, + struct bt_value *params, + bool *option, + bool *found) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_value *value = NULL; + enum bt_value_status status; + + value = bt_value_map_get(params, key); + if (!value) { + goto end; + } + status = bt_value_bool_get(value, option); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (found) { + *found = true; + } +end: + bt_put(value); + return ret; +} + +static +void warn_wrong_color_param(struct pretty_component *pretty) +{ + fprintf(pretty->err, + "[warning] Accepted values for the \"color\" parameter are:\n \"always\", \"auto\", \"never\"\n"); +} + +static +enum bt_component_status open_output_file(struct pretty_component *pretty) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + + if (!pretty->options.output_path) { + goto end; + } + + pretty->out = fopen(pretty->options.output_path, "w"); + if (!pretty->out) { + goto error; + } + + goto end; + +error: + ret = BT_COMPONENT_STATUS_ERROR; +end: + return ret; +} + +static +enum bt_component_status apply_params(struct pretty_component *pretty, + struct bt_value *params) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + enum bt_value_status status; + bool value, found; + char *str = NULL; + + pretty->plugin_opt_map = bt_value_map_create(); + if (!pretty->plugin_opt_map) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = add_params_to_map(pretty->plugin_opt_map); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + /* Report unknown parameters. */ + status = bt_value_map_foreach(params, check_param_exists, pretty); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + /* Known parameters. */ + pretty->options.color = PRETTY_COLOR_OPT_AUTO; + if (bt_value_map_has_key(params, "color")) { + struct bt_value *color_value; + const char *color; + + color_value = bt_value_map_get(params, "color"); + if (!color_value) { + goto end; + } + + status = bt_value_string_get(color_value, &color); + if (status) { + warn_wrong_color_param(pretty); + } else { + if (strcmp(color, "never") == 0) { + pretty->options.color = PRETTY_COLOR_OPT_NEVER; + } else if (strcmp(color, "auto") == 0) { + pretty->options.color = PRETTY_COLOR_OPT_AUTO; + } else if (strcmp(color, "always") == 0) { + pretty->options.color = PRETTY_COLOR_OPT_ALWAYS; + } else { + warn_wrong_color_param(pretty); + } + } + + bt_put(color_value); + } + + ret = apply_one_string("output-path", + params, + &pretty->options.output_path); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + ret = open_output_file(pretty); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = apply_one_string("debug-info-dir", + params, + &pretty->options.debug_info_dir); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = apply_one_string("debug-info-target-prefix", + params, + &pretty->options.debug_info_target_prefix); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + value = false; /* Default. */ + ret = apply_one_bool("debug-info-full-path", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.debug_info_full_path = value; + + value = false; /* Default. */ + ret = apply_one_bool("no-delta", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.print_delta_field = !value; /* Reverse logic. */ + + value = false; /* Default. */ + ret = apply_one_bool("clock-cycles", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.print_timestamp_cycles = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-seconds", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.clock_seconds = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-date", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.clock_date = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-gmt", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.clock_gmt = value; + + value = false; /* Default. */ + ret = apply_one_bool("verbose", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->options.verbose = value; + + /* Names. */ + ret = apply_one_string("name-default", params, &str); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (!str) { + pretty->options.name_default = PRETTY_DEFAULT_UNSET; + } else if (!strcmp(str, "show")) { + pretty->options.name_default = PRETTY_DEFAULT_SHOW; + } else if (!strcmp(str, "hide")) { + pretty->options.name_default = PRETTY_DEFAULT_HIDE; + } else { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + g_free(str); + str = NULL; + + switch (pretty->options.name_default) { + case PRETTY_DEFAULT_UNSET: + pretty->options.print_payload_field_names = true; + pretty->options.print_context_field_names = true; + pretty->options.print_header_field_names = false; + pretty->options.print_scope_field_names = false; + break; + case PRETTY_DEFAULT_SHOW: + pretty->options.print_payload_field_names = true; + pretty->options.print_context_field_names = true; + pretty->options.print_header_field_names = true; + pretty->options.print_scope_field_names = true; + break; + case PRETTY_DEFAULT_HIDE: + pretty->options.print_payload_field_names = false; + pretty->options.print_context_field_names = false; + pretty->options.print_header_field_names = false; + pretty->options.print_scope_field_names = false; + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + value = false; + found = false; + ret = apply_one_bool("name-payload", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_payload_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-context", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_context_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-header", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_header_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-scope", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_scope_field_names = value; + } + + /* Fields. */ + ret = apply_one_string("field-default", params, &str); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (!str) { + pretty->options.field_default = PRETTY_DEFAULT_UNSET; + } else if (!strcmp(str, "show")) { + pretty->options.field_default = PRETTY_DEFAULT_SHOW; + } else if (!strcmp(str, "hide")) { + pretty->options.field_default = PRETTY_DEFAULT_HIDE; + } else { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + g_free(str); + str = NULL; + + switch (pretty->options.field_default) { + case PRETTY_DEFAULT_UNSET: + pretty->options.print_trace_field = false; + pretty->options.print_trace_hostname_field = true; + pretty->options.print_trace_domain_field = false; + pretty->options.print_trace_procname_field = true; + pretty->options.print_trace_vpid_field = true; + pretty->options.print_loglevel_field = false; + pretty->options.print_emf_field = false; + pretty->options.print_callsite_field = false; + break; + case PRETTY_DEFAULT_SHOW: + pretty->options.print_trace_field = true; + pretty->options.print_trace_hostname_field = true; + pretty->options.print_trace_domain_field = true; + pretty->options.print_trace_procname_field = true; + pretty->options.print_trace_vpid_field = true; + pretty->options.print_loglevel_field = true; + pretty->options.print_emf_field = true; + pretty->options.print_callsite_field = true; + break; + case PRETTY_DEFAULT_HIDE: + pretty->options.print_trace_field = false; + pretty->options.print_trace_hostname_field = false; + pretty->options.print_trace_domain_field = false; + pretty->options.print_trace_procname_field = false; + pretty->options.print_trace_vpid_field = false; + pretty->options.print_loglevel_field = false; + pretty->options.print_emf_field = false; + pretty->options.print_callsite_field = false; + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_trace_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:hostname", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_trace_hostname_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:domain", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_trace_domain_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:procname", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_trace_procname_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:vpid", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_trace_vpid_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-loglevel", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_loglevel_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-emf", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_emf_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-callsite", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + pretty->options.print_callsite_field = value; + } + +end: + bt_put(pretty->plugin_opt_map); + pretty->plugin_opt_map = NULL; + g_free(str); + return ret; +} + +static +void set_use_colors(struct pretty_component *pretty) +{ + switch (pretty->options.color) { + case PRETTY_COLOR_OPT_ALWAYS: + pretty->use_colors = true; + break; + case PRETTY_COLOR_OPT_AUTO: + pretty->use_colors = pretty->out == stdout && + bt_common_colors_supported(); + break; + case PRETTY_COLOR_OPT_NEVER: + pretty->use_colors = false; + break; + } +} + +static +void init_stream_packet_context_quarks(void) +{ + stream_packet_context_quarks[Q_TIMESTAMP_BEGIN] = + g_quark_from_string("timestamp_begin"); + stream_packet_context_quarks[Q_TIMESTAMP_BEGIN] = + g_quark_from_string("timestamp_begin"); + stream_packet_context_quarks[Q_TIMESTAMP_END] = + g_quark_from_string("timestamp_end"); + stream_packet_context_quarks[Q_EVENTS_DISCARDED] = + g_quark_from_string("events_discarded"); + stream_packet_context_quarks[Q_CONTENT_SIZE] = + g_quark_from_string("content_size"); + stream_packet_context_quarks[Q_PACKET_SIZE] = + g_quark_from_string("packet_size"); + stream_packet_context_quarks[Q_PACKET_SEQ_NUM] = + g_quark_from_string("packet_seq_num"); +} + +BT_HIDDEN +enum bt_component_status pretty_init( + struct bt_private_component *component, + struct bt_value *params, + UNUSED_VAR void *init_method_data) +{ + enum bt_component_status ret; + struct pretty_component *pretty = create_pretty(); + + if (!pretty) { + ret = BT_COMPONENT_STATUS_NOMEM; + goto end; + } + + pretty->out = stdout; + pretty->err = stderr; + + pretty->delta_cycles = -1ULL; + pretty->last_cycles_timestamp = -1ULL; + + pretty->delta_real_timestamp = -1ULL; + pretty->last_real_timestamp = -1ULL; + + ret = apply_params(pretty, params); + if (ret != BT_COMPONENT_STATUS_OK) { + goto error; + } + + set_use_colors(pretty); + + ret = bt_private_component_set_user_data(component, pretty); + if (ret != BT_COMPONENT_STATUS_OK) { + goto error; + } + + init_stream_packet_context_quarks(); + +end: + return ret; +error: + destroy_pretty_data(pretty); + return ret; +} diff --git a/plugins/text/pretty/pretty.h b/plugins/text/pretty/pretty.h new file mode 100644 index 00000000..1eaf20c4 --- /dev/null +++ b/plugins/text/pretty/pretty.h @@ -0,0 +1,133 @@ +#ifndef BABELTRACE_PLUGIN_TEXT_PRETTY_PRETTY_H +#define BABELTRACE_PLUGIN_TEXT_PRETTY_PRETTY_H + +/* + * BabelTrace - CTF Text Output Plug-in + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +enum pretty_default { + PRETTY_DEFAULT_UNSET, + PRETTY_DEFAULT_SHOW, + PRETTY_DEFAULT_HIDE, +}; + +enum pretty_color_option { + PRETTY_COLOR_OPT_NEVER, + PRETTY_COLOR_OPT_AUTO, + PRETTY_COLOR_OPT_ALWAYS, +}; + +struct pretty_options { + char *output_path; + char *debug_info_dir; + char *debug_info_target_prefix; + + enum pretty_default name_default; + enum pretty_default field_default; + + bool print_scope_field_names; + bool print_header_field_names; + bool print_context_field_names; + bool print_payload_field_names; + + bool print_delta_field; + bool print_loglevel_field; + bool print_emf_field; + bool print_callsite_field; + bool print_trace_field; + bool print_trace_domain_field; + bool print_trace_procname_field; + bool print_trace_vpid_field; + bool print_trace_hostname_field; + + bool print_timestamp_cycles; + bool clock_seconds; + bool clock_date; + bool clock_gmt; + bool debug_info_full_path; + enum pretty_color_option color; + bool verbose; +}; + +struct pretty_component { + struct pretty_options options; + struct bt_notification_iterator *input_iterator; + FILE *out, *err; + bool processed_first_event; /* Should be per-iterator. */ + int depth; /* nesting, used for tabulation alignment. */ + bool start_line; + GString *string; + struct bt_value *plugin_opt_map; /* Temporary parameter map. */ + bool use_colors; + + uint64_t last_cycles_timestamp; + uint64_t delta_cycles; + + uint64_t last_real_timestamp; + uint64_t delta_real_timestamp; +}; + +enum stream_packet_context_quarks_enum { + Q_TIMESTAMP_BEGIN, + Q_TIMESTAMP_END, + Q_EVENTS_DISCARDED, + Q_CONTENT_SIZE, + Q_PACKET_SIZE, + Q_PACKET_SEQ_NUM, + STREAM_PACKET_CONTEXT_QUARKS_LEN, /* Always the last one of this enum. */ +}; + +GQuark stream_packet_context_quarks[STREAM_PACKET_CONTEXT_QUARKS_LEN]; + +BT_HIDDEN +enum bt_component_status pretty_init( + struct bt_private_component *component, + struct bt_value *params, + void *init_method_data); + +BT_HIDDEN +enum bt_component_status pretty_consume(struct bt_private_component *component); + +BT_HIDDEN +enum bt_component_status pretty_accept_port_connection( + struct bt_private_component *component, + struct bt_private_port *self_port, + struct bt_port *other_port); + +BT_HIDDEN +void pretty_finalize(struct bt_private_component *component); + +BT_HIDDEN +enum bt_component_status pretty_print_event(struct pretty_component *pretty, + struct bt_ctf_event *event); + +#endif /* BABELTRACE_PLUGIN_TEXT_PRETTY_PRETTY_H */ diff --git a/plugins/text/pretty/print.c b/plugins/text/pretty/print.c new file mode 100644 index 00000000..77c42a08 --- /dev/null +++ b/plugins/text/pretty/print.c @@ -0,0 +1,1489 @@ +/* + * print.c + * + * Babeltrace CTF Text Output Plugin Event Printing + * + * Copyright 2016 Jérémie Galarneau + * Copyright 2016 Mathieu Desnoyers + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pretty.h" + +#define NSEC_PER_SEC 1000000000LL + +#define COLOR_NAME BT_COMMON_COLOR_BOLD +#define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN +#define COLOR_RST BT_COMMON_COLOR_RESET +#define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD +#define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD +#define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD +#define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED +#define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA +#define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW + +static inline +const char *rem_(const char *str) +{ + if (str[0] == '_') + return &str[1]; + else + return str; +} + +struct timestamp { + int64_t real_timestamp; /* Relative to UNIX epoch. */ + uint64_t clock_value; /* In cycles. */ +}; + +static +enum bt_component_status print_field(struct pretty_component *pretty, + struct bt_ctf_field *field, bool print_names, + GQuark *filters_fields, int filter_array_len); + +static +void print_name_equal(struct pretty_component *pretty, const char *name) +{ + if (pretty->use_colors) { + fprintf(pretty->out, "%s%s%s = ", COLOR_NAME, name, COLOR_RST); + } else { + fprintf(pretty->out, "%s = ", name); + } +} + +static +void print_field_name_equal(struct pretty_component *pretty, const char *name) +{ + if (pretty->use_colors) { + fprintf(pretty->out, "%s%s%s = ", COLOR_FIELD_NAME, name, + COLOR_RST); + } else { + fprintf(pretty->out, "%s = ", name); + } +} + +static +void print_timestamp_cycles(struct pretty_component *pretty, + struct bt_ctf_clock_class *clock_class, + struct bt_ctf_event *event) +{ + int ret; + struct bt_ctf_clock_value *clock_value; + uint64_t cycles; + + clock_value = bt_ctf_event_get_clock_value(event, clock_class); + if (!clock_value) { + fputs("????????????????????", pretty->out); + return; + } + + ret = bt_ctf_clock_value_get_value(clock_value, &cycles); + bt_put(clock_value); + if (ret) { + fprintf(pretty->out, "Error"); + return; + } + fprintf(pretty->out, "%020" PRIu64, cycles); + + if (pretty->last_cycles_timestamp != -1ULL) { + pretty->delta_cycles = cycles - pretty->last_cycles_timestamp; + } + pretty->last_cycles_timestamp = cycles; +} + +static +void print_timestamp_wall(struct pretty_component *pretty, + struct bt_ctf_clock_class *clock_class, + struct bt_ctf_event *event) +{ + int ret; + struct bt_ctf_clock_value *clock_value; + int64_t ts_nsec = 0; /* add configurable offset */ + int64_t ts_sec = 0; /* add configurable offset */ + uint64_t ts_sec_abs, ts_nsec_abs; + bool is_negative; + + clock_value = bt_ctf_event_get_clock_value(event, clock_class); + if (!clock_value) { + fputs("??:??:??.?????????", pretty->out); + return; + } + + ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec); + bt_put(clock_value); + if (ret) { + fprintf(pretty->out, "Error"); + return; + } + + if (pretty->last_real_timestamp != -1ULL) { + pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp; + } + pretty->last_real_timestamp = ts_nsec; + + ts_sec += ts_nsec / NSEC_PER_SEC; + ts_nsec = ts_nsec % NSEC_PER_SEC; + if (ts_sec >= 0 && ts_nsec >= 0) { + is_negative = false; + ts_sec_abs = ts_sec; + ts_nsec_abs = ts_nsec; + } else if (ts_sec > 0 && ts_nsec < 0) { + is_negative = false; + ts_sec_abs = ts_sec - 1; + ts_nsec_abs = NSEC_PER_SEC + ts_nsec; + } else if (ts_sec == 0 && ts_nsec < 0) { + is_negative = true; + ts_sec_abs = ts_sec; + ts_nsec_abs = -ts_nsec; + } else if (ts_sec < 0 && ts_nsec > 0) { + is_negative = true; + ts_sec_abs = -(ts_sec + 1); + ts_nsec_abs = NSEC_PER_SEC - ts_nsec; + } else if (ts_sec < 0 && ts_nsec == 0) { + is_negative = true; + ts_sec_abs = -ts_sec; + ts_nsec_abs = ts_nsec; + } else { /* (ts_sec < 0 && ts_nsec < 0) */ + is_negative = true; + ts_sec_abs = -ts_sec; + ts_nsec_abs = -ts_nsec; + } + + if (!pretty->options.clock_seconds) { + struct tm tm; + time_t time_s = (time_t) ts_sec_abs; + + if (is_negative) { + fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n"); + goto seconds; + } + + if (!pretty->options.clock_gmt) { + struct tm *res; + + res = localtime_r(&time_s, &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to get localtime.\n"); + goto seconds; + } + } else { + struct tm *res; + + res = gmtime_r(&time_s, &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to get gmtime.\n"); + goto seconds; + } + } + if (pretty->options.clock_date) { + char timestr[26]; + size_t res; + + /* Print date and time */ + res = strftime(timestr, sizeof(timestr), + "%F ", &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to print ascii time.\n"); + goto seconds; + } + fprintf(pretty->out, "%s", timestr); + } + /* Print time in HH:MM:SS.ns */ + fprintf(pretty->out, "%02d:%02d:%02d.%09" PRIu64, + tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs); + goto end; + } +seconds: + fprintf(pretty->out, "%s%" PRId64 ".%09" PRIu64, + is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs); +end: + return; +} + +static +enum bt_component_status print_event_timestamp(struct pretty_component *pretty, + struct bt_ctf_event *event, bool *start_line) +{ + bool print_names = pretty->options.print_header_field_names; + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_stream *stream = NULL; + struct bt_ctf_stream_class *stream_class = NULL; + struct bt_ctf_trace *trace = NULL; + struct bt_ctf_clock_class *clock_class = NULL; + FILE *out = pretty->out; + + stream = bt_ctf_event_get_stream(event); + if (!stream) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + stream_class = bt_ctf_stream_get_class(stream); + if (!stream_class) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + trace = bt_ctf_stream_class_get_trace(stream_class); + if (!trace) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + clock_class = bt_ctf_trace_get_clock_class(trace, 0); + if (!clock_class) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + if (print_names) { + print_name_equal(pretty, "timestamp"); + } else { + fputs("[", out); + } + if (pretty->use_colors) { + fputs(COLOR_TIMESTAMP, pretty->out); + } + if (pretty->options.print_timestamp_cycles) { + print_timestamp_cycles(pretty, clock_class, event); + } else { + print_timestamp_wall(pretty, clock_class, event); + } + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + + if (!print_names) + fputs("] ", out); + + if (pretty->options.print_delta_field) { + if (print_names) { + fputs(", ", pretty->out); + print_name_equal(pretty, "delta"); + } else { + fputs("(", pretty->out); + } + if (pretty->options.print_timestamp_cycles) { + if (pretty->delta_cycles == -1ULL) { + fputs("+??????????\?\?) ", pretty->out); /* Not a trigraph. */ + } else { + fprintf(pretty->out, "+%012" PRIu64, pretty->delta_cycles); + } + } else { + if (pretty->delta_real_timestamp != -1ULL) { + uint64_t delta_sec, delta_nsec, delta; + + delta = pretty->delta_real_timestamp; + delta_sec = delta / NSEC_PER_SEC; + delta_nsec = delta % NSEC_PER_SEC; + fprintf(pretty->out, "+%" PRIu64 ".%09" PRIu64, + delta_sec, delta_nsec); + } else { + fputs("+?.?????????", pretty->out); + } + } + if (!print_names) { + fputs(") ", pretty->out); + } + } + *start_line = !print_names; + +end: + bt_put(stream); + bt_put(clock_class); + bt_put(stream_class); + bt_put(trace); + return ret; +} + +static +enum bt_component_status print_event_header(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + bool print_names = pretty->options.print_header_field_names; + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_event_class *event_class = NULL; + struct bt_ctf_stream_class *stream_class = NULL; + struct bt_ctf_trace *trace_class = NULL; + int dom_print = 0; + + event_class = bt_ctf_event_get_class(event); + if (!event_class) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + stream_class = bt_ctf_event_class_get_stream_class(event_class); + if (!stream_class) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + trace_class = bt_ctf_stream_class_get_trace(stream_class); + if (!trace_class) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = print_event_timestamp(pretty, event, &pretty->start_line); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (pretty->options.print_trace_field) { + const char *name; + + name = bt_ctf_trace_get_name(trace_class); + if (name) { + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "trace"); + } + fprintf(pretty->out, "%s", name); + if (!print_names) { + fprintf(pretty->out, " "); + } + } + } + if (pretty->options.print_trace_hostname_field) { + struct bt_value *hostname_str; + + hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, + "hostname"); + if (hostname_str) { + const char *str; + + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "trace:hostname"); + } + if (bt_value_string_get(hostname_str, &str) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s", str); + } + bt_put(hostname_str); + dom_print = 1; + } + } + if (pretty->options.print_trace_domain_field) { + struct bt_value *domain_str; + + domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, + "domain"); + if (domain_str) { + const char *str; + + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "trace:domain"); + } else if (dom_print) { + fputs(":", pretty->out); + } + if (bt_value_string_get(domain_str, &str) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s", str); + } + bt_put(domain_str); + dom_print = 1; + } + } + if (pretty->options.print_trace_procname_field) { + struct bt_value *procname_str; + + procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, + "procname"); + if (procname_str) { + const char *str; + + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "trace:procname"); + } else if (dom_print) { + fputs(":", pretty->out); + } + if (bt_value_string_get(procname_str, &str) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s", str); + } + bt_put(procname_str); + dom_print = 1; + } + } + if (pretty->options.print_trace_vpid_field) { + struct bt_value *vpid_value; + + vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class, + "vpid"); + if (vpid_value) { + int64_t value; + + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "trace:vpid"); + } else if (dom_print) { + fputs(":", pretty->out); + } + if (bt_value_integer_get(vpid_value, &value) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "(%" PRId64 ")", value); + } + bt_put(vpid_value); + dom_print = 1; + } + } + if (pretty->options.print_loglevel_field) { + struct bt_value *loglevel_str, *loglevel_value; + + loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, + "loglevel_string"); + loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class, + "loglevel"); + if (loglevel_str || loglevel_value) { + bool has_str = false; + + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "loglevel"); + } else if (dom_print) { + fputs(":", pretty->out); + } + if (loglevel_str) { + const char *str; + + if (bt_value_string_get(loglevel_str, &str) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s", str); + has_str = true; + } + } + if (loglevel_value) { + int64_t value; + + if (bt_value_integer_get(loglevel_value, &value) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s(%" PRId64 ")", + has_str ? " " : "", value); + } + } + bt_put(loglevel_str); + bt_put(loglevel_value); + dom_print = 1; + } + } + if (pretty->options.print_emf_field) { + struct bt_value *uri_str; + + uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, + "model.emf.uri"); + if (uri_str) { + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + if (print_names) { + print_name_equal(pretty, "model.emf.uri"); + } else if (dom_print) { + fputs(":", pretty->out); + } + if (uri_str) { + const char *str; + + if (bt_value_string_get(uri_str, &str) + == BT_VALUE_STATUS_OK) { + fprintf(pretty->out, "%s", str); + } + } + bt_put(uri_str); + dom_print = 1; + } + } + if (dom_print && !print_names) { + fputs(" ", pretty->out); + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = true; + if (print_names) { + print_name_equal(pretty, "name"); + } + if (pretty->use_colors) { + fputs(COLOR_EVENT_NAME, pretty->out); + } + fputs(bt_ctf_event_class_get_name(event_class), pretty->out); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + if (!print_names) { + fputs(": ", pretty->out); + } else { + fputs(", ", pretty->out); + } +end: + bt_put(trace_class); + bt_put(stream_class); + bt_put(event_class); + return ret; +} + +static +enum bt_component_status print_integer(struct pretty_component *pretty, + struct bt_ctf_field *field) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field_type *field_type = NULL; + enum bt_ctf_integer_base base; + enum bt_ctf_string_encoding encoding; + int signedness; + union { + uint64_t u; + int64_t s; + } v; + bool rst_color = false; + + field_type = bt_ctf_field_get_type(field); + if (!field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + signedness = bt_ctf_field_type_integer_get_signed(field_type); + if (signedness < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (!signedness) { + if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + } else { + if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + } + + encoding = bt_ctf_field_type_integer_get_encoding(field_type); + switch (encoding) { + case BT_CTF_STRING_ENCODING_UTF8: + case BT_CTF_STRING_ENCODING_ASCII: + g_string_append_c(pretty->string, (int) v.u); + goto end; + case BT_CTF_STRING_ENCODING_NONE: + case BT_CTF_STRING_ENCODING_UNKNOWN: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + if (pretty->use_colors) { + fputs(COLOR_NUMBER_VALUE, pretty->out); + rst_color = true; + } + + base = bt_ctf_field_type_integer_get_base(field_type); + switch (base) { + case BT_CTF_INTEGER_BASE_BINARY: + { + int bitnr, len; + + len = bt_ctf_field_type_integer_get_size(field_type); + if (len < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + fprintf(pretty->out, "0b"); + v.u = _bt_piecewise_lshift(v.u, 64 - len); + for (bitnr = 0; bitnr < len; bitnr++) { + fprintf(pretty->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); + v.u = _bt_piecewise_lshift(v.u, 1); + } + break; + } + case BT_CTF_INTEGER_BASE_OCTAL: + { + if (signedness) { + int len; + + len = bt_ctf_field_type_integer_get_size(field_type); + if (len < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (len < 64) { + size_t rounded_len; + + assert(len != 0); + /* Round length to the nearest 3-bit */ + rounded_len = (((len - 1) / 3) + 1) * 3; + v.u &= ((uint64_t) 1 << rounded_len) - 1; + } + } + + fprintf(pretty->out, "0%" PRIo64, v.u); + break; + } + case BT_CTF_INTEGER_BASE_DECIMAL: + if (!signedness) { + fprintf(pretty->out, "%" PRIu64, v.u); + } else { + fprintf(pretty->out, "%" PRId64, v.s); + } + break; + case BT_CTF_INTEGER_BASE_HEXADECIMAL: + { + int len; + + len = bt_ctf_field_type_integer_get_size(field_type); + if (len < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (len < 64) { + /* Round length to the nearest nibble */ + uint8_t rounded_len = ((len + 3) & ~0x3); + + v.u &= ((uint64_t) 1 << rounded_len) - 1; + } + + fprintf(pretty->out, "0x%" PRIX64, v.u); + break; + } + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } +end: + if (rst_color) { + fputs(COLOR_RST, pretty->out); + } + bt_put(field_type); + return ret; +} + +static +void print_escape_string(struct pretty_component *pretty, const char *str) +{ + int i; + + fputc('"', pretty->out); + for (i = 0; i < strlen(str); i++) { + /* Escape sequences not recognized by iscntrl(). */ + switch (str[i]) { + case '\\': + fputs("\\\\", pretty->out); + continue; + case '\'': + fputs("\\\'", pretty->out); + continue; + case '\"': + fputs("\\\"", pretty->out); + continue; + case '\?': + fputs("\\\?", pretty->out); + continue; + } + + /* Standard characters. */ + if (!iscntrl(str[i])) { + fputc(str[i], pretty->out); + continue; + } + + switch (str[i]) { + case '\0': + fputs("\\0", pretty->out); + break; + case '\a': + fputs("\\a", pretty->out); + break; + case '\b': + fputs("\\b", pretty->out); + break; + case '\e': + fputs("\\e", pretty->out); + break; + case '\f': + fputs("\\f", pretty->out); + break; + case '\n': + fputs("\\n", pretty->out); + break; + case '\r': + fputs("\\r", pretty->out); + break; + case '\t': + fputs("\\t", pretty->out); + break; + case '\v': + fputs("\\v", pretty->out); + break; + default: + /* Unhandled control-sequence, print as hex. */ + fprintf(pretty->out, "\\x%02x", str[i]); + break; + } + } + fputc('"', pretty->out); +} + +static +enum bt_component_status print_enum(struct pretty_component *pretty, + struct bt_ctf_field *field) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *container_field = NULL; + struct bt_ctf_field_type *enumeration_field_type = NULL; + struct bt_ctf_field_type *container_field_type = NULL; + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; + int nr_mappings = 0; + int is_signed; + + enumeration_field_type = bt_ctf_field_get_type(field); + if (!enumeration_field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + container_field = bt_ctf_field_enumeration_get_container(field); + if (!container_field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + container_field_type = bt_ctf_field_get_type(container_field); + if (!container_field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + is_signed = bt_ctf_field_type_integer_get_signed(container_field_type); + if (is_signed < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (is_signed) { + int64_t value; + + if (bt_ctf_field_signed_integer_get_value(container_field, + &value)) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( + enumeration_field_type, value); + } else { + uint64_t value; + + if (bt_ctf_field_unsigned_integer_get_value(container_field, + &value)) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( + enumeration_field_type, value); + } + if (!iter) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + fprintf(pretty->out, "( "); + for (;;) { + const char *mapping_name; + + if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + iter, &mapping_name, NULL, NULL) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (nr_mappings++) + fprintf(pretty->out, ", "); + if (pretty->use_colors) { + fputs(COLOR_ENUM_MAPPING_NAME, pretty->out); + } + print_escape_string(pretty, mapping_name); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) { + break; + } + } + if (!nr_mappings) { + if (pretty->use_colors) { + fputs(COLOR_UNKNOWN, pretty->out); + } + fprintf(pretty->out, ""); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + } + fprintf(pretty->out, " : container = "); + ret = print_integer(pretty, container_field); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + fprintf(pretty->out, " )"); +end: + bt_put(iter); + bt_put(container_field_type); + bt_put(container_field); + bt_put(enumeration_field_type); + return ret; +} + +static +int filter_field_name(struct pretty_component *pretty, const char *field_name, + GQuark *filter_fields, int filter_array_len) +{ + int i; + GQuark field_quark = g_quark_try_string(field_name); + + if (!field_quark || pretty->options.verbose) { + return 1; + } + + for (i = 0; i < filter_array_len; i++) { + if (field_quark == filter_fields[i]) { + return 0; + } + } + return 1; +} + +static +enum bt_component_status print_struct_field(struct pretty_component *pretty, + struct bt_ctf_field *_struct, + struct bt_ctf_field_type *struct_type, + int i, bool print_names, int *nr_printed_fields, + GQuark *filter_fields, int filter_array_len) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + const char *field_name; + struct bt_ctf_field *field = NULL; + struct bt_ctf_field_type *field_type = NULL;; + + field = bt_ctf_field_structure_get_field_by_index(_struct, i); + if (!field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (bt_ctf_field_type_structure_get_field(struct_type, + &field_name, &field_type, i) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + if (filter_fields && !filter_field_name(pretty, field_name, + filter_fields, filter_array_len)) { + ret = BT_COMPONENT_STATUS_OK; + goto end; + } + + if (*nr_printed_fields > 0) { + fprintf(pretty->out, ", "); + } else { + fprintf(pretty->out, " "); + } + if (print_names) { + print_field_name_equal(pretty, rem_(field_name)); + } + ret = print_field(pretty, field, print_names, NULL, 0); + *nr_printed_fields += 1; +end: + bt_put(field_type); + bt_put(field); + return ret; +} + +static +enum bt_component_status print_struct(struct pretty_component *pretty, + struct bt_ctf_field *_struct, bool print_names, + GQuark *filter_fields, int filter_array_len) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field_type *struct_type = NULL; + int nr_fields, i, nr_printed_fields; + + struct_type = bt_ctf_field_get_type(_struct); + if (!struct_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); + if (nr_fields < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + fprintf(pretty->out, "{"); + pretty->depth++; + nr_printed_fields = 0; + for (i = 0; i < nr_fields; i++) { + ret = print_struct_field(pretty, _struct, struct_type, i, + print_names, &nr_printed_fields, filter_fields, + filter_array_len); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + } + pretty->depth--; + fprintf(pretty->out, " }"); +end: + bt_put(struct_type); + return ret; +} + +static +enum bt_component_status print_array_field(struct pretty_component *pretty, + struct bt_ctf_field *array, uint64_t i, + bool is_string, bool print_names) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *field = NULL; + + if (!is_string) { + if (i != 0) { + fprintf(pretty->out, ", "); + } else { + fprintf(pretty->out, " "); + } + if (print_names) { + fprintf(pretty->out, "[%" PRIu64 "] = ", i); + } + } + field = bt_ctf_field_array_get_field(array, i); + if (!field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = print_field(pretty, field, print_names, NULL, 0); +end: + bt_put(field); + return ret; +} + +static +enum bt_component_status print_array(struct pretty_component *pretty, + struct bt_ctf_field *array, bool print_names) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field_type *array_type = NULL, *field_type = NULL; + enum bt_ctf_field_type_id type_id; + int64_t len; + uint64_t i; + bool is_string = false; + + array_type = bt_ctf_field_get_type(array); + if (!array_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + field_type = bt_ctf_field_type_array_get_element_type(array_type); + if (!field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + len = bt_ctf_field_type_array_get_length(array_type); + if (len < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + type_id = bt_ctf_field_type_get_type_id(field_type); + if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { + enum bt_ctf_string_encoding encoding; + + encoding = bt_ctf_field_type_integer_get_encoding(field_type); + if (encoding == BT_CTF_STRING_ENCODING_UTF8 + || encoding == BT_CTF_STRING_ENCODING_ASCII) { + int integer_len, integer_alignment; + + integer_len = bt_ctf_field_type_integer_get_size(field_type); + if (integer_len < 0) { + return BT_COMPONENT_STATUS_ERROR; + } + integer_alignment = bt_ctf_field_type_get_alignment(field_type); + if (integer_alignment < 0) { + return BT_COMPONENT_STATUS_ERROR; + } + if (integer_len == CHAR_BIT + && integer_alignment == CHAR_BIT) { + is_string = true; + } + } + } + + if (is_string) { + g_string_assign(pretty->string, ""); + } else { + fprintf(pretty->out, "["); + } + + pretty->depth++; + for (i = 0; i < len; i++) { + ret = print_array_field(pretty, array, i, is_string, print_names); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + } + pretty->depth--; + + if (is_string) { + if (pretty->use_colors) { + fputs(COLOR_STRING_VALUE, pretty->out); + } + print_escape_string(pretty, pretty->string->str); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + } else { + fprintf(pretty->out, " ]"); + } +end: + bt_put(field_type); + bt_put(array_type); + return ret; +} + +static +enum bt_component_status print_sequence_field(struct pretty_component *pretty, + struct bt_ctf_field *seq, uint64_t i, + bool is_string, bool print_names) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *field = NULL; + + if (!is_string) { + if (i != 0) { + fprintf(pretty->out, ", "); + } else { + fprintf(pretty->out, " "); + } + if (print_names) { + fprintf(pretty->out, "[%" PRIu64 "] = ", i); + } + } + field = bt_ctf_field_sequence_get_field(seq, i); + if (!field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = print_field(pretty, field, print_names, NULL, 0); +end: + bt_put(field); + return ret; +} + +static +enum bt_component_status print_sequence(struct pretty_component *pretty, + struct bt_ctf_field *seq, bool print_names) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL; + struct bt_ctf_field *length_field = NULL; + enum bt_ctf_field_type_id type_id; + uint64_t len; + uint64_t i; + bool is_string = false; + + seq_type = bt_ctf_field_get_type(seq); + if (!seq_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + length_field = bt_ctf_field_sequence_get_length(seq); + if (!length_field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + field_type = bt_ctf_field_type_sequence_get_element_type(seq_type); + if (!field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + type_id = bt_ctf_field_type_get_type_id(field_type); + if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { + enum bt_ctf_string_encoding encoding; + + encoding = bt_ctf_field_type_integer_get_encoding(field_type); + if (encoding == BT_CTF_STRING_ENCODING_UTF8 + || encoding == BT_CTF_STRING_ENCODING_ASCII) { + int integer_len, integer_alignment; + + integer_len = bt_ctf_field_type_integer_get_size(field_type); + if (integer_len < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + integer_alignment = bt_ctf_field_type_get_alignment(field_type); + if (integer_alignment < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (integer_len == CHAR_BIT + && integer_alignment == CHAR_BIT) { + is_string = true; + } + } + } + + if (is_string) { + g_string_assign(pretty->string, ""); + } else { + fprintf(pretty->out, "["); + } + + pretty->depth++; + for (i = 0; i < len; i++) { + ret = print_sequence_field(pretty, seq, i, + is_string, print_names); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + } + pretty->depth--; + + if (is_string) { + if (pretty->use_colors) { + fputs(COLOR_STRING_VALUE, pretty->out); + } + print_escape_string(pretty, pretty->string->str); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + } else { + fprintf(pretty->out, " ]"); + } +end: + bt_put(length_field); + bt_put(field_type); + bt_put(seq_type); + return ret; +} + +static +enum bt_component_status print_variant(struct pretty_component *pretty, + struct bt_ctf_field *variant, bool print_names) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *field = NULL; + + field = bt_ctf_field_variant_get_current_field(variant); + if (!field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + fprintf(pretty->out, "{ "); + pretty->depth++; + if (print_names) { + int iter_ret; + struct bt_ctf_field *tag_field = NULL; + const char *tag_choice; + struct bt_ctf_field_type_enumeration_mapping_iterator *iter; + + tag_field = bt_ctf_field_variant_get_tag(variant); + if (!tag_field) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + iter = bt_ctf_field_enumeration_get_mappings(tag_field); + if (!iter) { + bt_put(tag_field); + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + iter_ret = + bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + iter, &tag_choice, NULL, NULL); + if (iter_ret) { + bt_put(iter); + bt_put(tag_field); + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + print_field_name_equal(pretty, rem_(tag_choice)); + bt_put(tag_field); + bt_put(iter); + } + ret = print_field(pretty, field, print_names, NULL, 0); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + pretty->depth--; + fprintf(pretty->out, " }"); +end: + bt_put(field); + return ret; +} + +static +enum bt_component_status print_field(struct pretty_component *pretty, + struct bt_ctf_field *field, bool print_names, + GQuark *filter_fields, int filter_array_len) +{ + enum bt_ctf_field_type_id type_id; + + type_id = bt_ctf_field_get_type_id(field); + switch (type_id) { + case CTF_TYPE_INTEGER: + return print_integer(pretty, field); + case CTF_TYPE_FLOAT: + { + double v; + + if (bt_ctf_field_floating_point_get_value(field, &v)) { + return BT_COMPONENT_STATUS_ERROR; + } + if (pretty->use_colors) { + fputs(COLOR_NUMBER_VALUE, pretty->out); + } + fprintf(pretty->out, "%g", v); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + return BT_COMPONENT_STATUS_OK; + } + case CTF_TYPE_ENUM: + return print_enum(pretty, field); + case CTF_TYPE_STRING: + if (pretty->use_colors) { + fputs(COLOR_STRING_VALUE, pretty->out); + } + print_escape_string(pretty, bt_ctf_field_string_get_value(field)); + if (pretty->use_colors) { + fputs(COLOR_RST, pretty->out); + } + return BT_COMPONENT_STATUS_OK; + case CTF_TYPE_STRUCT: + return print_struct(pretty, field, print_names, filter_fields, + filter_array_len); + case CTF_TYPE_UNTAGGED_VARIANT: + case CTF_TYPE_VARIANT: + return print_variant(pretty, field, print_names); + case CTF_TYPE_ARRAY: + return print_array(pretty, field, print_names); + case CTF_TYPE_SEQUENCE: + return print_sequence(pretty, field, print_names); + default: + fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id); + return BT_COMPONENT_STATUS_ERROR; + } +} + +static +enum bt_component_status print_stream_packet_context(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_packet *packet = NULL; + struct bt_ctf_field *main_field = NULL; + + packet = bt_ctf_event_get_packet(event); + if (!packet) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + main_field = bt_ctf_packet_get_context(packet); + if (!main_field) { + goto end; + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = false; + if (pretty->options.print_scope_field_names) { + print_name_equal(pretty, "stream.packet.context"); + } + ret = print_field(pretty, main_field, + pretty->options.print_context_field_names, + stream_packet_context_quarks, + STREAM_PACKET_CONTEXT_QUARKS_LEN); +end: + bt_put(main_field); + bt_put(packet); + return ret; +} + +static +enum bt_component_status print_event_header_raw(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *main_field = NULL; + + main_field = bt_ctf_event_get_header(event); + if (!main_field) { + goto end; + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = false; + if (pretty->options.print_scope_field_names) { + print_name_equal(pretty, "stream.event.header"); + } + ret = print_field(pretty, main_field, + pretty->options.print_header_field_names, NULL, 0); +end: + bt_put(main_field); + return ret; +} + +static +enum bt_component_status print_stream_event_context(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *main_field = NULL; + + main_field = bt_ctf_event_get_stream_event_context(event); + if (!main_field) { + goto end; + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = false; + if (pretty->options.print_scope_field_names) { + print_name_equal(pretty, "stream.event.context"); + } + ret = print_field(pretty, main_field, + pretty->options.print_context_field_names, NULL, 0); +end: + bt_put(main_field); + return ret; +} + +static +enum bt_component_status print_event_context(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *main_field = NULL; + + main_field = bt_ctf_event_get_event_context(event); + if (!main_field) { + goto end; + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = false; + if (pretty->options.print_scope_field_names) { + print_name_equal(pretty, "event.context"); + } + ret = print_field(pretty, main_field, + pretty->options.print_context_field_names, NULL, 0); +end: + bt_put(main_field); + return ret; +} + +static +enum bt_component_status print_event_payload(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_ctf_field *main_field = NULL; + + main_field = bt_ctf_event_get_payload_field(event); + if (!main_field) { + goto end; + } + if (!pretty->start_line) { + fputs(", ", pretty->out); + } + pretty->start_line = false; + if (pretty->options.print_scope_field_names) { + print_name_equal(pretty, "event.fields"); + } + ret = print_field(pretty, main_field, + pretty->options.print_payload_field_names, NULL, 0); +end: + bt_put(main_field); + return ret; +} + +BT_HIDDEN +enum bt_component_status pretty_print_event(struct pretty_component *pretty, + struct bt_ctf_event *event) +{ + enum bt_component_status ret; + + pretty->start_line = true; + ret = print_event_header(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = print_stream_packet_context(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + if (pretty->options.verbose) { + ret = print_event_header_raw(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + } + + ret = print_stream_event_context(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = print_event_context(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = print_event_payload(pretty, event); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + fputc('\n', pretty->out); +end: + return ret; +} diff --git a/plugins/text/print.c b/plugins/text/print.c deleted file mode 100644 index 3634d068..00000000 --- a/plugins/text/print.c +++ /dev/null @@ -1,1489 +0,0 @@ -/* - * print.c - * - * Babeltrace CTF Text Output Plugin Event Printing - * - * Copyright 2016 Jérémie Galarneau - * Copyright 2016 Mathieu Desnoyers - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "text.h" - -#define NSEC_PER_SEC 1000000000LL - -#define COLOR_NAME BT_COMMON_COLOR_BOLD -#define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN -#define COLOR_RST BT_COMMON_COLOR_RESET -#define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD -#define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD -#define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD -#define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED -#define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA -#define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW - -static inline -const char *rem_(const char *str) -{ - if (str[0] == '_') - return &str[1]; - else - return str; -} - -struct timestamp { - int64_t real_timestamp; /* Relative to UNIX epoch. */ - uint64_t clock_value; /* In cycles. */ -}; - -static -enum bt_component_status print_field(struct text_component *text, - struct bt_ctf_field *field, bool print_names, - GQuark *filters_fields, int filter_array_len); - -static -void print_name_equal(struct text_component *text, const char *name) -{ - if (text->use_colors) { - fprintf(text->out, "%s%s%s = ", COLOR_NAME, name, COLOR_RST); - } else { - fprintf(text->out, "%s = ", name); - } -} - -static -void print_field_name_equal(struct text_component *text, const char *name) -{ - if (text->use_colors) { - fprintf(text->out, "%s%s%s = ", COLOR_FIELD_NAME, name, - COLOR_RST); - } else { - fprintf(text->out, "%s = ", name); - } -} - -static -void print_timestamp_cycles(struct text_component *text, - struct bt_ctf_clock_class *clock_class, - struct bt_ctf_event *event) -{ - int ret; - struct bt_ctf_clock_value *clock_value; - uint64_t cycles; - - clock_value = bt_ctf_event_get_clock_value(event, clock_class); - if (!clock_value) { - fputs("????????????????????", text->out); - return; - } - - ret = bt_ctf_clock_value_get_value(clock_value, &cycles); - bt_put(clock_value); - if (ret) { - fprintf(text->out, "Error"); - return; - } - fprintf(text->out, "%020" PRIu64, cycles); - - if (text->last_cycles_timestamp != -1ULL) { - text->delta_cycles = cycles - text->last_cycles_timestamp; - } - text->last_cycles_timestamp = cycles; -} - -static -void print_timestamp_wall(struct text_component *text, - struct bt_ctf_clock_class *clock_class, - struct bt_ctf_event *event) -{ - int ret; - struct bt_ctf_clock_value *clock_value; - int64_t ts_nsec = 0; /* add configurable offset */ - int64_t ts_sec = 0; /* add configurable offset */ - uint64_t ts_sec_abs, ts_nsec_abs; - bool is_negative; - - clock_value = bt_ctf_event_get_clock_value(event, clock_class); - if (!clock_value) { - fputs("??:??:??.?????????", text->out); - return; - } - - ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec); - bt_put(clock_value); - if (ret) { - fprintf(text->out, "Error"); - return; - } - - if (text->last_real_timestamp != -1ULL) { - text->delta_real_timestamp = ts_nsec - text->last_real_timestamp; - } - text->last_real_timestamp = ts_nsec; - - ts_sec += ts_nsec / NSEC_PER_SEC; - ts_nsec = ts_nsec % NSEC_PER_SEC; - if (ts_sec >= 0 && ts_nsec >= 0) { - is_negative = false; - ts_sec_abs = ts_sec; - ts_nsec_abs = ts_nsec; - } else if (ts_sec > 0 && ts_nsec < 0) { - is_negative = false; - ts_sec_abs = ts_sec - 1; - ts_nsec_abs = NSEC_PER_SEC + ts_nsec; - } else if (ts_sec == 0 && ts_nsec < 0) { - is_negative = true; - ts_sec_abs = ts_sec; - ts_nsec_abs = -ts_nsec; - } else if (ts_sec < 0 && ts_nsec > 0) { - is_negative = true; - ts_sec_abs = -(ts_sec + 1); - ts_nsec_abs = NSEC_PER_SEC - ts_nsec; - } else if (ts_sec < 0 && ts_nsec == 0) { - is_negative = true; - ts_sec_abs = -ts_sec; - ts_nsec_abs = ts_nsec; - } else { /* (ts_sec < 0 && ts_nsec < 0) */ - is_negative = true; - ts_sec_abs = -ts_sec; - ts_nsec_abs = -ts_nsec; - } - - if (!text->options.clock_seconds) { - struct tm tm; - time_t time_s = (time_t) ts_sec_abs; - - if (is_negative) { - fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n"); - goto seconds; - } - - if (!text->options.clock_gmt) { - struct tm *res; - - res = localtime_r(&time_s, &tm); - if (!res) { - fprintf(stderr, "[warning] Unable to get localtime.\n"); - goto seconds; - } - } else { - struct tm *res; - - res = gmtime_r(&time_s, &tm); - if (!res) { - fprintf(stderr, "[warning] Unable to get gmtime.\n"); - goto seconds; - } - } - if (text->options.clock_date) { - char timestr[26]; - size_t res; - - /* Print date and time */ - res = strftime(timestr, sizeof(timestr), - "%F ", &tm); - if (!res) { - fprintf(stderr, "[warning] Unable to print ascii time.\n"); - goto seconds; - } - fprintf(text->out, "%s", timestr); - } - /* Print time in HH:MM:SS.ns */ - fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64, - tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs); - goto end; - } -seconds: - fprintf(text->out, "%s%" PRId64 ".%09" PRIu64, - is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs); -end: - return; -} - -static -enum bt_component_status print_event_timestamp(struct text_component *text, - struct bt_ctf_event *event, bool *start_line) -{ - bool print_names = text->options.print_header_field_names; - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_stream *stream = NULL; - struct bt_ctf_stream_class *stream_class = NULL; - struct bt_ctf_trace *trace = NULL; - struct bt_ctf_clock_class *clock_class = NULL; - FILE *out = text->out; - - stream = bt_ctf_event_get_stream(event); - if (!stream) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - stream_class = bt_ctf_stream_get_class(stream); - if (!stream_class) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - trace = bt_ctf_stream_class_get_trace(stream_class); - if (!trace) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - clock_class = bt_ctf_trace_get_clock_class(trace, 0); - if (!clock_class) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - if (print_names) { - print_name_equal(text, "timestamp"); - } else { - fputs("[", out); - } - if (text->use_colors) { - fputs(COLOR_TIMESTAMP, text->out); - } - if (text->options.print_timestamp_cycles) { - print_timestamp_cycles(text, clock_class, event); - } else { - print_timestamp_wall(text, clock_class, event); - } - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - - if (!print_names) - fputs("] ", out); - - if (text->options.print_delta_field) { - if (print_names) { - fputs(", ", text->out); - print_name_equal(text, "delta"); - } else { - fputs("(", text->out); - } - if (text->options.print_timestamp_cycles) { - if (text->delta_cycles == -1ULL) { - fputs("+??????????\?\?) ", text->out); /* Not a trigraph. */ - } else { - fprintf(text->out, "+%012" PRIu64, text->delta_cycles); - } - } else { - if (text->delta_real_timestamp != -1ULL) { - uint64_t delta_sec, delta_nsec, delta; - - delta = text->delta_real_timestamp; - delta_sec = delta / NSEC_PER_SEC; - delta_nsec = delta % NSEC_PER_SEC; - fprintf(text->out, "+%" PRIu64 ".%09" PRIu64, - delta_sec, delta_nsec); - } else { - fputs("+?.?????????", text->out); - } - } - if (!print_names) { - fputs(") ", text->out); - } - } - *start_line = !print_names; - -end: - bt_put(stream); - bt_put(clock_class); - bt_put(stream_class); - bt_put(trace); - return ret; -} - -static -enum bt_component_status print_event_header(struct text_component *text, - struct bt_ctf_event *event) -{ - bool print_names = text->options.print_header_field_names; - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_event_class *event_class = NULL; - struct bt_ctf_stream_class *stream_class = NULL; - struct bt_ctf_trace *trace_class = NULL; - int dom_print = 0; - - event_class = bt_ctf_event_get_class(event); - if (!event_class) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - stream_class = bt_ctf_event_class_get_stream_class(event_class); - if (!stream_class) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - trace_class = bt_ctf_stream_class_get_trace(stream_class); - if (!trace_class) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - ret = print_event_timestamp(text, event, &text->start_line); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (text->options.print_trace_field) { - const char *name; - - name = bt_ctf_trace_get_name(trace_class); - if (name) { - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "trace"); - } - fprintf(text->out, "%s", name); - if (!print_names) { - fprintf(text->out, " "); - } - } - } - if (text->options.print_trace_hostname_field) { - struct bt_value *hostname_str; - - hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, - "hostname"); - if (hostname_str) { - const char *str; - - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "trace:hostname"); - } - if (bt_value_string_get(hostname_str, &str) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s", str); - } - bt_put(hostname_str); - dom_print = 1; - } - } - if (text->options.print_trace_domain_field) { - struct bt_value *domain_str; - - domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, - "domain"); - if (domain_str) { - const char *str; - - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "trace:domain"); - } else if (dom_print) { - fputs(":", text->out); - } - if (bt_value_string_get(domain_str, &str) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s", str); - } - bt_put(domain_str); - dom_print = 1; - } - } - if (text->options.print_trace_procname_field) { - struct bt_value *procname_str; - - procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, - "procname"); - if (procname_str) { - const char *str; - - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "trace:procname"); - } else if (dom_print) { - fputs(":", text->out); - } - if (bt_value_string_get(procname_str, &str) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s", str); - } - bt_put(procname_str); - dom_print = 1; - } - } - if (text->options.print_trace_vpid_field) { - struct bt_value *vpid_value; - - vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class, - "vpid"); - if (vpid_value) { - int64_t value; - - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "trace:vpid"); - } else if (dom_print) { - fputs(":", text->out); - } - if (bt_value_integer_get(vpid_value, &value) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "(%" PRId64 ")", value); - } - bt_put(vpid_value); - dom_print = 1; - } - } - if (text->options.print_loglevel_field) { - struct bt_value *loglevel_str, *loglevel_value; - - loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, - "loglevel_string"); - loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class, - "loglevel"); - if (loglevel_str || loglevel_value) { - bool has_str = false; - - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "loglevel"); - } else if (dom_print) { - fputs(":", text->out); - } - if (loglevel_str) { - const char *str; - - if (bt_value_string_get(loglevel_str, &str) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s", str); - has_str = true; - } - } - if (loglevel_value) { - int64_t value; - - if (bt_value_integer_get(loglevel_value, &value) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s(%" PRId64 ")", - has_str ? " " : "", value); - } - } - bt_put(loglevel_str); - bt_put(loglevel_value); - dom_print = 1; - } - } - if (text->options.print_emf_field) { - struct bt_value *uri_str; - - uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, - "model.emf.uri"); - if (uri_str) { - if (!text->start_line) { - fputs(", ", text->out); - } - if (print_names) { - print_name_equal(text, "model.emf.uri"); - } else if (dom_print) { - fputs(":", text->out); - } - if (uri_str) { - const char *str; - - if (bt_value_string_get(uri_str, &str) - == BT_VALUE_STATUS_OK) { - fprintf(text->out, "%s", str); - } - } - bt_put(uri_str); - dom_print = 1; - } - } - if (dom_print && !print_names) { - fputs(" ", text->out); - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = true; - if (print_names) { - print_name_equal(text, "name"); - } - if (text->use_colors) { - fputs(COLOR_EVENT_NAME, text->out); - } - fputs(bt_ctf_event_class_get_name(event_class), text->out); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - if (!print_names) { - fputs(": ", text->out); - } else { - fputs(", ", text->out); - } -end: - bt_put(trace_class); - bt_put(stream_class); - bt_put(event_class); - return ret; -} - -static -enum bt_component_status print_integer(struct text_component *text, - struct bt_ctf_field *field) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field_type *field_type = NULL; - enum bt_ctf_integer_base base; - enum bt_ctf_string_encoding encoding; - int signedness; - union { - uint64_t u; - int64_t s; - } v; - bool rst_color = false; - - field_type = bt_ctf_field_get_type(field); - if (!field_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - signedness = bt_ctf_field_type_integer_get_signed(field_type); - if (signedness < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (!signedness) { - if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - } else { - if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - } - - encoding = bt_ctf_field_type_integer_get_encoding(field_type); - switch (encoding) { - case BT_CTF_STRING_ENCODING_UTF8: - case BT_CTF_STRING_ENCODING_ASCII: - g_string_append_c(text->string, (int) v.u); - goto end; - case BT_CTF_STRING_ENCODING_NONE: - case BT_CTF_STRING_ENCODING_UNKNOWN: - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - if (text->use_colors) { - fputs(COLOR_NUMBER_VALUE, text->out); - rst_color = true; - } - - base = bt_ctf_field_type_integer_get_base(field_type); - switch (base) { - case BT_CTF_INTEGER_BASE_BINARY: - { - int bitnr, len; - - len = bt_ctf_field_type_integer_get_size(field_type); - if (len < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - fprintf(text->out, "0b"); - v.u = _bt_piecewise_lshift(v.u, 64 - len); - for (bitnr = 0; bitnr < len; bitnr++) { - fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); - v.u = _bt_piecewise_lshift(v.u, 1); - } - break; - } - case BT_CTF_INTEGER_BASE_OCTAL: - { - if (signedness) { - int len; - - len = bt_ctf_field_type_integer_get_size(field_type); - if (len < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (len < 64) { - size_t rounded_len; - - assert(len != 0); - /* Round length to the nearest 3-bit */ - rounded_len = (((len - 1) / 3) + 1) * 3; - v.u &= ((uint64_t) 1 << rounded_len) - 1; - } - } - - fprintf(text->out, "0%" PRIo64, v.u); - break; - } - case BT_CTF_INTEGER_BASE_DECIMAL: - if (!signedness) { - fprintf(text->out, "%" PRIu64, v.u); - } else { - fprintf(text->out, "%" PRId64, v.s); - } - break; - case BT_CTF_INTEGER_BASE_HEXADECIMAL: - { - int len; - - len = bt_ctf_field_type_integer_get_size(field_type); - if (len < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (len < 64) { - /* Round length to the nearest nibble */ - uint8_t rounded_len = ((len + 3) & ~0x3); - - v.u &= ((uint64_t) 1 << rounded_len) - 1; - } - - fprintf(text->out, "0x%" PRIX64, v.u); - break; - } - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } -end: - if (rst_color) { - fputs(COLOR_RST, text->out); - } - bt_put(field_type); - return ret; -} - -static -void print_escape_string(struct text_component *text, const char *str) -{ - int i; - - fputc('"', text->out); - for (i = 0; i < strlen(str); i++) { - /* Escape sequences not recognized by iscntrl(). */ - switch (str[i]) { - case '\\': - fputs("\\\\", text->out); - continue; - case '\'': - fputs("\\\'", text->out); - continue; - case '\"': - fputs("\\\"", text->out); - continue; - case '\?': - fputs("\\\?", text->out); - continue; - } - - /* Standard characters. */ - if (!iscntrl(str[i])) { - fputc(str[i], text->out); - continue; - } - - switch (str[i]) { - case '\0': - fputs("\\0", text->out); - break; - case '\a': - fputs("\\a", text->out); - break; - case '\b': - fputs("\\b", text->out); - break; - case '\e': - fputs("\\e", text->out); - break; - case '\f': - fputs("\\f", text->out); - break; - case '\n': - fputs("\\n", text->out); - break; - case '\r': - fputs("\\r", text->out); - break; - case '\t': - fputs("\\t", text->out); - break; - case '\v': - fputs("\\v", text->out); - break; - default: - /* Unhandled control-sequence, print as hex. */ - fprintf(text->out, "\\x%02x", str[i]); - break; - } - } - fputc('"', text->out); -} - -static -enum bt_component_status print_enum(struct text_component *text, - struct bt_ctf_field *field) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *container_field = NULL; - struct bt_ctf_field_type *enumeration_field_type = NULL; - struct bt_ctf_field_type *container_field_type = NULL; - struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; - int nr_mappings = 0; - int is_signed; - - enumeration_field_type = bt_ctf_field_get_type(field); - if (!enumeration_field_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - container_field = bt_ctf_field_enumeration_get_container(field); - if (!container_field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - container_field_type = bt_ctf_field_get_type(container_field); - if (!container_field_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - is_signed = bt_ctf_field_type_integer_get_signed(container_field_type); - if (is_signed < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (is_signed) { - int64_t value; - - if (bt_ctf_field_signed_integer_get_value(container_field, - &value)) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( - enumeration_field_type, value); - } else { - uint64_t value; - - if (bt_ctf_field_unsigned_integer_get_value(container_field, - &value)) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( - enumeration_field_type, value); - } - if (!iter) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - fprintf(text->out, "( "); - for (;;) { - const char *mapping_name; - - if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed( - iter, &mapping_name, NULL, NULL) < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (nr_mappings++) - fprintf(text->out, ", "); - if (text->use_colors) { - fputs(COLOR_ENUM_MAPPING_NAME, text->out); - } - print_escape_string(text, mapping_name); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) { - break; - } - } - if (!nr_mappings) { - if (text->use_colors) { - fputs(COLOR_UNKNOWN, text->out); - } - fprintf(text->out, ""); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - } - fprintf(text->out, " : container = "); - ret = print_integer(text, container_field); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - fprintf(text->out, " )"); -end: - bt_put(iter); - bt_put(container_field_type); - bt_put(container_field); - bt_put(enumeration_field_type); - return ret; -} - -static -int filter_field_name(struct text_component *text, const char *field_name, - GQuark *filter_fields, int filter_array_len) -{ - int i; - GQuark field_quark = g_quark_try_string(field_name); - - if (!field_quark || text->options.verbose) { - return 1; - } - - for (i = 0; i < filter_array_len; i++) { - if (field_quark == filter_fields[i]) { - return 0; - } - } - return 1; -} - -static -enum bt_component_status print_struct_field(struct text_component *text, - struct bt_ctf_field *_struct, - struct bt_ctf_field_type *struct_type, - int i, bool print_names, int *nr_printed_fields, - GQuark *filter_fields, int filter_array_len) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - const char *field_name; - struct bt_ctf_field *field = NULL; - struct bt_ctf_field_type *field_type = NULL;; - - field = bt_ctf_field_structure_get_field_by_index(_struct, i); - if (!field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (bt_ctf_field_type_structure_get_field(struct_type, - &field_name, &field_type, i) < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - if (filter_fields && !filter_field_name(text, field_name, - filter_fields, filter_array_len)) { - ret = BT_COMPONENT_STATUS_OK; - goto end; - } - - if (*nr_printed_fields > 0) { - fprintf(text->out, ", "); - } else { - fprintf(text->out, " "); - } - if (print_names) { - print_field_name_equal(text, rem_(field_name)); - } - ret = print_field(text, field, print_names, NULL, 0); - *nr_printed_fields += 1; -end: - bt_put(field_type); - bt_put(field); - return ret; -} - -static -enum bt_component_status print_struct(struct text_component *text, - struct bt_ctf_field *_struct, bool print_names, - GQuark *filter_fields, int filter_array_len) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field_type *struct_type = NULL; - int nr_fields, i, nr_printed_fields; - - struct_type = bt_ctf_field_get_type(_struct); - if (!struct_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); - if (nr_fields < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - fprintf(text->out, "{"); - text->depth++; - nr_printed_fields = 0; - for (i = 0; i < nr_fields; i++) { - ret = print_struct_field(text, _struct, struct_type, i, - print_names, &nr_printed_fields, filter_fields, - filter_array_len); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - } - text->depth--; - fprintf(text->out, " }"); -end: - bt_put(struct_type); - return ret; -} - -static -enum bt_component_status print_array_field(struct text_component *text, - struct bt_ctf_field *array, uint64_t i, - bool is_string, bool print_names) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *field = NULL; - - if (!is_string) { - if (i != 0) { - fprintf(text->out, ", "); - } else { - fprintf(text->out, " "); - } - if (print_names) { - fprintf(text->out, "[%" PRIu64 "] = ", i); - } - } - field = bt_ctf_field_array_get_field(array, i); - if (!field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - ret = print_field(text, field, print_names, NULL, 0); -end: - bt_put(field); - return ret; -} - -static -enum bt_component_status print_array(struct text_component *text, - struct bt_ctf_field *array, bool print_names) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field_type *array_type = NULL, *field_type = NULL; - enum bt_ctf_field_type_id type_id; - int64_t len; - uint64_t i; - bool is_string = false; - - array_type = bt_ctf_field_get_type(array); - if (!array_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - field_type = bt_ctf_field_type_array_get_element_type(array_type); - if (!field_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - len = bt_ctf_field_type_array_get_length(array_type); - if (len < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - type_id = bt_ctf_field_type_get_type_id(field_type); - if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { - enum bt_ctf_string_encoding encoding; - - encoding = bt_ctf_field_type_integer_get_encoding(field_type); - if (encoding == BT_CTF_STRING_ENCODING_UTF8 - || encoding == BT_CTF_STRING_ENCODING_ASCII) { - int integer_len, integer_alignment; - - integer_len = bt_ctf_field_type_integer_get_size(field_type); - if (integer_len < 0) { - return BT_COMPONENT_STATUS_ERROR; - } - integer_alignment = bt_ctf_field_type_get_alignment(field_type); - if (integer_alignment < 0) { - return BT_COMPONENT_STATUS_ERROR; - } - if (integer_len == CHAR_BIT - && integer_alignment == CHAR_BIT) { - is_string = true; - } - } - } - - if (is_string) { - g_string_assign(text->string, ""); - } else { - fprintf(text->out, "["); - } - - text->depth++; - for (i = 0; i < len; i++) { - ret = print_array_field(text, array, i, is_string, print_names); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - } - text->depth--; - - if (is_string) { - if (text->use_colors) { - fputs(COLOR_STRING_VALUE, text->out); - } - print_escape_string(text, text->string->str); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - } else { - fprintf(text->out, " ]"); - } -end: - bt_put(field_type); - bt_put(array_type); - return ret; -} - -static -enum bt_component_status print_sequence_field(struct text_component *text, - struct bt_ctf_field *seq, uint64_t i, - bool is_string, bool print_names) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *field = NULL; - - if (!is_string) { - if (i != 0) { - fprintf(text->out, ", "); - } else { - fprintf(text->out, " "); - } - if (print_names) { - fprintf(text->out, "[%" PRIu64 "] = ", i); - } - } - field = bt_ctf_field_sequence_get_field(seq, i); - if (!field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - ret = print_field(text, field, print_names, NULL, 0); -end: - bt_put(field); - return ret; -} - -static -enum bt_component_status print_sequence(struct text_component *text, - struct bt_ctf_field *seq, bool print_names) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL; - struct bt_ctf_field *length_field = NULL; - enum bt_ctf_field_type_id type_id; - uint64_t len; - uint64_t i; - bool is_string = false; - - seq_type = bt_ctf_field_get_type(seq); - if (!seq_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - length_field = bt_ctf_field_sequence_get_length(seq); - if (!length_field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - field_type = bt_ctf_field_type_sequence_get_element_type(seq_type); - if (!field_type) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - type_id = bt_ctf_field_type_get_type_id(field_type); - if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { - enum bt_ctf_string_encoding encoding; - - encoding = bt_ctf_field_type_integer_get_encoding(field_type); - if (encoding == BT_CTF_STRING_ENCODING_UTF8 - || encoding == BT_CTF_STRING_ENCODING_ASCII) { - int integer_len, integer_alignment; - - integer_len = bt_ctf_field_type_integer_get_size(field_type); - if (integer_len < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - integer_alignment = bt_ctf_field_type_get_alignment(field_type); - if (integer_alignment < 0) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (integer_len == CHAR_BIT - && integer_alignment == CHAR_BIT) { - is_string = true; - } - } - } - - if (is_string) { - g_string_assign(text->string, ""); - } else { - fprintf(text->out, "["); - } - - text->depth++; - for (i = 0; i < len; i++) { - ret = print_sequence_field(text, seq, i, - is_string, print_names); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - } - text->depth--; - - if (is_string) { - if (text->use_colors) { - fputs(COLOR_STRING_VALUE, text->out); - } - print_escape_string(text, text->string->str); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - } else { - fprintf(text->out, " ]"); - } -end: - bt_put(length_field); - bt_put(field_type); - bt_put(seq_type); - return ret; -} - -static -enum bt_component_status print_variant(struct text_component *text, - struct bt_ctf_field *variant, bool print_names) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *field = NULL; - - field = bt_ctf_field_variant_get_current_field(variant); - if (!field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - fprintf(text->out, "{ "); - text->depth++; - if (print_names) { - int iter_ret; - struct bt_ctf_field *tag_field = NULL; - const char *tag_choice; - struct bt_ctf_field_type_enumeration_mapping_iterator *iter; - - tag_field = bt_ctf_field_variant_get_tag(variant); - if (!tag_field) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - iter = bt_ctf_field_enumeration_get_mappings(tag_field); - if (!iter) { - bt_put(tag_field); - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - iter_ret = - bt_ctf_field_type_enumeration_mapping_iterator_get_signed( - iter, &tag_choice, NULL, NULL); - if (iter_ret) { - bt_put(iter); - bt_put(tag_field); - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - print_field_name_equal(text, rem_(tag_choice)); - bt_put(tag_field); - bt_put(iter); - } - ret = print_field(text, field, print_names, NULL, 0); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->depth--; - fprintf(text->out, " }"); -end: - bt_put(field); - return ret; -} - -static -enum bt_component_status print_field(struct text_component *text, - struct bt_ctf_field *field, bool print_names, - GQuark *filter_fields, int filter_array_len) -{ - enum bt_ctf_field_type_id type_id; - - type_id = bt_ctf_field_get_type_id(field); - switch (type_id) { - case CTF_TYPE_INTEGER: - return print_integer(text, field); - case CTF_TYPE_FLOAT: - { - double v; - - if (bt_ctf_field_floating_point_get_value(field, &v)) { - return BT_COMPONENT_STATUS_ERROR; - } - if (text->use_colors) { - fputs(COLOR_NUMBER_VALUE, text->out); - } - fprintf(text->out, "%g", v); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - return BT_COMPONENT_STATUS_OK; - } - case CTF_TYPE_ENUM: - return print_enum(text, field); - case CTF_TYPE_STRING: - if (text->use_colors) { - fputs(COLOR_STRING_VALUE, text->out); - } - print_escape_string(text, bt_ctf_field_string_get_value(field)); - if (text->use_colors) { - fputs(COLOR_RST, text->out); - } - return BT_COMPONENT_STATUS_OK; - case CTF_TYPE_STRUCT: - return print_struct(text, field, print_names, filter_fields, - filter_array_len); - case CTF_TYPE_UNTAGGED_VARIANT: - case CTF_TYPE_VARIANT: - return print_variant(text, field, print_names); - case CTF_TYPE_ARRAY: - return print_array(text, field, print_names); - case CTF_TYPE_SEQUENCE: - return print_sequence(text, field, print_names); - default: - fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id); - return BT_COMPONENT_STATUS_ERROR; - } -} - -static -enum bt_component_status print_stream_packet_context(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_packet *packet = NULL; - struct bt_ctf_field *main_field = NULL; - - packet = bt_ctf_event_get_packet(event); - if (!packet) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - main_field = bt_ctf_packet_get_context(packet); - if (!main_field) { - goto end; - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = false; - if (text->options.print_scope_field_names) { - print_name_equal(text, "stream.packet.context"); - } - ret = print_field(text, main_field, - text->options.print_context_field_names, - stream_packet_context_quarks, - STREAM_PACKET_CONTEXT_QUARKS_LEN); -end: - bt_put(main_field); - bt_put(packet); - return ret; -} - -static -enum bt_component_status print_event_header_raw(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *main_field = NULL; - - main_field = bt_ctf_event_get_header(event); - if (!main_field) { - goto end; - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = false; - if (text->options.print_scope_field_names) { - print_name_equal(text, "stream.event.header"); - } - ret = print_field(text, main_field, - text->options.print_header_field_names, NULL, 0); -end: - bt_put(main_field); - return ret; -} - -static -enum bt_component_status print_stream_event_context(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *main_field = NULL; - - main_field = bt_ctf_event_get_stream_event_context(event); - if (!main_field) { - goto end; - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = false; - if (text->options.print_scope_field_names) { - print_name_equal(text, "stream.event.context"); - } - ret = print_field(text, main_field, - text->options.print_context_field_names, NULL, 0); -end: - bt_put(main_field); - return ret; -} - -static -enum bt_component_status print_event_context(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *main_field = NULL; - - main_field = bt_ctf_event_get_event_context(event); - if (!main_field) { - goto end; - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = false; - if (text->options.print_scope_field_names) { - print_name_equal(text, "event.context"); - } - ret = print_field(text, main_field, - text->options.print_context_field_names, NULL, 0); -end: - bt_put(main_field); - return ret; -} - -static -enum bt_component_status print_event_payload(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_ctf_field *main_field = NULL; - - main_field = bt_ctf_event_get_payload_field(event); - if (!main_field) { - goto end; - } - if (!text->start_line) { - fputs(", ", text->out); - } - text->start_line = false; - if (text->options.print_scope_field_names) { - print_name_equal(text, "event.fields"); - } - ret = print_field(text, main_field, - text->options.print_payload_field_names, NULL, 0); -end: - bt_put(main_field); - return ret; -} - -BT_HIDDEN -enum bt_component_status text_print_event(struct text_component *text, - struct bt_ctf_event *event) -{ - enum bt_component_status ret; - - text->start_line = true; - ret = print_event_header(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - ret = print_stream_packet_context(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - if (text->options.verbose) { - ret = print_event_header_raw(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - } - - ret = print_stream_event_context(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - ret = print_event_context(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - ret = print_event_payload(text, event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - fputc('\n', text->out); -end: - return ret; -} diff --git a/plugins/text/text.c b/plugins/text/text.c deleted file mode 100644 index bf7201d2..00000000 --- a/plugins/text/text.c +++ /dev/null @@ -1,798 +0,0 @@ -/* - * text.c - * - * Babeltrace CTF Text Output Plugin - * - * Copyright 2016 Jérémie Galarneau - * Copyright 2016 Mathieu Desnoyers - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "text.h" -#include - -static -const char *plugin_options[] = { - "color", - "output-path", - "debug-info-dir", - "debug-info-target-prefix", - "debug-info-full-path", - "no-delta", - "clock-cycles", - "clock-seconds", - "clock-date", - "clock-gmt", - "verbose", - "name-default", /* show/hide */ - "name-payload", - "name-context", - "name-scope", - "name-header", - "field-default", /* show/hide */ - "field-trace", - "field-trace:hostname", - "field-trace:domain", - "field-trace:procname", - "field-trace:vpid", - "field-loglevel", - "field-emf", - "field-callsite", -}; - -static -void destroy_text_data(struct text_component *text) -{ - bt_put(text->input_iterator); - (void) g_string_free(text->string, TRUE); - if (text->out != stdout) { - int ret; - - ret = fclose(text->out); - if (ret) { - perror("close output file"); - } - } - g_free(text->options.output_path); - g_free(text->options.debug_info_dir); - g_free(text->options.debug_info_target_prefix); - g_free(text); -} - -static -struct text_component *create_text(void) -{ - struct text_component *text; - - text = g_new0(struct text_component, 1); - if (!text) { - goto end; - } - text->string = g_string_new(""); - if (!text->string) { - goto error; - } -end: - return text; - -error: - g_free(text); - return NULL; -} - -static -void finalize_text(struct bt_private_component *component) -{ - void *data = bt_private_component_get_user_data(component); - - destroy_text_data(data); -} - -static -enum bt_component_status handle_notification(struct text_component *text, - struct bt_notification *notification) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - - if (!text) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - switch (bt_notification_get_type(notification)) { - case BT_NOTIFICATION_TYPE_PACKET_BEGIN: - break; - case BT_NOTIFICATION_TYPE_PACKET_END: - break; - case BT_NOTIFICATION_TYPE_EVENT: - { - struct bt_ctf_event *event = bt_notification_event_get_event( - notification); - - if (!event) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - ret = text_print_event(text, event); - bt_put(event); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - break; - } - case BT_NOTIFICATION_TYPE_STREAM_END: - break; - default: - puts("Unhandled notification type"); - } -end: - return ret; -} - -static -enum bt_component_status text_accept_port_connection( - struct bt_private_component *component, - struct bt_private_port *self_port, - struct bt_port *other_port) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_private_connection *connection; - struct text_component *text; - - text = bt_private_component_get_user_data(component); - assert(text); - assert(!text->input_iterator); - connection = bt_private_port_get_private_connection(self_port); - assert(connection); - text->input_iterator = - bt_private_connection_create_notification_iterator(connection); - - if (!text->input_iterator) { - ret = BT_COMPONENT_STATUS_ERROR; - } - - bt_put(connection); - return ret; -} - -static -enum bt_component_status run(struct bt_private_component *component) -{ - enum bt_component_status ret; - struct bt_notification *notification = NULL; - struct bt_notification_iterator *it; - struct text_component *text = - bt_private_component_get_user_data(component); - enum bt_notification_iterator_status it_ret; - - it = text->input_iterator; - - it_ret = bt_notification_iterator_next(it); - switch (it_ret) { - case BT_NOTIFICATION_ITERATOR_STATUS_ERROR: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - case BT_NOTIFICATION_ITERATOR_STATUS_END: - ret = BT_COMPONENT_STATUS_END; - BT_PUT(text->input_iterator); - goto end; - default: - break; - } - - notification = bt_notification_iterator_get_notification(it); - assert(notification); - ret = handle_notification(text, notification); - text->processed_first_event = true; -end: - bt_put(notification); - return ret; -} - -static -enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - unsigned int i; - - for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) { - const char *key = plugin_options[i]; - enum bt_value_status status; - - status = bt_value_map_insert(plugin_opt_map, key, bt_value_null); - switch (status) { - case BT_VALUE_STATUS_OK: - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - } -end: - return ret; -} - -static -bool check_param_exists(const char *key, struct bt_value *object, void *data) -{ - struct text_component *text = data; - struct bt_value *plugin_opt_map = text->plugin_opt_map; - - if (!bt_value_map_get(plugin_opt_map, key)) { - fprintf(text->err, - "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key); - } - return true; -} - -static -enum bt_component_status apply_one_string(const char *key, - struct bt_value *params, - char **option) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_value *value = NULL; - enum bt_value_status status; - const char *str; - - value = bt_value_map_get(params, key); - if (!value) { - goto end; - } - if (bt_value_is_null(value)) { - goto end; - } - status = bt_value_string_get(value, &str); - switch (status) { - case BT_VALUE_STATUS_OK: - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - *option = g_strdup(str); -end: - bt_put(value); - return ret; -} - -static -enum bt_component_status apply_one_bool(const char *key, - struct bt_value *params, - bool *option, - bool *found) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct bt_value *value = NULL; - enum bt_value_status status; - - value = bt_value_map_get(params, key); - if (!value) { - goto end; - } - status = bt_value_bool_get(value, option); - switch (status) { - case BT_VALUE_STATUS_OK: - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (found) { - *found = true; - } -end: - bt_put(value); - return ret; -} - -static -void warn_wrong_color_param(struct text_component *text) -{ - fprintf(text->err, - "[warning] Accepted values for the \"color\" parameter are:\n \"always\", \"auto\", \"never\"\n"); -} - -static -enum bt_component_status open_output_file(struct text_component *text) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - - if (!text->options.output_path) { - goto end; - } - - text->out = fopen(text->options.output_path, "w"); - if (!text->out) { - goto error; - } - - goto end; - -error: - ret = BT_COMPONENT_STATUS_ERROR; -end: - return ret; -} - -static -enum bt_component_status apply_params(struct text_component *text, - struct bt_value *params) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - enum bt_value_status status; - bool value, found; - char *str = NULL; - - text->plugin_opt_map = bt_value_map_create(); - if (!text->plugin_opt_map) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - ret = add_params_to_map(text->plugin_opt_map); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - /* Report unknown parameters. */ - status = bt_value_map_foreach(params, check_param_exists, text); - switch (status) { - case BT_VALUE_STATUS_OK: - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - /* Known parameters. */ - text->options.color = TEXT_COLOR_OPT_AUTO; - if (bt_value_map_has_key(params, "color")) { - struct bt_value *color_value; - const char *color; - - color_value = bt_value_map_get(params, "color"); - if (!color_value) { - goto end; - } - - status = bt_value_string_get(color_value, &color); - if (status) { - warn_wrong_color_param(text); - } else { - if (strcmp(color, "never") == 0) { - text->options.color = TEXT_COLOR_OPT_NEVER; - } else if (strcmp(color, "auto") == 0) { - text->options.color = TEXT_COLOR_OPT_AUTO; - } else if (strcmp(color, "always") == 0) { - text->options.color = TEXT_COLOR_OPT_ALWAYS; - } else { - warn_wrong_color_param(text); - } - } - - bt_put(color_value); - } - - ret = apply_one_string("output-path", - params, - &text->options.output_path); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - ret = open_output_file(text); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - ret = apply_one_string("debug-info-dir", - params, - &text->options.debug_info_dir); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - ret = apply_one_string("debug-info-target-prefix", - params, - &text->options.debug_info_target_prefix); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - - value = false; /* Default. */ - ret = apply_one_bool("debug-info-full-path", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.debug_info_full_path = value; - - value = false; /* Default. */ - ret = apply_one_bool("no-delta", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.print_delta_field = !value; /* Reverse logic. */ - - value = false; /* Default. */ - ret = apply_one_bool("clock-cycles", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.print_timestamp_cycles = value; - - value = false; /* Default. */ - ret = apply_one_bool("clock-seconds", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.clock_seconds = value; - - value = false; /* Default. */ - ret = apply_one_bool("clock-date", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.clock_date = value; - - value = false; /* Default. */ - ret = apply_one_bool("clock-gmt", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.clock_gmt = value; - - value = false; /* Default. */ - ret = apply_one_bool("verbose", params, &value, NULL); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - text->options.verbose = value; - - /* Names. */ - ret = apply_one_string("name-default", params, &str); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (!str) { - text->options.name_default = TEXT_DEFAULT_UNSET; - } else if (!strcmp(str, "show")) { - text->options.name_default = TEXT_DEFAULT_SHOW; - } else if (!strcmp(str, "hide")) { - text->options.name_default = TEXT_DEFAULT_HIDE; - } else { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - g_free(str); - str = NULL; - - switch (text->options.name_default) { - case TEXT_DEFAULT_UNSET: - text->options.print_payload_field_names = true; - text->options.print_context_field_names = true; - text->options.print_header_field_names = false; - text->options.print_scope_field_names = false; - break; - case TEXT_DEFAULT_SHOW: - text->options.print_payload_field_names = true; - text->options.print_context_field_names = true; - text->options.print_header_field_names = true; - text->options.print_scope_field_names = true; - break; - case TEXT_DEFAULT_HIDE: - text->options.print_payload_field_names = false; - text->options.print_context_field_names = false; - text->options.print_header_field_names = false; - text->options.print_scope_field_names = false; - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - value = false; - found = false; - ret = apply_one_bool("name-payload", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_payload_field_names = value; - } - - value = false; - found = false; - ret = apply_one_bool("name-context", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_context_field_names = value; - } - - value = false; - found = false; - ret = apply_one_bool("name-header", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_header_field_names = value; - } - - value = false; - found = false; - ret = apply_one_bool("name-scope", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_scope_field_names = value; - } - - /* Fields. */ - ret = apply_one_string("field-default", params, &str); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (!str) { - text->options.field_default = TEXT_DEFAULT_UNSET; - } else if (!strcmp(str, "show")) { - text->options.field_default = TEXT_DEFAULT_SHOW; - } else if (!strcmp(str, "hide")) { - text->options.field_default = TEXT_DEFAULT_HIDE; - } else { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - g_free(str); - str = NULL; - - switch (text->options.field_default) { - case TEXT_DEFAULT_UNSET: - text->options.print_trace_field = false; - text->options.print_trace_hostname_field = true; - text->options.print_trace_domain_field = false; - text->options.print_trace_procname_field = true; - text->options.print_trace_vpid_field = true; - text->options.print_loglevel_field = false; - text->options.print_emf_field = false; - text->options.print_callsite_field = false; - break; - case TEXT_DEFAULT_SHOW: - text->options.print_trace_field = true; - text->options.print_trace_hostname_field = true; - text->options.print_trace_domain_field = true; - text->options.print_trace_procname_field = true; - text->options.print_trace_vpid_field = true; - text->options.print_loglevel_field = true; - text->options.print_emf_field = true; - text->options.print_callsite_field = true; - break; - case TEXT_DEFAULT_HIDE: - text->options.print_trace_field = false; - text->options.print_trace_hostname_field = false; - text->options.print_trace_domain_field = false; - text->options.print_trace_procname_field = false; - text->options.print_trace_vpid_field = false; - text->options.print_loglevel_field = false; - text->options.print_emf_field = false; - text->options.print_callsite_field = false; - break; - default: - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - - value = false; - found = false; - ret = apply_one_bool("field-trace", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_trace_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-trace:hostname", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_trace_hostname_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-trace:domain", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_trace_domain_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-trace:procname", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_trace_procname_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-trace:vpid", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_trace_vpid_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-loglevel", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_loglevel_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-emf", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_emf_field = value; - } - - value = false; - found = false; - ret = apply_one_bool("field-callsite", params, &value, &found); - if (ret != BT_COMPONENT_STATUS_OK) { - goto end; - } - if (found) { - text->options.print_callsite_field = value; - } - -end: - bt_put(text->plugin_opt_map); - text->plugin_opt_map = NULL; - g_free(str); - return ret; -} - -static -void set_use_colors(struct text_component *text) -{ - switch (text->options.color) { - case TEXT_COLOR_OPT_ALWAYS: - text->use_colors = true; - break; - case TEXT_COLOR_OPT_AUTO: - text->use_colors = text->out == stdout && - bt_common_colors_supported(); - break; - case TEXT_COLOR_OPT_NEVER: - text->use_colors = false; - break; - } -} - -static -void init_stream_packet_context_quarks(void) -{ - stream_packet_context_quarks[Q_TIMESTAMP_BEGIN] = - g_quark_from_string("timestamp_begin"); - stream_packet_context_quarks[Q_TIMESTAMP_BEGIN] = - g_quark_from_string("timestamp_begin"); - stream_packet_context_quarks[Q_TIMESTAMP_END] = - g_quark_from_string("timestamp_end"); - stream_packet_context_quarks[Q_EVENTS_DISCARDED] = - g_quark_from_string("events_discarded"); - stream_packet_context_quarks[Q_CONTENT_SIZE] = - g_quark_from_string("content_size"); - stream_packet_context_quarks[Q_PACKET_SIZE] = - g_quark_from_string("packet_size"); - stream_packet_context_quarks[Q_PACKET_SEQ_NUM] = - g_quark_from_string("packet_seq_num"); -} - -static -enum bt_component_status text_component_init( - struct bt_private_component *component, - struct bt_value *params, - UNUSED_VAR void *init_method_data) -{ - enum bt_component_status ret; - struct text_component *text = create_text(); - - if (!text) { - ret = BT_COMPONENT_STATUS_NOMEM; - goto end; - } - - text->out = stdout; - text->err = stderr; - - text->delta_cycles = -1ULL; - text->last_cycles_timestamp = -1ULL; - - text->delta_real_timestamp = -1ULL; - text->last_real_timestamp = -1ULL; - - ret = apply_params(text, params); - if (ret != BT_COMPONENT_STATUS_OK) { - goto error; - } - - set_use_colors(text); - - ret = bt_private_component_set_user_data(component, text); - if (ret != BT_COMPONENT_STATUS_OK) { - goto error; - } - - init_stream_packet_context_quarks(); - -end: - return ret; -error: - destroy_text_data(text); - return ret; -} - -/* Initialize plug-in entry points. */ -BT_PLUGIN(text); -BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in."); -BT_PLUGIN_AUTHOR("Jérémie Galarneau"); -BT_PLUGIN_LICENSE("MIT"); -BT_PLUGIN_SINK_COMPONENT_CLASS(text, run); -BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(text, text_component_init); -BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(text, text_accept_port_connection); -BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(text, finalize_text); -BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(text, - "Formats CTF-IR to text. Formerly known as ctf-text."); diff --git a/plugins/text/text.h b/plugins/text/text.h deleted file mode 100644 index 222035e8..00000000 --- a/plugins/text/text.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_TEXT_H -#define BABELTRACE_PLUGIN_TEXT_H - -/* - * BabelTrace - CTF Text Output Plug-in - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -enum text_default { - TEXT_DEFAULT_UNSET, - TEXT_DEFAULT_SHOW, - TEXT_DEFAULT_HIDE, -}; - -enum text_color_option { - TEXT_COLOR_OPT_NEVER, - TEXT_COLOR_OPT_AUTO, - TEXT_COLOR_OPT_ALWAYS, -}; - -struct text_options { - char *output_path; - char *debug_info_dir; - char *debug_info_target_prefix; - - enum text_default name_default; - enum text_default field_default; - - bool print_scope_field_names; - bool print_header_field_names; - bool print_context_field_names; - bool print_payload_field_names; - - bool print_delta_field; - bool print_loglevel_field; - bool print_emf_field; - bool print_callsite_field; - bool print_trace_field; - bool print_trace_domain_field; - bool print_trace_procname_field; - bool print_trace_vpid_field; - bool print_trace_hostname_field; - - bool print_timestamp_cycles; - bool clock_seconds; - bool clock_date; - bool clock_gmt; - bool debug_info_full_path; - enum text_color_option color; - bool verbose; -}; - -struct text_component { - struct text_options options; - struct bt_notification_iterator *input_iterator; - FILE *out, *err; - bool processed_first_event; /* Should be per-iterator. */ - int depth; /* nesting, used for tabulation alignment. */ - bool start_line; - GString *string; - struct bt_value *plugin_opt_map; /* Temporary parameter map. */ - bool use_colors; - - uint64_t last_cycles_timestamp; - uint64_t delta_cycles; - - uint64_t last_real_timestamp; - uint64_t delta_real_timestamp; -}; - -enum stream_packet_context_quarks_enum { - Q_TIMESTAMP_BEGIN, - Q_TIMESTAMP_END, - Q_EVENTS_DISCARDED, - Q_CONTENT_SIZE, - Q_PACKET_SIZE, - Q_PACKET_SEQ_NUM, - STREAM_PACKET_CONTEXT_QUARKS_LEN, /* Always the last one of this enum. */ -}; - -GQuark stream_packet_context_quarks[STREAM_PACKET_CONTEXT_QUARKS_LEN]; - -BT_HIDDEN -enum bt_component_status text_print_event(struct text_component *text, - struct bt_ctf_event *event); - -#endif /* BABELTRACE_PLUGIN_TEXT_H */