Print other fields
[babeltrace.git] / plugins / text / print.c
1 /*
2 * print.c
3 *
4 * Babeltrace CTF Text Output Plugin Event Printing
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
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
26 * SOFTWARE.
27 */
28
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/ctf-ir/trace.h>
38 #include <babeltrace/bitfield.h>
39 #include <inttypes.h>
40 #include "text.h"
41
42 #define NSEC_PER_SEC 1000000000LL
43
44 static inline
45 const char *rem_(const char *str)
46 {
47 if (str[0] == '_')
48 return &str[1];
49 else
50 return str;
51 }
52
53 struct timestamp {
54 int64_t real_timestamp; /* Relative to UNIX epoch. */
55 uint64_t clock_value; /* In cycles. */
56 };
57
58 static
59 enum bt_component_status print_field(struct text_component *text,
60 struct bt_ctf_field *field, bool print_names);
61
62 static
63 void print_timestamp_cycles(struct text_component *text,
64 struct bt_ctf_clock *clock,
65 struct bt_ctf_event *event)
66 {
67 int ret;
68 struct bt_ctf_clock_value *clock_value;
69 uint64_t cycles;
70
71 clock_value = bt_ctf_event_get_clock_value(event, clock);
72 if (!clock_value) {
73 fputs("????????????????????", text->out);
74 return;
75 }
76
77 ret = bt_ctf_clock_value_get_value(clock_value, &cycles);
78 bt_put(clock_value);
79 if (ret) {
80 fprintf(text->out, "Error");
81 return;
82 }
83 fprintf(text->out, "%020" PRIu64, cycles);
84 }
85
86 static
87 void print_timestamp_wall(struct text_component *text,
88 struct bt_ctf_clock *clock,
89 struct bt_ctf_event *event)
90 {
91 int ret;
92 struct bt_ctf_clock_value *clock_value;
93 int64_t ts_nsec = 0; /* add configurable offset */
94 int64_t ts_sec = 0; /* add configurable offset */
95 uint64_t ts_sec_abs, ts_nsec_abs;
96 bool is_negative;
97
98 clock_value = bt_ctf_event_get_clock_value(event, clock);
99 if (!clock_value) {
100 fputs("??:??:??.?????????", text->out);
101 return;
102 }
103
104 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
105 bt_put(clock_value);
106 if (ret) {
107 fprintf(text->out, "Error");
108 return;
109 }
110
111 ts_sec += ts_nsec / NSEC_PER_SEC;
112 ts_nsec = ts_nsec % NSEC_PER_SEC;
113 if (ts_sec >= 0 && ts_nsec >= 0) {
114 is_negative = false;
115 ts_sec_abs = ts_sec;
116 ts_nsec_abs = ts_nsec;
117 } else if (ts_sec > 0 && ts_nsec < 0) {
118 is_negative = false;
119 ts_sec_abs = ts_sec - 1;
120 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
121 } else if (ts_sec == 0 && ts_nsec < 0) {
122 is_negative = true;
123 ts_sec_abs = ts_sec;
124 ts_nsec_abs = -ts_nsec;
125 } else if (ts_sec < 0 && ts_nsec > 0) {
126 is_negative = true;
127 ts_sec_abs = -(ts_sec + 1);
128 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
129 } else if (ts_sec < 0 && ts_nsec == 0) {
130 is_negative = true;
131 ts_sec_abs = -ts_sec;
132 ts_nsec_abs = ts_nsec;
133 } else { /* (ts_sec < 0 && ts_nsec < 0) */
134 is_negative = true;
135 ts_sec_abs = -ts_sec;
136 ts_nsec_abs = -ts_nsec;
137 }
138
139 if (/*!opt_clock_seconds*/true) {
140 struct tm tm;
141 time_t time_s = (time_t) ts_sec_abs;
142
143 if (is_negative) {
144 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
145 goto seconds;
146 }
147
148 if (/*!opt_clock_gmt*/true) {
149 struct tm *res;
150
151 res = localtime_r(&time_s, &tm);
152 if (!res) {
153 fprintf(stderr, "[warning] Unable to get localtime.\n");
154 goto seconds;
155 }
156 } else {
157 struct tm *res;
158
159 res = gmtime_r(&time_s, &tm);
160 if (!res) {
161 fprintf(stderr, "[warning] Unable to get gmtime.\n");
162 goto seconds;
163 }
164 }
165 if (/*opt_clock_date*/false) {
166 char timestr[26];
167 size_t res;
168
169 /* Print date and time */
170 res = strftime(timestr, sizeof(timestr),
171 "%F ", &tm);
172 if (!res) {
173 fprintf(stderr, "[warning] Unable to print ascii time.\n");
174 goto seconds;
175 }
176 fprintf(text->out, "%s", timestr);
177 }
178 /* Print time in HH:MM:SS.ns */
179 fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64,
180 tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs);
181 goto end;
182 }
183 seconds:
184 fprintf(text->out, "%s%" PRId64 ".%09" PRIu64,
185 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
186 end:
187 return;
188 }
189
190 static
191 enum bt_component_status print_event_timestamp(struct text_component *text,
192 struct bt_ctf_event *event, bool *start_line)
193 {
194 bool print_names = text->options.print_header_field_names;
195 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
196 struct bt_ctf_stream *stream = NULL;
197 struct bt_ctf_stream_class *stream_class = NULL;
198 struct bt_ctf_trace *trace = NULL;
199 struct bt_ctf_clock *clock = NULL;
200 FILE *out = text->out;
201 FILE *err = text->err;
202 uint64_t real_timestamp;
203
204 stream = bt_ctf_event_get_stream(event);
205 if (!stream) {
206 ret = BT_COMPONENT_STATUS_ERROR;
207 goto end;
208 }
209
210 /* FIXME - error checking */
211 stream_class = bt_ctf_stream_get_class(stream);
212 trace = bt_ctf_stream_class_get_trace(stream_class);
213 clock = bt_ctf_trace_get_clock(trace, 0);
214
215 fputs(print_names ? "timestamp = " : "[", out);
216 if (text->options.print_timestamp_cycles) {
217 print_timestamp_cycles(text, clock, event);
218 } else {
219 print_timestamp_wall(text, clock, event);
220 }
221
222 if (!print_names)
223 fputs("] ", out);
224 *start_line = !print_names;
225
226 if (!text->options.print_delta_field) {
227 goto end;
228 }
229 end:
230 bt_put(stream);
231 bt_put(clock);
232 bt_put(stream_class);
233 bt_put(trace);
234 return ret;
235 }
236
237 static
238 enum bt_component_status print_event_header(struct text_component *text,
239 struct bt_ctf_event *event)
240 {
241 bool print_names = text->options.print_header_field_names;
242 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
243 struct bt_ctf_event_class *event_class = NULL;
244 struct bt_ctf_stream_class *stream_class = NULL;
245 struct bt_ctf_trace *trace_class = NULL;
246
247 event_class = bt_ctf_event_get_class(event);
248 if (!event_class) {
249 ret = BT_COMPONENT_STATUS_ERROR;
250 goto end;
251 }
252 stream_class = bt_ctf_event_class_get_stream_class(event_class);
253 if (!stream_class) {
254 ret = BT_COMPONENT_STATUS_ERROR;
255 goto end;
256 }
257 trace_class = bt_ctf_stream_class_get_trace(stream_class);
258 if (!trace_class) {
259 ret = BT_COMPONENT_STATUS_ERROR;
260 goto end;
261 }
262 if (!text->start_line) {
263 fputs(", ", text->out);
264 }
265 text->start_line = false;
266 ret = print_event_timestamp(text, event, &text->start_line);
267 if (ret != BT_COMPONENT_STATUS_OK) {
268 goto end;
269 }
270 if (text->options.print_trace_field) {
271 const char *name;
272
273 name = bt_ctf_trace_get_name(trace_class);
274 if (name) {
275 if (!text->start_line) {
276 fputs(", ", text->out);
277 }
278 text->start_line = false;
279 if (print_names) {
280 fputs("trace = ", text->out);
281 }
282 fprintf(text->out, "%s", name);
283 }
284 }
285 if (text->options.print_trace_hostname_field) {
286 struct bt_value *hostname_str;
287
288 hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
289 "hostname");
290 if (hostname_str) {
291 const char *str;
292
293 if (!text->start_line) {
294 fputs(", ", text->out);
295 }
296 text->start_line = false;
297 if (print_names) {
298 fputs("trace:hostname = ", text->out);
299 }
300 if (bt_value_string_get(hostname_str, &str)
301 == BT_VALUE_STATUS_OK) {
302 fprintf(text->out, "%s", str);
303 }
304 bt_put(hostname_str);
305 }
306 }
307 if (text->options.print_trace_domain_field) {
308 struct bt_value *domain_str;
309
310 domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
311 "domain");
312 if (domain_str) {
313 const char *str;
314
315 if (!text->start_line) {
316 fputs(", ", text->out);
317 }
318 text->start_line = false;
319 if (print_names) {
320 fputs("trace:domain = ", text->out);
321 }
322 if (bt_value_string_get(domain_str, &str)
323 == BT_VALUE_STATUS_OK) {
324 fprintf(text->out, "%s", str);
325 }
326 bt_put(domain_str);
327 }
328 }
329 if (text->options.print_trace_procname_field) {
330 struct bt_value *procname_str;
331
332 procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
333 "procname");
334 if (procname_str) {
335 const char *str;
336
337 if (!text->start_line) {
338 fputs(", ", text->out);
339 }
340 text->start_line = false;
341 if (print_names) {
342 fputs("trace:procname = ", text->out);
343 }
344 if (bt_value_string_get(procname_str, &str)
345 == BT_VALUE_STATUS_OK) {
346 fprintf(text->out, "%s", str);
347 }
348 bt_put(procname_str);
349 }
350 }
351 if (text->options.print_trace_vpid_field) {
352 struct bt_value *vpid_value;
353
354 vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
355 "vpid");
356 if (vpid_value) {
357 int64_t value;
358
359 if (!text->start_line) {
360 fputs(", ", text->out);
361 }
362 text->start_line = false;
363 if (print_names) {
364 fputs("trace:vpid = ", text->out);
365 }
366 if (bt_value_integer_get(vpid_value, &value)
367 == BT_VALUE_STATUS_OK) {
368 fprintf(text->out, "(%" PRId64 ")", value);
369 }
370 bt_put(vpid_value);
371 }
372 }
373 if (text->options.print_loglevel_field) {
374 struct bt_value *loglevel_str, *loglevel_value;
375
376 loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
377 "loglevel_string");
378 loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class,
379 "loglevel");
380 if (loglevel_str || loglevel_value) {
381 bool has_str = false;
382
383 if (!text->start_line) {
384 fputs(", ", text->out);
385 }
386 text->start_line = false;
387 if (print_names) {
388 fputs("loglevel = ", text->out);
389 }
390 if (loglevel_str) {
391 const char *str;
392
393 if (bt_value_string_get(loglevel_str, &str)
394 == BT_VALUE_STATUS_OK) {
395 fprintf(text->out, "%s", str);
396 has_str = true;
397 }
398 }
399 if (loglevel_value) {
400 int64_t value;
401
402 if (bt_value_integer_get(loglevel_value, &value)
403 == BT_VALUE_STATUS_OK) {
404 fprintf(text->out, "%s(%" PRId64 ")",
405 has_str ? " " : "", value);
406 }
407 }
408 bt_put(loglevel_str);
409 bt_put(loglevel_value);
410 }
411 }
412 if (text->options.print_emf_field) {
413 struct bt_value *uri_str;
414
415 uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
416 "model.emf.uri");
417 if (uri_str) {
418 if (!text->start_line) {
419 fputs(", ", text->out);
420 }
421 text->start_line = false;
422 if (print_names) {
423 fputs("model.emf.uri = ", text->out);
424 }
425 if (uri_str) {
426 const char *str;
427
428 if (bt_value_string_get(uri_str, &str)
429 == BT_VALUE_STATUS_OK) {
430 fprintf(text->out, "%s", str);
431 }
432 }
433 bt_put(uri_str);
434 }
435 }
436 if (text->options.print_callsite_field) {
437 if (!text->start_line) {
438 fputs(", ", text->out);
439 }
440 text->start_line = false;
441 if (print_names) {
442 fputs("callsite = ", text->out);
443 }
444 /* TODO */
445 }
446 if (!text->start_line) {
447 fputs(", ", text->out);
448 }
449 text->start_line = false;
450 if (print_names) {
451 fputs("name = ", text->out);
452 }
453 fputs(bt_ctf_event_class_get_name(event_class), text->out);
454 end:
455 bt_put(trace_class);
456 bt_put(stream_class);
457 bt_put(event_class);
458 return ret;
459 }
460
461 static
462 enum bt_component_status print_integer(struct text_component *text,
463 struct bt_ctf_field *field)
464 {
465 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
466 struct bt_ctf_field_type *field_type = NULL;
467 enum bt_ctf_integer_base base;
468 enum bt_ctf_string_encoding encoding;
469 int signedness;
470 union {
471 uint64_t u;
472 int64_t s;
473 } v;
474
475 field_type = bt_ctf_field_get_type(field);
476 if (!field_type) {
477 ret = BT_COMPONENT_STATUS_ERROR;
478 goto end;
479 }
480 signedness = bt_ctf_field_type_integer_get_signed(field_type);
481 if (signedness < 0) {
482 ret = BT_COMPONENT_STATUS_ERROR;
483 goto end;
484 }
485 if (!signedness) {
486 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
487 ret = BT_COMPONENT_STATUS_ERROR;
488 goto end;
489 }
490 } else {
491 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
492 ret = BT_COMPONENT_STATUS_ERROR;
493 goto end;
494 }
495 }
496
497 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
498 switch (encoding) {
499 case BT_CTF_STRING_ENCODING_UTF8:
500 case BT_CTF_STRING_ENCODING_ASCII:
501 g_string_append_c(text->string, (int) v.u);
502 goto end;
503 case BT_CTF_STRING_ENCODING_NONE:
504 case BT_CTF_STRING_ENCODING_UNKNOWN:
505 break;
506 default:
507 ret = BT_COMPONENT_STATUS_ERROR;
508 goto end;
509 }
510
511 base = bt_ctf_field_type_integer_get_base(field_type);
512 switch (base) {
513 case BT_CTF_INTEGER_BASE_BINARY:
514 {
515 int bitnr, len;
516
517 len = bt_ctf_field_type_integer_get_size(field_type);
518 if (len < 0) {
519 ret = BT_COMPONENT_STATUS_ERROR;
520 goto end;
521 }
522 fprintf(text->out, "0b");
523 v.u = _bt_piecewise_lshift(v.u, 64 - len);
524 for (bitnr = 0; bitnr < len; bitnr++) {
525 fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
526 v.u = _bt_piecewise_lshift(v.u, 1);
527 }
528 break;
529 }
530 case BT_CTF_INTEGER_BASE_OCTAL:
531 {
532 if (signedness) {
533 int len;
534
535 len = bt_ctf_field_type_integer_get_size(field_type);
536 if (len < 0) {
537 ret = BT_COMPONENT_STATUS_ERROR;
538 goto end;
539 }
540 if (len < 64) {
541 size_t rounded_len;
542
543 assert(len != 0);
544 /* Round length to the nearest 3-bit */
545 rounded_len = (((len - 1) / 3) + 1) * 3;
546 v.u &= ((uint64_t) 1 << rounded_len) - 1;
547 }
548 }
549
550 fprintf(text->out, "0%" PRIo64, v.u);
551 break;
552 }
553 case BT_CTF_INTEGER_BASE_DECIMAL:
554 if (!signedness) {
555 fprintf(text->out, "%" PRIu64, v.u);
556 } else {
557 fprintf(text->out, "%" PRId64, v.s);
558 }
559 break;
560 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
561 {
562 int len;
563
564 len = bt_ctf_field_type_integer_get_size(field_type);
565 if (len < 0) {
566 ret = BT_COMPONENT_STATUS_ERROR;
567 goto end;
568 }
569 if (len < 64) {
570 /* Round length to the nearest nibble */
571 uint8_t rounded_len = ((len + 3) & ~0x3);
572
573 v.u &= ((uint64_t) 1 << rounded_len) - 1;
574 }
575
576 fprintf(text->out, "0x%" PRIX64, v.u);
577 break;
578 }
579 default:
580 ret = BT_COMPONENT_STATUS_ERROR;
581 goto end;
582 }
583 end:
584 bt_put(field_type);
585 return ret;
586 }
587
588 static
589 enum bt_component_status print_enum(struct text_component *text,
590 struct bt_ctf_field *field)
591 {
592 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
593 struct bt_ctf_field *container_field = NULL;
594 const char *mapping_name;
595
596 container_field = bt_ctf_field_enumeration_get_container(field);
597 if (!container_field) {
598 ret = BT_COMPONENT_STATUS_ERROR;
599 goto end;
600 }
601 mapping_name = bt_ctf_field_enumeration_get_mapping_name(field);
602 if (mapping_name) {
603 fprintf(text->out, "( \"%s\"", mapping_name);
604 } else {
605 fprintf(text->out, "( <unknown>");
606 }
607 fprintf(text->out, " : container = ");
608 ret = print_integer(text, container_field);
609 if (ret != BT_COMPONENT_STATUS_OK) {
610 goto end;
611 }
612 fprintf(text->out, " )");
613 end:
614 bt_put(container_field);
615 return ret;
616 }
617
618 static
619 enum bt_component_status print_struct_field(struct text_component *text,
620 struct bt_ctf_field *_struct,
621 struct bt_ctf_field_type *struct_type,
622 int i, bool print_names)
623 {
624 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
625 const char *field_name;
626 struct bt_ctf_field *field = NULL;
627 struct bt_ctf_field_type *field_type = NULL;;
628
629 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
630 if (!field) {
631 ret = BT_COMPONENT_STATUS_ERROR;
632 goto end;
633 }
634 if (bt_ctf_field_type_structure_get_field(struct_type,
635 &field_name, &field_type, i) < 0) {
636 ret = BT_COMPONENT_STATUS_ERROR;
637 goto end;
638 }
639
640 if (i != 0) {
641 fprintf(text->out, ", ");
642 } else {
643 fprintf(text->out, " ");
644 }
645 if (print_names) {
646 fprintf(text->out, "%s = ", rem_(field_name));
647 }
648 ret = print_field(text, field, print_names);
649 end:
650 bt_put(field_type);
651 bt_put(field);
652 return ret;
653 }
654
655 static
656 enum bt_component_status print_struct(struct text_component *text,
657 struct bt_ctf_field *_struct, bool print_names)
658 {
659 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
660 struct bt_ctf_field_type *struct_type = NULL;
661 int nr_fields, i;
662
663 struct_type = bt_ctf_field_get_type(_struct);
664 if (!struct_type) {
665 ret = BT_COMPONENT_STATUS_ERROR;
666 goto end;
667 }
668 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
669 if (nr_fields < 0) {
670 ret = BT_COMPONENT_STATUS_ERROR;
671 goto end;
672 }
673 fprintf(text->out, "{");
674 text->depth++;
675 for (i = 0; i < nr_fields; i++) {
676 ret = print_struct_field(text, _struct, struct_type, i,
677 print_names);
678 if (ret != BT_COMPONENT_STATUS_OK) {
679 goto end;
680 }
681 }
682 text->depth--;
683 fprintf(text->out, " }");
684 end:
685 bt_put(struct_type);
686 return ret;
687 }
688
689 static
690 enum bt_component_status print_array_field(struct text_component *text,
691 struct bt_ctf_field *array, uint64_t i,
692 bool is_string, bool print_names)
693 {
694 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
695 struct bt_ctf_field *field = NULL;
696
697 if (!is_string) {
698 if (i != 0) {
699 fprintf(text->out, ", ");
700 } else {
701 fprintf(text->out, " ");
702 }
703 }
704 field = bt_ctf_field_array_get_field(array, i);
705 if (!field) {
706 ret = BT_COMPONENT_STATUS_ERROR;
707 goto end;
708 }
709 ret = print_field(text, field, print_names);
710 end:
711 bt_put(field);
712 return ret;
713 }
714
715 static
716 enum bt_component_status print_array(struct text_component *text,
717 struct bt_ctf_field *array, bool print_names)
718 {
719 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
720 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
721 enum bt_ctf_type_id type_id;
722 int64_t len;
723 uint64_t i;
724 bool is_string = false;
725
726 array_type = bt_ctf_field_get_type(array);
727 if (!array_type) {
728 ret = BT_COMPONENT_STATUS_ERROR;
729 goto end;
730 }
731 field_type = bt_ctf_field_type_array_get_element_type(array_type);
732 if (!field_type) {
733 ret = BT_COMPONENT_STATUS_ERROR;
734 goto end;
735 }
736 len = bt_ctf_field_type_array_get_length(array_type);
737 if (len < 0) {
738 ret = BT_COMPONENT_STATUS_ERROR;
739 goto end;
740 }
741 type_id = bt_ctf_field_type_get_type_id(field_type);
742 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
743 enum bt_ctf_string_encoding encoding;
744
745 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
746 if (encoding == BT_CTF_STRING_ENCODING_UTF8
747 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
748 int integer_len, integer_alignment;
749
750 integer_len = bt_ctf_field_type_integer_get_size(field_type);
751 if (integer_len < 0) {
752 return BT_COMPONENT_STATUS_ERROR;
753 }
754 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
755 if (integer_alignment < 0) {
756 return BT_COMPONENT_STATUS_ERROR;
757 }
758 if (integer_len == CHAR_BIT
759 && integer_alignment == CHAR_BIT) {
760 is_string = true;
761 }
762 }
763 }
764
765 if (is_string) {
766 g_string_assign(text->string, "");
767 } else {
768 fprintf(text->out, "[");
769 }
770
771 text->depth++;
772 for (i = 0; i < len; i++) {
773 ret = print_array_field(text, array, i, is_string, print_names);
774 if (ret != BT_COMPONENT_STATUS_OK) {
775 goto end;
776 }
777 }
778 text->depth--;
779
780 if (is_string) {
781 fprintf(text->out, "\"%s\"", text->string->str);
782 } else {
783 fprintf(text->out, " ]");
784 }
785 end:
786 bt_put(field_type);
787 bt_put(array_type);
788 return ret;
789 }
790
791 static
792 enum bt_component_status print_sequence_field(struct text_component *text,
793 struct bt_ctf_field *seq, uint64_t i,
794 bool is_string, bool print_names)
795 {
796 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
797 struct bt_ctf_field *field = NULL;
798
799 if (!is_string) {
800 if (i != 0) {
801 fprintf(text->out, ", ");
802 } else {
803 fprintf(text->out, " ");
804 }
805 }
806 field = bt_ctf_field_sequence_get_field(seq, i);
807 if (!field) {
808 ret = BT_COMPONENT_STATUS_ERROR;
809 goto end;
810 }
811 ret = print_field(text, field, print_names);
812 end:
813 bt_put(field);
814 return ret;
815 }
816
817 static
818 enum bt_component_status print_sequence(struct text_component *text,
819 struct bt_ctf_field *seq, bool print_names)
820 {
821 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
822 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
823 struct bt_ctf_field *length_field = NULL;
824 enum bt_ctf_type_id type_id;
825 uint64_t len;
826 uint64_t i;
827 bool is_string = false;
828
829 seq_type = bt_ctf_field_get_type(seq);
830 if (!seq_type) {
831 ret = BT_COMPONENT_STATUS_ERROR;
832 goto end;
833 }
834 length_field = bt_ctf_field_sequence_get_length(seq);
835 if (!length_field) {
836 ret = BT_COMPONENT_STATUS_ERROR;
837 goto end;
838 }
839 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
840 ret = BT_COMPONENT_STATUS_ERROR;
841 goto end;
842 }
843 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
844 if (!field_type) {
845 ret = BT_COMPONENT_STATUS_ERROR;
846 goto end;
847 }
848 type_id = bt_ctf_field_type_get_type_id(field_type);
849 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
850 enum bt_ctf_string_encoding encoding;
851
852 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
853 if (encoding == BT_CTF_STRING_ENCODING_UTF8
854 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
855 int integer_len, integer_alignment;
856
857 integer_len = bt_ctf_field_type_integer_get_size(field_type);
858 if (integer_len < 0) {
859 ret = BT_COMPONENT_STATUS_ERROR;
860 goto end;
861 }
862 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
863 if (integer_alignment < 0) {
864 ret = BT_COMPONENT_STATUS_ERROR;
865 goto end;
866 }
867 if (integer_len == CHAR_BIT
868 && integer_alignment == CHAR_BIT) {
869 is_string = true;
870 }
871 }
872 }
873
874 if (is_string) {
875 g_string_assign(text->string, "");
876 } else {
877 fprintf(text->out, "[");
878 }
879
880 text->depth++;
881 for (i = 0; i < len; i++) {
882 ret = print_sequence_field(text, seq, i,
883 is_string, print_names);
884 if (ret != BT_COMPONENT_STATUS_OK) {
885 goto end;
886 }
887 }
888 text->depth--;
889
890 if (is_string) {
891 fprintf(text->out, "\"%s\"", text->string->str);
892 } else {
893 fprintf(text->out, " ]");
894 }
895 end:
896 bt_put(length_field);
897 bt_put(field_type);
898 bt_put(seq_type);
899 return ret;
900 }
901
902 static
903 enum bt_component_status print_variant(struct text_component *text,
904 struct bt_ctf_field *variant, bool print_names)
905 {
906 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
907 struct bt_ctf_field *field = NULL;
908
909 field = bt_ctf_field_variant_get_current_field(variant);
910 if (!field) {
911 ret = BT_COMPONENT_STATUS_ERROR;
912 goto end;
913 }
914 fprintf(text->out, "{ ");
915 text->depth++;
916 if (print_names) {
917 struct bt_ctf_field *tag_field = NULL;
918 const char *tag_choice;
919
920 tag_field = bt_ctf_field_variant_get_tag(variant);
921 if (!tag_field) {
922 ret = BT_COMPONENT_STATUS_ERROR;
923 goto end;
924 }
925 tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field);
926 if (!tag_choice) {
927 bt_put(tag_field);
928 ret = BT_COMPONENT_STATUS_ERROR;
929 goto end;
930 }
931 fprintf(text->out, "%s = ", rem_(tag_choice));
932 bt_put(tag_field);
933 }
934 ret = print_field(text, field, print_names);
935 if (ret != BT_COMPONENT_STATUS_OK) {
936 goto end;
937 }
938 text->depth--;
939 fprintf(text->out, " }");
940 end:
941 bt_put(field);
942 return ret;
943 }
944
945 static
946 enum bt_component_status print_field(struct text_component *text,
947 struct bt_ctf_field *field, bool print_names)
948 {
949 enum bt_ctf_type_id type_id;
950
951 type_id = bt_ctf_field_get_type_id(field);
952 switch (type_id) {
953 case CTF_TYPE_INTEGER:
954 return print_integer(text, field);
955 case CTF_TYPE_FLOAT:
956 {
957 double v;
958
959 if (bt_ctf_field_floating_point_get_value(field, &v)) {
960 return BT_COMPONENT_STATUS_ERROR;
961 }
962 fprintf(text->out, "%g", v);
963 return BT_COMPONENT_STATUS_OK;
964 }
965 case CTF_TYPE_ENUM:
966 return print_enum(text, field);
967 case CTF_TYPE_STRING:
968 fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field));
969 return BT_COMPONENT_STATUS_OK;
970 case CTF_TYPE_STRUCT:
971 return print_struct(text, field, print_names);
972 case CTF_TYPE_UNTAGGED_VARIANT:
973 case CTF_TYPE_VARIANT:
974 return print_variant(text, field, print_names);
975 case CTF_TYPE_ARRAY:
976 return print_array(text, field, print_names);
977 case CTF_TYPE_SEQUENCE:
978 return print_sequence(text, field, print_names);
979 default:
980 fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id);
981 return BT_COMPONENT_STATUS_ERROR;
982 }
983 }
984
985 static
986 enum bt_component_status print_stream_packet_context(struct text_component *text,
987 struct bt_ctf_event *event)
988 {
989 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
990 struct bt_ctf_packet *packet = NULL;
991 struct bt_ctf_field *main_field = NULL;
992
993 packet = bt_ctf_event_get_packet(event);
994 if (!packet) {
995 ret = BT_COMPONENT_STATUS_ERROR;
996 goto end;
997 }
998 main_field = bt_ctf_packet_get_context(packet);
999 if (!main_field) {
1000 ret = BT_COMPONENT_STATUS_ERROR;
1001 goto end;
1002 }
1003 if (!text->start_line) {
1004 fputs(", ", text->out);
1005 }
1006 text->start_line = false;
1007 if (text->options.print_scope_field_names) {
1008 fputs("stream.packet.context = ", text->out);
1009 }
1010 ret = print_field(text, main_field,
1011 text->options.print_context_field_names);
1012 end:
1013 bt_put(main_field);
1014 bt_put(packet);
1015 return ret;
1016 }
1017
1018 static
1019 enum bt_component_status print_event_header_raw(struct text_component *text,
1020 struct bt_ctf_event *event)
1021 {
1022 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1023 struct bt_ctf_field *main_field = NULL;
1024
1025 main_field = bt_ctf_event_get_header(event);
1026 if (!main_field) {
1027 ret = BT_COMPONENT_STATUS_ERROR;
1028 goto end;
1029 }
1030 if (!text->start_line) {
1031 fputs(", ", text->out);
1032 }
1033 text->start_line = false;
1034 if (text->options.print_scope_field_names) {
1035 fputs("stream.event.header = ", text->out);
1036 }
1037 ret = print_field(text, main_field,
1038 text->options.print_header_field_names);
1039 end:
1040 bt_put(main_field);
1041 return ret;
1042 }
1043
1044 static
1045 enum bt_component_status print_stream_event_context(struct text_component *text,
1046 struct bt_ctf_event *event)
1047 {
1048 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1049 struct bt_ctf_field *main_field = NULL;
1050
1051 main_field = bt_ctf_event_get_stream_event_context(event);
1052 if (!main_field) {
1053 ret = BT_COMPONENT_STATUS_ERROR;
1054 goto end;
1055 }
1056 if (!text->start_line) {
1057 fputs(", ", text->out);
1058 }
1059 text->start_line = false;
1060 if (text->options.print_scope_field_names) {
1061 fputs("stream.event.context = ", text->out);
1062 }
1063 ret = print_field(text, main_field,
1064 text->options.print_context_field_names);
1065 end:
1066 bt_put(main_field);
1067 return ret;
1068 }
1069
1070 static
1071 enum bt_component_status print_event_context(struct text_component *text,
1072 struct bt_ctf_event *event)
1073 {
1074 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1075 struct bt_ctf_field *main_field = NULL;
1076
1077 main_field = bt_ctf_event_get_event_context(event);
1078 if (!main_field) {
1079 ret = BT_COMPONENT_STATUS_ERROR;
1080 goto end;
1081 }
1082 if (!text->start_line) {
1083 fputs(", ", text->out);
1084 }
1085 text->start_line = false;
1086 if (text->options.print_scope_field_names) {
1087 fputs("event.context = ", text->out);
1088 }
1089 ret = print_field(text, main_field,
1090 text->options.print_context_field_names);
1091 end:
1092 bt_put(main_field);
1093 return ret;
1094 }
1095
1096 static
1097 enum bt_component_status print_event_payload(struct text_component *text,
1098 struct bt_ctf_event *event)
1099 {
1100 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1101 struct bt_ctf_field *main_field = NULL;
1102
1103 main_field = bt_ctf_event_get_payload_field(event);
1104 if (!main_field) {
1105 ret = BT_COMPONENT_STATUS_ERROR;
1106 goto end;
1107 }
1108 if (!text->start_line) {
1109 fputs(", ", text->out);
1110 }
1111 text->start_line = false;
1112 if (text->options.print_scope_field_names) {
1113 fputs("event.fields = ", text->out);
1114 }
1115 ret = print_field(text, main_field,
1116 text->options.print_payload_field_names);
1117 end:
1118 bt_put(main_field);
1119 return ret;
1120 }
1121
1122 BT_HIDDEN
1123 enum bt_component_status text_print_event(struct text_component *text,
1124 struct bt_ctf_event *event)
1125 {
1126 enum bt_component_status ret;
1127
1128 text->start_line = true;
1129 ret = print_event_header(text, event);
1130 if (ret != BT_COMPONENT_STATUS_OK) {
1131 goto end;
1132 }
1133
1134 ret = print_stream_packet_context(text, event);
1135 if (ret != BT_COMPONENT_STATUS_OK) {
1136 goto end;
1137 }
1138
1139 ret = print_event_header_raw(text, event);
1140 if (ret != BT_COMPONENT_STATUS_OK) {
1141 goto end;
1142 }
1143
1144 ret = print_stream_event_context(text, event);
1145 if (ret != BT_COMPONENT_STATUS_OK) {
1146 goto end;
1147 }
1148
1149 ret = print_event_context(text, event);
1150 if (ret != BT_COMPONENT_STATUS_OK) {
1151 goto end;
1152 }
1153
1154 ret = print_event_payload(text, event);
1155 if (ret != BT_COMPONENT_STATUS_OK) {
1156 goto end;
1157 }
1158
1159 fputc('\n', text->out);
1160 end:
1161 return ret;
1162 }
This page took 0.052387 seconds and 5 git commands to generate.