Fix -Wmissing-prototypes/-Wmissing-declarations warnings
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-trace-ir-to-ctf-ir.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 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
24 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
25 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
26 #include "logging/comp-logging.h"
27
28 #include "translate-trace-ir-to-ctf-ir.h"
29
30 #include <babeltrace2/babeltrace.h>
31 #include "common/macros.h"
32 #include "common/common.h"
33 #include "common/assert.h"
34 #include <stdio.h>
35 #include <stdbool.h>
36 #include <string.h>
37 #include <glib.h>
38
39 #include "fs-sink.h"
40 #include "fs-sink-ctf-meta.h"
41
42 struct field_path_elem {
43 uint64_t index_in_parent;
44 GString *name;
45
46 /* Weak */
47 const bt_field_class *ir_fc;
48
49 /* Weak */
50 struct fs_sink_ctf_field_class *parent_fc;
51 };
52
53 struct ctx {
54 bt_logging_level log_level;
55 bt_self_component *self_comp;
56
57 /* Weak */
58 struct fs_sink_ctf_stream_class *cur_sc;
59
60 /* Weak */
61 struct fs_sink_ctf_event_class *cur_ec;
62
63 bt_field_path_scope cur_scope;
64
65 /*
66 * Array of `struct field_path_elem` */
67 GArray *cur_path;
68 };
69
70 static inline
71 struct field_path_elem *cur_path_stack_at(struct ctx *ctx, uint64_t i)
72 {
73 BT_ASSERT(i < ctx->cur_path->len);
74 return &g_array_index(ctx->cur_path, struct field_path_elem, i);
75 }
76
77 static inline
78 struct field_path_elem *cur_path_stack_top(struct ctx *ctx)
79 {
80 BT_ASSERT(ctx->cur_path->len > 0);
81 return cur_path_stack_at(ctx, ctx->cur_path->len - 1);
82 }
83
84 static inline
85 bool is_reserved_member_name(const char *name, const char *reserved_name)
86 {
87 bool is_reserved = false;
88
89 if (strcmp(name, reserved_name) == 0) {
90 is_reserved = true;
91 goto end;
92 }
93
94 if (name[0] == '_' && strcmp(&name[1], reserved_name) == 0) {
95 is_reserved = true;
96 goto end;
97 }
98
99 end:
100 return is_reserved;
101 }
102
103 static const char *reserved_tsdl_keywords[] = {
104 "align",
105 "callsite",
106 "const",
107 "char",
108 "clock",
109 "double",
110 "enum",
111 "env",
112 "event",
113 "floating_point",
114 "float",
115 "integer",
116 "int",
117 "long",
118 "short",
119 "signed",
120 "stream",
121 "string",
122 "struct",
123 "trace",
124 "typealias",
125 "typedef",
126 "unsigned",
127 "variant",
128 "void",
129 "_Bool",
130 "_Complex",
131 "_Imaginary",
132 };
133
134 static inline
135 bool ist_valid_identifier(const char *name)
136 {
137 const char *at;
138 uint64_t i;
139 bool ist_valid = true;
140
141 /* Make sure the name is not a reserved keyword */
142 for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
143 i++) {
144 if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
145 ist_valid = false;
146 goto end;
147 }
148 }
149
150 /* Make sure the name is not an empty string */
151 if (strlen(name) == 0) {
152 ist_valid = false;
153 goto end;
154 }
155
156 /* Make sure the name starts with a letter or `_` */
157 if (!isalpha(name[0]) && name[0] != '_') {
158 ist_valid = false;
159 goto end;
160 }
161
162 /* Make sure the name only contains letters, digits, and `_` */
163 for (at = name; *at != '\0'; at++) {
164 if (!isalnum(*at) && *at != '_') {
165 ist_valid = false;
166 goto end;
167 }
168 }
169
170 end:
171 return ist_valid;
172 }
173
174 static inline
175 bool must_protect_identifier(const char *name)
176 {
177 uint64_t i;
178 bool must_protect = false;
179
180 /* Protect a reserved keyword */
181 for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
182 i++) {
183 if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
184 must_protect = true;
185 goto end;
186 }
187 }
188
189 /* Protect an identifier which already starts with `_` */
190 if (name[0] == '_') {
191 must_protect = true;
192 goto end;
193 }
194
195 end:
196 return must_protect;
197 }
198
199 static inline
200 int cur_path_stack_push(struct ctx *ctx,
201 uint64_t index_in_parent, const char *name,
202 bool force_protect_name, const bt_field_class *ir_fc,
203 struct fs_sink_ctf_field_class *parent_fc)
204 {
205 int ret = 0;
206 struct field_path_elem *field_path_elem;
207
208 g_array_set_size(ctx->cur_path, ctx->cur_path->len + 1);
209 field_path_elem = cur_path_stack_top(ctx);
210 field_path_elem->index_in_parent = index_in_parent;
211 field_path_elem->name = g_string_new(NULL);
212
213 if (name) {
214 if (force_protect_name) {
215 g_string_assign(field_path_elem->name, "_");
216 }
217
218 g_string_append(field_path_elem->name, name);
219
220 if (ctx->cur_scope == BT_FIELD_PATH_SCOPE_PACKET_CONTEXT) {
221 if (is_reserved_member_name(name, "packet_size") ||
222 is_reserved_member_name(name, "content_size") ||
223 is_reserved_member_name(name, "timestamp_begin") ||
224 is_reserved_member_name(name, "timestamp_end") ||
225 is_reserved_member_name(name, "events_discarded") ||
226 is_reserved_member_name(name, "packet_seq_num")) {
227 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
228 "or variant field class option name: name=\"%s\"",
229 name);
230 ret = -1;
231 goto end;
232 }
233 }
234
235 if (!ist_valid_identifier(field_path_elem->name->str)) {
236 ret = -1;
237 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
238 "or variant field class option name: name=\"%s\"",
239 field_path_elem->name->str);
240 goto end;
241 }
242 }
243
244 field_path_elem->ir_fc = ir_fc;
245 field_path_elem->parent_fc = parent_fc;
246
247 end:
248 return ret;
249 }
250
251 static inline
252 void cur_path_stack_pop(struct ctx *ctx)
253 {
254 struct field_path_elem *field_path_elem;
255
256 BT_ASSERT(ctx->cur_path->len > 0);
257 field_path_elem = cur_path_stack_top(ctx);
258
259 if (field_path_elem->name) {
260 g_string_free(field_path_elem->name, TRUE);
261 field_path_elem->name = NULL;
262 }
263
264 g_array_set_size(ctx->cur_path, ctx->cur_path->len - 1);
265 }
266
267 /*
268 * Creates a relative field ref (a single name) from IR field path
269 * `tgt_ir_field_path`.
270 *
271 * This function tries to locate the target field class recursively from
272 * the top to the bottom of the context's current path using only the
273 * target field class's own name. This is because many CTF reading tools
274 * do not support a relative field ref with more than one element, for
275 * example `prev_struct.len`.
276 *
277 * Returns a negative value if this resolving operation failed.
278 */
279 static
280 int create_relative_field_ref(struct ctx *ctx,
281 const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
282 struct fs_sink_ctf_field_class **user_tgt_fc)
283 {
284 int ret = 0;
285 struct fs_sink_ctf_field_class *tgt_fc = NULL;
286 uint64_t i;
287 int64_t si;
288 const char *tgt_fc_name = NULL;
289 struct field_path_elem *field_path_elem;
290
291 /* Get target field class's name */
292 switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
293 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
294 BT_ASSERT(ctx->cur_sc);
295 tgt_fc = ctx->cur_sc->packet_context_fc;
296 break;
297 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
298 BT_ASSERT(ctx->cur_sc);
299 tgt_fc = ctx->cur_sc->event_common_context_fc;
300 break;
301 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
302 BT_ASSERT(ctx->cur_ec);
303 tgt_fc = ctx->cur_ec->spec_context_fc;
304 break;
305 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
306 BT_ASSERT(ctx->cur_ec);
307 tgt_fc = ctx->cur_ec->payload_fc;
308 break;
309 default:
310 abort();
311 }
312
313 i = 0;
314
315 while (i < bt_field_path_get_item_count(tgt_ir_field_path)) {
316 const bt_field_path_item *fp_item =
317 bt_field_path_borrow_item_by_index_const(
318 tgt_ir_field_path, i);
319 struct fs_sink_ctf_named_field_class *named_fc = NULL;
320
321 BT_ASSERT(tgt_fc);
322 BT_ASSERT(fp_item);
323
324 if (bt_field_path_item_get_type(fp_item) ==
325 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT) {
326 /* Not supported by CTF 1.8 */
327 ret = -1;
328 goto end;
329 }
330
331 switch (tgt_fc->type) {
332 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
333 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
334 BT_FIELD_PATH_ITEM_TYPE_INDEX);
335 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
336 (void *) tgt_fc,
337 bt_field_path_item_index_get_index(fp_item));
338 break;
339 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
340 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
341 BT_FIELD_PATH_ITEM_TYPE_INDEX);
342 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
343 (void *) tgt_fc,
344 bt_field_path_item_index_get_index(fp_item));
345 break;
346 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
347 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
348 {
349 struct fs_sink_ctf_field_class_array_base *array_base_fc =
350 (void *) tgt_fc;
351
352 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
353 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT);
354 tgt_fc = array_base_fc->elem_fc;
355 break;
356 }
357 default:
358 abort();
359 }
360
361 if (named_fc) {
362 tgt_fc = named_fc->fc;
363 tgt_fc_name = named_fc->name->str;
364 i++;
365 }
366 }
367
368 BT_ASSERT(tgt_fc);
369 BT_ASSERT(tgt_fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_INT);
370 BT_ASSERT(tgt_fc_name);
371
372 /* Find target field class having this name in current context */
373 for (si = ctx->cur_path->len - 1; si >= 0; si--) {
374 struct fs_sink_ctf_field_class *fc;
375 struct fs_sink_ctf_field_class_struct *struct_fc = NULL;
376 struct fs_sink_ctf_field_class_variant *var_fc = NULL;
377 struct fs_sink_ctf_named_field_class *named_fc;
378 uint64_t len;
379
380 field_path_elem = cur_path_stack_at(ctx, (uint64_t) si);
381 fc = field_path_elem->parent_fc;
382 if (!fc) {
383 /* Reached stack's bottom */
384 ret = -1;
385 goto end;
386 }
387
388 switch (fc->type) {
389 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
390 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
391 break;
392 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
393 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
394 continue;
395 default:
396 /* Not supported by TSDL 1.8 */
397 ret = -1;
398 goto end;
399 }
400
401 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
402 struct_fc = (void *) fc;
403 len = struct_fc->members->len;
404 } else {
405 var_fc = (void *) fc;
406 len = var_fc->options->len;
407 }
408
409 for (i = 0; i < len; i++) {
410 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
411 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
412 struct_fc, i);
413 } else {
414 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
415 var_fc, i);
416 }
417
418 if (strcmp(named_fc->name->str, tgt_fc_name) == 0) {
419 if (named_fc->fc == tgt_fc) {
420 g_string_assign(tgt_field_ref,
421 tgt_fc_name);
422
423 if (user_tgt_fc) {
424 *user_tgt_fc = tgt_fc;
425 }
426 } else {
427 /*
428 * Using only the target field
429 * class's name, we're not
430 * reaching the target field
431 * class. This is not supported
432 * by TSDL 1.8.
433 */
434 ret = -1;
435 }
436
437 goto end;
438 }
439 }
440 }
441
442 end:
443 return ret;
444 }
445
446 /*
447 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
448 *
449 * Returns a negative value if this resolving operation failed.
450 */
451 static
452 int create_absolute_field_ref(struct ctx *ctx,
453 const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
454 struct fs_sink_ctf_field_class **user_tgt_fc)
455 {
456 int ret = 0;
457 struct fs_sink_ctf_field_class *fc = NULL;
458 uint64_t i;
459
460 switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
461 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
462 BT_ASSERT(ctx->cur_sc);
463 fc = ctx->cur_sc->packet_context_fc;
464 g_string_assign(tgt_field_ref, "stream.packet.context");
465 break;
466 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
467 BT_ASSERT(ctx->cur_sc);
468 fc = ctx->cur_sc->event_common_context_fc;
469 g_string_assign(tgt_field_ref, "stream.event.context");
470 break;
471 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
472 BT_ASSERT(ctx->cur_ec);
473 fc = ctx->cur_ec->spec_context_fc;
474 g_string_assign(tgt_field_ref, "event.context");
475 break;
476 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
477 BT_ASSERT(ctx->cur_ec);
478 fc = ctx->cur_ec->payload_fc;
479 g_string_assign(tgt_field_ref, "event.fields");
480 break;
481 default:
482 abort();
483 }
484
485 BT_ASSERT(fc);
486
487 for (i = 0; i < bt_field_path_get_item_count(tgt_ir_field_path); i++) {
488 const bt_field_path_item *fp_item =
489 bt_field_path_borrow_item_by_index_const(
490 tgt_ir_field_path, i);
491 struct fs_sink_ctf_named_field_class *named_fc = NULL;
492
493 if (bt_field_path_item_get_type(fp_item) !=
494 BT_FIELD_PATH_ITEM_TYPE_INDEX) {
495 /* Not supported by TSDL 1.8 */
496 ret = -1;
497 goto end;
498 }
499
500 switch (fc->type) {
501 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
502 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
503 BT_FIELD_PATH_ITEM_TYPE_INDEX);
504 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
505 (void *) fc,
506 bt_field_path_item_index_get_index(fp_item));
507 break;
508 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
509 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
510 BT_FIELD_PATH_ITEM_TYPE_INDEX);
511 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
512 (void *) fc,
513 bt_field_path_item_index_get_index(fp_item));
514 break;
515 default:
516 abort();
517 }
518
519 BT_ASSERT(named_fc);
520 g_string_append_c(tgt_field_ref, '.');
521 g_string_append(tgt_field_ref, named_fc->name->str);
522 fc = named_fc->fc;
523 }
524
525 if (user_tgt_fc) {
526 *user_tgt_fc = fc;
527 }
528
529 end:
530 return ret;
531 }
532
533 /*
534 * Resolves a target field class located at `tgt_ir_field_path`, writing
535 * the resolved field ref to `tgt_field_ref` and setting
536 * `*create_before` according to whether or not the target field must be
537 * created immediately before (in which case `tgt_field_ref` is
538 * irrelevant).
539 */
540 static
541 void resolve_field_class(struct ctx *ctx,
542 const bt_field_path *tgt_ir_field_path,
543 GString *tgt_field_ref, bool *create_before,
544 struct fs_sink_ctf_field_class **user_tgt_fc)
545 {
546 int ret;
547 bt_field_path_scope tgt_scope;
548
549 *create_before = false;
550
551 if (!tgt_ir_field_path) {
552 *create_before = true;
553 goto end;
554 }
555
556 tgt_scope = bt_field_path_get_root_scope(tgt_ir_field_path);
557
558 if (tgt_scope == ctx->cur_scope) {
559 /*
560 * Try, in this order:
561 *
562 * 1. Use a relative path, using only the target field
563 * class's name. This is what is the most commonly
564 * supported by popular CTF reading tools.
565 *
566 * 2. Use an absolute path. This could fail if there's
567 * an array field class from the current root's field
568 * class to the target field class.
569 *
570 * 3. Create the target field class before the
571 * requesting field class (fallback).
572 */
573 ret = create_relative_field_ref(ctx, tgt_ir_field_path,
574 tgt_field_ref, user_tgt_fc);
575 if (ret) {
576 ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
577 tgt_field_ref, user_tgt_fc);
578 if (ret) {
579 *create_before = true;
580 goto end;
581 }
582 }
583 } else {
584 ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
585 tgt_field_ref, user_tgt_fc);
586
587 /* It must always work in previous scopes */
588 BT_ASSERT(ret == 0);
589 }
590
591 end:
592 return;
593 }
594
595 static
596 int translate_field_class(struct ctx *ctx);
597
598 static inline
599 void append_to_parent_field_class(struct ctx *ctx,
600 struct fs_sink_ctf_field_class *fc)
601 {
602 struct fs_sink_ctf_field_class *parent_fc =
603 cur_path_stack_top(ctx)->parent_fc;
604
605 switch (parent_fc->type) {
606 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
607 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc,
608 cur_path_stack_top(ctx)->name->str, fc);
609 break;
610 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
611 {
612 struct fs_sink_ctf_field_class_option *opt_fc =
613 (void *) parent_fc;
614
615 BT_ASSERT(!opt_fc->content_fc);
616 opt_fc->content_fc = fc;
617 opt_fc->base.alignment = fc->alignment;
618 break;
619 }
620 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
621 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc,
622 cur_path_stack_top(ctx)->name->str, fc);
623 break;
624 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
625 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
626 {
627 struct fs_sink_ctf_field_class_array_base *array_base_fc =
628 (void *) parent_fc;
629
630 BT_ASSERT(!array_base_fc->elem_fc);
631 array_base_fc->elem_fc = fc;
632 array_base_fc->base.alignment = fc->alignment;
633 break;
634 }
635 default:
636 abort();
637 }
638 }
639
640 static inline
641 void update_parent_field_class_alignment(struct ctx *ctx,
642 unsigned int alignment)
643 {
644 struct fs_sink_ctf_field_class *parent_fc =
645 cur_path_stack_top(ctx)->parent_fc;
646
647 switch (parent_fc->type) {
648 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
649 fs_sink_ctf_field_class_struct_align_at_least(
650 (void *) parent_fc, alignment);
651 break;
652 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
653 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
654 {
655 struct fs_sink_ctf_field_class_array_base *array_base_fc =
656 (void *) parent_fc;
657
658 array_base_fc->base.alignment = alignment;
659 break;
660 }
661 default:
662 break;
663 }
664 }
665
666 static inline
667 int translate_structure_field_class_members(struct ctx *ctx,
668 struct fs_sink_ctf_field_class_struct *struct_fc,
669 const bt_field_class *ir_fc)
670 {
671 int ret = 0;
672 uint64_t i;
673
674 for (i = 0; i < bt_field_class_structure_get_member_count(ir_fc); i++) {
675 const bt_field_class_structure_member *member;
676 const char *name;
677 const bt_field_class *memb_ir_fc;
678
679 member =
680 bt_field_class_structure_borrow_member_by_index_const(
681 ir_fc, i);
682 name = bt_field_class_structure_member_get_name(member);
683 memb_ir_fc = bt_field_class_structure_member_borrow_field_class_const(
684 member);
685 ret = cur_path_stack_push(ctx, i, name, true, memb_ir_fc,
686 (void *) struct_fc);
687 if (ret) {
688 BT_COMP_LOGE("Cannot translate structure field class member: "
689 "name=\"%s\"", name);
690 goto end;
691 }
692
693 ret = translate_field_class(ctx);
694 if (ret) {
695 BT_COMP_LOGE("Cannot translate structure field class member: "
696 "name=\"%s\"", name);
697 goto end;
698 }
699
700 cur_path_stack_pop(ctx);
701 }
702
703 end:
704 return ret;
705 }
706
707 static inline
708 int translate_structure_field_class(struct ctx *ctx)
709 {
710 int ret;
711 struct fs_sink_ctf_field_class_struct *fc =
712 fs_sink_ctf_field_class_struct_create_empty(
713 cur_path_stack_top(ctx)->ir_fc,
714 cur_path_stack_top(ctx)->index_in_parent);
715
716 BT_ASSERT(fc);
717 append_to_parent_field_class(ctx, (void *) fc);
718 ret = translate_structure_field_class_members(ctx, fc, fc->base.ir_fc);
719 if (ret) {
720 goto end;
721 }
722
723 update_parent_field_class_alignment(ctx, fc->base.alignment);
724
725 end:
726 return ret;
727 }
728
729 /*
730 * This function protects a given variant FC option name (with the `_`
731 * prefix) if required. On success, `name_buf->str` contains the variant
732 * FC option name to use (original option name or protected if
733 * required).
734 *
735 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
736 * close as possible to an original CTF trace as decoded by
737 * `src.ctf.fs`.
738 *
739 * This scenario is valid in CTF 1.8:
740 *
741 * enum {
742 * HELLO,
743 * MEOW
744 * } tag;
745 *
746 * variant <tag> {
747 * int HELLO;
748 * string MEOW;
749 * };
750 *
751 * Once in trace IR, the enumeration FC mapping names and variant FC
752 * option names are kept as is. For this reason, we don't want to
753 * protect the variant FC option names here (by prepending `_`): this
754 * would make the variant FC option name and the enumeration FC mapping
755 * name not match.
756 *
757 * This scenario is also valid in CTF 1.8:
758 *
759 * enum {
760 * _HELLO,
761 * MEOW
762 * } tag;
763 *
764 * variant <tag> {
765 * int _HELLO;
766 * string MEOW;
767 * };
768 *
769 * Once in trace IR, the enumeration FC mapping names are kept as is,
770 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
771 * for presentation, as recommended by CTF 1.8). When going back to
772 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
773 * the corresponding enumeration FC mapping name.
774 *
775 * This scenario is also valid in CTF 1.8:
776 *
777 * enum {
778 * __HELLO,
779 * MEOW
780 * } tag;
781 *
782 * variant <tag> {
783 * int __HELLO;
784 * string MEOW;
785 * };
786 *
787 * Once in trace IR, the enumeration FC mapping names are kept as is,
788 * but the `__HELLO` variant FC option name becomes `_HELLO`
789 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
790 * so that it becomes `__HELLO` to match the corresponding enumeration
791 * FC mapping name.
792 *
793 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
794 * FC mapping and a corresponding variant FC option. We can use that
795 * fact to find the original variant FC option names by matching variant
796 * FC options and enumeration FC mappings by range set.
797 */
798 static
799 int maybe_protect_variant_option_name(const bt_field_class *ir_var_fc,
800 const bt_field_class *ir_tag_fc, uint64_t opt_i,
801 GString *name_buf)
802 {
803 int ret = 0;
804 uint64_t i;
805 bt_field_class_type ir_var_fc_type;
806 const void *opt_ranges = NULL;
807 const char *mapping_label = NULL;
808 const char *ir_opt_name;
809 const bt_field_class_variant_option *base_var_opt;
810 bool force_protect = false;
811
812 ir_var_fc_type = bt_field_class_get_type(ir_var_fc);
813 base_var_opt = bt_field_class_variant_borrow_option_by_index_const(
814 ir_var_fc, opt_i);
815 BT_ASSERT(base_var_opt);
816 ir_opt_name = bt_field_class_variant_option_get_name(base_var_opt);
817 BT_ASSERT(ir_opt_name);
818
819 /*
820 * Check if the variant FC option name is required to be
821 * protected (reserved TSDL keyword or starts with `_`). In that
822 * case, the name of the selector FC mapping we find must match
823 * exactly the protected name.
824 */
825 force_protect = must_protect_identifier(ir_opt_name);
826 if (force_protect) {
827 g_string_assign(name_buf, "_");
828 g_string_append(name_buf, ir_opt_name);
829 } else {
830 g_string_assign(name_buf, ir_opt_name);
831 }
832
833 /* Borrow option's ranges */
834 if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD) {
835 /* No ranges: we're done */
836 goto end;
837 } if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) {
838 const bt_field_class_variant_with_selector_field_integer_unsigned_option *var_opt =
839 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
840 ir_var_fc, opt_i);
841 opt_ranges =
842 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
843 var_opt);
844 } else {
845 const bt_field_class_variant_with_selector_field_integer_signed_option *var_opt =
846 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
847 ir_var_fc, opt_i);
848 opt_ranges =
849 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
850 var_opt);
851 }
852
853 /* Find corresponding mapping by range set in selector FC */
854 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_tag_fc);
855 i++) {
856 if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) {
857 const bt_field_class_enumeration_mapping *mapping_base;
858 const bt_field_class_enumeration_unsigned_mapping *mapping;
859 const bt_integer_range_set_unsigned *mapping_ranges;
860
861 mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
862 ir_tag_fc, i);
863 mapping_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
864 mapping);
865
866 if (bt_integer_range_set_unsigned_is_equal(opt_ranges,
867 mapping_ranges)) {
868 /* We have a winner */
869 mapping_base =
870 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
871 mapping);
872 mapping_label =
873 bt_field_class_enumeration_mapping_get_label(
874 mapping_base);
875 break;
876 }
877 } else {
878 const bt_field_class_enumeration_mapping *mapping_base;
879 const bt_field_class_enumeration_signed_mapping *mapping;
880 const bt_integer_range_set_signed *mapping_ranges;
881
882 mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
883 ir_tag_fc, i);
884 mapping_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
885 mapping);
886
887 if (bt_integer_range_set_signed_is_equal(opt_ranges,
888 mapping_ranges)) {
889 /* We have a winner */
890 mapping_base =
891 bt_field_class_enumeration_signed_mapping_as_mapping_const(
892 mapping);
893 mapping_label =
894 bt_field_class_enumeration_mapping_get_label(
895 mapping_base);
896 break;
897 }
898 }
899 }
900
901 if (!mapping_label) {
902 /* Range set not found: invalid selector for CTF 1.8 */
903 ret = -1;
904 goto end;
905 }
906
907 /*
908 * If the enumeration FC mapping name is not the same as the
909 * variant FC option name and we didn't protect already, try
910 * protecting the option name and check again.
911 */
912 if (strcmp(mapping_label, name_buf->str) != 0) {
913 if (force_protect) {
914 ret = -1;
915 goto end;
916 }
917
918 if (mapping_label[0] == '\0') {
919 ret = -1;
920 goto end;
921 }
922
923 g_string_assign(name_buf, "_");
924 g_string_append(name_buf, ir_opt_name);
925
926 if (strcmp(mapping_label, name_buf->str) != 0) {
927 ret = -1;
928 goto end;
929 }
930 }
931
932 end:
933 return ret;
934 }
935
936 static inline
937 int translate_option_field_class(struct ctx *ctx)
938 {
939 struct fs_sink_ctf_field_class_option *fc =
940 fs_sink_ctf_field_class_option_create_empty(
941 cur_path_stack_top(ctx)->ir_fc,
942 cur_path_stack_top(ctx)->index_in_parent);
943 const bt_field_class *content_ir_fc =
944 bt_field_class_option_borrow_field_class_const(fc->base.ir_fc);
945 int ret;
946
947 BT_ASSERT(fc);
948
949 /*
950 * CTF 1.8 does not support the option field class type. To
951 * write something anyway, this component translates this type
952 * to a variant field class where the options are:
953 *
954 * * An empty structure field class.
955 * * The optional field class itself.
956 *
957 * The "tag" is always generated/before in that case (an 8-bit
958 * unsigned enumeration field class).
959 */
960 append_to_parent_field_class(ctx, (void *) fc);
961 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, content_ir_fc,
962 (void *) fc);
963 if (ret) {
964 BT_COMP_LOGE_STR("Cannot translate option field class content.");
965 goto end;
966 }
967
968 ret = translate_field_class(ctx);
969 if (ret) {
970 BT_COMP_LOGE_STR("Cannot translate option field class content.");
971 goto end;
972 }
973
974 cur_path_stack_pop(ctx);
975 update_parent_field_class_alignment(ctx, fc->base.alignment);
976
977 end:
978 return ret;
979 }
980
981 static inline
982 int translate_variant_field_class(struct ctx *ctx)
983 {
984 int ret = 0;
985 uint64_t i;
986 struct fs_sink_ctf_field_class_variant *fc =
987 fs_sink_ctf_field_class_variant_create_empty(
988 cur_path_stack_top(ctx)->ir_fc,
989 cur_path_stack_top(ctx)->index_in_parent);
990 bt_field_class_type ir_fc_type;
991 const bt_field_path *ir_selector_field_path = NULL;
992 struct fs_sink_ctf_field_class *tgt_fc = NULL;
993 GString *name_buf = g_string_new(NULL);
994 bt_value *prot_opt_names = bt_value_array_create();
995 uint64_t opt_count;
996
997 BT_ASSERT(fc);
998 BT_ASSERT(name_buf);
999 BT_ASSERT(prot_opt_names);
1000 ir_fc_type = bt_field_class_get_type(fc->base.ir_fc);
1001 opt_count = bt_field_class_variant_get_option_count(fc->base.ir_fc);
1002
1003 if (bt_field_class_type_is(ir_fc_type,
1004 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD)) {
1005 ir_selector_field_path = bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
1006 fc->base.ir_fc);
1007 BT_ASSERT(ir_selector_field_path);
1008 }
1009
1010 /* Resolve tag field class before appending to parent */
1011 resolve_field_class(ctx, ir_selector_field_path, fc->tag_ref,
1012 &fc->tag_is_before, &tgt_fc);
1013
1014 if (ir_selector_field_path && tgt_fc) {
1015 uint64_t mapping_count;
1016 uint64_t option_count;
1017
1018 /* CTF 1.8: selector FC must be an enumeration FC */
1019 bt_field_class_type type = bt_field_class_get_type(
1020 tgt_fc->ir_fc);
1021
1022 if (!bt_field_class_type_is(type,
1023 BT_FIELD_CLASS_TYPE_ENUMERATION)) {
1024 fc->tag_is_before = true;
1025 goto validate_opts;
1026 }
1027
1028 /*
1029 * Call maybe_protect_variant_option_name() for each
1030 * option below. In that case we also want selector FC
1031 * to contain as many mappings as the variant FC has
1032 * options.
1033 */
1034 mapping_count = bt_field_class_enumeration_get_mapping_count(
1035 tgt_fc->ir_fc);
1036 option_count = bt_field_class_variant_get_option_count(
1037 fc->base.ir_fc);
1038
1039 if (mapping_count != option_count) {
1040 fc->tag_is_before = true;
1041 goto validate_opts;
1042 }
1043 } else {
1044 /*
1045 * No compatible selector field class for CTF 1.8:
1046 * create the appropriate selector field class.
1047 */
1048 fc->tag_is_before = true;
1049 goto validate_opts;
1050 }
1051
1052 validate_opts:
1053 /*
1054 * First pass: detect any option name clash with option name
1055 * protection. In that case, we don't fail: just create the
1056 * selector field class before the variant field class.
1057 *
1058 * After this, `prot_opt_names` contains the final option names,
1059 * potentially protected if needed. They can still be invalid
1060 * TSDL identifiers however; this will be checked by
1061 * cur_path_stack_push().
1062 */
1063 for (i = 0; i < opt_count; i++) {
1064 if (!fc->tag_is_before) {
1065 BT_ASSERT(tgt_fc->ir_fc);
1066 ret = maybe_protect_variant_option_name(fc->base.ir_fc,
1067 tgt_fc->ir_fc, i, name_buf);
1068 if (ret) {
1069 fc->tag_is_before = true;
1070 }
1071 }
1072
1073 ret = bt_value_array_append_string_element(prot_opt_names,
1074 name_buf->str);
1075 if (ret) {
1076 goto end;
1077 }
1078 }
1079
1080 for (i = 0; i < opt_count; i++) {
1081 uint64_t j;
1082 const bt_value *opt_name_a =
1083 bt_value_array_borrow_element_by_index_const(
1084 prot_opt_names, i);
1085
1086 for (j = 0; j < opt_count; j++) {
1087 const bt_value *opt_name_b;
1088
1089 if (i == j) {
1090 continue;
1091 }
1092
1093 opt_name_b =
1094 bt_value_array_borrow_element_by_index_const(
1095 prot_opt_names, j);
1096 if (bt_value_is_equal(opt_name_a, opt_name_b)) {
1097 /*
1098 * Variant FC option names are not
1099 * unique when protected.
1100 */
1101 fc->tag_is_before = true;
1102 goto append_to_parent;
1103 }
1104 }
1105 }
1106
1107 append_to_parent:
1108 append_to_parent_field_class(ctx, (void *) fc);
1109
1110 for (i = 0; i < opt_count; i++) {
1111 const bt_field_class_variant_option *opt;
1112 const bt_field_class *opt_ir_fc;
1113 const bt_value *prot_opt_name_val =
1114 bt_value_array_borrow_element_by_index_const(
1115 prot_opt_names, i);
1116 const char *prot_opt_name = bt_value_string_get(
1117 prot_opt_name_val);
1118
1119 BT_ASSERT(prot_opt_name);
1120 opt = bt_field_class_variant_borrow_option_by_index_const(
1121 fc->base.ir_fc, i);
1122 opt_ir_fc = bt_field_class_variant_option_borrow_field_class_const(
1123 opt);
1124
1125 /*
1126 * We don't ask cur_path_stack_push() to protect the
1127 * option name because it's already protected at this
1128 * point.
1129 */
1130 ret = cur_path_stack_push(ctx, i, prot_opt_name, false,
1131 opt_ir_fc, (void *) fc);
1132 if (ret) {
1133 BT_COMP_LOGE("Cannot translate variant field class option: "
1134 "name=\"%s\"", prot_opt_name);
1135 goto end;
1136 }
1137
1138 ret = translate_field_class(ctx);
1139 if (ret) {
1140 BT_COMP_LOGE("Cannot translate variant field class option: "
1141 "name=\"%s\"", prot_opt_name);
1142 goto end;
1143 }
1144
1145 cur_path_stack_pop(ctx);
1146 }
1147
1148 end:
1149 if (name_buf) {
1150 g_string_free(name_buf, TRUE);
1151 }
1152
1153 bt_value_put_ref(prot_opt_names);
1154 return ret;
1155 }
1156
1157 static inline
1158 int translate_static_array_field_class(struct ctx *ctx)
1159 {
1160 struct fs_sink_ctf_field_class_array *fc =
1161 fs_sink_ctf_field_class_array_create_empty(
1162 cur_path_stack_top(ctx)->ir_fc,
1163 cur_path_stack_top(ctx)->index_in_parent);
1164 const bt_field_class *elem_ir_fc =
1165 bt_field_class_array_borrow_element_field_class_const(
1166 fc->base.base.ir_fc);
1167 int ret;
1168
1169 BT_ASSERT(fc);
1170 append_to_parent_field_class(ctx, (void *) fc);
1171 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
1172 (void *) fc);
1173 if (ret) {
1174 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1175 goto end;
1176 }
1177
1178 ret = translate_field_class(ctx);
1179 if (ret) {
1180 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1181 goto end;
1182 }
1183
1184 cur_path_stack_pop(ctx);
1185 update_parent_field_class_alignment(ctx, fc->base.base.alignment);
1186
1187 end:
1188 return ret;
1189 }
1190
1191 static inline
1192 int translate_dynamic_array_field_class(struct ctx *ctx)
1193 {
1194 struct fs_sink_ctf_field_class_sequence *fc =
1195 fs_sink_ctf_field_class_sequence_create_empty(
1196 cur_path_stack_top(ctx)->ir_fc,
1197 cur_path_stack_top(ctx)->index_in_parent);
1198 const bt_field_class *elem_ir_fc =
1199 bt_field_class_array_borrow_element_field_class_const(
1200 fc->base.base.ir_fc);
1201 int ret;
1202
1203 BT_ASSERT(fc);
1204
1205 /* Resolve length field class before appending to parent */
1206 if (bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc) ==
1207 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD) {
1208 resolve_field_class(ctx,
1209 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1210 fc->base.base.ir_fc),
1211 fc->length_ref, &fc->length_is_before, NULL);
1212 }
1213
1214 append_to_parent_field_class(ctx, (void *) fc);
1215 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
1216 (void *) fc);
1217 if (ret) {
1218 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1219 goto end;
1220 }
1221
1222 ret = translate_field_class(ctx);
1223 if (ret) {
1224 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1225 goto end;
1226 }
1227
1228 cur_path_stack_pop(ctx);
1229 update_parent_field_class_alignment(ctx, fc->base.base.alignment);
1230
1231 end:
1232 return ret;
1233 }
1234
1235 static inline
1236 int translate_bool_field_class(struct ctx *ctx)
1237 {
1238 struct fs_sink_ctf_field_class_bool *fc =
1239 fs_sink_ctf_field_class_bool_create(
1240 cur_path_stack_top(ctx)->ir_fc,
1241 cur_path_stack_top(ctx)->index_in_parent);
1242
1243 BT_ASSERT(fc);
1244 append_to_parent_field_class(ctx, (void *) fc);
1245 return 0;
1246 }
1247
1248 static inline
1249 int translate_bit_array_field_class(struct ctx *ctx)
1250 {
1251 struct fs_sink_ctf_field_class_bit_array *fc =
1252 fs_sink_ctf_field_class_bit_array_create(
1253 cur_path_stack_top(ctx)->ir_fc,
1254 cur_path_stack_top(ctx)->index_in_parent);
1255
1256 BT_ASSERT(fc);
1257 append_to_parent_field_class(ctx, (void *) fc);
1258 return 0;
1259 }
1260
1261 static inline
1262 int translate_integer_field_class(struct ctx *ctx)
1263 {
1264 struct fs_sink_ctf_field_class_int *fc =
1265 fs_sink_ctf_field_class_int_create(
1266 cur_path_stack_top(ctx)->ir_fc,
1267 cur_path_stack_top(ctx)->index_in_parent);
1268
1269 BT_ASSERT(fc);
1270 append_to_parent_field_class(ctx, (void *) fc);
1271 return 0;
1272 }
1273
1274 static inline
1275 int translate_real_field_class(struct ctx *ctx)
1276 {
1277 struct fs_sink_ctf_field_class_float *fc =
1278 fs_sink_ctf_field_class_float_create(
1279 cur_path_stack_top(ctx)->ir_fc,
1280 cur_path_stack_top(ctx)->index_in_parent);
1281
1282 BT_ASSERT(fc);
1283 append_to_parent_field_class(ctx, (void *) fc);
1284 return 0;
1285 }
1286
1287 static inline
1288 int translate_string_field_class(struct ctx *ctx)
1289 {
1290 struct fs_sink_ctf_field_class_string *fc =
1291 fs_sink_ctf_field_class_string_create(
1292 cur_path_stack_top(ctx)->ir_fc,
1293 cur_path_stack_top(ctx)->index_in_parent);
1294
1295 BT_ASSERT(fc);
1296 append_to_parent_field_class(ctx, (void *) fc);
1297 return 0;
1298 }
1299
1300 /*
1301 * Translates a field class, recursively.
1302 *
1303 * The field class's IR field class, parent field class, and index
1304 * within its parent are in the context's current path's top element
1305 * (cur_path_stack_top()).
1306 */
1307 static
1308 int translate_field_class(struct ctx *ctx)
1309 {
1310 int ret;
1311 bt_field_class_type ir_fc_type =
1312 bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc);
1313
1314 if (ir_fc_type == BT_FIELD_CLASS_TYPE_BOOL) {
1315 ret = translate_bool_field_class(ctx);
1316 } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_BIT_ARRAY) {
1317 ret = translate_bit_array_field_class(ctx);
1318 } else if (bt_field_class_type_is(ir_fc_type,
1319 BT_FIELD_CLASS_TYPE_INTEGER)) {
1320 ret = translate_integer_field_class(ctx);
1321 } else if (bt_field_class_type_is(ir_fc_type,
1322 BT_FIELD_CLASS_TYPE_REAL)) {
1323 ret = translate_real_field_class(ctx);
1324 } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STRING) {
1325 ret = translate_string_field_class(ctx);
1326 } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) {
1327 ret = translate_structure_field_class(ctx);
1328 } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) {
1329 ret = translate_static_array_field_class(ctx);
1330 } else if (bt_field_class_type_is(ir_fc_type,
1331 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY)) {
1332 ret = translate_dynamic_array_field_class(ctx);
1333 } else if (bt_field_class_type_is(ir_fc_type,
1334 BT_FIELD_CLASS_TYPE_OPTION)) {
1335 ret = translate_option_field_class(ctx);
1336 } else if (bt_field_class_type_is(ir_fc_type,
1337 BT_FIELD_CLASS_TYPE_VARIANT)) {
1338 ret = translate_variant_field_class(ctx);
1339 } else {
1340 abort();
1341 }
1342
1343 return ret;
1344 }
1345
1346 static
1347 int set_field_ref(struct fs_sink_ctf_field_class *fc, const char *fc_name,
1348 struct fs_sink_ctf_field_class *parent_fc)
1349 {
1350 int ret = 0;
1351 GString *field_ref = NULL;
1352 bool is_before;
1353 const char *tgt_type;
1354 struct fs_sink_ctf_field_class_struct *parent_struct_fc =
1355 (void *) parent_fc;
1356 uint64_t i;
1357 unsigned int suffix = 0;
1358
1359 if (!fc_name || !parent_fc ||
1360 parent_fc->type != FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1361 /* Not supported */
1362 ret = -1;
1363 goto end;
1364 }
1365
1366 switch (fc->type) {
1367 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
1368 {
1369 /*
1370 * CTF 1.8 does not support the option field class type.
1371 * To write something anyway, this component translates
1372 * this type to a variant field class where the options
1373 * are:
1374 *
1375 * * An empty structure field class.
1376 * * The optional field class itself.
1377 *
1378 * Because the option field class becomes a CTF variant
1379 * field class, we use the term "tag" too here.
1380 *
1381 * The "tag" is always generated/before in that case (an
1382 * 8-bit unsigned enumeration field class).
1383 */
1384 struct fs_sink_ctf_field_class_option *opt_fc = (void *) fc;
1385
1386 field_ref = opt_fc->tag_ref;
1387 is_before = true;
1388 tgt_type = "tag";
1389 break;
1390 }
1391 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
1392 {
1393 struct fs_sink_ctf_field_class_sequence *seq_fc = (void *) fc;
1394
1395 field_ref = seq_fc->length_ref;
1396 is_before = seq_fc->length_is_before;
1397 tgt_type = "len";
1398 break;
1399 }
1400 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
1401 {
1402 struct fs_sink_ctf_field_class_variant *var_fc = (void *) fc;
1403
1404 field_ref = var_fc->tag_ref;
1405 is_before = var_fc->tag_is_before;
1406 tgt_type = "tag";
1407 break;
1408 }
1409 default:
1410 abort();
1411 }
1412
1413 BT_ASSERT(field_ref);
1414
1415 if (!is_before) {
1416 goto end;
1417 }
1418
1419 /* Initial field ref */
1420 g_string_printf(field_ref, "__%s_%s", fc_name, tgt_type);
1421
1422 /*
1423 * Make sure field ref does not clash with an existing field
1424 * class name within the same parent structure field class.
1425 */
1426 while (true) {
1427 bool name_ok = true;
1428
1429 for (i = 0; i < parent_struct_fc->members->len; i++) {
1430 struct fs_sink_ctf_named_field_class *named_fc =
1431 fs_sink_ctf_field_class_struct_borrow_member_by_index(
1432 parent_struct_fc, i);
1433
1434 if (strcmp(field_ref->str, named_fc->name->str) == 0) {
1435 /* Name clash */
1436 name_ok = false;
1437 break;
1438 }
1439 }
1440
1441 if (name_ok) {
1442 /* No clash: we're done */
1443 break;
1444 }
1445
1446 /* Append suffix and try again */
1447 g_string_printf(field_ref, "__%s_%s_%u", fc_name, tgt_type,
1448 suffix);
1449 suffix++;
1450 }
1451
1452 end:
1453 return ret;
1454 }
1455
1456 /*
1457 * This function recursively sets field refs of sequence and variant
1458 * field classes when they are immediately before, avoiding name clashes
1459 * with existing field class names.
1460 *
1461 * It can fail at this point if, for example, a sequence field class of
1462 * which to set the length's field ref has something else than a
1463 * structure field class as its parent: in this case, there's no
1464 * location to place the length field class immediately before the
1465 * sequence field class.
1466 */
1467 static
1468 int set_field_refs(struct fs_sink_ctf_field_class * const fc,
1469 const char *fc_name, struct fs_sink_ctf_field_class *parent_fc)
1470 {
1471 int ret = 0;
1472 enum fs_sink_ctf_field_class_type fc_type;
1473 BT_ASSERT(fc);
1474
1475 fc_type = fc->type;
1476
1477 switch (fc_type) {
1478 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
1479 {
1480 struct fs_sink_ctf_field_class_option *opt_fc = (void *) fc;
1481
1482 ret = set_field_ref(fc, fc_name, parent_fc);
1483 if (ret) {
1484 goto end;
1485 }
1486
1487 ret = set_field_refs(opt_fc->content_fc, NULL, fc);
1488 if (ret) {
1489 goto end;
1490 }
1491
1492 break;
1493 }
1494 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
1495 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
1496 {
1497 uint64_t i;
1498 uint64_t len;
1499 struct fs_sink_ctf_field_class_struct *struct_fc = NULL;
1500 struct fs_sink_ctf_field_class_variant *var_fc = NULL;
1501 struct fs_sink_ctf_named_field_class *named_fc;
1502
1503 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1504 struct_fc = (void *) fc;
1505 len = struct_fc->members->len;
1506 } else {
1507 var_fc = (void *) fc;
1508 len = var_fc->options->len;
1509 ret = set_field_ref(fc, fc_name, parent_fc);
1510 if (ret) {
1511 goto end;
1512 }
1513 }
1514
1515 for (i = 0; i < len; i++) {
1516 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1517 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
1518 struct_fc, i);
1519 } else {
1520 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
1521 var_fc, i);
1522 }
1523
1524 ret = set_field_refs(named_fc->fc, named_fc->name->str,
1525 fc);
1526 if (ret) {
1527 goto end;
1528 }
1529 }
1530
1531 break;
1532 }
1533 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
1534 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
1535 {
1536 struct fs_sink_ctf_field_class_array_base *array_base_fc =
1537 (void *) fc;
1538
1539 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
1540 ret = set_field_ref(fc, fc_name, parent_fc);
1541 if (ret) {
1542 goto end;
1543 }
1544 }
1545
1546 ret = set_field_refs(array_base_fc->elem_fc, NULL, fc);
1547 if (ret) {
1548 goto end;
1549 }
1550
1551 break;
1552 }
1553 default:
1554 break;
1555 }
1556
1557 end:
1558 return ret;
1559 }
1560
1561 /*
1562 * This function translates a root scope trace IR field class to
1563 * a CTF IR field class.
1564 *
1565 * The resulting CTF IR field class is written to `*fc` so that it
1566 * exists as the parent object's (stream class or event class) true root
1567 * field class during the recursive translation for resolving purposes.
1568 * This is also why this function creates the empty structure field
1569 * class and then calls translate_structure_field_class_members() to
1570 * fill it.
1571 */
1572 static
1573 int translate_scope_field_class(struct ctx *ctx, bt_field_path_scope scope,
1574 struct fs_sink_ctf_field_class **fc,
1575 const bt_field_class *ir_fc)
1576 {
1577 int ret = 0;
1578
1579 if (!ir_fc) {
1580 goto end;
1581 }
1582
1583 BT_ASSERT(bt_field_class_get_type(ir_fc) ==
1584 BT_FIELD_CLASS_TYPE_STRUCTURE);
1585 BT_ASSERT(fc);
1586 *fc = (void *) fs_sink_ctf_field_class_struct_create_empty(
1587 ir_fc, UINT64_C(-1));
1588 BT_ASSERT(*fc);
1589 ctx->cur_scope = scope;
1590 BT_ASSERT(ctx->cur_path->len == 0);
1591 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, ir_fc, NULL);
1592 if (ret) {
1593 BT_COMP_LOGE("Cannot translate scope structure field class: "
1594 "scope=%d", scope);
1595 goto end;
1596 }
1597
1598 ret = translate_structure_field_class_members(ctx, (void *) *fc, ir_fc);
1599 if (ret) {
1600 BT_COMP_LOGE("Cannot translate scope structure field class: "
1601 "scope=%d", scope);
1602 goto end;
1603 }
1604
1605 cur_path_stack_pop(ctx);
1606
1607 /* Set field refs for preceding targets */
1608 ret = set_field_refs(*fc, NULL, NULL);
1609
1610 end:
1611 return ret;
1612 }
1613
1614 static inline
1615 void ctx_init(struct ctx *ctx, struct fs_sink_comp *fs_sink)
1616 {
1617 memset(ctx, 0, sizeof(struct ctx));
1618 ctx->cur_path = g_array_new(FALSE, TRUE,
1619 sizeof(struct field_path_elem));
1620 BT_ASSERT(ctx->cur_path);
1621 ctx->log_level = fs_sink->log_level;
1622 ctx->self_comp = fs_sink->self_comp;
1623 }
1624
1625 static inline
1626 void ctx_fini(struct ctx *ctx)
1627 {
1628 if (ctx->cur_path) {
1629 g_array_free(ctx->cur_path, TRUE);
1630 ctx->cur_path = NULL;
1631 }
1632 }
1633
1634 static
1635 int translate_event_class(struct fs_sink_comp *fs_sink,
1636 struct fs_sink_ctf_stream_class *sc,
1637 const bt_event_class *ir_ec,
1638 struct fs_sink_ctf_event_class **out_ec)
1639 {
1640 int ret = 0;
1641 struct ctx ctx;
1642 struct fs_sink_ctf_event_class *ec;
1643
1644 BT_ASSERT(sc);
1645 BT_ASSERT(ir_ec);
1646
1647 ctx_init(&ctx, fs_sink);
1648 ec = fs_sink_ctf_event_class_create(sc, ir_ec);
1649 BT_ASSERT(ec);
1650 ctx.cur_sc = sc;
1651 ctx.cur_ec = ec;
1652 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT,
1653 &ec->spec_context_fc,
1654 bt_event_class_borrow_specific_context_field_class_const(
1655 ir_ec));
1656 if (ret) {
1657 goto end;
1658 }
1659
1660 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD,
1661 &ec->payload_fc,
1662 bt_event_class_borrow_payload_field_class_const(ir_ec));
1663 if (ret) {
1664 goto end;
1665 }
1666
1667 end:
1668 ctx_fini(&ctx);
1669 *out_ec = ec;
1670 return ret;
1671 }
1672
1673 BT_HIDDEN
1674 int try_translate_event_class_trace_ir_to_ctf_ir(
1675 struct fs_sink_comp *fs_sink,
1676 struct fs_sink_ctf_stream_class *sc,
1677 const bt_event_class *ir_ec,
1678 struct fs_sink_ctf_event_class **out_ec)
1679 {
1680 int ret = 0;
1681
1682 BT_ASSERT(sc);
1683 BT_ASSERT(ir_ec);
1684
1685 /* Check in hash table first */
1686 *out_ec = g_hash_table_lookup(sc->event_classes_from_ir, ir_ec);
1687 if (G_LIKELY(*out_ec)) {
1688 goto end;
1689 }
1690
1691 ret = translate_event_class(fs_sink, sc, ir_ec, out_ec);
1692
1693 end:
1694 return ret;
1695 }
1696
1697 static
1698 bool default_clock_class_name_exists(struct fs_sink_ctf_trace *trace,
1699 const char *name)
1700 {
1701 bool exists = false;
1702 uint64_t i;
1703
1704 for (i = 0; i < trace->stream_classes->len; i++) {
1705 struct fs_sink_ctf_stream_class *sc =
1706 trace->stream_classes->pdata[i];
1707
1708 if (sc->default_clock_class_name->len == 0) {
1709 /* No default clock class */
1710 continue;
1711 }
1712
1713 if (strcmp(sc->default_clock_class_name->str, name) == 0) {
1714 exists = true;
1715 goto end;
1716 }
1717 }
1718
1719 end:
1720 return exists;
1721 }
1722
1723 static
1724 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class *sc)
1725 {
1726 unsigned int suffix = 0;
1727 char buf[16];
1728
1729 g_string_assign(sc->default_clock_class_name, "");
1730 sprintf(buf, "default");
1731
1732 while (default_clock_class_name_exists(sc->trace, buf)) {
1733 sprintf(buf, "default%u", suffix);
1734 suffix++;
1735 }
1736
1737 g_string_assign(sc->default_clock_class_name, buf);
1738 }
1739
1740 static
1741 int translate_stream_class(struct fs_sink_comp *fs_sink,
1742 struct fs_sink_ctf_trace *trace,
1743 const bt_stream_class *ir_sc,
1744 struct fs_sink_ctf_stream_class **out_sc)
1745 {
1746 int ret = 0;
1747 struct ctx ctx;
1748
1749 BT_ASSERT(trace);
1750 BT_ASSERT(ir_sc);
1751 ctx_init(&ctx, fs_sink);
1752 *out_sc = fs_sink_ctf_stream_class_create(trace, ir_sc);
1753 BT_ASSERT(*out_sc);
1754
1755 /* Set default clock class's protected name, if any */
1756 if ((*out_sc)->default_clock_class) {
1757 const char *name = bt_clock_class_get_name(
1758 (*out_sc)->default_clock_class);
1759
1760 if (name) {
1761 /* Try original name, protected */
1762 g_string_assign((*out_sc)->default_clock_class_name,
1763 "");
1764
1765 if (must_protect_identifier(name)) {
1766 g_string_assign(
1767 (*out_sc)->default_clock_class_name,
1768 "_");
1769 }
1770
1771 g_string_assign((*out_sc)->default_clock_class_name,
1772 name);
1773 if (!ist_valid_identifier(
1774 (*out_sc)->default_clock_class_name->str)) {
1775 /* Invalid: create a new name */
1776 make_unique_default_clock_class_name(*out_sc);
1777 }
1778 } else {
1779 /* No name: create a name */
1780 make_unique_default_clock_class_name(*out_sc);
1781 }
1782 }
1783
1784 ctx.cur_sc = *out_sc;
1785 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT,
1786 &(*out_sc)->packet_context_fc,
1787 bt_stream_class_borrow_packet_context_field_class_const(ir_sc));
1788 if (ret) {
1789 goto error;
1790 }
1791
1792 if ((*out_sc)->packet_context_fc) {
1793 /*
1794 * Make sure the structure field class's alignment is
1795 * enough: 8 is what we use for our own special members
1796 * in the packet context.
1797 */
1798 fs_sink_ctf_field_class_struct_align_at_least(
1799 (void *) (*out_sc)->packet_context_fc, 8);
1800 }
1801
1802 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT,
1803 &(*out_sc)->event_common_context_fc,
1804 bt_stream_class_borrow_event_common_context_field_class_const(
1805 ir_sc));
1806 if (ret) {
1807 goto error;
1808 }
1809
1810 goto end;
1811
1812 error:
1813 fs_sink_ctf_stream_class_destroy(*out_sc);
1814 *out_sc = NULL;
1815
1816 end:
1817 ctx_fini(&ctx);
1818 return ret;
1819 }
1820
1821 BT_HIDDEN
1822 int try_translate_stream_class_trace_ir_to_ctf_ir(
1823 struct fs_sink_comp *fs_sink,
1824 struct fs_sink_ctf_trace *trace,
1825 const bt_stream_class *ir_sc,
1826 struct fs_sink_ctf_stream_class **out_sc)
1827 {
1828 int ret = 0;
1829 uint64_t i;
1830
1831 BT_ASSERT(trace);
1832 BT_ASSERT(ir_sc);
1833
1834 for (i = 0; i < trace->stream_classes->len; i++) {
1835 *out_sc = trace->stream_classes->pdata[i];
1836
1837 if ((*out_sc)->ir_sc == ir_sc) {
1838 goto end;
1839 }
1840 }
1841
1842 ret = translate_stream_class(fs_sink, trace, ir_sc, out_sc);
1843
1844 end:
1845 return ret;
1846 }
1847
1848 BT_HIDDEN
1849 struct fs_sink_ctf_trace *translate_trace_trace_ir_to_ctf_ir(
1850 struct fs_sink_comp *fs_sink, const bt_trace *ir_trace)
1851 {
1852 uint64_t count;
1853 uint64_t i;
1854 struct fs_sink_ctf_trace *trace = NULL;
1855
1856 /* Check that trace's environment is TSDL-compatible */
1857 count = bt_trace_get_environment_entry_count(ir_trace);
1858 for (i = 0; i < count; i++) {
1859 const char *name;
1860 const bt_value *val;
1861
1862 bt_trace_borrow_environment_entry_by_index_const(
1863 ir_trace, i, &name, &val);
1864
1865 if (!ist_valid_identifier(name)) {
1866 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
1867 fs_sink->self_comp,
1868 "Unsupported trace class's environment entry name: "
1869 "name=\"%s\"", name);
1870 goto end;
1871 }
1872
1873 switch (bt_value_get_type(val)) {
1874 case BT_VALUE_TYPE_SIGNED_INTEGER:
1875 case BT_VALUE_TYPE_STRING:
1876 break;
1877 default:
1878 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
1879 fs_sink->self_comp,
1880 "Unsupported trace class's environment entry value type: "
1881 "type=%s",
1882 bt_common_value_type_string(
1883 bt_value_get_type(val)));
1884 goto end;
1885 }
1886 }
1887
1888 trace = fs_sink_ctf_trace_create(ir_trace);
1889 BT_ASSERT(trace);
1890
1891 end:
1892 return trace;
1893 }
This page took 0.13381 seconds and 4 git commands to generate.