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