fef1d040076cd33ed39eacbe7a5994ae99707c0a
[babeltrace.git] / 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 <babeltrace/babeltrace.h>
27 #include <babeltrace/babeltrace-internal.h>
28 #include <stdio.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <glib.h>
32 #include <babeltrace/assert-internal.h>
33 #include <babeltrace/endian-internal.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_unsigned_enumeration_mapping_ranges *u_ranges;
231 const bt_field_class_signed_enumeration_mapping_ranges *i_ranges;
232 uint64_t range_count;
233 uint64_t range_i;
234
235 if (is_signed) {
236 bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
237 ir_fc, i, &label, &i_ranges);
238 range_count = bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
239 i_ranges);
240 } else {
241 bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
242 ir_fc, i, &label, &u_ranges);
243 range_count = bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
244 u_ranges);
245 }
246
247 for (range_i = 0; range_i < range_count; range_i++) {
248 append_indent(ctx);
249
250 /*
251 * Systematically prepend `_` to the
252 * mapping's label as this could be used
253 * as the tag of a subsequent variant
254 * field class and variant FC option
255 * names are systematically protected
256 * with a leading `_`.
257 *
258 * FIXME: This is temporary as the
259 * library's API should change to
260 * decouple variant FC option names from
261 * selector FC labels. The current
262 * drawback is that an original label
263 * `HELLO` becomes `_HELLO` in the
264 * generated metadata, therefore tools
265 * expecting `HELLO` could fail.
266 */
267 g_string_append(ctx->tsdl, "\"_");
268 append_quoted_string_content(ctx, label);
269 g_string_append(ctx->tsdl, "\" = ");
270
271 if (is_signed) {
272 int64_t lower, upper;
273
274 bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
275 i_ranges, range_i,
276 &lower, &upper);
277
278 if (lower == upper) {
279 g_string_append_printf(
280 ctx->tsdl, "%" PRId64,
281 lower);
282 } else {
283 g_string_append_printf(
284 ctx->tsdl, "%" PRId64 " ... %" PRId64,
285 lower, upper);
286 }
287 } else {
288 uint64_t lower, upper;
289
290 bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
291 u_ranges, range_i,
292 &lower, &upper);
293
294 if (lower == upper) {
295 g_string_append_printf(
296 ctx->tsdl, "%" PRIu64,
297 lower);
298 } else {
299 g_string_append_printf(
300 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
301 lower, upper);
302 }
303 }
304
305 g_string_append(ctx->tsdl, ",\n");
306 }
307 }
308
309 append_end_block(ctx);
310 }
311 }
312
313 static
314 void append_float_field_class(struct ctx *ctx,
315 struct fs_sink_ctf_field_class_float *fc)
316 {
317 unsigned int mant_dig, exp_dig;
318
319 if (bt_field_class_real_is_single_precision(fc->base.base.ir_fc)) {
320 mant_dig = 24;
321 exp_dig = 8;
322 } else {
323 mant_dig = 53;
324 exp_dig = 11;
325 }
326
327 g_string_append_printf(ctx->tsdl,
328 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
329 mant_dig, exp_dig, fc->base.base.alignment);
330 }
331
332 static
333 void append_string_field_class(struct ctx *ctx,
334 struct fs_sink_ctf_field_class_float *fc)
335 {
336 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
337 }
338
339 static
340 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
341
342 static
343 void append_member(struct ctx *ctx, const char *name,
344 struct fs_sink_ctf_field_class *fc)
345 {
346 GString *lengths = NULL;
347 const char *lengths_str = "";
348
349 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
350 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
351 if (!lengths) {
352 lengths = g_string_new(NULL);
353 BT_ASSERT(lengths);
354 }
355
356 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
357 struct fs_sink_ctf_field_class_array *array_fc =
358 (void *) fc;
359
360 g_string_append_printf(lengths, "[%" PRIu64 "]",
361 array_fc->length);
362 fc = array_fc->base.elem_fc;
363 } else {
364 struct fs_sink_ctf_field_class_sequence *seq_fc =
365 (void *) fc;
366
367 g_string_append_printf(lengths, "[%s]",
368 seq_fc->length_ref->str);
369 fc = seq_fc->base.elem_fc;
370 }
371 }
372
373 append_field_class(ctx, fc);
374
375 if (lengths) {
376 lengths_str = lengths->str;
377 }
378
379 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
380
381 if (lengths) {
382 g_string_free(lengths, TRUE);
383 }
384 }
385
386 static
387 void append_struct_field_class_members(struct ctx *ctx,
388 struct fs_sink_ctf_field_class_struct *struct_fc)
389 {
390 uint64_t i;
391
392 for (i = 0; i < struct_fc->members->len; i++) {
393 struct fs_sink_ctf_named_field_class *named_fc =
394 fs_sink_ctf_field_class_struct_borrow_member_by_index(
395 struct_fc, i);
396 struct fs_sink_ctf_field_class *fc = named_fc->fc;
397
398 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
399 struct fs_sink_ctf_field_class_sequence *seq_fc =
400 (void *) fc;
401
402 if (seq_fc->length_is_before) {
403 append_indent(ctx);
404 append_integer_field_class_from_props(ctx,
405 32, 8, false,
406 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
407 NULL, seq_fc->length_ref->str, true);
408 }
409 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
410 struct fs_sink_ctf_field_class_variant *var_fc =
411 (void *) fc;
412
413 if (var_fc->tag_is_before) {
414 append_indent(ctx);
415 g_string_append(ctx->tsdl, "enum : ");
416 append_integer_field_class_from_props(ctx,
417 16, 8, false,
418 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
419 NULL, NULL, false);
420 g_string_append(ctx->tsdl, " {\n");
421 ctx->indent_level++;
422
423 for (i = 0; i < var_fc->options->len; i++) {
424 struct fs_sink_ctf_named_field_class *named_fc =
425 fs_sink_ctf_field_class_variant_borrow_option_by_index(
426 var_fc, i);
427
428 append_indent(ctx);
429 g_string_append_printf(ctx->tsdl,
430 "\"%s\" = %" PRIu64 ",\n",
431 named_fc->name->str, i);
432 }
433
434 append_end_block(ctx);
435 g_string_append_printf(ctx->tsdl, " %s;\n",
436 var_fc->tag_ref->str);
437 }
438 }
439
440 append_indent(ctx);
441 append_member(ctx, named_fc->name->str, fc);
442 }
443 }
444
445 static
446 void append_struct_field_class(struct ctx *ctx,
447 struct fs_sink_ctf_field_class_struct *fc)
448 {
449 g_string_append(ctx->tsdl, "struct {\n");
450 ctx->indent_level++;
451 append_struct_field_class_members(ctx, fc);
452 append_end_block(ctx);
453 g_string_append_printf(ctx->tsdl, " align(%u)",
454 fc->base.alignment);
455 }
456
457 static
458 void append_variant_field_class(struct ctx *ctx,
459 struct fs_sink_ctf_field_class_variant *var_fc)
460 {
461 uint64_t i;
462
463 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
464 var_fc->tag_ref->str);
465 ctx->indent_level++;
466
467 for (i = 0; i < var_fc->options->len; i++) {
468 struct fs_sink_ctf_named_field_class *named_fc =
469 fs_sink_ctf_field_class_variant_borrow_option_by_index(
470 var_fc, i);
471
472 append_indent(ctx);
473 append_member(ctx, named_fc->name->str, named_fc->fc);
474 }
475
476 append_end_block(ctx);
477 }
478
479 static
480 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
481 {
482 switch (fc->type) {
483 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
484 append_integer_field_class(ctx, (void *) fc);
485 break;
486 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
487 append_float_field_class(ctx, (void *) fc);
488 break;
489 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
490 append_string_field_class(ctx, (void *) fc);
491 break;
492 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
493 append_struct_field_class(ctx, (void *) fc);
494 break;
495 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
496 append_variant_field_class(ctx, (void *) fc);
497 break;
498 default:
499 abort();
500 }
501 }
502
503 static
504 void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
505 {
506 const char *str;
507 bt_event_class_log_level log_level;
508
509 /* Event class */
510 append_indent(ctx);
511 g_string_append(ctx->tsdl, "event {\n");
512 ctx->indent_level++;
513
514 /* Event class properties */
515 append_indent(ctx);
516 g_string_append(ctx->tsdl, "name = ");
517 str = bt_event_class_get_name(ec->ir_ec);
518 if (!str) {
519 str = "unknown";
520 }
521
522 append_quoted_string(ctx, str);
523 g_string_append(ctx->tsdl, ";\n");
524 append_indent(ctx);
525 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
526 bt_stream_class_get_id(ec->sc->ir_sc));
527 append_indent(ctx);
528 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
529 bt_event_class_get_id(ec->ir_ec));
530
531 str = bt_event_class_get_emf_uri(ec->ir_ec);
532 if (str) {
533 append_indent(ctx);
534 g_string_append(ctx->tsdl, "model.emf.uri = ");
535 append_quoted_string(ctx, str);
536 g_string_append(ctx->tsdl, ";\n");
537 }
538
539 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
540 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
541 unsigned int level;
542
543 append_indent(ctx);
544 g_string_append(ctx->tsdl, "loglevel = ");
545
546 switch (log_level) {
547 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
548 level = 0;
549 break;
550 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
551 level = 1;
552 break;
553 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
554 level = 2;
555 break;
556 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
557 level = 3;
558 break;
559 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
560 level = 4;
561 break;
562 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
563 level = 5;
564 break;
565 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
566 level = 6;
567 break;
568 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
569 level = 7;
570 break;
571 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
572 level = 8;
573 break;
574 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
575 level = 9;
576 break;
577 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
578 level = 10;
579 break;
580 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
581 level = 11;
582 break;
583 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
584 level = 12;
585 break;
586 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
587 level = 13;
588 break;
589 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
590 level = 14;
591 break;
592 default:
593 abort();
594 }
595
596 g_string_append_printf(ctx->tsdl, "%u;\n", level);
597 }
598
599 /* Event specific context field class */
600 if (ec->spec_context_fc) {
601 append_indent(ctx);
602 g_string_append(ctx->tsdl, "context := ");
603 append_field_class(ctx, ec->spec_context_fc);
604 g_string_append(ctx->tsdl, ";\n");
605 }
606
607 /* Event payload field class */
608 if (ec->payload_fc) {
609 append_indent(ctx);
610 g_string_append(ctx->tsdl, "fields := ");
611 append_field_class(ctx, ec->payload_fc);
612 g_string_append(ctx->tsdl, ";\n");
613 }
614
615 append_end_block_semi_nl_nl(ctx);
616 }
617
618 static
619 void append_stream_class(struct ctx *ctx,
620 struct fs_sink_ctf_stream_class *sc)
621 {
622 uint64_t i;
623
624 /* Default clock class */
625 if (sc->default_clock_class) {
626 const char *descr;
627 int64_t offset_seconds;
628 uint64_t offset_cycles;
629 bt_uuid uuid;
630
631 append_indent(ctx);
632 g_string_append(ctx->tsdl, "clock {\n");
633 ctx->indent_level++;
634 BT_ASSERT(sc->default_clock_class_name->len > 0);
635 append_indent(ctx);
636 g_string_append_printf(ctx->tsdl, "name = %s;\n",
637 sc->default_clock_class_name->str);
638 descr = bt_clock_class_get_description(sc->default_clock_class);
639 if (descr) {
640 append_indent(ctx);
641 g_string_append(ctx->tsdl, "description = ");
642 append_quoted_string(ctx, descr);
643 g_string_append(ctx->tsdl, ";\n");
644 }
645
646 append_indent(ctx);
647 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
648 bt_clock_class_get_frequency(sc->default_clock_class));
649 append_indent(ctx);
650 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
651 bt_clock_class_get_precision(sc->default_clock_class));
652 bt_clock_class_get_offset(sc->default_clock_class,
653 &offset_seconds, &offset_cycles);
654 append_indent(ctx);
655 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
656 offset_seconds);
657 append_indent(ctx);
658 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
659 offset_cycles);
660 append_indent(ctx);
661 g_string_append(ctx->tsdl, "absolute = ");
662
663 if (bt_clock_class_origin_is_unix_epoch(
664 sc->default_clock_class)) {
665 g_string_append(ctx->tsdl, "true");
666 } else {
667 g_string_append(ctx->tsdl, "false");
668 }
669
670 g_string_append(ctx->tsdl, ";\n");
671 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
672 if (uuid) {
673 append_indent(ctx);
674 g_string_append(ctx->tsdl, "uuid = ");
675 append_uuid(ctx, uuid);
676 g_string_append(ctx->tsdl, ";\n");
677 }
678
679 /* End clock class */
680 append_end_block_semi_nl_nl(ctx);
681 }
682
683 /* Stream class */
684 append_indent(ctx);
685 g_string_append(ctx->tsdl, "stream {\n");
686 ctx->indent_level++;
687
688 /* Stream class properties */
689 append_indent(ctx);
690 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
691 bt_stream_class_get_id(sc->ir_sc));
692
693 /* Packet context field class */
694 append_indent(ctx);
695 g_string_append(ctx->tsdl, "packet.context := struct {\n");
696 ctx->indent_level++;
697 append_indent(ctx);
698 append_integer_field_class_from_props(ctx, 64, 8, false,
699 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
700 NULL, "packet_size", true);
701 append_indent(ctx);
702 append_integer_field_class_from_props(ctx, 64, 8, false,
703 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
704 NULL, "content_size", true);
705
706 if (sc->default_clock_class) {
707 append_indent(ctx);
708 append_integer_field_class_from_props(ctx, 64, 8, false,
709 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
710 sc->default_clock_class_name->str,
711 "timestamp_begin", true);
712 append_indent(ctx);
713 append_integer_field_class_from_props(ctx, 64, 8, false,
714 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
715 sc->default_clock_class_name->str,
716 "timestamp_end", true);
717 }
718
719 append_indent(ctx);
720 append_integer_field_class_from_props(ctx, 64, 8, false,
721 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
722 NULL, "events_discarded", true);
723 append_indent(ctx);
724 append_integer_field_class_from_props(ctx, 64, 8, false,
725 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
726 NULL, "packet_seq_num", true);
727
728 if (sc->packet_context_fc) {
729 append_struct_field_class_members(ctx,
730 (void *) sc->packet_context_fc);
731 fs_sink_ctf_field_class_struct_align_at_least(
732 (void *) sc->packet_context_fc, 8);
733 }
734
735 /* End packet context field class */
736 append_end_block(ctx);
737 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
738 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
739
740 /* Event header field class */
741 append_indent(ctx);
742 g_string_append(ctx->tsdl, "event.header := struct {\n");
743 ctx->indent_level++;
744 append_indent(ctx);
745 append_integer_field_class_from_props(ctx, 64, 8, false,
746 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
747 NULL, "id", true);
748
749 if (sc->default_clock_class) {
750 append_indent(ctx);
751 append_integer_field_class_from_props(ctx, 64, 8, false,
752 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
753 sc->default_clock_class_name->str,
754 "timestamp", true);
755 }
756
757 /* End event header field class */
758 append_end_block(ctx);
759 g_string_append(ctx->tsdl, " align(8);\n");
760
761 /* Event common context field class */
762 if (sc->event_common_context_fc) {
763 append_indent(ctx);
764 g_string_append(ctx->tsdl, "event.context := ");
765 append_field_class(ctx,
766 (void *) sc->event_common_context_fc);
767 g_string_append(ctx->tsdl, ";\n");
768 }
769
770 /* End stream class */
771 append_end_block_semi_nl_nl(ctx);
772
773 /* Event classes */
774 for (i = 0; i < sc->event_classes->len; i++) {
775 append_event_class(ctx, sc->event_classes->pdata[i]);
776 }
777 }
778
779 BT_HIDDEN
780 void translate_trace_class_ctf_ir_to_tsdl(struct fs_sink_ctf_trace_class *tc,
781 GString *tsdl)
782 {
783 struct ctx ctx = {
784 .indent_level = 0,
785 .tsdl = tsdl,
786 };
787 uint64_t i;
788 uint64_t count;
789
790 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
791 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
792
793 /* Trace class */
794 append_indent(&ctx);
795 g_string_append(tsdl, "trace {\n");
796 ctx.indent_level++;
797
798 /* Trace class properties */
799 append_indent(&ctx);
800 g_string_append(tsdl, "major = 1;\n");
801 append_indent(&ctx);
802 g_string_append(tsdl, "minor = 8;\n");
803 append_indent(&ctx);
804 g_string_append(tsdl, "uuid = ");
805 append_uuid(&ctx, tc->uuid);
806 g_string_append(tsdl, ";\n");
807 append_indent(&ctx);
808 g_string_append(tsdl, "byte_order = ");
809
810 if (BYTE_ORDER == LITTLE_ENDIAN) {
811 g_string_append(tsdl, "le");
812 } else {
813 g_string_append(tsdl, "be");
814 }
815
816 g_string_append(tsdl, ";\n");
817
818 /* Packet header field class */
819 append_indent(&ctx);
820 g_string_append(tsdl, "packet.header := struct {\n");
821 ctx.indent_level++;
822 append_indent(&ctx);
823 append_integer_field_class_from_props(&ctx, 32, 8, false,
824 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
825 NULL, "magic", true);
826 append_indent(&ctx);
827 append_integer_field_class_from_props(&ctx, 8, 8, false,
828 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
829 NULL, "uuid[16]", true);
830 append_indent(&ctx);
831 append_integer_field_class_from_props(&ctx, 64, 8, false,
832 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
833 NULL, "stream_id", true);
834 append_indent(&ctx);
835 append_integer_field_class_from_props(&ctx, 64, 8, false,
836 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
837 NULL, "stream_instance_id", true);
838
839 /* End packet header field class */
840 append_end_block(&ctx);
841 g_string_append(ctx.tsdl, " align(8);\n");
842
843 /* End trace class */
844 append_end_block_semi_nl_nl(&ctx);
845
846 /* Trace class environment */
847 count = bt_trace_class_get_environment_entry_count(tc->ir_tc);
848 if (count > 0) {
849 append_indent(&ctx);
850 g_string_append(tsdl, "env {\n");
851 ctx.indent_level++;
852
853 for (i = 0; i < count; i++) {
854 const char *name;
855 const bt_value *val;
856
857 bt_trace_class_borrow_environment_entry_by_index_const(
858 tc->ir_tc, i, &name, &val);
859 append_indent(&ctx);
860 g_string_append_printf(tsdl, "%s = ", name);
861
862 switch (bt_value_get_type(val)) {
863 case BT_VALUE_TYPE_INTEGER:
864 g_string_append_printf(tsdl, "%" PRId64,
865 bt_value_integer_get(val));
866 break;
867 case BT_VALUE_TYPE_STRING:
868 append_quoted_string(&ctx, bt_value_string_get(val));
869 break;
870 default:
871 /*
872 * This is checked in
873 * translate_trace_class_trace_ir_to_ctf_ir().
874 */
875 abort();
876 }
877
878 g_string_append(tsdl, ";\n");
879 }
880
881 /* End trace class environment */
882 append_end_block_semi_nl_nl(&ctx);
883 }
884
885 /* Stream classes and their event classes */
886 for (i = 0; i < tc->stream_classes->len; i++) {
887 append_stream_class(&ctx, tc->stream_classes->pdata[i]);
888 }
889 }
This page took 0.04805 seconds and 3 git commands to generate.