c81b70f6e8c7db178475566317e98aed0a864cec
[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 #define BT_LOG_TAG "PLUGIN-CTF-FS-SINK-TRANSLATE-CTF-IR-TO-TSDL"
24 #include "logging.h"
25
26 #include <babeltrace2/babeltrace.h>
27 #include "common/macros.h"
28 #include <stdio.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <glib.h>
32 #include "common/assert.h"
33 #include "compat/endian.h"
34
35 #include "fs-sink-ctf-meta.h"
36
37 struct ctx {
38 unsigned int indent_level;
39 GString *tsdl;
40 };
41
42 static inline
43 void append_indent(struct ctx *ctx)
44 {
45 unsigned int i;
46
47 for (i = 0; i < ctx->indent_level; i++) {
48 g_string_append_c(ctx->tsdl, '\t');
49 }
50 }
51
52 static
53 void append_uuid(struct ctx *ctx, bt_uuid uuid)
54 {
55 g_string_append_printf(ctx->tsdl,
56 "\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
57 (unsigned int) uuid[0],
58 (unsigned int) uuid[1],
59 (unsigned int) uuid[2],
60 (unsigned int) uuid[3],
61 (unsigned int) uuid[4],
62 (unsigned int) uuid[5],
63 (unsigned int) uuid[6],
64 (unsigned int) uuid[7],
65 (unsigned int) uuid[8],
66 (unsigned int) uuid[9],
67 (unsigned int) uuid[10],
68 (unsigned int) uuid[11],
69 (unsigned int) uuid[12],
70 (unsigned int) uuid[13],
71 (unsigned int) uuid[14],
72 (unsigned int) uuid[15]);
73 }
74
75 static
76 void append_quoted_string_content(struct ctx *ctx, const char *str)
77 {
78 const char *ch;
79
80 for (ch = str; *ch != '\0'; ch++) {
81 unsigned char uch = (unsigned char) *ch;
82
83 if (uch < 32 || uch >= 127) {
84 switch (*ch) {
85 case '\a':
86 g_string_append(ctx->tsdl, "\\a");
87 break;
88 case '\b':
89 g_string_append(ctx->tsdl, "\\b");
90 break;
91 case '\f':
92 g_string_append(ctx->tsdl, "\\f");
93 break;
94 case '\n':
95 g_string_append(ctx->tsdl, "\\n");
96 break;
97 case '\r':
98 g_string_append(ctx->tsdl, "\\r");
99 break;
100 case '\t':
101 g_string_append(ctx->tsdl, "\\t");
102 break;
103 case '\v':
104 g_string_append(ctx->tsdl, "\\v");
105 break;
106 default:
107 g_string_append_printf(ctx->tsdl, "\\x%02x",
108 (unsigned int) uch);
109 break;
110 }
111 } else if (*ch == '"' || *ch == '\\') {
112 g_string_append_c(ctx->tsdl, '\\');
113 g_string_append_c(ctx->tsdl, *ch);
114 } else {
115 g_string_append_c(ctx->tsdl, *ch);
116 }
117 }
118 }
119
120 static
121 void append_quoted_string(struct ctx *ctx, const char *str)
122 {
123 g_string_append_c(ctx->tsdl, '"');
124 append_quoted_string_content(ctx, str);
125 g_string_append_c(ctx->tsdl, '"');
126 }
127
128 static
129 void append_integer_field_class_from_props(struct ctx *ctx, unsigned int size,
130 unsigned int alignment, bool is_signed,
131 bt_field_class_integer_preferred_display_base disp_base,
132 const char *mapped_clock_class_name, const char *field_name,
133 bool end)
134 {
135 g_string_append_printf(ctx->tsdl,
136 "integer { size = %u; align = %u;",
137 size, alignment);
138
139 if (is_signed) {
140 g_string_append(ctx->tsdl, " signed = true;");
141 }
142
143 if (disp_base != BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL) {
144 g_string_append(ctx->tsdl, " base = ");
145
146 switch (disp_base) {
147 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
148 g_string_append(ctx->tsdl, "b");
149 break;
150 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
151 g_string_append(ctx->tsdl, "o");
152 break;
153 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
154 g_string_append(ctx->tsdl, "x");
155 break;
156 default:
157 abort();
158 }
159
160 g_string_append_c(ctx->tsdl, ';');
161 }
162
163 if (mapped_clock_class_name) {
164 g_string_append_printf(ctx->tsdl, " map = clock.%s.value;",
165 mapped_clock_class_name);
166 }
167
168 g_string_append(ctx->tsdl, " }");
169
170 if (field_name) {
171 g_string_append_printf(ctx->tsdl, " %s", field_name);
172 }
173
174 if (end) {
175 g_string_append(ctx->tsdl, ";\n");
176 }
177 }
178
179 static
180 void append_end_block(struct ctx *ctx)
181 {
182 ctx->indent_level--;
183 append_indent(ctx);
184 g_string_append(ctx->tsdl, "}");
185 }
186
187 static
188 void append_end_block_semi_nl(struct ctx *ctx)
189 {
190 ctx->indent_level--;
191 append_indent(ctx);
192 g_string_append(ctx->tsdl, "};\n");
193 }
194
195 static
196 void append_end_block_semi_nl_nl(struct ctx *ctx)
197 {
198 append_end_block_semi_nl(ctx);
199 g_string_append_c(ctx->tsdl, '\n');
200 }
201
202 static
203 void append_integer_field_class(struct ctx *ctx,
204 struct fs_sink_ctf_field_class_int *fc)
205 {
206 const bt_field_class *ir_fc = fc->base.base.ir_fc;
207 bt_field_class_type type = bt_field_class_get_type(ir_fc);
208 bool is_signed = type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION ||
209 type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER;
210
211 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
212 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
213 g_string_append(ctx->tsdl, "enum : ");
214 }
215
216 append_integer_field_class_from_props(ctx, fc->base.size,
217 fc->base.base.alignment, is_signed,
218 bt_field_class_integer_get_preferred_display_base(ir_fc),
219 NULL, NULL, false);
220
221 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
222 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
223 uint64_t i;
224
225 g_string_append(ctx->tsdl, " {\n");
226 ctx->indent_level++;
227
228 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_fc); i++) {
229 const char *label;
230 const bt_field_class_enumeration_mapping *mapping;
231 const bt_field_class_unsigned_enumeration_mapping *u_mapping;
232 const bt_field_class_signed_enumeration_mapping *i_mapping;
233 uint64_t range_count;
234 uint64_t range_i;
235
236 if (is_signed) {
237 i_mapping = bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
238 ir_fc, i);
239 mapping = bt_field_class_signed_enumeration_mapping_as_mapping_const(
240 i_mapping);
241 } else {
242 u_mapping = bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
243 ir_fc, i);
244 mapping = bt_field_class_unsigned_enumeration_mapping_as_mapping_const(
245 u_mapping);
246 }
247
248 label = bt_field_class_enumeration_mapping_get_label(
249 mapping);
250 range_count =
251 bt_field_class_enumeration_mapping_get_range_count(
252 mapping);
253
254 for (range_i = 0; range_i < range_count; range_i++) {
255 append_indent(ctx);
256
257 /*
258 * Systematically prepend `_` to the
259 * mapping's label as this could be used
260 * as the tag of a subsequent variant
261 * field class and variant FC option
262 * names are systematically protected
263 * with a leading `_`.
264 *
265 * FIXME: This is temporary as the
266 * library's API should change to
267 * decouple variant FC option names from
268 * selector FC labels. The current
269 * drawback is that an original label
270 * `HELLO` becomes `_HELLO` in the
271 * generated metadata, therefore tools
272 * expecting `HELLO` could fail.
273 */
274 g_string_append(ctx->tsdl, "\"_");
275 append_quoted_string_content(ctx, label);
276 g_string_append(ctx->tsdl, "\" = ");
277
278 if (is_signed) {
279 int64_t lower, upper;
280
281 bt_field_class_signed_enumeration_mapping_get_range_by_index(
282 i_mapping, range_i,
283 &lower, &upper);
284
285 if (lower == upper) {
286 g_string_append_printf(
287 ctx->tsdl, "%" PRId64,
288 lower);
289 } else {
290 g_string_append_printf(
291 ctx->tsdl, "%" PRId64 " ... %" PRId64,
292 lower, upper);
293 }
294 } else {
295 uint64_t lower, upper;
296
297 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
298 u_mapping, range_i,
299 &lower, &upper);
300
301 if (lower == upper) {
302 g_string_append_printf(
303 ctx->tsdl, "%" PRIu64,
304 lower);
305 } else {
306 g_string_append_printf(
307 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
308 lower, upper);
309 }
310 }
311
312 g_string_append(ctx->tsdl, ",\n");
313 }
314 }
315
316 append_end_block(ctx);
317 }
318 }
319
320 static
321 void append_float_field_class(struct ctx *ctx,
322 struct fs_sink_ctf_field_class_float *fc)
323 {
324 unsigned int mant_dig, exp_dig;
325
326 if (bt_field_class_real_is_single_precision(fc->base.base.ir_fc)) {
327 mant_dig = 24;
328 exp_dig = 8;
329 } else {
330 mant_dig = 53;
331 exp_dig = 11;
332 }
333
334 g_string_append_printf(ctx->tsdl,
335 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
336 mant_dig, exp_dig, fc->base.base.alignment);
337 }
338
339 static
340 void append_string_field_class(struct ctx *ctx,
341 struct fs_sink_ctf_field_class_float *fc)
342 {
343 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
344 }
345
346 static
347 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
348
349 static
350 void append_member(struct ctx *ctx, const char *name,
351 struct fs_sink_ctf_field_class *fc)
352 {
353 GString *lengths = NULL;
354 const char *lengths_str = "";
355
356 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
357 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
358 if (!lengths) {
359 lengths = g_string_new(NULL);
360 BT_ASSERT(lengths);
361 }
362
363 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
364 struct fs_sink_ctf_field_class_array *array_fc =
365 (void *) fc;
366
367 g_string_append_printf(lengths, "[%" PRIu64 "]",
368 array_fc->length);
369 fc = array_fc->base.elem_fc;
370 } else {
371 struct fs_sink_ctf_field_class_sequence *seq_fc =
372 (void *) fc;
373
374 g_string_append_printf(lengths, "[%s]",
375 seq_fc->length_ref->str);
376 fc = seq_fc->base.elem_fc;
377 }
378 }
379
380 append_field_class(ctx, fc);
381
382 if (lengths) {
383 lengths_str = lengths->str;
384 }
385
386 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
387
388 if (lengths) {
389 g_string_free(lengths, TRUE);
390 }
391 }
392
393 static
394 void append_struct_field_class_members(struct ctx *ctx,
395 struct fs_sink_ctf_field_class_struct *struct_fc)
396 {
397 uint64_t i;
398
399 for (i = 0; i < struct_fc->members->len; i++) {
400 struct fs_sink_ctf_named_field_class *named_fc =
401 fs_sink_ctf_field_class_struct_borrow_member_by_index(
402 struct_fc, i);
403 struct fs_sink_ctf_field_class *fc = named_fc->fc;
404
405 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
406 struct fs_sink_ctf_field_class_sequence *seq_fc =
407 (void *) fc;
408
409 if (seq_fc->length_is_before) {
410 append_indent(ctx);
411 append_integer_field_class_from_props(ctx,
412 32, 8, false,
413 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
414 NULL, seq_fc->length_ref->str, true);
415 }
416 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
417 struct fs_sink_ctf_field_class_variant *var_fc =
418 (void *) fc;
419
420 if (var_fc->tag_is_before) {
421 append_indent(ctx);
422 g_string_append(ctx->tsdl, "enum : ");
423 append_integer_field_class_from_props(ctx,
424 16, 8, false,
425 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
426 NULL, NULL, false);
427 g_string_append(ctx->tsdl, " {\n");
428 ctx->indent_level++;
429
430 for (i = 0; i < var_fc->options->len; i++) {
431 struct fs_sink_ctf_named_field_class *named_fc =
432 fs_sink_ctf_field_class_variant_borrow_option_by_index(
433 var_fc, i);
434
435 append_indent(ctx);
436 g_string_append_printf(ctx->tsdl,
437 "\"%s\" = %" PRIu64 ",\n",
438 named_fc->name->str, i);
439 }
440
441 append_end_block(ctx);
442 g_string_append_printf(ctx->tsdl, " %s;\n",
443 var_fc->tag_ref->str);
444 }
445 }
446
447 append_indent(ctx);
448 append_member(ctx, named_fc->name->str, fc);
449 }
450 }
451
452 static
453 void append_struct_field_class(struct ctx *ctx,
454 struct fs_sink_ctf_field_class_struct *fc)
455 {
456 g_string_append(ctx->tsdl, "struct {\n");
457 ctx->indent_level++;
458 append_struct_field_class_members(ctx, fc);
459 append_end_block(ctx);
460 g_string_append_printf(ctx->tsdl, " align(%u)",
461 fc->base.alignment);
462 }
463
464 static
465 void append_variant_field_class(struct ctx *ctx,
466 struct fs_sink_ctf_field_class_variant *var_fc)
467 {
468 uint64_t i;
469
470 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
471 var_fc->tag_ref->str);
472 ctx->indent_level++;
473
474 for (i = 0; i < var_fc->options->len; i++) {
475 struct fs_sink_ctf_named_field_class *named_fc =
476 fs_sink_ctf_field_class_variant_borrow_option_by_index(
477 var_fc, i);
478
479 append_indent(ctx);
480 append_member(ctx, named_fc->name->str, named_fc->fc);
481 }
482
483 append_end_block(ctx);
484 }
485
486 static
487 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
488 {
489 switch (fc->type) {
490 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
491 append_integer_field_class(ctx, (void *) fc);
492 break;
493 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
494 append_float_field_class(ctx, (void *) fc);
495 break;
496 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
497 append_string_field_class(ctx, (void *) fc);
498 break;
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
500 append_struct_field_class(ctx, (void *) fc);
501 break;
502 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
503 append_variant_field_class(ctx, (void *) fc);
504 break;
505 default:
506 abort();
507 }
508 }
509
510 static
511 void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
512 {
513 const char *str;
514 bt_event_class_log_level log_level;
515
516 /* Event class */
517 append_indent(ctx);
518 g_string_append(ctx->tsdl, "event {\n");
519 ctx->indent_level++;
520
521 /* Event class properties */
522 append_indent(ctx);
523 g_string_append(ctx->tsdl, "name = ");
524 str = bt_event_class_get_name(ec->ir_ec);
525 if (!str) {
526 str = "unknown";
527 }
528
529 append_quoted_string(ctx, str);
530 g_string_append(ctx->tsdl, ";\n");
531 append_indent(ctx);
532 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
533 bt_stream_class_get_id(ec->sc->ir_sc));
534 append_indent(ctx);
535 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
536 bt_event_class_get_id(ec->ir_ec));
537
538 str = bt_event_class_get_emf_uri(ec->ir_ec);
539 if (str) {
540 append_indent(ctx);
541 g_string_append(ctx->tsdl, "model.emf.uri = ");
542 append_quoted_string(ctx, str);
543 g_string_append(ctx->tsdl, ";\n");
544 }
545
546 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
547 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
548 unsigned int level;
549
550 append_indent(ctx);
551 g_string_append(ctx->tsdl, "loglevel = ");
552
553 switch (log_level) {
554 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
555 level = 0;
556 break;
557 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
558 level = 1;
559 break;
560 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
561 level = 2;
562 break;
563 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
564 level = 3;
565 break;
566 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
567 level = 4;
568 break;
569 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
570 level = 5;
571 break;
572 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
573 level = 6;
574 break;
575 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
576 level = 7;
577 break;
578 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
579 level = 8;
580 break;
581 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
582 level = 9;
583 break;
584 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
585 level = 10;
586 break;
587 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
588 level = 11;
589 break;
590 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
591 level = 12;
592 break;
593 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
594 level = 13;
595 break;
596 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
597 level = 14;
598 break;
599 default:
600 abort();
601 }
602
603 g_string_append_printf(ctx->tsdl, "%u;\n", level);
604 }
605
606 /* Event specific context field class */
607 if (ec->spec_context_fc) {
608 append_indent(ctx);
609 g_string_append(ctx->tsdl, "context := ");
610 append_field_class(ctx, ec->spec_context_fc);
611 g_string_append(ctx->tsdl, ";\n");
612 }
613
614 /* Event payload field class */
615 if (ec->payload_fc) {
616 append_indent(ctx);
617 g_string_append(ctx->tsdl, "fields := ");
618 append_field_class(ctx, ec->payload_fc);
619 g_string_append(ctx->tsdl, ";\n");
620 }
621
622 append_end_block_semi_nl_nl(ctx);
623 }
624
625 static
626 void append_stream_class(struct ctx *ctx,
627 struct fs_sink_ctf_stream_class *sc)
628 {
629 uint64_t i;
630
631 /* Default clock class */
632 if (sc->default_clock_class) {
633 const char *descr;
634 int64_t offset_seconds;
635 uint64_t offset_cycles;
636 bt_uuid uuid;
637
638 append_indent(ctx);
639 g_string_append(ctx->tsdl, "clock {\n");
640 ctx->indent_level++;
641 BT_ASSERT(sc->default_clock_class_name->len > 0);
642 append_indent(ctx);
643 g_string_append_printf(ctx->tsdl, "name = %s;\n",
644 sc->default_clock_class_name->str);
645 descr = bt_clock_class_get_description(sc->default_clock_class);
646 if (descr) {
647 append_indent(ctx);
648 g_string_append(ctx->tsdl, "description = ");
649 append_quoted_string(ctx, descr);
650 g_string_append(ctx->tsdl, ";\n");
651 }
652
653 append_indent(ctx);
654 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
655 bt_clock_class_get_frequency(sc->default_clock_class));
656 append_indent(ctx);
657 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
658 bt_clock_class_get_precision(sc->default_clock_class));
659 bt_clock_class_get_offset(sc->default_clock_class,
660 &offset_seconds, &offset_cycles);
661 append_indent(ctx);
662 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
663 offset_seconds);
664 append_indent(ctx);
665 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
666 offset_cycles);
667 append_indent(ctx);
668 g_string_append(ctx->tsdl, "absolute = ");
669
670 if (bt_clock_class_origin_is_unix_epoch(
671 sc->default_clock_class)) {
672 g_string_append(ctx->tsdl, "true");
673 } else {
674 g_string_append(ctx->tsdl, "false");
675 }
676
677 g_string_append(ctx->tsdl, ";\n");
678 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
679 if (uuid) {
680 append_indent(ctx);
681 g_string_append(ctx->tsdl, "uuid = ");
682 append_uuid(ctx, uuid);
683 g_string_append(ctx->tsdl, ";\n");
684 }
685
686 /* End clock class */
687 append_end_block_semi_nl_nl(ctx);
688 }
689
690 /* Stream class */
691 append_indent(ctx);
692 g_string_append(ctx->tsdl, "stream {\n");
693 ctx->indent_level++;
694
695 /* Stream class properties */
696 append_indent(ctx);
697 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
698 bt_stream_class_get_id(sc->ir_sc));
699
700 /* Packet context field class */
701 append_indent(ctx);
702 g_string_append(ctx->tsdl, "packet.context := struct {\n");
703 ctx->indent_level++;
704 append_indent(ctx);
705 append_integer_field_class_from_props(ctx, 64, 8, false,
706 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
707 NULL, "packet_size", true);
708 append_indent(ctx);
709 append_integer_field_class_from_props(ctx, 64, 8, false,
710 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
711 NULL, "content_size", true);
712
713 if (sc->packets_have_ts_begin) {
714 append_indent(ctx);
715 append_integer_field_class_from_props(ctx, 64, 8, false,
716 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
717 sc->default_clock_class_name->str,
718 "timestamp_begin", true);
719 }
720
721 if (sc->packets_have_ts_end) {
722 append_indent(ctx);
723 append_integer_field_class_from_props(ctx, 64, 8, false,
724 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
725 sc->default_clock_class_name->str,
726 "timestamp_end", true);
727 }
728
729 if (sc->has_discarded_events) {
730 append_indent(ctx);
731 append_integer_field_class_from_props(ctx, 64, 8, false,
732 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
733 NULL, "events_discarded", true);
734 }
735
736 /*
737 * Unconditionnally write the packet sequence number as, even if
738 * there's no possible discarded packets message, it's still
739 * useful information to have.
740 */
741 append_indent(ctx);
742 append_integer_field_class_from_props(ctx, 64, 8, false,
743 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
744 NULL, "packet_seq_num", true);
745
746 if (sc->packet_context_fc) {
747 append_struct_field_class_members(ctx,
748 (void *) sc->packet_context_fc);
749 fs_sink_ctf_field_class_struct_align_at_least(
750 (void *) sc->packet_context_fc, 8);
751 }
752
753 /* End packet context field class */
754 append_end_block(ctx);
755 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
756 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
757
758 /* Event header field class */
759 append_indent(ctx);
760 g_string_append(ctx->tsdl, "event.header := struct {\n");
761 ctx->indent_level++;
762 append_indent(ctx);
763 append_integer_field_class_from_props(ctx, 64, 8, false,
764 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
765 NULL, "id", true);
766
767 if (sc->default_clock_class) {
768 append_indent(ctx);
769 append_integer_field_class_from_props(ctx, 64, 8, false,
770 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
771 sc->default_clock_class_name->str,
772 "timestamp", true);
773 }
774
775 /* End event header field class */
776 append_end_block(ctx);
777 g_string_append(ctx->tsdl, " align(8);\n");
778
779 /* Event common context field class */
780 if (sc->event_common_context_fc) {
781 append_indent(ctx);
782 g_string_append(ctx->tsdl, "event.context := ");
783 append_field_class(ctx,
784 (void *) sc->event_common_context_fc);
785 g_string_append(ctx->tsdl, ";\n");
786 }
787
788 /* End stream class */
789 append_end_block_semi_nl_nl(ctx);
790
791 /* Event classes */
792 for (i = 0; i < sc->event_classes->len; i++) {
793 append_event_class(ctx, sc->event_classes->pdata[i]);
794 }
795 }
796
797 BT_HIDDEN
798 void translate_trace_class_ctf_ir_to_tsdl(struct fs_sink_ctf_trace_class *tc,
799 GString *tsdl)
800 {
801 struct ctx ctx = {
802 .indent_level = 0,
803 .tsdl = tsdl,
804 };
805 uint64_t i;
806 uint64_t count;
807
808 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
809 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
810
811 /* Trace class */
812 append_indent(&ctx);
813 g_string_append(tsdl, "trace {\n");
814 ctx.indent_level++;
815
816 /* Trace class properties */
817 append_indent(&ctx);
818 g_string_append(tsdl, "major = 1;\n");
819 append_indent(&ctx);
820 g_string_append(tsdl, "minor = 8;\n");
821 append_indent(&ctx);
822 g_string_append(tsdl, "uuid = ");
823 append_uuid(&ctx, tc->uuid);
824 g_string_append(tsdl, ";\n");
825 append_indent(&ctx);
826 g_string_append(tsdl, "byte_order = ");
827
828 if (BYTE_ORDER == LITTLE_ENDIAN) {
829 g_string_append(tsdl, "le");
830 } else {
831 g_string_append(tsdl, "be");
832 }
833
834 g_string_append(tsdl, ";\n");
835
836 /* Packet header field class */
837 append_indent(&ctx);
838 g_string_append(tsdl, "packet.header := struct {\n");
839 ctx.indent_level++;
840 append_indent(&ctx);
841 append_integer_field_class_from_props(&ctx, 32, 8, false,
842 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
843 NULL, "magic", true);
844 append_indent(&ctx);
845 append_integer_field_class_from_props(&ctx, 8, 8, false,
846 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
847 NULL, "uuid[16]", true);
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, "stream_id", true);
852 append_indent(&ctx);
853 append_integer_field_class_from_props(&ctx, 64, 8, false,
854 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
855 NULL, "stream_instance_id", true);
856
857 /* End packet header field class */
858 append_end_block(&ctx);
859 g_string_append(ctx.tsdl, " align(8);\n");
860
861 /* End trace class */
862 append_end_block_semi_nl_nl(&ctx);
863
864 /* Trace class environment */
865 count = bt_trace_class_get_environment_entry_count(tc->ir_tc);
866 if (count > 0) {
867 append_indent(&ctx);
868 g_string_append(tsdl, "env {\n");
869 ctx.indent_level++;
870
871 for (i = 0; i < count; i++) {
872 const char *name;
873 const bt_value *val;
874
875 bt_trace_class_borrow_environment_entry_by_index_const(
876 tc->ir_tc, i, &name, &val);
877 append_indent(&ctx);
878 g_string_append_printf(tsdl, "%s = ", name);
879
880 switch (bt_value_get_type(val)) {
881 case BT_VALUE_TYPE_SIGNED_INTEGER:
882 g_string_append_printf(tsdl, "%" PRId64,
883 bt_value_signed_integer_get(val));
884 break;
885 case BT_VALUE_TYPE_STRING:
886 append_quoted_string(&ctx, bt_value_string_get(val));
887 break;
888 default:
889 /*
890 * This is checked in
891 * translate_trace_class_trace_ir_to_ctf_ir().
892 */
893 abort();
894 }
895
896 g_string_append(tsdl, ";\n");
897 }
898
899 /* End trace class environment */
900 append_end_block_semi_nl_nl(&ctx);
901 }
902
903 /* Stream classes and their event classes */
904 for (i = 0; i < tc->stream_classes->len; i++) {
905 append_stream_class(&ctx, tc->stream_classes->pdata[i]);
906 }
907 }
This page took 0.04768 seconds and 3 git commands to generate.