cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / plugins / text / pretty / print.c
CommitLineData
af9a82eb 1/*
0235b0db
MJ
2 * SPDX-License-Identifier: MIT
3 *
af9a82eb 4 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
f504043c 5 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
af9a82eb
JG
6 */
7
3fadfbc0 8#include <babeltrace2/babeltrace.h>
578e048b
MJ
9#include "compat/bitfield.h"
10#include "common/common.h"
6162e6b7 11#include "common/uuid.h"
578e048b
MJ
12#include "compat/time.h"
13#include "common/assert.h"
6a18b281 14#include <inttypes.h>
93a4161c 15#include <ctype.h>
c4f23e30 16#include <stdbool.h>
91d81473 17#include <string.h>
3228cc1d 18#include "pretty.h"
af9a82eb 19
1556a1af
JG
20#define NSEC_PER_SEC 1000000000LL
21
04609487
PP
22static char color_name[32];
23static char color_field_name[32];
24static char color_rst[32];
25static char color_string_value[32];
26static char color_number_value[32];
27static char color_enum_mapping_name[32];
28static char color_unknown[32];
29static char color_event_name[32];
30static char color_timestamp[32];
ad96d936 31
af9a82eb
JG
32struct timestamp {
33 int64_t real_timestamp; /* Relative to UNIX epoch. */
605e1019 34 uint64_t clock_snapshot; /* In cycles. */
af9a82eb
JG
35};
36
6a18b281 37static
d94d92ac 38int print_field(struct pretty_component *pretty,
2f84c7be 39 const bt_field *field, bool print_names);
6a18b281 40
ad96d936 41static
3228cc1d 42void print_name_equal(struct pretty_component *pretty, const char *name)
ad96d936 43{
3228cc1d 44 if (pretty->use_colors) {
04609487 45 bt_common_g_string_append(pretty->string, color_name);
dd61c4ed 46 bt_common_g_string_append(pretty->string, name);
04609487 47 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 48 } else {
dd61c4ed 49 bt_common_g_string_append(pretty->string, name);
ad96d936 50 }
dd61c4ed 51 bt_common_g_string_append(pretty->string, " = ");
ad96d936
PP
52}
53
54static
3228cc1d 55void print_field_name_equal(struct pretty_component *pretty, const char *name)
ad96d936 56{
3228cc1d 57 if (pretty->use_colors) {
04609487 58 bt_common_g_string_append(pretty->string, color_field_name);
dd61c4ed 59 bt_common_g_string_append(pretty->string, name);
04609487 60 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 61 } else {
dd61c4ed
MD
62 bt_common_g_string_append(pretty->string, name);
63 }
64 bt_common_g_string_append(pretty->string, " = ");
ad96d936
PP
65}
66
af9a82eb 67static
3228cc1d 68void print_timestamp_cycles(struct pretty_component *pretty,
9c202476 69 const bt_clock_snapshot *clock_snapshot, bool update_last)
af9a82eb 70{
1556a1af 71 uint64_t cycles;
1556a1af 72
605e1019 73 cycles = bt_clock_snapshot_get_value(clock_snapshot);
f354b1e1 74 bt_common_g_string_append_printf(pretty->string, "%020" PRIu64, cycles);
3af83b5a 75
9c202476
PP
76 if (update_last) {
77 if (pretty->last_cycles_timestamp != -1ULL) {
78 pretty->delta_cycles = cycles - pretty->last_cycles_timestamp;
79 }
2c091c04 80
9c202476
PP
81 pretty->last_cycles_timestamp = cycles;
82 }
af9a82eb
JG
83}
84
85static
3228cc1d 86void print_timestamp_wall(struct pretty_component *pretty,
9c202476 87 const bt_clock_snapshot *clock_snapshot, bool update_last)
af9a82eb 88{
1556a1af 89 int ret;
1556a1af
JG
90 int64_t ts_nsec = 0; /* add configurable offset */
91 int64_t ts_sec = 0; /* add configurable offset */
92 uint64_t ts_sec_abs, ts_nsec_abs;
93 bool is_negative;
af9a82eb 94
605e1019 95 if (!clock_snapshot) {
dd61c4ed 96 bt_common_g_string_append(pretty->string, "??:??:??.?????????");
1556a1af
JG
97 return;
98 }
99
605e1019 100 ret = bt_clock_snapshot_get_ns_from_origin(clock_snapshot, &ts_nsec);
1556a1af 101 if (ret) {
5280f742 102 // TODO: log, this is unexpected
dd61c4ed 103 bt_common_g_string_append(pretty->string, "Error");
1556a1af
JG
104 return;
105 }
106
9c202476
PP
107 if (update_last) {
108 if (pretty->last_real_timestamp != -1ULL) {
109 pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp;
110 }
111
112 pretty->last_real_timestamp = ts_nsec;
3af83b5a 113 }
3af83b5a 114
1556a1af
JG
115 ts_sec += ts_nsec / NSEC_PER_SEC;
116 ts_nsec = ts_nsec % NSEC_PER_SEC;
5280f742 117
1556a1af
JG
118 if (ts_sec >= 0 && ts_nsec >= 0) {
119 is_negative = false;
120 ts_sec_abs = ts_sec;
121 ts_nsec_abs = ts_nsec;
122 } else if (ts_sec > 0 && ts_nsec < 0) {
123 is_negative = false;
124 ts_sec_abs = ts_sec - 1;
125 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
126 } else if (ts_sec == 0 && ts_nsec < 0) {
127 is_negative = true;
128 ts_sec_abs = ts_sec;
129 ts_nsec_abs = -ts_nsec;
130 } else if (ts_sec < 0 && ts_nsec > 0) {
131 is_negative = true;
132 ts_sec_abs = -(ts_sec + 1);
133 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
134 } else if (ts_sec < 0 && ts_nsec == 0) {
135 is_negative = true;
136 ts_sec_abs = -ts_sec;
137 ts_nsec_abs = ts_nsec;
138 } else { /* (ts_sec < 0 && ts_nsec < 0) */
139 is_negative = true;
140 ts_sec_abs = -ts_sec;
141 ts_nsec_abs = -ts_nsec;
142 }
143
3228cc1d 144 if (!pretty->options.clock_seconds) {
1556a1af
JG
145 struct tm tm;
146 time_t time_s = (time_t) ts_sec_abs;
147
18adbd19 148 if (is_negative && !pretty->negative_timestamp_warning_done) {
5280f742 149 // TODO: log instead
1556a1af 150 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
18adbd19 151 pretty->negative_timestamp_warning_done = true;
1556a1af
JG
152 goto seconds;
153 }
154
3228cc1d 155 if (!pretty->options.clock_gmt) {
1556a1af
JG
156 struct tm *res;
157
58a2480d 158 res = bt_localtime_r(&time_s, &tm);
1556a1af 159 if (!res) {
5280f742 160 // TODO: log instead
1556a1af
JG
161 fprintf(stderr, "[warning] Unable to get localtime.\n");
162 goto seconds;
163 }
164 } else {
165 struct tm *res;
166
58a2480d 167 res = bt_gmtime_r(&time_s, &tm);
1556a1af 168 if (!res) {
5280f742 169 // TODO: log instead
1556a1af
JG
170 fprintf(stderr, "[warning] Unable to get gmtime.\n");
171 goto seconds;
172 }
173 }
3228cc1d 174 if (pretty->options.clock_date) {
1556a1af
JG
175 char timestr[26];
176 size_t res;
177
178 /* Print date and time */
179 res = strftime(timestr, sizeof(timestr),
4d2a94f1 180 "%Y-%m-%d ", &tm);
1556a1af 181 if (!res) {
5280f742 182 // TODO: log instead
1556a1af
JG
183 fprintf(stderr, "[warning] Unable to print ascii time.\n");
184 goto seconds;
185 }
5280f742 186
dd61c4ed 187 bt_common_g_string_append(pretty->string, timestr);
1556a1af 188 }
5280f742 189
1556a1af 190 /* Print time in HH:MM:SS.ns */
f354b1e1 191 bt_common_g_string_append_printf(pretty->string,
5280f742
PP
192 "%02d:%02d:%02d.%09" PRIu64, tm.tm_hour, tm.tm_min,
193 tm.tm_sec, ts_nsec_abs);
1556a1af
JG
194 goto end;
195 }
196seconds:
f354b1e1 197 bt_common_g_string_append_printf(pretty->string, "%s%" PRId64 ".%09" PRIu64,
5280f742 198 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
1556a1af
JG
199end:
200 return;
af9a82eb
JG
201}
202
203static
d94d92ac 204int print_event_timestamp(struct pretty_component *pretty,
2c091c04 205 const bt_message *event_msg, bool *start_line)
af9a82eb 206{
3228cc1d 207 bool print_names = pretty->options.print_header_field_names;
d94d92ac 208 int ret = 0;
605e1019 209 const bt_clock_snapshot *clock_snapshot = NULL;
af9a82eb 210
81c25620
PP
211 if (!bt_message_event_borrow_stream_class_default_clock_class_const(
212 event_msg)) {
2c091c04 213 /* No default clock class: skip the timestamp without an error */
f504043c
MD
214 goto end;
215 }
d9f65f09 216
0cbc2c33 217 clock_snapshot = bt_message_event_borrow_default_clock_snapshot_const(event_msg);
af9a82eb 218
ad96d936 219 if (print_names) {
3228cc1d 220 print_name_equal(pretty, "timestamp");
ad96d936 221 } else {
dd61c4ed 222 bt_common_g_string_append(pretty->string, "[");
ad96d936 223 }
3228cc1d 224 if (pretty->use_colors) {
04609487 225 bt_common_g_string_append(pretty->string, color_timestamp);
ad96d936 226 }
3228cc1d 227 if (pretty->options.print_timestamp_cycles) {
9c202476 228 print_timestamp_cycles(pretty, clock_snapshot, true);
af9a82eb 229 } else {
9c202476 230 print_timestamp_wall(pretty, clock_snapshot, true);
af9a82eb 231 }
3228cc1d 232 if (pretty->use_colors) {
04609487 233 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 234 }
af9a82eb 235
c3c30b08 236 if (!print_names)
dd61c4ed 237 bt_common_g_string_append(pretty->string, "] ");
c3c30b08 238
3228cc1d 239 if (pretty->options.print_delta_field) {
ad96d936 240 if (print_names) {
dd61c4ed 241 bt_common_g_string_append(pretty->string, ", ");
3228cc1d 242 print_name_equal(pretty, "delta");
ad96d936 243 } else {
dd61c4ed 244 bt_common_g_string_append(pretty->string, "(");
ad96d936 245 }
3228cc1d
PP
246 if (pretty->options.print_timestamp_cycles) {
247 if (pretty->delta_cycles == -1ULL) {
dd61c4ed 248 bt_common_g_string_append(pretty->string,
c6a871e9 249 "+??????????\?\?"); /* Not a trigraph. */
3af83b5a 250 } else {
f354b1e1 251 bt_common_g_string_append_printf(pretty->string,
5280f742 252 "+%012" PRIu64, pretty->delta_cycles);
3af83b5a
MD
253 }
254 } else {
3228cc1d 255 if (pretty->delta_real_timestamp != -1ULL) {
3af83b5a 256 uint64_t delta_sec, delta_nsec, delta;
f504043c 257
3228cc1d 258 delta = pretty->delta_real_timestamp;
3af83b5a
MD
259 delta_sec = delta / NSEC_PER_SEC;
260 delta_nsec = delta % NSEC_PER_SEC;
f354b1e1 261 bt_common_g_string_append_printf(pretty->string,
5280f742 262 "+%" PRIu64 ".%09" PRIu64,
3af83b5a
MD
263 delta_sec, delta_nsec);
264 } else {
dd61c4ed 265 bt_common_g_string_append(pretty->string, "+?.?????????");
3af83b5a
MD
266 }
267 }
268 if (!print_names) {
dd61c4ed 269 bt_common_g_string_append(pretty->string, ") ");
3af83b5a
MD
270 }
271 }
272 *start_line = !print_names;
f504043c 273
af9a82eb 274end:
af9a82eb
JG
275 return ret;
276}
277
6a18b281 278static
d94d92ac 279int print_event_header(struct pretty_component *pretty,
2c091c04 280 const bt_message *event_msg)
af9a82eb 281{
3228cc1d 282 bool print_names = pretty->options.print_header_field_names;
d94d92ac 283 int ret = 0;
b19ff26f 284 const bt_event_class *event_class = NULL;
b19ff26f
PP
285 const bt_stream *stream = NULL;
286 const bt_trace *trace = NULL;
2c091c04 287 const bt_event *event = bt_message_event_borrow_event_const(event_msg);
64925bba 288 const char *ev_name;
60535549 289 int dom_print = 0;
4cdfc5e8 290 bt_property_availability prop_avail;
af9a82eb 291
40f4ba76 292 event_class = bt_event_borrow_class_const(event);
26fc5aed 293 stream = bt_event_borrow_stream_const(event);
862ca4ed 294 trace = bt_stream_borrow_trace_const(stream);
2c091c04 295 ret = print_event_timestamp(pretty, event_msg, &pretty->start_line);
d94d92ac 296 if (ret) {
af9a82eb
JG
297 goto end;
298 }
3228cc1d 299 if (pretty->options.print_trace_field) {
c3c30b08
MD
300 const char *name;
301
862ca4ed 302 name = bt_trace_get_name(trace);
c3c30b08 303 if (name) {
3228cc1d 304 if (!pretty->start_line) {
dd61c4ed 305 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 306 }
c3c30b08 307 if (print_names) {
3228cc1d 308 print_name_equal(pretty, "trace");
c3c30b08 309 }
5280f742 310
dd61c4ed 311 bt_common_g_string_append(pretty->string, name);
5280f742 312
22b7fdc6 313 if (print_names) {
dd61c4ed 314 bt_common_g_string_append(pretty->string, ", ");
60535549 315 }
c3c30b08
MD
316 }
317 }
3228cc1d 318 if (pretty->options.print_trace_hostname_field) {
b19ff26f 319 const bt_value *hostname_str;
c3c30b08 320
335a2da5
PP
321 hostname_str = bt_trace_borrow_environment_entry_value_by_name_const(
322 trace, "hostname");
c3c30b08
MD
323 if (hostname_str) {
324 const char *str;
325
3228cc1d 326 if (!pretty->start_line) {
dd61c4ed 327 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 328 }
c3c30b08 329 if (print_names) {
3228cc1d 330 print_name_equal(pretty, "trace:hostname");
c3c30b08 331 }
601b0d3c 332 str = bt_value_string_get(hostname_str);
dd61c4ed 333 bt_common_g_string_append(pretty->string, str);
60535549 334 dom_print = 1;
c3c30b08
MD
335 }
336 }
3228cc1d 337 if (pretty->options.print_trace_domain_field) {
b19ff26f 338 const bt_value *domain_str;
c3c30b08 339
335a2da5
PP
340 domain_str = bt_trace_borrow_environment_entry_value_by_name_const(
341 trace, "domain");
c3c30b08
MD
342 if (domain_str) {
343 const char *str;
344
3228cc1d 345 if (!pretty->start_line) {
dd61c4ed 346 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 347 }
c3c30b08 348 if (print_names) {
3228cc1d 349 print_name_equal(pretty, "trace:domain");
60535549 350 } else if (dom_print) {
dd61c4ed 351 bt_common_g_string_append(pretty->string, ":");
c3c30b08 352 }
601b0d3c 353 str = bt_value_string_get(domain_str);
dd61c4ed 354 bt_common_g_string_append(pretty->string, str);
60535549 355 dom_print = 1;
c3c30b08
MD
356 }
357 }
3228cc1d 358 if (pretty->options.print_trace_procname_field) {
b19ff26f 359 const bt_value *procname_str;
c3c30b08 360
335a2da5
PP
361 procname_str = bt_trace_borrow_environment_entry_value_by_name_const(
362 trace, "procname");
c3c30b08
MD
363 if (procname_str) {
364 const char *str;
365
3228cc1d 366 if (!pretty->start_line) {
dd61c4ed 367 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 368 }
c3c30b08 369 if (print_names) {
3228cc1d 370 print_name_equal(pretty, "trace:procname");
60535549 371 } else if (dom_print) {
dd61c4ed 372 bt_common_g_string_append(pretty->string, ":");
c3c30b08 373 }
601b0d3c 374 str = bt_value_string_get(procname_str);
dd61c4ed 375 bt_common_g_string_append(pretty->string, str);
60535549 376 dom_print = 1;
c3c30b08
MD
377 }
378 }
3228cc1d 379 if (pretty->options.print_trace_vpid_field) {
b19ff26f 380 const bt_value *vpid_value;
c3c30b08 381
335a2da5
PP
382 vpid_value = bt_trace_borrow_environment_entry_value_by_name_const(
383 trace, "vpid");
c3c30b08
MD
384 if (vpid_value) {
385 int64_t value;
386
3228cc1d 387 if (!pretty->start_line) {
dd61c4ed 388 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 389 }
c3c30b08 390 if (print_names) {
3228cc1d 391 print_name_equal(pretty, "trace:vpid");
60535549 392 } else if (dom_print) {
dd61c4ed 393 bt_common_g_string_append(pretty->string, ":");
c3c30b08 394 }
9c08c816 395 value = bt_value_integer_signed_get(vpid_value);
f354b1e1 396 bt_common_g_string_append_printf(pretty->string,
601b0d3c 397 "(%" PRId64 ")", value);
60535549 398 dom_print = 1;
c3c30b08
MD
399 }
400 }
3228cc1d 401 if (pretty->options.print_loglevel_field) {
cf76ce92 402 static const char *log_level_names[] = {
50842bdc
PP
403 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY ] = "TRACE_EMERG",
404 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT ] = "TRACE_ALERT",
405 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL ] = "TRACE_CRIT",
406 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR ] = "TRACE_ERR",
407 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING ] = "TRACE_WARNING",
408 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE ] = "TRACE_NOTICE",
409 [ BT_EVENT_CLASS_LOG_LEVEL_INFO ] = "TRACE_INFO",
410 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM ] = "TRACE_DEBUG_SYSTEM",
411 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM ] = "TRACE_DEBUG_PROGRAM",
412 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS ] = "TRACE_DEBUG_PROCESS",
413 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE ] = "TRACE_DEBUG_MODULE",
414 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT ] = "TRACE_DEBUG_UNIT",
415 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION ] = "TRACE_DEBUG_FUNCTION",
416 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE ] = "TRACE_DEBUG_LINE",
417 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG ] = "TRACE_DEBUG",
cf76ce92 418 };
4cdfc5e8 419 bt_event_class_log_level log_level;
cf76ce92
PP
420 const char *log_level_str = NULL;
421
44c440bc
PP
422 prop_avail = bt_event_class_get_log_level(event_class,
423 &log_level);
424 if (prop_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) {
cf76ce92 425 log_level_str = log_level_names[log_level];
98b15851 426 BT_ASSERT_DBG(log_level_str);
c3c30b08 427
3228cc1d 428 if (!pretty->start_line) {
dd61c4ed 429 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 430 }
c3c30b08 431 if (print_names) {
3228cc1d 432 print_name_equal(pretty, "loglevel");
60535549 433 } else if (dom_print) {
dd61c4ed 434 bt_common_g_string_append(pretty->string, ":");
c3c30b08 435 }
cf76ce92 436
dd61c4ed 437 bt_common_g_string_append(pretty->string, log_level_str);
f354b1e1 438 bt_common_g_string_append_printf(
cf76ce92 439 pretty->string, " (%d)", (int) log_level);
60535549 440 dom_print = 1;
c3c30b08
MD
441 }
442 }
3228cc1d 443 if (pretty->options.print_emf_field) {
cf76ce92 444 const char *uri_str;
c3c30b08 445
50842bdc 446 uri_str = bt_event_class_get_emf_uri(event_class);
c3c30b08 447 if (uri_str) {
3228cc1d 448 if (!pretty->start_line) {
dd61c4ed 449 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 450 }
c3c30b08 451 if (print_names) {
3228cc1d 452 print_name_equal(pretty, "model.emf.uri");
60535549 453 } else if (dom_print) {
dd61c4ed 454 bt_common_g_string_append(pretty->string, ":");
c3c30b08 455 }
c3c30b08 456
dd61c4ed 457 bt_common_g_string_append(pretty->string, uri_str);
60535549 458 dom_print = 1;
c3c30b08
MD
459 }
460 }
60535549 461 if (dom_print && !print_names) {
dd61c4ed 462 bt_common_g_string_append(pretty->string, " ");
60535549 463 }
3228cc1d 464 if (!pretty->start_line) {
dd61c4ed 465 bt_common_g_string_append(pretty->string, ", ");
c3c30b08 466 }
3228cc1d 467 pretty->start_line = true;
6a18b281 468 if (print_names) {
3228cc1d 469 print_name_equal(pretty, "name");
ad96d936 470 }
64925bba 471 ev_name = bt_event_class_get_name(event_class);
3228cc1d 472 if (pretty->use_colors) {
64925bba 473 if (ev_name) {
dd61c4ed 474 bt_common_g_string_append(pretty->string,
04609487 475 color_event_name);
64925bba 476 } else {
dd61c4ed 477 bt_common_g_string_append(pretty->string,
04609487 478 color_unknown);
64925bba
PP
479 }
480 }
481 if (ev_name) {
dd61c4ed 482 bt_common_g_string_append(pretty->string, ev_name);
64925bba 483 } else {
dd61c4ed 484 bt_common_g_string_append(pretty->string, "<unknown>");
6a18b281 485 }
3228cc1d 486 if (pretty->use_colors) {
04609487 487 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 488 }
60535549 489 if (!print_names) {
dd61c4ed 490 bt_common_g_string_append(pretty->string, ": ");
60535549 491 } else {
dd61c4ed 492 bt_common_g_string_append(pretty->string, ", ");
60535549 493 }
a82e90e8 494
af9a82eb 495end:
6a18b281
MD
496 return ret;
497}
498
499static
d94d92ac 500int print_integer(struct pretty_component *pretty,
b19ff26f 501 const bt_field *field)
6a18b281 502{
d94d92ac 503 int ret = 0;
4cdfc5e8 504 bt_field_class_integer_preferred_display_base base;
b19ff26f 505 const bt_field_class *int_fc;
6a18b281
MD
506 union {
507 uint64_t u;
508 int64_t s;
509 } v;
ad96d936 510 bool rst_color = false;
4cdfc5e8 511 bt_field_class_type ft_type;
6a18b281 512
40f4ba76 513 int_fc = bt_field_borrow_class_const(field);
98b15851 514 BT_ASSERT_DBG(int_fc);
864cad70 515 ft_type = bt_field_get_class_type(field);
ebdb6693
PP
516 if (bt_field_class_type_is(ft_type,
517 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) {
9c08c816 518 v.u = bt_field_integer_unsigned_get_value(field);
6a18b281 519 } else {
9c08c816 520 v.s = bt_field_integer_signed_get_value(field);
6a18b281
MD
521 }
522
3228cc1d 523 if (pretty->use_colors) {
04609487 524 bt_common_g_string_append(pretty->string, color_number_value);
ad96d936
PP
525 rst_color = true;
526 }
527
5cd6d0e5 528 base = bt_field_class_integer_get_preferred_display_base(int_fc);
6a18b281 529 switch (base) {
5cd6d0e5 530 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
6a18b281
MD
531 {
532 int bitnr, len;
533
5cd6d0e5 534 len = bt_field_class_integer_get_field_value_range(int_fc);
dd61c4ed 535 bt_common_g_string_append(pretty->string, "0b");
7f140ae8 536 _bt_safe_lshift(v.u, 64 - len);
6a18b281 537 for (bitnr = 0; bitnr < len; bitnr++) {
242ed509
MD
538 bt_common_g_string_append_c(pretty->string,
539 (v.u & (1ULL << 63)) ? '1' : '0');
7f140ae8 540 _bt_safe_lshift(v.u, 1);
6a18b281
MD
541 }
542 break;
543 }
5cd6d0e5 544 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
6a18b281 545 {
ebdb6693
PP
546 if (bt_field_class_type_is(ft_type,
547 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER)) {
6a18b281
MD
548 int len;
549
5cd6d0e5
PP
550 len = bt_field_class_integer_get_field_value_range(
551 int_fc);
6a18b281
MD
552 if (len < 64) {
553 size_t rounded_len;
554
98b15851 555 BT_ASSERT_DBG(len != 0);
6a18b281
MD
556 /* Round length to the nearest 3-bit */
557 rounded_len = (((len - 1) / 3) + 1) * 3;
558 v.u &= ((uint64_t) 1 << rounded_len) - 1;
559 }
560 }
561
f354b1e1 562 bt_common_g_string_append_printf(pretty->string, "0%" PRIo64, v.u);
6a18b281
MD
563 break;
564 }
5cd6d0e5 565 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL:
ebdb6693
PP
566 if (bt_field_class_type_is(ft_type,
567 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) {
f354b1e1 568 bt_common_g_string_append_printf(pretty->string, "%" PRIu64, v.u);
6a18b281 569 } else {
f354b1e1 570 bt_common_g_string_append_printf(pretty->string, "%" PRId64, v.s);
6a18b281
MD
571 }
572 break;
5cd6d0e5 573 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
6a18b281
MD
574 {
575 int len;
576
5cd6d0e5 577 len = bt_field_class_integer_get_field_value_range(int_fc);
6a18b281
MD
578 if (len < 64) {
579 /* Round length to the nearest nibble */
580 uint8_t rounded_len = ((len + 3) & ~0x3);
581
582 v.u &= ((uint64_t) 1 << rounded_len) - 1;
583 }
584
f354b1e1 585 bt_common_g_string_append_printf(pretty->string, "0x%" PRIX64, v.u);
6a18b281
MD
586 break;
587 }
588 default:
d94d92ac 589 ret = -1;
6a18b281
MD
590 goto end;
591 }
592end:
ad96d936 593 if (rst_color) {
04609487 594 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 595 }
6a18b281
MD
596 return ret;
597}
598
93a4161c 599static
3228cc1d 600void print_escape_string(struct pretty_component *pretty, const char *str)
93a4161c
JD
601{
602 int i;
603
dd61c4ed 604 bt_common_g_string_append_c(pretty->string, '"');
5280f742 605
93a4161c
JD
606 for (i = 0; i < strlen(str); i++) {
607 /* Escape sequences not recognized by iscntrl(). */
608 switch (str[i]) {
609 case '\\':
dd61c4ed 610 bt_common_g_string_append(pretty->string, "\\\\");
93a4161c
JD
611 continue;
612 case '\'':
dd61c4ed 613 bt_common_g_string_append(pretty->string, "\\\'");
93a4161c
JD
614 continue;
615 case '\"':
dd61c4ed 616 bt_common_g_string_append(pretty->string, "\\\"");
93a4161c
JD
617 continue;
618 case '\?':
dd61c4ed 619 bt_common_g_string_append(pretty->string, "\\\?");
93a4161c
JD
620 continue;
621 }
622
623 /* Standard characters. */
994cd345 624 if (!iscntrl((unsigned char) str[i])) {
dd61c4ed 625 bt_common_g_string_append_c(pretty->string, str[i]);
93a4161c
JD
626 continue;
627 }
628
629 switch (str[i]) {
630 case '\0':
dd61c4ed 631 bt_common_g_string_append(pretty->string, "\\0");
93a4161c
JD
632 break;
633 case '\a':
dd61c4ed 634 bt_common_g_string_append(pretty->string, "\\a");
93a4161c
JD
635 break;
636 case '\b':
dd61c4ed 637 bt_common_g_string_append(pretty->string, "\\b");
93a4161c
JD
638 break;
639 case '\e':
dd61c4ed 640 bt_common_g_string_append(pretty->string, "\\e");
93a4161c
JD
641 break;
642 case '\f':
dd61c4ed 643 bt_common_g_string_append(pretty->string, "\\f");
93a4161c
JD
644 break;
645 case '\n':
dd61c4ed 646 bt_common_g_string_append(pretty->string, "\\n");
93a4161c
JD
647 break;
648 case '\r':
dd61c4ed 649 bt_common_g_string_append(pretty->string, "\\r");
93a4161c
JD
650 break;
651 case '\t':
dd61c4ed 652 bt_common_g_string_append(pretty->string, "\\t");
93a4161c
JD
653 break;
654 case '\v':
dd61c4ed 655 bt_common_g_string_append(pretty->string, "\\v");
93a4161c
JD
656 break;
657 default:
658 /* Unhandled control-sequence, print as hex. */
f354b1e1 659 bt_common_g_string_append_printf(pretty->string, "\\x%02x", str[i]);
93a4161c
JD
660 break;
661 }
662 }
5280f742 663
dd61c4ed 664 bt_common_g_string_append_c(pretty->string, '"');
93a4161c
JD
665}
666
5288c8ae
GB
667/*
668 * Print the unknown label.
669 */
670static
671void print_enum_value_label_unknown(struct pretty_component *pretty)
672{
673 if (pretty->use_colors) {
674 bt_common_g_string_append(pretty->string, color_unknown);
675 }
676
677 bt_common_g_string_append(pretty->string, "<unknown>");
678
679 if (pretty->use_colors) {
680 bt_common_g_string_append(pretty->string, color_rst);
681 }
682}
683
684/*
685 * Print labels for a value. If there are more than one label for the
686 * value, they will be printed in "{ }".
687 */
688static
689void print_enum_value_label_array(struct pretty_component *pretty,
690 uint64_t label_count,
691 bt_field_class_enumeration_mapping_label_array label_array)
692{
693 uint64_t i;
694
695 if (label_count > 1) {
696 bt_common_g_string_append(pretty->string, "{ ");
697 }
698
699 for (i = 0; i < label_count; i++) {
700 const char *mapping_name = label_array[i];
701
702 if (i != 0) {
703 bt_common_g_string_append(pretty->string, ", ");
704 }
705 if (pretty->use_colors) {
706 bt_common_g_string_append(pretty->string, color_enum_mapping_name);
707 }
708 print_escape_string(pretty, mapping_name);
709 if (pretty->use_colors) {
710 bt_common_g_string_append(pretty->string, color_rst);
711 }
712 }
713
714 if (label_count > 1) {
715 bt_common_g_string_append(pretty->string, " }");
716 }
717}
718
719/*
720 * Print arrays of labels and counts are ORed bit flags.
721 */
722static
723void print_enum_value_bit_flag_label_arrays(struct pretty_component *pretty)
724{
725 uint64_t i;
726 bool first_label = true;
727
728 /* For each bit with a label count > 0, print the labels. */
729 for (i = 0; i < ENUMERATION_MAX_BITFLAGS_COUNT; i++) {
730 uint64_t label_count = pretty->enum_bit_labels[i]->len;
731
732 if (label_count > 0) {
733 if (!first_label) {
734 bt_common_g_string_append(pretty->string, " | ");
735 }
736 print_enum_value_label_array(pretty, label_count,
737 (void *) pretty->enum_bit_labels[i]->pdata);
738 first_label = false;
739 }
740 }
741}
742
743/*
744 * Get the labels mapping to an unsigned value.
745 *
746 * This function will set the count to the count of mapping labels that match
747 * the value. If count == 0, the caller has nothing to do, if count > 0,
e7401568 748 * the label_array contains the labels to print and the caller is responsible
5288c8ae
GB
749 * to call g_free on it once the values have been used.
750 */
751static
752void print_enum_unsigned_get_mapping_labels_for_value(const bt_field_class *fc,
753 uint64_t value, GPtrArray *labels)
754{
755 uint64_t mapping_count = bt_field_class_enumeration_get_mapping_count(fc);
756 uint64_t i;
757
758 for (i = 0; i < mapping_count; i++) {
759 uint64_t range_i;
760 const struct bt_field_class_enumeration_unsigned_mapping *mapping =
761 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(fc, i);
762 const bt_integer_range_set_unsigned *ranges =
763 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping);
764 uint64_t range_count = bt_integer_range_set_get_range_count(
765 bt_integer_range_set_unsigned_as_range_set_const(ranges));
766
767 for (range_i = 0; range_i < range_count; range_i++) {
768 const bt_integer_range_unsigned *range =
769 bt_integer_range_set_unsigned_borrow_range_by_index_const(ranges, range_i);
770 uint64_t lower = bt_integer_range_unsigned_get_lower(range);
771 uint64_t upper = bt_integer_range_unsigned_get_upper(range);
772
773 /*
774 * Flag is active if this range represents a single value
775 * (lower == upper) and the lower is the same as the bit
776 * value to test against.
777 */
778 if ((lower == upper) && (lower == value)) {
779 g_ptr_array_add(labels, (void *) bt_field_class_enumeration_mapping_get_label(
780 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping)));
781 break;
782 }
783 }
784 }
785}
786
787/*
788 * Splits an unsigned enum value into its bit and for each bit set,
789 * try to find a corresponding label.
790 *
791 * If any bit set does not have a corresponding label, then it prints
792 * an unknown value, otherwise, it prints the labels, separated by '|'
793 */
794static
795void print_enum_unsigned_try_bit_flags(struct pretty_component *pretty,
796 const bt_field *field)
797{
798 uint64_t i;
799 uint64_t value = bt_field_integer_unsigned_get_value(field);
800 const bt_field_class *fc = bt_field_borrow_class_const(field);
801
802 /* Value is 0, if there was a label for it, we would know by now. */
803 if (value == 0) {
804 print_enum_value_label_unknown(pretty);
805 goto end;
806 }
807
808 for (i = 0; i < ENUMERATION_MAX_BITFLAGS_COUNT; i++) {
809 uint64_t bit_value = UINT64_C(1) << i;
810
811 if ((value & bit_value) != 0) {
812 print_enum_unsigned_get_mapping_labels_for_value(
813 fc, bit_value, pretty->enum_bit_labels[i]);
814
815 if (pretty->enum_bit_labels[i]->len == 0) {
816 /*
817 * This bit has no matching label, so this
818 * field is not a bit flag field, print
819 * unknown and return.
820 */
821 print_enum_value_label_unknown(pretty);
822 goto end;
823 }
824 }
825 }
826
827 print_enum_value_bit_flag_label_arrays(pretty);
828
829end:
830 return;
831}
832
833/*
834 * Get the labels mapping to a signed value
835 *
836 * This function will set the count to the count of mapping labels that match
837 * the value. If count == 0, the caller has nothing to do, if count > 0,
e7401568 838 * the label_array contains the labels to print and the caller is responsible
5288c8ae
GB
839 * to call g_free on it once the values have been used.
840 */
841static
842void print_enum_signed_get_mapping_labels_for_value(const bt_field_class *fc,
843 int64_t value, GPtrArray *labels)
844{
845 uint64_t mapping_count = bt_field_class_enumeration_get_mapping_count(fc);
846 uint64_t i;
847
848 for (i = 0; i < mapping_count; i++) {
849 uint64_t range_i;
850 const struct bt_field_class_enumeration_signed_mapping *mapping =
851 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(fc, i);
852 const bt_integer_range_set_signed *ranges =
853 bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping);
854 uint64_t range_count = bt_integer_range_set_get_range_count(
855 bt_integer_range_set_signed_as_range_set_const(ranges));
856
857 for (range_i = 0; range_i < range_count; range_i++) {
858 const bt_integer_range_signed *range =
859 bt_integer_range_set_signed_borrow_range_by_index_const(ranges, range_i);
860 uint64_t lower = bt_integer_range_signed_get_lower(range);
861 uint64_t upper = bt_integer_range_signed_get_upper(range);
862
863 /*
864 * Flag is active if this range represents a single value
865 * (lower == upper) and the lower is the same as the bit
866 * value to test against.
867 */
868 if ((lower == upper) && (lower == value)) {
869 g_ptr_array_add(labels, (void*) bt_field_class_enumeration_mapping_get_label(
870 bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping)));
871 break;
872 }
873 }
874 }
875}
876
877/*
878 * Splits a signed enum value into its bit and for each bit set,
879 * try to find a corresponding label.
880 *
881 * If any bit set does not have a corresponding label, then it prints
882 * an unknown value, otherwise, it prints the labels, separated by '|'.
883 */
884static
885void print_enum_signed_try_bit_flags(struct pretty_component *pretty,
886 const bt_field *field)
887{
888 uint64_t i;
889 int64_t value = bt_field_integer_signed_get_value(field);
890 const bt_field_class *fc = bt_field_borrow_class_const(field);
891
892 /*
893 * Negative value, not a bit flag enum
894 * For 0, if there was a value, we would know by now.
895 */
896 if (value <= 0) {
897 print_enum_value_label_unknown(pretty);
898 goto end;
899 }
900
901 for (i = 0; i < ENUMERATION_MAX_BITFLAGS_COUNT; i++) {
902 uint64_t bit_value = 1ULL << i;
903
904 if ((value & bit_value) != 0) {
905 print_enum_signed_get_mapping_labels_for_value(
906 fc, bit_value, pretty->enum_bit_labels[i]);
907
908 if (pretty->enum_bit_labels[i]->len == 0) {
909 /*
910 * This bit has no matching label, so this
911 * field is not a bit flag field, print
912 * unknown and return.
913 */
914 print_enum_value_label_unknown(pretty);
915 goto end;
916 }
917 }
918 }
919
920 print_enum_value_bit_flag_label_arrays(pretty);
921
922end:
923 return;
924}
925
926/*
927 * Main function to try to print the value of the enum field as a
928 * bit flag. It calls the appropriate function depending on the
929 * field type's signedness and prints the label for each bit set,
930 * if it's a bit flag field.
931 */
932static
933void print_enum_try_bit_flags(struct pretty_component *pretty,
934 const bt_field *field)
935{
936 const bt_field_class *fc = bt_field_borrow_class_const(field);
937 uint64_t int_range = bt_field_class_integer_get_field_value_range(fc);
938 int i;
939
940 BT_ASSERT(int_range <= ENUMERATION_MAX_BITFLAGS_COUNT);
941
942 /*
943 * Remove all labels from the previous enumeration field.
944 */
945 for (i = 0; i < ENUMERATION_MAX_BITFLAGS_COUNT; i++) {
946 g_ptr_array_set_size(pretty->enum_bit_labels[i], 0);
947 }
948
949 /* Get the mapping labels for the bit value. */
950 switch (bt_field_class_get_type(fc)) {
951 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
952 print_enum_unsigned_try_bit_flags(pretty, field);
953 break;
954 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
955 print_enum_signed_try_bit_flags(pretty, field);
956 break;
957 default:
958 bt_common_abort();
959 }
960}
961
6a18b281 962static
d94d92ac 963int print_enum(struct pretty_component *pretty,
b19ff26f 964 const bt_field *field)
6a18b281 965{
d94d92ac 966 int ret = 0;
5cd6d0e5 967 bt_field_class_enumeration_mapping_label_array label_array;
44c440bc 968 uint64_t label_count;
96e8f959 969
864cad70
PP
970 switch (bt_field_get_class_type(field)) {
971 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
9c08c816 972 ret = bt_field_enumeration_unsigned_get_mapping_labels(field,
44c440bc
PP
973 &label_array, &label_count);
974 break;
864cad70 975 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
9c08c816 976 ret = bt_field_enumeration_signed_get_mapping_labels(field,
44c440bc
PP
977 &label_array, &label_count);
978 break;
979 default:
498e7994 980 bt_common_abort();
96e8f959 981 }
44c440bc
PP
982
983 if (ret) {
d94d92ac 984 ret = -1;
96e8f959
MD
985 goto end;
986 }
44c440bc 987
dd61c4ed 988 bt_common_g_string_append(pretty->string, "( ");
5288c8ae
GB
989 if (label_count != 0) {
990 /* The numerical value matches some labels, print them. */
991 print_enum_value_label_array(pretty, label_count, label_array);
992 } else if (pretty->options.print_enum_flags) {
993 /*
994 * The numerical value of the enumeration does not match any
995 * label but the `print-enum-flags` parameter is TRUE so try to
996 * decompose the value of the enum into bits and print it as a
997 * bit flag enum.
998 */
999 print_enum_try_bit_flags(pretty, field);
1000 } else {
1001 print_enum_value_label_unknown(pretty);
96e8f959 1002 }
96e8f959 1003
5288c8ae 1004 /* Print the actual value of the enum. */
dd61c4ed 1005 bt_common_g_string_append(pretty->string, " : container = ");
312c056a 1006 ret = print_integer(pretty, field);
d94d92ac 1007 if (ret != 0) {
6a18b281
MD
1008 goto end;
1009 }
dd61c4ed 1010 bt_common_g_string_append(pretty->string, " )");
6a18b281 1011end:
6a18b281
MD
1012 return ret;
1013}
1014
1015static
d94d92ac 1016int print_struct_field(struct pretty_component *pretty,
b19ff26f
PP
1017 const bt_field *_struct,
1018 const bt_field_class *struct_class,
2f84c7be 1019 uint64_t i, bool print_names, uint64_t *nr_printed_fields)
6a18b281 1020{
d94d92ac 1021 int ret = 0;
6a18b281 1022 const char *field_name;
b19ff26f 1023 const bt_field *field = NULL;
1e6fd1d7 1024 const bt_field_class_structure_member *member;
6a18b281 1025
40f4ba76 1026 field = bt_field_structure_borrow_member_field_by_index_const(_struct, i);
6a18b281 1027 if (!field) {
d94d92ac 1028 ret = -1;
6a18b281
MD
1029 goto end;
1030 }
44c440bc 1031
1e6fd1d7
PP
1032 member = bt_field_class_structure_borrow_member_by_index_const(
1033 struct_class, i);
1034 field_name = bt_field_class_structure_member_get_name(member);
6a18b281 1035
2b4c4a7c 1036 if (*nr_printed_fields > 0) {
dd61c4ed 1037 bt_common_g_string_append(pretty->string, ", ");
6a18b281 1038 } else {
dd61c4ed 1039 bt_common_g_string_append(pretty->string, " ");
6a18b281
MD
1040 }
1041 if (print_names) {
6acddae3 1042 print_field_name_equal(pretty, field_name);
6a18b281 1043 }
2f84c7be 1044 ret = print_field(pretty, field, print_names);
2b4c4a7c 1045 *nr_printed_fields += 1;
a82e90e8 1046
6a18b281 1047end:
6a18b281
MD
1048 return ret;
1049}
1050
1051static
d94d92ac 1052int print_struct(struct pretty_component *pretty,
2f84c7be 1053 const bt_field *_struct, bool print_names)
6a18b281 1054{
d94d92ac 1055 int ret = 0;
b19ff26f 1056 const bt_field_class *struct_class = NULL;
44c440bc 1057 uint64_t nr_fields, i, nr_printed_fields;
6a18b281 1058
40f4ba76 1059 struct_class = bt_field_borrow_class_const(_struct);
5cd6d0e5 1060 nr_fields = bt_field_class_structure_get_member_count(struct_class);
53dc85fa 1061
dd61c4ed 1062 bt_common_g_string_append(pretty->string, "{");
3228cc1d 1063 pretty->depth++;
2b4c4a7c 1064 nr_printed_fields = 0;
6a18b281 1065 for (i = 0; i < nr_fields; i++) {
5cd6d0e5 1066 ret = print_struct_field(pretty, _struct, struct_class, i,
2f84c7be 1067 print_names, &nr_printed_fields);
d94d92ac 1068 if (ret != 0) {
6a18b281
MD
1069 goto end;
1070 }
1071 }
3228cc1d 1072 pretty->depth--;
dd61c4ed 1073 bt_common_g_string_append(pretty->string, " }");
a82e90e8 1074
6a18b281 1075end:
6a18b281
MD
1076 return ret;
1077}
1078
1079static
d94d92ac 1080int print_array_field(struct pretty_component *pretty,
b19ff26f 1081 const bt_field *array, uint64_t i, bool print_names)
6a18b281 1082{
b19ff26f 1083 const bt_field *field = NULL;
6a18b281 1084
44c440bc 1085 if (i != 0) {
dd61c4ed 1086 bt_common_g_string_append(pretty->string, ", ");
44c440bc 1087 } else {
dd61c4ed 1088 bt_common_g_string_append(pretty->string, " ");
6a18b281 1089 }
44c440bc 1090 if (print_names) {
f354b1e1 1091 bt_common_g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
6a18b281 1092 }
a82e90e8 1093
40f4ba76 1094 field = bt_field_array_borrow_element_field_by_index_const(array, i);
98b15851 1095 BT_ASSERT_DBG(field);
2f84c7be 1096 return print_field(pretty, field, print_names);
6a18b281
MD
1097}
1098
1099static
d94d92ac 1100int print_array(struct pretty_component *pretty,
b19ff26f 1101 const bt_field *array, bool print_names)
6a18b281 1102{
d94d92ac 1103 int ret = 0;
44c440bc 1104 uint64_t len;
6a18b281 1105 uint64_t i;
6a18b281 1106
44c440bc 1107 len = bt_field_array_get_length(array);
dd61c4ed 1108 bt_common_g_string_append(pretty->string, "[");
3228cc1d 1109 pretty->depth++;
6a18b281 1110 for (i = 0; i < len; i++) {
44c440bc 1111 ret = print_array_field(pretty, array, i, print_names);
d94d92ac 1112 if (ret != 0) {
6a18b281
MD
1113 goto end;
1114 }
1115 }
3228cc1d 1116 pretty->depth--;
dd61c4ed 1117 bt_common_g_string_append(pretty->string, " ]");
a82e90e8 1118
6a18b281 1119end:
6a18b281
MD
1120 return ret;
1121}
1122
1123static
d94d92ac 1124int print_sequence_field(struct pretty_component *pretty,
b19ff26f 1125 const bt_field *seq, uint64_t i, bool print_names)
6a18b281 1126{
b19ff26f 1127 const bt_field *field = NULL;
6a18b281 1128
44c440bc 1129 if (i != 0) {
dd61c4ed 1130 bt_common_g_string_append(pretty->string, ", ");
44c440bc 1131 } else {
dd61c4ed 1132 bt_common_g_string_append(pretty->string, " ");
6a18b281 1133 }
44c440bc 1134 if (print_names) {
f354b1e1 1135 bt_common_g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
6a18b281 1136 }
a82e90e8 1137
40f4ba76 1138 field = bt_field_array_borrow_element_field_by_index_const(seq, i);
98b15851 1139 BT_ASSERT_DBG(field);
2f84c7be 1140 return print_field(pretty, field, print_names);
6a18b281
MD
1141}
1142
1143static
d94d92ac 1144int print_sequence(struct pretty_component *pretty,
b19ff26f 1145 const bt_field *seq, bool print_names)
6a18b281 1146{
d94d92ac 1147 int ret = 0;
44c440bc 1148 uint64_t len;
6a18b281 1149 uint64_t i;
6a18b281 1150
44c440bc 1151 len = bt_field_array_get_length(seq);
dd61c4ed 1152 bt_common_g_string_append(pretty->string, "[");
6a18b281 1153
3228cc1d 1154 pretty->depth++;
6a18b281 1155 for (i = 0; i < len; i++) {
44c440bc 1156 ret = print_sequence_field(pretty, seq, i, print_names);
d94d92ac 1157 if (ret != 0) {
6a18b281
MD
1158 goto end;
1159 }
1160 }
3228cc1d 1161 pretty->depth--;
dd61c4ed 1162 bt_common_g_string_append(pretty->string, " ]");
a82e90e8 1163
6a18b281 1164end:
6a18b281
MD
1165 return ret;
1166}
1167
51e61f06
PP
1168static
1169int print_option(struct pretty_component *pretty,
1170 const bt_field *option, bool print_names)
1171{
1172 int ret = 0;
1173 const bt_field *field = NULL;
1174
1175 field = bt_field_option_borrow_field_const(option);
1176 if (field) {
1177 bt_common_g_string_append(pretty->string, "{ ");
1178 pretty->depth++;
1179 if (print_names) {
1180 // TODO: find tag's name using field path
1181 // print_field_name_equal(pretty, tag_choice);
1182 }
1183 ret = print_field(pretty, field, print_names);
1184 if (ret != 0) {
1185 goto end;
1186 }
1187 pretty->depth--;
1188 bt_common_g_string_append(pretty->string, " }");
1189 } else {
1190 bt_common_g_string_append(pretty->string, "<none>");
1191 }
1192
1193end:
1194 return ret;
1195}
1196
6a18b281 1197static
d94d92ac 1198int print_variant(struct pretty_component *pretty,
b19ff26f 1199 const bt_field *variant, bool print_names)
6a18b281 1200{
d94d92ac 1201 int ret = 0;
b19ff26f 1202 const bt_field *field = NULL;
6a18b281 1203
40f4ba76 1204 field = bt_field_variant_borrow_selected_option_field_const(variant);
98b15851 1205 BT_ASSERT_DBG(field);
dd61c4ed 1206 bt_common_g_string_append(pretty->string, "{ ");
3228cc1d 1207 pretty->depth++;
6a18b281 1208 if (print_names) {
44c440bc
PP
1209 // TODO: find tag's name using field path
1210 // print_field_name_equal(pretty, tag_choice);
6a18b281 1211 }
2f84c7be 1212 ret = print_field(pretty, field, print_names);
d94d92ac 1213 if (ret != 0) {
6a18b281
MD
1214 goto end;
1215 }
3228cc1d 1216 pretty->depth--;
dd61c4ed 1217 bt_common_g_string_append(pretty->string, " }");
a82e90e8 1218
6a18b281 1219end:
6a18b281
MD
1220 return ret;
1221}
1222
1223static
d94d92ac 1224int print_field(struct pretty_component *pretty,
2f84c7be 1225 const bt_field *field, bool print_names)
6a18b281 1226{
4cdfc5e8 1227 bt_field_class_type class_id;
6a18b281 1228
864cad70 1229 class_id = bt_field_get_class_type(field);
ebdb6693 1230 if (class_id == BT_FIELD_CLASS_TYPE_BOOL) {
ff87f7c6
PP
1231 bt_bool v;
1232 const char *text;
1233
1234 v = bt_field_bool_get_value(field);
1235 if (pretty->use_colors) {
04609487 1236 bt_common_g_string_append(pretty->string, color_number_value);
ff87f7c6
PP
1237 }
1238 if (v) {
1239 text = "true";
1240 } else {
1241 text = "false";
1242 }
1243 bt_common_g_string_append(pretty->string, text);
1244 if (pretty->use_colors) {
04609487 1245 bt_common_g_string_append(pretty->string, color_rst);
ff87f7c6
PP
1246 }
1247 return 0;
ebdb6693 1248 } else if (class_id == BT_FIELD_CLASS_TYPE_BIT_ARRAY) {
6be72e6c
PP
1249 uint64_t v = bt_field_bit_array_get_value_as_integer(field);
1250
1251 if (pretty->use_colors) {
1252 bt_common_g_string_append(pretty->string,
04609487 1253 color_number_value);
6be72e6c
PP
1254 }
1255 bt_common_g_string_append_printf(pretty->string, "0x%" PRIX64,
1256 v);
1257 if (pretty->use_colors) {
04609487 1258 bt_common_g_string_append(pretty->string, color_rst);
6be72e6c
PP
1259 }
1260 return 0;
ebdb6693
PP
1261 } else if (bt_field_class_type_is(class_id,
1262 BT_FIELD_CLASS_TYPE_ENUMERATION)) {
1263 return print_enum(pretty, field);
1264 } else if (bt_field_class_type_is(class_id,
1265 BT_FIELD_CLASS_TYPE_INTEGER)) {
3228cc1d 1266 return print_integer(pretty, field);
ebdb6693
PP
1267 } else if (bt_field_class_type_is(class_id,
1268 BT_FIELD_CLASS_TYPE_REAL)) {
6a18b281
MD
1269 double v;
1270
fe4df857 1271 if (class_id == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) {
ebdb6693 1272 v = bt_field_real_single_precision_get_value(field);
fe4df857
FD
1273 } else {
1274 v = bt_field_real_double_precision_get_value(field);
1275 }
1276
3228cc1d 1277 if (pretty->use_colors) {
04609487 1278 bt_common_g_string_append(pretty->string, color_number_value);
ad96d936 1279 }
f354b1e1 1280 bt_common_g_string_append_printf(pretty->string, "%g", v);
3228cc1d 1281 if (pretty->use_colors) {
04609487 1282 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 1283 }
d94d92ac 1284 return 0;
ebdb6693 1285 } else if (class_id == BT_FIELD_CLASS_TYPE_STRING) {
95a518bf
JG
1286 const char *str;
1287
50842bdc 1288 str = bt_field_string_get_value(field);
95a518bf 1289 if (!str) {
d94d92ac 1290 return -1;
95a518bf
JG
1291 }
1292
3228cc1d 1293 if (pretty->use_colors) {
04609487 1294 bt_common_g_string_append(pretty->string, color_string_value);
ad96d936 1295 }
95a518bf 1296 print_escape_string(pretty, str);
3228cc1d 1297 if (pretty->use_colors) {
04609487 1298 bt_common_g_string_append(pretty->string, color_rst);
ad96d936 1299 }
d94d92ac 1300 return 0;
ebdb6693 1301 } else if (class_id == BT_FIELD_CLASS_TYPE_STRUCTURE) {
2f84c7be 1302 return print_struct(pretty, field, print_names);
ebdb6693
PP
1303 } else if (bt_field_class_type_is(class_id,
1304 BT_FIELD_CLASS_TYPE_OPTION)) {
51e61f06 1305 return print_option(pretty, field, print_names);
ebdb6693
PP
1306 } else if (bt_field_class_type_is(class_id,
1307 BT_FIELD_CLASS_TYPE_VARIANT)) {
3228cc1d 1308 return print_variant(pretty, field, print_names);
ebdb6693 1309 } else if (class_id == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) {
3228cc1d 1310 return print_array(pretty, field, print_names);
ebdb6693
PP
1311 } else if (bt_field_class_type_is(class_id,
1312 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY)) {
3228cc1d 1313 return print_sequence(pretty, field, print_names);
6a18b281 1314 }
507d9140
SM
1315
1316 bt_common_abort();
6a18b281
MD
1317}
1318
1319static
d94d92ac 1320int print_stream_packet_context(struct pretty_component *pretty,
b19ff26f 1321 const bt_event *event)
6a18b281 1322{
d94d92ac 1323 int ret = 0;
b19ff26f
PP
1324 const bt_packet *packet = NULL;
1325 const bt_field *main_field = NULL;
6a18b281 1326
40f4ba76 1327 packet = bt_event_borrow_packet_const(event);
6a18b281 1328 if (!packet) {
6a18b281
MD
1329 goto end;
1330 }
40f4ba76 1331 main_field = bt_packet_borrow_context_field_const(packet);
6a18b281 1332 if (!main_field) {
6a18b281
MD
1333 goto end;
1334 }
3228cc1d 1335 if (!pretty->start_line) {
dd61c4ed 1336 bt_common_g_string_append(pretty->string, ", ");
6e1bc0df 1337 }
3228cc1d
PP
1338 pretty->start_line = false;
1339 if (pretty->options.print_scope_field_names) {
1340 print_name_equal(pretty, "stream.packet.context");
6a18b281 1341 }
3228cc1d 1342 ret = print_field(pretty, main_field,
2f84c7be 1343 pretty->options.print_context_field_names);
a82e90e8 1344
6a18b281 1345end:
6a18b281
MD
1346 return ret;
1347}
1348
6a18b281 1349static
d94d92ac 1350int print_stream_event_context(struct pretty_component *pretty,
b19ff26f 1351 const bt_event *event)
6a18b281 1352{
d94d92ac 1353 int ret = 0;
b19ff26f 1354 const bt_field *main_field = NULL;
6a18b281 1355
40f4ba76 1356 main_field = bt_event_borrow_common_context_field_const(event);
6a18b281 1357 if (!main_field) {
6a18b281
MD
1358 goto end;
1359 }
3228cc1d 1360 if (!pretty->start_line) {
dd61c4ed 1361 bt_common_g_string_append(pretty->string, ", ");
6e1bc0df 1362 }
3228cc1d
PP
1363 pretty->start_line = false;
1364 if (pretty->options.print_scope_field_names) {
1365 print_name_equal(pretty, "stream.event.context");
6a18b281 1366 }
3228cc1d 1367 ret = print_field(pretty, main_field,
2f84c7be 1368 pretty->options.print_context_field_names);
a82e90e8 1369
6a18b281 1370end:
6a18b281
MD
1371 return ret;
1372}
1373
1374static
d94d92ac 1375int print_event_context(struct pretty_component *pretty,
b19ff26f 1376 const bt_event *event)
6a18b281 1377{
d94d92ac 1378 int ret = 0;
b19ff26f 1379 const bt_field *main_field = NULL;
6a18b281 1380
40f4ba76 1381 main_field = bt_event_borrow_specific_context_field_const(event);
6a18b281 1382 if (!main_field) {
6a18b281
MD
1383 goto end;
1384 }
3228cc1d 1385 if (!pretty->start_line) {
dd61c4ed 1386 bt_common_g_string_append(pretty->string, ", ");
6e1bc0df 1387 }
3228cc1d
PP
1388 pretty->start_line = false;
1389 if (pretty->options.print_scope_field_names) {
1390 print_name_equal(pretty, "event.context");
6a18b281 1391 }
3228cc1d 1392 ret = print_field(pretty, main_field,
2f84c7be 1393 pretty->options.print_context_field_names);
a82e90e8 1394
6a18b281 1395end:
6a18b281
MD
1396 return ret;
1397}
1398
1399static
d94d92ac 1400int print_event_payload(struct pretty_component *pretty,
b19ff26f 1401 const bt_event *event)
6a18b281 1402{
d94d92ac 1403 int ret = 0;
b19ff26f 1404 const bt_field *main_field = NULL;
6a18b281 1405
40f4ba76 1406 main_field = bt_event_borrow_payload_field_const(event);
6a18b281 1407 if (!main_field) {
6a18b281
MD
1408 goto end;
1409 }
3228cc1d 1410 if (!pretty->start_line) {
dd61c4ed 1411 bt_common_g_string_append(pretty->string, ", ");
6e1bc0df 1412 }
3228cc1d
PP
1413 pretty->start_line = false;
1414 if (pretty->options.print_scope_field_names) {
1415 print_name_equal(pretty, "event.fields");
6a18b281 1416 }
3228cc1d 1417 ret = print_field(pretty, main_field,
2f84c7be 1418 pretty->options.print_payload_field_names);
a82e90e8 1419
6a18b281 1420end:
af9a82eb
JG
1421 return ret;
1422}
1423
08899d39 1424static
0f6bea4e 1425int flush_buf(FILE *stream, struct pretty_component *pretty)
08899d39
PP
1426{
1427 int ret = 0;
1428
1429 if (pretty->string->len == 0) {
1430 goto end;
1431 }
1432
0f6bea4e 1433 if (fwrite(pretty->string->str, pretty->string->len, 1, stream) != 1) {
08899d39
PP
1434 ret = -1;
1435 }
1436
1437end:
1438 return ret;
1439}
1440
d94d92ac 1441int pretty_print_event(struct pretty_component *pretty,
d6e69534 1442 const bt_message *event_msg)
af9a82eb 1443{
d94d92ac 1444 int ret;
b19ff26f 1445 const bt_event *event =
d6e69534 1446 bt_message_event_borrow_event_const(event_msg);
af9a82eb 1447
98b15851 1448 BT_ASSERT_DBG(event);
3228cc1d 1449 pretty->start_line = true;
5280f742 1450 g_string_assign(pretty->string, "");
2c091c04 1451 ret = print_event_header(pretty, event_msg);
d94d92ac 1452 if (ret != 0) {
af9a82eb
JG
1453 goto end;
1454 }
6a18b281 1455
3228cc1d 1456 ret = print_stream_packet_context(pretty, event);
d94d92ac 1457 if (ret != 0) {
6a18b281
MD
1458 goto end;
1459 }
6a18b281 1460
3228cc1d 1461 ret = print_stream_event_context(pretty, event);
d94d92ac 1462 if (ret != 0) {
6a18b281
MD
1463 goto end;
1464 }
6a18b281 1465
3228cc1d 1466 ret = print_event_context(pretty, event);
d94d92ac 1467 if (ret != 0) {
6a18b281
MD
1468 goto end;
1469 }
6a18b281 1470
3228cc1d 1471 ret = print_event_payload(pretty, event);
d94d92ac 1472 if (ret != 0) {
6a18b281
MD
1473 goto end;
1474 }
af9a82eb 1475
dd61c4ed 1476 bt_common_g_string_append_c(pretty->string, '\n');
0f6bea4e 1477 if (flush_buf(pretty->out, pretty)) {
d94d92ac 1478 ret = -1;
5280f742
PP
1479 goto end;
1480 }
1481
af9a82eb
JG
1482end:
1483 return ret;
1484}
0f6bea4e
PP
1485
1486static
8e53bed4
PP
1487int print_discarded_elements_msg(struct pretty_component *pretty,
1488 const bt_stream *stream,
1489 const bt_clock_snapshot *begin_clock_snapshot,
1490 const bt_clock_snapshot *end_clock_snapshot,
0f6bea4e
PP
1491 uint64_t count, const char *elem_type)
1492{
d94d92ac 1493 int ret = 0;
b19ff26f
PP
1494 const bt_stream_class *stream_class = NULL;
1495 const bt_trace *trace = NULL;
0f6bea4e
PP
1496 const char *stream_name;
1497 const char *trace_name;
8e53bed4 1498 bt_uuid trace_uuid;
0f6bea4e
PP
1499 int64_t stream_class_id;
1500 int64_t stream_id;
697f479d 1501 const char *init_msg;
0f6bea4e
PP
1502
1503 /* Stream name */
0f6bea4e 1504 stream_name = bt_stream_get_name(stream);
8e53bed4
PP
1505 if (!stream_name) {
1506 stream_name = "(unknown)";
1507 }
0f6bea4e
PP
1508
1509 /* Stream class ID */
40f4ba76 1510 stream_class = bt_stream_borrow_class_const(stream);
0f6bea4e
PP
1511 BT_ASSERT(stream_class);
1512 stream_class_id = bt_stream_class_get_id(stream_class);
1513
1514 /* Stream ID */
1515 stream_id = bt_stream_get_id(stream);
1516
1517 /* Trace name */
8e53bed4 1518 trace = bt_stream_borrow_trace_const(stream);
0f6bea4e
PP
1519 BT_ASSERT(trace);
1520 trace_name = bt_trace_get_name(trace);
1521 if (!trace_name) {
1522 trace_name = "(unknown)";
1523 }
1524
1525 /* Trace UUID */
335a2da5 1526 trace_uuid = bt_trace_get_uuid(trace);
0f6bea4e
PP
1527
1528 /* Format message */
1529 g_string_assign(pretty->string, "");
697f479d
PP
1530
1531 if (count == UINT64_C(-1)) {
1532 init_msg = "Tracer may have discarded";
1533 } else {
1534 init_msg = "Tracer discarded";
1535 }
1536
f354b1e1 1537 bt_common_g_string_append_printf(pretty->string,
697f479d 1538 "%s%sWARNING%s%s: %s ",
0f6bea4e
PP
1539 bt_common_color_fg_yellow(),
1540 bt_common_color_bold(),
1541 bt_common_color_reset(),
697f479d 1542 bt_common_color_fg_yellow(), init_msg);
8e53bed4
PP
1543
1544 if (count == UINT64_C(-1)) {
f354b1e1 1545 bt_common_g_string_append_printf(pretty->string, "%ss", elem_type);
8e53bed4 1546 } else {
f354b1e1 1547 bt_common_g_string_append_printf(pretty->string,
8e53bed4
PP
1548 "%" PRIu64 " %s%s", count, elem_type,
1549 count == 1 ? "" : "s");
1550 }
0f6bea4e 1551
dd61c4ed 1552 bt_common_g_string_append_c(pretty->string, ' ');
3f2f6b21 1553
605e1019 1554 if (begin_clock_snapshot && end_clock_snapshot) {
dd61c4ed 1555 bt_common_g_string_append(pretty->string, "between [");
9c202476 1556 print_timestamp_wall(pretty, begin_clock_snapshot, false);
dd61c4ed 1557 bt_common_g_string_append(pretty->string, "] and [");
9c202476 1558 print_timestamp_wall(pretty, end_clock_snapshot, false);
dd61c4ed 1559 bt_common_g_string_append(pretty->string, "]");
0f6bea4e 1560 } else {
dd61c4ed 1561 bt_common_g_string_append(pretty->string, "(unknown time range)");
0f6bea4e
PP
1562 }
1563
f354b1e1 1564 bt_common_g_string_append_printf(pretty->string, " in trace \"%s\" ", trace_name);
0f6bea4e
PP
1565
1566 if (trace_uuid) {
f354b1e1 1567 bt_common_g_string_append_printf(pretty->string,
6162e6b7
MJ
1568 "(UUID: " BT_UUID_FMT ") ",
1569 BT_UUID_FMT_VALUES(trace_uuid));
0f6bea4e 1570 } else {
dd61c4ed 1571 bt_common_g_string_append(pretty->string, "(no UUID) ");
0f6bea4e
PP
1572 }
1573
f354b1e1 1574 bt_common_g_string_append_printf(pretty->string,
8e53bed4 1575 "within stream \"%s\" (stream class ID: %" PRIu64 ", ",
0f6bea4e
PP
1576 stream_name, stream_class_id);
1577
1578 if (stream_id >= 0) {
f354b1e1 1579 bt_common_g_string_append_printf(pretty->string,
8e53bed4 1580 "stream ID: %" PRIu64, stream_id);
0f6bea4e 1581 } else {
dd61c4ed 1582 bt_common_g_string_append(pretty->string, "no stream ID");
0f6bea4e
PP
1583 }
1584
f354b1e1 1585 bt_common_g_string_append_printf(pretty->string, ").%s\n",
0f6bea4e
PP
1586 bt_common_color_reset());
1587
1588 /*
1589 * Print to standard error stream to remain backward compatible
1590 * with Babeltrace 1.
1591 */
1592 if (flush_buf(stderr, pretty)) {
d94d92ac 1593 ret = -1;
0f6bea4e
PP
1594 }
1595
1596 return ret;
1597}
1598
8e53bed4
PP
1599int pretty_print_discarded_items(struct pretty_component *pretty,
1600 const bt_message *msg)
0f6bea4e 1601{
8e53bed4
PP
1602 const bt_clock_snapshot *begin = NULL;
1603 const bt_clock_snapshot *end = NULL;
1604 const bt_stream *stream;
1605 const bt_stream_class *stream_class;
1606 uint64_t count = UINT64_C(-1);
1607 const char *elem_type;
1608
1609 switch (bt_message_get_type(msg)) {
1610 case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
1611 stream = bt_message_discarded_events_borrow_stream_const(msg);
1612
1613 if (bt_message_discarded_events_get_count(msg, &count) ==
1614 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1615 count = UINT64_C(-1);
0f6bea4e 1616 }
8e53bed4
PP
1617
1618 elem_type = "event";
1619 break;
1620 case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
1621 stream = bt_message_discarded_packets_borrow_stream_const(msg);
1622
1623 if (bt_message_discarded_packets_get_count(msg, &count) ==
1624 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1625 count = UINT64_C(-1);
1626 }
1627
1628 elem_type = "packet";
1629 break;
1630 default:
498e7994 1631 bt_common_abort();
0f6bea4e
PP
1632 }
1633
8e53bed4
PP
1634 BT_ASSERT(stream);
1635 stream_class = bt_stream_borrow_class_const(stream);
1636
2e90378a
PP
1637 switch (bt_message_get_type(msg)) {
1638 case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
1639 if (bt_stream_class_discarded_events_have_default_clock_snapshots(
1640 stream_class)) {
9b24b6aa 1641 begin = bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
0cbc2c33 1642 msg);
9b24b6aa 1643 end = bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
0cbc2c33 1644 msg);
2e90378a
PP
1645 }
1646
1647 break;
1648 case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
1649 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(
1650 stream_class)) {
9b24b6aa 1651 begin = bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
0cbc2c33 1652 msg);
9b24b6aa 1653 end = bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
0cbc2c33 1654 msg);
0f6bea4e 1655 }
2e90378a
PP
1656
1657 break;
1658 default:
498e7994 1659 bt_common_abort();
0f6bea4e
PP
1660 }
1661
8e53bed4
PP
1662 print_discarded_elements_msg(pretty, stream, begin, end,
1663 count, elem_type);
44c440bc 1664 return 0;
0f6bea4e 1665}
04609487 1666
04609487
PP
1667void pretty_print_init(void)
1668{
1669 strcpy(color_name, bt_common_color_bold());
1670 strcpy(color_field_name, bt_common_color_fg_cyan());
1671 strcpy(color_rst, bt_common_color_reset());
1672 strcpy(color_string_value, bt_common_color_bold());
1673 strcpy(color_number_value, bt_common_color_bold());
1674 strcpy(color_enum_mapping_name, bt_common_color_bold());
1675 strcpy(color_unknown, bt_common_color_bold());
1676 strcat(color_unknown, bt_common_color_fg_bright_red());
1677 strcpy(color_event_name, bt_common_color_bold());
1678 strcat(color_event_name, bt_common_color_fg_bright_magenta());
1679 strcpy(color_timestamp, bt_common_color_bold());
1680 strcat(color_timestamp, bt_common_color_fg_bright_yellow());
1681}
This page took 0.232115 seconds and 4 git commands to generate.