4 * Babeltrace CTF Text Output Plugin Event Printing
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #include <babeltrace/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock-class.h>
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/trace.h>
39 #include <babeltrace/bitfield.h>
40 #include <babeltrace/common-internal.h>
44 #define NSEC_PER_SEC 1000000000LL
46 #define COLOR_NAME BT_COMMON_COLOR_BOLD
47 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
48 #define COLOR_RST BT_COMMON_COLOR_RESET
49 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
50 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
51 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
52 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
53 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
54 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
57 const char *rem_(const char *str
)
66 int64_t real_timestamp
; /* Relative to UNIX epoch. */
67 uint64_t clock_value
; /* In cycles. */
71 enum bt_component_status
print_field(struct text_component
*text
,
72 struct bt_ctf_field
*field
, bool print_names
,
73 GQuark
*filters_fields
, int filter_array_len
);
76 void print_name_equal(struct text_component
*text
, const char *name
)
78 if (text
->use_colors
) {
79 fprintf(text
->out
, "%s%s%s = ", COLOR_NAME
, name
, COLOR_RST
);
81 fprintf(text
->out
, "%s = ", name
);
86 void print_field_name_equal(struct text_component
*text
, const char *name
)
88 if (text
->use_colors
) {
89 fprintf(text
->out
, "%s%s%s = ", COLOR_FIELD_NAME
, name
,
92 fprintf(text
->out
, "%s = ", name
);
97 void print_timestamp_cycles(struct text_component
*text
,
98 struct bt_ctf_clock_class
*clock_class
,
99 struct bt_ctf_event
*event
)
102 struct bt_ctf_clock_value
*clock_value
;
105 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
107 fputs("????????????????????", text
->out
);
111 ret
= bt_ctf_clock_value_get_value(clock_value
, &cycles
);
114 fprintf(text
->out
, "Error");
117 fprintf(text
->out
, "%020" PRIu64
, cycles
);
119 if (text
->last_cycles_timestamp
!= -1ULL) {
120 text
->delta_cycles
= cycles
- text
->last_cycles_timestamp
;
122 text
->last_cycles_timestamp
= cycles
;
126 void print_timestamp_wall(struct text_component
*text
,
127 struct bt_ctf_clock_class
*clock_class
,
128 struct bt_ctf_event
*event
)
131 struct bt_ctf_clock_value
*clock_value
;
132 int64_t ts_nsec
= 0; /* add configurable offset */
133 int64_t ts_sec
= 0; /* add configurable offset */
134 uint64_t ts_sec_abs
, ts_nsec_abs
;
137 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
139 fputs("??:??:??.?????????", text
->out
);
143 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
146 fprintf(text
->out
, "Error");
150 if (text
->last_real_timestamp
!= -1ULL) {
151 text
->delta_real_timestamp
= ts_nsec
- text
->last_real_timestamp
;
153 text
->last_real_timestamp
= ts_nsec
;
155 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
156 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
157 if (ts_sec
>= 0 && ts_nsec
>= 0) {
160 ts_nsec_abs
= ts_nsec
;
161 } else if (ts_sec
> 0 && ts_nsec
< 0) {
163 ts_sec_abs
= ts_sec
- 1;
164 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
165 } else if (ts_sec
== 0 && ts_nsec
< 0) {
168 ts_nsec_abs
= -ts_nsec
;
169 } else if (ts_sec
< 0 && ts_nsec
> 0) {
171 ts_sec_abs
= -(ts_sec
+ 1);
172 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
173 } else if (ts_sec
< 0 && ts_nsec
== 0) {
175 ts_sec_abs
= -ts_sec
;
176 ts_nsec_abs
= ts_nsec
;
177 } else { /* (ts_sec < 0 && ts_nsec < 0) */
179 ts_sec_abs
= -ts_sec
;
180 ts_nsec_abs
= -ts_nsec
;
183 if (!text
->options
.clock_seconds
) {
185 time_t time_s
= (time_t) ts_sec_abs
;
188 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
192 if (!text
->options
.clock_gmt
) {
195 res
= localtime_r(&time_s
, &tm
);
197 fprintf(stderr
, "[warning] Unable to get localtime.\n");
203 res
= gmtime_r(&time_s
, &tm
);
205 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
209 if (text
->options
.clock_date
) {
213 /* Print date and time */
214 res
= strftime(timestr
, sizeof(timestr
),
217 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
220 fprintf(text
->out
, "%s", timestr
);
222 /* Print time in HH:MM:SS.ns */
223 fprintf(text
->out
, "%02d:%02d:%02d.%09" PRIu64
,
224 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, ts_nsec_abs
);
228 fprintf(text
->out
, "%s%" PRId64
".%09" PRIu64
,
229 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
235 enum bt_component_status
print_event_timestamp(struct text_component
*text
,
236 struct bt_ctf_event
*event
, bool *start_line
)
238 bool print_names
= text
->options
.print_header_field_names
;
239 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
240 struct bt_ctf_stream
*stream
= NULL
;
241 struct bt_ctf_stream_class
*stream_class
= NULL
;
242 struct bt_ctf_trace
*trace
= NULL
;
243 struct bt_ctf_clock_class
*clock_class
= NULL
;
244 FILE *out
= text
->out
;
246 stream
= bt_ctf_event_get_stream(event
);
248 ret
= BT_COMPONENT_STATUS_ERROR
;
252 stream_class
= bt_ctf_stream_get_class(stream
);
254 ret
= BT_COMPONENT_STATUS_ERROR
;
257 trace
= bt_ctf_stream_class_get_trace(stream_class
);
259 ret
= BT_COMPONENT_STATUS_ERROR
;
262 clock_class
= bt_ctf_trace_get_clock_class(trace
, 0);
264 ret
= BT_COMPONENT_STATUS_ERROR
;
269 print_name_equal(text
, "timestamp");
273 if (text
->use_colors
) {
274 fputs(COLOR_TIMESTAMP
, text
->out
);
276 if (text
->options
.print_timestamp_cycles
) {
277 print_timestamp_cycles(text
, clock_class
, event
);
279 print_timestamp_wall(text
, clock_class
, event
);
281 if (text
->use_colors
) {
282 fputs(COLOR_RST
, text
->out
);
288 if (text
->options
.print_delta_field
) {
290 fputs(", ", text
->out
);
291 print_name_equal(text
, "delta");
293 fputs("(", text
->out
);
295 if (text
->options
.print_timestamp_cycles
) {
296 if (text
->delta_cycles
== -1ULL) {
297 fputs("+??????????\?\?) ", text
->out
); /* Not a trigraph. */
299 fprintf(text
->out
, "+%012" PRIu64
, text
->delta_cycles
);
302 if (text
->delta_real_timestamp
!= -1ULL) {
303 uint64_t delta_sec
, delta_nsec
, delta
;
305 delta
= text
->delta_real_timestamp
;
306 delta_sec
= delta
/ NSEC_PER_SEC
;
307 delta_nsec
= delta
% NSEC_PER_SEC
;
308 fprintf(text
->out
, "+%" PRIu64
".%09" PRIu64
,
309 delta_sec
, delta_nsec
);
311 fputs("+?.?????????", text
->out
);
315 fputs(") ", text
->out
);
318 *start_line
= !print_names
;
323 bt_put(stream_class
);
329 enum bt_component_status
print_event_header(struct text_component
*text
,
330 struct bt_ctf_event
*event
)
332 bool print_names
= text
->options
.print_header_field_names
;
333 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
334 struct bt_ctf_event_class
*event_class
= NULL
;
335 struct bt_ctf_stream_class
*stream_class
= NULL
;
336 struct bt_ctf_trace
*trace_class
= NULL
;
339 event_class
= bt_ctf_event_get_class(event
);
341 ret
= BT_COMPONENT_STATUS_ERROR
;
344 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
346 ret
= BT_COMPONENT_STATUS_ERROR
;
349 trace_class
= bt_ctf_stream_class_get_trace(stream_class
);
351 ret
= BT_COMPONENT_STATUS_ERROR
;
354 ret
= print_event_timestamp(text
, event
, &text
->start_line
);
355 if (ret
!= BT_COMPONENT_STATUS_OK
) {
358 if (text
->options
.print_trace_field
) {
361 name
= bt_ctf_trace_get_name(trace_class
);
363 if (!text
->start_line
) {
364 fputs(", ", text
->out
);
367 print_name_equal(text
, "trace");
369 fprintf(text
->out
, "%s", name
);
371 fprintf(text
->out
, " ");
375 if (text
->options
.print_trace_hostname_field
) {
376 struct bt_value
*hostname_str
;
378 hostname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
383 if (!text
->start_line
) {
384 fputs(", ", text
->out
);
387 print_name_equal(text
, "trace:hostname");
389 if (bt_value_string_get(hostname_str
, &str
)
390 == BT_VALUE_STATUS_OK
) {
391 fprintf(text
->out
, "%s", str
);
393 bt_put(hostname_str
);
397 if (text
->options
.print_trace_domain_field
) {
398 struct bt_value
*domain_str
;
400 domain_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
405 if (!text
->start_line
) {
406 fputs(", ", text
->out
);
409 print_name_equal(text
, "trace:domain");
410 } else if (dom_print
) {
411 fputs(":", text
->out
);
413 if (bt_value_string_get(domain_str
, &str
)
414 == BT_VALUE_STATUS_OK
) {
415 fprintf(text
->out
, "%s", str
);
421 if (text
->options
.print_trace_procname_field
) {
422 struct bt_value
*procname_str
;
424 procname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
429 if (!text
->start_line
) {
430 fputs(", ", text
->out
);
433 print_name_equal(text
, "trace:procname");
434 } else if (dom_print
) {
435 fputs(":", text
->out
);
437 if (bt_value_string_get(procname_str
, &str
)
438 == BT_VALUE_STATUS_OK
) {
439 fprintf(text
->out
, "%s", str
);
441 bt_put(procname_str
);
445 if (text
->options
.print_trace_vpid_field
) {
446 struct bt_value
*vpid_value
;
448 vpid_value
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
453 if (!text
->start_line
) {
454 fputs(", ", text
->out
);
457 print_name_equal(text
, "trace:vpid");
458 } else if (dom_print
) {
459 fputs(":", text
->out
);
461 if (bt_value_integer_get(vpid_value
, &value
)
462 == BT_VALUE_STATUS_OK
) {
463 fprintf(text
->out
, "(%" PRId64
")", value
);
469 if (text
->options
.print_loglevel_field
) {
470 struct bt_value
*loglevel_str
, *loglevel_value
;
472 loglevel_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
474 loglevel_value
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
476 if (loglevel_str
|| loglevel_value
) {
477 bool has_str
= false;
479 if (!text
->start_line
) {
480 fputs(", ", text
->out
);
483 print_name_equal(text
, "loglevel");
484 } else if (dom_print
) {
485 fputs(":", text
->out
);
490 if (bt_value_string_get(loglevel_str
, &str
)
491 == BT_VALUE_STATUS_OK
) {
492 fprintf(text
->out
, "%s", str
);
496 if (loglevel_value
) {
499 if (bt_value_integer_get(loglevel_value
, &value
)
500 == BT_VALUE_STATUS_OK
) {
501 fprintf(text
->out
, "%s(%" PRId64
")",
502 has_str
? " " : "", value
);
505 bt_put(loglevel_str
);
506 bt_put(loglevel_value
);
510 if (text
->options
.print_emf_field
) {
511 struct bt_value
*uri_str
;
513 uri_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
516 if (!text
->start_line
) {
517 fputs(", ", text
->out
);
520 print_name_equal(text
, "model.emf.uri");
521 } else if (dom_print
) {
522 fputs(":", text
->out
);
527 if (bt_value_string_get(uri_str
, &str
)
528 == BT_VALUE_STATUS_OK
) {
529 fprintf(text
->out
, "%s", str
);
536 if (dom_print
&& !print_names
) {
537 fputs(" ", text
->out
);
539 if (!text
->start_line
) {
540 fputs(", ", text
->out
);
542 text
->start_line
= true;
544 print_name_equal(text
, "name");
546 if (text
->use_colors
) {
547 fputs(COLOR_EVENT_NAME
, text
->out
);
549 fputs(bt_ctf_event_class_get_name(event_class
), text
->out
);
550 if (text
->use_colors
) {
551 fputs(COLOR_RST
, text
->out
);
554 fputs(": ", text
->out
);
556 fputs(", ", text
->out
);
560 bt_put(stream_class
);
566 enum bt_component_status
print_integer(struct text_component
*text
,
567 struct bt_ctf_field
*field
)
569 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
570 struct bt_ctf_field_type
*field_type
= NULL
;
571 enum bt_ctf_integer_base base
;
572 enum bt_ctf_string_encoding encoding
;
578 bool rst_color
= false;
580 field_type
= bt_ctf_field_get_type(field
);
582 ret
= BT_COMPONENT_STATUS_ERROR
;
585 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
586 if (signedness
< 0) {
587 ret
= BT_COMPONENT_STATUS_ERROR
;
591 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
592 ret
= BT_COMPONENT_STATUS_ERROR
;
596 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
597 ret
= BT_COMPONENT_STATUS_ERROR
;
602 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
604 case BT_CTF_STRING_ENCODING_UTF8
:
605 case BT_CTF_STRING_ENCODING_ASCII
:
606 g_string_append_c(text
->string
, (int) v
.u
);
608 case BT_CTF_STRING_ENCODING_NONE
:
609 case BT_CTF_STRING_ENCODING_UNKNOWN
:
612 ret
= BT_COMPONENT_STATUS_ERROR
;
616 if (text
->use_colors
) {
617 fputs(COLOR_NUMBER_VALUE
, text
->out
);
621 base
= bt_ctf_field_type_integer_get_base(field_type
);
623 case BT_CTF_INTEGER_BASE_BINARY
:
627 len
= bt_ctf_field_type_integer_get_size(field_type
);
629 ret
= BT_COMPONENT_STATUS_ERROR
;
632 fprintf(text
->out
, "0b");
633 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
634 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
635 fprintf(text
->out
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
636 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
640 case BT_CTF_INTEGER_BASE_OCTAL
:
645 len
= bt_ctf_field_type_integer_get_size(field_type
);
647 ret
= BT_COMPONENT_STATUS_ERROR
;
654 /* Round length to the nearest 3-bit */
655 rounded_len
= (((len
- 1) / 3) + 1) * 3;
656 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
660 fprintf(text
->out
, "0%" PRIo64
, v
.u
);
663 case BT_CTF_INTEGER_BASE_DECIMAL
:
665 fprintf(text
->out
, "%" PRIu64
, v
.u
);
667 fprintf(text
->out
, "%" PRId64
, v
.s
);
670 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
674 len
= bt_ctf_field_type_integer_get_size(field_type
);
676 ret
= BT_COMPONENT_STATUS_ERROR
;
680 /* Round length to the nearest nibble */
681 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
683 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
686 fprintf(text
->out
, "0x%" PRIX64
, v
.u
);
690 ret
= BT_COMPONENT_STATUS_ERROR
;
695 fputs(COLOR_RST
, text
->out
);
702 enum bt_component_status
print_enum(struct text_component
*text
,
703 struct bt_ctf_field
*field
)
705 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
706 struct bt_ctf_field
*container_field
= NULL
;
707 struct bt_ctf_field_type
*enumeration_field_type
= NULL
;
708 struct bt_ctf_field_type
*container_field_type
= NULL
;
709 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
= NULL
;
713 enumeration_field_type
= bt_ctf_field_get_type(field
);
714 if (!enumeration_field_type
) {
715 ret
= BT_COMPONENT_STATUS_ERROR
;
718 container_field
= bt_ctf_field_enumeration_get_container(field
);
719 if (!container_field
) {
720 ret
= BT_COMPONENT_STATUS_ERROR
;
723 container_field_type
= bt_ctf_field_get_type(container_field
);
724 if (!container_field_type
) {
725 ret
= BT_COMPONENT_STATUS_ERROR
;
728 is_signed
= bt_ctf_field_type_integer_get_signed(container_field_type
);
730 ret
= BT_COMPONENT_STATUS_ERROR
;
736 if (bt_ctf_field_signed_integer_get_value(container_field
,
738 ret
= BT_COMPONENT_STATUS_ERROR
;
741 iter
= bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
742 enumeration_field_type
, value
);
746 if (bt_ctf_field_unsigned_integer_get_value(container_field
,
748 ret
= BT_COMPONENT_STATUS_ERROR
;
751 iter
= bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
752 enumeration_field_type
, value
);
755 ret
= BT_COMPONENT_STATUS_ERROR
;
758 fprintf(text
->out
, "( ");
760 const char *mapping_name
;
762 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
763 iter
, &mapping_name
, NULL
, NULL
) < 0) {
764 ret
= BT_COMPONENT_STATUS_ERROR
;
768 fprintf(text
->out
, ", ");
769 if (text
->use_colors
) {
770 fputs(COLOR_ENUM_MAPPING_NAME
, text
->out
);
772 // TODO: escape string
773 fprintf(text
->out
, "\"%s\"", mapping_name
);
774 if (text
->use_colors
) {
775 fputs(COLOR_RST
, text
->out
);
777 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
782 if (text
->use_colors
) {
783 fputs(COLOR_UNKNOWN
, text
->out
);
785 fprintf(text
->out
, "<unknown>");
786 if (text
->use_colors
) {
787 fputs(COLOR_RST
, text
->out
);
790 fprintf(text
->out
, " : container = ");
791 ret
= print_integer(text
, container_field
);
792 if (ret
!= BT_COMPONENT_STATUS_OK
) {
795 fprintf(text
->out
, " )");
798 bt_put(container_field_type
);
799 bt_put(container_field
);
800 bt_put(enumeration_field_type
);
805 int filter_field_name(struct text_component
*text
, const char *field_name
,
806 GQuark
*filter_fields
, int filter_array_len
)
809 GQuark field_quark
= g_quark_try_string(field_name
);
811 if (!field_quark
|| text
->options
.verbose
) {
815 for (i
= 0; i
< filter_array_len
; i
++) {
816 if (field_quark
== filter_fields
[i
]) {
824 enum bt_component_status
print_struct_field(struct text_component
*text
,
825 struct bt_ctf_field
*_struct
,
826 struct bt_ctf_field_type
*struct_type
,
827 int i
, bool print_names
, int *nr_printed_fields
,
828 GQuark
*filter_fields
, int filter_array_len
)
830 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
831 const char *field_name
;
832 struct bt_ctf_field
*field
= NULL
;
833 struct bt_ctf_field_type
*field_type
= NULL
;;
835 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
837 ret
= BT_COMPONENT_STATUS_ERROR
;
840 if (bt_ctf_field_type_structure_get_field(struct_type
,
841 &field_name
, &field_type
, i
) < 0) {
842 ret
= BT_COMPONENT_STATUS_ERROR
;
846 if (filter_fields
&& !filter_field_name(text
, field_name
,
847 filter_fields
, filter_array_len
)) {
848 ret
= BT_COMPONENT_STATUS_OK
;
852 if (*nr_printed_fields
> 0) {
853 fprintf(text
->out
, ", ");
855 fprintf(text
->out
, " ");
858 print_field_name_equal(text
, rem_(field_name
));
860 ret
= print_field(text
, field
, print_names
, NULL
, 0);
861 *nr_printed_fields
+= 1;
869 enum bt_component_status
print_struct(struct text_component
*text
,
870 struct bt_ctf_field
*_struct
, bool print_names
,
871 GQuark
*filter_fields
, int filter_array_len
)
873 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
874 struct bt_ctf_field_type
*struct_type
= NULL
;
875 int nr_fields
, i
, nr_printed_fields
;
877 struct_type
= bt_ctf_field_get_type(_struct
);
879 ret
= BT_COMPONENT_STATUS_ERROR
;
882 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
884 ret
= BT_COMPONENT_STATUS_ERROR
;
887 fprintf(text
->out
, "{");
889 nr_printed_fields
= 0;
890 for (i
= 0; i
< nr_fields
; i
++) {
891 ret
= print_struct_field(text
, _struct
, struct_type
, i
,
892 print_names
, &nr_printed_fields
, filter_fields
,
894 if (ret
!= BT_COMPONENT_STATUS_OK
) {
899 fprintf(text
->out
, " }");
906 enum bt_component_status
print_array_field(struct text_component
*text
,
907 struct bt_ctf_field
*array
, uint64_t i
,
908 bool is_string
, bool print_names
)
910 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
911 struct bt_ctf_field
*field
= NULL
;
915 fprintf(text
->out
, ", ");
917 fprintf(text
->out
, " ");
920 fprintf(text
->out
, "[%" PRIu64
"] = ", i
);
923 field
= bt_ctf_field_array_get_field(array
, i
);
925 ret
= BT_COMPONENT_STATUS_ERROR
;
928 ret
= print_field(text
, field
, print_names
, NULL
, 0);
935 enum bt_component_status
print_array(struct text_component
*text
,
936 struct bt_ctf_field
*array
, bool print_names
)
938 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
939 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
940 enum bt_ctf_type_id type_id
;
943 bool is_string
= false;
945 array_type
= bt_ctf_field_get_type(array
);
947 ret
= BT_COMPONENT_STATUS_ERROR
;
950 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
952 ret
= BT_COMPONENT_STATUS_ERROR
;
955 len
= bt_ctf_field_type_array_get_length(array_type
);
957 ret
= BT_COMPONENT_STATUS_ERROR
;
960 type_id
= bt_ctf_field_type_get_type_id(field_type
);
961 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
962 enum bt_ctf_string_encoding encoding
;
964 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
965 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
966 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
967 int integer_len
, integer_alignment
;
969 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
970 if (integer_len
< 0) {
971 return BT_COMPONENT_STATUS_ERROR
;
973 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
974 if (integer_alignment
< 0) {
975 return BT_COMPONENT_STATUS_ERROR
;
977 if (integer_len
== CHAR_BIT
978 && integer_alignment
== CHAR_BIT
) {
985 g_string_assign(text
->string
, "");
987 fprintf(text
->out
, "[");
991 for (i
= 0; i
< len
; i
++) {
992 ret
= print_array_field(text
, array
, i
, is_string
, print_names
);
993 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1000 if (text
->use_colors
) {
1001 fputs(COLOR_STRING_VALUE
, text
->out
);
1003 // TODO: escape string
1004 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
1005 if (text
->use_colors
) {
1006 fputs(COLOR_RST
, text
->out
);
1009 fprintf(text
->out
, " ]");
1018 enum bt_component_status
print_sequence_field(struct text_component
*text
,
1019 struct bt_ctf_field
*seq
, uint64_t i
,
1020 bool is_string
, bool print_names
)
1022 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1023 struct bt_ctf_field
*field
= NULL
;
1027 fprintf(text
->out
, ", ");
1029 fprintf(text
->out
, " ");
1032 fprintf(text
->out
, "[%" PRIu64
"] = ", i
);
1035 field
= bt_ctf_field_sequence_get_field(seq
, i
);
1037 ret
= BT_COMPONENT_STATUS_ERROR
;
1040 ret
= print_field(text
, field
, print_names
, NULL
, 0);
1047 enum bt_component_status
print_sequence(struct text_component
*text
,
1048 struct bt_ctf_field
*seq
, bool print_names
)
1050 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1051 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
1052 struct bt_ctf_field
*length_field
= NULL
;
1053 enum bt_ctf_type_id type_id
;
1056 bool is_string
= false;
1058 seq_type
= bt_ctf_field_get_type(seq
);
1060 ret
= BT_COMPONENT_STATUS_ERROR
;
1063 length_field
= bt_ctf_field_sequence_get_length(seq
);
1064 if (!length_field
) {
1065 ret
= BT_COMPONENT_STATUS_ERROR
;
1068 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
1069 ret
= BT_COMPONENT_STATUS_ERROR
;
1072 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
1074 ret
= BT_COMPONENT_STATUS_ERROR
;
1077 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1078 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
1079 enum bt_ctf_string_encoding encoding
;
1081 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1082 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1083 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1084 int integer_len
, integer_alignment
;
1086 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1087 if (integer_len
< 0) {
1088 ret
= BT_COMPONENT_STATUS_ERROR
;
1091 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1092 if (integer_alignment
< 0) {
1093 ret
= BT_COMPONENT_STATUS_ERROR
;
1096 if (integer_len
== CHAR_BIT
1097 && integer_alignment
== CHAR_BIT
) {
1104 g_string_assign(text
->string
, "");
1106 fprintf(text
->out
, "[");
1110 for (i
= 0; i
< len
; i
++) {
1111 ret
= print_sequence_field(text
, seq
, i
,
1112 is_string
, print_names
);
1113 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1120 if (text
->use_colors
) {
1121 fputs(COLOR_STRING_VALUE
, text
->out
);
1123 // TODO: escape string
1124 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
1125 if (text
->use_colors
) {
1126 fputs(COLOR_RST
, text
->out
);
1129 fprintf(text
->out
, " ]");
1132 bt_put(length_field
);
1139 enum bt_component_status
print_variant(struct text_component
*text
,
1140 struct bt_ctf_field
*variant
, bool print_names
)
1142 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1143 struct bt_ctf_field
*field
= NULL
;
1145 field
= bt_ctf_field_variant_get_current_field(variant
);
1147 ret
= BT_COMPONENT_STATUS_ERROR
;
1150 fprintf(text
->out
, "{ ");
1154 struct bt_ctf_field
*tag_field
= NULL
;
1155 const char *tag_choice
;
1156 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
;
1158 tag_field
= bt_ctf_field_variant_get_tag(variant
);
1160 ret
= BT_COMPONENT_STATUS_ERROR
;
1164 iter
= bt_ctf_field_enumeration_get_mappings(tag_field
);
1167 ret
= BT_COMPONENT_STATUS_ERROR
;
1172 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1173 iter
, &tag_choice
, NULL
, NULL
);
1177 ret
= BT_COMPONENT_STATUS_ERROR
;
1180 print_field_name_equal(text
, rem_(tag_choice
));
1184 ret
= print_field(text
, field
, print_names
, NULL
, 0);
1185 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1189 fprintf(text
->out
, " }");
1196 enum bt_component_status
print_field(struct text_component
*text
,
1197 struct bt_ctf_field
*field
, bool print_names
,
1198 GQuark
*filter_fields
, int filter_array_len
)
1200 enum bt_ctf_type_id type_id
;
1202 type_id
= bt_ctf_field_get_type_id(field
);
1204 case CTF_TYPE_INTEGER
:
1205 return print_integer(text
, field
);
1206 case CTF_TYPE_FLOAT
:
1210 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
1211 return BT_COMPONENT_STATUS_ERROR
;
1213 if (text
->use_colors
) {
1214 fputs(COLOR_NUMBER_VALUE
, text
->out
);
1216 fprintf(text
->out
, "%g", v
);
1217 if (text
->use_colors
) {
1218 fputs(COLOR_RST
, text
->out
);
1220 return BT_COMPONENT_STATUS_OK
;
1223 return print_enum(text
, field
);
1224 case CTF_TYPE_STRING
:
1225 if (text
->use_colors
) {
1226 fputs(COLOR_STRING_VALUE
, text
->out
);
1228 // TODO: escape the string value
1229 fprintf(text
->out
, "\"%s\"",
1230 bt_ctf_field_string_get_value(field
));
1231 if (text
->use_colors
) {
1232 fputs(COLOR_RST
, text
->out
);
1234 return BT_COMPONENT_STATUS_OK
;
1235 case CTF_TYPE_STRUCT
:
1236 return print_struct(text
, field
, print_names
, filter_fields
,
1238 case CTF_TYPE_UNTAGGED_VARIANT
:
1239 case CTF_TYPE_VARIANT
:
1240 return print_variant(text
, field
, print_names
);
1241 case CTF_TYPE_ARRAY
:
1242 return print_array(text
, field
, print_names
);
1243 case CTF_TYPE_SEQUENCE
:
1244 return print_sequence(text
, field
, print_names
);
1246 fprintf(text
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1247 return BT_COMPONENT_STATUS_ERROR
;
1252 enum bt_component_status
print_stream_packet_context(struct text_component
*text
,
1253 struct bt_ctf_event
*event
)
1255 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1256 struct bt_ctf_packet
*packet
= NULL
;
1257 struct bt_ctf_field
*main_field
= NULL
;
1259 packet
= bt_ctf_event_get_packet(event
);
1261 ret
= BT_COMPONENT_STATUS_ERROR
;
1264 main_field
= bt_ctf_packet_get_context(packet
);
1268 if (!text
->start_line
) {
1269 fputs(", ", text
->out
);
1271 text
->start_line
= false;
1272 if (text
->options
.print_scope_field_names
) {
1273 print_name_equal(text
, "stream.packet.context");
1275 ret
= print_field(text
, main_field
,
1276 text
->options
.print_context_field_names
,
1277 stream_packet_context_quarks
,
1278 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1286 enum bt_component_status
print_event_header_raw(struct text_component
*text
,
1287 struct bt_ctf_event
*event
)
1289 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1290 struct bt_ctf_field
*main_field
= NULL
;
1292 main_field
= bt_ctf_event_get_header(event
);
1296 if (!text
->start_line
) {
1297 fputs(", ", text
->out
);
1299 text
->start_line
= false;
1300 if (text
->options
.print_scope_field_names
) {
1301 print_name_equal(text
, "stream.event.header");
1303 ret
= print_field(text
, main_field
,
1304 text
->options
.print_header_field_names
, NULL
, 0);
1311 enum bt_component_status
print_stream_event_context(struct text_component
*text
,
1312 struct bt_ctf_event
*event
)
1314 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1315 struct bt_ctf_field
*main_field
= NULL
;
1317 main_field
= bt_ctf_event_get_stream_event_context(event
);
1321 if (!text
->start_line
) {
1322 fputs(", ", text
->out
);
1324 text
->start_line
= false;
1325 if (text
->options
.print_scope_field_names
) {
1326 print_name_equal(text
, "stream.event.context");
1328 ret
= print_field(text
, main_field
,
1329 text
->options
.print_context_field_names
, NULL
, 0);
1336 enum bt_component_status
print_event_context(struct text_component
*text
,
1337 struct bt_ctf_event
*event
)
1339 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1340 struct bt_ctf_field
*main_field
= NULL
;
1342 main_field
= bt_ctf_event_get_event_context(event
);
1346 if (!text
->start_line
) {
1347 fputs(", ", text
->out
);
1349 text
->start_line
= false;
1350 if (text
->options
.print_scope_field_names
) {
1351 print_name_equal(text
, "event.context");
1353 ret
= print_field(text
, main_field
,
1354 text
->options
.print_context_field_names
, NULL
, 0);
1361 enum bt_component_status
print_event_payload(struct text_component
*text
,
1362 struct bt_ctf_event
*event
)
1364 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1365 struct bt_ctf_field
*main_field
= NULL
;
1367 main_field
= bt_ctf_event_get_payload_field(event
);
1371 if (!text
->start_line
) {
1372 fputs(", ", text
->out
);
1374 text
->start_line
= false;
1375 if (text
->options
.print_scope_field_names
) {
1376 print_name_equal(text
, "event.fields");
1378 ret
= print_field(text
, main_field
,
1379 text
->options
.print_payload_field_names
, NULL
, 0);
1386 enum bt_component_status
text_print_event(struct text_component
*text
,
1387 struct bt_ctf_event
*event
)
1389 enum bt_component_status ret
;
1391 text
->start_line
= true;
1392 ret
= print_event_header(text
, event
);
1393 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1397 ret
= print_stream_packet_context(text
, event
);
1398 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1402 if (text
->options
.verbose
) {
1403 ret
= print_event_header_raw(text
, event
);
1404 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1409 ret
= print_stream_event_context(text
, event
);
1410 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1414 ret
= print_event_context(text
, event
);
1415 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1419 ret
= print_event_payload(text
, event
);
1420 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1424 fputc('\n', text
->out
);