bfab450c2c4035ee82d9608db5099d574393da2b
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-ctf-ir-to-tsdl.c
1 /*
2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "translate-ctf-ir-to-tsdl.h"
24
25 #include <babeltrace2/babeltrace.h>
26 #include "common/macros.h"
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <string.h>
30 #include <glib.h>
31 #include "common/assert.h"
32 #include "compat/endian.h"
33
34 #include "fs-sink-ctf-meta.h"
35
36 struct ctx {
37 unsigned int indent_level;
38 GString *tsdl;
39 };
40
41 static inline
42 void append_indent(struct ctx *ctx)
43 {
44 unsigned int i;
45
46 for (i = 0; i < ctx->indent_level; i++) {
47 g_string_append_c(ctx->tsdl, '\t');
48 }
49 }
50
51 static
52 void append_uuid(struct ctx *ctx, bt_uuid uuid)
53 {
54 g_string_append_printf(ctx->tsdl,
55 "\"" BT_UUID_FMT "\"",
56 BT_UUID_FMT_VALUES(uuid));
57 }
58
59 static
60 void append_quoted_string_content(struct ctx *ctx, const char *str)
61 {
62 const char *ch;
63
64 for (ch = str; *ch != '\0'; ch++) {
65 unsigned char uch = (unsigned char) *ch;
66
67 if (uch < 32 || uch >= 127) {
68 switch (*ch) {
69 case '\a':
70 g_string_append(ctx->tsdl, "\\a");
71 break;
72 case '\b':
73 g_string_append(ctx->tsdl, "\\b");
74 break;
75 case '\f':
76 g_string_append(ctx->tsdl, "\\f");
77 break;
78 case '\n':
79 g_string_append(ctx->tsdl, "\\n");
80 break;
81 case '\r':
82 g_string_append(ctx->tsdl, "\\r");
83 break;
84 case '\t':
85 g_string_append(ctx->tsdl, "\\t");
86 break;
87 case '\v':
88 g_string_append(ctx->tsdl, "\\v");
89 break;
90 default:
91 g_string_append_printf(ctx->tsdl, "\\x%02x",
92 (unsigned int) uch);
93 break;
94 }
95 } else if (*ch == '"' || *ch == '\\') {
96 g_string_append_c(ctx->tsdl, '\\');
97 g_string_append_c(ctx->tsdl, *ch);
98 } else {
99 g_string_append_c(ctx->tsdl, *ch);
100 }
101 }
102 }
103
104 static
105 void append_quoted_string(struct ctx *ctx, const char *str)
106 {
107 g_string_append_c(ctx->tsdl, '"');
108 append_quoted_string_content(ctx, str);
109 g_string_append_c(ctx->tsdl, '"');
110 }
111
112 static
113 void append_integer_field_class_from_props(struct ctx *ctx, unsigned int size,
114 unsigned int alignment, bool is_signed,
115 bt_field_class_integer_preferred_display_base disp_base,
116 const char *mapped_clock_class_name, const char *field_name,
117 bool end)
118 {
119 g_string_append_printf(ctx->tsdl,
120 "integer { size = %u; align = %u;",
121 size, alignment);
122
123 if (is_signed) {
124 g_string_append(ctx->tsdl, " signed = true;");
125 }
126
127 if (disp_base != BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL) {
128 g_string_append(ctx->tsdl, " base = ");
129
130 switch (disp_base) {
131 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
132 g_string_append(ctx->tsdl, "b");
133 break;
134 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
135 g_string_append(ctx->tsdl, "o");
136 break;
137 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
138 g_string_append(ctx->tsdl, "x");
139 break;
140 default:
141 bt_common_abort();
142 }
143
144 g_string_append_c(ctx->tsdl, ';');
145 }
146
147 if (mapped_clock_class_name) {
148 g_string_append_printf(ctx->tsdl, " map = clock.%s.value;",
149 mapped_clock_class_name);
150 }
151
152 g_string_append(ctx->tsdl, " }");
153
154 if (field_name) {
155 g_string_append_printf(ctx->tsdl, " %s", field_name);
156 }
157
158 if (end) {
159 g_string_append(ctx->tsdl, ";\n");
160 }
161 }
162
163 static
164 void append_end_block(struct ctx *ctx)
165 {
166 ctx->indent_level--;
167 append_indent(ctx);
168 g_string_append(ctx->tsdl, "}");
169 }
170
171 static
172 void append_end_block_semi_nl(struct ctx *ctx)
173 {
174 ctx->indent_level--;
175 append_indent(ctx);
176 g_string_append(ctx->tsdl, "};\n");
177 }
178
179 static
180 void append_end_block_semi_nl_nl(struct ctx *ctx)
181 {
182 append_end_block_semi_nl(ctx);
183 g_string_append_c(ctx->tsdl, '\n');
184 }
185
186 static
187 void append_bool_field_class(struct ctx *ctx,
188 __attribute__((unused)) struct fs_sink_ctf_field_class_bool *fc)
189 {
190 /*
191 * CTF 1.8 has no boolean field class type, so this component
192 * translates it to an 8-bit unsigned integer field class.
193 */
194 append_integer_field_class_from_props(ctx, fc->base.size,
195 fc->base.base.alignment, false,
196 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
197 NULL, NULL, false);
198 }
199
200 static
201 void append_bit_array_field_class(struct ctx *ctx,
202 struct fs_sink_ctf_field_class_bit_array *fc)
203 {
204 /*
205 * CTF 1.8 has no bit array field class type, so this component
206 * translates it to an unsigned integer field class with an
207 * hexadecimal base.
208 */
209 append_integer_field_class_from_props(ctx, fc->size,
210 fc->base.alignment, false,
211 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
212 NULL, NULL, false);
213 }
214
215 static
216 void append_integer_field_class(struct ctx *ctx,
217 struct fs_sink_ctf_field_class_int *fc)
218 {
219 const bt_field_class *ir_fc = fc->base.base.ir_fc;
220 bt_field_class_type type = bt_field_class_get_type(ir_fc);
221 bool is_signed = bt_field_class_type_is(type,
222 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
223
224 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
225 g_string_append(ctx->tsdl, "enum : ");
226 }
227
228 append_integer_field_class_from_props(ctx, fc->base.size,
229 fc->base.base.alignment, is_signed,
230 bt_field_class_integer_get_preferred_display_base(ir_fc),
231 NULL, NULL, false);
232
233 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
234 uint64_t i;
235
236 g_string_append(ctx->tsdl, " {\n");
237 ctx->indent_level++;
238
239 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_fc); i++) {
240 const char *label;
241 const bt_field_class_enumeration_mapping *mapping;
242 const bt_field_class_enumeration_unsigned_mapping *u_mapping;
243 const bt_field_class_enumeration_signed_mapping *s_mapping;
244 const bt_integer_range_set *ranges;
245 const bt_integer_range_set_unsigned *u_ranges;
246 const bt_integer_range_set_signed *s_ranges;
247 uint64_t range_count;
248 uint64_t range_i;
249
250 if (is_signed) {
251 s_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
252 ir_fc, i);
253 mapping = bt_field_class_enumeration_signed_mapping_as_mapping_const(
254 s_mapping);
255 s_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
256 s_mapping);
257 ranges = bt_integer_range_set_signed_as_range_set_const(
258 s_ranges);
259 } else {
260 u_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
261 ir_fc, i);
262 mapping = bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
263 u_mapping);
264 u_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
265 u_mapping);
266 ranges = bt_integer_range_set_unsigned_as_range_set_const(
267 u_ranges);
268 }
269
270 label = bt_field_class_enumeration_mapping_get_label(
271 mapping);
272 range_count = bt_integer_range_set_get_range_count(
273 ranges);
274
275 for (range_i = 0; range_i < range_count; range_i++) {
276 append_indent(ctx);
277 g_string_append(ctx->tsdl, "\"");
278 append_quoted_string_content(ctx, label);
279 g_string_append(ctx->tsdl, "\" = ");
280
281 if (is_signed) {
282 const bt_integer_range_signed *range;
283 int64_t lower, upper;
284
285 range = bt_integer_range_set_signed_borrow_range_by_index_const(
286 s_ranges, range_i);
287 lower = bt_integer_range_signed_get_lower(
288 range);
289 upper = bt_integer_range_signed_get_upper(
290 range);
291
292 if (lower == upper) {
293 g_string_append_printf(
294 ctx->tsdl, "%" PRId64,
295 lower);
296 } else {
297 g_string_append_printf(
298 ctx->tsdl, "%" PRId64 " ... %" PRId64,
299 lower, upper);
300 }
301 } else {
302 const bt_integer_range_unsigned *range;
303 uint64_t lower, upper;
304
305 range = bt_integer_range_set_unsigned_borrow_range_by_index_const(
306 u_ranges, range_i);
307 lower = bt_integer_range_unsigned_get_lower(
308 range);
309 upper = bt_integer_range_unsigned_get_upper(
310 range);
311
312 if (lower == upper) {
313 g_string_append_printf(
314 ctx->tsdl, "%" PRIu64,
315 lower);
316 } else {
317 g_string_append_printf(
318 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
319 lower, upper);
320 }
321 }
322
323 g_string_append(ctx->tsdl, ",\n");
324 }
325 }
326
327 append_end_block(ctx);
328 }
329 }
330
331 static
332 void append_float_field_class(struct ctx *ctx,
333 struct fs_sink_ctf_field_class_float *fc)
334 {
335 unsigned int mant_dig, exp_dig;
336
337 if (bt_field_class_get_type(fc->base.base.ir_fc) ==
338 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) {
339 mant_dig = 24;
340 exp_dig = 8;
341 } else {
342 mant_dig = 53;
343 exp_dig = 11;
344 }
345
346 g_string_append_printf(ctx->tsdl,
347 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
348 mant_dig, exp_dig, fc->base.base.alignment);
349 }
350
351 static
352 void append_string_field_class(struct ctx *ctx,
353 struct fs_sink_ctf_field_class_float *fc)
354 {
355 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
356 }
357
358 static
359 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
360
361 static
362 void append_member(struct ctx *ctx, const char *name,
363 struct fs_sink_ctf_field_class *fc)
364 {
365 GString *lengths = NULL;
366 const char *lengths_str = "";
367
368 BT_ASSERT(fc);
369
370 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
371 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
372 if (!lengths) {
373 lengths = g_string_new(NULL);
374 BT_ASSERT(lengths);
375 }
376
377 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
378 struct fs_sink_ctf_field_class_array *array_fc =
379 (void *) fc;
380
381 g_string_append_printf(lengths, "[%" PRIu64 "]",
382 array_fc->length);
383 fc = array_fc->base.elem_fc;
384 } else {
385 struct fs_sink_ctf_field_class_sequence *seq_fc =
386 (void *) fc;
387
388 g_string_append_printf(lengths, "[%s]",
389 seq_fc->length_ref->str);
390 fc = seq_fc->base.elem_fc;
391 }
392 }
393
394 append_field_class(ctx, fc);
395
396 if (lengths) {
397 lengths_str = lengths->str;
398 }
399
400 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
401
402 if (lengths) {
403 g_string_free(lengths, TRUE);
404 }
405 }
406
407 static
408 void append_struct_field_class_members(struct ctx *ctx,
409 struct fs_sink_ctf_field_class_struct *struct_fc)
410 {
411 uint64_t i;
412
413 for (i = 0; i < struct_fc->members->len; i++) {
414 struct fs_sink_ctf_named_field_class *named_fc =
415 fs_sink_ctf_field_class_struct_borrow_member_by_index(
416 struct_fc, i);
417 struct fs_sink_ctf_field_class *fc = named_fc->fc;
418
419 /*
420 * For sequence, option, and variant field classes, if
421 * the length/tag field class is generated before, write
422 * it now before the dependent field class.
423 */
424 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
425 struct fs_sink_ctf_field_class_sequence *seq_fc =
426 (void *) fc;
427
428 if (seq_fc->length_is_before) {
429 append_indent(ctx);
430 append_integer_field_class_from_props(ctx,
431 32, 8, false,
432 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
433 NULL, seq_fc->length_ref->str, true);
434 }
435 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION) {
436 struct fs_sink_ctf_field_class_option *opt_fc =
437 (void *) fc;
438
439 /*
440 * CTF 1.8 does not support the option field
441 * class type. To write something anyway, this
442 * component translates this type to a variant
443 * field class where the options are:
444 *
445 * * An empty structure field class.
446 * * The optional field class itself.
447 *
448 * The "tag" is always generated/before in that
449 * case (an 8-bit unsigned enumeration field
450 * class).
451 */
452 append_indent(ctx);
453 g_string_append(ctx->tsdl,
454 "/* The enumeration and variant field classes "
455 "below were a trace IR option field class. */\n");
456 append_indent(ctx);
457 g_string_append(ctx->tsdl, "enum : ");
458 append_integer_field_class_from_props(ctx,
459 8, 8, false,
460 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
461 NULL, NULL, false);
462 g_string_append(ctx->tsdl, " {\n");
463 ctx->indent_level++;
464 append_indent(ctx);
465 g_string_append(ctx->tsdl, "none = 0,\n");
466 append_indent(ctx);
467 g_string_append(ctx->tsdl, "content = 1,\n");
468 append_end_block(ctx);
469 g_string_append_printf(ctx->tsdl, " %s;\n",
470 opt_fc->tag_ref->str);
471 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
472 struct fs_sink_ctf_field_class_variant *var_fc =
473 (void *) fc;
474
475 if (var_fc->tag_is_before) {
476 append_indent(ctx);
477 g_string_append(ctx->tsdl, "enum : ");
478 append_integer_field_class_from_props(ctx,
479 16, 8, false,
480 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
481 NULL, NULL, false);
482 g_string_append(ctx->tsdl, " {\n");
483 ctx->indent_level++;
484
485 for (i = 0; i < var_fc->options->len; i++) {
486 struct fs_sink_ctf_named_field_class *option_named_fc =
487 fs_sink_ctf_field_class_variant_borrow_option_by_index(
488 var_fc, i);
489
490 append_indent(ctx);
491 g_string_append_printf(ctx->tsdl,
492 "\"%s\" = %" PRIu64 ",\n",
493 option_named_fc->name->str, i);
494 }
495
496 append_end_block(ctx);
497 g_string_append_printf(ctx->tsdl, " %s;\n",
498 var_fc->tag_ref->str);
499 }
500 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL) {
501 append_indent(ctx);
502 g_string_append(ctx->tsdl,
503 "/* The integer field class below was a trace IR boolean field class. */\n");
504 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY) {
505 append_indent(ctx);
506 g_string_append(ctx->tsdl,
507 "/* The integer field class below was a trace IR bit array field class. */\n");
508 }
509
510 append_indent(ctx);
511 append_member(ctx, named_fc->name->str, fc);
512 }
513 }
514
515 static
516 void append_struct_field_class(struct ctx *ctx,
517 struct fs_sink_ctf_field_class_struct *fc)
518 {
519 g_string_append(ctx->tsdl, "struct {\n");
520 ctx->indent_level++;
521 append_struct_field_class_members(ctx, fc);
522 append_end_block(ctx);
523 g_string_append_printf(ctx->tsdl, " align(%u)",
524 fc->base.alignment);
525 }
526
527 static
528 void append_option_field_class(struct ctx *ctx,
529 struct fs_sink_ctf_field_class_option *opt_fc)
530 {
531 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
532 opt_fc->tag_ref->str);
533 ctx->indent_level++;
534 append_indent(ctx);
535 g_string_append(ctx->tsdl, "struct { } none;\n");
536 append_indent(ctx);
537 append_member(ctx, "content", opt_fc->content_fc);
538 append_end_block(ctx);
539 }
540
541 static
542 void append_variant_field_class(struct ctx *ctx,
543 struct fs_sink_ctf_field_class_variant *var_fc)
544 {
545 uint64_t i;
546
547 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
548 var_fc->tag_ref->str);
549 ctx->indent_level++;
550
551 for (i = 0; i < var_fc->options->len; i++) {
552 struct fs_sink_ctf_named_field_class *named_fc =
553 fs_sink_ctf_field_class_variant_borrow_option_by_index(
554 var_fc, i);
555
556 append_indent(ctx);
557 append_member(ctx, named_fc->name->str, named_fc->fc);
558 }
559
560 append_end_block(ctx);
561 }
562
563 static
564 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
565 {
566 switch (fc->type) {
567 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL:
568 append_bool_field_class(ctx, (void *) fc);
569 break;
570 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY:
571 append_bit_array_field_class(ctx, (void *) fc);
572 break;
573 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
574 append_integer_field_class(ctx, (void *) fc);
575 break;
576 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
577 append_float_field_class(ctx, (void *) fc);
578 break;
579 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
580 append_string_field_class(ctx, (void *) fc);
581 break;
582 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
583 append_struct_field_class(ctx, (void *) fc);
584 break;
585 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
586 append_option_field_class(ctx, (void *) fc);
587 break;
588 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
589 append_variant_field_class(ctx, (void *) fc);
590 break;
591 default:
592 bt_common_abort();
593 }
594 }
595
596 static
597 void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
598 {
599 const char *str;
600 bt_event_class_log_level log_level;
601
602 /* Event class */
603 append_indent(ctx);
604 g_string_append(ctx->tsdl, "event {\n");
605 ctx->indent_level++;
606
607 /* Event class properties */
608 append_indent(ctx);
609 g_string_append(ctx->tsdl, "name = ");
610 str = bt_event_class_get_name(ec->ir_ec);
611 if (!str) {
612 str = "unknown";
613 }
614
615 append_quoted_string(ctx, str);
616 g_string_append(ctx->tsdl, ";\n");
617 append_indent(ctx);
618 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
619 bt_stream_class_get_id(ec->sc->ir_sc));
620 append_indent(ctx);
621 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
622 bt_event_class_get_id(ec->ir_ec));
623
624 str = bt_event_class_get_emf_uri(ec->ir_ec);
625 if (str) {
626 append_indent(ctx);
627 g_string_append(ctx->tsdl, "model.emf.uri = ");
628 append_quoted_string(ctx, str);
629 g_string_append(ctx->tsdl, ";\n");
630 }
631
632 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
633 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
634 unsigned int level;
635
636 append_indent(ctx);
637 g_string_append(ctx->tsdl, "loglevel = ");
638
639 switch (log_level) {
640 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
641 level = 0;
642 break;
643 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
644 level = 1;
645 break;
646 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
647 level = 2;
648 break;
649 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
650 level = 3;
651 break;
652 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
653 level = 4;
654 break;
655 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
656 level = 5;
657 break;
658 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
659 level = 6;
660 break;
661 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
662 level = 7;
663 break;
664 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
665 level = 8;
666 break;
667 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
668 level = 9;
669 break;
670 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
671 level = 10;
672 break;
673 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
674 level = 11;
675 break;
676 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
677 level = 12;
678 break;
679 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
680 level = 13;
681 break;
682 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
683 level = 14;
684 break;
685 default:
686 bt_common_abort();
687 }
688
689 g_string_append_printf(ctx->tsdl, "%u;\n", level);
690 }
691
692 /* Event specific context field class */
693 if (ec->spec_context_fc) {
694 append_indent(ctx);
695 g_string_append(ctx->tsdl, "context := ");
696 append_field_class(ctx, ec->spec_context_fc);
697 g_string_append(ctx->tsdl, ";\n");
698 }
699
700 /* Event payload field class */
701 if (ec->payload_fc) {
702 append_indent(ctx);
703 g_string_append(ctx->tsdl, "fields := ");
704 append_field_class(ctx, ec->payload_fc);
705 g_string_append(ctx->tsdl, ";\n");
706 }
707
708 append_end_block_semi_nl_nl(ctx);
709 }
710
711 static
712 void append_stream_class(struct ctx *ctx,
713 struct fs_sink_ctf_stream_class *sc)
714 {
715 uint64_t i;
716
717 /* Default clock class */
718 if (sc->default_clock_class) {
719 const char *descr;
720 int64_t offset_seconds;
721 uint64_t offset_cycles;
722 bt_uuid uuid;
723
724 append_indent(ctx);
725 g_string_append(ctx->tsdl, "clock {\n");
726 ctx->indent_level++;
727 BT_ASSERT(sc->default_clock_class_name->len > 0);
728 append_indent(ctx);
729 g_string_append_printf(ctx->tsdl, "name = %s;\n",
730 sc->default_clock_class_name->str);
731 descr = bt_clock_class_get_description(sc->default_clock_class);
732 if (descr) {
733 append_indent(ctx);
734 g_string_append(ctx->tsdl, "description = ");
735 append_quoted_string(ctx, descr);
736 g_string_append(ctx->tsdl, ";\n");
737 }
738
739 append_indent(ctx);
740 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
741 bt_clock_class_get_frequency(sc->default_clock_class));
742 append_indent(ctx);
743 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
744 bt_clock_class_get_precision(sc->default_clock_class));
745 bt_clock_class_get_offset(sc->default_clock_class,
746 &offset_seconds, &offset_cycles);
747 append_indent(ctx);
748 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
749 offset_seconds);
750 append_indent(ctx);
751 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
752 offset_cycles);
753 append_indent(ctx);
754 g_string_append(ctx->tsdl, "absolute = ");
755
756 if (bt_clock_class_origin_is_unix_epoch(
757 sc->default_clock_class)) {
758 g_string_append(ctx->tsdl, "true");
759 } else {
760 g_string_append(ctx->tsdl, "false");
761 }
762
763 g_string_append(ctx->tsdl, ";\n");
764 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
765 if (uuid) {
766 append_indent(ctx);
767 g_string_append(ctx->tsdl, "uuid = ");
768 append_uuid(ctx, uuid);
769 g_string_append(ctx->tsdl, ";\n");
770 }
771
772 /* End clock class */
773 append_end_block_semi_nl_nl(ctx);
774 }
775
776 /* Stream class */
777 append_indent(ctx);
778 g_string_append(ctx->tsdl, "stream {\n");
779 ctx->indent_level++;
780
781 /* Stream class properties */
782 append_indent(ctx);
783 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
784 bt_stream_class_get_id(sc->ir_sc));
785
786 /* Packet context field class */
787 append_indent(ctx);
788 g_string_append(ctx->tsdl, "packet.context := struct {\n");
789 ctx->indent_level++;
790 append_indent(ctx);
791 append_integer_field_class_from_props(ctx, 64, 8, false,
792 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
793 NULL, "packet_size", true);
794 append_indent(ctx);
795 append_integer_field_class_from_props(ctx, 64, 8, false,
796 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
797 NULL, "content_size", true);
798
799 if (sc->packets_have_ts_begin) {
800 append_indent(ctx);
801 append_integer_field_class_from_props(ctx, 64, 8, false,
802 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
803 sc->default_clock_class_name->str,
804 "timestamp_begin", true);
805 }
806
807 if (sc->packets_have_ts_end) {
808 append_indent(ctx);
809 append_integer_field_class_from_props(ctx, 64, 8, false,
810 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
811 sc->default_clock_class_name->str,
812 "timestamp_end", true);
813 }
814
815 if (sc->has_discarded_events) {
816 append_indent(ctx);
817 append_integer_field_class_from_props(ctx, 64, 8, false,
818 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
819 NULL, "events_discarded", true);
820 }
821
822 /*
823 * Unconditionnally write the packet sequence number as, even if
824 * there's no possible discarded packets message, it's still
825 * useful information to have.
826 */
827 append_indent(ctx);
828 append_integer_field_class_from_props(ctx, 64, 8, false,
829 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
830 NULL, "packet_seq_num", true);
831
832 if (sc->packet_context_fc) {
833 append_struct_field_class_members(ctx,
834 (void *) sc->packet_context_fc);
835 fs_sink_ctf_field_class_struct_align_at_least(
836 (void *) sc->packet_context_fc, 8);
837 }
838
839 /* End packet context field class */
840 append_end_block(ctx);
841 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
842 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
843
844 /* Event header field class */
845 append_indent(ctx);
846 g_string_append(ctx->tsdl, "event.header := struct {\n");
847 ctx->indent_level++;
848 append_indent(ctx);
849 append_integer_field_class_from_props(ctx, 64, 8, false,
850 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
851 NULL, "id", true);
852
853 if (sc->default_clock_class) {
854 append_indent(ctx);
855 append_integer_field_class_from_props(ctx, 64, 8, false,
856 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
857 sc->default_clock_class_name->str,
858 "timestamp", true);
859 }
860
861 /* End event header field class */
862 append_end_block(ctx);
863 g_string_append(ctx->tsdl, " align(8);\n");
864
865 /* Event common context field class */
866 if (sc->event_common_context_fc) {
867 append_indent(ctx);
868 g_string_append(ctx->tsdl, "event.context := ");
869 append_field_class(ctx,
870 (void *) sc->event_common_context_fc);
871 g_string_append(ctx->tsdl, ";\n");
872 }
873
874 /* End stream class */
875 append_end_block_semi_nl_nl(ctx);
876
877 /* Event classes */
878 for (i = 0; i < sc->event_classes->len; i++) {
879 append_event_class(ctx, sc->event_classes->pdata[i]);
880 }
881 }
882
883 BT_HIDDEN
884 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace *trace,
885 GString *tsdl)
886 {
887 struct ctx ctx = {
888 .indent_level = 0,
889 .tsdl = tsdl,
890 };
891 uint64_t i;
892 uint64_t count;
893
894 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
895 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
896
897 /* Trace class */
898 append_indent(&ctx);
899 g_string_append(tsdl, "trace {\n");
900 ctx.indent_level++;
901
902 /* Trace class properties */
903 append_indent(&ctx);
904 g_string_append(tsdl, "major = 1;\n");
905 append_indent(&ctx);
906 g_string_append(tsdl, "minor = 8;\n");
907 append_indent(&ctx);
908 g_string_append(tsdl, "uuid = ");
909 append_uuid(&ctx, trace->uuid);
910 g_string_append(tsdl, ";\n");
911 append_indent(&ctx);
912 g_string_append(tsdl, "byte_order = ");
913
914 if (BYTE_ORDER == LITTLE_ENDIAN) {
915 g_string_append(tsdl, "le");
916 } else {
917 g_string_append(tsdl, "be");
918 }
919
920 g_string_append(tsdl, ";\n");
921
922 /* Packet header field class */
923 append_indent(&ctx);
924 g_string_append(tsdl, "packet.header := struct {\n");
925 ctx.indent_level++;
926 append_indent(&ctx);
927 append_integer_field_class_from_props(&ctx, 32, 8, false,
928 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
929 NULL, "magic", true);
930 append_indent(&ctx);
931 append_integer_field_class_from_props(&ctx, 8, 8, false,
932 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
933 NULL, "uuid[16]", true);
934 append_indent(&ctx);
935 append_integer_field_class_from_props(&ctx, 64, 8, false,
936 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
937 NULL, "stream_id", true);
938 append_indent(&ctx);
939 append_integer_field_class_from_props(&ctx, 64, 8, false,
940 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
941 NULL, "stream_instance_id", true);
942
943 /* End packet header field class */
944 append_end_block(&ctx);
945 g_string_append(ctx.tsdl, " align(8);\n");
946
947 /* End trace class */
948 append_end_block_semi_nl_nl(&ctx);
949
950 /* Trace environment */
951 count = bt_trace_get_environment_entry_count(trace->ir_trace);
952 if (count > 0) {
953 append_indent(&ctx);
954 g_string_append(tsdl, "env {\n");
955 ctx.indent_level++;
956
957 for (i = 0; i < count; i++) {
958 const char *name;
959 const bt_value *val;
960
961 bt_trace_borrow_environment_entry_by_index_const(
962 trace->ir_trace, i, &name, &val);
963 append_indent(&ctx);
964 g_string_append_printf(tsdl, "%s = ", name);
965
966 switch (bt_value_get_type(val)) {
967 case BT_VALUE_TYPE_SIGNED_INTEGER:
968 g_string_append_printf(tsdl, "%" PRId64,
969 bt_value_integer_signed_get(val));
970 break;
971 case BT_VALUE_TYPE_STRING:
972 append_quoted_string(&ctx, bt_value_string_get(val));
973 break;
974 default:
975 /*
976 * This is checked in
977 * translate_trace_trace_ir_to_ctf_ir().
978 */
979 bt_common_abort();
980 }
981
982 g_string_append(tsdl, ";\n");
983 }
984
985 /* End trace class environment */
986 append_end_block_semi_nl_nl(&ctx);
987 }
988
989 /* Stream classes and their event classes */
990 for (i = 0; i < trace->stream_classes->len; i++) {
991 append_stream_class(&ctx, trace->stream_classes->pdata[i]);
992 }
993 }
This page took 0.064357 seconds and 3 git commands to generate.