lib: have dedicated, unique unsigned and signed enum FC mapping objects
[babeltrace.git] / plugins / ctf / fs-sink / translate-ctf-ir-to-tsdl.c
CommitLineData
46bdd3e0
PP
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
37struct ctx {
38 unsigned int indent_level;
39 GString *tsdl;
40};
41
42static inline
43void 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
52static
53void 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
75static
76void 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
120static
121void 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
128static
129void 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
179static
180void append_end_block(struct ctx *ctx)
181{
182 ctx->indent_level--;
183 append_indent(ctx);
184 g_string_append(ctx->tsdl, "}");
185}
186
187static
188void 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
195static
196void 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
202static
203void 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;
b6baf3bb
PP
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;
46bdd3e0
PP
233 uint64_t range_count;
234 uint64_t range_i;
235
236 if (is_signed) {
b6baf3bb
PP
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);
46bdd3e0 241 } else {
b6baf3bb
PP
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);
46bdd3e0
PP
246 }
247
b6baf3bb
PP
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
46bdd3e0
PP
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
b6baf3bb
PP
281 bt_field_class_signed_enumeration_mapping_get_range_by_index(
282 i_mapping, range_i,
46bdd3e0
PP
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
b6baf3bb
PP
297 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
298 u_mapping, range_i,
46bdd3e0
PP
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
320static
321void 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
339static
340void 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
346static
347void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
348
349static
350void 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
393static
394void 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
452static
453void 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
464static
465void 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
486static
487void 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
510static
511void 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
625static
626void 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->default_clock_class) {
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 append_indent(ctx);
720 append_integer_field_class_from_props(ctx, 64, 8, false,
721 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
722 sc->default_clock_class_name->str,
723 "timestamp_end", true);
724 }
725
726 append_indent(ctx);
727 append_integer_field_class_from_props(ctx, 64, 8, false,
728 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
729 NULL, "events_discarded", true);
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, "packet_seq_num", true);
734
735 if (sc->packet_context_fc) {
736 append_struct_field_class_members(ctx,
737 (void *) sc->packet_context_fc);
738 fs_sink_ctf_field_class_struct_align_at_least(
739 (void *) sc->packet_context_fc, 8);
740 }
741
742 /* End packet context field class */
743 append_end_block(ctx);
744 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
745 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
746
747 /* Event header field class */
748 append_indent(ctx);
749 g_string_append(ctx->tsdl, "event.header := struct {\n");
750 ctx->indent_level++;
751 append_indent(ctx);
752 append_integer_field_class_from_props(ctx, 64, 8, false,
753 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
754 NULL, "id", true);
755
756 if (sc->default_clock_class) {
757 append_indent(ctx);
758 append_integer_field_class_from_props(ctx, 64, 8, false,
759 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
760 sc->default_clock_class_name->str,
761 "timestamp", true);
762 }
763
764 /* End event header field class */
765 append_end_block(ctx);
766 g_string_append(ctx->tsdl, " align(8);\n");
767
768 /* Event common context field class */
769 if (sc->event_common_context_fc) {
770 append_indent(ctx);
771 g_string_append(ctx->tsdl, "event.context := ");
772 append_field_class(ctx,
773 (void *) sc->event_common_context_fc);
774 g_string_append(ctx->tsdl, ";\n");
775 }
776
777 /* End stream class */
778 append_end_block_semi_nl_nl(ctx);
779
780 /* Event classes */
781 for (i = 0; i < sc->event_classes->len; i++) {
782 append_event_class(ctx, sc->event_classes->pdata[i]);
783 }
784}
785
786BT_HIDDEN
787void translate_trace_class_ctf_ir_to_tsdl(struct fs_sink_ctf_trace_class *tc,
788 GString *tsdl)
789{
790 struct ctx ctx = {
791 .indent_level = 0,
792 .tsdl = tsdl,
793 };
794 uint64_t i;
795 uint64_t count;
796
797 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
798 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
799
800 /* Trace class */
801 append_indent(&ctx);
802 g_string_append(tsdl, "trace {\n");
803 ctx.indent_level++;
804
805 /* Trace class properties */
806 append_indent(&ctx);
807 g_string_append(tsdl, "major = 1;\n");
808 append_indent(&ctx);
809 g_string_append(tsdl, "minor = 8;\n");
810 append_indent(&ctx);
811 g_string_append(tsdl, "uuid = ");
812 append_uuid(&ctx, tc->uuid);
813 g_string_append(tsdl, ";\n");
814 append_indent(&ctx);
815 g_string_append(tsdl, "byte_order = ");
816
817 if (BYTE_ORDER == LITTLE_ENDIAN) {
818 g_string_append(tsdl, "le");
819 } else {
820 g_string_append(tsdl, "be");
821 }
822
823 g_string_append(tsdl, ";\n");
824
825 /* Packet header field class */
826 append_indent(&ctx);
827 g_string_append(tsdl, "packet.header := struct {\n");
828 ctx.indent_level++;
829 append_indent(&ctx);
830 append_integer_field_class_from_props(&ctx, 32, 8, false,
831 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
832 NULL, "magic", true);
833 append_indent(&ctx);
834 append_integer_field_class_from_props(&ctx, 8, 8, false,
835 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
836 NULL, "uuid[16]", true);
837 append_indent(&ctx);
838 append_integer_field_class_from_props(&ctx, 64, 8, false,
839 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
840 NULL, "stream_id", true);
841 append_indent(&ctx);
842 append_integer_field_class_from_props(&ctx, 64, 8, false,
843 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
844 NULL, "stream_instance_id", true);
845
846 /* End packet header field class */
847 append_end_block(&ctx);
848 g_string_append(ctx.tsdl, " align(8);\n");
849
850 /* End trace class */
851 append_end_block_semi_nl_nl(&ctx);
852
853 /* Trace class environment */
854 count = bt_trace_class_get_environment_entry_count(tc->ir_tc);
855 if (count > 0) {
856 append_indent(&ctx);
857 g_string_append(tsdl, "env {\n");
858 ctx.indent_level++;
859
860 for (i = 0; i < count; i++) {
861 const char *name;
862 const bt_value *val;
863
864 bt_trace_class_borrow_environment_entry_by_index_const(
865 tc->ir_tc, i, &name, &val);
866 append_indent(&ctx);
867 g_string_append_printf(tsdl, "%s = ", name);
868
869 switch (bt_value_get_type(val)) {
870 case BT_VALUE_TYPE_INTEGER:
871 g_string_append_printf(tsdl, "%" PRId64,
872 bt_value_integer_get(val));
873 break;
874 case BT_VALUE_TYPE_STRING:
875 append_quoted_string(&ctx, bt_value_string_get(val));
876 break;
877 default:
878 /*
879 * This is checked in
880 * translate_trace_class_trace_ir_to_ctf_ir().
881 */
882 abort();
883 }
884
885 g_string_append(tsdl, ";\n");
886 }
887
888 /* End trace class environment */
889 append_end_block_semi_nl_nl(&ctx);
890 }
891
892 /* Stream classes and their event classes */
893 for (i = 0; i < tc->stream_classes->len; i++) {
894 append_stream_class(&ctx, tc->stream_classes->pdata[i]);
895 }
896}
This page took 0.05563 seconds and 4 git commands to generate.