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