Replace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()
[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/babeltrace.h>
31 #include <babeltrace/bitfield-internal.h>
32 #include <babeltrace/common-internal.h>
33 #include <babeltrace/compat/time-internal.h>
34 #include <babeltrace/assert-internal.h>
35 #include <inttypes.h>
36 #include <ctype.h>
37 #include "pretty.h"
38
39 #define NSEC_PER_SEC 1000000000LL
40
41 #define COLOR_NAME BT_COMMON_COLOR_BOLD
42 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
43 #define COLOR_RST BT_COMMON_COLOR_RESET
44 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
45 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
46 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
47 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
48 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
49 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
50
51 struct timestamp {
52 int64_t real_timestamp; /* Relative to UNIX epoch. */
53 uint64_t clock_value; /* In cycles. */
54 };
55
56 static
57 enum bt_component_status print_field(struct pretty_component *pretty,
58 struct bt_field *field, bool print_names,
59 GQuark *filters_fields, int filter_array_len);
60
61 static
62 void print_name_equal(struct pretty_component *pretty, const char *name)
63 {
64 if (pretty->use_colors) {
65 g_string_append_printf(pretty->string, "%s%s%s = ", COLOR_NAME,
66 name, COLOR_RST);
67 } else {
68 g_string_append_printf(pretty->string, "%s = ", name);
69 }
70 }
71
72 static
73 void print_field_name_equal(struct pretty_component *pretty, const char *name)
74 {
75 if (pretty->use_colors) {
76 g_string_append_printf(pretty->string, "%s%s%s = ",
77 COLOR_FIELD_NAME, name, COLOR_RST);
78 } else {
79 g_string_append_printf(pretty->string, "%s = ", name);
80 }
81 }
82
83 static
84 void print_timestamp_cycles(struct pretty_component *pretty,
85 struct bt_clock_class *clock_class,
86 struct bt_event *event)
87 {
88 int ret;
89 struct bt_clock_value *clock_value;
90 uint64_t cycles;
91
92 clock_value = bt_event_get_clock_value(event, clock_class);
93 if (!clock_value) {
94 g_string_append(pretty->string, "????????????????????");
95 return;
96 }
97
98 ret = bt_clock_value_get_value(clock_value, &cycles);
99 bt_put(clock_value);
100 if (ret) {
101 // TODO: log, this is unexpected
102 g_string_append(pretty->string, "Error");
103 return;
104 }
105
106 g_string_append_printf(pretty->string, "%020" PRIu64, cycles);
107
108 if (pretty->last_cycles_timestamp != -1ULL) {
109 pretty->delta_cycles = cycles - pretty->last_cycles_timestamp;
110 }
111 pretty->last_cycles_timestamp = cycles;
112 }
113
114 static
115 void print_timestamp_wall(struct pretty_component *pretty,
116 struct bt_clock_value *clock_value)
117 {
118 int ret;
119 int64_t ts_nsec = 0; /* add configurable offset */
120 int64_t ts_sec = 0; /* add configurable offset */
121 uint64_t ts_sec_abs, ts_nsec_abs;
122 bool is_negative;
123
124 if (!clock_value) {
125 g_string_append(pretty->string, "??:??:??.?????????");
126 return;
127 }
128
129 ret = bt_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
130 if (ret) {
131 // TODO: log, this is unexpected
132 g_string_append(pretty->string, "Error");
133 return;
134 }
135
136 if (pretty->last_real_timestamp != -1ULL) {
137 pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp;
138 }
139
140 pretty->last_real_timestamp = ts_nsec;
141 ts_sec += ts_nsec / NSEC_PER_SEC;
142 ts_nsec = ts_nsec % NSEC_PER_SEC;
143
144 if (ts_sec >= 0 && ts_nsec >= 0) {
145 is_negative = false;
146 ts_sec_abs = ts_sec;
147 ts_nsec_abs = ts_nsec;
148 } else if (ts_sec > 0 && ts_nsec < 0) {
149 is_negative = false;
150 ts_sec_abs = ts_sec - 1;
151 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
152 } else if (ts_sec == 0 && ts_nsec < 0) {
153 is_negative = true;
154 ts_sec_abs = ts_sec;
155 ts_nsec_abs = -ts_nsec;
156 } else if (ts_sec < 0 && ts_nsec > 0) {
157 is_negative = true;
158 ts_sec_abs = -(ts_sec + 1);
159 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
160 } else if (ts_sec < 0 && ts_nsec == 0) {
161 is_negative = true;
162 ts_sec_abs = -ts_sec;
163 ts_nsec_abs = ts_nsec;
164 } else { /* (ts_sec < 0 && ts_nsec < 0) */
165 is_negative = true;
166 ts_sec_abs = -ts_sec;
167 ts_nsec_abs = -ts_nsec;
168 }
169
170 if (!pretty->options.clock_seconds) {
171 struct tm tm;
172 time_t time_s = (time_t) ts_sec_abs;
173
174 if (is_negative && !pretty->negative_timestamp_warning_done) {
175 // TODO: log instead
176 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
177 pretty->negative_timestamp_warning_done = true;
178 goto seconds;
179 }
180
181 if (!pretty->options.clock_gmt) {
182 struct tm *res;
183
184 res = bt_localtime_r(&time_s, &tm);
185 if (!res) {
186 // TODO: log instead
187 fprintf(stderr, "[warning] Unable to get localtime.\n");
188 goto seconds;
189 }
190 } else {
191 struct tm *res;
192
193 res = bt_gmtime_r(&time_s, &tm);
194 if (!res) {
195 // TODO: log instead
196 fprintf(stderr, "[warning] Unable to get gmtime.\n");
197 goto seconds;
198 }
199 }
200 if (pretty->options.clock_date) {
201 char timestr[26];
202 size_t res;
203
204 /* Print date and time */
205 res = strftime(timestr, sizeof(timestr),
206 "%Y-%m-%d ", &tm);
207 if (!res) {
208 // TODO: log instead
209 fprintf(stderr, "[warning] Unable to print ascii time.\n");
210 goto seconds;
211 }
212
213 g_string_append(pretty->string, timestr);
214 }
215
216 /* Print time in HH:MM:SS.ns */
217 g_string_append_printf(pretty->string,
218 "%02d:%02d:%02d.%09" PRIu64, tm.tm_hour, tm.tm_min,
219 tm.tm_sec, ts_nsec_abs);
220 goto end;
221 }
222 seconds:
223 g_string_append_printf(pretty->string, "%s%" PRId64 ".%09" PRIu64,
224 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
225 end:
226 return;
227 }
228
229 static
230 enum bt_component_status print_event_timestamp(struct pretty_component *pretty,
231 struct bt_event *event,
232 struct bt_clock_class_priority_map *cc_prio_map,
233 bool *start_line)
234 {
235 bool print_names = pretty->options.print_header_field_names;
236 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
237 struct bt_stream *stream = NULL;
238 struct bt_stream_class *stream_class = NULL;
239 struct bt_trace *trace = NULL;
240 struct bt_clock_class *clock_class = NULL;
241
242 stream = bt_event_get_stream(event);
243 if (!stream) {
244 ret = BT_COMPONENT_STATUS_ERROR;
245 goto end;
246 }
247
248 stream_class = bt_stream_get_class(stream);
249 if (!stream_class) {
250 ret = BT_COMPONENT_STATUS_ERROR;
251 goto end;
252 }
253 trace = bt_stream_class_get_trace(stream_class);
254 if (!trace) {
255 ret = BT_COMPONENT_STATUS_ERROR;
256 goto end;
257 }
258
259 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map) == 0) {
260 /* No clock class: skip the timestamp without an error */
261 goto end;
262 }
263
264 clock_class =
265 bt_clock_class_priority_map_get_highest_priority_clock_class(
266 cc_prio_map);
267 if (!clock_class) {
268 ret = BT_COMPONENT_STATUS_ERROR;
269 goto end;
270 }
271
272 if (print_names) {
273 print_name_equal(pretty, "timestamp");
274 } else {
275 g_string_append(pretty->string, "[");
276 }
277 if (pretty->use_colors) {
278 g_string_append(pretty->string, COLOR_TIMESTAMP);
279 }
280 if (pretty->options.print_timestamp_cycles) {
281 print_timestamp_cycles(pretty, clock_class, event);
282 } else {
283 struct bt_clock_value *clock_value =
284 bt_event_get_clock_value(event, clock_class);
285
286 print_timestamp_wall(pretty, clock_value);
287 bt_put(clock_value);
288 }
289 if (pretty->use_colors) {
290 g_string_append(pretty->string, COLOR_RST);
291 }
292
293 if (!print_names)
294 g_string_append(pretty->string, "] ");
295
296 if (pretty->options.print_delta_field) {
297 if (print_names) {
298 g_string_append(pretty->string, ", ");
299 print_name_equal(pretty, "delta");
300 } else {
301 g_string_append(pretty->string, "(");
302 }
303 if (pretty->options.print_timestamp_cycles) {
304 if (pretty->delta_cycles == -1ULL) {
305 g_string_append(pretty->string,
306 "+??????????\?\?) "); /* Not a trigraph. */
307 } else {
308 g_string_append_printf(pretty->string,
309 "+%012" PRIu64, pretty->delta_cycles);
310 }
311 } else {
312 if (pretty->delta_real_timestamp != -1ULL) {
313 uint64_t delta_sec, delta_nsec, delta;
314
315 delta = pretty->delta_real_timestamp;
316 delta_sec = delta / NSEC_PER_SEC;
317 delta_nsec = delta % NSEC_PER_SEC;
318 g_string_append_printf(pretty->string,
319 "+%" PRIu64 ".%09" PRIu64,
320 delta_sec, delta_nsec);
321 } else {
322 g_string_append(pretty->string, "+?.?????????");
323 }
324 }
325 if (!print_names) {
326 g_string_append(pretty->string, ") ");
327 }
328 }
329 *start_line = !print_names;
330
331 end:
332 bt_put(stream);
333 bt_put(clock_class);
334 bt_put(stream_class);
335 bt_put(trace);
336 return ret;
337 }
338
339 static
340 enum bt_component_status print_event_header(struct pretty_component *pretty,
341 struct bt_event *event,
342 struct bt_clock_class_priority_map *cc_prio_map)
343 {
344 bool print_names = pretty->options.print_header_field_names;
345 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
346 struct bt_event_class *event_class = NULL;
347 struct bt_stream_class *stream_class = NULL;
348 struct bt_trace *trace_class = NULL;
349 int dom_print = 0;
350
351 event_class = bt_event_get_class(event);
352 if (!event_class) {
353 ret = BT_COMPONENT_STATUS_ERROR;
354 goto end;
355 }
356 stream_class = bt_event_class_get_stream_class(event_class);
357 if (!stream_class) {
358 ret = BT_COMPONENT_STATUS_ERROR;
359 goto end;
360 }
361 trace_class = bt_stream_class_get_trace(stream_class);
362 if (!trace_class) {
363 ret = BT_COMPONENT_STATUS_ERROR;
364 goto end;
365 }
366 ret = print_event_timestamp(pretty, event, cc_prio_map,
367 &pretty->start_line);
368 if (ret != BT_COMPONENT_STATUS_OK) {
369 goto end;
370 }
371 if (pretty->options.print_trace_field) {
372 const char *name;
373
374 name = bt_trace_get_name(trace_class);
375 if (name) {
376 if (!pretty->start_line) {
377 g_string_append(pretty->string, ", ");
378 }
379 if (print_names) {
380 print_name_equal(pretty, "trace");
381 }
382
383 g_string_append(pretty->string, name);
384
385 if (!print_names) {
386 g_string_append(pretty->string, " ");
387 }
388 }
389 }
390 if (pretty->options.print_trace_hostname_field) {
391 struct bt_value *hostname_str;
392
393 hostname_str = bt_trace_get_environment_field_value_by_name(trace_class,
394 "hostname");
395 if (hostname_str) {
396 const char *str;
397
398 if (!pretty->start_line) {
399 g_string_append(pretty->string, ", ");
400 }
401 if (print_names) {
402 print_name_equal(pretty, "trace:hostname");
403 }
404 if (bt_value_string_get(hostname_str, &str)
405 == BT_VALUE_STATUS_OK) {
406 g_string_append(pretty->string, str);
407 }
408 bt_put(hostname_str);
409 dom_print = 1;
410 }
411 }
412 if (pretty->options.print_trace_domain_field) {
413 struct bt_value *domain_str;
414
415 domain_str = bt_trace_get_environment_field_value_by_name(trace_class,
416 "domain");
417 if (domain_str) {
418 const char *str;
419
420 if (!pretty->start_line) {
421 g_string_append(pretty->string, ", ");
422 }
423 if (print_names) {
424 print_name_equal(pretty, "trace:domain");
425 } else if (dom_print) {
426 g_string_append(pretty->string, ":");
427 }
428 if (bt_value_string_get(domain_str, &str)
429 == BT_VALUE_STATUS_OK) {
430 g_string_append(pretty->string, str);
431 }
432 bt_put(domain_str);
433 dom_print = 1;
434 }
435 }
436 if (pretty->options.print_trace_procname_field) {
437 struct bt_value *procname_str;
438
439 procname_str = bt_trace_get_environment_field_value_by_name(trace_class,
440 "procname");
441 if (procname_str) {
442 const char *str;
443
444 if (!pretty->start_line) {
445 g_string_append(pretty->string, ", ");
446 }
447 if (print_names) {
448 print_name_equal(pretty, "trace:procname");
449 } else if (dom_print) {
450 g_string_append(pretty->string, ":");
451 }
452 if (bt_value_string_get(procname_str, &str)
453 == BT_VALUE_STATUS_OK) {
454 g_string_append(pretty->string, str);
455 }
456 bt_put(procname_str);
457 dom_print = 1;
458 }
459 }
460 if (pretty->options.print_trace_vpid_field) {
461 struct bt_value *vpid_value;
462
463 vpid_value = bt_trace_get_environment_field_value_by_name(trace_class,
464 "vpid");
465 if (vpid_value) {
466 int64_t value;
467
468 if (!pretty->start_line) {
469 g_string_append(pretty->string, ", ");
470 }
471 if (print_names) {
472 print_name_equal(pretty, "trace:vpid");
473 } else if (dom_print) {
474 g_string_append(pretty->string, ":");
475 }
476 if (bt_value_integer_get(vpid_value, &value)
477 == BT_VALUE_STATUS_OK) {
478 g_string_append_printf(pretty->string, "(%" PRId64 ")", value);
479 }
480 bt_put(vpid_value);
481 dom_print = 1;
482 }
483 }
484 if (pretty->options.print_loglevel_field) {
485 static const char *log_level_names[] = {
486 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY ] = "TRACE_EMERG",
487 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT ] = "TRACE_ALERT",
488 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL ] = "TRACE_CRIT",
489 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR ] = "TRACE_ERR",
490 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING ] = "TRACE_WARNING",
491 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE ] = "TRACE_NOTICE",
492 [ BT_EVENT_CLASS_LOG_LEVEL_INFO ] = "TRACE_INFO",
493 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM ] = "TRACE_DEBUG_SYSTEM",
494 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM ] = "TRACE_DEBUG_PROGRAM",
495 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS ] = "TRACE_DEBUG_PROCESS",
496 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE ] = "TRACE_DEBUG_MODULE",
497 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT ] = "TRACE_DEBUG_UNIT",
498 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION ] = "TRACE_DEBUG_FUNCTION",
499 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE ] = "TRACE_DEBUG_LINE",
500 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG ] = "TRACE_DEBUG",
501 };
502 enum bt_event_class_log_level log_level;
503 const char *log_level_str = NULL;
504
505 log_level = bt_event_class_get_log_level(event_class);
506 BT_ASSERT(log_level != BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN);
507 if (log_level != BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
508 log_level_str = log_level_names[log_level];
509 }
510
511 if (log_level_str) {
512 if (!pretty->start_line) {
513 g_string_append(pretty->string, ", ");
514 }
515 if (print_names) {
516 print_name_equal(pretty, "loglevel");
517 } else if (dom_print) {
518 g_string_append(pretty->string, ":");
519 }
520
521 g_string_append(pretty->string, log_level_str);
522 g_string_append_printf(
523 pretty->string, " (%d)", (int) log_level);
524 dom_print = 1;
525 }
526 }
527 if (pretty->options.print_emf_field) {
528 const char *uri_str;
529
530 uri_str = bt_event_class_get_emf_uri(event_class);
531 if (uri_str) {
532 if (!pretty->start_line) {
533 g_string_append(pretty->string, ", ");
534 }
535 if (print_names) {
536 print_name_equal(pretty, "model.emf.uri");
537 } else if (dom_print) {
538 g_string_append(pretty->string, ":");
539 }
540
541 g_string_append(pretty->string, uri_str);
542 dom_print = 1;
543 }
544 }
545 if (dom_print && !print_names) {
546 g_string_append(pretty->string, " ");
547 }
548 if (!pretty->start_line) {
549 g_string_append(pretty->string, ", ");
550 }
551 pretty->start_line = true;
552 if (print_names) {
553 print_name_equal(pretty, "name");
554 }
555 if (pretty->use_colors) {
556 g_string_append(pretty->string, COLOR_EVENT_NAME);
557 }
558 g_string_append(pretty->string, bt_event_class_get_name(event_class));
559 if (pretty->use_colors) {
560 g_string_append(pretty->string, COLOR_RST);
561 }
562 if (!print_names) {
563 g_string_append(pretty->string, ": ");
564 } else {
565 g_string_append(pretty->string, ", ");
566 }
567 end:
568 bt_put(trace_class);
569 bt_put(stream_class);
570 bt_put(event_class);
571 return ret;
572 }
573
574 static
575 enum bt_component_status print_integer(struct pretty_component *pretty,
576 struct bt_field *field)
577 {
578 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
579 struct bt_field_type *field_type = NULL;
580 enum bt_integer_base base;
581 enum bt_string_encoding encoding;
582 int signedness;
583 union {
584 uint64_t u;
585 int64_t s;
586 } v;
587 bool rst_color = false;
588
589 field_type = bt_field_get_type(field);
590 if (!field_type) {
591 ret = BT_COMPONENT_STATUS_ERROR;
592 goto end;
593 }
594 signedness = bt_ctf_field_type_integer_get_signed(field_type);
595 if (signedness < 0) {
596 ret = BT_COMPONENT_STATUS_ERROR;
597 goto end;
598 }
599 if (!signedness) {
600 if (bt_field_unsigned_integer_get_value(field, &v.u) < 0) {
601 ret = BT_COMPONENT_STATUS_ERROR;
602 goto end;
603 }
604 } else {
605 if (bt_field_signed_integer_get_value(field, &v.s) < 0) {
606 ret = BT_COMPONENT_STATUS_ERROR;
607 goto end;
608 }
609 }
610
611 encoding = bt_field_type_integer_get_encoding(field_type);
612 switch (encoding) {
613 case BT_STRING_ENCODING_UTF8:
614 case BT_STRING_ENCODING_ASCII:
615 g_string_append_c(pretty->tmp_string, (int) v.u);
616 goto end;
617 case BT_STRING_ENCODING_NONE:
618 case BT_STRING_ENCODING_UNKNOWN:
619 break;
620 default:
621 ret = BT_COMPONENT_STATUS_ERROR;
622 goto end;
623 }
624
625 if (pretty->use_colors) {
626 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
627 rst_color = true;
628 }
629
630 base = bt_field_type_integer_get_base(field_type);
631 switch (base) {
632 case BT_INTEGER_BASE_BINARY:
633 {
634 int bitnr, len;
635
636 len = bt_field_type_integer_get_size(field_type);
637 if (len < 0) {
638 ret = BT_COMPONENT_STATUS_ERROR;
639 goto end;
640 }
641 g_string_append(pretty->string, "0b");
642 v.u = _bt_piecewise_lshift(v.u, 64 - len);
643 for (bitnr = 0; bitnr < len; bitnr++) {
644 g_string_append_printf(pretty->string, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
645 v.u = _bt_piecewise_lshift(v.u, 1);
646 }
647 break;
648 }
649 case BT_INTEGER_BASE_OCTAL:
650 {
651 if (signedness) {
652 int len;
653
654 len = bt_field_type_integer_get_size(field_type);
655 if (len < 0) {
656 ret = BT_COMPONENT_STATUS_ERROR;
657 goto end;
658 }
659 if (len < 64) {
660 size_t rounded_len;
661
662 BT_ASSERT(len != 0);
663 /* Round length to the nearest 3-bit */
664 rounded_len = (((len - 1) / 3) + 1) * 3;
665 v.u &= ((uint64_t) 1 << rounded_len) - 1;
666 }
667 }
668
669 g_string_append_printf(pretty->string, "0%" PRIo64, v.u);
670 break;
671 }
672 case BT_INTEGER_BASE_DECIMAL:
673 case BT_INTEGER_BASE_UNSPECIFIED:
674 if (!signedness) {
675 g_string_append_printf(pretty->string, "%" PRIu64, v.u);
676 } else {
677 g_string_append_printf(pretty->string, "%" PRId64, v.s);
678 }
679 break;
680 case BT_INTEGER_BASE_HEXADECIMAL:
681 {
682 int len;
683
684 len = bt_field_type_integer_get_size(field_type);
685 if (len < 0) {
686 ret = BT_COMPONENT_STATUS_ERROR;
687 goto end;
688 }
689 if (len < 64) {
690 /* Round length to the nearest nibble */
691 uint8_t rounded_len = ((len + 3) & ~0x3);
692
693 v.u &= ((uint64_t) 1 << rounded_len) - 1;
694 }
695
696 g_string_append_printf(pretty->string, "0x%" PRIX64, v.u);
697 break;
698 }
699 default:
700 ret = BT_COMPONENT_STATUS_ERROR;
701 goto end;
702 }
703 end:
704 if (rst_color) {
705 g_string_append(pretty->string, COLOR_RST);
706 }
707 bt_put(field_type);
708 return ret;
709 }
710
711 static
712 void print_escape_string(struct pretty_component *pretty, const char *str)
713 {
714 int i;
715
716 g_string_append_c(pretty->string, '"');
717
718 for (i = 0; i < strlen(str); i++) {
719 /* Escape sequences not recognized by iscntrl(). */
720 switch (str[i]) {
721 case '\\':
722 g_string_append(pretty->string, "\\\\");
723 continue;
724 case '\'':
725 g_string_append(pretty->string, "\\\'");
726 continue;
727 case '\"':
728 g_string_append(pretty->string, "\\\"");
729 continue;
730 case '\?':
731 g_string_append(pretty->string, "\\\?");
732 continue;
733 }
734
735 /* Standard characters. */
736 if (!iscntrl(str[i])) {
737 g_string_append_c(pretty->string, str[i]);
738 continue;
739 }
740
741 switch (str[i]) {
742 case '\0':
743 g_string_append(pretty->string, "\\0");
744 break;
745 case '\a':
746 g_string_append(pretty->string, "\\a");
747 break;
748 case '\b':
749 g_string_append(pretty->string, "\\b");
750 break;
751 case '\e':
752 g_string_append(pretty->string, "\\e");
753 break;
754 case '\f':
755 g_string_append(pretty->string, "\\f");
756 break;
757 case '\n':
758 g_string_append(pretty->string, "\\n");
759 break;
760 case '\r':
761 g_string_append(pretty->string, "\\r");
762 break;
763 case '\t':
764 g_string_append(pretty->string, "\\t");
765 break;
766 case '\v':
767 g_string_append(pretty->string, "\\v");
768 break;
769 default:
770 /* Unhandled control-sequence, print as hex. */
771 g_string_append_printf(pretty->string, "\\x%02x", str[i]);
772 break;
773 }
774 }
775
776 g_string_append_c(pretty->string, '"');
777 }
778
779 static
780 enum bt_component_status print_enum(struct pretty_component *pretty,
781 struct bt_field *field)
782 {
783 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
784 struct bt_field *container_field = NULL;
785 struct bt_field_type *enumeration_field_type = NULL;
786 struct bt_field_type *container_field_type = NULL;
787 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
788 int nr_mappings = 0;
789 int is_signed;
790
791 enumeration_field_type = bt_field_get_type(field);
792 if (!enumeration_field_type) {
793 ret = BT_COMPONENT_STATUS_ERROR;
794 goto end;
795 }
796 container_field = bt_field_enumeration_get_container(field);
797 if (!container_field) {
798 ret = BT_COMPONENT_STATUS_ERROR;
799 goto end;
800 }
801 container_field_type = bt_field_get_type(container_field);
802 if (!container_field_type) {
803 ret = BT_COMPONENT_STATUS_ERROR;
804 goto end;
805 }
806 is_signed = bt_ctf_field_type_integer_get_signed(container_field_type);
807 if (is_signed < 0) {
808 ret = BT_COMPONENT_STATUS_ERROR;
809 goto end;
810 }
811 if (is_signed) {
812 int64_t value;
813
814 if (bt_field_signed_integer_get_value(container_field,
815 &value)) {
816 ret = BT_COMPONENT_STATUS_ERROR;
817 goto end;
818 }
819 iter = bt_field_type_enumeration_find_mappings_by_signed_value(
820 enumeration_field_type, value);
821 } else {
822 uint64_t value;
823
824 if (bt_field_unsigned_integer_get_value(container_field,
825 &value)) {
826 ret = BT_COMPONENT_STATUS_ERROR;
827 goto end;
828 }
829 iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(
830 enumeration_field_type, value);
831 }
832 g_string_append(pretty->string, "( ");
833 ret = bt_field_type_enumeration_mapping_iterator_next(iter);
834 if (ret) {
835 if (pretty->use_colors) {
836 g_string_append(pretty->string, COLOR_UNKNOWN);
837 }
838 g_string_append(pretty->string, "<unknown>");
839 if (pretty->use_colors) {
840 g_string_append(pretty->string, COLOR_RST);
841 }
842 goto skip_loop;
843 }
844 for (;;) {
845 const char *mapping_name;
846
847 if (bt_field_type_enumeration_mapping_iterator_get_signed(
848 iter, &mapping_name, NULL, NULL) < 0) {
849 ret = BT_COMPONENT_STATUS_ERROR;
850 goto end;
851 }
852 if (nr_mappings++)
853 g_string_append(pretty->string, ", ");
854 if (pretty->use_colors) {
855 g_string_append(pretty->string, COLOR_ENUM_MAPPING_NAME);
856 }
857 print_escape_string(pretty, mapping_name);
858 if (pretty->use_colors) {
859 g_string_append(pretty->string, COLOR_RST);
860 }
861 if (bt_field_type_enumeration_mapping_iterator_next(iter) < 0) {
862 break;
863 }
864 }
865 skip_loop:
866 g_string_append(pretty->string, " : container = ");
867 ret = print_integer(pretty, container_field);
868 if (ret != BT_COMPONENT_STATUS_OK) {
869 goto end;
870 }
871 g_string_append(pretty->string, " )");
872 end:
873 bt_put(iter);
874 bt_put(container_field_type);
875 bt_put(container_field);
876 bt_put(enumeration_field_type);
877 return ret;
878 }
879
880 static
881 int filter_field_name(struct pretty_component *pretty, const char *field_name,
882 GQuark *filter_fields, int filter_array_len)
883 {
884 int i;
885 GQuark field_quark = g_quark_try_string(field_name);
886
887 if (!field_quark || pretty->options.verbose) {
888 return 1;
889 }
890
891 for (i = 0; i < filter_array_len; i++) {
892 if (field_quark == filter_fields[i]) {
893 return 0;
894 }
895 }
896 return 1;
897 }
898
899 static
900 enum bt_component_status print_struct_field(struct pretty_component *pretty,
901 struct bt_field *_struct,
902 struct bt_field_type *struct_type,
903 int i, bool print_names, int *nr_printed_fields,
904 GQuark *filter_fields, int filter_array_len)
905 {
906 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
907 const char *field_name;
908 struct bt_field *field = NULL;
909 struct bt_field_type *field_type = NULL;;
910
911 field = bt_field_structure_get_field_by_index(_struct, i);
912 if (!field) {
913 ret = BT_COMPONENT_STATUS_ERROR;
914 goto end;
915 }
916 if (bt_field_type_structure_get_field_by_index(struct_type,
917 &field_name, &field_type, i) < 0) {
918 ret = BT_COMPONENT_STATUS_ERROR;
919 goto end;
920 }
921
922 if (filter_fields && !filter_field_name(pretty, field_name,
923 filter_fields, filter_array_len)) {
924 ret = BT_COMPONENT_STATUS_OK;
925 goto end;
926 }
927
928 if (*nr_printed_fields > 0) {
929 g_string_append(pretty->string, ", ");
930 } else {
931 g_string_append(pretty->string, " ");
932 }
933 if (print_names) {
934 print_field_name_equal(pretty, field_name);
935 }
936 ret = print_field(pretty, field, print_names, NULL, 0);
937 *nr_printed_fields += 1;
938 end:
939 bt_put(field_type);
940 bt_put(field);
941 return ret;
942 }
943
944 static
945 enum bt_component_status print_struct(struct pretty_component *pretty,
946 struct bt_field *_struct, bool print_names,
947 GQuark *filter_fields, int filter_array_len)
948 {
949 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
950 struct bt_field_type *struct_type = NULL;
951 int nr_fields, i, nr_printed_fields;
952
953 struct_type = bt_field_get_type(_struct);
954 if (!struct_type) {
955 ret = BT_COMPONENT_STATUS_ERROR;
956 goto end;
957 }
958 nr_fields = bt_field_type_structure_get_field_count(struct_type);
959 if (nr_fields < 0) {
960 ret = BT_COMPONENT_STATUS_ERROR;
961 goto end;
962 }
963 g_string_append(pretty->string, "{");
964 pretty->depth++;
965 nr_printed_fields = 0;
966 for (i = 0; i < nr_fields; i++) {
967 ret = print_struct_field(pretty, _struct, struct_type, i,
968 print_names, &nr_printed_fields, filter_fields,
969 filter_array_len);
970 if (ret != BT_COMPONENT_STATUS_OK) {
971 goto end;
972 }
973 }
974 pretty->depth--;
975 g_string_append(pretty->string, " }");
976 end:
977 bt_put(struct_type);
978 return ret;
979 }
980
981 static
982 enum bt_component_status print_array_field(struct pretty_component *pretty,
983 struct bt_field *array, uint64_t i,
984 bool is_string, bool print_names)
985 {
986 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
987 struct bt_field *field = NULL;
988
989 if (!is_string) {
990 if (i != 0) {
991 g_string_append(pretty->string, ", ");
992 } else {
993 g_string_append(pretty->string, " ");
994 }
995 if (print_names) {
996 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
997 }
998 }
999 field = bt_field_array_get_field(array, i);
1000 if (!field) {
1001 ret = BT_COMPONENT_STATUS_ERROR;
1002 goto end;
1003 }
1004 ret = print_field(pretty, field, print_names, NULL, 0);
1005 end:
1006 bt_put(field);
1007 return ret;
1008 }
1009
1010 static
1011 enum bt_component_status print_array(struct pretty_component *pretty,
1012 struct bt_field *array, bool print_names)
1013 {
1014 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1015 struct bt_field_type *array_type = NULL, *field_type = NULL;
1016 enum bt_field_type_id type_id;
1017 int64_t len;
1018 uint64_t i;
1019 bool is_string = false;
1020
1021 array_type = bt_field_get_type(array);
1022 if (!array_type) {
1023 ret = BT_COMPONENT_STATUS_ERROR;
1024 goto end;
1025 }
1026 field_type = bt_field_type_array_get_element_type(array_type);
1027 if (!field_type) {
1028 ret = BT_COMPONENT_STATUS_ERROR;
1029 goto end;
1030 }
1031 len = bt_field_type_array_get_length(array_type);
1032 if (len < 0) {
1033 ret = BT_COMPONENT_STATUS_ERROR;
1034 goto end;
1035 }
1036 type_id = bt_field_type_get_type_id(field_type);
1037 if (type_id == BT_FIELD_TYPE_ID_INTEGER) {
1038 enum bt_string_encoding encoding;
1039
1040 encoding = bt_field_type_integer_get_encoding(field_type);
1041 if (encoding == BT_STRING_ENCODING_UTF8
1042 || encoding == BT_STRING_ENCODING_ASCII) {
1043 int integer_len, integer_alignment;
1044
1045 integer_len = bt_field_type_integer_get_size(field_type);
1046 if (integer_len < 0) {
1047 return BT_COMPONENT_STATUS_ERROR;
1048 }
1049 integer_alignment = bt_field_type_get_alignment(field_type);
1050 if (integer_alignment < 0) {
1051 return BT_COMPONENT_STATUS_ERROR;
1052 }
1053 if (integer_len == CHAR_BIT
1054 && integer_alignment == CHAR_BIT) {
1055 is_string = true;
1056 }
1057 }
1058 }
1059
1060 if (is_string) {
1061 g_string_assign(pretty->tmp_string, "");
1062 } else {
1063 g_string_append(pretty->string, "[");
1064 }
1065
1066 pretty->depth++;
1067 for (i = 0; i < len; i++) {
1068 ret = print_array_field(pretty, array, i, is_string, print_names);
1069 if (ret != BT_COMPONENT_STATUS_OK) {
1070 goto end;
1071 }
1072 }
1073 pretty->depth--;
1074
1075 if (is_string) {
1076 if (pretty->use_colors) {
1077 g_string_append(pretty->string, COLOR_STRING_VALUE);
1078 }
1079 print_escape_string(pretty, pretty->tmp_string->str);
1080 if (pretty->use_colors) {
1081 g_string_append(pretty->string, COLOR_RST);
1082 }
1083 } else {
1084 g_string_append(pretty->string, " ]");
1085 }
1086 end:
1087 bt_put(field_type);
1088 bt_put(array_type);
1089 return ret;
1090 }
1091
1092 static
1093 enum bt_component_status print_sequence_field(struct pretty_component *pretty,
1094 struct bt_field *seq, uint64_t i,
1095 bool is_string, bool print_names)
1096 {
1097 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1098 struct bt_field *field = NULL;
1099
1100 if (!is_string) {
1101 if (i != 0) {
1102 g_string_append(pretty->string, ", ");
1103 } else {
1104 g_string_append(pretty->string, " ");
1105 }
1106 if (print_names) {
1107 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1108 }
1109 }
1110 field = bt_field_sequence_get_field(seq, i);
1111 if (!field) {
1112 ret = BT_COMPONENT_STATUS_ERROR;
1113 goto end;
1114 }
1115 ret = print_field(pretty, field, print_names, NULL, 0);
1116 end:
1117 bt_put(field);
1118 return ret;
1119 }
1120
1121 static
1122 enum bt_component_status print_sequence(struct pretty_component *pretty,
1123 struct bt_field *seq, bool print_names)
1124 {
1125 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1126 struct bt_field_type *seq_type = NULL, *field_type = NULL;
1127 struct bt_field *length_field = NULL;
1128 enum bt_field_type_id type_id;
1129 uint64_t len;
1130 uint64_t i;
1131 bool is_string = false;
1132
1133 seq_type = bt_field_get_type(seq);
1134 if (!seq_type) {
1135 ret = BT_COMPONENT_STATUS_ERROR;
1136 goto end;
1137 }
1138 length_field = bt_field_sequence_get_length(seq);
1139 if (!length_field) {
1140 ret = BT_COMPONENT_STATUS_ERROR;
1141 goto end;
1142 }
1143 if (bt_field_unsigned_integer_get_value(length_field, &len) < 0) {
1144 ret = BT_COMPONENT_STATUS_ERROR;
1145 goto end;
1146 }
1147 field_type = bt_field_type_sequence_get_element_type(seq_type);
1148 if (!field_type) {
1149 ret = BT_COMPONENT_STATUS_ERROR;
1150 goto end;
1151 }
1152 type_id = bt_field_type_get_type_id(field_type);
1153 if (type_id == BT_FIELD_TYPE_ID_INTEGER) {
1154 enum bt_string_encoding encoding;
1155
1156 encoding = bt_field_type_integer_get_encoding(field_type);
1157 if (encoding == BT_STRING_ENCODING_UTF8
1158 || encoding == BT_STRING_ENCODING_ASCII) {
1159 int integer_len, integer_alignment;
1160
1161 integer_len = bt_field_type_integer_get_size(field_type);
1162 if (integer_len < 0) {
1163 ret = BT_COMPONENT_STATUS_ERROR;
1164 goto end;
1165 }
1166 integer_alignment = bt_field_type_get_alignment(field_type);
1167 if (integer_alignment < 0) {
1168 ret = BT_COMPONENT_STATUS_ERROR;
1169 goto end;
1170 }
1171 if (integer_len == CHAR_BIT
1172 && integer_alignment == CHAR_BIT) {
1173 is_string = true;
1174 }
1175 }
1176 }
1177
1178 if (is_string) {
1179 g_string_assign(pretty->tmp_string, "");
1180 } else {
1181 g_string_append(pretty->string, "[");
1182 }
1183
1184 pretty->depth++;
1185 for (i = 0; i < len; i++) {
1186 ret = print_sequence_field(pretty, seq, i,
1187 is_string, print_names);
1188 if (ret != BT_COMPONENT_STATUS_OK) {
1189 goto end;
1190 }
1191 }
1192 pretty->depth--;
1193
1194 if (is_string) {
1195 if (pretty->use_colors) {
1196 g_string_append(pretty->string, COLOR_STRING_VALUE);
1197 }
1198 print_escape_string(pretty, pretty->tmp_string->str);
1199 if (pretty->use_colors) {
1200 g_string_append(pretty->string, COLOR_RST);
1201 }
1202 } else {
1203 g_string_append(pretty->string, " ]");
1204 }
1205 end:
1206 bt_put(length_field);
1207 bt_put(field_type);
1208 bt_put(seq_type);
1209 return ret;
1210 }
1211
1212 static
1213 enum bt_component_status print_variant(struct pretty_component *pretty,
1214 struct bt_field *variant, bool print_names)
1215 {
1216 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1217 struct bt_field *field = NULL;
1218
1219 field = bt_field_variant_get_current_field(variant);
1220 if (!field) {
1221 ret = BT_COMPONENT_STATUS_ERROR;
1222 goto end;
1223 }
1224 g_string_append(pretty->string, "{ ");
1225 pretty->depth++;
1226 if (print_names) {
1227 int iter_ret;
1228 struct bt_field *tag_field = NULL;
1229 const char *tag_choice;
1230 struct bt_field_type_enumeration_mapping_iterator *iter;
1231
1232 tag_field = bt_field_variant_get_tag(variant);
1233 if (!tag_field) {
1234 ret = BT_COMPONENT_STATUS_ERROR;
1235 goto end;
1236 }
1237
1238 iter = bt_field_enumeration_get_mappings(tag_field);
1239 iter_ret = bt_field_type_enumeration_mapping_iterator_next(
1240 iter);
1241 if (!iter || ret) {
1242 bt_put(tag_field);
1243 ret = BT_COMPONENT_STATUS_ERROR;
1244 goto end;
1245 }
1246
1247 iter_ret =
1248 bt_field_type_enumeration_mapping_iterator_get_signed(
1249 iter, &tag_choice, NULL, NULL);
1250 if (iter_ret) {
1251 bt_put(iter);
1252 bt_put(tag_field);
1253 ret = BT_COMPONENT_STATUS_ERROR;
1254 goto end;
1255 }
1256 print_field_name_equal(pretty, tag_choice);
1257 bt_put(tag_field);
1258 bt_put(iter);
1259 }
1260 ret = print_field(pretty, field, print_names, NULL, 0);
1261 if (ret != BT_COMPONENT_STATUS_OK) {
1262 goto end;
1263 }
1264 pretty->depth--;
1265 g_string_append(pretty->string, " }");
1266 end:
1267 bt_put(field);
1268 return ret;
1269 }
1270
1271 static
1272 enum bt_component_status print_field(struct pretty_component *pretty,
1273 struct bt_field *field, bool print_names,
1274 GQuark *filter_fields, int filter_array_len)
1275 {
1276 enum bt_field_type_id type_id;
1277
1278 type_id = bt_field_get_type_id(field);
1279 switch (type_id) {
1280 case CTF_TYPE_INTEGER:
1281 return print_integer(pretty, field);
1282 case CTF_TYPE_FLOAT:
1283 {
1284 double v;
1285
1286 if (bt_field_floating_point_get_value(field, &v)) {
1287 return BT_COMPONENT_STATUS_ERROR;
1288 }
1289 if (pretty->use_colors) {
1290 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
1291 }
1292 g_string_append_printf(pretty->string, "%g", v);
1293 if (pretty->use_colors) {
1294 g_string_append(pretty->string, COLOR_RST);
1295 }
1296 return BT_COMPONENT_STATUS_OK;
1297 }
1298 case CTF_TYPE_ENUM:
1299 return print_enum(pretty, field);
1300 case CTF_TYPE_STRING:
1301 {
1302 const char *str;
1303
1304 str = bt_field_string_get_value(field);
1305 if (!str) {
1306 return BT_COMPONENT_STATUS_ERROR;
1307 }
1308
1309 if (pretty->use_colors) {
1310 g_string_append(pretty->string, COLOR_STRING_VALUE);
1311 }
1312 print_escape_string(pretty, str);
1313 if (pretty->use_colors) {
1314 g_string_append(pretty->string, COLOR_RST);
1315 }
1316 return BT_COMPONENT_STATUS_OK;
1317 }
1318 case CTF_TYPE_STRUCT:
1319 return print_struct(pretty, field, print_names, filter_fields,
1320 filter_array_len);
1321 case CTF_TYPE_VARIANT:
1322 return print_variant(pretty, field, print_names);
1323 case CTF_TYPE_ARRAY:
1324 return print_array(pretty, field, print_names);
1325 case CTF_TYPE_SEQUENCE:
1326 return print_sequence(pretty, field, print_names);
1327 default:
1328 // TODO: log instead
1329 fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id);
1330 return BT_COMPONENT_STATUS_ERROR;
1331 }
1332 }
1333
1334 static
1335 enum bt_component_status print_stream_packet_context(struct pretty_component *pretty,
1336 struct bt_event *event)
1337 {
1338 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1339 struct bt_packet *packet = NULL;
1340 struct bt_field *main_field = NULL;
1341
1342 packet = bt_event_get_packet(event);
1343 if (!packet) {
1344 ret = BT_COMPONENT_STATUS_ERROR;
1345 goto end;
1346 }
1347 main_field = bt_packet_get_context(packet);
1348 if (!main_field) {
1349 goto end;
1350 }
1351 if (!pretty->start_line) {
1352 g_string_append(pretty->string, ", ");
1353 }
1354 pretty->start_line = false;
1355 if (pretty->options.print_scope_field_names) {
1356 print_name_equal(pretty, "stream.packet.context");
1357 }
1358 ret = print_field(pretty, main_field,
1359 pretty->options.print_context_field_names,
1360 stream_packet_context_quarks,
1361 STREAM_PACKET_CONTEXT_QUARKS_LEN);
1362 end:
1363 bt_put(main_field);
1364 bt_put(packet);
1365 return ret;
1366 }
1367
1368 static
1369 enum bt_component_status print_event_header_raw(struct pretty_component *pretty,
1370 struct bt_event *event)
1371 {
1372 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1373 struct bt_field *main_field = NULL;
1374
1375 main_field = bt_event_get_header(event);
1376 if (!main_field) {
1377 goto end;
1378 }
1379 if (!pretty->start_line) {
1380 g_string_append(pretty->string, ", ");
1381 }
1382 pretty->start_line = false;
1383 if (pretty->options.print_scope_field_names) {
1384 print_name_equal(pretty, "stream.event.header");
1385 }
1386 ret = print_field(pretty, main_field,
1387 pretty->options.print_header_field_names, NULL, 0);
1388 end:
1389 bt_put(main_field);
1390 return ret;
1391 }
1392
1393 static
1394 enum bt_component_status print_stream_event_context(struct pretty_component *pretty,
1395 struct bt_event *event)
1396 {
1397 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1398 struct bt_field *main_field = NULL;
1399
1400 main_field = bt_event_get_stream_event_context(event);
1401 if (!main_field) {
1402 goto end;
1403 }
1404 if (!pretty->start_line) {
1405 g_string_append(pretty->string, ", ");
1406 }
1407 pretty->start_line = false;
1408 if (pretty->options.print_scope_field_names) {
1409 print_name_equal(pretty, "stream.event.context");
1410 }
1411 ret = print_field(pretty, main_field,
1412 pretty->options.print_context_field_names, NULL, 0);
1413 end:
1414 bt_put(main_field);
1415 return ret;
1416 }
1417
1418 static
1419 enum bt_component_status print_event_context(struct pretty_component *pretty,
1420 struct bt_event *event)
1421 {
1422 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1423 struct bt_field *main_field = NULL;
1424
1425 main_field = bt_event_get_event_context(event);
1426 if (!main_field) {
1427 goto end;
1428 }
1429 if (!pretty->start_line) {
1430 g_string_append(pretty->string, ", ");
1431 }
1432 pretty->start_line = false;
1433 if (pretty->options.print_scope_field_names) {
1434 print_name_equal(pretty, "event.context");
1435 }
1436 ret = print_field(pretty, main_field,
1437 pretty->options.print_context_field_names, NULL, 0);
1438 end:
1439 bt_put(main_field);
1440 return ret;
1441 }
1442
1443 static
1444 enum bt_component_status print_event_payload(struct pretty_component *pretty,
1445 struct bt_event *event)
1446 {
1447 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1448 struct bt_field *main_field = NULL;
1449
1450 main_field = bt_event_get_event_payload(event);
1451 if (!main_field) {
1452 goto end;
1453 }
1454 if (!pretty->start_line) {
1455 g_string_append(pretty->string, ", ");
1456 }
1457 pretty->start_line = false;
1458 if (pretty->options.print_scope_field_names) {
1459 print_name_equal(pretty, "event.fields");
1460 }
1461 ret = print_field(pretty, main_field,
1462 pretty->options.print_payload_field_names, NULL, 0);
1463 end:
1464 bt_put(main_field);
1465 return ret;
1466 }
1467
1468 static
1469 int flush_buf(struct pretty_component *pretty)
1470 {
1471 int ret = 0;
1472
1473 if (pretty->string->len == 0) {
1474 goto end;
1475 }
1476
1477 if (fwrite(pretty->string->str, pretty->string->len, 1, pretty->out) != 1) {
1478 ret = -1;
1479 }
1480
1481 end:
1482 return ret;
1483 }
1484
1485 BT_HIDDEN
1486 enum bt_component_status pretty_print_event(struct pretty_component *pretty,
1487 struct bt_notification *event_notif)
1488 {
1489 enum bt_component_status ret;
1490 struct bt_event *event =
1491 bt_notification_event_get_event(event_notif);
1492 struct bt_clock_class_priority_map *cc_prio_map =
1493 bt_notification_event_get_clock_class_priority_map(event_notif);
1494
1495 BT_ASSERT(event);
1496 BT_ASSERT(cc_prio_map);
1497 pretty->start_line = true;
1498 g_string_assign(pretty->string, "");
1499 ret = print_event_header(pretty, event, cc_prio_map);
1500 if (ret != BT_COMPONENT_STATUS_OK) {
1501 goto end;
1502 }
1503
1504 ret = print_stream_packet_context(pretty, event);
1505 if (ret != BT_COMPONENT_STATUS_OK) {
1506 goto end;
1507 }
1508
1509 if (pretty->options.verbose) {
1510 ret = print_event_header_raw(pretty, event);
1511 if (ret != BT_COMPONENT_STATUS_OK) {
1512 goto end;
1513 }
1514 }
1515
1516 ret = print_stream_event_context(pretty, event);
1517 if (ret != BT_COMPONENT_STATUS_OK) {
1518 goto end;
1519 }
1520
1521 ret = print_event_context(pretty, event);
1522 if (ret != BT_COMPONENT_STATUS_OK) {
1523 goto end;
1524 }
1525
1526 ret = print_event_payload(pretty, event);
1527 if (ret != BT_COMPONENT_STATUS_OK) {
1528 goto end;
1529 }
1530
1531 g_string_append_c(pretty->string, '\n');
1532 if (flush_buf(pretty)) {
1533 ret = BT_COMPONENT_STATUS_ERROR;
1534 goto end;
1535 }
1536
1537 end:
1538 bt_put(event);
1539 bt_put(cc_prio_map);
1540 return ret;
1541 }
1542
1543 BT_HIDDEN
1544 enum bt_component_status pretty_print_discarded_elements(
1545 struct pretty_component *pretty,
1546 struct bt_notification *notif)
1547 {
1548 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1549 struct bt_stream *stream = NULL;
1550 struct bt_stream_class *stream_class = NULL;
1551 struct bt_trace *trace = NULL;
1552 const char *stream_name;
1553 const char *trace_name;
1554 const unsigned char *trace_uuid;
1555 int64_t stream_class_id;
1556 int64_t stream_id;
1557 bool is_discarded_events;
1558 int64_t count;
1559 struct bt_clock_value *clock_value = NULL;
1560
1561 /* Stream name */
1562 switch (bt_notification_get_type(notif)) {
1563 case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
1564 stream = bt_notification_discarded_events_get_stream(notif);
1565 count = bt_notification_discarded_events_get_count(notif);
1566 is_discarded_events = true;
1567 break;
1568 case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
1569 stream = bt_notification_discarded_packets_get_stream(notif);
1570 count = bt_notification_discarded_packets_get_count(notif);
1571 is_discarded_events = false;
1572 break;
1573 default:
1574 abort();
1575 }
1576
1577 BT_ASSERT(stream);
1578 stream_name = bt_stream_get_name(stream);
1579
1580 /* Stream class ID */
1581 stream_class = bt_stream_get_class(stream);
1582 BT_ASSERT(stream_class);
1583 stream_class_id = bt_stream_class_get_id(stream_class);
1584
1585 /* Stream ID */
1586 stream_id = bt_stream_get_id(stream);
1587
1588 /* Trace path */
1589 trace = bt_stream_class_get_trace(stream_class);
1590 BT_ASSERT(trace);
1591 trace_name = bt_trace_get_name(trace);
1592 if (!trace_name) {
1593 trace_name = "(unknown)";
1594 }
1595
1596 /* Trace UUID */
1597 trace_uuid = bt_trace_get_uuid(trace);
1598
1599 /*
1600 * Print to standard error stream to remain backward compatible
1601 * with Babeltrace 1.
1602 */
1603 fprintf(stderr,
1604 "%s%sWARNING%s%s: Tracer discarded %" PRId64 " %s%s between [",
1605 bt_common_color_fg_yellow(),
1606 bt_common_color_bold(),
1607 bt_common_color_reset(),
1608 bt_common_color_fg_yellow(),
1609 count, is_discarded_events ? "event" : "packet",
1610 count == 1 ? "" : "s");
1611 g_string_assign(pretty->string, "");
1612 clock_value = is_discarded_events ?
1613 bt_notification_discarded_events_get_begin_clock_value(notif) :
1614 bt_notification_discarded_packets_get_begin_clock_value(notif);
1615 print_timestamp_wall(pretty, clock_value);
1616 BT_PUT(clock_value);
1617 fprintf(stderr, "%s] and [", pretty->string->str);
1618 g_string_assign(pretty->string, "");
1619 clock_value = is_discarded_events ?
1620 bt_notification_discarded_events_get_end_clock_value(notif) :
1621 bt_notification_discarded_packets_get_end_clock_value(notif);
1622 print_timestamp_wall(pretty, clock_value);
1623 BT_PUT(clock_value);
1624 fprintf(stderr, "%s] in trace \"%s\" ",
1625 pretty->string->str, trace_name);
1626
1627 if (trace_uuid) {
1628 fprintf(stderr,
1629 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1630 trace_uuid[0],
1631 trace_uuid[1],
1632 trace_uuid[2],
1633 trace_uuid[3],
1634 trace_uuid[4],
1635 trace_uuid[5],
1636 trace_uuid[6],
1637 trace_uuid[7],
1638 trace_uuid[8],
1639 trace_uuid[9],
1640 trace_uuid[10],
1641 trace_uuid[11],
1642 trace_uuid[12],
1643 trace_uuid[13],
1644 trace_uuid[14],
1645 trace_uuid[15]);
1646 } else {
1647 fprintf(stderr, "(no UUID) ");
1648 }
1649
1650 fprintf(stderr, "within stream \"%s\" (stream class ID: %" PRId64 ", ",
1651 stream_name, stream_class_id);
1652
1653 if (stream_id >= 0) {
1654 fprintf(stderr, "stream ID: %" PRId64, stream_id);
1655 } else {
1656 fprintf(stderr, "no stream ID");
1657 }
1658
1659 fprintf(stderr, ").%s\n", bt_common_color_reset());
1660 bt_put(stream);
1661 bt_put(stream_class);
1662 bt_put(trace);
1663 bt_put(clock_value);
1664 return ret;
1665 }
This page took 0.134787 seconds and 5 git commands to generate.