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