4 * Babeltrace CTF Text Output Plugin Event Printing
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <babeltrace/ctf-ir/event.h>
30 #include <babeltrace/ctf-ir/event-class.h>
31 #include <babeltrace/ctf-ir/packet.h>
32 #include <babeltrace/ctf-ir/stream.h>
33 #include <babeltrace/ctf-ir/stream-class.h>
34 #include <babeltrace/ctf-ir/clock.h>
35 #include <babeltrace/ctf-ir/field-types.h>
36 #include <babeltrace/ctf-ir/fields.h>
37 #include <babeltrace/bitfield.h>
42 const char *rem_(const char *str
)
51 int64_t real_timestamp
; /* Relative to UNIX epoch. */
52 uint64_t clock_value
; /* In cycles. */
56 enum bt_component_status
print_field(struct text_component
*text
,
57 struct bt_ctf_field
*field
, bool print_names
);
60 void print_timestamp_cycles(struct text_component
*text
,
61 struct bt_ctf_clock
*clock
,
62 struct bt_ctf_event
*event
)
64 fputs("00000000000000000000", text
->out
);
68 void print_timestamp_wall(struct text_component
*text
,
69 struct bt_ctf_clock
*clock
,
70 struct bt_ctf_event
*event
)
72 fputs("??:??:??.?????????", text
->out
);
76 enum bt_component_status
get_event_timestamp(struct bt_ctf_event
*event
)
79 uint64_t value, frequency;
80 int64_t offset_s, offset;
82 return BT_COMPONENT_STATUS_OK
;
86 enum bt_component_status
print_event_timestamp(struct text_component
*text
,
87 struct bt_ctf_event
*event
)
89 bool print_names
= text
->options
.print_header_field_names
;
90 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
91 struct bt_ctf_stream
*stream
= NULL
;
92 struct bt_ctf_clock
*clock
= NULL
;
93 FILE *out
= text
->out
;
94 FILE *err
= text
->err
;
95 uint64_t real_timestamp
;
97 stream
= bt_ctf_event_get_stream(event
);
99 ret
= BT_COMPONENT_STATUS_ERROR
;
103 clock
= bt_ctf_event_get_clock(event
);
105 /* Stream has no timestamp. */
106 //puts("no_timestamp!");
110 fputs(print_names
? "timestamp = " : "[", out
);
111 if (text
->options
.print_timestamp_cycles
) {
112 print_timestamp_cycles(text
, clock
, event
);
114 print_timestamp_wall(text
, clock
, event
);
117 fputs(print_names
? ", " : "] ", out
);
118 if (!text
->options
.print_delta_field
) {
128 enum bt_component_status
print_event_header(struct text_component
*text
,
129 struct bt_ctf_event
*event
)
131 bool print_names
= text
->options
.print_header_field_names
;
132 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
133 struct bt_ctf_event_class
*event_class
= NULL
;
135 event_class
= bt_ctf_event_get_class(event
);
137 ret
= BT_COMPONENT_STATUS_ERROR
;
140 if (!text
->start_line
) {
141 fputs(", ", text
->out
);
143 text
->start_line
= false;
144 ret
= print_event_timestamp(text
, event
);
145 if (ret
!= BT_COMPONENT_STATUS_OK
) {
149 fputs("name = ", text
->out
);
151 fputs(bt_ctf_event_class_get_name(event_class
), text
->out
);
159 enum bt_component_status
print_integer(struct text_component
*text
,
160 struct bt_ctf_field
*field
)
162 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
163 struct bt_ctf_field_type
*field_type
= NULL
;
164 enum bt_ctf_integer_base base
;
165 enum bt_ctf_string_encoding encoding
;
172 field_type
= bt_ctf_field_get_type(field
);
174 ret
= BT_COMPONENT_STATUS_ERROR
;
177 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
178 if (signedness
< 0) {
179 ret
= BT_COMPONENT_STATUS_ERROR
;
183 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
184 ret
= BT_COMPONENT_STATUS_ERROR
;
188 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
189 ret
= BT_COMPONENT_STATUS_ERROR
;
194 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
196 case BT_CTF_STRING_ENCODING_UTF8
:
197 case BT_CTF_STRING_ENCODING_ASCII
:
198 g_string_append_c(text
->string
, (int) v
.u
);
200 case BT_CTF_STRING_ENCODING_NONE
:
201 case BT_CTF_STRING_ENCODING_UNKNOWN
:
204 ret
= BT_COMPONENT_STATUS_ERROR
;
208 base
= bt_ctf_field_type_integer_get_base(field_type
);
210 case BT_CTF_INTEGER_BASE_BINARY
:
214 len
= bt_ctf_field_type_integer_get_size(field_type
);
216 ret
= BT_COMPONENT_STATUS_ERROR
;
219 fprintf(text
->out
, "0b");
220 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
221 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
222 fprintf(text
->out
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
223 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
227 case BT_CTF_INTEGER_BASE_OCTAL
:
232 len
= bt_ctf_field_type_integer_get_size(field_type
);
234 ret
= BT_COMPONENT_STATUS_ERROR
;
241 /* Round length to the nearest 3-bit */
242 rounded_len
= (((len
- 1) / 3) + 1) * 3;
243 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
247 fprintf(text
->out
, "0%" PRIo64
, v
.u
);
250 case BT_CTF_INTEGER_BASE_DECIMAL
:
252 fprintf(text
->out
, "%" PRIu64
, v
.u
);
254 fprintf(text
->out
, "%" PRId64
, v
.s
);
257 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
261 len
= bt_ctf_field_type_integer_get_size(field_type
);
263 ret
= BT_COMPONENT_STATUS_ERROR
;
267 /* Round length to the nearest nibble */
268 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
270 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
273 fprintf(text
->out
, "0x%" PRIX64
, v
.u
);
277 ret
= BT_COMPONENT_STATUS_ERROR
;
286 enum bt_component_status
print_enum(struct text_component
*text
,
287 struct bt_ctf_field
*field
)
289 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
290 struct bt_ctf_field
*container_field
= NULL
;
291 const char *mapping_name
;
293 container_field
= bt_ctf_field_enumeration_get_container(field
);
294 if (!container_field
) {
295 ret
= BT_COMPONENT_STATUS_ERROR
;
298 mapping_name
= bt_ctf_field_enumeration_get_mapping_name(field
);
300 fprintf(text
->out
, "( \"%s\"", mapping_name
);
302 fprintf(text
->out
, "( <unknown>");
304 fprintf(text
->out
, " : container = ");
305 ret
= print_integer(text
, container_field
);
306 if (ret
!= BT_COMPONENT_STATUS_OK
) {
309 fprintf(text
->out
, " )");
311 bt_put(container_field
);
316 enum bt_component_status
print_struct_field(struct text_component
*text
,
317 struct bt_ctf_field
*_struct
,
318 struct bt_ctf_field_type
*struct_type
,
319 int i
, bool print_names
)
321 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
322 const char *field_name
;
323 struct bt_ctf_field
*field
= NULL
;
324 struct bt_ctf_field_type
*field_type
= NULL
;;
326 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
328 ret
= BT_COMPONENT_STATUS_ERROR
;
331 if (bt_ctf_field_type_structure_get_field(struct_type
,
332 &field_name
, &field_type
, i
) < 0) {
333 ret
= BT_COMPONENT_STATUS_ERROR
;
338 fprintf(text
->out
, ", ");
340 fprintf(text
->out
, " ");
343 fprintf(text
->out
, "%s = ", rem_(field_name
));
345 ret
= print_field(text
, field
, print_names
);
353 enum bt_component_status
print_struct(struct text_component
*text
,
354 struct bt_ctf_field
*_struct
, bool print_names
)
356 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
357 struct bt_ctf_field_type
*struct_type
= NULL
;
360 struct_type
= bt_ctf_field_get_type(_struct
);
362 ret
= BT_COMPONENT_STATUS_ERROR
;
365 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
367 ret
= BT_COMPONENT_STATUS_ERROR
;
370 fprintf(text
->out
, "{");
372 for (i
= 0; i
< nr_fields
; i
++) {
373 ret
= print_struct_field(text
, _struct
, struct_type
, i
,
375 if (ret
!= BT_COMPONENT_STATUS_OK
) {
380 fprintf(text
->out
, " }");
387 enum bt_component_status
print_array_field(struct text_component
*text
,
388 struct bt_ctf_field
*array
, uint64_t i
,
389 bool is_string
, bool print_names
)
391 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
392 struct bt_ctf_field
*field
= NULL
;
396 fprintf(text
->out
, ", ");
398 fprintf(text
->out
, " ");
401 field
= bt_ctf_field_array_get_field(array
, i
);
403 ret
= BT_COMPONENT_STATUS_ERROR
;
406 ret
= print_field(text
, field
, print_names
);
413 enum bt_component_status
print_array(struct text_component
*text
,
414 struct bt_ctf_field
*array
, bool print_names
)
416 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
417 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
418 enum bt_ctf_type_id type_id
;
421 bool is_string
= false;
423 array_type
= bt_ctf_field_get_type(array
);
425 ret
= BT_COMPONENT_STATUS_ERROR
;
428 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
430 ret
= BT_COMPONENT_STATUS_ERROR
;
433 len
= bt_ctf_field_type_array_get_length(array_type
);
435 ret
= BT_COMPONENT_STATUS_ERROR
;
438 type_id
= bt_ctf_field_type_get_type_id(field_type
);
439 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
440 enum bt_ctf_string_encoding encoding
;
442 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
443 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
444 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
445 int integer_len
, integer_alignment
;
447 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
448 if (integer_len
< 0) {
449 return BT_COMPONENT_STATUS_ERROR
;
451 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
452 if (integer_alignment
< 0) {
453 return BT_COMPONENT_STATUS_ERROR
;
455 if (integer_len
== CHAR_BIT
456 && integer_alignment
== CHAR_BIT
) {
463 g_string_assign(text
->string
, "");
465 fprintf(text
->out
, "[");
469 for (i
= 0; i
< len
; i
++) {
470 ret
= print_array_field(text
, array
, i
, is_string
, print_names
);
471 if (ret
!= BT_COMPONENT_STATUS_OK
) {
478 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
480 fprintf(text
->out
, " ]");
489 enum bt_component_status
print_sequence_field(struct text_component
*text
,
490 struct bt_ctf_field
*seq
, uint64_t i
,
491 bool is_string
, bool print_names
)
493 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
494 struct bt_ctf_field
*field
= NULL
;
498 fprintf(text
->out
, ", ");
500 fprintf(text
->out
, " ");
503 field
= bt_ctf_field_sequence_get_field(seq
, i
);
505 ret
= BT_COMPONENT_STATUS_ERROR
;
508 ret
= print_field(text
, field
, print_names
);
515 enum bt_component_status
print_sequence(struct text_component
*text
,
516 struct bt_ctf_field
*seq
, bool print_names
)
518 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
519 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
520 struct bt_ctf_field
*length_field
= NULL
;
521 enum bt_ctf_type_id type_id
;
524 bool is_string
= false;
526 seq_type
= bt_ctf_field_get_type(seq
);
528 ret
= BT_COMPONENT_STATUS_ERROR
;
531 length_field
= bt_ctf_field_sequence_get_length(seq
);
533 ret
= BT_COMPONENT_STATUS_ERROR
;
536 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
537 ret
= BT_COMPONENT_STATUS_ERROR
;
540 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
542 ret
= BT_COMPONENT_STATUS_ERROR
;
545 type_id
= bt_ctf_field_type_get_type_id(field_type
);
546 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
547 enum bt_ctf_string_encoding encoding
;
549 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
550 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
551 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
552 int integer_len
, integer_alignment
;
554 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
555 if (integer_len
< 0) {
556 ret
= BT_COMPONENT_STATUS_ERROR
;
559 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
560 if (integer_alignment
< 0) {
561 ret
= BT_COMPONENT_STATUS_ERROR
;
564 if (integer_len
== CHAR_BIT
565 && integer_alignment
== CHAR_BIT
) {
572 g_string_assign(text
->string
, "");
574 fprintf(text
->out
, "[");
578 for (i
= 0; i
< len
; i
++) {
579 ret
= print_sequence_field(text
, seq
, i
,
580 is_string
, print_names
);
581 if (ret
!= BT_COMPONENT_STATUS_OK
) {
588 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
590 fprintf(text
->out
, " ]");
593 bt_put(length_field
);
600 enum bt_component_status
print_variant(struct text_component
*text
,
601 struct bt_ctf_field
*variant
, bool print_names
)
603 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
604 struct bt_ctf_field
*field
= NULL
;
606 field
= bt_ctf_field_variant_get_current_field(variant
);
608 ret
= BT_COMPONENT_STATUS_ERROR
;
611 fprintf(text
->out
, "{ ");
614 struct bt_ctf_field
*tag_field
= NULL
;
615 const char *tag_choice
;
617 tag_field
= bt_ctf_field_variant_get_tag(variant
);
619 ret
= BT_COMPONENT_STATUS_ERROR
;
622 tag_choice
= bt_ctf_field_enumeration_get_mapping_name(tag_field
);
625 ret
= BT_COMPONENT_STATUS_ERROR
;
628 fprintf(text
->out
, "%s = ", rem_(tag_choice
));
631 ret
= print_field(text
, field
, print_names
);
632 if (ret
!= BT_COMPONENT_STATUS_OK
) {
636 fprintf(text
->out
, " }");
643 enum bt_component_status
print_field(struct text_component
*text
,
644 struct bt_ctf_field
*field
, bool print_names
)
646 enum bt_ctf_type_id type_id
;
648 type_id
= bt_ctf_field_get_type_id(field
);
650 case CTF_TYPE_INTEGER
:
651 return print_integer(text
, field
);
656 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
657 return BT_COMPONENT_STATUS_ERROR
;
659 fprintf(text
->out
, "%g", v
);
660 return BT_COMPONENT_STATUS_OK
;
663 return print_enum(text
, field
);
664 case CTF_TYPE_STRING
:
665 fprintf(text
->out
, "\"%s\"", bt_ctf_field_string_get_value(field
));
666 return BT_COMPONENT_STATUS_OK
;
667 case CTF_TYPE_STRUCT
:
668 return print_struct(text
, field
, print_names
);
669 case CTF_TYPE_UNTAGGED_VARIANT
:
670 case CTF_TYPE_VARIANT
:
671 return print_variant(text
, field
, print_names
);
673 return print_array(text
, field
, print_names
);
674 case CTF_TYPE_SEQUENCE
:
675 return print_sequence(text
, field
, print_names
);
677 fprintf(text
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
678 return BT_COMPONENT_STATUS_ERROR
;
683 enum bt_component_status
print_stream_packet_context(struct text_component
*text
,
684 struct bt_ctf_event
*event
)
686 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
687 struct bt_ctf_packet
*packet
= NULL
;
688 struct bt_ctf_field
*main_field
= NULL
;
690 packet
= bt_ctf_event_get_packet(event
);
692 ret
= BT_COMPONENT_STATUS_ERROR
;
695 main_field
= bt_ctf_packet_get_context(packet
);
697 ret
= BT_COMPONENT_STATUS_ERROR
;
700 if (!text
->start_line
) {
701 fputs(", ", text
->out
);
703 text
->start_line
= false;
704 if (text
->options
.print_scope_field_names
) {
705 fputs("stream.packet.context = ", text
->out
);
707 ret
= print_field(text
, main_field
,
708 text
->options
.print_context_field_names
);
716 enum bt_component_status
print_event_header_raw(struct text_component
*text
,
717 struct bt_ctf_event
*event
)
719 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
720 struct bt_ctf_field
*main_field
= NULL
;
722 main_field
= bt_ctf_event_get_header(event
);
724 ret
= BT_COMPONENT_STATUS_ERROR
;
727 if (!text
->start_line
) {
728 fputs(", ", text
->out
);
730 text
->start_line
= false;
731 if (text
->options
.print_scope_field_names
) {
732 fputs("stream.event.header = ", text
->out
);
734 ret
= print_field(text
, main_field
,
735 text
->options
.print_header_field_names
);
742 enum bt_component_status
print_stream_event_context(struct text_component
*text
,
743 struct bt_ctf_event
*event
)
745 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
746 struct bt_ctf_field
*main_field
= NULL
;
748 main_field
= bt_ctf_event_get_stream_event_context(event
);
750 ret
= BT_COMPONENT_STATUS_ERROR
;
753 if (!text
->start_line
) {
754 fputs(", ", text
->out
);
756 text
->start_line
= false;
757 if (text
->options
.print_scope_field_names
) {
758 fputs("stream.event.context = ", text
->out
);
760 ret
= print_field(text
, main_field
,
761 text
->options
.print_context_field_names
);
768 enum bt_component_status
print_event_context(struct text_component
*text
,
769 struct bt_ctf_event
*event
)
771 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
772 struct bt_ctf_field
*main_field
= NULL
;
774 main_field
= bt_ctf_event_get_event_context(event
);
776 ret
= BT_COMPONENT_STATUS_ERROR
;
779 if (!text
->start_line
) {
780 fputs(", ", text
->out
);
782 text
->start_line
= false;
783 if (text
->options
.print_scope_field_names
) {
784 fputs("event.context = ", text
->out
);
786 ret
= print_field(text
, main_field
,
787 text
->options
.print_context_field_names
);
794 enum bt_component_status
print_event_payload(struct text_component
*text
,
795 struct bt_ctf_event
*event
)
797 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
798 struct bt_ctf_field
*main_field
= NULL
;
800 main_field
= bt_ctf_event_get_payload_field(event
);
802 ret
= BT_COMPONENT_STATUS_ERROR
;
805 if (!text
->start_line
) {
806 fputs(", ", text
->out
);
808 text
->start_line
= false;
809 if (text
->options
.print_scope_field_names
) {
810 fputs("event.fields = ", text
->out
);
812 ret
= print_field(text
, main_field
,
813 text
->options
.print_payload_field_names
);
820 enum bt_component_status
text_print_event(struct text_component
*text
,
821 struct bt_ctf_event
*event
)
823 enum bt_component_status ret
;
825 text
->start_line
= true;
826 ret
= print_event_header(text
, event
);
827 if (ret
!= BT_COMPONENT_STATUS_OK
) {
831 ret
= print_stream_packet_context(text
, event
);
832 if (ret
!= BT_COMPONENT_STATUS_OK
) {
836 ret
= print_event_header_raw(text
, event
);
837 if (ret
!= BT_COMPONENT_STATUS_OK
) {
841 ret
= print_stream_event_context(text
, event
);
842 if (ret
!= BT_COMPONENT_STATUS_OK
) {
846 ret
= print_event_context(text
, event
);
847 if (ret
!= BT_COMPONENT_STATUS_OK
) {
851 ret
= print_event_payload(text
, event
);
852 if (ret
!= BT_COMPONENT_STATUS_OK
) {
856 fputc('\n', text
->out
);