Commit | Line | Data |
---|---|---|
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> | |
7 | * | |
8 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
9 | * | |
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
11 | * of this software and associated documentation files (the "Software"), to deal | |
12 | * in the Software without restriction, including without limitation the rights | |
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
14 | * copies of the Software, and to permit persons to whom the Software is | |
15 | * furnished to do so, subject to the following conditions: | |
16 | * | |
17 | * The above copyright notice and this permission notice shall be included in | |
18 | * all copies or substantial portions of the Software. | |
19 | * | |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
26 | * SOFTWARE. | |
27 | */ | |
28 | ||
29 | #include <babeltrace/ctf-ir/event.h> | |
30 | #include <babeltrace/ctf-ir/event-class.h> | |
6a18b281 | 31 | #include <babeltrace/ctf-ir/packet.h> |
af9a82eb JG |
32 | #include <babeltrace/ctf-ir/stream.h> |
33 | #include <babeltrace/ctf-ir/stream-class.h> | |
34 | #include <babeltrace/ctf-ir/clock.h> | |
6a18b281 MD |
35 | #include <babeltrace/ctf-ir/field-types.h> |
36 | #include <babeltrace/ctf-ir/fields.h> | |
37 | #include <babeltrace/bitfield.h> | |
38 | #include <inttypes.h> | |
af9a82eb JG |
39 | #include "text.h" |
40 | ||
6a18b281 MD |
41 | static inline |
42 | const char *rem_(const char *str) | |
43 | { | |
44 | if (str[0] == '_') | |
45 | return &str[1]; | |
46 | else | |
47 | return str; | |
48 | } | |
49 | ||
af9a82eb JG |
50 | struct timestamp { |
51 | int64_t real_timestamp; /* Relative to UNIX epoch. */ | |
52 | uint64_t clock_value; /* In cycles. */ | |
53 | }; | |
54 | ||
6a18b281 MD |
55 | static |
56 | enum bt_component_status print_field(struct text_component *text, | |
57 | struct bt_ctf_field *field, bool print_names); | |
58 | ||
af9a82eb JG |
59 | static |
60 | void print_timestamp_cycles(struct text_component *text, | |
61 | struct bt_ctf_clock *clock, | |
62 | struct bt_ctf_event *event) | |
63 | { | |
64 | fputs("00000000000000000000", text->out); | |
65 | } | |
66 | ||
67 | static | |
68 | void print_timestamp_wall(struct text_component *text, | |
69 | struct bt_ctf_clock *clock, | |
70 | struct bt_ctf_event *event) | |
71 | { | |
72 | fputs("??:??:??.?????????", text->out); | |
73 | } | |
74 | ||
75 | static | |
76 | enum bt_component_status get_event_timestamp(struct bt_ctf_event *event) | |
77 | { | |
78 | /* int ret; | |
79 | uint64_t value, frequency; | |
80 | int64_t offset_s, offset; | |
81 | */ | |
82 | return BT_COMPONENT_STATUS_OK; | |
83 | } | |
84 | ||
85 | static | |
86 | enum bt_component_status print_event_timestamp(struct text_component *text, | |
87 | struct bt_ctf_event *event) | |
88 | { | |
89 | bool print_names = text->options.print_header_field_names; | |
90 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
6a18b281 | 91 | struct bt_ctf_stream *stream = NULL; |
af9a82eb JG |
92 | struct bt_ctf_clock *clock = NULL; |
93 | FILE *out = text->out; | |
94 | FILE *err = text->err; | |
95 | uint64_t real_timestamp; | |
96 | ||
97 | stream = bt_ctf_event_get_stream(event); | |
98 | if (!stream) { | |
99 | ret = BT_COMPONENT_STATUS_ERROR; | |
100 | goto end; | |
101 | } | |
102 | ||
103 | clock = bt_ctf_event_get_clock(event); | |
104 | if (!clock) { | |
105 | /* Stream has no timestamp. */ | |
106 | //puts("no_timestamp!"); | |
107 | //goto end; | |
108 | } | |
109 | ||
110 | fputs(print_names ? "timestamp = " : "[", out); | |
111 | if (text->options.print_timestamp_cycles) { | |
112 | print_timestamp_cycles(text, clock, event); | |
113 | } else { | |
114 | print_timestamp_wall(text, clock, event); | |
115 | } | |
116 | ||
117 | fputs(print_names ? ", " : "] ", out); | |
118 | if (!text->options.print_delta_field) { | |
119 | goto end; | |
120 | } | |
121 | end: | |
122 | bt_put(stream); | |
123 | bt_put(clock); | |
124 | return ret; | |
125 | } | |
126 | ||
6a18b281 | 127 | static |
af9a82eb JG |
128 | enum bt_component_status print_event_header(struct text_component *text, |
129 | struct bt_ctf_event *event) | |
130 | { | |
6a18b281 MD |
131 | bool print_names = text->options.print_header_field_names; |
132 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
133 | struct bt_ctf_event_class *event_class = NULL; | |
af9a82eb | 134 | |
6a18b281 MD |
135 | event_class = bt_ctf_event_get_class(event); |
136 | if (!event_class) { | |
137 | ret = BT_COMPONENT_STATUS_ERROR; | |
138 | goto end; | |
139 | } | |
6e1bc0df MD |
140 | if (!text->start_line) { |
141 | fputs(", ", text->out); | |
142 | } | |
143 | text->start_line = false; | |
af9a82eb JG |
144 | ret = print_event_timestamp(text, event); |
145 | if (ret != BT_COMPONENT_STATUS_OK) { | |
146 | goto end; | |
147 | } | |
6a18b281 MD |
148 | if (print_names) { |
149 | fputs("name = ", text->out); | |
150 | } | |
af9a82eb JG |
151 | fputs(bt_ctf_event_class_get_name(event_class), text->out); |
152 | end: | |
6a18b281 MD |
153 | bt_put(event_class); |
154 | return ret; | |
155 | } | |
156 | ||
157 | static | |
158 | enum bt_component_status print_integer(struct text_component *text, | |
159 | struct bt_ctf_field *field) | |
160 | { | |
161 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
162 | struct bt_ctf_field_type *field_type = NULL; | |
163 | enum bt_ctf_integer_base base; | |
164 | enum bt_ctf_string_encoding encoding; | |
165 | int signedness; | |
166 | union { | |
167 | uint64_t u; | |
168 | int64_t s; | |
169 | } v; | |
170 | ||
171 | field_type = bt_ctf_field_get_type(field); | |
172 | if (!field_type) { | |
173 | ret = BT_COMPONENT_STATUS_ERROR; | |
174 | goto end; | |
175 | } | |
176 | signedness = bt_ctf_field_type_integer_get_signed(field_type); | |
177 | if (signedness < 0) { | |
178 | ret = BT_COMPONENT_STATUS_ERROR; | |
179 | goto end; | |
180 | } | |
181 | if (!signedness) { | |
182 | if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) { | |
183 | ret = BT_COMPONENT_STATUS_ERROR; | |
184 | goto end; | |
185 | } | |
186 | } else { | |
187 | if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) { | |
188 | ret = BT_COMPONENT_STATUS_ERROR; | |
189 | goto end; | |
190 | } | |
191 | } | |
192 | ||
193 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
194 | switch (encoding) { | |
195 | case BT_CTF_STRING_ENCODING_UTF8: | |
196 | case BT_CTF_STRING_ENCODING_ASCII: | |
197 | g_string_append_c(text->string, (int) v.u); | |
198 | goto end; | |
199 | case BT_CTF_STRING_ENCODING_NONE: | |
200 | case BT_CTF_STRING_ENCODING_UNKNOWN: | |
201 | break; | |
202 | default: | |
203 | ret = BT_COMPONENT_STATUS_ERROR; | |
204 | goto end; | |
205 | } | |
206 | ||
207 | base = bt_ctf_field_type_integer_get_base(field_type); | |
208 | switch (base) { | |
209 | case BT_CTF_INTEGER_BASE_BINARY: | |
210 | { | |
211 | int bitnr, len; | |
212 | ||
213 | len = bt_ctf_field_type_integer_get_size(field_type); | |
214 | if (len < 0) { | |
215 | ret = BT_COMPONENT_STATUS_ERROR; | |
216 | goto end; | |
217 | } | |
218 | fprintf(text->out, "0b"); | |
219 | v.u = _bt_piecewise_lshift(v.u, 64 - len); | |
220 | for (bitnr = 0; bitnr < len; bitnr++) { | |
221 | fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); | |
222 | v.u = _bt_piecewise_lshift(v.u, 1); | |
223 | } | |
224 | break; | |
225 | } | |
226 | case BT_CTF_INTEGER_BASE_OCTAL: | |
227 | { | |
228 | if (signedness) { | |
229 | int len; | |
230 | ||
231 | len = bt_ctf_field_type_integer_get_size(field_type); | |
232 | if (len < 0) { | |
233 | ret = BT_COMPONENT_STATUS_ERROR; | |
234 | goto end; | |
235 | } | |
236 | if (len < 64) { | |
237 | size_t rounded_len; | |
238 | ||
239 | assert(len != 0); | |
240 | /* Round length to the nearest 3-bit */ | |
241 | rounded_len = (((len - 1) / 3) + 1) * 3; | |
242 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
243 | } | |
244 | } | |
245 | ||
246 | fprintf(text->out, "0%" PRIo64, v.u); | |
247 | break; | |
248 | } | |
249 | case BT_CTF_INTEGER_BASE_DECIMAL: | |
250 | if (!signedness) { | |
251 | fprintf(text->out, "%" PRIu64, v.u); | |
252 | } else { | |
253 | fprintf(text->out, "%" PRId64, v.s); | |
254 | } | |
255 | break; | |
256 | case BT_CTF_INTEGER_BASE_HEXADECIMAL: | |
257 | { | |
258 | int len; | |
259 | ||
260 | len = bt_ctf_field_type_integer_get_size(field_type); | |
261 | if (len < 0) { | |
262 | ret = BT_COMPONENT_STATUS_ERROR; | |
263 | goto end; | |
264 | } | |
265 | if (len < 64) { | |
266 | /* Round length to the nearest nibble */ | |
267 | uint8_t rounded_len = ((len + 3) & ~0x3); | |
268 | ||
269 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
270 | } | |
271 | ||
272 | fprintf(text->out, "0x%" PRIX64, v.u); | |
273 | break; | |
274 | } | |
275 | default: | |
276 | ret = BT_COMPONENT_STATUS_ERROR; | |
277 | goto end; | |
278 | } | |
279 | end: | |
280 | bt_put(field_type); | |
281 | return ret; | |
282 | } | |
283 | ||
284 | static | |
285 | enum bt_component_status print_enum(struct text_component *text, | |
286 | struct bt_ctf_field *field) | |
287 | { | |
288 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
289 | struct bt_ctf_field *container_field = NULL; | |
290 | const char *mapping_name; | |
291 | ||
292 | container_field = bt_ctf_field_enumeration_get_container(field); | |
293 | if (!container_field) { | |
294 | ret = BT_COMPONENT_STATUS_ERROR; | |
295 | goto end; | |
296 | } | |
297 | mapping_name = bt_ctf_field_enumeration_get_mapping_name(field); | |
298 | if (mapping_name) { | |
299 | fprintf(text->out, "( \"%s\"", mapping_name); | |
300 | } else { | |
301 | fprintf(text->out, "( <unknown>"); | |
302 | } | |
303 | fprintf(text->out, " : container = "); | |
304 | ret = print_integer(text, container_field); | |
305 | if (ret != BT_COMPONENT_STATUS_OK) { | |
306 | goto end; | |
307 | } | |
308 | fprintf(text->out, " )"); | |
309 | end: | |
310 | bt_put(container_field); | |
311 | return ret; | |
312 | } | |
313 | ||
314 | static | |
315 | enum bt_component_status print_struct_field(struct text_component *text, | |
316 | struct bt_ctf_field *_struct, | |
317 | struct bt_ctf_field_type *struct_type, | |
318 | int i, bool print_names) | |
319 | { | |
320 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
321 | const char *field_name; | |
322 | struct bt_ctf_field *field = NULL; | |
323 | struct bt_ctf_field_type *field_type = NULL;; | |
324 | ||
325 | field = bt_ctf_field_structure_get_field_by_index(_struct, i); | |
326 | if (!field) { | |
327 | ret = BT_COMPONENT_STATUS_ERROR; | |
328 | goto end; | |
329 | } | |
330 | if (bt_ctf_field_type_structure_get_field(struct_type, | |
331 | &field_name, &field_type, i) < 0) { | |
332 | ret = BT_COMPONENT_STATUS_ERROR; | |
333 | goto end; | |
334 | } | |
335 | ||
336 | if (i != 0) { | |
337 | fprintf(text->out, ", "); | |
338 | } else { | |
339 | fprintf(text->out, " "); | |
340 | } | |
341 | if (print_names) { | |
342 | fprintf(text->out, "%s = ", rem_(field_name)); | |
343 | } | |
344 | ret = print_field(text, field, print_names); | |
345 | end: | |
346 | bt_put(field_type); | |
347 | bt_put(field); | |
348 | return ret; | |
349 | } | |
350 | ||
351 | static | |
352 | enum bt_component_status print_struct(struct text_component *text, | |
353 | struct bt_ctf_field *_struct, bool print_names) | |
354 | { | |
355 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
356 | struct bt_ctf_field_type *struct_type = NULL; | |
357 | int nr_fields, i; | |
358 | ||
359 | struct_type = bt_ctf_field_get_type(_struct); | |
360 | if (!struct_type) { | |
361 | ret = BT_COMPONENT_STATUS_ERROR; | |
362 | goto end; | |
363 | } | |
364 | nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); | |
365 | if (nr_fields < 0) { | |
366 | ret = BT_COMPONENT_STATUS_ERROR; | |
367 | goto end; | |
368 | } | |
369 | fprintf(text->out, "{"); | |
370 | text->depth++; | |
371 | for (i = 0; i < nr_fields; i++) { | |
372 | ret = print_struct_field(text, _struct, struct_type, i, | |
373 | print_names); | |
374 | if (ret != BT_COMPONENT_STATUS_OK) { | |
375 | goto end; | |
376 | } | |
377 | } | |
378 | text->depth--; | |
379 | fprintf(text->out, " }"); | |
380 | end: | |
381 | bt_put(struct_type); | |
382 | return ret; | |
383 | } | |
384 | ||
385 | static | |
386 | enum bt_component_status print_array_field(struct text_component *text, | |
387 | struct bt_ctf_field *array, uint64_t i, | |
388 | bool is_string, bool print_names) | |
389 | { | |
390 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
391 | struct bt_ctf_field *field = NULL; | |
392 | ||
393 | if (!is_string) { | |
394 | if (i != 0) { | |
395 | fprintf(text->out, ", "); | |
396 | } else { | |
397 | fprintf(text->out, " "); | |
398 | } | |
399 | } | |
400 | field = bt_ctf_field_array_get_field(array, i); | |
401 | if (!field) { | |
402 | ret = BT_COMPONENT_STATUS_ERROR; | |
403 | goto end; | |
404 | } | |
405 | ret = print_field(text, field, print_names); | |
406 | end: | |
407 | bt_put(field); | |
408 | return ret; | |
409 | } | |
410 | ||
411 | static | |
412 | enum bt_component_status print_array(struct text_component *text, | |
413 | struct bt_ctf_field *array, bool print_names) | |
414 | { | |
415 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
416 | struct bt_ctf_field_type *array_type = NULL, *field_type = NULL; | |
417 | enum bt_ctf_type_id type_id; | |
418 | int64_t len; | |
419 | uint64_t i; | |
420 | bool is_string = false; | |
421 | ||
422 | array_type = bt_ctf_field_get_type(array); | |
423 | if (!array_type) { | |
424 | ret = BT_COMPONENT_STATUS_ERROR; | |
425 | goto end; | |
426 | } | |
427 | field_type = bt_ctf_field_type_array_get_element_type(array_type); | |
428 | if (!field_type) { | |
429 | ret = BT_COMPONENT_STATUS_ERROR; | |
430 | goto end; | |
431 | } | |
432 | len = bt_ctf_field_type_array_get_length(array_type); | |
433 | if (len < 0) { | |
434 | ret = BT_COMPONENT_STATUS_ERROR; | |
435 | goto end; | |
436 | } | |
437 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
438 | if (type_id == BT_CTF_TYPE_ID_INTEGER) { | |
439 | enum bt_ctf_string_encoding encoding; | |
440 | ||
441 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
442 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
443 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
444 | int integer_len, integer_alignment; | |
445 | ||
446 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
447 | if (integer_len < 0) { | |
448 | return BT_COMPONENT_STATUS_ERROR; | |
449 | } | |
450 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
451 | if (integer_alignment < 0) { | |
452 | return BT_COMPONENT_STATUS_ERROR; | |
453 | } | |
454 | if (integer_len == CHAR_BIT | |
455 | && integer_alignment == CHAR_BIT) { | |
456 | is_string = true; | |
457 | } | |
458 | } | |
459 | } | |
460 | ||
461 | if (is_string) { | |
462 | g_string_assign(text->string, ""); | |
463 | } else { | |
464 | fprintf(text->out, "["); | |
465 | } | |
466 | ||
467 | text->depth++; | |
468 | for (i = 0; i < len; i++) { | |
469 | ret = print_array_field(text, array, i, is_string, print_names); | |
470 | if (ret != BT_COMPONENT_STATUS_OK) { | |
471 | goto end; | |
472 | } | |
473 | } | |
474 | text->depth--; | |
475 | ||
476 | if (is_string) { | |
477 | fprintf(text->out, "\"%s\"", text->string->str); | |
478 | } else { | |
479 | fprintf(text->out, " ]"); | |
480 | } | |
481 | end: | |
482 | bt_put(field_type); | |
483 | bt_put(array_type); | |
484 | return ret; | |
485 | } | |
486 | ||
487 | static | |
488 | enum bt_component_status print_sequence_field(struct text_component *text, | |
489 | struct bt_ctf_field *seq, uint64_t i, | |
490 | bool is_string, bool print_names) | |
491 | { | |
492 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
493 | struct bt_ctf_field *field = NULL; | |
494 | ||
495 | if (!is_string) { | |
496 | if (i != 0) { | |
497 | fprintf(text->out, ", "); | |
498 | } else { | |
499 | fprintf(text->out, " "); | |
500 | } | |
501 | } | |
502 | field = bt_ctf_field_sequence_get_field(seq, i); | |
503 | if (!field) { | |
504 | ret = BT_COMPONENT_STATUS_ERROR; | |
505 | goto end; | |
506 | } | |
507 | ret = print_field(text, field, print_names); | |
508 | end: | |
509 | bt_put(field); | |
510 | return ret; | |
511 | } | |
512 | ||
513 | static | |
514 | enum bt_component_status print_sequence(struct text_component *text, | |
515 | struct bt_ctf_field *seq, bool print_names) | |
516 | { | |
517 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
518 | struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL; | |
519 | struct bt_ctf_field *length_field = NULL; | |
520 | enum bt_ctf_type_id type_id; | |
521 | uint64_t len; | |
522 | uint64_t i; | |
523 | bool is_string = false; | |
524 | ||
525 | seq_type = bt_ctf_field_get_type(seq); | |
526 | if (!seq_type) { | |
527 | ret = BT_COMPONENT_STATUS_ERROR; | |
528 | goto end; | |
529 | } | |
530 | length_field = bt_ctf_field_sequence_get_length(seq); | |
531 | if (!length_field) { | |
532 | ret = BT_COMPONENT_STATUS_ERROR; | |
533 | goto end; | |
534 | } | |
535 | if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) { | |
536 | ret = BT_COMPONENT_STATUS_ERROR; | |
537 | goto end; | |
538 | } | |
539 | field_type = bt_ctf_field_type_sequence_get_element_type(seq_type); | |
540 | if (!field_type) { | |
541 | ret = BT_COMPONENT_STATUS_ERROR; | |
542 | goto end; | |
543 | } | |
544 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
545 | if (type_id == BT_CTF_TYPE_ID_INTEGER) { | |
546 | enum bt_ctf_string_encoding encoding; | |
547 | ||
548 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
549 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
550 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
551 | int integer_len, integer_alignment; | |
552 | ||
553 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
554 | if (integer_len < 0) { | |
555 | ret = BT_COMPONENT_STATUS_ERROR; | |
556 | goto end; | |
557 | } | |
558 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
559 | if (integer_alignment < 0) { | |
560 | ret = BT_COMPONENT_STATUS_ERROR; | |
561 | goto end; | |
562 | } | |
563 | if (integer_len == CHAR_BIT | |
564 | && integer_alignment == CHAR_BIT) { | |
565 | is_string = true; | |
566 | } | |
567 | } | |
568 | } | |
569 | ||
570 | if (is_string) { | |
571 | g_string_assign(text->string, ""); | |
572 | } else { | |
573 | fprintf(text->out, "["); | |
574 | } | |
575 | ||
576 | text->depth++; | |
577 | for (i = 0; i < len; i++) { | |
578 | ret = print_sequence_field(text, seq, i, | |
579 | is_string, print_names); | |
580 | if (ret != BT_COMPONENT_STATUS_OK) { | |
581 | goto end; | |
582 | } | |
583 | } | |
584 | text->depth--; | |
585 | ||
586 | if (is_string) { | |
587 | fprintf(text->out, "\"%s\"", text->string->str); | |
588 | } else { | |
589 | fprintf(text->out, " ]"); | |
590 | } | |
591 | end: | |
592 | bt_put(length_field); | |
593 | bt_put(field_type); | |
594 | bt_put(seq_type); | |
595 | return ret; | |
596 | } | |
597 | ||
598 | static | |
599 | enum bt_component_status print_variant(struct text_component *text, | |
600 | struct bt_ctf_field *variant, bool print_names) | |
601 | { | |
602 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
603 | struct bt_ctf_field *field = NULL; | |
604 | ||
605 | field = bt_ctf_field_variant_get_current_field(variant); | |
606 | if (!field) { | |
607 | ret = BT_COMPONENT_STATUS_ERROR; | |
608 | goto end; | |
609 | } | |
610 | fprintf(text->out, "{ "); | |
611 | text->depth++; | |
612 | if (print_names) { | |
613 | struct bt_ctf_field *tag_field = NULL; | |
614 | const char *tag_choice; | |
615 | ||
616 | tag_field = bt_ctf_field_variant_get_tag(variant); | |
617 | if (!tag_field) { | |
618 | ret = BT_COMPONENT_STATUS_ERROR; | |
619 | goto end; | |
620 | } | |
621 | tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field); | |
622 | if (!tag_choice) { | |
623 | bt_put(tag_field); | |
624 | ret = BT_COMPONENT_STATUS_ERROR; | |
625 | goto end; | |
626 | } | |
627 | fprintf(text->out, "%s = ", rem_(tag_choice)); | |
628 | bt_put(tag_field); | |
629 | } | |
630 | ret = print_field(text, field, print_names); | |
631 | if (ret != BT_COMPONENT_STATUS_OK) { | |
632 | goto end; | |
633 | } | |
634 | text->depth--; | |
635 | fprintf(text->out, " }"); | |
636 | end: | |
637 | bt_put(field); | |
638 | return ret; | |
639 | } | |
640 | ||
641 | static | |
642 | enum bt_component_status print_field(struct text_component *text, | |
643 | struct bt_ctf_field *field, bool print_names) | |
644 | { | |
645 | enum bt_ctf_type_id type_id; | |
646 | ||
647 | type_id = bt_ctf_field_get_type_id(field); | |
648 | switch (type_id) { | |
649 | case CTF_TYPE_INTEGER: | |
650 | return print_integer(text, field); | |
651 | case CTF_TYPE_FLOAT: | |
652 | { | |
653 | double v; | |
654 | ||
655 | if (bt_ctf_field_floating_point_get_value(field, &v)) { | |
656 | return BT_COMPONENT_STATUS_ERROR; | |
657 | } | |
658 | fprintf(text->out, "%g", v); | |
659 | return BT_COMPONENT_STATUS_OK; | |
660 | } | |
661 | case CTF_TYPE_ENUM: | |
662 | return print_enum(text, field); | |
663 | case CTF_TYPE_STRING: | |
664 | fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field)); | |
665 | return BT_COMPONENT_STATUS_OK; | |
666 | case CTF_TYPE_STRUCT: | |
667 | return print_struct(text, field, print_names); | |
668 | case CTF_TYPE_UNTAGGED_VARIANT: | |
669 | case CTF_TYPE_VARIANT: | |
670 | return print_variant(text, field, print_names); | |
671 | case CTF_TYPE_ARRAY: | |
672 | return print_array(text, field, print_names); | |
673 | case CTF_TYPE_SEQUENCE: | |
674 | return print_sequence(text, field, print_names); | |
675 | default: | |
676 | fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id); | |
677 | return BT_COMPONENT_STATUS_ERROR; | |
678 | } | |
679 | } | |
680 | ||
681 | static | |
682 | enum bt_component_status print_stream_packet_context(struct text_component *text, | |
683 | struct bt_ctf_event *event) | |
684 | { | |
685 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
686 | struct bt_ctf_packet *packet = NULL; | |
687 | struct bt_ctf_field *main_field = NULL; | |
688 | ||
689 | packet = bt_ctf_event_get_packet(event); | |
690 | if (!packet) { | |
691 | ret = BT_COMPONENT_STATUS_ERROR; | |
692 | goto end; | |
693 | } | |
694 | main_field = bt_ctf_packet_get_context(packet); | |
695 | if (!main_field) { | |
696 | ret = BT_COMPONENT_STATUS_ERROR; | |
697 | goto end; | |
698 | } | |
6e1bc0df MD |
699 | if (!text->start_line) { |
700 | fputs(", ", text->out); | |
701 | } | |
702 | text->start_line = false; | |
6a18b281 | 703 | if (text->options.print_scope_field_names) { |
6e1bc0df | 704 | fputs("stream.packet.context = ", text->out); |
6a18b281 MD |
705 | } |
706 | ret = print_field(text, main_field, | |
707 | text->options.print_context_field_names); | |
708 | end: | |
709 | bt_put(main_field); | |
710 | bt_put(packet); | |
711 | return ret; | |
712 | } | |
713 | ||
714 | static | |
715 | enum bt_component_status print_event_header_raw(struct text_component *text, | |
716 | struct bt_ctf_event *event) | |
717 | { | |
718 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
719 | struct bt_ctf_field *main_field = NULL; | |
720 | ||
721 | main_field = bt_ctf_event_get_header(event); | |
722 | if (!main_field) { | |
723 | ret = BT_COMPONENT_STATUS_ERROR; | |
724 | goto end; | |
725 | } | |
6e1bc0df MD |
726 | if (!text->start_line) { |
727 | fputs(", ", text->out); | |
728 | } | |
729 | text->start_line = false; | |
6a18b281 | 730 | if (text->options.print_scope_field_names) { |
6e1bc0df | 731 | fputs("stream.event.header = ", text->out); |
6a18b281 MD |
732 | } |
733 | ret = print_field(text, main_field, | |
6e1bc0df | 734 | text->options.print_header_field_names); |
6a18b281 MD |
735 | end: |
736 | bt_put(main_field); | |
737 | return ret; | |
738 | } | |
739 | ||
740 | static | |
741 | enum bt_component_status print_stream_event_context(struct text_component *text, | |
742 | struct bt_ctf_event *event) | |
743 | { | |
744 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
745 | struct bt_ctf_field *main_field = NULL; | |
746 | ||
747 | main_field = bt_ctf_event_get_stream_event_context(event); | |
748 | if (!main_field) { | |
749 | ret = BT_COMPONENT_STATUS_ERROR; | |
750 | goto end; | |
751 | } | |
6e1bc0df MD |
752 | if (!text->start_line) { |
753 | fputs(", ", text->out); | |
754 | } | |
755 | text->start_line = false; | |
6a18b281 | 756 | if (text->options.print_scope_field_names) { |
6e1bc0df | 757 | fputs("stream.event.context = ", text->out); |
6a18b281 MD |
758 | } |
759 | ret = print_field(text, main_field, | |
760 | text->options.print_context_field_names); | |
761 | end: | |
762 | bt_put(main_field); | |
763 | return ret; | |
764 | } | |
765 | ||
766 | static | |
767 | enum bt_component_status print_event_context(struct text_component *text, | |
768 | struct bt_ctf_event *event) | |
769 | { | |
770 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
771 | struct bt_ctf_field *main_field = NULL; | |
772 | ||
773 | main_field = bt_ctf_event_get_event_context(event); | |
774 | if (!main_field) { | |
775 | ret = BT_COMPONENT_STATUS_ERROR; | |
776 | goto end; | |
777 | } | |
6e1bc0df MD |
778 | if (!text->start_line) { |
779 | fputs(", ", text->out); | |
780 | } | |
781 | text->start_line = false; | |
6a18b281 | 782 | if (text->options.print_scope_field_names) { |
6e1bc0df | 783 | fputs("event.context = ", text->out); |
6a18b281 MD |
784 | } |
785 | ret = print_field(text, main_field, | |
786 | text->options.print_context_field_names); | |
787 | end: | |
788 | bt_put(main_field); | |
789 | return ret; | |
790 | } | |
791 | ||
792 | static | |
793 | enum bt_component_status print_event_payload(struct text_component *text, | |
794 | struct bt_ctf_event *event) | |
795 | { | |
796 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
797 | struct bt_ctf_field *main_field = NULL; | |
798 | ||
799 | main_field = bt_ctf_event_get_payload_field(event); | |
800 | if (!main_field) { | |
801 | ret = BT_COMPONENT_STATUS_ERROR; | |
802 | goto end; | |
803 | } | |
6e1bc0df MD |
804 | if (!text->start_line) { |
805 | fputs(", ", text->out); | |
806 | } | |
807 | text->start_line = false; | |
6a18b281 | 808 | if (text->options.print_scope_field_names) { |
6e1bc0df | 809 | fputs("event.fields = ", text->out); |
6a18b281 MD |
810 | } |
811 | ret = print_field(text, main_field, | |
812 | text->options.print_payload_field_names); | |
813 | end: | |
814 | bt_put(main_field); | |
af9a82eb JG |
815 | return ret; |
816 | } | |
817 | ||
818 | BT_HIDDEN | |
819 | enum bt_component_status text_print_event(struct text_component *text, | |
820 | struct bt_ctf_event *event) | |
821 | { | |
822 | enum bt_component_status ret; | |
823 | ||
6e1bc0df | 824 | text->start_line = true; |
af9a82eb JG |
825 | ret = print_event_header(text, event); |
826 | if (ret != BT_COMPONENT_STATUS_OK) { | |
827 | goto end; | |
828 | } | |
6a18b281 MD |
829 | |
830 | ret = print_stream_packet_context(text, event); | |
831 | if (ret != BT_COMPONENT_STATUS_OK) { | |
832 | goto end; | |
833 | } | |
6a18b281 MD |
834 | |
835 | ret = print_event_header_raw(text, event); | |
836 | if (ret != BT_COMPONENT_STATUS_OK) { | |
837 | goto end; | |
838 | } | |
6a18b281 MD |
839 | |
840 | ret = print_stream_event_context(text, event); | |
841 | if (ret != BT_COMPONENT_STATUS_OK) { | |
842 | goto end; | |
843 | } | |
6a18b281 MD |
844 | |
845 | ret = print_event_context(text, event); | |
846 | if (ret != BT_COMPONENT_STATUS_OK) { | |
847 | goto end; | |
848 | } | |
6a18b281 MD |
849 | |
850 | ret = print_event_payload(text, event); | |
851 | if (ret != BT_COMPONENT_STATUS_OK) { | |
852 | goto end; | |
853 | } | |
af9a82eb JG |
854 | |
855 | fputc('\n', text->out); | |
856 | end: | |
857 | return ret; | |
858 | } |