97e9bf11ce1aa3bb9a73cba8a60ea35da8220720
[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 if (!iter) {
853 ret = BT_COMPONENT_STATUS_ERROR;
854 goto end;
855 }
856 g_string_append(pretty->string, "( ");
857 for (;;) {
858 const char *mapping_name;
859
860 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
861 iter, &mapping_name, NULL, NULL) < 0) {
862 ret = BT_COMPONENT_STATUS_ERROR;
863 goto end;
864 }
865 if (nr_mappings++)
866 g_string_append(pretty->string, ", ");
867 if (pretty->use_colors) {
868 g_string_append(pretty->string, COLOR_ENUM_MAPPING_NAME);
869 }
870 print_escape_string(pretty, mapping_name);
871 if (pretty->use_colors) {
872 g_string_append(pretty->string, COLOR_RST);
873 }
874 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) {
875 break;
876 }
877 }
878 if (!nr_mappings) {
879 if (pretty->use_colors) {
880 g_string_append(pretty->string, COLOR_UNKNOWN);
881 }
882 g_string_append(pretty->string, "<unknown>");
883 if (pretty->use_colors) {
884 g_string_append(pretty->string, COLOR_RST);
885 }
886 }
887 g_string_append(pretty->string, " : container = ");
888 ret = print_integer(pretty, container_field);
889 if (ret != BT_COMPONENT_STATUS_OK) {
890 goto end;
891 }
892 g_string_append(pretty->string, " )");
893 end:
894 bt_put(iter);
895 bt_put(container_field_type);
896 bt_put(container_field);
897 bt_put(enumeration_field_type);
898 return ret;
899 }
900
901 static
902 int filter_field_name(struct pretty_component *pretty, const char *field_name,
903 GQuark *filter_fields, int filter_array_len)
904 {
905 int i;
906 GQuark field_quark = g_quark_try_string(field_name);
907
908 if (!field_quark || pretty->options.verbose) {
909 return 1;
910 }
911
912 for (i = 0; i < filter_array_len; i++) {
913 if (field_quark == filter_fields[i]) {
914 return 0;
915 }
916 }
917 return 1;
918 }
919
920 static
921 enum bt_component_status print_struct_field(struct pretty_component *pretty,
922 struct bt_ctf_field *_struct,
923 struct bt_ctf_field_type *struct_type,
924 int i, bool print_names, int *nr_printed_fields,
925 GQuark *filter_fields, int filter_array_len)
926 {
927 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
928 const char *field_name;
929 struct bt_ctf_field *field = NULL;
930 struct bt_ctf_field_type *field_type = NULL;;
931
932 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
933 if (!field) {
934 ret = BT_COMPONENT_STATUS_ERROR;
935 goto end;
936 }
937 if (bt_ctf_field_type_structure_get_field(struct_type,
938 &field_name, &field_type, i) < 0) {
939 ret = BT_COMPONENT_STATUS_ERROR;
940 goto end;
941 }
942
943 if (filter_fields && !filter_field_name(pretty, field_name,
944 filter_fields, filter_array_len)) {
945 ret = BT_COMPONENT_STATUS_OK;
946 goto end;
947 }
948
949 if (*nr_printed_fields > 0) {
950 g_string_append(pretty->string, ", ");
951 } else {
952 g_string_append(pretty->string, " ");
953 }
954 if (print_names) {
955 print_field_name_equal(pretty, rem_(field_name));
956 }
957 ret = print_field(pretty, field, print_names, NULL, 0);
958 *nr_printed_fields += 1;
959 end:
960 bt_put(field_type);
961 bt_put(field);
962 return ret;
963 }
964
965 static
966 enum bt_component_status print_struct(struct pretty_component *pretty,
967 struct bt_ctf_field *_struct, bool print_names,
968 GQuark *filter_fields, int filter_array_len)
969 {
970 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
971 struct bt_ctf_field_type *struct_type = NULL;
972 int nr_fields, i, nr_printed_fields;
973
974 struct_type = bt_ctf_field_get_type(_struct);
975 if (!struct_type) {
976 ret = BT_COMPONENT_STATUS_ERROR;
977 goto end;
978 }
979 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
980 if (nr_fields < 0) {
981 ret = BT_COMPONENT_STATUS_ERROR;
982 goto end;
983 }
984 g_string_append(pretty->string, "{");
985 pretty->depth++;
986 nr_printed_fields = 0;
987 for (i = 0; i < nr_fields; i++) {
988 ret = print_struct_field(pretty, _struct, struct_type, i,
989 print_names, &nr_printed_fields, filter_fields,
990 filter_array_len);
991 if (ret != BT_COMPONENT_STATUS_OK) {
992 goto end;
993 }
994 }
995 pretty->depth--;
996 g_string_append(pretty->string, " }");
997 end:
998 bt_put(struct_type);
999 return ret;
1000 }
1001
1002 static
1003 enum bt_component_status print_array_field(struct pretty_component *pretty,
1004 struct bt_ctf_field *array, uint64_t i,
1005 bool is_string, bool print_names)
1006 {
1007 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1008 struct bt_ctf_field *field = NULL;
1009
1010 if (!is_string) {
1011 if (i != 0) {
1012 g_string_append(pretty->string, ", ");
1013 } else {
1014 g_string_append(pretty->string, " ");
1015 }
1016 if (print_names) {
1017 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1018 }
1019 }
1020 field = bt_ctf_field_array_get_field(array, i);
1021 if (!field) {
1022 ret = BT_COMPONENT_STATUS_ERROR;
1023 goto end;
1024 }
1025 ret = print_field(pretty, field, print_names, NULL, 0);
1026 end:
1027 bt_put(field);
1028 return ret;
1029 }
1030
1031 static
1032 enum bt_component_status print_array(struct pretty_component *pretty,
1033 struct bt_ctf_field *array, bool print_names)
1034 {
1035 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1036 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
1037 enum bt_ctf_field_type_id type_id;
1038 int64_t len;
1039 uint64_t i;
1040 bool is_string = false;
1041
1042 array_type = bt_ctf_field_get_type(array);
1043 if (!array_type) {
1044 ret = BT_COMPONENT_STATUS_ERROR;
1045 goto end;
1046 }
1047 field_type = bt_ctf_field_type_array_get_element_type(array_type);
1048 if (!field_type) {
1049 ret = BT_COMPONENT_STATUS_ERROR;
1050 goto end;
1051 }
1052 len = bt_ctf_field_type_array_get_length(array_type);
1053 if (len < 0) {
1054 ret = BT_COMPONENT_STATUS_ERROR;
1055 goto end;
1056 }
1057 type_id = bt_ctf_field_type_get_type_id(field_type);
1058 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1059 enum bt_ctf_string_encoding encoding;
1060
1061 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1062 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1063 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1064 int integer_len, integer_alignment;
1065
1066 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1067 if (integer_len < 0) {
1068 return BT_COMPONENT_STATUS_ERROR;
1069 }
1070 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1071 if (integer_alignment < 0) {
1072 return BT_COMPONENT_STATUS_ERROR;
1073 }
1074 if (integer_len == CHAR_BIT
1075 && integer_alignment == CHAR_BIT) {
1076 is_string = true;
1077 }
1078 }
1079 }
1080
1081 if (is_string) {
1082 g_string_assign(pretty->tmp_string, "");
1083 } else {
1084 g_string_append(pretty->string, "[");
1085 }
1086
1087 pretty->depth++;
1088 for (i = 0; i < len; i++) {
1089 ret = print_array_field(pretty, array, i, is_string, print_names);
1090 if (ret != BT_COMPONENT_STATUS_OK) {
1091 goto end;
1092 }
1093 }
1094 pretty->depth--;
1095
1096 if (is_string) {
1097 if (pretty->use_colors) {
1098 g_string_append(pretty->string, COLOR_STRING_VALUE);
1099 }
1100 print_escape_string(pretty, pretty->tmp_string->str);
1101 if (pretty->use_colors) {
1102 g_string_append(pretty->string, COLOR_RST);
1103 }
1104 } else {
1105 g_string_append(pretty->string, " ]");
1106 }
1107 end:
1108 bt_put(field_type);
1109 bt_put(array_type);
1110 return ret;
1111 }
1112
1113 static
1114 enum bt_component_status print_sequence_field(struct pretty_component *pretty,
1115 struct bt_ctf_field *seq, uint64_t i,
1116 bool is_string, bool print_names)
1117 {
1118 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1119 struct bt_ctf_field *field = NULL;
1120
1121 if (!is_string) {
1122 if (i != 0) {
1123 g_string_append(pretty->string, ", ");
1124 } else {
1125 g_string_append(pretty->string, " ");
1126 }
1127 if (print_names) {
1128 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1129 }
1130 }
1131 field = bt_ctf_field_sequence_get_field(seq, i);
1132 if (!field) {
1133 ret = BT_COMPONENT_STATUS_ERROR;
1134 goto end;
1135 }
1136 ret = print_field(pretty, field, print_names, NULL, 0);
1137 end:
1138 bt_put(field);
1139 return ret;
1140 }
1141
1142 static
1143 enum bt_component_status print_sequence(struct pretty_component *pretty,
1144 struct bt_ctf_field *seq, bool print_names)
1145 {
1146 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1147 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
1148 struct bt_ctf_field *length_field = NULL;
1149 enum bt_ctf_field_type_id type_id;
1150 uint64_t len;
1151 uint64_t i;
1152 bool is_string = false;
1153
1154 seq_type = bt_ctf_field_get_type(seq);
1155 if (!seq_type) {
1156 ret = BT_COMPONENT_STATUS_ERROR;
1157 goto end;
1158 }
1159 length_field = bt_ctf_field_sequence_get_length(seq);
1160 if (!length_field) {
1161 ret = BT_COMPONENT_STATUS_ERROR;
1162 goto end;
1163 }
1164 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
1165 ret = BT_COMPONENT_STATUS_ERROR;
1166 goto end;
1167 }
1168 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
1169 if (!field_type) {
1170 ret = BT_COMPONENT_STATUS_ERROR;
1171 goto end;
1172 }
1173 type_id = bt_ctf_field_type_get_type_id(field_type);
1174 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1175 enum bt_ctf_string_encoding encoding;
1176
1177 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1178 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1179 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1180 int integer_len, integer_alignment;
1181
1182 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1183 if (integer_len < 0) {
1184 ret = BT_COMPONENT_STATUS_ERROR;
1185 goto end;
1186 }
1187 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1188 if (integer_alignment < 0) {
1189 ret = BT_COMPONENT_STATUS_ERROR;
1190 goto end;
1191 }
1192 if (integer_len == CHAR_BIT
1193 && integer_alignment == CHAR_BIT) {
1194 is_string = true;
1195 }
1196 }
1197 }
1198
1199 if (is_string) {
1200 g_string_assign(pretty->tmp_string, "");
1201 } else {
1202 g_string_append(pretty->string, "[");
1203 }
1204
1205 pretty->depth++;
1206 for (i = 0; i < len; i++) {
1207 ret = print_sequence_field(pretty, seq, i,
1208 is_string, print_names);
1209 if (ret != BT_COMPONENT_STATUS_OK) {
1210 goto end;
1211 }
1212 }
1213 pretty->depth--;
1214
1215 if (is_string) {
1216 if (pretty->use_colors) {
1217 g_string_append(pretty->string, COLOR_STRING_VALUE);
1218 }
1219 print_escape_string(pretty, pretty->tmp_string->str);
1220 if (pretty->use_colors) {
1221 g_string_append(pretty->string, COLOR_RST);
1222 }
1223 } else {
1224 g_string_append(pretty->string, " ]");
1225 }
1226 end:
1227 bt_put(length_field);
1228 bt_put(field_type);
1229 bt_put(seq_type);
1230 return ret;
1231 }
1232
1233 static
1234 enum bt_component_status print_variant(struct pretty_component *pretty,
1235 struct bt_ctf_field *variant, bool print_names)
1236 {
1237 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1238 struct bt_ctf_field *field = NULL;
1239
1240 field = bt_ctf_field_variant_get_current_field(variant);
1241 if (!field) {
1242 ret = BT_COMPONENT_STATUS_ERROR;
1243 goto end;
1244 }
1245 g_string_append(pretty->string, "{ ");
1246 pretty->depth++;
1247 if (print_names) {
1248 int iter_ret;
1249 struct bt_ctf_field *tag_field = NULL;
1250 const char *tag_choice;
1251 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
1252
1253 tag_field = bt_ctf_field_variant_get_tag(variant);
1254 if (!tag_field) {
1255 ret = BT_COMPONENT_STATUS_ERROR;
1256 goto end;
1257 }
1258
1259 iter = bt_ctf_field_enumeration_get_mappings(tag_field);
1260 if (!iter) {
1261 bt_put(tag_field);
1262 ret = BT_COMPONENT_STATUS_ERROR;
1263 goto end;
1264 }
1265
1266 iter_ret =
1267 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1268 iter, &tag_choice, NULL, NULL);
1269 if (iter_ret) {
1270 bt_put(iter);
1271 bt_put(tag_field);
1272 ret = BT_COMPONENT_STATUS_ERROR;
1273 goto end;
1274 }
1275 print_field_name_equal(pretty, rem_(tag_choice));
1276 bt_put(tag_field);
1277 bt_put(iter);
1278 }
1279 ret = print_field(pretty, field, print_names, NULL, 0);
1280 if (ret != BT_COMPONENT_STATUS_OK) {
1281 goto end;
1282 }
1283 pretty->depth--;
1284 g_string_append(pretty->string, " }");
1285 end:
1286 bt_put(field);
1287 return ret;
1288 }
1289
1290 static
1291 enum bt_component_status print_field(struct pretty_component *pretty,
1292 struct bt_ctf_field *field, bool print_names,
1293 GQuark *filter_fields, int filter_array_len)
1294 {
1295 enum bt_ctf_field_type_id type_id;
1296
1297 type_id = bt_ctf_field_get_type_id(field);
1298 switch (type_id) {
1299 case CTF_TYPE_INTEGER:
1300 return print_integer(pretty, field);
1301 case CTF_TYPE_FLOAT:
1302 {
1303 double v;
1304
1305 if (bt_ctf_field_floating_point_get_value(field, &v)) {
1306 return BT_COMPONENT_STATUS_ERROR;
1307 }
1308 if (pretty->use_colors) {
1309 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
1310 }
1311 g_string_append_printf(pretty->string, "%g", v);
1312 if (pretty->use_colors) {
1313 g_string_append(pretty->string, COLOR_RST);
1314 }
1315 return BT_COMPONENT_STATUS_OK;
1316 }
1317 case CTF_TYPE_ENUM:
1318 return print_enum(pretty, field);
1319 case CTF_TYPE_STRING:
1320 {
1321 const char *str;
1322
1323 str = bt_ctf_field_string_get_value(field);
1324 if (!str) {
1325 return BT_COMPONENT_STATUS_ERROR;
1326 }
1327
1328 if (pretty->use_colors) {
1329 g_string_append(pretty->string, COLOR_STRING_VALUE);
1330 }
1331 print_escape_string(pretty, str);
1332 if (pretty->use_colors) {
1333 g_string_append(pretty->string, COLOR_RST);
1334 }
1335 return BT_COMPONENT_STATUS_OK;
1336 }
1337 case CTF_TYPE_STRUCT:
1338 return print_struct(pretty, field, print_names, filter_fields,
1339 filter_array_len);
1340 case CTF_TYPE_VARIANT:
1341 return print_variant(pretty, field, print_names);
1342 case CTF_TYPE_ARRAY:
1343 return print_array(pretty, field, print_names);
1344 case CTF_TYPE_SEQUENCE:
1345 return print_sequence(pretty, field, print_names);
1346 default:
1347 // TODO: log instead
1348 fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id);
1349 return BT_COMPONENT_STATUS_ERROR;
1350 }
1351 }
1352
1353 static
1354 enum bt_component_status print_stream_packet_context(struct pretty_component *pretty,
1355 struct bt_ctf_event *event)
1356 {
1357 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1358 struct bt_ctf_packet *packet = NULL;
1359 struct bt_ctf_field *main_field = NULL;
1360
1361 packet = bt_ctf_event_get_packet(event);
1362 if (!packet) {
1363 ret = BT_COMPONENT_STATUS_ERROR;
1364 goto end;
1365 }
1366 main_field = bt_ctf_packet_get_context(packet);
1367 if (!main_field) {
1368 goto end;
1369 }
1370 if (!pretty->start_line) {
1371 g_string_append(pretty->string, ", ");
1372 }
1373 pretty->start_line = false;
1374 if (pretty->options.print_scope_field_names) {
1375 print_name_equal(pretty, "stream.packet.context");
1376 }
1377 ret = print_field(pretty, main_field,
1378 pretty->options.print_context_field_names,
1379 stream_packet_context_quarks,
1380 STREAM_PACKET_CONTEXT_QUARKS_LEN);
1381 end:
1382 bt_put(main_field);
1383 bt_put(packet);
1384 return ret;
1385 }
1386
1387 static
1388 enum bt_component_status print_event_header_raw(struct pretty_component *pretty,
1389 struct bt_ctf_event *event)
1390 {
1391 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1392 struct bt_ctf_field *main_field = NULL;
1393
1394 main_field = bt_ctf_event_get_header(event);
1395 if (!main_field) {
1396 goto end;
1397 }
1398 if (!pretty->start_line) {
1399 g_string_append(pretty->string, ", ");
1400 }
1401 pretty->start_line = false;
1402 if (pretty->options.print_scope_field_names) {
1403 print_name_equal(pretty, "stream.event.header");
1404 }
1405 ret = print_field(pretty, main_field,
1406 pretty->options.print_header_field_names, NULL, 0);
1407 end:
1408 bt_put(main_field);
1409 return ret;
1410 }
1411
1412 static
1413 enum bt_component_status print_stream_event_context(struct pretty_component *pretty,
1414 struct bt_ctf_event *event)
1415 {
1416 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1417 struct bt_ctf_field *main_field = NULL;
1418
1419 main_field = bt_ctf_event_get_stream_event_context(event);
1420 if (!main_field) {
1421 goto end;
1422 }
1423 if (!pretty->start_line) {
1424 g_string_append(pretty->string, ", ");
1425 }
1426 pretty->start_line = false;
1427 if (pretty->options.print_scope_field_names) {
1428 print_name_equal(pretty, "stream.event.context");
1429 }
1430 ret = print_field(pretty, main_field,
1431 pretty->options.print_context_field_names, NULL, 0);
1432 end:
1433 bt_put(main_field);
1434 return ret;
1435 }
1436
1437 static
1438 enum bt_component_status print_event_context(struct pretty_component *pretty,
1439 struct bt_ctf_event *event)
1440 {
1441 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1442 struct bt_ctf_field *main_field = NULL;
1443
1444 main_field = bt_ctf_event_get_event_context(event);
1445 if (!main_field) {
1446 goto end;
1447 }
1448 if (!pretty->start_line) {
1449 g_string_append(pretty->string, ", ");
1450 }
1451 pretty->start_line = false;
1452 if (pretty->options.print_scope_field_names) {
1453 print_name_equal(pretty, "event.context");
1454 }
1455 ret = print_field(pretty, main_field,
1456 pretty->options.print_context_field_names, NULL, 0);
1457 end:
1458 bt_put(main_field);
1459 return ret;
1460 }
1461
1462 static
1463 enum bt_component_status print_event_payload(struct pretty_component *pretty,
1464 struct bt_ctf_event *event)
1465 {
1466 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1467 struct bt_ctf_field *main_field = NULL;
1468
1469 main_field = bt_ctf_event_get_event_payload(event);
1470 if (!main_field) {
1471 goto end;
1472 }
1473 if (!pretty->start_line) {
1474 g_string_append(pretty->string, ", ");
1475 }
1476 pretty->start_line = false;
1477 if (pretty->options.print_scope_field_names) {
1478 print_name_equal(pretty, "event.fields");
1479 }
1480 ret = print_field(pretty, main_field,
1481 pretty->options.print_payload_field_names, NULL, 0);
1482 end:
1483 bt_put(main_field);
1484 return ret;
1485 }
1486
1487 static
1488 int flush_buf(struct pretty_component *pretty)
1489 {
1490 int ret = 0;
1491
1492 if (pretty->string->len == 0) {
1493 goto end;
1494 }
1495
1496 if (fwrite(pretty->string->str, pretty->string->len, 1, pretty->out) != 1) {
1497 ret = -1;
1498 }
1499
1500 end:
1501 return ret;
1502 }
1503
1504 BT_HIDDEN
1505 enum bt_component_status pretty_print_event(struct pretty_component *pretty,
1506 struct bt_notification *event_notif)
1507 {
1508 enum bt_component_status ret;
1509 struct bt_ctf_event *event =
1510 bt_notification_event_get_event(event_notif);
1511 struct bt_clock_class_priority_map *cc_prio_map =
1512 bt_notification_event_get_clock_class_priority_map(event_notif);
1513
1514 assert(event);
1515 assert(cc_prio_map);
1516 pretty->start_line = true;
1517 g_string_assign(pretty->string, "");
1518 ret = print_event_header(pretty, event, cc_prio_map);
1519 if (ret != BT_COMPONENT_STATUS_OK) {
1520 goto end;
1521 }
1522
1523 ret = print_stream_packet_context(pretty, event);
1524 if (ret != BT_COMPONENT_STATUS_OK) {
1525 goto end;
1526 }
1527
1528 if (pretty->options.verbose) {
1529 ret = print_event_header_raw(pretty, event);
1530 if (ret != BT_COMPONENT_STATUS_OK) {
1531 goto end;
1532 }
1533 }
1534
1535 ret = print_stream_event_context(pretty, event);
1536 if (ret != BT_COMPONENT_STATUS_OK) {
1537 goto end;
1538 }
1539
1540 ret = print_event_context(pretty, event);
1541 if (ret != BT_COMPONENT_STATUS_OK) {
1542 goto end;
1543 }
1544
1545 ret = print_event_payload(pretty, event);
1546 if (ret != BT_COMPONENT_STATUS_OK) {
1547 goto end;
1548 }
1549
1550 g_string_append_c(pretty->string, '\n');
1551 if (flush_buf(pretty)) {
1552 ret = BT_COMPONENT_STATUS_ERROR;
1553 goto end;
1554 }
1555
1556 end:
1557 bt_put(event);
1558 bt_put(cc_prio_map);
1559 return ret;
1560 }
1561
1562 BT_HIDDEN
1563 enum bt_component_status pretty_print_discarded_elements(
1564 struct pretty_component *pretty,
1565 struct bt_notification *notif)
1566 {
1567 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1568 struct bt_ctf_stream *stream = NULL;
1569 struct bt_ctf_stream_class *stream_class = NULL;
1570 struct bt_ctf_trace *trace = NULL;
1571 const char *stream_name;
1572 const char *trace_name;
1573 const unsigned char *trace_uuid;
1574 int64_t stream_class_id;
1575 int64_t stream_id;
1576 bool is_discarded_events;
1577 int64_t count;
1578 struct bt_ctf_clock_value *clock_value = NULL;
1579
1580 /* Stream name */
1581 switch (bt_notification_get_type(notif)) {
1582 case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
1583 stream = bt_notification_discarded_events_get_stream(notif);
1584 count = bt_notification_discarded_events_get_count(notif);
1585 is_discarded_events = true;
1586 break;
1587 case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
1588 stream = bt_notification_discarded_packets_get_stream(notif);
1589 count = bt_notification_discarded_packets_get_count(notif);
1590 is_discarded_events = false;
1591 break;
1592 default:
1593 abort();
1594 }
1595
1596 assert(stream);
1597 stream_name = bt_ctf_stream_get_name(stream);
1598
1599 /* Stream class ID */
1600 stream_class = bt_ctf_stream_get_class(stream);
1601 assert(stream_class);
1602 stream_class_id = bt_ctf_stream_class_get_id(stream_class);
1603
1604 /* Stream ID */
1605 stream_id = bt_ctf_stream_get_id(stream);
1606
1607 /* Trace path */
1608 trace = bt_ctf_stream_class_get_trace(stream_class);
1609 assert(trace);
1610 trace_name = bt_ctf_trace_get_name(trace);
1611 if (!trace_name) {
1612 trace_name = "(unknown)";
1613 }
1614
1615 /* Trace UUID */
1616 trace_uuid = bt_ctf_trace_get_uuid(trace);
1617
1618 /*
1619 * Print to standard error stream to remain backward compatible
1620 * with Babeltrace 1.
1621 */
1622 fprintf(stderr,
1623 "%s%sWARNING%s%s: Tracer discarded %" PRId64 " %s%s between [",
1624 bt_common_color_fg_yellow(),
1625 bt_common_color_bold(),
1626 bt_common_color_reset(),
1627 bt_common_color_fg_yellow(),
1628 count, is_discarded_events ? "event" : "packet",
1629 count == 1 ? "" : "s");
1630 g_string_assign(pretty->string, "");
1631 clock_value = is_discarded_events ?
1632 bt_notification_discarded_events_get_begin_clock_value(notif) :
1633 bt_notification_discarded_packets_get_begin_clock_value(notif);
1634 print_timestamp_wall(pretty, clock_value);
1635 BT_PUT(clock_value);
1636 fprintf(stderr, "%s] and [", pretty->string->str);
1637 g_string_assign(pretty->string, "");
1638 clock_value = is_discarded_events ?
1639 bt_notification_discarded_events_get_end_clock_value(notif) :
1640 bt_notification_discarded_packets_get_end_clock_value(notif);
1641 print_timestamp_wall(pretty, clock_value);
1642 BT_PUT(clock_value);
1643 fprintf(stderr, "%s] in trace \"%s\" ",
1644 pretty->string->str, trace_name);
1645
1646 if (trace_uuid) {
1647 fprintf(stderr,
1648 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1649 trace_uuid[0],
1650 trace_uuid[1],
1651 trace_uuid[2],
1652 trace_uuid[3],
1653 trace_uuid[4],
1654 trace_uuid[5],
1655 trace_uuid[6],
1656 trace_uuid[7],
1657 trace_uuid[8],
1658 trace_uuid[9],
1659 trace_uuid[10],
1660 trace_uuid[11],
1661 trace_uuid[12],
1662 trace_uuid[13],
1663 trace_uuid[14],
1664 trace_uuid[15]);
1665 } else {
1666 fprintf(stderr, "(no UUID) ");
1667 }
1668
1669 fprintf(stderr, "within stream \"%s\" (stream class ID: %" PRId64 ", ",
1670 stream_name, stream_class_id);
1671
1672 if (stream_id >= 0) {
1673 fprintf(stderr, "stream ID: %" PRId64, stream_id);
1674 } else {
1675 fprintf(stderr, "no stream ID");
1676 }
1677
1678 fprintf(stderr, ").%s\n", bt_common_color_reset());
1679 bt_put(stream);
1680 bt_put(stream_class);
1681 bt_put(trace);
1682 bt_put(clock_value);
1683 return ret;
1684 }
This page took 0.067427 seconds and 3 git commands to generate.