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