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
);
158 enum bt_component_status
print_integer(struct text_component
*text
,
159 struct bt_ctf_field
*field
)
161 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
162 struct bt_ctf_field_type
*field_type
= NULL
;
163 enum bt_ctf_integer_base base
;
164 enum bt_ctf_string_encoding encoding
;
171 field_type
= bt_ctf_field_get_type(field
);
173 ret
= BT_COMPONENT_STATUS_ERROR
;
176 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
177 if (signedness
< 0) {
178 ret
= BT_COMPONENT_STATUS_ERROR
;
182 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
183 ret
= BT_COMPONENT_STATUS_ERROR
;
187 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
188 ret
= BT_COMPONENT_STATUS_ERROR
;
193 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
195 case BT_CTF_STRING_ENCODING_UTF8
:
196 case BT_CTF_STRING_ENCODING_ASCII
:
197 g_string_append_c(text
->string
, (int) v
.u
);
199 case BT_CTF_STRING_ENCODING_NONE
:
200 case BT_CTF_STRING_ENCODING_UNKNOWN
:
203 ret
= BT_COMPONENT_STATUS_ERROR
;
207 base
= bt_ctf_field_type_integer_get_base(field_type
);
209 case BT_CTF_INTEGER_BASE_BINARY
:
213 len
= bt_ctf_field_type_integer_get_size(field_type
);
215 ret
= BT_COMPONENT_STATUS_ERROR
;
218 fprintf(text
->out
, "0b");
219 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
220 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
221 fprintf(text
->out
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
222 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
226 case BT_CTF_INTEGER_BASE_OCTAL
:
231 len
= bt_ctf_field_type_integer_get_size(field_type
);
233 ret
= BT_COMPONENT_STATUS_ERROR
;
240 /* Round length to the nearest 3-bit */
241 rounded_len
= (((len
- 1) / 3) + 1) * 3;
242 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
246 fprintf(text
->out
, "0%" PRIo64
, v
.u
);
249 case BT_CTF_INTEGER_BASE_DECIMAL
:
251 fprintf(text
->out
, "%" PRIu64
, v
.u
);
253 fprintf(text
->out
, "%" PRId64
, v
.s
);
256 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
260 len
= bt_ctf_field_type_integer_get_size(field_type
);
262 ret
= BT_COMPONENT_STATUS_ERROR
;
266 /* Round length to the nearest nibble */
267 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
269 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
272 fprintf(text
->out
, "0x%" PRIX64
, v
.u
);
276 ret
= BT_COMPONENT_STATUS_ERROR
;
285 enum bt_component_status
print_enum(struct text_component
*text
,
286 struct bt_ctf_field
*field
)
288 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
289 struct bt_ctf_field
*container_field
= NULL
;
290 const char *mapping_name
;
292 container_field
= bt_ctf_field_enumeration_get_container(field
);
293 if (!container_field
) {
294 ret
= BT_COMPONENT_STATUS_ERROR
;
297 mapping_name
= bt_ctf_field_enumeration_get_mapping_name(field
);
299 fprintf(text
->out
, "( \"%s\"", mapping_name
);
301 fprintf(text
->out
, "( <unknown>");
303 fprintf(text
->out
, " : container = ");
304 ret
= print_integer(text
, container_field
);
305 if (ret
!= BT_COMPONENT_STATUS_OK
) {
308 fprintf(text
->out
, " )");
310 bt_put(container_field
);
315 enum bt_component_status
print_struct_field(struct text_component
*text
,
316 struct bt_ctf_field
*_struct
,
317 struct bt_ctf_field_type
*struct_type
,
318 int i
, bool print_names
)
320 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
321 const char *field_name
;
322 struct bt_ctf_field
*field
= NULL
;
323 struct bt_ctf_field_type
*field_type
= NULL
;;
325 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
327 ret
= BT_COMPONENT_STATUS_ERROR
;
330 if (bt_ctf_field_type_structure_get_field(struct_type
,
331 &field_name
, &field_type
, i
) < 0) {
332 ret
= BT_COMPONENT_STATUS_ERROR
;
337 fprintf(text
->out
, ", ");
339 fprintf(text
->out
, " ");
342 fprintf(text
->out
, "%s = ", rem_(field_name
));
344 ret
= print_field(text
, field
, print_names
);
352 enum bt_component_status
print_struct(struct text_component
*text
,
353 struct bt_ctf_field
*_struct
, bool print_names
)
355 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
356 struct bt_ctf_field_type
*struct_type
= NULL
;
359 struct_type
= bt_ctf_field_get_type(_struct
);
361 ret
= BT_COMPONENT_STATUS_ERROR
;
364 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
366 ret
= BT_COMPONENT_STATUS_ERROR
;
369 fprintf(text
->out
, "{");
371 for (i
= 0; i
< nr_fields
; i
++) {
372 ret
= print_struct_field(text
, _struct
, struct_type
, i
,
374 if (ret
!= BT_COMPONENT_STATUS_OK
) {
379 fprintf(text
->out
, " }");
386 enum bt_component_status
print_array_field(struct text_component
*text
,
387 struct bt_ctf_field
*array
, uint64_t i
,
388 bool is_string
, bool print_names
)
390 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
391 struct bt_ctf_field
*field
= NULL
;
395 fprintf(text
->out
, ", ");
397 fprintf(text
->out
, " ");
400 field
= bt_ctf_field_array_get_field(array
, i
);
402 ret
= BT_COMPONENT_STATUS_ERROR
;
405 ret
= print_field(text
, field
, print_names
);
412 enum bt_component_status
print_array(struct text_component
*text
,
413 struct bt_ctf_field
*array
, bool print_names
)
415 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
416 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
417 enum bt_ctf_type_id type_id
;
420 bool is_string
= false;
422 array_type
= bt_ctf_field_get_type(array
);
424 ret
= BT_COMPONENT_STATUS_ERROR
;
427 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
429 ret
= BT_COMPONENT_STATUS_ERROR
;
432 len
= bt_ctf_field_type_array_get_length(array_type
);
434 ret
= BT_COMPONENT_STATUS_ERROR
;
437 type_id
= bt_ctf_field_type_get_type_id(field_type
);
438 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
439 enum bt_ctf_string_encoding encoding
;
441 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
442 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
443 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
444 int integer_len
, integer_alignment
;
446 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
447 if (integer_len
< 0) {
448 return BT_COMPONENT_STATUS_ERROR
;
450 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
451 if (integer_alignment
< 0) {
452 return BT_COMPONENT_STATUS_ERROR
;
454 if (integer_len
== CHAR_BIT
455 && integer_alignment
== CHAR_BIT
) {
462 g_string_assign(text
->string
, "");
464 fprintf(text
->out
, "[");
468 for (i
= 0; i
< len
; i
++) {
469 ret
= print_array_field(text
, array
, i
, is_string
, print_names
);
470 if (ret
!= BT_COMPONENT_STATUS_OK
) {
477 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
479 fprintf(text
->out
, " ]");
488 enum bt_component_status
print_sequence_field(struct text_component
*text
,
489 struct bt_ctf_field
*seq
, uint64_t i
,
490 bool is_string
, bool print_names
)
492 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
493 struct bt_ctf_field
*field
= NULL
;
497 fprintf(text
->out
, ", ");
499 fprintf(text
->out
, " ");
502 field
= bt_ctf_field_sequence_get_field(seq
, i
);
504 ret
= BT_COMPONENT_STATUS_ERROR
;
507 ret
= print_field(text
, field
, print_names
);
514 enum bt_component_status
print_sequence(struct text_component
*text
,
515 struct bt_ctf_field
*seq
, bool print_names
)
517 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
518 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
519 struct bt_ctf_field
*length_field
= NULL
;
520 enum bt_ctf_type_id type_id
;
523 bool is_string
= false;
525 seq_type
= bt_ctf_field_get_type(seq
);
527 ret
= BT_COMPONENT_STATUS_ERROR
;
530 length_field
= bt_ctf_field_sequence_get_length(seq
);
532 ret
= BT_COMPONENT_STATUS_ERROR
;
535 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
536 ret
= BT_COMPONENT_STATUS_ERROR
;
539 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
541 ret
= BT_COMPONENT_STATUS_ERROR
;
544 type_id
= bt_ctf_field_type_get_type_id(field_type
);
545 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
546 enum bt_ctf_string_encoding encoding
;
548 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
549 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
550 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
551 int integer_len
, integer_alignment
;
553 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
554 if (integer_len
< 0) {
555 ret
= BT_COMPONENT_STATUS_ERROR
;
558 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
559 if (integer_alignment
< 0) {
560 ret
= BT_COMPONENT_STATUS_ERROR
;
563 if (integer_len
== CHAR_BIT
564 && integer_alignment
== CHAR_BIT
) {
571 g_string_assign(text
->string
, "");
573 fprintf(text
->out
, "[");
577 for (i
= 0; i
< len
; i
++) {
578 ret
= print_sequence_field(text
, seq
, i
,
579 is_string
, print_names
);
580 if (ret
!= BT_COMPONENT_STATUS_OK
) {
587 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
589 fprintf(text
->out
, " ]");
592 bt_put(length_field
);
599 enum bt_component_status
print_variant(struct text_component
*text
,
600 struct bt_ctf_field
*variant
, bool print_names
)
602 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
603 struct bt_ctf_field
*field
= NULL
;
605 field
= bt_ctf_field_variant_get_current_field(variant
);
607 ret
= BT_COMPONENT_STATUS_ERROR
;
610 fprintf(text
->out
, "{ ");
613 struct bt_ctf_field
*tag_field
= NULL
;
614 const char *tag_choice
;
616 tag_field
= bt_ctf_field_variant_get_tag(variant
);
618 ret
= BT_COMPONENT_STATUS_ERROR
;
621 tag_choice
= bt_ctf_field_enumeration_get_mapping_name(tag_field
);
624 ret
= BT_COMPONENT_STATUS_ERROR
;
627 fprintf(text
->out
, "%s = ", rem_(tag_choice
));
630 ret
= print_field(text
, field
, print_names
);
631 if (ret
!= BT_COMPONENT_STATUS_OK
) {
635 fprintf(text
->out
, " }");
642 enum bt_component_status
print_field(struct text_component
*text
,
643 struct bt_ctf_field
*field
, bool print_names
)
645 enum bt_ctf_type_id type_id
;
647 type_id
= bt_ctf_field_get_type_id(field
);
649 case CTF_TYPE_INTEGER
:
650 return print_integer(text
, field
);
655 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
656 return BT_COMPONENT_STATUS_ERROR
;
658 fprintf(text
->out
, "%g", v
);
659 return BT_COMPONENT_STATUS_OK
;
662 return print_enum(text
, field
);
663 case CTF_TYPE_STRING
:
664 fprintf(text
->out
, "\"%s\"", bt_ctf_field_string_get_value(field
));
665 return BT_COMPONENT_STATUS_OK
;
666 case CTF_TYPE_STRUCT
:
667 return print_struct(text
, field
, print_names
);
668 case CTF_TYPE_UNTAGGED_VARIANT
:
669 case CTF_TYPE_VARIANT
:
670 return print_variant(text
, field
, print_names
);
672 return print_array(text
, field
, print_names
);
673 case CTF_TYPE_SEQUENCE
:
674 return print_sequence(text
, field
, print_names
);
676 fprintf(text
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
677 return BT_COMPONENT_STATUS_ERROR
;
682 enum bt_component_status
print_stream_packet_context(struct text_component
*text
,
683 struct bt_ctf_event
*event
)
685 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
686 struct bt_ctf_packet
*packet
= NULL
;
687 struct bt_ctf_field
*main_field
= NULL
;
689 packet
= bt_ctf_event_get_packet(event
);
691 ret
= BT_COMPONENT_STATUS_ERROR
;
694 main_field
= bt_ctf_packet_get_context(packet
);
696 ret
= BT_COMPONENT_STATUS_ERROR
;
699 if (!text
->start_line
) {
700 fputs(", ", text
->out
);
702 text
->start_line
= false;
703 if (text
->options
.print_scope_field_names
) {
704 fputs("stream.packet.context = ", text
->out
);
706 ret
= print_field(text
, main_field
,
707 text
->options
.print_context_field_names
);
715 enum bt_component_status
print_event_header_raw(struct text_component
*text
,
716 struct bt_ctf_event
*event
)
718 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
719 struct bt_ctf_field
*main_field
= NULL
;
721 main_field
= bt_ctf_event_get_header(event
);
723 ret
= BT_COMPONENT_STATUS_ERROR
;
726 if (!text
->start_line
) {
727 fputs(", ", text
->out
);
729 text
->start_line
= false;
730 if (text
->options
.print_scope_field_names
) {
731 fputs("stream.event.header = ", text
->out
);
733 ret
= print_field(text
, main_field
,
734 text
->options
.print_header_field_names
);
741 enum bt_component_status
print_stream_event_context(struct text_component
*text
,
742 struct bt_ctf_event
*event
)
744 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
745 struct bt_ctf_field
*main_field
= NULL
;
747 main_field
= bt_ctf_event_get_stream_event_context(event
);
749 ret
= BT_COMPONENT_STATUS_ERROR
;
752 if (!text
->start_line
) {
753 fputs(", ", text
->out
);
755 text
->start_line
= false;
756 if (text
->options
.print_scope_field_names
) {
757 fputs("stream.event.context = ", text
->out
);
759 ret
= print_field(text
, main_field
,
760 text
->options
.print_context_field_names
);
767 enum bt_component_status
print_event_context(struct text_component
*text
,
768 struct bt_ctf_event
*event
)
770 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
771 struct bt_ctf_field
*main_field
= NULL
;
773 main_field
= bt_ctf_event_get_event_context(event
);
775 ret
= BT_COMPONENT_STATUS_ERROR
;
778 if (!text
->start_line
) {
779 fputs(", ", text
->out
);
781 text
->start_line
= false;
782 if (text
->options
.print_scope_field_names
) {
783 fputs("event.context = ", text
->out
);
785 ret
= print_field(text
, main_field
,
786 text
->options
.print_context_field_names
);
793 enum bt_component_status
print_event_payload(struct text_component
*text
,
794 struct bt_ctf_event
*event
)
796 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
797 struct bt_ctf_field
*main_field
= NULL
;
799 main_field
= bt_ctf_event_get_payload_field(event
);
801 ret
= BT_COMPONENT_STATUS_ERROR
;
804 if (!text
->start_line
) {
805 fputs(", ", text
->out
);
807 text
->start_line
= false;
808 if (text
->options
.print_scope_field_names
) {
809 fputs("event.fields = ", text
->out
);
811 ret
= print_field(text
, main_field
,
812 text
->options
.print_payload_field_names
);
819 enum bt_component_status
text_print_event(struct text_component
*text
,
820 struct bt_ctf_event
*event
)
822 enum bt_component_status ret
;
824 text
->start_line
= true;
825 ret
= print_event_header(text
, event
);
826 if (ret
!= BT_COMPONENT_STATUS_OK
) {
830 ret
= print_stream_packet_context(text
, event
);
831 if (ret
!= BT_COMPONENT_STATUS_OK
) {
835 ret
= print_event_header_raw(text
, event
);
836 if (ret
!= BT_COMPONENT_STATUS_OK
) {
840 ret
= print_stream_event_context(text
, event
);
841 if (ret
!= BT_COMPONENT_STATUS_OK
) {
845 ret
= print_event_context(text
, event
);
846 if (ret
!= BT_COMPONENT_STATUS_OK
) {
850 ret
= print_event_payload(text
, event
);
851 if (ret
!= BT_COMPONENT_STATUS_OK
) {
855 fputc('\n', text
->out
);