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