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