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