sink.ctf.fs: write boolean field classes and fields
[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_integer_field_class(struct ctx *ctx,
200 struct fs_sink_ctf_field_class_int *fc)
201 {
202 const bt_field_class *ir_fc = fc->base.base.ir_fc;
203 bt_field_class_type type = bt_field_class_get_type(ir_fc);
204 bool is_signed = type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION ||
205 type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER;
206
207 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
208 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
209 g_string_append(ctx->tsdl, "enum : ");
210 }
211
212 append_integer_field_class_from_props(ctx, fc->base.size,
213 fc->base.base.alignment, is_signed,
214 bt_field_class_integer_get_preferred_display_base(ir_fc),
215 NULL, NULL, false);
216
217 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
218 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
219 uint64_t i;
220
221 g_string_append(ctx->tsdl, " {\n");
222 ctx->indent_level++;
223
224 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_fc); i++) {
225 const char *label;
226 const bt_field_class_enumeration_mapping *mapping;
227 const bt_field_class_enumeration_unsigned_mapping *u_mapping;
228 const bt_field_class_enumeration_signed_mapping *s_mapping;
229 const bt_integer_range_set *ranges;
230 const bt_integer_range_set_unsigned *u_ranges;
231 const bt_integer_range_set_signed *s_ranges;
232 uint64_t range_count;
233 uint64_t range_i;
234
235 if (is_signed) {
236 s_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
237 ir_fc, i);
238 mapping = bt_field_class_enumeration_signed_mapping_as_mapping_const(
239 s_mapping);
240 s_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
241 s_mapping);
242 ranges = bt_integer_range_set_signed_as_range_set_const(
243 s_ranges);
244 } else {
245 u_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
246 ir_fc, i);
247 mapping = bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
248 u_mapping);
249 u_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
250 u_mapping);
251 ranges = bt_integer_range_set_unsigned_as_range_set_const(
252 u_ranges);
253 }
254
255 label = bt_field_class_enumeration_mapping_get_label(
256 mapping);
257 range_count = bt_integer_range_set_get_range_count(
258 ranges);
259
260 for (range_i = 0; range_i < range_count; range_i++) {
261 append_indent(ctx);
262 g_string_append(ctx->tsdl, "\"");
263 append_quoted_string_content(ctx, label);
264 g_string_append(ctx->tsdl, "\" = ");
265
266 if (is_signed) {
267 const bt_integer_range_signed *range;
268 int64_t lower, upper;
269
270 range = bt_integer_range_set_signed_borrow_range_by_index_const(
271 s_ranges, range_i);
272 lower = bt_integer_range_signed_get_lower(
273 range);
274 upper = bt_integer_range_signed_get_upper(
275 range);
276
277 if (lower == upper) {
278 g_string_append_printf(
279 ctx->tsdl, "%" PRId64,
280 lower);
281 } else {
282 g_string_append_printf(
283 ctx->tsdl, "%" PRId64 " ... %" PRId64,
284 lower, upper);
285 }
286 } else {
287 const bt_integer_range_unsigned *range;
288 uint64_t lower, upper;
289
290 range = bt_integer_range_set_unsigned_borrow_range_by_index_const(
291 u_ranges, range_i);
292 lower = bt_integer_range_unsigned_get_lower(
293 range);
294 upper = bt_integer_range_unsigned_get_upper(
295 range);
296
297 if (lower == upper) {
298 g_string_append_printf(
299 ctx->tsdl, "%" PRIu64,
300 lower);
301 } else {
302 g_string_append_printf(
303 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
304 lower, upper);
305 }
306 }
307
308 g_string_append(ctx->tsdl, ",\n");
309 }
310 }
311
312 append_end_block(ctx);
313 }
314 }
315
316 static
317 void append_float_field_class(struct ctx *ctx,
318 struct fs_sink_ctf_field_class_float *fc)
319 {
320 unsigned int mant_dig, exp_dig;
321
322 if (bt_field_class_real_is_single_precision(fc->base.base.ir_fc)) {
323 mant_dig = 24;
324 exp_dig = 8;
325 } else {
326 mant_dig = 53;
327 exp_dig = 11;
328 }
329
330 g_string_append_printf(ctx->tsdl,
331 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
332 mant_dig, exp_dig, fc->base.base.alignment);
333 }
334
335 static
336 void append_string_field_class(struct ctx *ctx,
337 struct fs_sink_ctf_field_class_float *fc)
338 {
339 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
340 }
341
342 static
343 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
344
345 static
346 void append_member(struct ctx *ctx, const char *name,
347 struct fs_sink_ctf_field_class *fc)
348 {
349 GString *lengths = NULL;
350 const char *lengths_str = "";
351
352 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
353 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
354 if (!lengths) {
355 lengths = g_string_new(NULL);
356 BT_ASSERT(lengths);
357 }
358
359 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
360 struct fs_sink_ctf_field_class_array *array_fc =
361 (void *) fc;
362
363 g_string_append_printf(lengths, "[%" PRIu64 "]",
364 array_fc->length);
365 fc = array_fc->base.elem_fc;
366 } else {
367 struct fs_sink_ctf_field_class_sequence *seq_fc =
368 (void *) fc;
369
370 g_string_append_printf(lengths, "[%s]",
371 seq_fc->length_ref->str);
372 fc = seq_fc->base.elem_fc;
373 }
374 }
375
376 append_field_class(ctx, fc);
377
378 if (lengths) {
379 lengths_str = lengths->str;
380 }
381
382 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
383
384 if (lengths) {
385 g_string_free(lengths, TRUE);
386 }
387 }
388
389 static
390 void append_struct_field_class_members(struct ctx *ctx,
391 struct fs_sink_ctf_field_class_struct *struct_fc)
392 {
393 uint64_t i;
394
395 for (i = 0; i < struct_fc->members->len; i++) {
396 struct fs_sink_ctf_named_field_class *named_fc =
397 fs_sink_ctf_field_class_struct_borrow_member_by_index(
398 struct_fc, i);
399 struct fs_sink_ctf_field_class *fc = named_fc->fc;
400
401 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
402 struct fs_sink_ctf_field_class_sequence *seq_fc =
403 (void *) fc;
404
405 if (seq_fc->length_is_before) {
406 append_indent(ctx);
407 append_integer_field_class_from_props(ctx,
408 32, 8, false,
409 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
410 NULL, seq_fc->length_ref->str, true);
411 }
412 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
413 struct fs_sink_ctf_field_class_variant *var_fc =
414 (void *) fc;
415
416 if (var_fc->tag_is_before) {
417 append_indent(ctx);
418 g_string_append(ctx->tsdl, "enum : ");
419 append_integer_field_class_from_props(ctx,
420 16, 8, false,
421 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
422 NULL, NULL, false);
423 g_string_append(ctx->tsdl, " {\n");
424 ctx->indent_level++;
425
426 for (i = 0; i < var_fc->options->len; i++) {
427 struct fs_sink_ctf_named_field_class *named_fc =
428 fs_sink_ctf_field_class_variant_borrow_option_by_index(
429 var_fc, i);
430
431 append_indent(ctx);
432 g_string_append_printf(ctx->tsdl,
433 "\"%s\" = %" PRIu64 ",\n",
434 named_fc->name->str, i);
435 }
436
437 append_end_block(ctx);
438 g_string_append_printf(ctx->tsdl, " %s;\n",
439 var_fc->tag_ref->str);
440 }
441 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL) {
442 append_indent(ctx);
443 g_string_append(ctx->tsdl,
444 "/* The integer field class below was a trace IR boolean field class. */\n");
445 }
446
447 append_indent(ctx);
448 append_member(ctx, named_fc->name->str, fc);
449 }
450 }
451
452 static
453 void append_struct_field_class(struct ctx *ctx,
454 struct fs_sink_ctf_field_class_struct *fc)
455 {
456 g_string_append(ctx->tsdl, "struct {\n");
457 ctx->indent_level++;
458 append_struct_field_class_members(ctx, fc);
459 append_end_block(ctx);
460 g_string_append_printf(ctx->tsdl, " align(%u)",
461 fc->base.alignment);
462 }
463
464 static
465 void append_variant_field_class(struct ctx *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",
471 var_fc->tag_ref->str);
472 ctx->indent_level++;
473
474 for (i = 0; i < var_fc->options->len; i++) {
475 struct fs_sink_ctf_named_field_class *named_fc =
476 fs_sink_ctf_field_class_variant_borrow_option_by_index(
477 var_fc, i);
478
479 append_indent(ctx);
480 append_member(ctx, named_fc->name->str, named_fc->fc);
481 }
482
483 append_end_block(ctx);
484 }
485
486 static
487 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
488 {
489 switch (fc->type) {
490 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL:
491 append_bool_field_class(ctx, (void *) fc);
492 break;
493 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
494 append_integer_field_class(ctx, (void *) fc);
495 break;
496 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
497 append_float_field_class(ctx, (void *) fc);
498 break;
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
500 append_string_field_class(ctx, (void *) fc);
501 break;
502 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
503 append_struct_field_class(ctx, (void *) fc);
504 break;
505 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
506 append_variant_field_class(ctx, (void *) fc);
507 break;
508 default:
509 abort();
510 }
511 }
512
513 static
514 void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
515 {
516 const char *str;
517 bt_event_class_log_level log_level;
518
519 /* Event class */
520 append_indent(ctx);
521 g_string_append(ctx->tsdl, "event {\n");
522 ctx->indent_level++;
523
524 /* Event class properties */
525 append_indent(ctx);
526 g_string_append(ctx->tsdl, "name = ");
527 str = bt_event_class_get_name(ec->ir_ec);
528 if (!str) {
529 str = "unknown";
530 }
531
532 append_quoted_string(ctx, str);
533 g_string_append(ctx->tsdl, ";\n");
534 append_indent(ctx);
535 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
536 bt_stream_class_get_id(ec->sc->ir_sc));
537 append_indent(ctx);
538 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
539 bt_event_class_get_id(ec->ir_ec));
540
541 str = bt_event_class_get_emf_uri(ec->ir_ec);
542 if (str) {
543 append_indent(ctx);
544 g_string_append(ctx->tsdl, "model.emf.uri = ");
545 append_quoted_string(ctx, str);
546 g_string_append(ctx->tsdl, ";\n");
547 }
548
549 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
550 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 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
629 void append_stream_class(struct ctx *ctx,
630 struct fs_sink_ctf_stream_class *sc)
631 {
632 uint64_t i;
633
634 /* Default clock class */
635 if (sc->default_clock_class) {
636 const char *descr;
637 int64_t offset_seconds;
638 uint64_t offset_cycles;
639 bt_uuid uuid;
640
641 append_indent(ctx);
642 g_string_append(ctx->tsdl, "clock {\n");
643 ctx->indent_level++;
644 BT_ASSERT(sc->default_clock_class_name->len > 0);
645 append_indent(ctx);
646 g_string_append_printf(ctx->tsdl, "name = %s;\n",
647 sc->default_clock_class_name->str);
648 descr = bt_clock_class_get_description(sc->default_clock_class);
649 if (descr) {
650 append_indent(ctx);
651 g_string_append(ctx->tsdl, "description = ");
652 append_quoted_string(ctx, descr);
653 g_string_append(ctx->tsdl, ";\n");
654 }
655
656 append_indent(ctx);
657 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
658 bt_clock_class_get_frequency(sc->default_clock_class));
659 append_indent(ctx);
660 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
661 bt_clock_class_get_precision(sc->default_clock_class));
662 bt_clock_class_get_offset(sc->default_clock_class,
663 &offset_seconds, &offset_cycles);
664 append_indent(ctx);
665 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
666 offset_seconds);
667 append_indent(ctx);
668 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
669 offset_cycles);
670 append_indent(ctx);
671 g_string_append(ctx->tsdl, "absolute = ");
672
673 if (bt_clock_class_origin_is_unix_epoch(
674 sc->default_clock_class)) {
675 g_string_append(ctx->tsdl, "true");
676 } else {
677 g_string_append(ctx->tsdl, "false");
678 }
679
680 g_string_append(ctx->tsdl, ";\n");
681 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
682 if (uuid) {
683 append_indent(ctx);
684 g_string_append(ctx->tsdl, "uuid = ");
685 append_uuid(ctx, uuid);
686 g_string_append(ctx->tsdl, ";\n");
687 }
688
689 /* End clock class */
690 append_end_block_semi_nl_nl(ctx);
691 }
692
693 /* Stream class */
694 append_indent(ctx);
695 g_string_append(ctx->tsdl, "stream {\n");
696 ctx->indent_level++;
697
698 /* Stream class properties */
699 append_indent(ctx);
700 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
701 bt_stream_class_get_id(sc->ir_sc));
702
703 /* Packet context field class */
704 append_indent(ctx);
705 g_string_append(ctx->tsdl, "packet.context := struct {\n");
706 ctx->indent_level++;
707 append_indent(ctx);
708 append_integer_field_class_from_props(ctx, 64, 8, false,
709 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
710 NULL, "packet_size", true);
711 append_indent(ctx);
712 append_integer_field_class_from_props(ctx, 64, 8, false,
713 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
714 NULL, "content_size", true);
715
716 if (sc->packets_have_ts_begin) {
717 append_indent(ctx);
718 append_integer_field_class_from_props(ctx, 64, 8, false,
719 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
720 sc->default_clock_class_name->str,
721 "timestamp_begin", true);
722 }
723
724 if (sc->packets_have_ts_end) {
725 append_indent(ctx);
726 append_integer_field_class_from_props(ctx, 64, 8, false,
727 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
728 sc->default_clock_class_name->str,
729 "timestamp_end", true);
730 }
731
732 if (sc->has_discarded_events) {
733 append_indent(ctx);
734 append_integer_field_class_from_props(ctx, 64, 8, false,
735 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
736 NULL, "events_discarded", true);
737 }
738
739 /*
740 * Unconditionnally write the packet sequence number as, even if
741 * there's no possible discarded packets message, it's still
742 * useful information to have.
743 */
744 append_indent(ctx);
745 append_integer_field_class_from_props(ctx, 64, 8, false,
746 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
747 NULL, "packet_seq_num", true);
748
749 if (sc->packet_context_fc) {
750 append_struct_field_class_members(ctx,
751 (void *) sc->packet_context_fc);
752 fs_sink_ctf_field_class_struct_align_at_least(
753 (void *) sc->packet_context_fc, 8);
754 }
755
756 /* End packet context field class */
757 append_end_block(ctx);
758 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
759 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
760
761 /* Event header field class */
762 append_indent(ctx);
763 g_string_append(ctx->tsdl, "event.header := struct {\n");
764 ctx->indent_level++;
765 append_indent(ctx);
766 append_integer_field_class_from_props(ctx, 64, 8, false,
767 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
768 NULL, "id", true);
769
770 if (sc->default_clock_class) {
771 append_indent(ctx);
772 append_integer_field_class_from_props(ctx, 64, 8, false,
773 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
774 sc->default_clock_class_name->str,
775 "timestamp", true);
776 }
777
778 /* End event header field class */
779 append_end_block(ctx);
780 g_string_append(ctx->tsdl, " align(8);\n");
781
782 /* Event common context field class */
783 if (sc->event_common_context_fc) {
784 append_indent(ctx);
785 g_string_append(ctx->tsdl, "event.context := ");
786 append_field_class(ctx,
787 (void *) sc->event_common_context_fc);
788 g_string_append(ctx->tsdl, ";\n");
789 }
790
791 /* End stream class */
792 append_end_block_semi_nl_nl(ctx);
793
794 /* Event classes */
795 for (i = 0; i < sc->event_classes->len; i++) {
796 append_event_class(ctx, sc->event_classes->pdata[i]);
797 }
798 }
799
800 BT_HIDDEN
801 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace *trace,
802 GString *tsdl)
803 {
804 struct ctx ctx = {
805 .indent_level = 0,
806 .tsdl = tsdl,
807 };
808 uint64_t i;
809 uint64_t count;
810
811 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
812 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
813
814 /* Trace class */
815 append_indent(&ctx);
816 g_string_append(tsdl, "trace {\n");
817 ctx.indent_level++;
818
819 /* Trace class properties */
820 append_indent(&ctx);
821 g_string_append(tsdl, "major = 1;\n");
822 append_indent(&ctx);
823 g_string_append(tsdl, "minor = 8;\n");
824 append_indent(&ctx);
825 g_string_append(tsdl, "uuid = ");
826 append_uuid(&ctx, trace->uuid);
827 g_string_append(tsdl, ";\n");
828 append_indent(&ctx);
829 g_string_append(tsdl, "byte_order = ");
830
831 if (BYTE_ORDER == LITTLE_ENDIAN) {
832 g_string_append(tsdl, "le");
833 } else {
834 g_string_append(tsdl, "be");
835 }
836
837 g_string_append(tsdl, ";\n");
838
839 /* Packet header field class */
840 append_indent(&ctx);
841 g_string_append(tsdl, "packet.header := struct {\n");
842 ctx.indent_level++;
843 append_indent(&ctx);
844 append_integer_field_class_from_props(&ctx, 32, 8, false,
845 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
846 NULL, "magic", true);
847 append_indent(&ctx);
848 append_integer_field_class_from_props(&ctx, 8, 8, false,
849 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
850 NULL, "uuid[16]", true);
851 append_indent(&ctx);
852 append_integer_field_class_from_props(&ctx, 64, 8, false,
853 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
854 NULL, "stream_id", true);
855 append_indent(&ctx);
856 append_integer_field_class_from_props(&ctx, 64, 8, false,
857 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
858 NULL, "stream_instance_id", true);
859
860 /* End packet header field class */
861 append_end_block(&ctx);
862 g_string_append(ctx.tsdl, " align(8);\n");
863
864 /* End trace class */
865 append_end_block_semi_nl_nl(&ctx);
866
867 /* Trace environment */
868 count = bt_trace_get_environment_entry_count(trace->ir_trace);
869 if (count > 0) {
870 append_indent(&ctx);
871 g_string_append(tsdl, "env {\n");
872 ctx.indent_level++;
873
874 for (i = 0; i < count; i++) {
875 const char *name;
876 const bt_value *val;
877
878 bt_trace_borrow_environment_entry_by_index_const(
879 trace->ir_trace, i, &name, &val);
880 append_indent(&ctx);
881 g_string_append_printf(tsdl, "%s = ", name);
882
883 switch (bt_value_get_type(val)) {
884 case BT_VALUE_TYPE_SIGNED_INTEGER:
885 g_string_append_printf(tsdl, "%" PRId64,
886 bt_value_integer_signed_get(val));
887 break;
888 case BT_VALUE_TYPE_STRING:
889 append_quoted_string(&ctx, bt_value_string_get(val));
890 break;
891 default:
892 /*
893 * This is checked in
894 * translate_trace_trace_ir_to_ctf_ir().
895 */
896 abort();
897 }
898
899 g_string_append(tsdl, ";\n");
900 }
901
902 /* End trace class environment */
903 append_end_block_semi_nl_nl(&ctx);
904 }
905
906 /* Stream classes and their event classes */
907 for (i = 0; i < trace->stream_classes->len; i++) {
908 append_stream_class(&ctx, trace->stream_classes->pdata[i]);
909 }
910 }
This page took 0.049305 seconds and 5 git commands to generate.