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