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