Fix: shadowed variables
[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);
ebdb6693
PP
219 bool is_signed = bt_field_class_type_is(type,
220 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
15fe47e0 221
ebdb6693 222 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
15fe47e0
PP
223 g_string_append(ctx->tsdl, "enum : ");
224 }
225
226 append_integer_field_class_from_props(ctx, fc->base.size,
227 fc->base.base.alignment, is_signed,
228 bt_field_class_integer_get_preferred_display_base(ir_fc),
229 NULL, NULL, false);
230
ebdb6693 231 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
15fe47e0
PP
232 uint64_t i;
233
234 g_string_append(ctx->tsdl, " {\n");
235 ctx->indent_level++;
236
237 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_fc); i++) {
238 const char *label;
8f3ccfbc 239 const bt_field_class_enumeration_mapping *mapping;
9c08c816
PP
240 const bt_field_class_enumeration_unsigned_mapping *u_mapping;
241 const bt_field_class_enumeration_signed_mapping *s_mapping;
45c51519
PP
242 const bt_integer_range_set *ranges;
243 const bt_integer_range_set_unsigned *u_ranges;
244 const bt_integer_range_set_signed *s_ranges;
15fe47e0
PP
245 uint64_t range_count;
246 uint64_t range_i;
247
248 if (is_signed) {
9c08c816 249 s_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
8f3ccfbc 250 ir_fc, i);
9c08c816 251 mapping = bt_field_class_enumeration_signed_mapping_as_mapping_const(
45c51519 252 s_mapping);
9c08c816 253 s_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
45c51519
PP
254 s_mapping);
255 ranges = bt_integer_range_set_signed_as_range_set_const(
256 s_ranges);
15fe47e0 257 } else {
9c08c816 258 u_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
8f3ccfbc 259 ir_fc, i);
9c08c816 260 mapping = bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
8f3ccfbc 261 u_mapping);
9c08c816 262 u_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
45c51519
PP
263 u_mapping);
264 ranges = bt_integer_range_set_unsigned_as_range_set_const(
265 u_ranges);
15fe47e0
PP
266 }
267
8f3ccfbc
PP
268 label = bt_field_class_enumeration_mapping_get_label(
269 mapping);
45c51519
PP
270 range_count = bt_integer_range_set_get_range_count(
271 ranges);
8f3ccfbc 272
15fe47e0
PP
273 for (range_i = 0; range_i < range_count; range_i++) {
274 append_indent(ctx);
45c51519 275 g_string_append(ctx->tsdl, "\"");
15fe47e0
PP
276 append_quoted_string_content(ctx, label);
277 g_string_append(ctx->tsdl, "\" = ");
278
279 if (is_signed) {
45c51519 280 const bt_integer_range_signed *range;
15fe47e0
PP
281 int64_t lower, upper;
282
45c51519
PP
283 range = bt_integer_range_set_signed_borrow_range_by_index_const(
284 s_ranges, range_i);
285 lower = bt_integer_range_signed_get_lower(
286 range);
287 upper = bt_integer_range_signed_get_upper(
288 range);
15fe47e0
PP
289
290 if (lower == upper) {
291 g_string_append_printf(
292 ctx->tsdl, "%" PRId64,
293 lower);
294 } else {
295 g_string_append_printf(
296 ctx->tsdl, "%" PRId64 " ... %" PRId64,
297 lower, upper);
298 }
299 } else {
45c51519 300 const bt_integer_range_unsigned *range;
15fe47e0
PP
301 uint64_t lower, upper;
302
45c51519
PP
303 range = bt_integer_range_set_unsigned_borrow_range_by_index_const(
304 u_ranges, range_i);
305 lower = bt_integer_range_unsigned_get_lower(
306 range);
307 upper = bt_integer_range_unsigned_get_upper(
308 range);
15fe47e0
PP
309
310 if (lower == upper) {
311 g_string_append_printf(
312 ctx->tsdl, "%" PRIu64,
313 lower);
314 } else {
315 g_string_append_printf(
316 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
317 lower, upper);
318 }
319 }
320
321 g_string_append(ctx->tsdl, ",\n");
322 }
323 }
324
325 append_end_block(ctx);
326 }
327}
328
329static
330void append_float_field_class(struct ctx *ctx,
331 struct fs_sink_ctf_field_class_float *fc)
332{
333 unsigned int mant_dig, exp_dig;
334
ebdb6693
PP
335 if (bt_field_class_get_type(fc->base.base.ir_fc) ==
336 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) {
15fe47e0
PP
337 mant_dig = 24;
338 exp_dig = 8;
339 } else {
340 mant_dig = 53;
341 exp_dig = 11;
342 }
343
344 g_string_append_printf(ctx->tsdl,
345 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
346 mant_dig, exp_dig, fc->base.base.alignment);
347}
348
349static
350void append_string_field_class(struct ctx *ctx,
351 struct fs_sink_ctf_field_class_float *fc)
352{
353 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
354}
355
356static
357void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
358
359static
360void append_member(struct ctx *ctx, const char *name,
361 struct fs_sink_ctf_field_class *fc)
362{
363 GString *lengths = NULL;
364 const char *lengths_str = "";
365
c25f8e53
PP
366 BT_ASSERT(fc);
367
15fe47e0
PP
368 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
369 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
370 if (!lengths) {
371 lengths = g_string_new(NULL);
372 BT_ASSERT(lengths);
373 }
374
375 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
376 struct fs_sink_ctf_field_class_array *array_fc =
377 (void *) fc;
378
379 g_string_append_printf(lengths, "[%" PRIu64 "]",
380 array_fc->length);
381 fc = array_fc->base.elem_fc;
382 } else {
383 struct fs_sink_ctf_field_class_sequence *seq_fc =
384 (void *) fc;
385
386 g_string_append_printf(lengths, "[%s]",
387 seq_fc->length_ref->str);
388 fc = seq_fc->base.elem_fc;
389 }
390 }
391
392 append_field_class(ctx, fc);
393
394 if (lengths) {
395 lengths_str = lengths->str;
396 }
397
398 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
399
400 if (lengths) {
401 g_string_free(lengths, TRUE);
402 }
403}
404
405static
406void append_struct_field_class_members(struct ctx *ctx,
407 struct fs_sink_ctf_field_class_struct *struct_fc)
408{
409 uint64_t i;
410
411 for (i = 0; i < struct_fc->members->len; i++) {
412 struct fs_sink_ctf_named_field_class *named_fc =
413 fs_sink_ctf_field_class_struct_borrow_member_by_index(
414 struct_fc, i);
415 struct fs_sink_ctf_field_class *fc = named_fc->fc;
416
c25f8e53
PP
417 /*
418 * For sequence, option, and variant field classes, if
419 * the length/tag field class is generated before, write
420 * it now before the dependent field class.
421 */
15fe47e0
PP
422 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
423 struct fs_sink_ctf_field_class_sequence *seq_fc =
424 (void *) fc;
425
426 if (seq_fc->length_is_before) {
427 append_indent(ctx);
428 append_integer_field_class_from_props(ctx,
429 32, 8, false,
430 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
431 NULL, seq_fc->length_ref->str, true);
432 }
c25f8e53
PP
433 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION) {
434 struct fs_sink_ctf_field_class_option *opt_fc =
435 (void *) fc;
436
437 /*
438 * CTF 1.8 does not support the option field
439 * class type. To write something anyway, this
440 * component translates this type to a variant
441 * field class where the options are:
442 *
443 * * An empty structure field class.
444 * * The optional field class itself.
445 *
446 * The "tag" is always generated/before in that
447 * case (an 8-bit unsigned enumeration field
448 * class).
449 */
450 append_indent(ctx);
451 g_string_append(ctx->tsdl,
452 "/* The enumeration and variant field classes "
453 "below were a trace IR option field class. */\n");
454 append_indent(ctx);
455 g_string_append(ctx->tsdl, "enum : ");
456 append_integer_field_class_from_props(ctx,
457 8, 8, false,
458 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
459 NULL, NULL, false);
460 g_string_append(ctx->tsdl, " {\n");
461 ctx->indent_level++;
462 append_indent(ctx);
463 g_string_append(ctx->tsdl, "none = 0,\n");
464 append_indent(ctx);
465 g_string_append(ctx->tsdl, "content = 1,\n");
466 append_end_block(ctx);
467 g_string_append_printf(ctx->tsdl, " %s;\n",
468 opt_fc->tag_ref->str);
15fe47e0
PP
469 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
470 struct fs_sink_ctf_field_class_variant *var_fc =
471 (void *) fc;
472
473 if (var_fc->tag_is_before) {
474 append_indent(ctx);
475 g_string_append(ctx->tsdl, "enum : ");
476 append_integer_field_class_from_props(ctx,
477 16, 8, false,
478 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
479 NULL, NULL, false);
480 g_string_append(ctx->tsdl, " {\n");
481 ctx->indent_level++;
482
483 for (i = 0; i < var_fc->options->len; i++) {
50233236 484 struct fs_sink_ctf_named_field_class *option_named_fc =
15fe47e0
PP
485 fs_sink_ctf_field_class_variant_borrow_option_by_index(
486 var_fc, i);
487
488 append_indent(ctx);
489 g_string_append_printf(ctx->tsdl,
490 "\"%s\" = %" PRIu64 ",\n",
50233236 491 option_named_fc->name->str, i);
15fe47e0
PP
492 }
493
494 append_end_block(ctx);
495 g_string_append_printf(ctx->tsdl, " %s;\n",
496 var_fc->tag_ref->str);
497 }
ecd27ae4
PP
498 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL) {
499 append_indent(ctx);
500 g_string_append(ctx->tsdl,
501 "/* The integer field class below was a trace IR boolean field class. */\n");
43a94dc9
PP
502 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY) {
503 append_indent(ctx);
504 g_string_append(ctx->tsdl,
505 "/* The integer field class below was a trace IR bit array field class. */\n");
15fe47e0
PP
506 }
507
508 append_indent(ctx);
509 append_member(ctx, named_fc->name->str, fc);
510 }
511}
512
513static
514void append_struct_field_class(struct ctx *ctx,
515 struct fs_sink_ctf_field_class_struct *fc)
516{
517 g_string_append(ctx->tsdl, "struct {\n");
518 ctx->indent_level++;
519 append_struct_field_class_members(ctx, fc);
520 append_end_block(ctx);
521 g_string_append_printf(ctx->tsdl, " align(%u)",
522 fc->base.alignment);
523}
524
c25f8e53
PP
525static
526void append_option_field_class(struct ctx *ctx,
527 struct fs_sink_ctf_field_class_option *opt_fc)
528{
529 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
530 opt_fc->tag_ref->str);
531 ctx->indent_level++;
532 append_indent(ctx);
533 g_string_append(ctx->tsdl, "struct { } none;\n");
534 append_indent(ctx);
535 append_member(ctx, "content", opt_fc->content_fc);
536 append_end_block(ctx);
537}
538
15fe47e0
PP
539static
540void append_variant_field_class(struct ctx *ctx,
541 struct fs_sink_ctf_field_class_variant *var_fc)
542{
543 uint64_t i;
544
545 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
546 var_fc->tag_ref->str);
547 ctx->indent_level++;
548
549 for (i = 0; i < var_fc->options->len; i++) {
550 struct fs_sink_ctf_named_field_class *named_fc =
551 fs_sink_ctf_field_class_variant_borrow_option_by_index(
552 var_fc, i);
553
554 append_indent(ctx);
555 append_member(ctx, named_fc->name->str, named_fc->fc);
556 }
557
558 append_end_block(ctx);
559}
560
561static
562void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
563{
564 switch (fc->type) {
ecd27ae4
PP
565 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL:
566 append_bool_field_class(ctx, (void *) fc);
567 break;
43a94dc9
PP
568 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY:
569 append_bit_array_field_class(ctx, (void *) fc);
570 break;
15fe47e0
PP
571 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
572 append_integer_field_class(ctx, (void *) fc);
573 break;
574 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
575 append_float_field_class(ctx, (void *) fc);
576 break;
577 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
578 append_string_field_class(ctx, (void *) fc);
579 break;
580 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
581 append_struct_field_class(ctx, (void *) fc);
582 break;
c25f8e53
PP
583 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
584 append_option_field_class(ctx, (void *) fc);
585 break;
15fe47e0
PP
586 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
587 append_variant_field_class(ctx, (void *) fc);
588 break;
589 default:
590 abort();
591 }
592}
593
594static
595void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
596{
597 const char *str;
598 bt_event_class_log_level log_level;
599
600 /* Event class */
601 append_indent(ctx);
602 g_string_append(ctx->tsdl, "event {\n");
603 ctx->indent_level++;
604
605 /* Event class properties */
606 append_indent(ctx);
607 g_string_append(ctx->tsdl, "name = ");
608 str = bt_event_class_get_name(ec->ir_ec);
609 if (!str) {
610 str = "unknown";
611 }
612
613 append_quoted_string(ctx, str);
614 g_string_append(ctx->tsdl, ";\n");
615 append_indent(ctx);
616 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
617 bt_stream_class_get_id(ec->sc->ir_sc));
618 append_indent(ctx);
619 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
620 bt_event_class_get_id(ec->ir_ec));
621
622 str = bt_event_class_get_emf_uri(ec->ir_ec);
623 if (str) {
624 append_indent(ctx);
625 g_string_append(ctx->tsdl, "model.emf.uri = ");
626 append_quoted_string(ctx, str);
627 g_string_append(ctx->tsdl, ";\n");
628 }
629
630 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
631 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
632 unsigned int level;
633
634 append_indent(ctx);
635 g_string_append(ctx->tsdl, "loglevel = ");
636
637 switch (log_level) {
638 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
639 level = 0;
640 break;
641 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
642 level = 1;
643 break;
644 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
645 level = 2;
646 break;
647 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
648 level = 3;
649 break;
650 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
651 level = 4;
652 break;
653 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
654 level = 5;
655 break;
656 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
657 level = 6;
658 break;
659 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
660 level = 7;
661 break;
662 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
663 level = 8;
664 break;
665 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
666 level = 9;
667 break;
668 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
669 level = 10;
670 break;
671 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
672 level = 11;
673 break;
674 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
675 level = 12;
676 break;
677 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
678 level = 13;
679 break;
680 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
681 level = 14;
682 break;
683 default:
684 abort();
685 }
686
687 g_string_append_printf(ctx->tsdl, "%u;\n", level);
688 }
689
690 /* Event specific context field class */
691 if (ec->spec_context_fc) {
692 append_indent(ctx);
693 g_string_append(ctx->tsdl, "context := ");
694 append_field_class(ctx, ec->spec_context_fc);
695 g_string_append(ctx->tsdl, ";\n");
696 }
697
698 /* Event payload field class */
699 if (ec->payload_fc) {
700 append_indent(ctx);
701 g_string_append(ctx->tsdl, "fields := ");
702 append_field_class(ctx, ec->payload_fc);
703 g_string_append(ctx->tsdl, ";\n");
704 }
705
706 append_end_block_semi_nl_nl(ctx);
707}
708
709static
710void append_stream_class(struct ctx *ctx,
711 struct fs_sink_ctf_stream_class *sc)
712{
713 uint64_t i;
714
715 /* Default clock class */
716 if (sc->default_clock_class) {
717 const char *descr;
718 int64_t offset_seconds;
719 uint64_t offset_cycles;
720 bt_uuid uuid;
721
722 append_indent(ctx);
723 g_string_append(ctx->tsdl, "clock {\n");
724 ctx->indent_level++;
725 BT_ASSERT(sc->default_clock_class_name->len > 0);
726 append_indent(ctx);
727 g_string_append_printf(ctx->tsdl, "name = %s;\n",
728 sc->default_clock_class_name->str);
729 descr = bt_clock_class_get_description(sc->default_clock_class);
730 if (descr) {
731 append_indent(ctx);
732 g_string_append(ctx->tsdl, "description = ");
733 append_quoted_string(ctx, descr);
734 g_string_append(ctx->tsdl, ";\n");
735 }
736
737 append_indent(ctx);
738 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
739 bt_clock_class_get_frequency(sc->default_clock_class));
740 append_indent(ctx);
741 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
742 bt_clock_class_get_precision(sc->default_clock_class));
743 bt_clock_class_get_offset(sc->default_clock_class,
744 &offset_seconds, &offset_cycles);
745 append_indent(ctx);
746 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
747 offset_seconds);
748 append_indent(ctx);
749 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
750 offset_cycles);
751 append_indent(ctx);
752 g_string_append(ctx->tsdl, "absolute = ");
753
754 if (bt_clock_class_origin_is_unix_epoch(
755 sc->default_clock_class)) {
756 g_string_append(ctx->tsdl, "true");
757 } else {
758 g_string_append(ctx->tsdl, "false");
759 }
760
761 g_string_append(ctx->tsdl, ";\n");
762 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
763 if (uuid) {
764 append_indent(ctx);
765 g_string_append(ctx->tsdl, "uuid = ");
766 append_uuid(ctx, uuid);
767 g_string_append(ctx->tsdl, ";\n");
768 }
769
770 /* End clock class */
771 append_end_block_semi_nl_nl(ctx);
772 }
773
774 /* Stream class */
775 append_indent(ctx);
776 g_string_append(ctx->tsdl, "stream {\n");
777 ctx->indent_level++;
778
779 /* Stream class properties */
780 append_indent(ctx);
781 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
782 bt_stream_class_get_id(sc->ir_sc));
783
784 /* Packet context field class */
785 append_indent(ctx);
786 g_string_append(ctx->tsdl, "packet.context := struct {\n");
787 ctx->indent_level++;
788 append_indent(ctx);
789 append_integer_field_class_from_props(ctx, 64, 8, false,
790 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
791 NULL, "packet_size", true);
792 append_indent(ctx);
793 append_integer_field_class_from_props(ctx, 64, 8, false,
794 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
795 NULL, "content_size", true);
796
ffb5c13c 797 if (sc->packets_have_ts_begin) {
15fe47e0
PP
798 append_indent(ctx);
799 append_integer_field_class_from_props(ctx, 64, 8, false,
800 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
801 sc->default_clock_class_name->str,
802 "timestamp_begin", true);
ffb5c13c
PP
803 }
804
805 if (sc->packets_have_ts_end) {
15fe47e0
PP
806 append_indent(ctx);
807 append_integer_field_class_from_props(ctx, 64, 8, false,
808 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
809 sc->default_clock_class_name->str,
810 "timestamp_end", true);
811 }
812
ffb5c13c
PP
813 if (sc->has_discarded_events) {
814 append_indent(ctx);
815 append_integer_field_class_from_props(ctx, 64, 8, false,
816 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
817 NULL, "events_discarded", true);
818 }
819
820 /*
821 * Unconditionnally write the packet sequence number as, even if
822 * there's no possible discarded packets message, it's still
823 * useful information to have.
824 */
15fe47e0
PP
825 append_indent(ctx);
826 append_integer_field_class_from_props(ctx, 64, 8, false,
827 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
828 NULL, "packet_seq_num", true);
829
830 if (sc->packet_context_fc) {
831 append_struct_field_class_members(ctx,
832 (void *) sc->packet_context_fc);
833 fs_sink_ctf_field_class_struct_align_at_least(
834 (void *) sc->packet_context_fc, 8);
835 }
836
837 /* End packet context field class */
838 append_end_block(ctx);
839 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
840 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
841
842 /* Event header field class */
843 append_indent(ctx);
844 g_string_append(ctx->tsdl, "event.header := struct {\n");
845 ctx->indent_level++;
846 append_indent(ctx);
847 append_integer_field_class_from_props(ctx, 64, 8, false,
848 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
849 NULL, "id", true);
850
851 if (sc->default_clock_class) {
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 sc->default_clock_class_name->str,
856 "timestamp", true);
857 }
858
859 /* End event header field class */
860 append_end_block(ctx);
861 g_string_append(ctx->tsdl, " align(8);\n");
862
863 /* Event common context field class */
864 if (sc->event_common_context_fc) {
865 append_indent(ctx);
866 g_string_append(ctx->tsdl, "event.context := ");
867 append_field_class(ctx,
868 (void *) sc->event_common_context_fc);
869 g_string_append(ctx->tsdl, ";\n");
870 }
871
872 /* End stream class */
873 append_end_block_semi_nl_nl(ctx);
874
875 /* Event classes */
876 for (i = 0; i < sc->event_classes->len; i++) {
877 append_event_class(ctx, sc->event_classes->pdata[i]);
878 }
879}
880
881BT_HIDDEN
335a2da5 882void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace *trace,
15fe47e0
PP
883 GString *tsdl)
884{
885 struct ctx ctx = {
886 .indent_level = 0,
887 .tsdl = tsdl,
888 };
889 uint64_t i;
890 uint64_t count;
891
892 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
893 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
894
895 /* Trace class */
896 append_indent(&ctx);
897 g_string_append(tsdl, "trace {\n");
898 ctx.indent_level++;
899
900 /* Trace class properties */
901 append_indent(&ctx);
902 g_string_append(tsdl, "major = 1;\n");
903 append_indent(&ctx);
904 g_string_append(tsdl, "minor = 8;\n");
905 append_indent(&ctx);
906 g_string_append(tsdl, "uuid = ");
335a2da5 907 append_uuid(&ctx, trace->uuid);
15fe47e0
PP
908 g_string_append(tsdl, ";\n");
909 append_indent(&ctx);
910 g_string_append(tsdl, "byte_order = ");
911
912 if (BYTE_ORDER == LITTLE_ENDIAN) {
913 g_string_append(tsdl, "le");
914 } else {
915 g_string_append(tsdl, "be");
916 }
917
918 g_string_append(tsdl, ";\n");
919
920 /* Packet header field class */
921 append_indent(&ctx);
922 g_string_append(tsdl, "packet.header := struct {\n");
923 ctx.indent_level++;
924 append_indent(&ctx);
925 append_integer_field_class_from_props(&ctx, 32, 8, false,
926 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
927 NULL, "magic", true);
928 append_indent(&ctx);
929 append_integer_field_class_from_props(&ctx, 8, 8, false,
930 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
931 NULL, "uuid[16]", true);
932 append_indent(&ctx);
933 append_integer_field_class_from_props(&ctx, 64, 8, false,
934 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
935 NULL, "stream_id", true);
936 append_indent(&ctx);
937 append_integer_field_class_from_props(&ctx, 64, 8, false,
938 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
939 NULL, "stream_instance_id", true);
940
941 /* End packet header field class */
942 append_end_block(&ctx);
943 g_string_append(ctx.tsdl, " align(8);\n");
944
945 /* End trace class */
946 append_end_block_semi_nl_nl(&ctx);
947
335a2da5
PP
948 /* Trace environment */
949 count = bt_trace_get_environment_entry_count(trace->ir_trace);
15fe47e0
PP
950 if (count > 0) {
951 append_indent(&ctx);
952 g_string_append(tsdl, "env {\n");
953 ctx.indent_level++;
954
955 for (i = 0; i < count; i++) {
956 const char *name;
957 const bt_value *val;
958
335a2da5
PP
959 bt_trace_borrow_environment_entry_by_index_const(
960 trace->ir_trace, i, &name, &val);
15fe47e0
PP
961 append_indent(&ctx);
962 g_string_append_printf(tsdl, "%s = ", name);
963
964 switch (bt_value_get_type(val)) {
fdd3a2da 965 case BT_VALUE_TYPE_SIGNED_INTEGER:
15fe47e0 966 g_string_append_printf(tsdl, "%" PRId64,
9c08c816 967 bt_value_integer_signed_get(val));
15fe47e0
PP
968 break;
969 case BT_VALUE_TYPE_STRING:
970 append_quoted_string(&ctx, bt_value_string_get(val));
971 break;
972 default:
973 /*
974 * This is checked in
335a2da5 975 * translate_trace_trace_ir_to_ctf_ir().
15fe47e0
PP
976 */
977 abort();
978 }
979
980 g_string_append(tsdl, ";\n");
981 }
982
983 /* End trace class environment */
984 append_end_block_semi_nl_nl(&ctx);
985 }
986
987 /* Stream classes and their event classes */
335a2da5
PP
988 for (i = 0; i < trace->stream_classes->len; i++) {
989 append_stream_class(&ctx, trace->stream_classes->pdata[i]);
15fe47e0
PP
990 }
991}
This page took 0.077584 seconds and 4 git commands to generate.