Add BT_CTF_INTEGER_BASE_UNSPECIFIED
[babeltrace.git] / plugins / text / pretty / 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 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include <babeltrace/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock-class.h>
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/trace.h>
39 #include <babeltrace/graph/notification-event.h>
40 #include <babeltrace/graph/clock-class-priority-map.h>
41 #include <babeltrace/bitfield-internal.h>
42 #include <babeltrace/common-internal.h>
43 #include <babeltrace/compat/time-internal.h>
44 #include <inttypes.h>
45 #include <ctype.h>
46 #include "pretty.h"
47
48 #define NSEC_PER_SEC 1000000000LL
49
50 #define COLOR_NAME BT_COMMON_COLOR_BOLD
51 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
52 #define COLOR_RST BT_COMMON_COLOR_RESET
53 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
54 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
55 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
56 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
57 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
58 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
59
60 static inline
61 const char *rem_(const char *str)
62 {
63 if (str[0] == '_')
64 return &str[1];
65 else
66 return str;
67 }
68
69 struct timestamp {
70 int64_t real_timestamp; /* Relative to UNIX epoch. */
71 uint64_t clock_value; /* In cycles. */
72 };
73
74 static
75 enum bt_component_status print_field(struct pretty_component *pretty,
76 struct bt_ctf_field *field, bool print_names,
77 GQuark *filters_fields, int filter_array_len);
78
79 static
80 void print_name_equal(struct pretty_component *pretty, const char *name)
81 {
82 if (pretty->use_colors) {
83 g_string_append_printf(pretty->string, "%s%s%s = ", COLOR_NAME,
84 name, COLOR_RST);
85 } else {
86 g_string_append_printf(pretty->string, "%s = ", name);
87 }
88 }
89
90 static
91 void print_field_name_equal(struct pretty_component *pretty, const char *name)
92 {
93 if (pretty->use_colors) {
94 g_string_append_printf(pretty->string, "%s%s%s = ",
95 COLOR_FIELD_NAME, name, COLOR_RST);
96 } else {
97 g_string_append_printf(pretty->string, "%s = ", name);
98 }
99 }
100
101 static
102 void print_timestamp_cycles(struct pretty_component *pretty,
103 struct bt_ctf_clock_class *clock_class,
104 struct bt_ctf_event *event)
105 {
106 int ret;
107 struct bt_ctf_clock_value *clock_value;
108 uint64_t cycles;
109
110 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
111 if (!clock_value) {
112 g_string_append(pretty->string, "????????????????????");
113 return;
114 }
115
116 ret = bt_ctf_clock_value_get_value(clock_value, &cycles);
117 bt_put(clock_value);
118 if (ret) {
119 // TODO: log, this is unexpected
120 g_string_append(pretty->string, "Error");
121 return;
122 }
123
124 g_string_append_printf(pretty->string, "%020" PRIu64, cycles);
125
126 if (pretty->last_cycles_timestamp != -1ULL) {
127 pretty->delta_cycles = cycles - pretty->last_cycles_timestamp;
128 }
129 pretty->last_cycles_timestamp = cycles;
130 }
131
132 static
133 void print_timestamp_wall(struct pretty_component *pretty,
134 struct bt_ctf_clock_class *clock_class,
135 struct bt_ctf_event *event)
136 {
137 int ret;
138 struct bt_ctf_clock_value *clock_value;
139 int64_t ts_nsec = 0; /* add configurable offset */
140 int64_t ts_sec = 0; /* add configurable offset */
141 uint64_t ts_sec_abs, ts_nsec_abs;
142 bool is_negative;
143
144 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
145 if (!clock_value) {
146 g_string_append(pretty->string, "??:??:??.?????????");
147 return;
148 }
149
150 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
151 bt_put(clock_value);
152 if (ret) {
153 // TODO: log, this is unexpected
154 g_string_append(pretty->string, "Error");
155 return;
156 }
157
158 if (pretty->last_real_timestamp != -1ULL) {
159 pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp;
160 }
161
162 pretty->last_real_timestamp = ts_nsec;
163 ts_sec += ts_nsec / NSEC_PER_SEC;
164 ts_nsec = ts_nsec % NSEC_PER_SEC;
165
166 if (ts_sec >= 0 && ts_nsec >= 0) {
167 is_negative = false;
168 ts_sec_abs = ts_sec;
169 ts_nsec_abs = ts_nsec;
170 } else if (ts_sec > 0 && ts_nsec < 0) {
171 is_negative = false;
172 ts_sec_abs = ts_sec - 1;
173 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
174 } else if (ts_sec == 0 && ts_nsec < 0) {
175 is_negative = true;
176 ts_sec_abs = ts_sec;
177 ts_nsec_abs = -ts_nsec;
178 } else if (ts_sec < 0 && ts_nsec > 0) {
179 is_negative = true;
180 ts_sec_abs = -(ts_sec + 1);
181 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
182 } else if (ts_sec < 0 && ts_nsec == 0) {
183 is_negative = true;
184 ts_sec_abs = -ts_sec;
185 ts_nsec_abs = ts_nsec;
186 } else { /* (ts_sec < 0 && ts_nsec < 0) */
187 is_negative = true;
188 ts_sec_abs = -ts_sec;
189 ts_nsec_abs = -ts_nsec;
190 }
191
192 if (!pretty->options.clock_seconds) {
193 struct tm tm;
194 time_t time_s = (time_t) ts_sec_abs;
195
196 if (is_negative) {
197 // TODO: log instead
198 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
199 goto seconds;
200 }
201
202 if (!pretty->options.clock_gmt) {
203 struct tm *res;
204
205 res = bt_localtime_r(&time_s, &tm);
206 if (!res) {
207 // TODO: log instead
208 fprintf(stderr, "[warning] Unable to get localtime.\n");
209 goto seconds;
210 }
211 } else {
212 struct tm *res;
213
214 res = bt_gmtime_r(&time_s, &tm);
215 if (!res) {
216 // TODO: log instead
217 fprintf(stderr, "[warning] Unable to get gmtime.\n");
218 goto seconds;
219 }
220 }
221 if (pretty->options.clock_date) {
222 char timestr[26];
223 size_t res;
224
225 /* Print date and time */
226 res = strftime(timestr, sizeof(timestr),
227 "%Y-%m-%d ", &tm);
228 if (!res) {
229 // TODO: log instead
230 fprintf(stderr, "[warning] Unable to print ascii time.\n");
231 goto seconds;
232 }
233
234 g_string_append(pretty->string, timestr);
235 }
236
237 /* Print time in HH:MM:SS.ns */
238 g_string_append_printf(pretty->string,
239 "%02d:%02d:%02d.%09" PRIu64, tm.tm_hour, tm.tm_min,
240 tm.tm_sec, ts_nsec_abs);
241 goto end;
242 }
243 seconds:
244 g_string_append_printf(pretty->string, "%s%" PRId64 ".%09" PRIu64,
245 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
246 end:
247 return;
248 }
249
250 static
251 enum bt_component_status print_event_timestamp(struct pretty_component *pretty,
252 struct bt_ctf_event *event,
253 struct bt_clock_class_priority_map *cc_prio_map,
254 bool *start_line)
255 {
256 bool print_names = pretty->options.print_header_field_names;
257 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
258 struct bt_ctf_stream *stream = NULL;
259 struct bt_ctf_stream_class *stream_class = NULL;
260 struct bt_ctf_trace *trace = NULL;
261 struct bt_ctf_clock_class *clock_class = NULL;
262
263 stream = bt_ctf_event_get_stream(event);
264 if (!stream) {
265 ret = BT_COMPONENT_STATUS_ERROR;
266 goto end;
267 }
268
269 stream_class = bt_ctf_stream_get_class(stream);
270 if (!stream_class) {
271 ret = BT_COMPONENT_STATUS_ERROR;
272 goto end;
273 }
274 trace = bt_ctf_stream_class_get_trace(stream_class);
275 if (!trace) {
276 ret = BT_COMPONENT_STATUS_ERROR;
277 goto end;
278 }
279
280 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map) == 0) {
281 /* No clock class: skip the timestamp without an error */
282 goto end;
283 }
284
285 clock_class =
286 bt_clock_class_priority_map_get_highest_priority_clock_class(
287 cc_prio_map);
288 if (!clock_class) {
289 ret = BT_COMPONENT_STATUS_ERROR;
290 goto end;
291 }
292
293 if (print_names) {
294 print_name_equal(pretty, "timestamp");
295 } else {
296 g_string_append(pretty->string, "[");
297 }
298 if (pretty->use_colors) {
299 g_string_append(pretty->string, COLOR_TIMESTAMP);
300 }
301 if (pretty->options.print_timestamp_cycles) {
302 print_timestamp_cycles(pretty, clock_class, event);
303 } else {
304 print_timestamp_wall(pretty, clock_class, event);
305 }
306 if (pretty->use_colors) {
307 g_string_append(pretty->string, COLOR_RST);
308 }
309
310 if (!print_names)
311 g_string_append(pretty->string, "] ");
312
313 if (pretty->options.print_delta_field) {
314 if (print_names) {
315 g_string_append(pretty->string, ", ");
316 print_name_equal(pretty, "delta");
317 } else {
318 g_string_append(pretty->string, "(");
319 }
320 if (pretty->options.print_timestamp_cycles) {
321 if (pretty->delta_cycles == -1ULL) {
322 g_string_append(pretty->string,
323 "+??????????\?\?) "); /* Not a trigraph. */
324 } else {
325 g_string_append_printf(pretty->string,
326 "+%012" PRIu64, pretty->delta_cycles);
327 }
328 } else {
329 if (pretty->delta_real_timestamp != -1ULL) {
330 uint64_t delta_sec, delta_nsec, delta;
331
332 delta = pretty->delta_real_timestamp;
333 delta_sec = delta / NSEC_PER_SEC;
334 delta_nsec = delta % NSEC_PER_SEC;
335 g_string_append_printf(pretty->string,
336 "+%" PRIu64 ".%09" PRIu64,
337 delta_sec, delta_nsec);
338 } else {
339 g_string_append(pretty->string, "+?.?????????");
340 }
341 }
342 if (!print_names) {
343 g_string_append(pretty->string, ") ");
344 }
345 }
346 *start_line = !print_names;
347
348 end:
349 bt_put(stream);
350 bt_put(clock_class);
351 bt_put(stream_class);
352 bt_put(trace);
353 return ret;
354 }
355
356 static
357 enum bt_component_status print_event_header(struct pretty_component *pretty,
358 struct bt_ctf_event *event,
359 struct bt_clock_class_priority_map *cc_prio_map)
360 {
361 bool print_names = pretty->options.print_header_field_names;
362 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
363 struct bt_ctf_event_class *event_class = NULL;
364 struct bt_ctf_stream_class *stream_class = NULL;
365 struct bt_ctf_trace *trace_class = NULL;
366 int dom_print = 0;
367
368 event_class = bt_ctf_event_get_class(event);
369 if (!event_class) {
370 ret = BT_COMPONENT_STATUS_ERROR;
371 goto end;
372 }
373 stream_class = bt_ctf_event_class_get_stream_class(event_class);
374 if (!stream_class) {
375 ret = BT_COMPONENT_STATUS_ERROR;
376 goto end;
377 }
378 trace_class = bt_ctf_stream_class_get_trace(stream_class);
379 if (!trace_class) {
380 ret = BT_COMPONENT_STATUS_ERROR;
381 goto end;
382 }
383 ret = print_event_timestamp(pretty, event, cc_prio_map,
384 &pretty->start_line);
385 if (ret != BT_COMPONENT_STATUS_OK) {
386 goto end;
387 }
388 if (pretty->options.print_trace_field) {
389 const char *name;
390
391 name = bt_ctf_trace_get_name(trace_class);
392 if (name) {
393 if (!pretty->start_line) {
394 g_string_append(pretty->string, ", ");
395 }
396 if (print_names) {
397 print_name_equal(pretty, "trace");
398 }
399
400 g_string_append(pretty->string, name);
401
402 if (!print_names) {
403 g_string_append(pretty->string, " ");
404 }
405 }
406 }
407 if (pretty->options.print_trace_hostname_field) {
408 struct bt_value *hostname_str;
409
410 hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
411 "hostname");
412 if (hostname_str) {
413 const char *str;
414
415 if (!pretty->start_line) {
416 g_string_append(pretty->string, ", ");
417 }
418 if (print_names) {
419 print_name_equal(pretty, "trace:hostname");
420 }
421 if (bt_value_string_get(hostname_str, &str)
422 == BT_VALUE_STATUS_OK) {
423 g_string_append(pretty->string, str);
424 }
425 bt_put(hostname_str);
426 dom_print = 1;
427 }
428 }
429 if (pretty->options.print_trace_domain_field) {
430 struct bt_value *domain_str;
431
432 domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
433 "domain");
434 if (domain_str) {
435 const char *str;
436
437 if (!pretty->start_line) {
438 g_string_append(pretty->string, ", ");
439 }
440 if (print_names) {
441 print_name_equal(pretty, "trace:domain");
442 } else if (dom_print) {
443 g_string_append(pretty->string, ":");
444 }
445 if (bt_value_string_get(domain_str, &str)
446 == BT_VALUE_STATUS_OK) {
447 g_string_append(pretty->string, str);
448 }
449 bt_put(domain_str);
450 dom_print = 1;
451 }
452 }
453 if (pretty->options.print_trace_procname_field) {
454 struct bt_value *procname_str;
455
456 procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
457 "procname");
458 if (procname_str) {
459 const char *str;
460
461 if (!pretty->start_line) {
462 g_string_append(pretty->string, ", ");
463 }
464 if (print_names) {
465 print_name_equal(pretty, "trace:procname");
466 } else if (dom_print) {
467 g_string_append(pretty->string, ":");
468 }
469 if (bt_value_string_get(procname_str, &str)
470 == BT_VALUE_STATUS_OK) {
471 g_string_append(pretty->string, str);
472 }
473 bt_put(procname_str);
474 dom_print = 1;
475 }
476 }
477 if (pretty->options.print_trace_vpid_field) {
478 struct bt_value *vpid_value;
479
480 vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
481 "vpid");
482 if (vpid_value) {
483 int64_t value;
484
485 if (!pretty->start_line) {
486 g_string_append(pretty->string, ", ");
487 }
488 if (print_names) {
489 print_name_equal(pretty, "trace:vpid");
490 } else if (dom_print) {
491 g_string_append(pretty->string, ":");
492 }
493 if (bt_value_integer_get(vpid_value, &value)
494 == BT_VALUE_STATUS_OK) {
495 g_string_append_printf(pretty->string, "(%" PRId64 ")", value);
496 }
497 bt_put(vpid_value);
498 dom_print = 1;
499 }
500 }
501 if (pretty->options.print_loglevel_field) {
502 struct bt_value *loglevel_str, *loglevel_value;
503
504 loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
505 "loglevel_string");
506 loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class,
507 "loglevel");
508 if (loglevel_str || loglevel_value) {
509 bool has_str = false;
510
511 if (!pretty->start_line) {
512 g_string_append(pretty->string, ", ");
513 }
514 if (print_names) {
515 print_name_equal(pretty, "loglevel");
516 } else if (dom_print) {
517 g_string_append(pretty->string, ":");
518 }
519 if (loglevel_str) {
520 const char *str;
521
522 if (bt_value_string_get(loglevel_str, &str)
523 == BT_VALUE_STATUS_OK) {
524 g_string_append(pretty->string, str);
525 has_str = true;
526 }
527 }
528 if (loglevel_value) {
529 int64_t value;
530
531 if (bt_value_integer_get(loglevel_value, &value)
532 == BT_VALUE_STATUS_OK) {
533 g_string_append_printf(pretty->string, "%s(%" PRId64 ")",
534 has_str ? " " : "", value);
535 }
536 }
537 bt_put(loglevel_str);
538 bt_put(loglevel_value);
539 dom_print = 1;
540 }
541 }
542 if (pretty->options.print_emf_field) {
543 struct bt_value *uri_str;
544
545 uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
546 "model.emf.uri");
547 if (uri_str) {
548 if (!pretty->start_line) {
549 g_string_append(pretty->string, ", ");
550 }
551 if (print_names) {
552 print_name_equal(pretty, "model.emf.uri");
553 } else if (dom_print) {
554 g_string_append(pretty->string, ":");
555 }
556 if (uri_str) {
557 const char *str;
558
559 if (bt_value_string_get(uri_str, &str)
560 == BT_VALUE_STATUS_OK) {
561 g_string_append(pretty->string, str);
562 }
563 }
564 bt_put(uri_str);
565 dom_print = 1;
566 }
567 }
568 if (dom_print && !print_names) {
569 g_string_append(pretty->string, " ");
570 }
571 if (!pretty->start_line) {
572 g_string_append(pretty->string, ", ");
573 }
574 pretty->start_line = true;
575 if (print_names) {
576 print_name_equal(pretty, "name");
577 }
578 if (pretty->use_colors) {
579 g_string_append(pretty->string, COLOR_EVENT_NAME);
580 }
581 g_string_append(pretty->string, bt_ctf_event_class_get_name(event_class));
582 if (pretty->use_colors) {
583 g_string_append(pretty->string, COLOR_RST);
584 }
585 if (!print_names) {
586 g_string_append(pretty->string, ": ");
587 } else {
588 g_string_append(pretty->string, ", ");
589 }
590 end:
591 bt_put(trace_class);
592 bt_put(stream_class);
593 bt_put(event_class);
594 return ret;
595 }
596
597 static
598 enum bt_component_status print_integer(struct pretty_component *pretty,
599 struct bt_ctf_field *field)
600 {
601 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
602 struct bt_ctf_field_type *field_type = NULL;
603 enum bt_ctf_integer_base base;
604 enum bt_ctf_string_encoding encoding;
605 int signedness;
606 union {
607 uint64_t u;
608 int64_t s;
609 } v;
610 bool rst_color = false;
611
612 field_type = bt_ctf_field_get_type(field);
613 if (!field_type) {
614 ret = BT_COMPONENT_STATUS_ERROR;
615 goto end;
616 }
617 signedness = bt_ctf_field_type_integer_get_signed(field_type);
618 if (signedness < 0) {
619 ret = BT_COMPONENT_STATUS_ERROR;
620 goto end;
621 }
622 if (!signedness) {
623 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
624 ret = BT_COMPONENT_STATUS_ERROR;
625 goto end;
626 }
627 } else {
628 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
629 ret = BT_COMPONENT_STATUS_ERROR;
630 goto end;
631 }
632 }
633
634 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
635 switch (encoding) {
636 case BT_CTF_STRING_ENCODING_UTF8:
637 case BT_CTF_STRING_ENCODING_ASCII:
638 g_string_append_c(pretty->tmp_string, (int) v.u);
639 goto end;
640 case BT_CTF_STRING_ENCODING_NONE:
641 case BT_CTF_STRING_ENCODING_UNKNOWN:
642 break;
643 default:
644 ret = BT_COMPONENT_STATUS_ERROR;
645 goto end;
646 }
647
648 if (pretty->use_colors) {
649 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
650 rst_color = true;
651 }
652
653 base = bt_ctf_field_type_integer_get_base(field_type);
654 switch (base) {
655 case BT_CTF_INTEGER_BASE_BINARY:
656 {
657 int bitnr, len;
658
659 len = bt_ctf_field_type_integer_get_size(field_type);
660 if (len < 0) {
661 ret = BT_COMPONENT_STATUS_ERROR;
662 goto end;
663 }
664 g_string_append(pretty->string, "0b");
665 v.u = _bt_piecewise_lshift(v.u, 64 - len);
666 for (bitnr = 0; bitnr < len; bitnr++) {
667 g_string_append_printf(pretty->string, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
668 v.u = _bt_piecewise_lshift(v.u, 1);
669 }
670 break;
671 }
672 case BT_CTF_INTEGER_BASE_OCTAL:
673 {
674 if (signedness) {
675 int len;
676
677 len = bt_ctf_field_type_integer_get_size(field_type);
678 if (len < 0) {
679 ret = BT_COMPONENT_STATUS_ERROR;
680 goto end;
681 }
682 if (len < 64) {
683 size_t rounded_len;
684
685 assert(len != 0);
686 /* Round length to the nearest 3-bit */
687 rounded_len = (((len - 1) / 3) + 1) * 3;
688 v.u &= ((uint64_t) 1 << rounded_len) - 1;
689 }
690 }
691
692 g_string_append_printf(pretty->string, "0%" PRIo64, v.u);
693 break;
694 }
695 case BT_CTF_INTEGER_BASE_DECIMAL:
696 case BT_CTF_INTEGER_BASE_UNSPECIFIED:
697 if (!signedness) {
698 g_string_append_printf(pretty->string, "%" PRIu64, v.u);
699 } else {
700 g_string_append_printf(pretty->string, "%" PRId64, v.s);
701 }
702 break;
703 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
704 {
705 int len;
706
707 len = bt_ctf_field_type_integer_get_size(field_type);
708 if (len < 0) {
709 ret = BT_COMPONENT_STATUS_ERROR;
710 goto end;
711 }
712 if (len < 64) {
713 /* Round length to the nearest nibble */
714 uint8_t rounded_len = ((len + 3) & ~0x3);
715
716 v.u &= ((uint64_t) 1 << rounded_len) - 1;
717 }
718
719 g_string_append_printf(pretty->string, "0x%" PRIX64, v.u);
720 break;
721 }
722 default:
723 ret = BT_COMPONENT_STATUS_ERROR;
724 goto end;
725 }
726 end:
727 if (rst_color) {
728 g_string_append(pretty->string, COLOR_RST);
729 }
730 bt_put(field_type);
731 return ret;
732 }
733
734 static
735 void print_escape_string(struct pretty_component *pretty, const char *str)
736 {
737 int i;
738
739 g_string_append_c(pretty->string, '"');
740
741 for (i = 0; i < strlen(str); i++) {
742 /* Escape sequences not recognized by iscntrl(). */
743 switch (str[i]) {
744 case '\\':
745 g_string_append(pretty->string, "\\\\");
746 continue;
747 case '\'':
748 g_string_append(pretty->string, "\\\'");
749 continue;
750 case '\"':
751 g_string_append(pretty->string, "\\\"");
752 continue;
753 case '\?':
754 g_string_append(pretty->string, "\\\?");
755 continue;
756 }
757
758 /* Standard characters. */
759 if (!iscntrl(str[i])) {
760 g_string_append_c(pretty->string, str[i]);
761 continue;
762 }
763
764 switch (str[i]) {
765 case '\0':
766 g_string_append(pretty->string, "\\0");
767 break;
768 case '\a':
769 g_string_append(pretty->string, "\\a");
770 break;
771 case '\b':
772 g_string_append(pretty->string, "\\b");
773 break;
774 case '\e':
775 g_string_append(pretty->string, "\\e");
776 break;
777 case '\f':
778 g_string_append(pretty->string, "\\f");
779 break;
780 case '\n':
781 g_string_append(pretty->string, "\\n");
782 break;
783 case '\r':
784 g_string_append(pretty->string, "\\r");
785 break;
786 case '\t':
787 g_string_append(pretty->string, "\\t");
788 break;
789 case '\v':
790 g_string_append(pretty->string, "\\v");
791 break;
792 default:
793 /* Unhandled control-sequence, print as hex. */
794 g_string_append_printf(pretty->string, "\\x%02x", str[i]);
795 break;
796 }
797 }
798
799 g_string_append_c(pretty->string, '"');
800 }
801
802 static
803 enum bt_component_status print_enum(struct pretty_component *pretty,
804 struct bt_ctf_field *field)
805 {
806 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
807 struct bt_ctf_field *container_field = NULL;
808 struct bt_ctf_field_type *enumeration_field_type = NULL;
809 struct bt_ctf_field_type *container_field_type = NULL;
810 struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
811 int nr_mappings = 0;
812 int is_signed;
813
814 enumeration_field_type = bt_ctf_field_get_type(field);
815 if (!enumeration_field_type) {
816 ret = BT_COMPONENT_STATUS_ERROR;
817 goto end;
818 }
819 container_field = bt_ctf_field_enumeration_get_container(field);
820 if (!container_field) {
821 ret = BT_COMPONENT_STATUS_ERROR;
822 goto end;
823 }
824 container_field_type = bt_ctf_field_get_type(container_field);
825 if (!container_field_type) {
826 ret = BT_COMPONENT_STATUS_ERROR;
827 goto end;
828 }
829 is_signed = bt_ctf_field_type_integer_get_signed(container_field_type);
830 if (is_signed < 0) {
831 ret = BT_COMPONENT_STATUS_ERROR;
832 goto end;
833 }
834 if (is_signed) {
835 int64_t value;
836
837 if (bt_ctf_field_signed_integer_get_value(container_field,
838 &value)) {
839 ret = BT_COMPONENT_STATUS_ERROR;
840 goto end;
841 }
842 iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
843 enumeration_field_type, value);
844 } else {
845 uint64_t value;
846
847 if (bt_ctf_field_unsigned_integer_get_value(container_field,
848 &value)) {
849 ret = BT_COMPONENT_STATUS_ERROR;
850 goto end;
851 }
852 iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
853 enumeration_field_type, value);
854 }
855 if (!iter) {
856 ret = BT_COMPONENT_STATUS_ERROR;
857 goto end;
858 }
859 g_string_append(pretty->string, "( ");
860 for (;;) {
861 const char *mapping_name;
862
863 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
864 iter, &mapping_name, NULL, NULL) < 0) {
865 ret = BT_COMPONENT_STATUS_ERROR;
866 goto end;
867 }
868 if (nr_mappings++)
869 g_string_append(pretty->string, ", ");
870 if (pretty->use_colors) {
871 g_string_append(pretty->string, COLOR_ENUM_MAPPING_NAME);
872 }
873 print_escape_string(pretty, mapping_name);
874 if (pretty->use_colors) {
875 g_string_append(pretty->string, COLOR_RST);
876 }
877 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) {
878 break;
879 }
880 }
881 if (!nr_mappings) {
882 if (pretty->use_colors) {
883 g_string_append(pretty->string, COLOR_UNKNOWN);
884 }
885 g_string_append(pretty->string, "<unknown>");
886 if (pretty->use_colors) {
887 g_string_append(pretty->string, COLOR_RST);
888 }
889 }
890 g_string_append(pretty->string, " : container = ");
891 ret = print_integer(pretty, container_field);
892 if (ret != BT_COMPONENT_STATUS_OK) {
893 goto end;
894 }
895 g_string_append(pretty->string, " )");
896 end:
897 bt_put(iter);
898 bt_put(container_field_type);
899 bt_put(container_field);
900 bt_put(enumeration_field_type);
901 return ret;
902 }
903
904 static
905 int filter_field_name(struct pretty_component *pretty, const char *field_name,
906 GQuark *filter_fields, int filter_array_len)
907 {
908 int i;
909 GQuark field_quark = g_quark_try_string(field_name);
910
911 if (!field_quark || pretty->options.verbose) {
912 return 1;
913 }
914
915 for (i = 0; i < filter_array_len; i++) {
916 if (field_quark == filter_fields[i]) {
917 return 0;
918 }
919 }
920 return 1;
921 }
922
923 static
924 enum bt_component_status print_struct_field(struct pretty_component *pretty,
925 struct bt_ctf_field *_struct,
926 struct bt_ctf_field_type *struct_type,
927 int i, bool print_names, int *nr_printed_fields,
928 GQuark *filter_fields, int filter_array_len)
929 {
930 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
931 const char *field_name;
932 struct bt_ctf_field *field = NULL;
933 struct bt_ctf_field_type *field_type = NULL;;
934
935 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
936 if (!field) {
937 ret = BT_COMPONENT_STATUS_ERROR;
938 goto end;
939 }
940 if (bt_ctf_field_type_structure_get_field(struct_type,
941 &field_name, &field_type, i) < 0) {
942 ret = BT_COMPONENT_STATUS_ERROR;
943 goto end;
944 }
945
946 if (filter_fields && !filter_field_name(pretty, field_name,
947 filter_fields, filter_array_len)) {
948 ret = BT_COMPONENT_STATUS_OK;
949 goto end;
950 }
951
952 if (*nr_printed_fields > 0) {
953 g_string_append(pretty->string, ", ");
954 } else {
955 g_string_append(pretty->string, " ");
956 }
957 if (print_names) {
958 print_field_name_equal(pretty, rem_(field_name));
959 }
960 ret = print_field(pretty, field, print_names, NULL, 0);
961 *nr_printed_fields += 1;
962 end:
963 bt_put(field_type);
964 bt_put(field);
965 return ret;
966 }
967
968 static
969 enum bt_component_status print_struct(struct pretty_component *pretty,
970 struct bt_ctf_field *_struct, bool print_names,
971 GQuark *filter_fields, int filter_array_len)
972 {
973 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
974 struct bt_ctf_field_type *struct_type = NULL;
975 int nr_fields, i, nr_printed_fields;
976
977 struct_type = bt_ctf_field_get_type(_struct);
978 if (!struct_type) {
979 ret = BT_COMPONENT_STATUS_ERROR;
980 goto end;
981 }
982 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
983 if (nr_fields < 0) {
984 ret = BT_COMPONENT_STATUS_ERROR;
985 goto end;
986 }
987 g_string_append(pretty->string, "{");
988 pretty->depth++;
989 nr_printed_fields = 0;
990 for (i = 0; i < nr_fields; i++) {
991 ret = print_struct_field(pretty, _struct, struct_type, i,
992 print_names, &nr_printed_fields, filter_fields,
993 filter_array_len);
994 if (ret != BT_COMPONENT_STATUS_OK) {
995 goto end;
996 }
997 }
998 pretty->depth--;
999 g_string_append(pretty->string, " }");
1000 end:
1001 bt_put(struct_type);
1002 return ret;
1003 }
1004
1005 static
1006 enum bt_component_status print_array_field(struct pretty_component *pretty,
1007 struct bt_ctf_field *array, uint64_t i,
1008 bool is_string, bool print_names)
1009 {
1010 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1011 struct bt_ctf_field *field = NULL;
1012
1013 if (!is_string) {
1014 if (i != 0) {
1015 g_string_append(pretty->string, ", ");
1016 } else {
1017 g_string_append(pretty->string, " ");
1018 }
1019 if (print_names) {
1020 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1021 }
1022 }
1023 field = bt_ctf_field_array_get_field(array, i);
1024 if (!field) {
1025 ret = BT_COMPONENT_STATUS_ERROR;
1026 goto end;
1027 }
1028 ret = print_field(pretty, field, print_names, NULL, 0);
1029 end:
1030 bt_put(field);
1031 return ret;
1032 }
1033
1034 static
1035 enum bt_component_status print_array(struct pretty_component *pretty,
1036 struct bt_ctf_field *array, bool print_names)
1037 {
1038 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1039 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
1040 enum bt_ctf_field_type_id type_id;
1041 int64_t len;
1042 uint64_t i;
1043 bool is_string = false;
1044
1045 array_type = bt_ctf_field_get_type(array);
1046 if (!array_type) {
1047 ret = BT_COMPONENT_STATUS_ERROR;
1048 goto end;
1049 }
1050 field_type = bt_ctf_field_type_array_get_element_type(array_type);
1051 if (!field_type) {
1052 ret = BT_COMPONENT_STATUS_ERROR;
1053 goto end;
1054 }
1055 len = bt_ctf_field_type_array_get_length(array_type);
1056 if (len < 0) {
1057 ret = BT_COMPONENT_STATUS_ERROR;
1058 goto end;
1059 }
1060 type_id = bt_ctf_field_type_get_type_id(field_type);
1061 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1062 enum bt_ctf_string_encoding encoding;
1063
1064 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1065 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1066 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1067 int integer_len, integer_alignment;
1068
1069 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1070 if (integer_len < 0) {
1071 return BT_COMPONENT_STATUS_ERROR;
1072 }
1073 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1074 if (integer_alignment < 0) {
1075 return BT_COMPONENT_STATUS_ERROR;
1076 }
1077 if (integer_len == CHAR_BIT
1078 && integer_alignment == CHAR_BIT) {
1079 is_string = true;
1080 }
1081 }
1082 }
1083
1084 if (is_string) {
1085 g_string_assign(pretty->tmp_string, "");
1086 } else {
1087 g_string_append(pretty->string, "[");
1088 }
1089
1090 pretty->depth++;
1091 for (i = 0; i < len; i++) {
1092 ret = print_array_field(pretty, array, i, is_string, print_names);
1093 if (ret != BT_COMPONENT_STATUS_OK) {
1094 goto end;
1095 }
1096 }
1097 pretty->depth--;
1098
1099 if (is_string) {
1100 if (pretty->use_colors) {
1101 g_string_append(pretty->string, COLOR_STRING_VALUE);
1102 }
1103 print_escape_string(pretty, pretty->tmp_string->str);
1104 if (pretty->use_colors) {
1105 g_string_append(pretty->string, COLOR_RST);
1106 }
1107 } else {
1108 g_string_append(pretty->string, " ]");
1109 }
1110 end:
1111 bt_put(field_type);
1112 bt_put(array_type);
1113 return ret;
1114 }
1115
1116 static
1117 enum bt_component_status print_sequence_field(struct pretty_component *pretty,
1118 struct bt_ctf_field *seq, uint64_t i,
1119 bool is_string, bool print_names)
1120 {
1121 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1122 struct bt_ctf_field *field = NULL;
1123
1124 if (!is_string) {
1125 if (i != 0) {
1126 g_string_append(pretty->string, ", ");
1127 } else {
1128 g_string_append(pretty->string, " ");
1129 }
1130 if (print_names) {
1131 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1132 }
1133 }
1134 field = bt_ctf_field_sequence_get_field(seq, i);
1135 if (!field) {
1136 ret = BT_COMPONENT_STATUS_ERROR;
1137 goto end;
1138 }
1139 ret = print_field(pretty, field, print_names, NULL, 0);
1140 end:
1141 bt_put(field);
1142 return ret;
1143 }
1144
1145 static
1146 enum bt_component_status print_sequence(struct pretty_component *pretty,
1147 struct bt_ctf_field *seq, bool print_names)
1148 {
1149 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1150 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
1151 struct bt_ctf_field *length_field = NULL;
1152 enum bt_ctf_field_type_id type_id;
1153 uint64_t len;
1154 uint64_t i;
1155 bool is_string = false;
1156
1157 seq_type = bt_ctf_field_get_type(seq);
1158 if (!seq_type) {
1159 ret = BT_COMPONENT_STATUS_ERROR;
1160 goto end;
1161 }
1162 length_field = bt_ctf_field_sequence_get_length(seq);
1163 if (!length_field) {
1164 ret = BT_COMPONENT_STATUS_ERROR;
1165 goto end;
1166 }
1167 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
1168 ret = BT_COMPONENT_STATUS_ERROR;
1169 goto end;
1170 }
1171 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
1172 if (!field_type) {
1173 ret = BT_COMPONENT_STATUS_ERROR;
1174 goto end;
1175 }
1176 type_id = bt_ctf_field_type_get_type_id(field_type);
1177 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1178 enum bt_ctf_string_encoding encoding;
1179
1180 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1181 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1182 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1183 int integer_len, integer_alignment;
1184
1185 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1186 if (integer_len < 0) {
1187 ret = BT_COMPONENT_STATUS_ERROR;
1188 goto end;
1189 }
1190 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1191 if (integer_alignment < 0) {
1192 ret = BT_COMPONENT_STATUS_ERROR;
1193 goto end;
1194 }
1195 if (integer_len == CHAR_BIT
1196 && integer_alignment == CHAR_BIT) {
1197 is_string = true;
1198 }
1199 }
1200 }
1201
1202 if (is_string) {
1203 g_string_assign(pretty->tmp_string, "");
1204 } else {
1205 g_string_append(pretty->string, "[");
1206 }
1207
1208 pretty->depth++;
1209 for (i = 0; i < len; i++) {
1210 ret = print_sequence_field(pretty, seq, i,
1211 is_string, print_names);
1212 if (ret != BT_COMPONENT_STATUS_OK) {
1213 goto end;
1214 }
1215 }
1216 pretty->depth--;
1217
1218 if (is_string) {
1219 if (pretty->use_colors) {
1220 g_string_append(pretty->string, COLOR_STRING_VALUE);
1221 }
1222 print_escape_string(pretty, pretty->tmp_string->str);
1223 if (pretty->use_colors) {
1224 g_string_append(pretty->string, COLOR_RST);
1225 }
1226 } else {
1227 g_string_append(pretty->string, " ]");
1228 }
1229 end:
1230 bt_put(length_field);
1231 bt_put(field_type);
1232 bt_put(seq_type);
1233 return ret;
1234 }
1235
1236 static
1237 enum bt_component_status print_variant(struct pretty_component *pretty,
1238 struct bt_ctf_field *variant, bool print_names)
1239 {
1240 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1241 struct bt_ctf_field *field = NULL;
1242
1243 field = bt_ctf_field_variant_get_current_field(variant);
1244 if (!field) {
1245 ret = BT_COMPONENT_STATUS_ERROR;
1246 goto end;
1247 }
1248 g_string_append(pretty->string, "{ ");
1249 pretty->depth++;
1250 if (print_names) {
1251 int iter_ret;
1252 struct bt_ctf_field *tag_field = NULL;
1253 const char *tag_choice;
1254 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
1255
1256 tag_field = bt_ctf_field_variant_get_tag(variant);
1257 if (!tag_field) {
1258 ret = BT_COMPONENT_STATUS_ERROR;
1259 goto end;
1260 }
1261
1262 iter = bt_ctf_field_enumeration_get_mappings(tag_field);
1263 if (!iter) {
1264 bt_put(tag_field);
1265 ret = BT_COMPONENT_STATUS_ERROR;
1266 goto end;
1267 }
1268
1269 iter_ret =
1270 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1271 iter, &tag_choice, NULL, NULL);
1272 if (iter_ret) {
1273 bt_put(iter);
1274 bt_put(tag_field);
1275 ret = BT_COMPONENT_STATUS_ERROR;
1276 goto end;
1277 }
1278 print_field_name_equal(pretty, rem_(tag_choice));
1279 bt_put(tag_field);
1280 bt_put(iter);
1281 }
1282 ret = print_field(pretty, field, print_names, NULL, 0);
1283 if (ret != BT_COMPONENT_STATUS_OK) {
1284 goto end;
1285 }
1286 pretty->depth--;
1287 g_string_append(pretty->string, " }");
1288 end:
1289 bt_put(field);
1290 return ret;
1291 }
1292
1293 static
1294 enum bt_component_status print_field(struct pretty_component *pretty,
1295 struct bt_ctf_field *field, bool print_names,
1296 GQuark *filter_fields, int filter_array_len)
1297 {
1298 enum bt_ctf_field_type_id type_id;
1299
1300 type_id = bt_ctf_field_get_type_id(field);
1301 switch (type_id) {
1302 case CTF_TYPE_INTEGER:
1303 return print_integer(pretty, field);
1304 case CTF_TYPE_FLOAT:
1305 {
1306 double v;
1307
1308 if (bt_ctf_field_floating_point_get_value(field, &v)) {
1309 return BT_COMPONENT_STATUS_ERROR;
1310 }
1311 if (pretty->use_colors) {
1312 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
1313 }
1314 g_string_append_printf(pretty->string, "%g", v);
1315 if (pretty->use_colors) {
1316 g_string_append(pretty->string, COLOR_RST);
1317 }
1318 return BT_COMPONENT_STATUS_OK;
1319 }
1320 case CTF_TYPE_ENUM:
1321 return print_enum(pretty, field);
1322 case CTF_TYPE_STRING:
1323 if (pretty->use_colors) {
1324 g_string_append(pretty->string, COLOR_STRING_VALUE);
1325 }
1326 print_escape_string(pretty, bt_ctf_field_string_get_value(field));
1327 if (pretty->use_colors) {
1328 g_string_append(pretty->string, COLOR_RST);
1329 }
1330 return BT_COMPONENT_STATUS_OK;
1331 case CTF_TYPE_STRUCT:
1332 return print_struct(pretty, field, print_names, filter_fields,
1333 filter_array_len);
1334 case CTF_TYPE_VARIANT:
1335 return print_variant(pretty, field, print_names);
1336 case CTF_TYPE_ARRAY:
1337 return print_array(pretty, field, print_names);
1338 case CTF_TYPE_SEQUENCE:
1339 return print_sequence(pretty, field, print_names);
1340 default:
1341 // TODO: log instead
1342 fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id);
1343 return BT_COMPONENT_STATUS_ERROR;
1344 }
1345 }
1346
1347 static
1348 enum bt_component_status print_stream_packet_context(struct pretty_component *pretty,
1349 struct bt_ctf_event *event)
1350 {
1351 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1352 struct bt_ctf_packet *packet = NULL;
1353 struct bt_ctf_field *main_field = NULL;
1354
1355 packet = bt_ctf_event_get_packet(event);
1356 if (!packet) {
1357 ret = BT_COMPONENT_STATUS_ERROR;
1358 goto end;
1359 }
1360 main_field = bt_ctf_packet_get_context(packet);
1361 if (!main_field) {
1362 goto end;
1363 }
1364 if (!pretty->start_line) {
1365 g_string_append(pretty->string, ", ");
1366 }
1367 pretty->start_line = false;
1368 if (pretty->options.print_scope_field_names) {
1369 print_name_equal(pretty, "stream.packet.context");
1370 }
1371 ret = print_field(pretty, main_field,
1372 pretty->options.print_context_field_names,
1373 stream_packet_context_quarks,
1374 STREAM_PACKET_CONTEXT_QUARKS_LEN);
1375 end:
1376 bt_put(main_field);
1377 bt_put(packet);
1378 return ret;
1379 }
1380
1381 static
1382 enum bt_component_status print_event_header_raw(struct pretty_component *pretty,
1383 struct bt_ctf_event *event)
1384 {
1385 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1386 struct bt_ctf_field *main_field = NULL;
1387
1388 main_field = bt_ctf_event_get_header(event);
1389 if (!main_field) {
1390 goto end;
1391 }
1392 if (!pretty->start_line) {
1393 g_string_append(pretty->string, ", ");
1394 }
1395 pretty->start_line = false;
1396 if (pretty->options.print_scope_field_names) {
1397 print_name_equal(pretty, "stream.event.header");
1398 }
1399 ret = print_field(pretty, main_field,
1400 pretty->options.print_header_field_names, NULL, 0);
1401 end:
1402 bt_put(main_field);
1403 return ret;
1404 }
1405
1406 static
1407 enum bt_component_status print_stream_event_context(struct pretty_component *pretty,
1408 struct bt_ctf_event *event)
1409 {
1410 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1411 struct bt_ctf_field *main_field = NULL;
1412
1413 main_field = bt_ctf_event_get_stream_event_context(event);
1414 if (!main_field) {
1415 goto end;
1416 }
1417 if (!pretty->start_line) {
1418 g_string_append(pretty->string, ", ");
1419 }
1420 pretty->start_line = false;
1421 if (pretty->options.print_scope_field_names) {
1422 print_name_equal(pretty, "stream.event.context");
1423 }
1424 ret = print_field(pretty, main_field,
1425 pretty->options.print_context_field_names, NULL, 0);
1426 end:
1427 bt_put(main_field);
1428 return ret;
1429 }
1430
1431 static
1432 enum bt_component_status print_event_context(struct pretty_component *pretty,
1433 struct bt_ctf_event *event)
1434 {
1435 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1436 struct bt_ctf_field *main_field = NULL;
1437
1438 main_field = bt_ctf_event_get_event_context(event);
1439 if (!main_field) {
1440 goto end;
1441 }
1442 if (!pretty->start_line) {
1443 g_string_append(pretty->string, ", ");
1444 }
1445 pretty->start_line = false;
1446 if (pretty->options.print_scope_field_names) {
1447 print_name_equal(pretty, "event.context");
1448 }
1449 ret = print_field(pretty, main_field,
1450 pretty->options.print_context_field_names, NULL, 0);
1451 end:
1452 bt_put(main_field);
1453 return ret;
1454 }
1455
1456 static
1457 enum bt_component_status print_event_payload(struct pretty_component *pretty,
1458 struct bt_ctf_event *event)
1459 {
1460 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1461 struct bt_ctf_field *main_field = NULL;
1462
1463 main_field = bt_ctf_event_get_event_payload(event);
1464 if (!main_field) {
1465 goto end;
1466 }
1467 if (!pretty->start_line) {
1468 g_string_append(pretty->string, ", ");
1469 }
1470 pretty->start_line = false;
1471 if (pretty->options.print_scope_field_names) {
1472 print_name_equal(pretty, "event.fields");
1473 }
1474 ret = print_field(pretty, main_field,
1475 pretty->options.print_payload_field_names, NULL, 0);
1476 end:
1477 bt_put(main_field);
1478 return ret;
1479 }
1480
1481 BT_HIDDEN
1482 enum bt_component_status pretty_print_event(struct pretty_component *pretty,
1483 struct bt_notification *event_notif)
1484 {
1485 enum bt_component_status ret;
1486 struct bt_ctf_event *event =
1487 bt_notification_event_get_event(event_notif);
1488 struct bt_clock_class_priority_map *cc_prio_map =
1489 bt_notification_event_get_clock_class_priority_map(event_notif);
1490
1491 assert(event);
1492 assert(cc_prio_map);
1493 pretty->start_line = true;
1494 g_string_assign(pretty->string, "");
1495 ret = print_event_header(pretty, event, cc_prio_map);
1496 if (ret != BT_COMPONENT_STATUS_OK) {
1497 goto end;
1498 }
1499
1500 ret = print_stream_packet_context(pretty, event);
1501 if (ret != BT_COMPONENT_STATUS_OK) {
1502 goto end;
1503 }
1504
1505 if (pretty->options.verbose) {
1506 ret = print_event_header_raw(pretty, event);
1507 if (ret != BT_COMPONENT_STATUS_OK) {
1508 goto end;
1509 }
1510 }
1511
1512 ret = print_stream_event_context(pretty, event);
1513 if (ret != BT_COMPONENT_STATUS_OK) {
1514 goto end;
1515 }
1516
1517 ret = print_event_context(pretty, event);
1518 if (ret != BT_COMPONENT_STATUS_OK) {
1519 goto end;
1520 }
1521
1522 ret = print_event_payload(pretty, event);
1523 if (ret != BT_COMPONENT_STATUS_OK) {
1524 goto end;
1525 }
1526
1527 g_string_append_c(pretty->string, '\n');
1528 if (fwrite(pretty->string->str, pretty->string->len, 1, pretty->out) != 1) {
1529 ret = BT_COMPONENT_STATUS_ERROR;
1530 goto end;
1531 }
1532
1533 end:
1534 bt_put(event);
1535 bt_put(cc_prio_map);
1536 return ret;
1537 }
This page took 0.073025 seconds and 5 git commands to generate.