lib, plugins: use bt_field_class_type_is() where suitable
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-ctf-ir-to-tsdl.c
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
23 #include <babeltrace2/babeltrace.h>
24 #include "common/macros.h"
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <glib.h>
29 #include "common/assert.h"
30 #include "compat/endian.h"
31
32 #include "fs-sink-ctf-meta.h"
33
34 struct ctx {
35 unsigned int indent_level;
36 GString *tsdl;
37 };
38
39 static inline
40 void 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
49 static
50 void append_uuid(struct ctx *ctx, bt_uuid uuid)
51 {
52 g_string_append_printf(ctx->tsdl,
53 "\"" BT_UUID_FMT "\"",
54 BT_UUID_FMT_VALUES(uuid));
55 }
56
57 static
58 void 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
102 static
103 void 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
110 static
111 void 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
161 static
162 void append_end_block(struct ctx *ctx)
163 {
164 ctx->indent_level--;
165 append_indent(ctx);
166 g_string_append(ctx->tsdl, "}");
167 }
168
169 static
170 void 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
177 static
178 void 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
184 static
185 void 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
198 static
199 void 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
213 static
214 void append_integer_field_class(struct ctx *ctx,
215 struct fs_sink_ctf_field_class_int *fc)
216 {
217 const bt_field_class *ir_fc = fc->base.base.ir_fc;
218 bt_field_class_type type = bt_field_class_get_type(ir_fc);
219 bool is_signed = bt_field_class_type_is(type,
220 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
221
222 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
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
231 if (bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_ENUMERATION)) {
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;
239 const bt_field_class_enumeration_mapping *mapping;
240 const bt_field_class_enumeration_unsigned_mapping *u_mapping;
241 const bt_field_class_enumeration_signed_mapping *s_mapping;
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;
245 uint64_t range_count;
246 uint64_t range_i;
247
248 if (is_signed) {
249 s_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
250 ir_fc, i);
251 mapping = bt_field_class_enumeration_signed_mapping_as_mapping_const(
252 s_mapping);
253 s_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
254 s_mapping);
255 ranges = bt_integer_range_set_signed_as_range_set_const(
256 s_ranges);
257 } else {
258 u_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
259 ir_fc, i);
260 mapping = bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
261 u_mapping);
262 u_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
263 u_mapping);
264 ranges = bt_integer_range_set_unsigned_as_range_set_const(
265 u_ranges);
266 }
267
268 label = bt_field_class_enumeration_mapping_get_label(
269 mapping);
270 range_count = bt_integer_range_set_get_range_count(
271 ranges);
272
273 for (range_i = 0; range_i < range_count; range_i++) {
274 append_indent(ctx);
275 g_string_append(ctx->tsdl, "\"");
276 append_quoted_string_content(ctx, label);
277 g_string_append(ctx->tsdl, "\" = ");
278
279 if (is_signed) {
280 const bt_integer_range_signed *range;
281 int64_t lower, upper;
282
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);
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 {
300 const bt_integer_range_unsigned *range;
301 uint64_t lower, upper;
302
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);
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
329 static
330 void 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
335 if (bt_field_class_get_type(fc->base.base.ir_fc) ==
336 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) {
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
349 static
350 void 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
356 static
357 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
358
359 static
360 void 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
366 BT_ASSERT(fc);
367
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
405 static
406 void 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
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 */
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 }
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);
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++) {
484 struct fs_sink_ctf_named_field_class *named_fc =
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",
491 named_fc->name->str, i);
492 }
493
494 append_end_block(ctx);
495 g_string_append_printf(ctx->tsdl, " %s;\n",
496 var_fc->tag_ref->str);
497 }
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");
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");
506 }
507
508 append_indent(ctx);
509 append_member(ctx, named_fc->name->str, fc);
510 }
511 }
512
513 static
514 void 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
525 static
526 void 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
539 static
540 void 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
561 static
562 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
563 {
564 switch (fc->type) {
565 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL:
566 append_bool_field_class(ctx, (void *) fc);
567 break;
568 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY:
569 append_bit_array_field_class(ctx, (void *) fc);
570 break;
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;
583 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
584 append_option_field_class(ctx, (void *) fc);
585 break;
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
594 static
595 void 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
709 static
710 void 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
797 if (sc->packets_have_ts_begin) {
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);
803 }
804
805 if (sc->packets_have_ts_end) {
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
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 */
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
881 BT_HIDDEN
882 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace *trace,
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 = ");
907 append_uuid(&ctx, trace->uuid);
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
948 /* Trace environment */
949 count = bt_trace_get_environment_entry_count(trace->ir_trace);
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
959 bt_trace_borrow_environment_entry_by_index_const(
960 trace->ir_trace, i, &name, &val);
961 append_indent(&ctx);
962 g_string_append_printf(tsdl, "%s = ", name);
963
964 switch (bt_value_get_type(val)) {
965 case BT_VALUE_TYPE_SIGNED_INTEGER:
966 g_string_append_printf(tsdl, "%" PRId64,
967 bt_value_integer_signed_get(val));
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
975 * translate_trace_trace_ir_to_ctf_ir().
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 */
988 for (i = 0; i < trace->stream_classes->len; i++) {
989 append_stream_class(&ctx, trace->stream_classes->pdata[i]);
990 }
991 }
This page took 0.08176 seconds and 5 git commands to generate.