99739e2fd1f48d0afdc7e7b41106971ea4dd9d34
[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_integer_field_class(struct ctx *ctx,
186 struct fs_sink_ctf_field_class_int *fc)
187 {
188 const bt_field_class *ir_fc = fc->base.base.ir_fc;
189 bt_field_class_type type = bt_field_class_get_type(ir_fc);
190 bool is_signed = type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION ||
191 type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER;
192
193 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
194 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
195 g_string_append(ctx->tsdl, "enum : ");
196 }
197
198 append_integer_field_class_from_props(ctx, fc->base.size,
199 fc->base.base.alignment, is_signed,
200 bt_field_class_integer_get_preferred_display_base(ir_fc),
201 NULL, NULL, false);
202
203 if (type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION ||
204 type == BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
205 uint64_t i;
206
207 g_string_append(ctx->tsdl, " {\n");
208 ctx->indent_level++;
209
210 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_fc); i++) {
211 const char *label;
212 const bt_field_class_enumeration_mapping *mapping;
213 const bt_field_class_unsigned_enumeration_mapping *u_mapping;
214 const bt_field_class_signed_enumeration_mapping *i_mapping;
215 uint64_t range_count;
216 uint64_t range_i;
217
218 if (is_signed) {
219 i_mapping = bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
220 ir_fc, i);
221 mapping = bt_field_class_signed_enumeration_mapping_as_mapping_const(
222 i_mapping);
223 } else {
224 u_mapping = bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
225 ir_fc, i);
226 mapping = bt_field_class_unsigned_enumeration_mapping_as_mapping_const(
227 u_mapping);
228 }
229
230 label = bt_field_class_enumeration_mapping_get_label(
231 mapping);
232 range_count =
233 bt_field_class_enumeration_mapping_get_range_count(
234 mapping);
235
236 for (range_i = 0; range_i < range_count; range_i++) {
237 append_indent(ctx);
238
239 /*
240 * Systematically prepend `_` to the
241 * mapping's label as this could be used
242 * as the tag of a subsequent variant
243 * field class and variant FC option
244 * names are systematically protected
245 * with a leading `_`.
246 *
247 * FIXME: This is temporary as the
248 * library's API should change to
249 * decouple variant FC option names from
250 * selector FC labels. The current
251 * drawback is that an original label
252 * `HELLO` becomes `_HELLO` in the
253 * generated metadata, therefore tools
254 * expecting `HELLO` could fail.
255 */
256 g_string_append(ctx->tsdl, "\"_");
257 append_quoted_string_content(ctx, label);
258 g_string_append(ctx->tsdl, "\" = ");
259
260 if (is_signed) {
261 int64_t lower, upper;
262
263 bt_field_class_signed_enumeration_mapping_get_range_by_index(
264 i_mapping, range_i,
265 &lower, &upper);
266
267 if (lower == upper) {
268 g_string_append_printf(
269 ctx->tsdl, "%" PRId64,
270 lower);
271 } else {
272 g_string_append_printf(
273 ctx->tsdl, "%" PRId64 " ... %" PRId64,
274 lower, upper);
275 }
276 } else {
277 uint64_t lower, upper;
278
279 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
280 u_mapping, range_i,
281 &lower, &upper);
282
283 if (lower == upper) {
284 g_string_append_printf(
285 ctx->tsdl, "%" PRIu64,
286 lower);
287 } else {
288 g_string_append_printf(
289 ctx->tsdl, "%" PRIu64 " ... %" PRIu64,
290 lower, upper);
291 }
292 }
293
294 g_string_append(ctx->tsdl, ",\n");
295 }
296 }
297
298 append_end_block(ctx);
299 }
300 }
301
302 static
303 void append_float_field_class(struct ctx *ctx,
304 struct fs_sink_ctf_field_class_float *fc)
305 {
306 unsigned int mant_dig, exp_dig;
307
308 if (bt_field_class_real_is_single_precision(fc->base.base.ir_fc)) {
309 mant_dig = 24;
310 exp_dig = 8;
311 } else {
312 mant_dig = 53;
313 exp_dig = 11;
314 }
315
316 g_string_append_printf(ctx->tsdl,
317 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
318 mant_dig, exp_dig, fc->base.base.alignment);
319 }
320
321 static
322 void append_string_field_class(struct ctx *ctx,
323 struct fs_sink_ctf_field_class_float *fc)
324 {
325 g_string_append(ctx->tsdl, "string { encoding = UTF8; }");
326 }
327
328 static
329 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc);
330
331 static
332 void append_member(struct ctx *ctx, const char *name,
333 struct fs_sink_ctf_field_class *fc)
334 {
335 GString *lengths = NULL;
336 const char *lengths_str = "";
337
338 while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
339 fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
340 if (!lengths) {
341 lengths = g_string_new(NULL);
342 BT_ASSERT(lengths);
343 }
344
345 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY) {
346 struct fs_sink_ctf_field_class_array *array_fc =
347 (void *) fc;
348
349 g_string_append_printf(lengths, "[%" PRIu64 "]",
350 array_fc->length);
351 fc = array_fc->base.elem_fc;
352 } else {
353 struct fs_sink_ctf_field_class_sequence *seq_fc =
354 (void *) fc;
355
356 g_string_append_printf(lengths, "[%s]",
357 seq_fc->length_ref->str);
358 fc = seq_fc->base.elem_fc;
359 }
360 }
361
362 append_field_class(ctx, fc);
363
364 if (lengths) {
365 lengths_str = lengths->str;
366 }
367
368 g_string_append_printf(ctx->tsdl, " %s%s;\n", name, lengths_str);
369
370 if (lengths) {
371 g_string_free(lengths, TRUE);
372 }
373 }
374
375 static
376 void append_struct_field_class_members(struct ctx *ctx,
377 struct fs_sink_ctf_field_class_struct *struct_fc)
378 {
379 uint64_t i;
380
381 for (i = 0; i < struct_fc->members->len; i++) {
382 struct fs_sink_ctf_named_field_class *named_fc =
383 fs_sink_ctf_field_class_struct_borrow_member_by_index(
384 struct_fc, i);
385 struct fs_sink_ctf_field_class *fc = named_fc->fc;
386
387 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
388 struct fs_sink_ctf_field_class_sequence *seq_fc =
389 (void *) fc;
390
391 if (seq_fc->length_is_before) {
392 append_indent(ctx);
393 append_integer_field_class_from_props(ctx,
394 32, 8, false,
395 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
396 NULL, seq_fc->length_ref->str, true);
397 }
398 } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
399 struct fs_sink_ctf_field_class_variant *var_fc =
400 (void *) fc;
401
402 if (var_fc->tag_is_before) {
403 append_indent(ctx);
404 g_string_append(ctx->tsdl, "enum : ");
405 append_integer_field_class_from_props(ctx,
406 16, 8, false,
407 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
408 NULL, NULL, false);
409 g_string_append(ctx->tsdl, " {\n");
410 ctx->indent_level++;
411
412 for (i = 0; i < var_fc->options->len; i++) {
413 struct fs_sink_ctf_named_field_class *named_fc =
414 fs_sink_ctf_field_class_variant_borrow_option_by_index(
415 var_fc, i);
416
417 append_indent(ctx);
418 g_string_append_printf(ctx->tsdl,
419 "\"%s\" = %" PRIu64 ",\n",
420 named_fc->name->str, i);
421 }
422
423 append_end_block(ctx);
424 g_string_append_printf(ctx->tsdl, " %s;\n",
425 var_fc->tag_ref->str);
426 }
427 }
428
429 append_indent(ctx);
430 append_member(ctx, named_fc->name->str, fc);
431 }
432 }
433
434 static
435 void append_struct_field_class(struct ctx *ctx,
436 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)",
443 fc->base.alignment);
444 }
445
446 static
447 void append_variant_field_class(struct ctx *ctx,
448 struct fs_sink_ctf_field_class_variant *var_fc)
449 {
450 uint64_t i;
451
452 g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
453 var_fc->tag_ref->str);
454 ctx->indent_level++;
455
456 for (i = 0; i < var_fc->options->len; i++) {
457 struct fs_sink_ctf_named_field_class *named_fc =
458 fs_sink_ctf_field_class_variant_borrow_option_by_index(
459 var_fc, i);
460
461 append_indent(ctx);
462 append_member(ctx, named_fc->name->str, named_fc->fc);
463 }
464
465 append_end_block(ctx);
466 }
467
468 static
469 void append_field_class(struct ctx *ctx, struct fs_sink_ctf_field_class *fc)
470 {
471 switch (fc->type) {
472 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT:
473 append_integer_field_class(ctx, (void *) fc);
474 break;
475 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT:
476 append_float_field_class(ctx, (void *) fc);
477 break;
478 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING:
479 append_string_field_class(ctx, (void *) fc);
480 break;
481 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
482 append_struct_field_class(ctx, (void *) fc);
483 break;
484 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
485 append_variant_field_class(ctx, (void *) fc);
486 break;
487 default:
488 abort();
489 }
490 }
491
492 static
493 void append_event_class(struct ctx *ctx, struct fs_sink_ctf_event_class *ec)
494 {
495 const char *str;
496 bt_event_class_log_level log_level;
497
498 /* Event class */
499 append_indent(ctx);
500 g_string_append(ctx->tsdl, "event {\n");
501 ctx->indent_level++;
502
503 /* Event class properties */
504 append_indent(ctx);
505 g_string_append(ctx->tsdl, "name = ");
506 str = bt_event_class_get_name(ec->ir_ec);
507 if (!str) {
508 str = "unknown";
509 }
510
511 append_quoted_string(ctx, str);
512 g_string_append(ctx->tsdl, ";\n");
513 append_indent(ctx);
514 g_string_append_printf(ctx->tsdl, "stream_id = %" PRIu64 ";\n",
515 bt_stream_class_get_id(ec->sc->ir_sc));
516 append_indent(ctx);
517 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
518 bt_event_class_get_id(ec->ir_ec));
519
520 str = bt_event_class_get_emf_uri(ec->ir_ec);
521 if (str) {
522 append_indent(ctx);
523 g_string_append(ctx->tsdl, "model.emf.uri = ");
524 append_quoted_string(ctx, str);
525 g_string_append(ctx->tsdl, ";\n");
526 }
527
528 if (bt_event_class_get_log_level(ec->ir_ec, &log_level) ==
529 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
530 unsigned int level;
531
532 append_indent(ctx);
533 g_string_append(ctx->tsdl, "loglevel = ");
534
535 switch (log_level) {
536 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
537 level = 0;
538 break;
539 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
540 level = 1;
541 break;
542 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
543 level = 2;
544 break;
545 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
546 level = 3;
547 break;
548 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
549 level = 4;
550 break;
551 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
552 level = 5;
553 break;
554 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
555 level = 6;
556 break;
557 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
558 level = 7;
559 break;
560 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
561 level = 8;
562 break;
563 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
564 level = 9;
565 break;
566 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
567 level = 10;
568 break;
569 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
570 level = 11;
571 break;
572 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
573 level = 12;
574 break;
575 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
576 level = 13;
577 break;
578 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
579 level = 14;
580 break;
581 default:
582 abort();
583 }
584
585 g_string_append_printf(ctx->tsdl, "%u;\n", level);
586 }
587
588 /* Event specific context field class */
589 if (ec->spec_context_fc) {
590 append_indent(ctx);
591 g_string_append(ctx->tsdl, "context := ");
592 append_field_class(ctx, ec->spec_context_fc);
593 g_string_append(ctx->tsdl, ";\n");
594 }
595
596 /* Event payload field class */
597 if (ec->payload_fc) {
598 append_indent(ctx);
599 g_string_append(ctx->tsdl, "fields := ");
600 append_field_class(ctx, ec->payload_fc);
601 g_string_append(ctx->tsdl, ";\n");
602 }
603
604 append_end_block_semi_nl_nl(ctx);
605 }
606
607 static
608 void append_stream_class(struct ctx *ctx,
609 struct fs_sink_ctf_stream_class *sc)
610 {
611 uint64_t i;
612
613 /* Default clock class */
614 if (sc->default_clock_class) {
615 const char *descr;
616 int64_t offset_seconds;
617 uint64_t offset_cycles;
618 bt_uuid uuid;
619
620 append_indent(ctx);
621 g_string_append(ctx->tsdl, "clock {\n");
622 ctx->indent_level++;
623 BT_ASSERT(sc->default_clock_class_name->len > 0);
624 append_indent(ctx);
625 g_string_append_printf(ctx->tsdl, "name = %s;\n",
626 sc->default_clock_class_name->str);
627 descr = bt_clock_class_get_description(sc->default_clock_class);
628 if (descr) {
629 append_indent(ctx);
630 g_string_append(ctx->tsdl, "description = ");
631 append_quoted_string(ctx, descr);
632 g_string_append(ctx->tsdl, ";\n");
633 }
634
635 append_indent(ctx);
636 g_string_append_printf(ctx->tsdl, "freq = %" PRIu64 ";\n",
637 bt_clock_class_get_frequency(sc->default_clock_class));
638 append_indent(ctx);
639 g_string_append_printf(ctx->tsdl, "precision = %" PRIu64 ";\n",
640 bt_clock_class_get_precision(sc->default_clock_class));
641 bt_clock_class_get_offset(sc->default_clock_class,
642 &offset_seconds, &offset_cycles);
643 append_indent(ctx);
644 g_string_append_printf(ctx->tsdl, "offset_s = %" PRId64 ";\n",
645 offset_seconds);
646 append_indent(ctx);
647 g_string_append_printf(ctx->tsdl, "offset = %" PRIu64 ";\n",
648 offset_cycles);
649 append_indent(ctx);
650 g_string_append(ctx->tsdl, "absolute = ");
651
652 if (bt_clock_class_origin_is_unix_epoch(
653 sc->default_clock_class)) {
654 g_string_append(ctx->tsdl, "true");
655 } else {
656 g_string_append(ctx->tsdl, "false");
657 }
658
659 g_string_append(ctx->tsdl, ";\n");
660 uuid = bt_clock_class_get_uuid(sc->default_clock_class);
661 if (uuid) {
662 append_indent(ctx);
663 g_string_append(ctx->tsdl, "uuid = ");
664 append_uuid(ctx, uuid);
665 g_string_append(ctx->tsdl, ";\n");
666 }
667
668 /* End clock class */
669 append_end_block_semi_nl_nl(ctx);
670 }
671
672 /* Stream class */
673 append_indent(ctx);
674 g_string_append(ctx->tsdl, "stream {\n");
675 ctx->indent_level++;
676
677 /* Stream class properties */
678 append_indent(ctx);
679 g_string_append_printf(ctx->tsdl, "id = %" PRIu64 ";\n",
680 bt_stream_class_get_id(sc->ir_sc));
681
682 /* Packet context field class */
683 append_indent(ctx);
684 g_string_append(ctx->tsdl, "packet.context := struct {\n");
685 ctx->indent_level++;
686 append_indent(ctx);
687 append_integer_field_class_from_props(ctx, 64, 8, false,
688 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
689 NULL, "packet_size", true);
690 append_indent(ctx);
691 append_integer_field_class_from_props(ctx, 64, 8, false,
692 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
693 NULL, "content_size", true);
694
695 if (sc->packets_have_ts_begin) {
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 sc->default_clock_class_name->str,
700 "timestamp_begin", true);
701 }
702
703 if (sc->packets_have_ts_end) {
704 append_indent(ctx);
705 append_integer_field_class_from_props(ctx, 64, 8, false,
706 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
707 sc->default_clock_class_name->str,
708 "timestamp_end", true);
709 }
710
711 if (sc->has_discarded_events) {
712 append_indent(ctx);
713 append_integer_field_class_from_props(ctx, 64, 8, false,
714 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
715 NULL, "events_discarded", true);
716 }
717
718 /*
719 * Unconditionnally write the packet sequence number as, even if
720 * there's no possible discarded packets message, it's still
721 * useful information to have.
722 */
723 append_indent(ctx);
724 append_integer_field_class_from_props(ctx, 64, 8, false,
725 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
726 NULL, "packet_seq_num", true);
727
728 if (sc->packet_context_fc) {
729 append_struct_field_class_members(ctx,
730 (void *) sc->packet_context_fc);
731 fs_sink_ctf_field_class_struct_align_at_least(
732 (void *) sc->packet_context_fc, 8);
733 }
734
735 /* End packet context field class */
736 append_end_block(ctx);
737 g_string_append_printf(ctx->tsdl, " align(%u);\n\n",
738 sc->packet_context_fc ? sc->packet_context_fc->alignment : 8);
739
740 /* Event header field class */
741 append_indent(ctx);
742 g_string_append(ctx->tsdl, "event.header := struct {\n");
743 ctx->indent_level++;
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, "id", true);
748
749 if (sc->default_clock_class) {
750 append_indent(ctx);
751 append_integer_field_class_from_props(ctx, 64, 8, false,
752 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
753 sc->default_clock_class_name->str,
754 "timestamp", true);
755 }
756
757 /* End event header field class */
758 append_end_block(ctx);
759 g_string_append(ctx->tsdl, " align(8);\n");
760
761 /* Event common context field class */
762 if (sc->event_common_context_fc) {
763 append_indent(ctx);
764 g_string_append(ctx->tsdl, "event.context := ");
765 append_field_class(ctx,
766 (void *) 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, 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,
781 GString *tsdl)
782 {
783 struct ctx ctx = {
784 .indent_level = 0,
785 .tsdl = tsdl,
786 };
787 uint64_t i;
788 uint64_t count;
789
790 g_string_assign(tsdl, "/* CTF 1.8 */\n\n");
791 g_string_append(tsdl, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
792
793 /* Trace class */
794 append_indent(&ctx);
795 g_string_append(tsdl, "trace {\n");
796 ctx.indent_level++;
797
798 /* Trace class properties */
799 append_indent(&ctx);
800 g_string_append(tsdl, "major = 1;\n");
801 append_indent(&ctx);
802 g_string_append(tsdl, "minor = 8;\n");
803 append_indent(&ctx);
804 g_string_append(tsdl, "uuid = ");
805 append_uuid(&ctx, trace->uuid);
806 g_string_append(tsdl, ";\n");
807 append_indent(&ctx);
808 g_string_append(tsdl, "byte_order = ");
809
810 if (BYTE_ORDER == LITTLE_ENDIAN) {
811 g_string_append(tsdl, "le");
812 } else {
813 g_string_append(tsdl, "be");
814 }
815
816 g_string_append(tsdl, ";\n");
817
818 /* Packet header field class */
819 append_indent(&ctx);
820 g_string_append(tsdl, "packet.header := struct {\n");
821 ctx.indent_level++;
822 append_indent(&ctx);
823 append_integer_field_class_from_props(&ctx, 32, 8, false,
824 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
825 NULL, "magic", true);
826 append_indent(&ctx);
827 append_integer_field_class_from_props(&ctx, 8, 8, false,
828 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
829 NULL, "uuid[16]", true);
830 append_indent(&ctx);
831 append_integer_field_class_from_props(&ctx, 64, 8, false,
832 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
833 NULL, "stream_id", true);
834 append_indent(&ctx);
835 append_integer_field_class_from_props(&ctx, 64, 8, false,
836 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
837 NULL, "stream_instance_id", true);
838
839 /* End packet header field class */
840 append_end_block(&ctx);
841 g_string_append(ctx.tsdl, " align(8);\n");
842
843 /* End trace class */
844 append_end_block_semi_nl_nl(&ctx);
845
846 /* Trace environment */
847 count = bt_trace_get_environment_entry_count(trace->ir_trace);
848 if (count > 0) {
849 append_indent(&ctx);
850 g_string_append(tsdl, "env {\n");
851 ctx.indent_level++;
852
853 for (i = 0; i < count; i++) {
854 const char *name;
855 const bt_value *val;
856
857 bt_trace_borrow_environment_entry_by_index_const(
858 trace->ir_trace, i, &name, &val);
859 append_indent(&ctx);
860 g_string_append_printf(tsdl, "%s = ", name);
861
862 switch (bt_value_get_type(val)) {
863 case BT_VALUE_TYPE_SIGNED_INTEGER:
864 g_string_append_printf(tsdl, "%" PRId64,
865 bt_value_signed_integer_get(val));
866 break;
867 case BT_VALUE_TYPE_STRING:
868 append_quoted_string(&ctx, bt_value_string_get(val));
869 break;
870 default:
871 /*
872 * This is checked in
873 * translate_trace_trace_ir_to_ctf_ir().
874 */
875 abort();
876 }
877
878 g_string_append(tsdl, ";\n");
879 }
880
881 /* End trace class environment */
882 append_end_block_semi_nl_nl(&ctx);
883 }
884
885 /* Stream classes and their event classes */
886 for (i = 0; i < trace->stream_classes->len; i++) {
887 append_stream_class(&ctx, trace->stream_classes->pdata[i]);
888 }
889 }
This page took 0.048442 seconds and 3 git commands to generate.