Fix: allow duplicate keys and overlapping ranges in enumerations
[babeltrace.git] / plugins / text / 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
30#include <babeltrace/ctf-ir/event.h>
31#include <babeltrace/ctf-ir/event-class.h>
6a18b281 32#include <babeltrace/ctf-ir/packet.h>
af9a82eb
JG
33#include <babeltrace/ctf-ir/stream.h>
34#include <babeltrace/ctf-ir/stream-class.h>
ac0c6bdd 35#include <babeltrace/ctf-ir/clock-class.h>
6a18b281
MD
36#include <babeltrace/ctf-ir/field-types.h>
37#include <babeltrace/ctf-ir/fields.h>
1556a1af 38#include <babeltrace/ctf-ir/trace.h>
6a18b281
MD
39#include <babeltrace/bitfield.h>
40#include <inttypes.h>
af9a82eb
JG
41#include "text.h"
42
1556a1af
JG
43#define NSEC_PER_SEC 1000000000LL
44
6a18b281
MD
45static inline
46const char *rem_(const char *str)
47{
48 if (str[0] == '_')
49 return &str[1];
50 else
51 return str;
52}
53
af9a82eb
JG
54struct timestamp {
55 int64_t real_timestamp; /* Relative to UNIX epoch. */
56 uint64_t clock_value; /* In cycles. */
57};
58
6a18b281
MD
59static
60enum bt_component_status print_field(struct text_component *text,
61 struct bt_ctf_field *field, bool print_names);
62
af9a82eb
JG
63static
64void print_timestamp_cycles(struct text_component *text,
ac0c6bdd 65 struct bt_ctf_clock_class *clock_class,
af9a82eb
JG
66 struct bt_ctf_event *event)
67{
1556a1af
JG
68 int ret;
69 struct bt_ctf_clock_value *clock_value;
70 uint64_t cycles;
71
ac0c6bdd 72 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
1556a1af
JG
73 if (!clock_value) {
74 fputs("????????????????????", text->out);
75 return;
76 }
77
78 ret = bt_ctf_clock_value_get_value(clock_value, &cycles);
79 bt_put(clock_value);
80 if (ret) {
81 fprintf(text->out, "Error");
82 return;
83 }
84 fprintf(text->out, "%020" PRIu64, cycles);
3af83b5a
MD
85
86 if (text->last_cycles_timestamp != -1ULL) {
87 text->delta_cycles = cycles - text->last_cycles_timestamp;
88 }
89 text->last_cycles_timestamp = cycles;
af9a82eb
JG
90}
91
92static
93void print_timestamp_wall(struct text_component *text,
ac0c6bdd 94 struct bt_ctf_clock_class *clock_class,
af9a82eb
JG
95 struct bt_ctf_event *event)
96{
1556a1af
JG
97 int ret;
98 struct bt_ctf_clock_value *clock_value;
99 int64_t ts_nsec = 0; /* add configurable offset */
100 int64_t ts_sec = 0; /* add configurable offset */
101 uint64_t ts_sec_abs, ts_nsec_abs;
102 bool is_negative;
af9a82eb 103
ac0c6bdd 104 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
1556a1af
JG
105 if (!clock_value) {
106 fputs("??:??:??.?????????", text->out);
107 return;
108 }
109
110 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
111 bt_put(clock_value);
112 if (ret) {
113 fprintf(text->out, "Error");
114 return;
115 }
116
3af83b5a
MD
117 if (text->last_real_timestamp != -1ULL) {
118 text->delta_real_timestamp = ts_nsec - text->last_real_timestamp;
119 }
120 text->last_real_timestamp = ts_nsec;
121
1556a1af
JG
122 ts_sec += ts_nsec / NSEC_PER_SEC;
123 ts_nsec = ts_nsec % NSEC_PER_SEC;
124 if (ts_sec >= 0 && ts_nsec >= 0) {
125 is_negative = false;
126 ts_sec_abs = ts_sec;
127 ts_nsec_abs = ts_nsec;
128 } else if (ts_sec > 0 && ts_nsec < 0) {
129 is_negative = false;
130 ts_sec_abs = ts_sec - 1;
131 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
132 } else if (ts_sec == 0 && ts_nsec < 0) {
133 is_negative = true;
134 ts_sec_abs = ts_sec;
135 ts_nsec_abs = -ts_nsec;
136 } else if (ts_sec < 0 && ts_nsec > 0) {
137 is_negative = true;
138 ts_sec_abs = -(ts_sec + 1);
139 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
140 } else if (ts_sec < 0 && ts_nsec == 0) {
141 is_negative = true;
142 ts_sec_abs = -ts_sec;
143 ts_nsec_abs = ts_nsec;
144 } else { /* (ts_sec < 0 && ts_nsec < 0) */
145 is_negative = true;
146 ts_sec_abs = -ts_sec;
147 ts_nsec_abs = -ts_nsec;
148 }
149
f504043c 150 if (!text->options.clock_seconds) {
1556a1af
JG
151 struct tm tm;
152 time_t time_s = (time_t) ts_sec_abs;
153
154 if (is_negative) {
155 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
156 goto seconds;
157 }
158
f504043c 159 if (!text->options.clock_gmt) {
1556a1af
JG
160 struct tm *res;
161
162 res = localtime_r(&time_s, &tm);
163 if (!res) {
164 fprintf(stderr, "[warning] Unable to get localtime.\n");
165 goto seconds;
166 }
167 } else {
168 struct tm *res;
169
170 res = gmtime_r(&time_s, &tm);
171 if (!res) {
172 fprintf(stderr, "[warning] Unable to get gmtime.\n");
173 goto seconds;
174 }
175 }
f504043c 176 if (text->options.clock_date) {
1556a1af
JG
177 char timestr[26];
178 size_t res;
179
180 /* Print date and time */
181 res = strftime(timestr, sizeof(timestr),
182 "%F ", &tm);
183 if (!res) {
184 fprintf(stderr, "[warning] Unable to print ascii time.\n");
185 goto seconds;
186 }
187 fprintf(text->out, "%s", timestr);
188 }
189 /* Print time in HH:MM:SS.ns */
190 fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64,
191 tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs);
192 goto end;
193 }
194seconds:
195 fprintf(text->out, "%s%" PRId64 ".%09" PRIu64,
196 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
197end:
198 return;
af9a82eb
JG
199}
200
201static
202enum bt_component_status print_event_timestamp(struct text_component *text,
c3c30b08 203 struct bt_ctf_event *event, bool *start_line)
af9a82eb
JG
204{
205 bool print_names = text->options.print_header_field_names;
206 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
6a18b281 207 struct bt_ctf_stream *stream = NULL;
1556a1af
JG
208 struct bt_ctf_stream_class *stream_class = NULL;
209 struct bt_ctf_trace *trace = NULL;
ac0c6bdd 210 struct bt_ctf_clock_class *clock_class = NULL;
af9a82eb 211 FILE *out = text->out;
af9a82eb
JG
212
213 stream = bt_ctf_event_get_stream(event);
214 if (!stream) {
215 ret = BT_COMPONENT_STATUS_ERROR;
216 goto end;
217 }
218
1556a1af 219 stream_class = bt_ctf_stream_get_class(stream);
f504043c
MD
220 if (!stream_class) {
221 ret = BT_COMPONENT_STATUS_ERROR;
222 goto end;
223 }
1556a1af 224 trace = bt_ctf_stream_class_get_trace(stream_class);
f504043c
MD
225 if (!trace) {
226 ret = BT_COMPONENT_STATUS_ERROR;
227 goto end;
228 }
ac0c6bdd
PP
229 clock_class = bt_ctf_trace_get_clock_class(trace, 0);
230 if (!clock_class) {
f504043c
MD
231 ret = BT_COMPONENT_STATUS_ERROR;
232 goto end;
233 }
af9a82eb
JG
234
235 fputs(print_names ? "timestamp = " : "[", out);
236 if (text->options.print_timestamp_cycles) {
ac0c6bdd 237 print_timestamp_cycles(text, clock_class, event);
af9a82eb 238 } else {
ac0c6bdd 239 print_timestamp_wall(text, clock_class, event);
af9a82eb
JG
240 }
241
c3c30b08
MD
242 if (!print_names)
243 fputs("] ", out);
c3c30b08 244
3af83b5a
MD
245 if (text->options.print_delta_field) {
246 if (print_names)
247 fputs(", delta = ", text->out);
248 else
249 fputs("(", text->out);
250 if (text->options.print_timestamp_cycles) {
251 if (text->delta_cycles == -1ULL) {
252 fputs("+??????????\?\?) ", text->out); /* Not a trigraph. */
253 } else {
254 fprintf(text->out, "+%012" PRIu64, text->delta_cycles);
255 }
256 } else {
257 if (text->delta_real_timestamp != -1ULL) {
258 uint64_t delta_sec, delta_nsec, delta;
f504043c 259
3af83b5a
MD
260 delta = text->delta_real_timestamp;
261 delta_sec = delta / NSEC_PER_SEC;
262 delta_nsec = delta % NSEC_PER_SEC;
263 fprintf(text->out, "+%" PRIu64 ".%09" PRIu64,
264 delta_sec, delta_nsec);
265 } else {
266 fputs("+?.?????????", text->out);
267 }
268 }
269 if (!print_names) {
270 fputs(") ", text->out);
271 }
272 }
273 *start_line = !print_names;
f504043c 274
af9a82eb
JG
275end:
276 bt_put(stream);
ac0c6bdd 277 bt_put(clock_class);
1556a1af
JG
278 bt_put(stream_class);
279 bt_put(trace);
af9a82eb
JG
280 return ret;
281}
282
6a18b281 283static
af9a82eb
JG
284enum bt_component_status print_event_header(struct text_component *text,
285 struct bt_ctf_event *event)
286{
6a18b281
MD
287 bool print_names = text->options.print_header_field_names;
288 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
289 struct bt_ctf_event_class *event_class = NULL;
c3c30b08
MD
290 struct bt_ctf_stream_class *stream_class = NULL;
291 struct bt_ctf_trace *trace_class = NULL;
af9a82eb 292
6a18b281
MD
293 event_class = bt_ctf_event_get_class(event);
294 if (!event_class) {
295 ret = BT_COMPONENT_STATUS_ERROR;
296 goto end;
297 }
c3c30b08
MD
298 stream_class = bt_ctf_event_class_get_stream_class(event_class);
299 if (!stream_class) {
300 ret = BT_COMPONENT_STATUS_ERROR;
301 goto end;
302 }
303 trace_class = bt_ctf_stream_class_get_trace(stream_class);
304 if (!trace_class) {
305 ret = BT_COMPONENT_STATUS_ERROR;
306 goto end;
307 }
6e1bc0df
MD
308 if (!text->start_line) {
309 fputs(", ", text->out);
310 }
311 text->start_line = false;
c3c30b08 312 ret = print_event_timestamp(text, event, &text->start_line);
af9a82eb
JG
313 if (ret != BT_COMPONENT_STATUS_OK) {
314 goto end;
315 }
c3c30b08
MD
316 if (text->options.print_trace_field) {
317 const char *name;
318
319 name = bt_ctf_trace_get_name(trace_class);
320 if (name) {
321 if (!text->start_line) {
322 fputs(", ", text->out);
323 }
324 text->start_line = false;
325 if (print_names) {
326 fputs("trace = ", text->out);
327 }
328 fprintf(text->out, "%s", name);
329 }
330 }
331 if (text->options.print_trace_hostname_field) {
332 struct bt_value *hostname_str;
333
334 hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
335 "hostname");
336 if (hostname_str) {
337 const char *str;
338
339 if (!text->start_line) {
340 fputs(", ", text->out);
341 }
342 text->start_line = false;
343 if (print_names) {
344 fputs("trace:hostname = ", text->out);
345 }
346 if (bt_value_string_get(hostname_str, &str)
347 == BT_VALUE_STATUS_OK) {
348 fprintf(text->out, "%s", str);
349 }
350 bt_put(hostname_str);
351 }
352 }
353 if (text->options.print_trace_domain_field) {
354 struct bt_value *domain_str;
355
356 domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
357 "domain");
358 if (domain_str) {
359 const char *str;
360
361 if (!text->start_line) {
362 fputs(", ", text->out);
363 }
364 text->start_line = false;
365 if (print_names) {
366 fputs("trace:domain = ", text->out);
367 }
368 if (bt_value_string_get(domain_str, &str)
369 == BT_VALUE_STATUS_OK) {
370 fprintf(text->out, "%s", str);
371 }
372 bt_put(domain_str);
373 }
374 }
375 if (text->options.print_trace_procname_field) {
376 struct bt_value *procname_str;
377
378 procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
379 "procname");
380 if (procname_str) {
381 const char *str;
382
383 if (!text->start_line) {
384 fputs(", ", text->out);
385 }
386 text->start_line = false;
387 if (print_names) {
388 fputs("trace:procname = ", text->out);
389 }
390 if (bt_value_string_get(procname_str, &str)
391 == BT_VALUE_STATUS_OK) {
392 fprintf(text->out, "%s", str);
393 }
394 bt_put(procname_str);
395 }
396 }
397 if (text->options.print_trace_vpid_field) {
398 struct bt_value *vpid_value;
399
400 vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
401 "vpid");
402 if (vpid_value) {
403 int64_t value;
404
405 if (!text->start_line) {
406 fputs(", ", text->out);
407 }
408 text->start_line = false;
409 if (print_names) {
410 fputs("trace:vpid = ", text->out);
411 }
412 if (bt_value_integer_get(vpid_value, &value)
413 == BT_VALUE_STATUS_OK) {
414 fprintf(text->out, "(%" PRId64 ")", value);
415 }
416 bt_put(vpid_value);
417 }
418 }
419 if (text->options.print_loglevel_field) {
420 struct bt_value *loglevel_str, *loglevel_value;
421
422 loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
423 "loglevel_string");
424 loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class,
425 "loglevel");
426 if (loglevel_str || loglevel_value) {
427 bool has_str = false;
428
429 if (!text->start_line) {
430 fputs(", ", text->out);
431 }
432 text->start_line = false;
433 if (print_names) {
434 fputs("loglevel = ", text->out);
435 }
436 if (loglevel_str) {
437 const char *str;
438
439 if (bt_value_string_get(loglevel_str, &str)
440 == BT_VALUE_STATUS_OK) {
441 fprintf(text->out, "%s", str);
442 has_str = true;
443 }
444 }
445 if (loglevel_value) {
446 int64_t value;
447
448 if (bt_value_integer_get(loglevel_value, &value)
449 == BT_VALUE_STATUS_OK) {
450 fprintf(text->out, "%s(%" PRId64 ")",
451 has_str ? " " : "", value);
452 }
453 }
454 bt_put(loglevel_str);
455 bt_put(loglevel_value);
456 }
457 }
458 if (text->options.print_emf_field) {
459 struct bt_value *uri_str;
460
461 uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
462 "model.emf.uri");
463 if (uri_str) {
464 if (!text->start_line) {
465 fputs(", ", text->out);
466 }
467 text->start_line = false;
468 if (print_names) {
469 fputs("model.emf.uri = ", text->out);
470 }
471 if (uri_str) {
472 const char *str;
473
474 if (bt_value_string_get(uri_str, &str)
475 == BT_VALUE_STATUS_OK) {
476 fprintf(text->out, "%s", str);
477 }
478 }
479 bt_put(uri_str);
480 }
481 }
c3c30b08
MD
482 if (!text->start_line) {
483 fputs(", ", text->out);
484 }
485 text->start_line = false;
6a18b281
MD
486 if (print_names) {
487 fputs("name = ", text->out);
488 }
af9a82eb
JG
489 fputs(bt_ctf_event_class_get_name(event_class), text->out);
490end:
c3c30b08
MD
491 bt_put(trace_class);
492 bt_put(stream_class);
6a18b281
MD
493 bt_put(event_class);
494 return ret;
495}
496
497static
498enum bt_component_status print_integer(struct text_component *text,
499 struct bt_ctf_field *field)
500{
501 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
502 struct bt_ctf_field_type *field_type = NULL;
503 enum bt_ctf_integer_base base;
504 enum bt_ctf_string_encoding encoding;
505 int signedness;
506 union {
507 uint64_t u;
508 int64_t s;
509 } v;
510
511 field_type = bt_ctf_field_get_type(field);
512 if (!field_type) {
513 ret = BT_COMPONENT_STATUS_ERROR;
514 goto end;
515 }
516 signedness = bt_ctf_field_type_integer_get_signed(field_type);
517 if (signedness < 0) {
518 ret = BT_COMPONENT_STATUS_ERROR;
519 goto end;
520 }
521 if (!signedness) {
522 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
523 ret = BT_COMPONENT_STATUS_ERROR;
524 goto end;
525 }
526 } else {
527 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
528 ret = BT_COMPONENT_STATUS_ERROR;
529 goto end;
530 }
531 }
532
533 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
534 switch (encoding) {
535 case BT_CTF_STRING_ENCODING_UTF8:
536 case BT_CTF_STRING_ENCODING_ASCII:
537 g_string_append_c(text->string, (int) v.u);
538 goto end;
539 case BT_CTF_STRING_ENCODING_NONE:
540 case BT_CTF_STRING_ENCODING_UNKNOWN:
541 break;
542 default:
543 ret = BT_COMPONENT_STATUS_ERROR;
544 goto end;
545 }
546
547 base = bt_ctf_field_type_integer_get_base(field_type);
548 switch (base) {
549 case BT_CTF_INTEGER_BASE_BINARY:
550 {
551 int bitnr, len;
552
553 len = bt_ctf_field_type_integer_get_size(field_type);
554 if (len < 0) {
555 ret = BT_COMPONENT_STATUS_ERROR;
556 goto end;
557 }
558 fprintf(text->out, "0b");
559 v.u = _bt_piecewise_lshift(v.u, 64 - len);
560 for (bitnr = 0; bitnr < len; bitnr++) {
561 fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
562 v.u = _bt_piecewise_lshift(v.u, 1);
563 }
564 break;
565 }
566 case BT_CTF_INTEGER_BASE_OCTAL:
567 {
568 if (signedness) {
569 int len;
570
571 len = bt_ctf_field_type_integer_get_size(field_type);
572 if (len < 0) {
573 ret = BT_COMPONENT_STATUS_ERROR;
574 goto end;
575 }
576 if (len < 64) {
577 size_t rounded_len;
578
579 assert(len != 0);
580 /* Round length to the nearest 3-bit */
581 rounded_len = (((len - 1) / 3) + 1) * 3;
582 v.u &= ((uint64_t) 1 << rounded_len) - 1;
583 }
584 }
585
586 fprintf(text->out, "0%" PRIo64, v.u);
587 break;
588 }
589 case BT_CTF_INTEGER_BASE_DECIMAL:
590 if (!signedness) {
591 fprintf(text->out, "%" PRIu64, v.u);
592 } else {
593 fprintf(text->out, "%" PRId64, v.s);
594 }
595 break;
596 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
597 {
598 int len;
599
600 len = bt_ctf_field_type_integer_get_size(field_type);
601 if (len < 0) {
602 ret = BT_COMPONENT_STATUS_ERROR;
603 goto end;
604 }
605 if (len < 64) {
606 /* Round length to the nearest nibble */
607 uint8_t rounded_len = ((len + 3) & ~0x3);
608
609 v.u &= ((uint64_t) 1 << rounded_len) - 1;
610 }
611
612 fprintf(text->out, "0x%" PRIX64, v.u);
613 break;
614 }
615 default:
616 ret = BT_COMPONENT_STATUS_ERROR;
617 goto end;
618 }
619end:
620 bt_put(field_type);
621 return ret;
622}
623
624static
625enum bt_component_status print_enum(struct text_component *text,
626 struct bt_ctf_field *field)
627{
628 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
629 struct bt_ctf_field *container_field = NULL;
96e8f959
MD
630 struct bt_ctf_field_type *enumeration_field_type = NULL;
631 struct bt_ctf_field_type *container_field_type = NULL;
632 struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
633 int nr_mappings = 0;
634 int is_signed;
635
636 enumeration_field_type = bt_ctf_field_get_type(field);
637 if (!enumeration_field_type) {
638 ret = BT_COMPONENT_STATUS_ERROR;
639 goto end;
640 }
6a18b281
MD
641 container_field = bt_ctf_field_enumeration_get_container(field);
642 if (!container_field) {
643 ret = BT_COMPONENT_STATUS_ERROR;
644 goto end;
645 }
96e8f959
MD
646 container_field_type = bt_ctf_field_get_type(container_field);
647 if (!container_field_type) {
648 ret = BT_COMPONENT_STATUS_ERROR;
649 goto end;
650 }
651 is_signed = bt_ctf_field_type_integer_get_signed(container_field_type);
652 if (is_signed < 0) {
653 ret = BT_COMPONENT_STATUS_ERROR;
654 goto end;
655 }
656 if (is_signed) {
657 int64_t value;
658
659 if (bt_ctf_field_signed_integer_get_value(container_field,
660 &value)) {
661 ret = BT_COMPONENT_STATUS_ERROR;
662 goto end;
663 }
664 iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
665 enumeration_field_type, value);
6a18b281 666 } else {
96e8f959
MD
667 uint64_t value;
668
669 if (bt_ctf_field_unsigned_integer_get_value(container_field,
670 &value)) {
671 ret = BT_COMPONENT_STATUS_ERROR;
672 goto end;
673 }
674 iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
675 enumeration_field_type, value);
676 }
677 if (!iter) {
678 ret = BT_COMPONENT_STATUS_ERROR;
679 goto end;
680 }
681 fprintf(text->out, "( ");
682 for (;;) {
683 const char *mapping_name;
684
685 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
686 iter, &mapping_name, NULL, NULL) < 0) {
687 ret = BT_COMPONENT_STATUS_ERROR;
688 goto end;
689 }
690 if (nr_mappings++)
691 fprintf(text->out, ", ");
692 fprintf(text->out, "\"%s\"", mapping_name);
693 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) {
694 break;
695 }
696 }
697 if (!nr_mappings) {
698 fprintf(text->out, "<unknown>");
6a18b281
MD
699 }
700 fprintf(text->out, " : container = ");
701 ret = print_integer(text, container_field);
702 if (ret != BT_COMPONENT_STATUS_OK) {
703 goto end;
704 }
705 fprintf(text->out, " )");
706end:
96e8f959
MD
707 bt_put(iter);
708 bt_put(container_field_type);
6a18b281 709 bt_put(container_field);
96e8f959 710 bt_put(enumeration_field_type);
6a18b281
MD
711 return ret;
712}
713
714static
715enum bt_component_status print_struct_field(struct text_component *text,
716 struct bt_ctf_field *_struct,
717 struct bt_ctf_field_type *struct_type,
718 int i, bool print_names)
719{
720 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
721 const char *field_name;
722 struct bt_ctf_field *field = NULL;
723 struct bt_ctf_field_type *field_type = NULL;;
724
725 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
726 if (!field) {
727 ret = BT_COMPONENT_STATUS_ERROR;
728 goto end;
729 }
730 if (bt_ctf_field_type_structure_get_field(struct_type,
731 &field_name, &field_type, i) < 0) {
732 ret = BT_COMPONENT_STATUS_ERROR;
733 goto end;
734 }
735
736 if (i != 0) {
737 fprintf(text->out, ", ");
738 } else {
739 fprintf(text->out, " ");
740 }
741 if (print_names) {
742 fprintf(text->out, "%s = ", rem_(field_name));
743 }
744 ret = print_field(text, field, print_names);
745end:
746 bt_put(field_type);
747 bt_put(field);
748 return ret;
749}
750
751static
752enum bt_component_status print_struct(struct text_component *text,
753 struct bt_ctf_field *_struct, bool print_names)
754{
755 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
756 struct bt_ctf_field_type *struct_type = NULL;
757 int nr_fields, i;
758
759 struct_type = bt_ctf_field_get_type(_struct);
760 if (!struct_type) {
761 ret = BT_COMPONENT_STATUS_ERROR;
762 goto end;
763 }
764 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
765 if (nr_fields < 0) {
766 ret = BT_COMPONENT_STATUS_ERROR;
767 goto end;
768 }
769 fprintf(text->out, "{");
770 text->depth++;
771 for (i = 0; i < nr_fields; i++) {
772 ret = print_struct_field(text, _struct, struct_type, i,
773 print_names);
774 if (ret != BT_COMPONENT_STATUS_OK) {
775 goto end;
776 }
777 }
778 text->depth--;
779 fprintf(text->out, " }");
780end:
781 bt_put(struct_type);
782 return ret;
783}
784
785static
786enum bt_component_status print_array_field(struct text_component *text,
787 struct bt_ctf_field *array, uint64_t i,
788 bool is_string, bool print_names)
789{
790 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
791 struct bt_ctf_field *field = NULL;
792
793 if (!is_string) {
794 if (i != 0) {
795 fprintf(text->out, ", ");
796 } else {
797 fprintf(text->out, " ");
798 }
799 }
800 field = bt_ctf_field_array_get_field(array, i);
801 if (!field) {
802 ret = BT_COMPONENT_STATUS_ERROR;
803 goto end;
804 }
805 ret = print_field(text, field, print_names);
806end:
807 bt_put(field);
808 return ret;
809}
810
811static
812enum bt_component_status print_array(struct text_component *text,
813 struct bt_ctf_field *array, bool print_names)
814{
815 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
816 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
817 enum bt_ctf_type_id type_id;
818 int64_t len;
819 uint64_t i;
820 bool is_string = false;
821
822 array_type = bt_ctf_field_get_type(array);
823 if (!array_type) {
824 ret = BT_COMPONENT_STATUS_ERROR;
825 goto end;
826 }
827 field_type = bt_ctf_field_type_array_get_element_type(array_type);
828 if (!field_type) {
829 ret = BT_COMPONENT_STATUS_ERROR;
830 goto end;
831 }
832 len = bt_ctf_field_type_array_get_length(array_type);
833 if (len < 0) {
834 ret = BT_COMPONENT_STATUS_ERROR;
835 goto end;
836 }
837 type_id = bt_ctf_field_type_get_type_id(field_type);
838 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
839 enum bt_ctf_string_encoding encoding;
840
841 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
842 if (encoding == BT_CTF_STRING_ENCODING_UTF8
843 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
844 int integer_len, integer_alignment;
845
846 integer_len = bt_ctf_field_type_integer_get_size(field_type);
847 if (integer_len < 0) {
848 return BT_COMPONENT_STATUS_ERROR;
849 }
850 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
851 if (integer_alignment < 0) {
852 return BT_COMPONENT_STATUS_ERROR;
853 }
854 if (integer_len == CHAR_BIT
855 && integer_alignment == CHAR_BIT) {
856 is_string = true;
857 }
858 }
859 }
860
861 if (is_string) {
862 g_string_assign(text->string, "");
863 } else {
864 fprintf(text->out, "[");
865 }
866
867 text->depth++;
868 for (i = 0; i < len; i++) {
869 ret = print_array_field(text, array, i, is_string, print_names);
870 if (ret != BT_COMPONENT_STATUS_OK) {
871 goto end;
872 }
873 }
874 text->depth--;
875
876 if (is_string) {
877 fprintf(text->out, "\"%s\"", text->string->str);
878 } else {
879 fprintf(text->out, " ]");
880 }
881end:
882 bt_put(field_type);
883 bt_put(array_type);
884 return ret;
885}
886
887static
888enum bt_component_status print_sequence_field(struct text_component *text,
889 struct bt_ctf_field *seq, uint64_t i,
890 bool is_string, bool print_names)
891{
892 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
893 struct bt_ctf_field *field = NULL;
894
895 if (!is_string) {
896 if (i != 0) {
897 fprintf(text->out, ", ");
898 } else {
899 fprintf(text->out, " ");
900 }
901 }
902 field = bt_ctf_field_sequence_get_field(seq, i);
903 if (!field) {
904 ret = BT_COMPONENT_STATUS_ERROR;
905 goto end;
906 }
907 ret = print_field(text, field, print_names);
908end:
909 bt_put(field);
910 return ret;
911}
912
913static
914enum bt_component_status print_sequence(struct text_component *text,
915 struct bt_ctf_field *seq, bool print_names)
916{
917 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
918 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
919 struct bt_ctf_field *length_field = NULL;
920 enum bt_ctf_type_id type_id;
921 uint64_t len;
922 uint64_t i;
923 bool is_string = false;
924
925 seq_type = bt_ctf_field_get_type(seq);
926 if (!seq_type) {
927 ret = BT_COMPONENT_STATUS_ERROR;
928 goto end;
929 }
930 length_field = bt_ctf_field_sequence_get_length(seq);
931 if (!length_field) {
932 ret = BT_COMPONENT_STATUS_ERROR;
933 goto end;
934 }
935 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
936 ret = BT_COMPONENT_STATUS_ERROR;
937 goto end;
938 }
939 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
940 if (!field_type) {
941 ret = BT_COMPONENT_STATUS_ERROR;
942 goto end;
943 }
944 type_id = bt_ctf_field_type_get_type_id(field_type);
945 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
946 enum bt_ctf_string_encoding encoding;
947
948 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
949 if (encoding == BT_CTF_STRING_ENCODING_UTF8
950 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
951 int integer_len, integer_alignment;
952
953 integer_len = bt_ctf_field_type_integer_get_size(field_type);
954 if (integer_len < 0) {
955 ret = BT_COMPONENT_STATUS_ERROR;
956 goto end;
957 }
958 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
959 if (integer_alignment < 0) {
960 ret = BT_COMPONENT_STATUS_ERROR;
961 goto end;
962 }
963 if (integer_len == CHAR_BIT
964 && integer_alignment == CHAR_BIT) {
965 is_string = true;
966 }
967 }
968 }
969
970 if (is_string) {
971 g_string_assign(text->string, "");
972 } else {
973 fprintf(text->out, "[");
974 }
975
976 text->depth++;
977 for (i = 0; i < len; i++) {
978 ret = print_sequence_field(text, seq, i,
979 is_string, print_names);
980 if (ret != BT_COMPONENT_STATUS_OK) {
981 goto end;
982 }
983 }
984 text->depth--;
985
986 if (is_string) {
987 fprintf(text->out, "\"%s\"", text->string->str);
988 } else {
989 fprintf(text->out, " ]");
990 }
991end:
992 bt_put(length_field);
993 bt_put(field_type);
994 bt_put(seq_type);
995 return ret;
996}
997
998static
999enum bt_component_status print_variant(struct text_component *text,
1000 struct bt_ctf_field *variant, bool print_names)
1001{
1002 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1003 struct bt_ctf_field *field = NULL;
1004
1005 field = bt_ctf_field_variant_get_current_field(variant);
1006 if (!field) {
1007 ret = BT_COMPONENT_STATUS_ERROR;
1008 goto end;
1009 }
1010 fprintf(text->out, "{ ");
1011 text->depth++;
1012 if (print_names) {
1013 struct bt_ctf_field *tag_field = NULL;
1014 const char *tag_choice;
1015
1016 tag_field = bt_ctf_field_variant_get_tag(variant);
1017 if (!tag_field) {
1018 ret = BT_COMPONENT_STATUS_ERROR;
1019 goto end;
1020 }
96e8f959 1021 tag_choice = bt_ctf_field_enumeration_get_single_mapping_name(tag_field);
6a18b281
MD
1022 if (!tag_choice) {
1023 bt_put(tag_field);
1024 ret = BT_COMPONENT_STATUS_ERROR;
1025 goto end;
1026 }
1027 fprintf(text->out, "%s = ", rem_(tag_choice));
1028 bt_put(tag_field);
1029 }
1030 ret = print_field(text, field, print_names);
1031 if (ret != BT_COMPONENT_STATUS_OK) {
1032 goto end;
1033 }
1034 text->depth--;
1035 fprintf(text->out, " }");
1036end:
1037 bt_put(field);
1038 return ret;
1039}
1040
1041static
1042enum bt_component_status print_field(struct text_component *text,
1043 struct bt_ctf_field *field, bool print_names)
1044{
1045 enum bt_ctf_type_id type_id;
1046
1047 type_id = bt_ctf_field_get_type_id(field);
1048 switch (type_id) {
1049 case CTF_TYPE_INTEGER:
1050 return print_integer(text, field);
1051 case CTF_TYPE_FLOAT:
1052 {
1053 double v;
1054
1055 if (bt_ctf_field_floating_point_get_value(field, &v)) {
1056 return BT_COMPONENT_STATUS_ERROR;
1057 }
1058 fprintf(text->out, "%g", v);
1059 return BT_COMPONENT_STATUS_OK;
1060 }
1061 case CTF_TYPE_ENUM:
1062 return print_enum(text, field);
1063 case CTF_TYPE_STRING:
1064 fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field));
1065 return BT_COMPONENT_STATUS_OK;
1066 case CTF_TYPE_STRUCT:
1067 return print_struct(text, field, print_names);
1068 case CTF_TYPE_UNTAGGED_VARIANT:
1069 case CTF_TYPE_VARIANT:
1070 return print_variant(text, field, print_names);
1071 case CTF_TYPE_ARRAY:
1072 return print_array(text, field, print_names);
1073 case CTF_TYPE_SEQUENCE:
1074 return print_sequence(text, field, print_names);
1075 default:
1076 fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id);
1077 return BT_COMPONENT_STATUS_ERROR;
1078 }
1079}
1080
1081static
1082enum bt_component_status print_stream_packet_context(struct text_component *text,
1083 struct bt_ctf_event *event)
1084{
1085 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1086 struct bt_ctf_packet *packet = NULL;
1087 struct bt_ctf_field *main_field = NULL;
1088
1089 packet = bt_ctf_event_get_packet(event);
1090 if (!packet) {
1091 ret = BT_COMPONENT_STATUS_ERROR;
1092 goto end;
1093 }
1094 main_field = bt_ctf_packet_get_context(packet);
1095 if (!main_field) {
6a18b281
MD
1096 goto end;
1097 }
6e1bc0df
MD
1098 if (!text->start_line) {
1099 fputs(", ", text->out);
1100 }
1101 text->start_line = false;
6a18b281 1102 if (text->options.print_scope_field_names) {
6e1bc0df 1103 fputs("stream.packet.context = ", text->out);
6a18b281
MD
1104 }
1105 ret = print_field(text, main_field,
1106 text->options.print_context_field_names);
1107end:
1108 bt_put(main_field);
1109 bt_put(packet);
1110 return ret;
1111}
1112
1113static
1114enum bt_component_status print_event_header_raw(struct text_component *text,
1115 struct bt_ctf_event *event)
1116{
1117 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1118 struct bt_ctf_field *main_field = NULL;
1119
1120 main_field = bt_ctf_event_get_header(event);
1121 if (!main_field) {
6a18b281
MD
1122 goto end;
1123 }
6e1bc0df
MD
1124 if (!text->start_line) {
1125 fputs(", ", text->out);
1126 }
1127 text->start_line = false;
6a18b281 1128 if (text->options.print_scope_field_names) {
6e1bc0df 1129 fputs("stream.event.header = ", text->out);
6a18b281
MD
1130 }
1131 ret = print_field(text, main_field,
6e1bc0df 1132 text->options.print_header_field_names);
6a18b281
MD
1133end:
1134 bt_put(main_field);
1135 return ret;
1136}
1137
1138static
1139enum bt_component_status print_stream_event_context(struct text_component *text,
1140 struct bt_ctf_event *event)
1141{
1142 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1143 struct bt_ctf_field *main_field = NULL;
1144
1145 main_field = bt_ctf_event_get_stream_event_context(event);
1146 if (!main_field) {
6a18b281
MD
1147 goto end;
1148 }
6e1bc0df
MD
1149 if (!text->start_line) {
1150 fputs(", ", text->out);
1151 }
1152 text->start_line = false;
6a18b281 1153 if (text->options.print_scope_field_names) {
6e1bc0df 1154 fputs("stream.event.context = ", text->out);
6a18b281
MD
1155 }
1156 ret = print_field(text, main_field,
1157 text->options.print_context_field_names);
1158end:
1159 bt_put(main_field);
1160 return ret;
1161}
1162
1163static
1164enum bt_component_status print_event_context(struct text_component *text,
1165 struct bt_ctf_event *event)
1166{
1167 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1168 struct bt_ctf_field *main_field = NULL;
1169
1170 main_field = bt_ctf_event_get_event_context(event);
1171 if (!main_field) {
6a18b281
MD
1172 goto end;
1173 }
6e1bc0df
MD
1174 if (!text->start_line) {
1175 fputs(", ", text->out);
1176 }
1177 text->start_line = false;
6a18b281 1178 if (text->options.print_scope_field_names) {
6e1bc0df 1179 fputs("event.context = ", text->out);
6a18b281
MD
1180 }
1181 ret = print_field(text, main_field,
1182 text->options.print_context_field_names);
1183end:
1184 bt_put(main_field);
1185 return ret;
1186}
1187
1188static
1189enum bt_component_status print_event_payload(struct text_component *text,
1190 struct bt_ctf_event *event)
1191{
1192 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1193 struct bt_ctf_field *main_field = NULL;
1194
1195 main_field = bt_ctf_event_get_payload_field(event);
1196 if (!main_field) {
6a18b281
MD
1197 goto end;
1198 }
6e1bc0df
MD
1199 if (!text->start_line) {
1200 fputs(", ", text->out);
1201 }
1202 text->start_line = false;
6a18b281 1203 if (text->options.print_scope_field_names) {
6e1bc0df 1204 fputs("event.fields = ", text->out);
6a18b281
MD
1205 }
1206 ret = print_field(text, main_field,
1207 text->options.print_payload_field_names);
1208end:
1209 bt_put(main_field);
af9a82eb
JG
1210 return ret;
1211}
1212
1213BT_HIDDEN
1214enum bt_component_status text_print_event(struct text_component *text,
1215 struct bt_ctf_event *event)
1216{
1217 enum bt_component_status ret;
1218
6e1bc0df 1219 text->start_line = true;
af9a82eb
JG
1220 ret = print_event_header(text, event);
1221 if (ret != BT_COMPONENT_STATUS_OK) {
1222 goto end;
1223 }
6a18b281
MD
1224
1225 ret = print_stream_packet_context(text, event);
1226 if (ret != BT_COMPONENT_STATUS_OK) {
1227 goto end;
1228 }
6a18b281
MD
1229
1230 ret = print_event_header_raw(text, event);
1231 if (ret != BT_COMPONENT_STATUS_OK) {
1232 goto end;
1233 }
6a18b281
MD
1234
1235 ret = print_stream_event_context(text, event);
1236 if (ret != BT_COMPONENT_STATUS_OK) {
1237 goto end;
1238 }
6a18b281
MD
1239
1240 ret = print_event_context(text, event);
1241 if (ret != BT_COMPONENT_STATUS_OK) {
1242 goto end;
1243 }
6a18b281
MD
1244
1245 ret = print_event_payload(text, event);
1246 if (ret != BT_COMPONENT_STATUS_OK) {
1247 goto end;
1248 }
af9a82eb
JG
1249
1250 fputc('\n', text->out);
1251end:
1252 return ret;
1253}
This page took 0.073993 seconds and 4 git commands to generate.