2 * SPDX-License-Identifier: MIT
4 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 #include <babeltrace2/babeltrace.h>
9 #include "compat/bitfield.h"
10 #include "common/common.h"
11 #include "common/uuid.h"
12 #include "compat/time.h"
13 #include "common/assert.h"
20 #define NSEC_PER_SEC 1000000000LL
22 static char color_name
[32];
23 static char color_field_name
[32];
24 static char color_rst
[32];
25 static char color_string_value
[32];
26 static char color_number_value
[32];
27 static char color_enum_mapping_name
[32];
28 static char color_unknown
[32];
29 static char color_event_name
[32];
30 static char color_timestamp
[32];
33 int64_t real_timestamp
; /* Relative to UNIX epoch. */
34 uint64_t clock_snapshot
; /* In cycles. */
38 int print_field(struct pretty_component
*pretty
,
39 const bt_field
*field
, bool print_names
);
42 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
44 if (pretty
->use_colors
) {
45 bt_common_g_string_append(pretty
->string
, color_name
);
46 bt_common_g_string_append(pretty
->string
, name
);
47 bt_common_g_string_append(pretty
->string
, color_rst
);
49 bt_common_g_string_append(pretty
->string
, name
);
51 bt_common_g_string_append(pretty
->string
, " = ");
55 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
57 if (pretty
->use_colors
) {
58 bt_common_g_string_append(pretty
->string
, color_field_name
);
59 bt_common_g_string_append(pretty
->string
, name
);
60 bt_common_g_string_append(pretty
->string
, color_rst
);
62 bt_common_g_string_append(pretty
->string
, name
);
64 bt_common_g_string_append(pretty
->string
, " = ");
68 void print_timestamp_cycles(struct pretty_component
*pretty
,
69 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
73 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
74 bt_common_g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
77 if (pretty
->last_cycles_timestamp
!= -1ULL) {
78 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
81 pretty
->last_cycles_timestamp
= cycles
;
86 void print_timestamp_wall(struct pretty_component
*pretty
,
87 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
90 int64_t ts_nsec
= 0; /* add configurable offset */
91 int64_t ts_sec
= 0; /* add configurable offset */
92 uint64_t ts_sec_abs
, ts_nsec_abs
;
95 if (!clock_snapshot
) {
96 bt_common_g_string_append(pretty
->string
, "??:??:??.?????????");
100 ret
= bt_clock_snapshot_get_ns_from_origin(clock_snapshot
, &ts_nsec
);
102 // TODO: log, this is unexpected
103 bt_common_g_string_append(pretty
->string
, "Error");
108 if (pretty
->last_real_timestamp
!= -1ULL) {
109 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
112 pretty
->last_real_timestamp
= ts_nsec
;
115 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
116 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
118 if (ts_sec
>= 0 && ts_nsec
>= 0) {
121 ts_nsec_abs
= ts_nsec
;
122 } else if (ts_sec
> 0 && ts_nsec
< 0) {
124 ts_sec_abs
= ts_sec
- 1;
125 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
126 } else if (ts_sec
== 0 && ts_nsec
< 0) {
129 ts_nsec_abs
= -ts_nsec
;
130 } else if (ts_sec
< 0 && ts_nsec
> 0) {
132 ts_sec_abs
= -(ts_sec
+ 1);
133 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
134 } else if (ts_sec
< 0 && ts_nsec
== 0) {
136 ts_sec_abs
= -ts_sec
;
137 ts_nsec_abs
= ts_nsec
;
138 } else { /* (ts_sec < 0 && ts_nsec < 0) */
140 ts_sec_abs
= -ts_sec
;
141 ts_nsec_abs
= -ts_nsec
;
144 if (!pretty
->options
.clock_seconds
) {
146 time_t time_s
= (time_t) ts_sec_abs
;
148 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
150 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
151 pretty
->negative_timestamp_warning_done
= true;
155 if (!pretty
->options
.clock_gmt
) {
158 res
= bt_localtime_r(&time_s
, &tm
);
161 fprintf(stderr
, "[warning] Unable to get localtime.\n");
167 res
= bt_gmtime_r(&time_s
, &tm
);
170 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
174 if (pretty
->options
.clock_date
) {
178 /* Print date and time */
179 res
= strftime(timestr
, sizeof(timestr
),
183 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
187 bt_common_g_string_append(pretty
->string
, timestr
);
190 /* Print time in HH:MM:SS.ns */
191 bt_common_g_string_append_printf(pretty
->string
,
192 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
193 tm
.tm_sec
, ts_nsec_abs
);
197 bt_common_g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
198 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
204 int print_event_timestamp(struct pretty_component
*pretty
,
205 const bt_message
*event_msg
, bool *start_line
)
207 bool print_names
= pretty
->options
.print_header_field_names
;
209 const bt_clock_snapshot
*clock_snapshot
= NULL
;
211 if (!bt_message_event_borrow_stream_class_default_clock_class_const(
213 /* No default clock class: skip the timestamp without an error */
217 clock_snapshot
= bt_message_event_borrow_default_clock_snapshot_const(event_msg
);
220 print_name_equal(pretty
, "timestamp");
222 bt_common_g_string_append(pretty
->string
, "[");
224 if (pretty
->use_colors
) {
225 bt_common_g_string_append(pretty
->string
, color_timestamp
);
227 if (pretty
->options
.print_timestamp_cycles
) {
228 print_timestamp_cycles(pretty
, clock_snapshot
, true);
230 print_timestamp_wall(pretty
, clock_snapshot
, true);
232 if (pretty
->use_colors
) {
233 bt_common_g_string_append(pretty
->string
, color_rst
);
237 bt_common_g_string_append(pretty
->string
, "] ");
239 if (pretty
->options
.print_delta_field
) {
241 bt_common_g_string_append(pretty
->string
, ", ");
242 print_name_equal(pretty
, "delta");
244 bt_common_g_string_append(pretty
->string
, "(");
246 if (pretty
->options
.print_timestamp_cycles
) {
247 if (pretty
->delta_cycles
== -1ULL) {
248 bt_common_g_string_append(pretty
->string
,
249 "+??????????\?\?"); /* Not a trigraph. */
251 bt_common_g_string_append_printf(pretty
->string
,
252 "+%012" PRIu64
, pretty
->delta_cycles
);
255 if (pretty
->delta_real_timestamp
!= -1ULL) {
256 uint64_t delta_sec
, delta_nsec
, delta
;
258 delta
= pretty
->delta_real_timestamp
;
259 delta_sec
= delta
/ NSEC_PER_SEC
;
260 delta_nsec
= delta
% NSEC_PER_SEC
;
261 bt_common_g_string_append_printf(pretty
->string
,
262 "+%" PRIu64
".%09" PRIu64
,
263 delta_sec
, delta_nsec
);
265 bt_common_g_string_append(pretty
->string
, "+?.?????????");
269 bt_common_g_string_append(pretty
->string
, ") ");
272 *start_line
= !print_names
;
279 int print_event_header(struct pretty_component
*pretty
,
280 const bt_message
*event_msg
)
282 bool print_names
= pretty
->options
.print_header_field_names
;
284 const bt_event_class
*event_class
= NULL
;
285 const bt_stream
*stream
= NULL
;
286 const bt_trace
*trace
= NULL
;
287 const bt_event
*event
= bt_message_event_borrow_event_const(event_msg
);
290 bt_property_availability prop_avail
;
292 event_class
= bt_event_borrow_class_const(event
);
293 stream
= bt_event_borrow_stream_const(event
);
294 trace
= bt_stream_borrow_trace_const(stream
);
295 ret
= print_event_timestamp(pretty
, event_msg
, &pretty
->start_line
);
299 if (pretty
->options
.print_trace_field
) {
302 name
= bt_trace_get_name(trace
);
304 if (!pretty
->start_line
) {
305 bt_common_g_string_append(pretty
->string
, ", ");
308 print_name_equal(pretty
, "trace");
311 bt_common_g_string_append(pretty
->string
, name
);
314 bt_common_g_string_append(pretty
->string
, ", ");
318 if (pretty
->options
.print_trace_hostname_field
) {
319 const bt_value
*hostname_str
;
321 hostname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
326 if (!pretty
->start_line
) {
327 bt_common_g_string_append(pretty
->string
, ", ");
330 print_name_equal(pretty
, "trace:hostname");
332 str
= bt_value_string_get(hostname_str
);
333 bt_common_g_string_append(pretty
->string
, str
);
337 if (pretty
->options
.print_trace_domain_field
) {
338 const bt_value
*domain_str
;
340 domain_str
= bt_trace_borrow_environment_entry_value_by_name_const(
345 if (!pretty
->start_line
) {
346 bt_common_g_string_append(pretty
->string
, ", ");
349 print_name_equal(pretty
, "trace:domain");
350 } else if (dom_print
) {
351 bt_common_g_string_append(pretty
->string
, ":");
353 str
= bt_value_string_get(domain_str
);
354 bt_common_g_string_append(pretty
->string
, str
);
358 if (pretty
->options
.print_trace_procname_field
) {
359 const bt_value
*procname_str
;
361 procname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
366 if (!pretty
->start_line
) {
367 bt_common_g_string_append(pretty
->string
, ", ");
370 print_name_equal(pretty
, "trace:procname");
371 } else if (dom_print
) {
372 bt_common_g_string_append(pretty
->string
, ":");
374 str
= bt_value_string_get(procname_str
);
375 bt_common_g_string_append(pretty
->string
, str
);
379 if (pretty
->options
.print_trace_vpid_field
) {
380 const bt_value
*vpid_value
;
382 vpid_value
= bt_trace_borrow_environment_entry_value_by_name_const(
387 if (!pretty
->start_line
) {
388 bt_common_g_string_append(pretty
->string
, ", ");
391 print_name_equal(pretty
, "trace:vpid");
392 } else if (dom_print
) {
393 bt_common_g_string_append(pretty
->string
, ":");
395 value
= bt_value_integer_signed_get(vpid_value
);
396 bt_common_g_string_append_printf(pretty
->string
,
397 "(%" PRId64
")", value
);
401 if (pretty
->options
.print_loglevel_field
) {
402 static const char *log_level_names
[] = {
403 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
404 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
405 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
406 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
407 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
408 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
409 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
410 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
411 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
412 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
413 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
414 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
415 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
416 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
417 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
419 bt_event_class_log_level log_level
;
420 const char *log_level_str
= NULL
;
422 prop_avail
= bt_event_class_get_log_level(event_class
,
424 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
425 log_level_str
= log_level_names
[log_level
];
426 BT_ASSERT_DBG(log_level_str
);
428 if (!pretty
->start_line
) {
429 bt_common_g_string_append(pretty
->string
, ", ");
432 print_name_equal(pretty
, "loglevel");
433 } else if (dom_print
) {
434 bt_common_g_string_append(pretty
->string
, ":");
437 bt_common_g_string_append(pretty
->string
, log_level_str
);
438 bt_common_g_string_append_printf(
439 pretty
->string
, " (%d)", (int) log_level
);
443 if (pretty
->options
.print_emf_field
) {
446 uri_str
= bt_event_class_get_emf_uri(event_class
);
448 if (!pretty
->start_line
) {
449 bt_common_g_string_append(pretty
->string
, ", ");
452 print_name_equal(pretty
, "model.emf.uri");
453 } else if (dom_print
) {
454 bt_common_g_string_append(pretty
->string
, ":");
457 bt_common_g_string_append(pretty
->string
, uri_str
);
461 if (dom_print
&& !print_names
) {
462 bt_common_g_string_append(pretty
->string
, " ");
464 if (!pretty
->start_line
) {
465 bt_common_g_string_append(pretty
->string
, ", ");
467 pretty
->start_line
= true;
469 print_name_equal(pretty
, "name");
471 ev_name
= bt_event_class_get_name(event_class
);
472 if (pretty
->use_colors
) {
474 bt_common_g_string_append(pretty
->string
,
477 bt_common_g_string_append(pretty
->string
,
482 bt_common_g_string_append(pretty
->string
, ev_name
);
484 bt_common_g_string_append(pretty
->string
, "<unknown>");
486 if (pretty
->use_colors
) {
487 bt_common_g_string_append(pretty
->string
, color_rst
);
490 bt_common_g_string_append(pretty
->string
, ": ");
492 bt_common_g_string_append(pretty
->string
, ", ");
500 int print_integer(struct pretty_component
*pretty
,
501 const bt_field
*field
)
504 bt_field_class_integer_preferred_display_base base
;
505 const bt_field_class
*int_fc
;
510 bool rst_color
= false;
511 bt_field_class_type ft_type
;
513 int_fc
= bt_field_borrow_class_const(field
);
514 BT_ASSERT_DBG(int_fc
);
515 ft_type
= bt_field_get_class_type(field
);
516 if (bt_field_class_type_is(ft_type
,
517 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
)) {
518 v
.u
= bt_field_integer_unsigned_get_value(field
);
520 v
.s
= bt_field_integer_signed_get_value(field
);
523 if (pretty
->use_colors
) {
524 bt_common_g_string_append(pretty
->string
, color_number_value
);
528 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
530 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
534 len
= bt_field_class_integer_get_field_value_range(int_fc
);
535 bt_common_g_string_append(pretty
->string
, "0b");
536 _bt_safe_lshift(v
.u
, 64 - len
);
537 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
538 bt_common_g_string_append_c(pretty
->string
,
539 (v
.u
& (1ULL << 63)) ? '1' : '0');
540 _bt_safe_lshift(v
.u
, 1);
544 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
546 if (bt_field_class_type_is(ft_type
,
547 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
)) {
550 len
= bt_field_class_integer_get_field_value_range(
555 BT_ASSERT_DBG(len
!= 0);
556 /* Round length to the nearest 3-bit */
557 rounded_len
= (((len
- 1) / 3) + 1) * 3;
558 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
562 bt_common_g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
565 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
566 if (bt_field_class_type_is(ft_type
,
567 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
)) {
568 bt_common_g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
570 bt_common_g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
573 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
577 len
= bt_field_class_integer_get_field_value_range(int_fc
);
579 /* Round length to the nearest nibble */
580 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
582 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
585 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
594 bt_common_g_string_append(pretty
->string
, color_rst
);
600 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
604 bt_common_g_string_append_c(pretty
->string
, '"');
606 for (i
= 0; i
< strlen(str
); i
++) {
607 /* Escape sequences not recognized by iscntrl(). */
610 bt_common_g_string_append(pretty
->string
, "\\\\");
613 bt_common_g_string_append(pretty
->string
, "\\\'");
616 bt_common_g_string_append(pretty
->string
, "\\\"");
619 bt_common_g_string_append(pretty
->string
, "\\\?");
623 /* Standard characters. */
624 if (!iscntrl((unsigned char) str
[i
])) {
625 bt_common_g_string_append_c(pretty
->string
, str
[i
]);
631 bt_common_g_string_append(pretty
->string
, "\\0");
634 bt_common_g_string_append(pretty
->string
, "\\a");
637 bt_common_g_string_append(pretty
->string
, "\\b");
640 bt_common_g_string_append(pretty
->string
, "\\e");
643 bt_common_g_string_append(pretty
->string
, "\\f");
646 bt_common_g_string_append(pretty
->string
, "\\n");
649 bt_common_g_string_append(pretty
->string
, "\\r");
652 bt_common_g_string_append(pretty
->string
, "\\t");
655 bt_common_g_string_append(pretty
->string
, "\\v");
658 /* Unhandled control-sequence, print as hex. */
659 bt_common_g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
664 bt_common_g_string_append_c(pretty
->string
, '"');
668 * Print the unknown label.
671 void print_enum_value_label_unknown(struct pretty_component
*pretty
)
673 if (pretty
->use_colors
) {
674 bt_common_g_string_append(pretty
->string
, color_unknown
);
677 bt_common_g_string_append(pretty
->string
, "<unknown>");
679 if (pretty
->use_colors
) {
680 bt_common_g_string_append(pretty
->string
, color_rst
);
685 * Print labels for a value. If there are more than one label for the
686 * value, they will be printed in "{ }".
689 void print_enum_value_label_array(struct pretty_component
*pretty
,
690 uint64_t label_count
,
691 bt_field_class_enumeration_mapping_label_array label_array
)
695 if (label_count
> 1) {
696 bt_common_g_string_append(pretty
->string
, "{ ");
699 for (i
= 0; i
< label_count
; i
++) {
700 const char *mapping_name
= label_array
[i
];
703 bt_common_g_string_append(pretty
->string
, ", ");
705 if (pretty
->use_colors
) {
706 bt_common_g_string_append(pretty
->string
, color_enum_mapping_name
);
708 print_escape_string(pretty
, mapping_name
);
709 if (pretty
->use_colors
) {
710 bt_common_g_string_append(pretty
->string
, color_rst
);
714 if (label_count
> 1) {
715 bt_common_g_string_append(pretty
->string
, " }");
720 * Print arrays of labels and counts are ORed bit flags.
723 void print_enum_value_bit_flag_label_arrays(struct pretty_component
*pretty
)
726 bool first_label
= true;
728 /* For each bit with a label count > 0, print the labels. */
729 for (i
= 0; i
< ENUMERATION_MAX_BITFLAGS_COUNT
; i
++) {
730 uint64_t label_count
= pretty
->enum_bit_labels
[i
]->len
;
732 if (label_count
> 0) {
734 bt_common_g_string_append(pretty
->string
, " | ");
736 print_enum_value_label_array(pretty
, label_count
,
737 (void *) pretty
->enum_bit_labels
[i
]->pdata
);
744 * Get the labels mapping to an unsigned value.
746 * This function will set the count to the count of mapping labels that match
747 * the value. If count == 0, the caller has nothing to do, if count > 0,
748 * the label_array contains the labels to print and the caller is responsible
749 * to call g_free on it once the values have been used.
752 void print_enum_unsigned_get_mapping_labels_for_value(const bt_field_class
*fc
,
753 uint64_t value
, GPtrArray
*labels
)
755 uint64_t mapping_count
= bt_field_class_enumeration_get_mapping_count(fc
);
758 for (i
= 0; i
< mapping_count
; i
++) {
760 const struct bt_field_class_enumeration_unsigned_mapping
*mapping
=
761 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(fc
, i
);
762 const bt_integer_range_set_unsigned
*ranges
=
763 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
764 uint64_t range_count
= bt_integer_range_set_get_range_count(
765 bt_integer_range_set_unsigned_as_range_set_const(ranges
));
767 for (range_i
= 0; range_i
< range_count
; range_i
++) {
768 const bt_integer_range_unsigned
*range
=
769 bt_integer_range_set_unsigned_borrow_range_by_index_const(ranges
, range_i
);
770 uint64_t lower
= bt_integer_range_unsigned_get_lower(range
);
771 uint64_t upper
= bt_integer_range_unsigned_get_upper(range
);
774 * Flag is active if this range represents a single value
775 * (lower == upper) and the lower is the same as the bit
776 * value to test against.
778 if ((lower
== upper
) && (lower
== value
)) {
779 g_ptr_array_add(labels
, (void *) bt_field_class_enumeration_mapping_get_label(
780 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping
)));
788 * Splits an unsigned enum value into its bit and for each bit set,
789 * try to find a corresponding label.
791 * If any bit set does not have a corresponding label, then it prints
792 * an unknown value, otherwise, it prints the labels, separated by '|'
795 void print_enum_unsigned_try_bit_flags(struct pretty_component
*pretty
,
796 const bt_field
*field
)
799 uint64_t value
= bt_field_integer_unsigned_get_value(field
);
800 const bt_field_class
*fc
= bt_field_borrow_class_const(field
);
802 /* Value is 0, if there was a label for it, we would know by now. */
804 print_enum_value_label_unknown(pretty
);
808 for (i
= 0; i
< ENUMERATION_MAX_BITFLAGS_COUNT
; i
++) {
809 uint64_t bit_value
= UINT64_C(1) << i
;
811 if ((value
& bit_value
) != 0) {
812 print_enum_unsigned_get_mapping_labels_for_value(
813 fc
, bit_value
, pretty
->enum_bit_labels
[i
]);
815 if (pretty
->enum_bit_labels
[i
]->len
== 0) {
817 * This bit has no matching label, so this
818 * field is not a bit flag field, print
819 * unknown and return.
821 print_enum_value_label_unknown(pretty
);
827 print_enum_value_bit_flag_label_arrays(pretty
);
834 * Get the labels mapping to a signed value
836 * This function will set the count to the count of mapping labels that match
837 * the value. If count == 0, the caller has nothing to do, if count > 0,
838 * the label_array contains the labels to print and the caller is responsible
839 * to call g_free on it once the values have been used.
842 void print_enum_signed_get_mapping_labels_for_value(const bt_field_class
*fc
,
843 int64_t value
, GPtrArray
*labels
)
845 uint64_t mapping_count
= bt_field_class_enumeration_get_mapping_count(fc
);
848 for (i
= 0; i
< mapping_count
; i
++) {
850 const struct bt_field_class_enumeration_signed_mapping
*mapping
=
851 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(fc
, i
);
852 const bt_integer_range_set_signed
*ranges
=
853 bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
854 uint64_t range_count
= bt_integer_range_set_get_range_count(
855 bt_integer_range_set_signed_as_range_set_const(ranges
));
857 for (range_i
= 0; range_i
< range_count
; range_i
++) {
858 const bt_integer_range_signed
*range
=
859 bt_integer_range_set_signed_borrow_range_by_index_const(ranges
, range_i
);
860 uint64_t lower
= bt_integer_range_signed_get_lower(range
);
861 uint64_t upper
= bt_integer_range_signed_get_upper(range
);
864 * Flag is active if this range represents a single value
865 * (lower == upper) and the lower is the same as the bit
866 * value to test against.
868 if ((lower
== upper
) && (lower
== value
)) {
869 g_ptr_array_add(labels
, (void*) bt_field_class_enumeration_mapping_get_label(
870 bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping
)));
878 * Splits a signed enum value into its bit and for each bit set,
879 * try to find a corresponding label.
881 * If any bit set does not have a corresponding label, then it prints
882 * an unknown value, otherwise, it prints the labels, separated by '|'.
885 void print_enum_signed_try_bit_flags(struct pretty_component
*pretty
,
886 const bt_field
*field
)
889 int64_t value
= bt_field_integer_signed_get_value(field
);
890 const bt_field_class
*fc
= bt_field_borrow_class_const(field
);
893 * Negative value, not a bit flag enum
894 * For 0, if there was a value, we would know by now.
897 print_enum_value_label_unknown(pretty
);
901 for (i
= 0; i
< ENUMERATION_MAX_BITFLAGS_COUNT
; i
++) {
902 uint64_t bit_value
= 1ULL << i
;
904 if ((value
& bit_value
) != 0) {
905 print_enum_signed_get_mapping_labels_for_value(
906 fc
, bit_value
, pretty
->enum_bit_labels
[i
]);
908 if (pretty
->enum_bit_labels
[i
]->len
== 0) {
910 * This bit has no matching label, so this
911 * field is not a bit flag field, print
912 * unknown and return.
914 print_enum_value_label_unknown(pretty
);
920 print_enum_value_bit_flag_label_arrays(pretty
);
927 * Main function to try to print the value of the enum field as a
928 * bit flag. It calls the appropriate function depending on the
929 * field type's signedness and prints the label for each bit set,
930 * if it's a bit flag field.
933 void print_enum_try_bit_flags(struct pretty_component
*pretty
,
934 const bt_field
*field
)
936 const bt_field_class
*fc
= bt_field_borrow_class_const(field
);
937 uint64_t int_range
= bt_field_class_integer_get_field_value_range(fc
);
940 BT_ASSERT(int_range
<= ENUMERATION_MAX_BITFLAGS_COUNT
);
943 * Remove all labels from the previous enumeration field.
945 for (i
= 0; i
< ENUMERATION_MAX_BITFLAGS_COUNT
; i
++) {
946 g_ptr_array_set_size(pretty
->enum_bit_labels
[i
], 0);
949 /* Get the mapping labels for the bit value. */
950 switch (bt_field_class_get_type(fc
)) {
951 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
952 print_enum_unsigned_try_bit_flags(pretty
, field
);
954 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
955 print_enum_signed_try_bit_flags(pretty
, field
);
963 int print_enum(struct pretty_component
*pretty
,
964 const bt_field
*field
)
967 bt_field_class_enumeration_mapping_label_array label_array
;
968 uint64_t label_count
;
970 switch (bt_field_get_class_type(field
)) {
971 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
972 ret
= bt_field_enumeration_unsigned_get_mapping_labels(field
,
973 &label_array
, &label_count
);
975 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
976 ret
= bt_field_enumeration_signed_get_mapping_labels(field
,
977 &label_array
, &label_count
);
988 bt_common_g_string_append(pretty
->string
, "( ");
989 if (label_count
!= 0) {
990 /* The numerical value matches some labels, print them. */
991 print_enum_value_label_array(pretty
, label_count
, label_array
);
992 } else if (pretty
->options
.print_enum_flags
) {
994 * The numerical value of the enumeration does not match any
995 * label but the `print-enum-flags` parameter is TRUE so try to
996 * decompose the value of the enum into bits and print it as a
999 print_enum_try_bit_flags(pretty
, field
);
1001 print_enum_value_label_unknown(pretty
);
1004 /* Print the actual value of the enum. */
1005 bt_common_g_string_append(pretty
->string
, " : container = ");
1006 ret
= print_integer(pretty
, field
);
1010 bt_common_g_string_append(pretty
->string
, " )");
1016 int print_struct_field(struct pretty_component
*pretty
,
1017 const bt_field
*_struct
,
1018 const bt_field_class
*struct_class
,
1019 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
)
1022 const char *field_name
;
1023 const bt_field
*field
= NULL
;
1024 const bt_field_class_structure_member
*member
;
1026 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
1032 member
= bt_field_class_structure_borrow_member_by_index_const(
1034 field_name
= bt_field_class_structure_member_get_name(member
);
1036 if (*nr_printed_fields
> 0) {
1037 bt_common_g_string_append(pretty
->string
, ", ");
1039 bt_common_g_string_append(pretty
->string
, " ");
1042 print_field_name_equal(pretty
, field_name
);
1044 ret
= print_field(pretty
, field
, print_names
);
1045 *nr_printed_fields
+= 1;
1052 int print_struct(struct pretty_component
*pretty
,
1053 const bt_field
*_struct
, bool print_names
)
1056 const bt_field_class
*struct_class
= NULL
;
1057 uint64_t nr_fields
, i
, nr_printed_fields
;
1059 struct_class
= bt_field_borrow_class_const(_struct
);
1060 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
1062 bt_common_g_string_append(pretty
->string
, "{");
1064 nr_printed_fields
= 0;
1065 for (i
= 0; i
< nr_fields
; i
++) {
1066 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
1067 print_names
, &nr_printed_fields
);
1073 bt_common_g_string_append(pretty
->string
, " }");
1080 int print_array_field(struct pretty_component
*pretty
,
1081 const bt_field
*array
, uint64_t i
, bool print_names
)
1083 const bt_field
*field
= NULL
;
1086 bt_common_g_string_append(pretty
->string
, ", ");
1088 bt_common_g_string_append(pretty
->string
, " ");
1091 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1094 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
1095 BT_ASSERT_DBG(field
);
1096 return print_field(pretty
, field
, print_names
);
1100 int print_array(struct pretty_component
*pretty
,
1101 const bt_field
*array
, bool print_names
)
1107 len
= bt_field_array_get_length(array
);
1108 bt_common_g_string_append(pretty
->string
, "[");
1110 for (i
= 0; i
< len
; i
++) {
1111 ret
= print_array_field(pretty
, array
, i
, print_names
);
1117 bt_common_g_string_append(pretty
->string
, " ]");
1124 int print_sequence_field(struct pretty_component
*pretty
,
1125 const bt_field
*seq
, uint64_t i
, bool print_names
)
1127 const bt_field
*field
= NULL
;
1130 bt_common_g_string_append(pretty
->string
, ", ");
1132 bt_common_g_string_append(pretty
->string
, " ");
1135 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1138 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
1139 BT_ASSERT_DBG(field
);
1140 return print_field(pretty
, field
, print_names
);
1144 int print_sequence(struct pretty_component
*pretty
,
1145 const bt_field
*seq
, bool print_names
)
1151 len
= bt_field_array_get_length(seq
);
1152 bt_common_g_string_append(pretty
->string
, "[");
1155 for (i
= 0; i
< len
; i
++) {
1156 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
1162 bt_common_g_string_append(pretty
->string
, " ]");
1169 int print_option(struct pretty_component
*pretty
,
1170 const bt_field
*option
, bool print_names
)
1173 const bt_field
*field
= NULL
;
1175 field
= bt_field_option_borrow_field_const(option
);
1177 bt_common_g_string_append(pretty
->string
, "{ ");
1180 // TODO: find tag's name using field path
1181 // print_field_name_equal(pretty, tag_choice);
1183 ret
= print_field(pretty
, field
, print_names
);
1188 bt_common_g_string_append(pretty
->string
, " }");
1190 bt_common_g_string_append(pretty
->string
, "<none>");
1198 int print_variant(struct pretty_component
*pretty
,
1199 const bt_field
*variant
, bool print_names
)
1202 const bt_field
*field
= NULL
;
1204 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
1205 BT_ASSERT_DBG(field
);
1206 bt_common_g_string_append(pretty
->string
, "{ ");
1209 // TODO: find tag's name using field path
1210 // print_field_name_equal(pretty, tag_choice);
1212 ret
= print_field(pretty
, field
, print_names
);
1217 bt_common_g_string_append(pretty
->string
, " }");
1224 int print_field(struct pretty_component
*pretty
,
1225 const bt_field
*field
, bool print_names
)
1227 bt_field_class_type class_id
;
1229 class_id
= bt_field_get_class_type(field
);
1230 if (class_id
== BT_FIELD_CLASS_TYPE_BOOL
) {
1234 v
= bt_field_bool_get_value(field
);
1235 if (pretty
->use_colors
) {
1236 bt_common_g_string_append(pretty
->string
, color_number_value
);
1243 bt_common_g_string_append(pretty
->string
, text
);
1244 if (pretty
->use_colors
) {
1245 bt_common_g_string_append(pretty
->string
, color_rst
);
1248 } else if (class_id
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1249 uint64_t v
= bt_field_bit_array_get_value_as_integer(field
);
1251 if (pretty
->use_colors
) {
1252 bt_common_g_string_append(pretty
->string
,
1253 color_number_value
);
1255 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
,
1257 if (pretty
->use_colors
) {
1258 bt_common_g_string_append(pretty
->string
, color_rst
);
1261 } else if (bt_field_class_type_is(class_id
,
1262 BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
1263 return print_enum(pretty
, field
);
1264 } else if (bt_field_class_type_is(class_id
,
1265 BT_FIELD_CLASS_TYPE_INTEGER
)) {
1266 return print_integer(pretty
, field
);
1267 } else if (bt_field_class_type_is(class_id
,
1268 BT_FIELD_CLASS_TYPE_REAL
)) {
1271 if (class_id
== BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
1272 v
= bt_field_real_single_precision_get_value(field
);
1274 v
= bt_field_real_double_precision_get_value(field
);
1277 if (pretty
->use_colors
) {
1278 bt_common_g_string_append(pretty
->string
, color_number_value
);
1280 bt_common_g_string_append_printf(pretty
->string
, "%g", v
);
1281 if (pretty
->use_colors
) {
1282 bt_common_g_string_append(pretty
->string
, color_rst
);
1285 } else if (class_id
== BT_FIELD_CLASS_TYPE_STRING
) {
1288 str
= bt_field_string_get_value(field
);
1293 if (pretty
->use_colors
) {
1294 bt_common_g_string_append(pretty
->string
, color_string_value
);
1296 print_escape_string(pretty
, str
);
1297 if (pretty
->use_colors
) {
1298 bt_common_g_string_append(pretty
->string
, color_rst
);
1301 } else if (class_id
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1302 return print_struct(pretty
, field
, print_names
);
1303 } else if (bt_field_class_type_is(class_id
,
1304 BT_FIELD_CLASS_TYPE_OPTION
)) {
1305 return print_option(pretty
, field
, print_names
);
1306 } else if (bt_field_class_type_is(class_id
,
1307 BT_FIELD_CLASS_TYPE_VARIANT
)) {
1308 return print_variant(pretty
, field
, print_names
);
1309 } else if (class_id
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1310 return print_array(pretty
, field
, print_names
);
1311 } else if (bt_field_class_type_is(class_id
,
1312 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1313 return print_sequence(pretty
, field
, print_names
);
1320 int print_stream_packet_context(struct pretty_component
*pretty
,
1321 const bt_event
*event
)
1324 const bt_packet
*packet
= NULL
;
1325 const bt_field
*main_field
= NULL
;
1327 packet
= bt_event_borrow_packet_const(event
);
1331 main_field
= bt_packet_borrow_context_field_const(packet
);
1335 if (!pretty
->start_line
) {
1336 bt_common_g_string_append(pretty
->string
, ", ");
1338 pretty
->start_line
= false;
1339 if (pretty
->options
.print_scope_field_names
) {
1340 print_name_equal(pretty
, "stream.packet.context");
1342 ret
= print_field(pretty
, main_field
,
1343 pretty
->options
.print_context_field_names
);
1350 int print_stream_event_context(struct pretty_component
*pretty
,
1351 const bt_event
*event
)
1354 const bt_field
*main_field
= NULL
;
1356 main_field
= bt_event_borrow_common_context_field_const(event
);
1360 if (!pretty
->start_line
) {
1361 bt_common_g_string_append(pretty
->string
, ", ");
1363 pretty
->start_line
= false;
1364 if (pretty
->options
.print_scope_field_names
) {
1365 print_name_equal(pretty
, "stream.event.context");
1367 ret
= print_field(pretty
, main_field
,
1368 pretty
->options
.print_context_field_names
);
1375 int print_event_context(struct pretty_component
*pretty
,
1376 const bt_event
*event
)
1379 const bt_field
*main_field
= NULL
;
1381 main_field
= bt_event_borrow_specific_context_field_const(event
);
1385 if (!pretty
->start_line
) {
1386 bt_common_g_string_append(pretty
->string
, ", ");
1388 pretty
->start_line
= false;
1389 if (pretty
->options
.print_scope_field_names
) {
1390 print_name_equal(pretty
, "event.context");
1392 ret
= print_field(pretty
, main_field
,
1393 pretty
->options
.print_context_field_names
);
1400 int print_event_payload(struct pretty_component
*pretty
,
1401 const bt_event
*event
)
1404 const bt_field
*main_field
= NULL
;
1406 main_field
= bt_event_borrow_payload_field_const(event
);
1410 if (!pretty
->start_line
) {
1411 bt_common_g_string_append(pretty
->string
, ", ");
1413 pretty
->start_line
= false;
1414 if (pretty
->options
.print_scope_field_names
) {
1415 print_name_equal(pretty
, "event.fields");
1417 ret
= print_field(pretty
, main_field
,
1418 pretty
->options
.print_payload_field_names
);
1425 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1429 if (pretty
->string
->len
== 0) {
1433 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1441 int pretty_print_event(struct pretty_component
*pretty
,
1442 const bt_message
*event_msg
)
1445 const bt_event
*event
=
1446 bt_message_event_borrow_event_const(event_msg
);
1448 BT_ASSERT_DBG(event
);
1449 pretty
->start_line
= true;
1450 g_string_assign(pretty
->string
, "");
1451 ret
= print_event_header(pretty
, event_msg
);
1456 ret
= print_stream_packet_context(pretty
, event
);
1461 ret
= print_stream_event_context(pretty
, event
);
1466 ret
= print_event_context(pretty
, event
);
1471 ret
= print_event_payload(pretty
, event
);
1476 bt_common_g_string_append_c(pretty
->string
, '\n');
1477 if (flush_buf(pretty
->out
, pretty
)) {
1487 int print_discarded_elements_msg(struct pretty_component
*pretty
,
1488 const bt_stream
*stream
,
1489 const bt_clock_snapshot
*begin_clock_snapshot
,
1490 const bt_clock_snapshot
*end_clock_snapshot
,
1491 uint64_t count
, const char *elem_type
)
1494 const bt_stream_class
*stream_class
= NULL
;
1495 const bt_trace
*trace
= NULL
;
1496 const char *stream_name
;
1497 const char *trace_name
;
1499 int64_t stream_class_id
;
1501 const char *init_msg
;
1504 stream_name
= bt_stream_get_name(stream
);
1506 stream_name
= "(unknown)";
1509 /* Stream class ID */
1510 stream_class
= bt_stream_borrow_class_const(stream
);
1511 BT_ASSERT(stream_class
);
1512 stream_class_id
= bt_stream_class_get_id(stream_class
);
1515 stream_id
= bt_stream_get_id(stream
);
1518 trace
= bt_stream_borrow_trace_const(stream
);
1520 trace_name
= bt_trace_get_name(trace
);
1522 trace_name
= "(unknown)";
1526 trace_uuid
= bt_trace_get_uuid(trace
);
1528 /* Format message */
1529 g_string_assign(pretty
->string
, "");
1531 if (count
== UINT64_C(-1)) {
1532 init_msg
= "Tracer may have discarded";
1534 init_msg
= "Tracer discarded";
1537 bt_common_g_string_append_printf(pretty
->string
,
1538 "%s%sWARNING%s%s: %s ",
1539 bt_common_color_fg_yellow(),
1540 bt_common_color_bold(),
1541 bt_common_color_reset(),
1542 bt_common_color_fg_yellow(), init_msg
);
1544 if (count
== UINT64_C(-1)) {
1545 bt_common_g_string_append_printf(pretty
->string
, "%ss", elem_type
);
1547 bt_common_g_string_append_printf(pretty
->string
,
1548 "%" PRIu64
" %s%s", count
, elem_type
,
1549 count
== 1 ? "" : "s");
1552 bt_common_g_string_append_c(pretty
->string
, ' ');
1554 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1555 bt_common_g_string_append(pretty
->string
, "between [");
1556 print_timestamp_wall(pretty
, begin_clock_snapshot
, false);
1557 bt_common_g_string_append(pretty
->string
, "] and [");
1558 print_timestamp_wall(pretty
, end_clock_snapshot
, false);
1559 bt_common_g_string_append(pretty
->string
, "]");
1561 bt_common_g_string_append(pretty
->string
, "(unknown time range)");
1564 bt_common_g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1567 bt_common_g_string_append_printf(pretty
->string
,
1568 "(UUID: " BT_UUID_FMT
") ",
1569 BT_UUID_FMT_VALUES(trace_uuid
));
1571 bt_common_g_string_append(pretty
->string
, "(no UUID) ");
1574 bt_common_g_string_append_printf(pretty
->string
,
1575 "within stream \"%s\" (stream class ID: %" PRIu64
", ",
1576 stream_name
, stream_class_id
);
1578 if (stream_id
>= 0) {
1579 bt_common_g_string_append_printf(pretty
->string
,
1580 "stream ID: %" PRIu64
, stream_id
);
1582 bt_common_g_string_append(pretty
->string
, "no stream ID");
1585 bt_common_g_string_append_printf(pretty
->string
, ").%s\n",
1586 bt_common_color_reset());
1589 * Print to standard error stream to remain backward compatible
1590 * with Babeltrace 1.
1592 if (flush_buf(stderr
, pretty
)) {
1599 int pretty_print_discarded_items(struct pretty_component
*pretty
,
1600 const bt_message
*msg
)
1602 const bt_clock_snapshot
*begin
= NULL
;
1603 const bt_clock_snapshot
*end
= NULL
;
1604 const bt_stream
*stream
;
1605 const bt_stream_class
*stream_class
;
1606 uint64_t count
= UINT64_C(-1);
1607 const char *elem_type
;
1609 switch (bt_message_get_type(msg
)) {
1610 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1611 stream
= bt_message_discarded_events_borrow_stream_const(msg
);
1613 if (bt_message_discarded_events_get_count(msg
, &count
) ==
1614 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1615 count
= UINT64_C(-1);
1618 elem_type
= "event";
1620 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1621 stream
= bt_message_discarded_packets_borrow_stream_const(msg
);
1623 if (bt_message_discarded_packets_get_count(msg
, &count
) ==
1624 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1625 count
= UINT64_C(-1);
1628 elem_type
= "packet";
1635 stream_class
= bt_stream_borrow_class_const(stream
);
1637 switch (bt_message_get_type(msg
)) {
1638 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1639 if (bt_stream_class_discarded_events_have_default_clock_snapshots(
1641 begin
= bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1643 end
= bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1648 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1649 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(
1651 begin
= bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1653 end
= bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1662 print_discarded_elements_msg(pretty
, stream
, begin
, end
,
1667 void pretty_print_init(void)
1669 strcpy(color_name
, bt_common_color_bold());
1670 strcpy(color_field_name
, bt_common_color_fg_cyan());
1671 strcpy(color_rst
, bt_common_color_reset());
1672 strcpy(color_string_value
, bt_common_color_bold());
1673 strcpy(color_number_value
, bt_common_color_bold());
1674 strcpy(color_enum_mapping_name
, bt_common_color_bold());
1675 strcpy(color_unknown
, bt_common_color_bold());
1676 strcat(color_unknown
, bt_common_color_fg_bright_red());
1677 strcpy(color_event_name
, bt_common_color_bold());
1678 strcat(color_event_name
, bt_common_color_fg_bright_magenta());
1679 strcpy(color_timestamp
, bt_common_color_bold());
1680 strcat(color_timestamp
, bt_common_color_fg_bright_yellow());