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 | } | |
af9a82eb JG |
140 | ret = print_event_timestamp(text, event); |
141 | if (ret != BT_COMPONENT_STATUS_OK) { | |
142 | goto end; | |
143 | } | |
6a18b281 MD |
144 | if (print_names) { |
145 | fputs("name = ", text->out); | |
146 | } | |
af9a82eb | 147 | fputs(bt_ctf_event_class_get_name(event_class), text->out); |
f607e11e | 148 | bt_put(event_class); |
af9a82eb | 149 | end: |
6a18b281 MD |
150 | bt_put(event_class); |
151 | return ret; | |
152 | } | |
153 | ||
154 | static | |
155 | enum bt_component_status print_integer(struct text_component *text, | |
156 | struct bt_ctf_field *field) | |
157 | { | |
158 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
159 | struct bt_ctf_field_type *field_type = NULL; | |
160 | enum bt_ctf_integer_base base; | |
161 | enum bt_ctf_string_encoding encoding; | |
162 | int signedness; | |
163 | union { | |
164 | uint64_t u; | |
165 | int64_t s; | |
166 | } v; | |
167 | ||
168 | field_type = bt_ctf_field_get_type(field); | |
169 | if (!field_type) { | |
170 | ret = BT_COMPONENT_STATUS_ERROR; | |
171 | goto end; | |
172 | } | |
173 | signedness = bt_ctf_field_type_integer_get_signed(field_type); | |
174 | if (signedness < 0) { | |
175 | ret = BT_COMPONENT_STATUS_ERROR; | |
176 | goto end; | |
177 | } | |
178 | if (!signedness) { | |
179 | if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) { | |
180 | ret = BT_COMPONENT_STATUS_ERROR; | |
181 | goto end; | |
182 | } | |
183 | } else { | |
184 | if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) { | |
185 | ret = BT_COMPONENT_STATUS_ERROR; | |
186 | goto end; | |
187 | } | |
188 | } | |
189 | ||
190 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
191 | switch (encoding) { | |
192 | case BT_CTF_STRING_ENCODING_UTF8: | |
193 | case BT_CTF_STRING_ENCODING_ASCII: | |
194 | g_string_append_c(text->string, (int) v.u); | |
195 | goto end; | |
196 | case BT_CTF_STRING_ENCODING_NONE: | |
197 | case BT_CTF_STRING_ENCODING_UNKNOWN: | |
198 | break; | |
199 | default: | |
200 | ret = BT_COMPONENT_STATUS_ERROR; | |
201 | goto end; | |
202 | } | |
203 | ||
204 | base = bt_ctf_field_type_integer_get_base(field_type); | |
205 | switch (base) { | |
206 | case BT_CTF_INTEGER_BASE_BINARY: | |
207 | { | |
208 | int bitnr, len; | |
209 | ||
210 | len = bt_ctf_field_type_integer_get_size(field_type); | |
211 | if (len < 0) { | |
212 | ret = BT_COMPONENT_STATUS_ERROR; | |
213 | goto end; | |
214 | } | |
215 | fprintf(text->out, "0b"); | |
216 | v.u = _bt_piecewise_lshift(v.u, 64 - len); | |
217 | for (bitnr = 0; bitnr < len; bitnr++) { | |
218 | fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); | |
219 | v.u = _bt_piecewise_lshift(v.u, 1); | |
220 | } | |
221 | break; | |
222 | } | |
223 | case BT_CTF_INTEGER_BASE_OCTAL: | |
224 | { | |
225 | if (signedness) { | |
226 | int len; | |
227 | ||
228 | len = bt_ctf_field_type_integer_get_size(field_type); | |
229 | if (len < 0) { | |
230 | ret = BT_COMPONENT_STATUS_ERROR; | |
231 | goto end; | |
232 | } | |
233 | if (len < 64) { | |
234 | size_t rounded_len; | |
235 | ||
236 | assert(len != 0); | |
237 | /* Round length to the nearest 3-bit */ | |
238 | rounded_len = (((len - 1) / 3) + 1) * 3; | |
239 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
240 | } | |
241 | } | |
242 | ||
243 | fprintf(text->out, "0%" PRIo64, v.u); | |
244 | break; | |
245 | } | |
246 | case BT_CTF_INTEGER_BASE_DECIMAL: | |
247 | if (!signedness) { | |
248 | fprintf(text->out, "%" PRIu64, v.u); | |
249 | } else { | |
250 | fprintf(text->out, "%" PRId64, v.s); | |
251 | } | |
252 | break; | |
253 | case BT_CTF_INTEGER_BASE_HEXADECIMAL: | |
254 | { | |
255 | int len; | |
256 | ||
257 | len = bt_ctf_field_type_integer_get_size(field_type); | |
258 | if (len < 0) { | |
259 | ret = BT_COMPONENT_STATUS_ERROR; | |
260 | goto end; | |
261 | } | |
262 | if (len < 64) { | |
263 | /* Round length to the nearest nibble */ | |
264 | uint8_t rounded_len = ((len + 3) & ~0x3); | |
265 | ||
266 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
267 | } | |
268 | ||
269 | fprintf(text->out, "0x%" PRIX64, v.u); | |
270 | break; | |
271 | } | |
272 | default: | |
273 | ret = BT_COMPONENT_STATUS_ERROR; | |
274 | goto end; | |
275 | } | |
276 | end: | |
277 | bt_put(field_type); | |
278 | return ret; | |
279 | } | |
280 | ||
281 | static | |
282 | enum bt_component_status print_enum(struct text_component *text, | |
283 | struct bt_ctf_field *field) | |
284 | { | |
285 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
286 | struct bt_ctf_field *container_field = NULL; | |
287 | const char *mapping_name; | |
288 | ||
289 | container_field = bt_ctf_field_enumeration_get_container(field); | |
290 | if (!container_field) { | |
291 | ret = BT_COMPONENT_STATUS_ERROR; | |
292 | goto end; | |
293 | } | |
294 | mapping_name = bt_ctf_field_enumeration_get_mapping_name(field); | |
295 | if (mapping_name) { | |
296 | fprintf(text->out, "( \"%s\"", mapping_name); | |
297 | } else { | |
298 | fprintf(text->out, "( <unknown>"); | |
299 | } | |
300 | fprintf(text->out, " : container = "); | |
301 | ret = print_integer(text, container_field); | |
302 | if (ret != BT_COMPONENT_STATUS_OK) { | |
303 | goto end; | |
304 | } | |
305 | fprintf(text->out, " )"); | |
306 | end: | |
307 | bt_put(container_field); | |
308 | return ret; | |
309 | } | |
310 | ||
311 | static | |
312 | enum bt_component_status print_struct_field(struct text_component *text, | |
313 | struct bt_ctf_field *_struct, | |
314 | struct bt_ctf_field_type *struct_type, | |
315 | int i, bool print_names) | |
316 | { | |
317 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
318 | const char *field_name; | |
319 | struct bt_ctf_field *field = NULL; | |
320 | struct bt_ctf_field_type *field_type = NULL;; | |
321 | ||
322 | field = bt_ctf_field_structure_get_field_by_index(_struct, i); | |
323 | if (!field) { | |
324 | ret = BT_COMPONENT_STATUS_ERROR; | |
325 | goto end; | |
326 | } | |
327 | if (bt_ctf_field_type_structure_get_field(struct_type, | |
328 | &field_name, &field_type, i) < 0) { | |
329 | ret = BT_COMPONENT_STATUS_ERROR; | |
330 | goto end; | |
331 | } | |
332 | ||
333 | if (i != 0) { | |
334 | fprintf(text->out, ", "); | |
335 | } else { | |
336 | fprintf(text->out, " "); | |
337 | } | |
338 | if (print_names) { | |
339 | fprintf(text->out, "%s = ", rem_(field_name)); | |
340 | } | |
341 | ret = print_field(text, field, print_names); | |
342 | end: | |
343 | bt_put(field_type); | |
344 | bt_put(field); | |
345 | return ret; | |
346 | } | |
347 | ||
348 | static | |
349 | enum bt_component_status print_struct(struct text_component *text, | |
350 | struct bt_ctf_field *_struct, bool print_names) | |
351 | { | |
352 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
353 | struct bt_ctf_field_type *struct_type = NULL; | |
354 | int nr_fields, i; | |
355 | ||
356 | struct_type = bt_ctf_field_get_type(_struct); | |
357 | if (!struct_type) { | |
358 | ret = BT_COMPONENT_STATUS_ERROR; | |
359 | goto end; | |
360 | } | |
361 | nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); | |
362 | if (nr_fields < 0) { | |
363 | ret = BT_COMPONENT_STATUS_ERROR; | |
364 | goto end; | |
365 | } | |
366 | fprintf(text->out, "{"); | |
367 | text->depth++; | |
368 | for (i = 0; i < nr_fields; i++) { | |
369 | ret = print_struct_field(text, _struct, struct_type, i, | |
370 | print_names); | |
371 | if (ret != BT_COMPONENT_STATUS_OK) { | |
372 | goto end; | |
373 | } | |
374 | } | |
375 | text->depth--; | |
376 | fprintf(text->out, " }"); | |
377 | end: | |
378 | bt_put(struct_type); | |
379 | return ret; | |
380 | } | |
381 | ||
382 | static | |
383 | enum bt_component_status print_array_field(struct text_component *text, | |
384 | struct bt_ctf_field *array, uint64_t i, | |
385 | bool is_string, bool print_names) | |
386 | { | |
387 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
388 | struct bt_ctf_field *field = NULL; | |
389 | ||
390 | if (!is_string) { | |
391 | if (i != 0) { | |
392 | fprintf(text->out, ", "); | |
393 | } else { | |
394 | fprintf(text->out, " "); | |
395 | } | |
396 | } | |
397 | field = bt_ctf_field_array_get_field(array, i); | |
398 | if (!field) { | |
399 | ret = BT_COMPONENT_STATUS_ERROR; | |
400 | goto end; | |
401 | } | |
402 | ret = print_field(text, field, print_names); | |
403 | end: | |
404 | bt_put(field); | |
405 | return ret; | |
406 | } | |
407 | ||
408 | static | |
409 | enum bt_component_status print_array(struct text_component *text, | |
410 | struct bt_ctf_field *array, bool print_names) | |
411 | { | |
412 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
413 | struct bt_ctf_field_type *array_type = NULL, *field_type = NULL; | |
414 | enum bt_ctf_type_id type_id; | |
415 | int64_t len; | |
416 | uint64_t i; | |
417 | bool is_string = false; | |
418 | ||
419 | array_type = bt_ctf_field_get_type(array); | |
420 | if (!array_type) { | |
421 | ret = BT_COMPONENT_STATUS_ERROR; | |
422 | goto end; | |
423 | } | |
424 | field_type = bt_ctf_field_type_array_get_element_type(array_type); | |
425 | if (!field_type) { | |
426 | ret = BT_COMPONENT_STATUS_ERROR; | |
427 | goto end; | |
428 | } | |
429 | len = bt_ctf_field_type_array_get_length(array_type); | |
430 | if (len < 0) { | |
431 | ret = BT_COMPONENT_STATUS_ERROR; | |
432 | goto end; | |
433 | } | |
434 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
435 | if (type_id == BT_CTF_TYPE_ID_INTEGER) { | |
436 | enum bt_ctf_string_encoding encoding; | |
437 | ||
438 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
439 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
440 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
441 | int integer_len, integer_alignment; | |
442 | ||
443 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
444 | if (integer_len < 0) { | |
445 | return BT_COMPONENT_STATUS_ERROR; | |
446 | } | |
447 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
448 | if (integer_alignment < 0) { | |
449 | return BT_COMPONENT_STATUS_ERROR; | |
450 | } | |
451 | if (integer_len == CHAR_BIT | |
452 | && integer_alignment == CHAR_BIT) { | |
453 | is_string = true; | |
454 | } | |
455 | } | |
456 | } | |
457 | ||
458 | if (is_string) { | |
459 | g_string_assign(text->string, ""); | |
460 | } else { | |
461 | fprintf(text->out, "["); | |
462 | } | |
463 | ||
464 | text->depth++; | |
465 | for (i = 0; i < len; i++) { | |
466 | ret = print_array_field(text, array, i, is_string, print_names); | |
467 | if (ret != BT_COMPONENT_STATUS_OK) { | |
468 | goto end; | |
469 | } | |
470 | } | |
471 | text->depth--; | |
472 | ||
473 | if (is_string) { | |
474 | fprintf(text->out, "\"%s\"", text->string->str); | |
475 | } else { | |
476 | fprintf(text->out, " ]"); | |
477 | } | |
478 | end: | |
479 | bt_put(field_type); | |
480 | bt_put(array_type); | |
481 | return ret; | |
482 | } | |
483 | ||
484 | static | |
485 | enum bt_component_status print_sequence_field(struct text_component *text, | |
486 | struct bt_ctf_field *seq, uint64_t i, | |
487 | bool is_string, bool print_names) | |
488 | { | |
489 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
490 | struct bt_ctf_field *field = NULL; | |
491 | ||
492 | if (!is_string) { | |
493 | if (i != 0) { | |
494 | fprintf(text->out, ", "); | |
495 | } else { | |
496 | fprintf(text->out, " "); | |
497 | } | |
498 | } | |
499 | field = bt_ctf_field_sequence_get_field(seq, i); | |
500 | if (!field) { | |
501 | ret = BT_COMPONENT_STATUS_ERROR; | |
502 | goto end; | |
503 | } | |
504 | ret = print_field(text, field, print_names); | |
505 | end: | |
506 | bt_put(field); | |
507 | return ret; | |
508 | } | |
509 | ||
510 | static | |
511 | enum bt_component_status print_sequence(struct text_component *text, | |
512 | struct bt_ctf_field *seq, bool print_names) | |
513 | { | |
514 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
515 | struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL; | |
516 | struct bt_ctf_field *length_field = NULL; | |
517 | enum bt_ctf_type_id type_id; | |
518 | uint64_t len; | |
519 | uint64_t i; | |
520 | bool is_string = false; | |
521 | ||
522 | seq_type = bt_ctf_field_get_type(seq); | |
523 | if (!seq_type) { | |
524 | ret = BT_COMPONENT_STATUS_ERROR; | |
525 | goto end; | |
526 | } | |
527 | length_field = bt_ctf_field_sequence_get_length(seq); | |
528 | if (!length_field) { | |
529 | ret = BT_COMPONENT_STATUS_ERROR; | |
530 | goto end; | |
531 | } | |
532 | if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) { | |
533 | ret = BT_COMPONENT_STATUS_ERROR; | |
534 | goto end; | |
535 | } | |
536 | field_type = bt_ctf_field_type_sequence_get_element_type(seq_type); | |
537 | if (!field_type) { | |
538 | ret = BT_COMPONENT_STATUS_ERROR; | |
539 | goto end; | |
540 | } | |
541 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
542 | if (type_id == BT_CTF_TYPE_ID_INTEGER) { | |
543 | enum bt_ctf_string_encoding encoding; | |
544 | ||
545 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
546 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
547 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
548 | int integer_len, integer_alignment; | |
549 | ||
550 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
551 | if (integer_len < 0) { | |
552 | ret = BT_COMPONENT_STATUS_ERROR; | |
553 | goto end; | |
554 | } | |
555 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
556 | if (integer_alignment < 0) { | |
557 | ret = BT_COMPONENT_STATUS_ERROR; | |
558 | goto end; | |
559 | } | |
560 | if (integer_len == CHAR_BIT | |
561 | && integer_alignment == CHAR_BIT) { | |
562 | is_string = true; | |
563 | } | |
564 | } | |
565 | } | |
566 | ||
567 | if (is_string) { | |
568 | g_string_assign(text->string, ""); | |
569 | } else { | |
570 | fprintf(text->out, "["); | |
571 | } | |
572 | ||
573 | text->depth++; | |
574 | for (i = 0; i < len; i++) { | |
575 | ret = print_sequence_field(text, seq, i, | |
576 | is_string, print_names); | |
577 | if (ret != BT_COMPONENT_STATUS_OK) { | |
578 | goto end; | |
579 | } | |
580 | } | |
581 | text->depth--; | |
582 | ||
583 | if (is_string) { | |
584 | fprintf(text->out, "\"%s\"", text->string->str); | |
585 | } else { | |
586 | fprintf(text->out, " ]"); | |
587 | } | |
588 | end: | |
589 | bt_put(length_field); | |
590 | bt_put(field_type); | |
591 | bt_put(seq_type); | |
592 | return ret; | |
593 | } | |
594 | ||
595 | static | |
596 | enum bt_component_status print_variant(struct text_component *text, | |
597 | struct bt_ctf_field *variant, bool print_names) | |
598 | { | |
599 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
600 | struct bt_ctf_field *field = NULL; | |
601 | ||
602 | field = bt_ctf_field_variant_get_current_field(variant); | |
603 | if (!field) { | |
604 | ret = BT_COMPONENT_STATUS_ERROR; | |
605 | goto end; | |
606 | } | |
607 | fprintf(text->out, "{ "); | |
608 | text->depth++; | |
609 | if (print_names) { | |
610 | struct bt_ctf_field *tag_field = NULL; | |
611 | const char *tag_choice; | |
612 | ||
613 | tag_field = bt_ctf_field_variant_get_tag(variant); | |
614 | if (!tag_field) { | |
615 | ret = BT_COMPONENT_STATUS_ERROR; | |
616 | goto end; | |
617 | } | |
618 | tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field); | |
619 | if (!tag_choice) { | |
620 | bt_put(tag_field); | |
621 | ret = BT_COMPONENT_STATUS_ERROR; | |
622 | goto end; | |
623 | } | |
624 | fprintf(text->out, "%s = ", rem_(tag_choice)); | |
625 | bt_put(tag_field); | |
626 | } | |
627 | ret = print_field(text, field, print_names); | |
628 | if (ret != BT_COMPONENT_STATUS_OK) { | |
629 | goto end; | |
630 | } | |
631 | text->depth--; | |
632 | fprintf(text->out, " }"); | |
633 | end: | |
634 | bt_put(field); | |
635 | return ret; | |
636 | } | |
637 | ||
638 | static | |
639 | enum bt_component_status print_field(struct text_component *text, | |
640 | struct bt_ctf_field *field, bool print_names) | |
641 | { | |
642 | enum bt_ctf_type_id type_id; | |
643 | ||
644 | type_id = bt_ctf_field_get_type_id(field); | |
645 | switch (type_id) { | |
646 | case CTF_TYPE_INTEGER: | |
647 | return print_integer(text, field); | |
648 | case CTF_TYPE_FLOAT: | |
649 | { | |
650 | double v; | |
651 | ||
652 | if (bt_ctf_field_floating_point_get_value(field, &v)) { | |
653 | return BT_COMPONENT_STATUS_ERROR; | |
654 | } | |
655 | fprintf(text->out, "%g", v); | |
656 | return BT_COMPONENT_STATUS_OK; | |
657 | } | |
658 | case CTF_TYPE_ENUM: | |
659 | return print_enum(text, field); | |
660 | case CTF_TYPE_STRING: | |
661 | fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field)); | |
662 | return BT_COMPONENT_STATUS_OK; | |
663 | case CTF_TYPE_STRUCT: | |
664 | return print_struct(text, field, print_names); | |
665 | case CTF_TYPE_UNTAGGED_VARIANT: | |
666 | case CTF_TYPE_VARIANT: | |
667 | return print_variant(text, field, print_names); | |
668 | case CTF_TYPE_ARRAY: | |
669 | return print_array(text, field, print_names); | |
670 | case CTF_TYPE_SEQUENCE: | |
671 | return print_sequence(text, field, print_names); | |
672 | default: | |
673 | fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id); | |
674 | return BT_COMPONENT_STATUS_ERROR; | |
675 | } | |
676 | } | |
677 | ||
678 | static | |
679 | enum bt_component_status print_stream_packet_context(struct text_component *text, | |
680 | struct bt_ctf_event *event) | |
681 | { | |
682 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
683 | struct bt_ctf_packet *packet = NULL; | |
684 | struct bt_ctf_field *main_field = NULL; | |
685 | ||
686 | packet = bt_ctf_event_get_packet(event); | |
687 | if (!packet) { | |
688 | ret = BT_COMPONENT_STATUS_ERROR; | |
689 | goto end; | |
690 | } | |
691 | main_field = bt_ctf_packet_get_context(packet); | |
692 | if (!main_field) { | |
693 | ret = BT_COMPONENT_STATUS_ERROR; | |
694 | goto end; | |
695 | } | |
696 | if (text->options.print_scope_field_names) { | |
697 | fputs(" stream.packet.context = ", text->out); | |
698 | } | |
699 | ret = print_field(text, main_field, | |
700 | text->options.print_context_field_names); | |
701 | end: | |
702 | bt_put(main_field); | |
703 | bt_put(packet); | |
704 | return ret; | |
705 | } | |
706 | ||
707 | static | |
708 | enum bt_component_status print_event_header_raw(struct text_component *text, | |
709 | struct bt_ctf_event *event) | |
710 | { | |
711 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
712 | struct bt_ctf_field *main_field = NULL; | |
713 | ||
714 | main_field = bt_ctf_event_get_header(event); | |
715 | if (!main_field) { | |
716 | ret = BT_COMPONENT_STATUS_ERROR; | |
717 | goto end; | |
718 | } | |
719 | if (text->options.print_scope_field_names) { | |
720 | fputs(" stream.event.header = ", text->out); | |
721 | } | |
722 | ret = print_field(text, main_field, | |
723 | text->options.print_context_field_names); | |
724 | end: | |
725 | bt_put(main_field); | |
726 | return ret; | |
727 | } | |
728 | ||
729 | static | |
730 | enum bt_component_status print_stream_event_context(struct text_component *text, | |
731 | struct bt_ctf_event *event) | |
732 | { | |
733 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
734 | struct bt_ctf_field *main_field = NULL; | |
735 | ||
736 | main_field = bt_ctf_event_get_stream_event_context(event); | |
737 | if (!main_field) { | |
738 | ret = BT_COMPONENT_STATUS_ERROR; | |
739 | goto end; | |
740 | } | |
741 | if (text->options.print_scope_field_names) { | |
742 | fputs(" stream.event.context = ", text->out); | |
743 | } | |
744 | ret = print_field(text, main_field, | |
745 | text->options.print_context_field_names); | |
746 | end: | |
747 | bt_put(main_field); | |
748 | return ret; | |
749 | } | |
750 | ||
751 | static | |
752 | enum bt_component_status print_event_context(struct text_component *text, | |
753 | struct bt_ctf_event *event) | |
754 | { | |
755 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
756 | struct bt_ctf_field *main_field = NULL; | |
757 | ||
758 | main_field = bt_ctf_event_get_event_context(event); | |
759 | if (!main_field) { | |
760 | ret = BT_COMPONENT_STATUS_ERROR; | |
761 | goto end; | |
762 | } | |
763 | if (text->options.print_scope_field_names) { | |
764 | fputs(" event.context = ", text->out); | |
765 | } | |
766 | ret = print_field(text, main_field, | |
767 | text->options.print_context_field_names); | |
768 | end: | |
769 | bt_put(main_field); | |
770 | return ret; | |
771 | } | |
772 | ||
773 | static | |
774 | enum bt_component_status print_event_payload(struct text_component *text, | |
775 | struct bt_ctf_event *event) | |
776 | { | |
777 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
778 | struct bt_ctf_field *main_field = NULL; | |
779 | ||
780 | main_field = bt_ctf_event_get_payload_field(event); | |
781 | if (!main_field) { | |
782 | ret = BT_COMPONENT_STATUS_ERROR; | |
783 | goto end; | |
784 | } | |
785 | if (text->options.print_scope_field_names) { | |
786 | fputs(" event.fields = ", text->out); | |
787 | } | |
788 | ret = print_field(text, main_field, | |
789 | text->options.print_payload_field_names); | |
790 | end: | |
791 | bt_put(main_field); | |
af9a82eb JG |
792 | return ret; |
793 | } | |
794 | ||
795 | BT_HIDDEN | |
796 | enum bt_component_status text_print_event(struct text_component *text, | |
797 | struct bt_ctf_event *event) | |
798 | { | |
799 | enum bt_component_status ret; | |
800 | ||
6a18b281 MD |
801 | //TEST XXX |
802 | text->options.print_scope_field_names = true; | |
803 | text->options.print_payload_field_names = true; | |
804 | text->options.print_context_field_names = true; | |
805 | ||
af9a82eb JG |
806 | ret = print_event_header(text, event); |
807 | if (ret != BT_COMPONENT_STATUS_OK) { | |
808 | goto end; | |
809 | } | |
6a18b281 MD |
810 | fputs(",", text->out); |
811 | ||
812 | ret = print_stream_packet_context(text, event); | |
813 | if (ret != BT_COMPONENT_STATUS_OK) { | |
814 | goto end; | |
815 | } | |
816 | fputs(",", text->out); | |
817 | ||
818 | ret = print_event_header_raw(text, event); | |
819 | if (ret != BT_COMPONENT_STATUS_OK) { | |
820 | goto end; | |
821 | } | |
822 | fputs(",", text->out); | |
823 | ||
824 | ret = print_stream_event_context(text, event); | |
825 | if (ret != BT_COMPONENT_STATUS_OK) { | |
826 | goto end; | |
827 | } | |
828 | fputs(",", text->out); | |
829 | ||
830 | ret = print_event_context(text, event); | |
831 | if (ret != BT_COMPONENT_STATUS_OK) { | |
832 | goto end; | |
833 | } | |
834 | fputs(",", text->out); | |
835 | ||
836 | ret = print_event_payload(text, event); | |
837 | if (ret != BT_COMPONENT_STATUS_OK) { | |
838 | goto end; | |
839 | } | |
af9a82eb JG |
840 | |
841 | fputc('\n', text->out); | |
842 | end: | |
843 | return ret; | |
844 | } |