Remove callsite text output code
[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->start_line) {
437 fputs(", ", text->out);
438 }
439 text->start_line = false;
440 if (print_names) {
441 fputs("name = ", text->out);
442 }
443 fputs(bt_ctf_event_class_get_name(event_class), text->out);
444 end:
445 bt_put(trace_class);
446 bt_put(stream_class);
447 bt_put(event_class);
448 return ret;
449 }
450
451 static
452 enum bt_component_status print_integer(struct text_component *text,
453 struct bt_ctf_field *field)
454 {
455 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
456 struct bt_ctf_field_type *field_type = NULL;
457 enum bt_ctf_integer_base base;
458 enum bt_ctf_string_encoding encoding;
459 int signedness;
460 union {
461 uint64_t u;
462 int64_t s;
463 } v;
464
465 field_type = bt_ctf_field_get_type(field);
466 if (!field_type) {
467 ret = BT_COMPONENT_STATUS_ERROR;
468 goto end;
469 }
470 signedness = bt_ctf_field_type_integer_get_signed(field_type);
471 if (signedness < 0) {
472 ret = BT_COMPONENT_STATUS_ERROR;
473 goto end;
474 }
475 if (!signedness) {
476 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
477 ret = BT_COMPONENT_STATUS_ERROR;
478 goto end;
479 }
480 } else {
481 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
482 ret = BT_COMPONENT_STATUS_ERROR;
483 goto end;
484 }
485 }
486
487 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
488 switch (encoding) {
489 case BT_CTF_STRING_ENCODING_UTF8:
490 case BT_CTF_STRING_ENCODING_ASCII:
491 g_string_append_c(text->string, (int) v.u);
492 goto end;
493 case BT_CTF_STRING_ENCODING_NONE:
494 case BT_CTF_STRING_ENCODING_UNKNOWN:
495 break;
496 default:
497 ret = BT_COMPONENT_STATUS_ERROR;
498 goto end;
499 }
500
501 base = bt_ctf_field_type_integer_get_base(field_type);
502 switch (base) {
503 case BT_CTF_INTEGER_BASE_BINARY:
504 {
505 int bitnr, len;
506
507 len = bt_ctf_field_type_integer_get_size(field_type);
508 if (len < 0) {
509 ret = BT_COMPONENT_STATUS_ERROR;
510 goto end;
511 }
512 fprintf(text->out, "0b");
513 v.u = _bt_piecewise_lshift(v.u, 64 - len);
514 for (bitnr = 0; bitnr < len; bitnr++) {
515 fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
516 v.u = _bt_piecewise_lshift(v.u, 1);
517 }
518 break;
519 }
520 case BT_CTF_INTEGER_BASE_OCTAL:
521 {
522 if (signedness) {
523 int len;
524
525 len = bt_ctf_field_type_integer_get_size(field_type);
526 if (len < 0) {
527 ret = BT_COMPONENT_STATUS_ERROR;
528 goto end;
529 }
530 if (len < 64) {
531 size_t rounded_len;
532
533 assert(len != 0);
534 /* Round length to the nearest 3-bit */
535 rounded_len = (((len - 1) / 3) + 1) * 3;
536 v.u &= ((uint64_t) 1 << rounded_len) - 1;
537 }
538 }
539
540 fprintf(text->out, "0%" PRIo64, v.u);
541 break;
542 }
543 case BT_CTF_INTEGER_BASE_DECIMAL:
544 if (!signedness) {
545 fprintf(text->out, "%" PRIu64, v.u);
546 } else {
547 fprintf(text->out, "%" PRId64, v.s);
548 }
549 break;
550 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
551 {
552 int len;
553
554 len = bt_ctf_field_type_integer_get_size(field_type);
555 if (len < 0) {
556 ret = BT_COMPONENT_STATUS_ERROR;
557 goto end;
558 }
559 if (len < 64) {
560 /* Round length to the nearest nibble */
561 uint8_t rounded_len = ((len + 3) & ~0x3);
562
563 v.u &= ((uint64_t) 1 << rounded_len) - 1;
564 }
565
566 fprintf(text->out, "0x%" PRIX64, v.u);
567 break;
568 }
569 default:
570 ret = BT_COMPONENT_STATUS_ERROR;
571 goto end;
572 }
573 end:
574 bt_put(field_type);
575 return ret;
576 }
577
578 static
579 enum bt_component_status print_enum(struct text_component *text,
580 struct bt_ctf_field *field)
581 {
582 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
583 struct bt_ctf_field *container_field = NULL;
584 const char *mapping_name;
585
586 container_field = bt_ctf_field_enumeration_get_container(field);
587 if (!container_field) {
588 ret = BT_COMPONENT_STATUS_ERROR;
589 goto end;
590 }
591 mapping_name = bt_ctf_field_enumeration_get_mapping_name(field);
592 if (mapping_name) {
593 fprintf(text->out, "( \"%s\"", mapping_name);
594 } else {
595 fprintf(text->out, "( <unknown>");
596 }
597 fprintf(text->out, " : container = ");
598 ret = print_integer(text, container_field);
599 if (ret != BT_COMPONENT_STATUS_OK) {
600 goto end;
601 }
602 fprintf(text->out, " )");
603 end:
604 bt_put(container_field);
605 return ret;
606 }
607
608 static
609 enum bt_component_status print_struct_field(struct text_component *text,
610 struct bt_ctf_field *_struct,
611 struct bt_ctf_field_type *struct_type,
612 int i, bool print_names)
613 {
614 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
615 const char *field_name;
616 struct bt_ctf_field *field = NULL;
617 struct bt_ctf_field_type *field_type = NULL;;
618
619 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
620 if (!field) {
621 ret = BT_COMPONENT_STATUS_ERROR;
622 goto end;
623 }
624 if (bt_ctf_field_type_structure_get_field(struct_type,
625 &field_name, &field_type, i) < 0) {
626 ret = BT_COMPONENT_STATUS_ERROR;
627 goto end;
628 }
629
630 if (i != 0) {
631 fprintf(text->out, ", ");
632 } else {
633 fprintf(text->out, " ");
634 }
635 if (print_names) {
636 fprintf(text->out, "%s = ", rem_(field_name));
637 }
638 ret = print_field(text, field, print_names);
639 end:
640 bt_put(field_type);
641 bt_put(field);
642 return ret;
643 }
644
645 static
646 enum bt_component_status print_struct(struct text_component *text,
647 struct bt_ctf_field *_struct, bool print_names)
648 {
649 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
650 struct bt_ctf_field_type *struct_type = NULL;
651 int nr_fields, i;
652
653 struct_type = bt_ctf_field_get_type(_struct);
654 if (!struct_type) {
655 ret = BT_COMPONENT_STATUS_ERROR;
656 goto end;
657 }
658 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
659 if (nr_fields < 0) {
660 ret = BT_COMPONENT_STATUS_ERROR;
661 goto end;
662 }
663 fprintf(text->out, "{");
664 text->depth++;
665 for (i = 0; i < nr_fields; i++) {
666 ret = print_struct_field(text, _struct, struct_type, i,
667 print_names);
668 if (ret != BT_COMPONENT_STATUS_OK) {
669 goto end;
670 }
671 }
672 text->depth--;
673 fprintf(text->out, " }");
674 end:
675 bt_put(struct_type);
676 return ret;
677 }
678
679 static
680 enum bt_component_status print_array_field(struct text_component *text,
681 struct bt_ctf_field *array, uint64_t i,
682 bool is_string, bool print_names)
683 {
684 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
685 struct bt_ctf_field *field = NULL;
686
687 if (!is_string) {
688 if (i != 0) {
689 fprintf(text->out, ", ");
690 } else {
691 fprintf(text->out, " ");
692 }
693 }
694 field = bt_ctf_field_array_get_field(array, i);
695 if (!field) {
696 ret = BT_COMPONENT_STATUS_ERROR;
697 goto end;
698 }
699 ret = print_field(text, field, print_names);
700 end:
701 bt_put(field);
702 return ret;
703 }
704
705 static
706 enum bt_component_status print_array(struct text_component *text,
707 struct bt_ctf_field *array, bool print_names)
708 {
709 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
710 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
711 enum bt_ctf_type_id type_id;
712 int64_t len;
713 uint64_t i;
714 bool is_string = false;
715
716 array_type = bt_ctf_field_get_type(array);
717 if (!array_type) {
718 ret = BT_COMPONENT_STATUS_ERROR;
719 goto end;
720 }
721 field_type = bt_ctf_field_type_array_get_element_type(array_type);
722 if (!field_type) {
723 ret = BT_COMPONENT_STATUS_ERROR;
724 goto end;
725 }
726 len = bt_ctf_field_type_array_get_length(array_type);
727 if (len < 0) {
728 ret = BT_COMPONENT_STATUS_ERROR;
729 goto end;
730 }
731 type_id = bt_ctf_field_type_get_type_id(field_type);
732 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
733 enum bt_ctf_string_encoding encoding;
734
735 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
736 if (encoding == BT_CTF_STRING_ENCODING_UTF8
737 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
738 int integer_len, integer_alignment;
739
740 integer_len = bt_ctf_field_type_integer_get_size(field_type);
741 if (integer_len < 0) {
742 return BT_COMPONENT_STATUS_ERROR;
743 }
744 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
745 if (integer_alignment < 0) {
746 return BT_COMPONENT_STATUS_ERROR;
747 }
748 if (integer_len == CHAR_BIT
749 && integer_alignment == CHAR_BIT) {
750 is_string = true;
751 }
752 }
753 }
754
755 if (is_string) {
756 g_string_assign(text->string, "");
757 } else {
758 fprintf(text->out, "[");
759 }
760
761 text->depth++;
762 for (i = 0; i < len; i++) {
763 ret = print_array_field(text, array, i, is_string, print_names);
764 if (ret != BT_COMPONENT_STATUS_OK) {
765 goto end;
766 }
767 }
768 text->depth--;
769
770 if (is_string) {
771 fprintf(text->out, "\"%s\"", text->string->str);
772 } else {
773 fprintf(text->out, " ]");
774 }
775 end:
776 bt_put(field_type);
777 bt_put(array_type);
778 return ret;
779 }
780
781 static
782 enum bt_component_status print_sequence_field(struct text_component *text,
783 struct bt_ctf_field *seq, uint64_t i,
784 bool is_string, bool print_names)
785 {
786 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
787 struct bt_ctf_field *field = NULL;
788
789 if (!is_string) {
790 if (i != 0) {
791 fprintf(text->out, ", ");
792 } else {
793 fprintf(text->out, " ");
794 }
795 }
796 field = bt_ctf_field_sequence_get_field(seq, i);
797 if (!field) {
798 ret = BT_COMPONENT_STATUS_ERROR;
799 goto end;
800 }
801 ret = print_field(text, field, print_names);
802 end:
803 bt_put(field);
804 return ret;
805 }
806
807 static
808 enum bt_component_status print_sequence(struct text_component *text,
809 struct bt_ctf_field *seq, bool print_names)
810 {
811 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
812 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
813 struct bt_ctf_field *length_field = NULL;
814 enum bt_ctf_type_id type_id;
815 uint64_t len;
816 uint64_t i;
817 bool is_string = false;
818
819 seq_type = bt_ctf_field_get_type(seq);
820 if (!seq_type) {
821 ret = BT_COMPONENT_STATUS_ERROR;
822 goto end;
823 }
824 length_field = bt_ctf_field_sequence_get_length(seq);
825 if (!length_field) {
826 ret = BT_COMPONENT_STATUS_ERROR;
827 goto end;
828 }
829 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
830 ret = BT_COMPONENT_STATUS_ERROR;
831 goto end;
832 }
833 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
834 if (!field_type) {
835 ret = BT_COMPONENT_STATUS_ERROR;
836 goto end;
837 }
838 type_id = bt_ctf_field_type_get_type_id(field_type);
839 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
840 enum bt_ctf_string_encoding encoding;
841
842 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
843 if (encoding == BT_CTF_STRING_ENCODING_UTF8
844 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
845 int integer_len, integer_alignment;
846
847 integer_len = bt_ctf_field_type_integer_get_size(field_type);
848 if (integer_len < 0) {
849 ret = BT_COMPONENT_STATUS_ERROR;
850 goto end;
851 }
852 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
853 if (integer_alignment < 0) {
854 ret = BT_COMPONENT_STATUS_ERROR;
855 goto end;
856 }
857 if (integer_len == CHAR_BIT
858 && integer_alignment == CHAR_BIT) {
859 is_string = true;
860 }
861 }
862 }
863
864 if (is_string) {
865 g_string_assign(text->string, "");
866 } else {
867 fprintf(text->out, "[");
868 }
869
870 text->depth++;
871 for (i = 0; i < len; i++) {
872 ret = print_sequence_field(text, seq, i,
873 is_string, print_names);
874 if (ret != BT_COMPONENT_STATUS_OK) {
875 goto end;
876 }
877 }
878 text->depth--;
879
880 if (is_string) {
881 fprintf(text->out, "\"%s\"", text->string->str);
882 } else {
883 fprintf(text->out, " ]");
884 }
885 end:
886 bt_put(length_field);
887 bt_put(field_type);
888 bt_put(seq_type);
889 return ret;
890 }
891
892 static
893 enum bt_component_status print_variant(struct text_component *text,
894 struct bt_ctf_field *variant, bool print_names)
895 {
896 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
897 struct bt_ctf_field *field = NULL;
898
899 field = bt_ctf_field_variant_get_current_field(variant);
900 if (!field) {
901 ret = BT_COMPONENT_STATUS_ERROR;
902 goto end;
903 }
904 fprintf(text->out, "{ ");
905 text->depth++;
906 if (print_names) {
907 struct bt_ctf_field *tag_field = NULL;
908 const char *tag_choice;
909
910 tag_field = bt_ctf_field_variant_get_tag(variant);
911 if (!tag_field) {
912 ret = BT_COMPONENT_STATUS_ERROR;
913 goto end;
914 }
915 tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field);
916 if (!tag_choice) {
917 bt_put(tag_field);
918 ret = BT_COMPONENT_STATUS_ERROR;
919 goto end;
920 }
921 fprintf(text->out, "%s = ", rem_(tag_choice));
922 bt_put(tag_field);
923 }
924 ret = print_field(text, field, print_names);
925 if (ret != BT_COMPONENT_STATUS_OK) {
926 goto end;
927 }
928 text->depth--;
929 fprintf(text->out, " }");
930 end:
931 bt_put(field);
932 return ret;
933 }
934
935 static
936 enum bt_component_status print_field(struct text_component *text,
937 struct bt_ctf_field *field, bool print_names)
938 {
939 enum bt_ctf_type_id type_id;
940
941 type_id = bt_ctf_field_get_type_id(field);
942 switch (type_id) {
943 case CTF_TYPE_INTEGER:
944 return print_integer(text, field);
945 case CTF_TYPE_FLOAT:
946 {
947 double v;
948
949 if (bt_ctf_field_floating_point_get_value(field, &v)) {
950 return BT_COMPONENT_STATUS_ERROR;
951 }
952 fprintf(text->out, "%g", v);
953 return BT_COMPONENT_STATUS_OK;
954 }
955 case CTF_TYPE_ENUM:
956 return print_enum(text, field);
957 case CTF_TYPE_STRING:
958 fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field));
959 return BT_COMPONENT_STATUS_OK;
960 case CTF_TYPE_STRUCT:
961 return print_struct(text, field, print_names);
962 case CTF_TYPE_UNTAGGED_VARIANT:
963 case CTF_TYPE_VARIANT:
964 return print_variant(text, field, print_names);
965 case CTF_TYPE_ARRAY:
966 return print_array(text, field, print_names);
967 case CTF_TYPE_SEQUENCE:
968 return print_sequence(text, field, print_names);
969 default:
970 fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id);
971 return BT_COMPONENT_STATUS_ERROR;
972 }
973 }
974
975 static
976 enum bt_component_status print_stream_packet_context(struct text_component *text,
977 struct bt_ctf_event *event)
978 {
979 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
980 struct bt_ctf_packet *packet = NULL;
981 struct bt_ctf_field *main_field = NULL;
982
983 packet = bt_ctf_event_get_packet(event);
984 if (!packet) {
985 ret = BT_COMPONENT_STATUS_ERROR;
986 goto end;
987 }
988 main_field = bt_ctf_packet_get_context(packet);
989 if (!main_field) {
990 ret = BT_COMPONENT_STATUS_ERROR;
991 goto end;
992 }
993 if (!text->start_line) {
994 fputs(", ", text->out);
995 }
996 text->start_line = false;
997 if (text->options.print_scope_field_names) {
998 fputs("stream.packet.context = ", text->out);
999 }
1000 ret = print_field(text, main_field,
1001 text->options.print_context_field_names);
1002 end:
1003 bt_put(main_field);
1004 bt_put(packet);
1005 return ret;
1006 }
1007
1008 static
1009 enum bt_component_status print_event_header_raw(struct text_component *text,
1010 struct bt_ctf_event *event)
1011 {
1012 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1013 struct bt_ctf_field *main_field = NULL;
1014
1015 main_field = bt_ctf_event_get_header(event);
1016 if (!main_field) {
1017 ret = BT_COMPONENT_STATUS_ERROR;
1018 goto end;
1019 }
1020 if (!text->start_line) {
1021 fputs(", ", text->out);
1022 }
1023 text->start_line = false;
1024 if (text->options.print_scope_field_names) {
1025 fputs("stream.event.header = ", text->out);
1026 }
1027 ret = print_field(text, main_field,
1028 text->options.print_header_field_names);
1029 end:
1030 bt_put(main_field);
1031 return ret;
1032 }
1033
1034 static
1035 enum bt_component_status print_stream_event_context(struct text_component *text,
1036 struct bt_ctf_event *event)
1037 {
1038 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1039 struct bt_ctf_field *main_field = NULL;
1040
1041 main_field = bt_ctf_event_get_stream_event_context(event);
1042 if (!main_field) {
1043 ret = BT_COMPONENT_STATUS_ERROR;
1044 goto end;
1045 }
1046 if (!text->start_line) {
1047 fputs(", ", text->out);
1048 }
1049 text->start_line = false;
1050 if (text->options.print_scope_field_names) {
1051 fputs("stream.event.context = ", text->out);
1052 }
1053 ret = print_field(text, main_field,
1054 text->options.print_context_field_names);
1055 end:
1056 bt_put(main_field);
1057 return ret;
1058 }
1059
1060 static
1061 enum bt_component_status print_event_context(struct text_component *text,
1062 struct bt_ctf_event *event)
1063 {
1064 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1065 struct bt_ctf_field *main_field = NULL;
1066
1067 main_field = bt_ctf_event_get_event_context(event);
1068 if (!main_field) {
1069 ret = BT_COMPONENT_STATUS_ERROR;
1070 goto end;
1071 }
1072 if (!text->start_line) {
1073 fputs(", ", text->out);
1074 }
1075 text->start_line = false;
1076 if (text->options.print_scope_field_names) {
1077 fputs("event.context = ", text->out);
1078 }
1079 ret = print_field(text, main_field,
1080 text->options.print_context_field_names);
1081 end:
1082 bt_put(main_field);
1083 return ret;
1084 }
1085
1086 static
1087 enum bt_component_status print_event_payload(struct text_component *text,
1088 struct bt_ctf_event *event)
1089 {
1090 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1091 struct bt_ctf_field *main_field = NULL;
1092
1093 main_field = bt_ctf_event_get_payload_field(event);
1094 if (!main_field) {
1095 ret = BT_COMPONENT_STATUS_ERROR;
1096 goto end;
1097 }
1098 if (!text->start_line) {
1099 fputs(", ", text->out);
1100 }
1101 text->start_line = false;
1102 if (text->options.print_scope_field_names) {
1103 fputs("event.fields = ", text->out);
1104 }
1105 ret = print_field(text, main_field,
1106 text->options.print_payload_field_names);
1107 end:
1108 bt_put(main_field);
1109 return ret;
1110 }
1111
1112 BT_HIDDEN
1113 enum bt_component_status text_print_event(struct text_component *text,
1114 struct bt_ctf_event *event)
1115 {
1116 enum bt_component_status ret;
1117
1118 text->start_line = true;
1119 ret = print_event_header(text, event);
1120 if (ret != BT_COMPONENT_STATUS_OK) {
1121 goto end;
1122 }
1123
1124 ret = print_stream_packet_context(text, event);
1125 if (ret != BT_COMPONENT_STATUS_OK) {
1126 goto end;
1127 }
1128
1129 ret = print_event_header_raw(text, event);
1130 if (ret != BT_COMPONENT_STATUS_OK) {
1131 goto end;
1132 }
1133
1134 ret = print_stream_event_context(text, event);
1135 if (ret != BT_COMPONENT_STATUS_OK) {
1136 goto end;
1137 }
1138
1139 ret = print_event_context(text, event);
1140 if (ret != BT_COMPONENT_STATUS_OK) {
1141 goto end;
1142 }
1143
1144 ret = print_event_payload(text, event);
1145 if (ret != BT_COMPONENT_STATUS_OK) {
1146 goto end;
1147 }
1148
1149 fputc('\n', text->out);
1150 end:
1151 return ret;
1152 }
This page took 0.064537 seconds and 4 git commands to generate.