Fix warnings emitted by `gcc -Wall`
[babeltrace.git] / lib / ctf-ir / resolve.c
1 /*
2 * resolve.c
3 *
4 * Babeltrace - CTF IR: Type resolving internal
5 *
6 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Authors: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Philippe Proulx <pproulx@efficios.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 */
30
31 #include <babeltrace/ctf-ir/event.h>
32 #include <babeltrace/ctf-ir/stream-class.h>
33 #include <babeltrace/ctf-ir/resolve-internal.h>
34 #include <babeltrace/ctf-ir/field-types.h>
35 #include <babeltrace/ctf-ir/field-path.h>
36 #include <babeltrace/ctf-ir/field-path-internal.h>
37 #include <babeltrace/ctf-ir/event-internal.h>
38 #include <babeltrace/ref.h>
39 #include <babeltrace/babeltrace-internal.h>
40 #include <babeltrace/values.h>
41 #include <babeltrace/types.h>
42 #include <limits.h>
43 #include <glib.h>
44
45 #define _printf_error(fmt, args...) \
46 printf_verbose("[resolving] " fmt, ## args)
47
48 typedef GPtrArray type_stack;
49
50 /*
51 * A stack frame.
52 *
53 * `type` contains a compound field type (structure, variant, array,
54 * or sequence) and `index` indicates the index of the field type in
55 * the upper frame (-1 for array and sequence field types).
56 *
57 * `type` is owned by the stack frame.
58 */
59 struct type_stack_frame {
60 struct bt_ctf_field_type *type;
61 int index;
62 };
63
64 /*
65 * The current context of the resolving engine.
66 *
67 * `scopes` contain the 6 CTF scope field types (see CTF, sect. 7.3.2)
68 * in the following order:
69 *
70 * * Packet header
71 * * Packet context
72 * * Event header
73 * * Stream event context
74 * * Event context
75 * * Event payload
76 */
77 struct resolve_context {
78 struct bt_value *environment;
79 struct bt_ctf_field_type *scopes[6];
80
81 /* Root scope being visited */
82 enum bt_ctf_scope root_scope;
83 type_stack *type_stack;
84 struct bt_ctf_field_type *cur_field_type;
85 };
86
87 /* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
88 static const char * const absolute_path_prefixes[] = {
89 [BT_CTF_SCOPE_ENV] = "env.",
90 [BT_CTF_SCOPE_TRACE_PACKET_HEADER] = "trace.packet.header.",
91 [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT] = "stream.packet.context.",
92 [BT_CTF_SCOPE_STREAM_EVENT_HEADER] = "stream.event.header.",
93 [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT] = "stream.event.context.",
94 [BT_CTF_SCOPE_EVENT_CONTEXT] = "event.context.",
95 [BT_CTF_SCOPE_EVENT_FIELDS] = "event.fields.",
96 };
97
98 /* Number of path tokens used for the absolute prefixes */
99 static const int absolute_path_prefix_ptoken_counts[] = {
100 [BT_CTF_SCOPE_ENV] = 1,
101 [BT_CTF_SCOPE_TRACE_PACKET_HEADER] = 3,
102 [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT] = 3,
103 [BT_CTF_SCOPE_STREAM_EVENT_HEADER] = 3,
104 [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT] = 3,
105 [BT_CTF_SCOPE_EVENT_CONTEXT] = 2,
106 [BT_CTF_SCOPE_EVENT_FIELDS] = 2,
107 };
108
109 /*
110 * Destroys a type stack frame.
111 */
112 static
113 void type_stack_destroy_notify(gpointer data)
114 {
115 struct type_stack_frame *frame = data;
116
117 BT_PUT(frame->type);
118 g_free(frame);
119 }
120
121 /*
122 * Creates a type stack.
123 *
124 * Return value is owned by the caller.
125 */
126 static
127 type_stack *type_stack_create(void)
128 {
129 return g_ptr_array_new_with_free_func(type_stack_destroy_notify);
130 }
131
132 /*
133 * Destroys a type stack.
134 */
135 static
136 void type_stack_destroy(type_stack *stack)
137 {
138 g_ptr_array_free(stack, TRUE);
139 }
140
141 /*
142 * Pushes a field type onto a type stack.
143 *
144 * `type` is owned by the caller (stack frame gets a new reference).
145 */
146 static
147 int type_stack_push(type_stack *stack, struct bt_ctf_field_type *type)
148 {
149 int ret = 0;
150 struct type_stack_frame *frame = NULL;
151
152 if (!stack || !type) {
153 ret = -1;
154 goto end;
155 }
156
157 frame = g_new0(struct type_stack_frame, 1);
158 if (!frame) {
159 ret = -1;
160 goto end;
161 }
162
163 frame->type = bt_get(type);
164 g_ptr_array_add(stack, frame);
165
166 end:
167 return ret;
168 }
169
170 /*
171 * Checks whether or not `stack` is empty.
172 */
173 static
174 bt_bool type_stack_empty(type_stack *stack)
175 {
176 return stack->len == 0;
177 }
178
179 /*
180 * Returns the number of frames in `stack`.
181 */
182 static
183 size_t type_stack_size(type_stack *stack)
184 {
185 return stack->len;
186 }
187
188 /*
189 * Returns the top frame of `stack`.
190 *
191 * Return value is owned by `stack`.
192 */
193 static
194 struct type_stack_frame *type_stack_peek(type_stack *stack)
195 {
196 struct type_stack_frame *entry = NULL;
197
198 if (!stack || type_stack_empty(stack)) {
199 goto end;
200 }
201
202 entry = g_ptr_array_index(stack, stack->len - 1);
203 end:
204 return entry;
205 }
206
207 /*
208 * Returns the frame at index `index` in `stack`.
209 *
210 * Return value is owned by `stack`.
211 */
212 static
213 struct type_stack_frame *type_stack_at(type_stack *stack,
214 size_t index)
215 {
216 struct type_stack_frame *entry = NULL;
217
218 if (!stack || index >= stack->len) {
219 goto end;
220 }
221
222 entry = g_ptr_array_index(stack, index);
223
224 end:
225 return entry;
226 }
227
228 /*
229 * Removes the top frame of `stack`.
230 */
231 static
232 void type_stack_pop(type_stack *stack)
233 {
234 if (!type_stack_empty(stack)) {
235 /*
236 * This will call the frame's destructor and free it, as
237 * well as put its contained field type.
238 */
239 g_ptr_array_set_size(stack, stack->len - 1);
240 }
241 }
242
243 /*
244 * Returns the scope field type of `scope` in the context `ctx`.
245 *
246 * Return value is owned by `ctx` on success.
247 */
248 static
249 struct bt_ctf_field_type *get_type_from_ctx(struct resolve_context *ctx,
250 enum bt_ctf_scope scope)
251 {
252 assert(scope >= BT_CTF_SCOPE_TRACE_PACKET_HEADER &&
253 scope <= BT_CTF_SCOPE_EVENT_FIELDS);
254
255 return ctx->scopes[scope - BT_CTF_SCOPE_TRACE_PACKET_HEADER];
256 }
257
258 /*
259 * Returns the CTF scope from a path string. May return
260 * CTF_NODE_UNKNOWN if the path is found to be relative.
261 */
262 static
263 enum bt_ctf_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
264 {
265 enum bt_ctf_scope scope;
266 enum bt_ctf_scope ret = BT_CTF_SCOPE_UNKNOWN;
267 const size_t prefixes_count = sizeof(absolute_path_prefixes) /
268 sizeof(*absolute_path_prefixes);
269
270 for (scope = BT_CTF_SCOPE_ENV; scope < BT_CTF_SCOPE_ENV +
271 prefixes_count; scope++) {
272 /*
273 * Chech if path string starts with a known absolute
274 * path prefix.
275 *
276 * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
277 */
278 if (strncmp(pathstr, absolute_path_prefixes[scope],
279 strlen(absolute_path_prefixes[scope]))) {
280 /* Prefix does not match: try the next one */
281 continue;
282 }
283
284 /* Found it! */
285 ret = scope;
286 goto end;
287 }
288
289 end:
290 return ret;
291 }
292
293 /*
294 * Destroys a path token.
295 */
296 static
297 void ptokens_destroy_func(gpointer ptoken, gpointer data)
298 {
299 g_string_free(ptoken, TRUE);
300 }
301
302 /*
303 * Destroys a path token list.
304 */
305 static
306 void ptokens_destroy(GList *ptokens)
307 {
308 if (!ptokens) {
309 return;
310 }
311
312 g_list_foreach(ptokens, ptokens_destroy_func, NULL);
313 g_list_free(ptokens);
314 }
315
316 /*
317 * Returns the string contained in a path token.
318 */
319 static
320 const char *ptoken_get_string(GList *ptoken)
321 {
322 GString *tokenstr = (GString *) ptoken->data;
323
324 return tokenstr->str;
325 }
326
327 /*
328 * Converts a path string to a path token list, that is, splits the
329 * individual words of a path string into a list of individual
330 * strings.
331 *
332 * Return value is owned by the caller on success.
333 */
334 static
335 GList *pathstr_to_ptokens(const char *pathstr)
336 {
337 const char *at = pathstr;
338 const char *last = at;
339 GList *ptokens = NULL;
340
341 for (;;) {
342 if (*at == '.' || *at == '\0') {
343 GString *tokenstr;
344
345 if (at == last) {
346 /* Error: empty token */
347 _printf_error("Empty token in path string at position %d\n",
348 (int) (at - pathstr));
349 goto error;
350 }
351
352 tokenstr = g_string_new(NULL);
353 g_string_append_len(tokenstr, last, at - last);
354 ptokens = g_list_append(ptokens, tokenstr);
355 last = at + 1;
356 }
357
358 if (*at == '\0') {
359 break;
360 }
361
362 at++;
363 }
364
365 return ptokens;
366
367 error:
368 ptokens_destroy(ptokens);
369 return NULL;
370 }
371
372 /*
373 * Converts a path token list to a field path object. The path token
374 * list is relative from `type`. The index of the source looking for
375 * its target within `type` is indicated by `src_index`. This can be
376 * `INT_MAX` if the source is contained in `type`.
377 *
378 * `ptokens` is owned by the caller. `field_path` is an output parameter
379 * owned by the caller that must be filled here. `type` is owned by the
380 * caller.
381 */
382 static
383 int ptokens_to_field_path(GList *ptokens, struct bt_ctf_field_path *field_path,
384 struct bt_ctf_field_type *type, int src_index)
385 {
386 int ret = 0;
387 GList *cur_ptoken = ptokens;
388 bt_bool first_level_done = BT_FALSE;
389
390 /* Get our own reference */
391 bt_get(type);
392
393 /* Locate target */
394 while (cur_ptoken) {
395 int child_index;
396 struct bt_ctf_field_type *child_type;
397 const char *field_name = ptoken_get_string(cur_ptoken);
398 enum bt_ctf_field_type_id type_id =
399 bt_ctf_field_type_get_type_id(type);
400
401 /* Find to which index corresponds the current path token */
402 if (type_id == BT_CTF_FIELD_TYPE_ID_ARRAY ||
403 type_id == BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
404 child_index = -1;
405 } else {
406 child_index = bt_ctf_field_type_get_field_index(type,
407 field_name);
408 if (child_index < 0) {
409 /*
410 * Error: field name does not exist or
411 * wrong current type.
412 */
413 _printf_error("Cannot get index of field type named \"%s\"\n",
414 field_name);
415 ret = -1;
416 goto end;
417 } else if (child_index > src_index &&
418 !first_level_done) {
419 _printf_error("Child type is located after source index (%d)\n",
420 src_index);
421 ret = -1;
422 goto end;
423 }
424
425 /* Next path token */
426 cur_ptoken = g_list_next(cur_ptoken);
427 first_level_done = BT_TRUE;
428 }
429
430 /* Create new field path entry */
431 g_array_append_val(field_path->indexes, child_index);
432
433 /* Get child field type */
434 child_type = bt_ctf_field_type_get_field_at_index(type,
435 child_index);
436 if (!child_type) {
437 _printf_error("Cannot get child type at index %d (field \"%s\")\n",
438 child_index, field_name);
439 ret = -1;
440 goto end;
441 }
442
443 /* Move child type to current type */
444 BT_MOVE(type, child_type);
445 }
446
447 end:
448 bt_put(type);
449 return ret;
450 }
451
452 /*
453 * Converts a known absolute path token list to a field path object
454 * within the resolving context `ctx`.
455 *
456 * `ptokens` is owned by the caller. `field_path` is an output parameter
457 * owned by the caller that must be filled here.
458 */
459 static
460 int absolute_ptokens_to_field_path(GList *ptokens,
461 struct bt_ctf_field_path *field_path,
462 struct resolve_context *ctx)
463 {
464 int ret = 0;
465 GList *cur_ptoken;
466 struct bt_ctf_field_type *type;
467
468 /* Skip absolute path tokens */
469 cur_ptoken = g_list_nth(ptokens,
470 absolute_path_prefix_ptoken_counts[field_path->root]);
471
472 /* Start with root type */
473 type = get_type_from_ctx(ctx, field_path->root);
474 if (!type) {
475 /* Error: root type is not available */
476 _printf_error("Root type with scope type %d is not available\n",
477 field_path->root);
478 ret = -1;
479 goto end;
480 }
481
482 /* Locate target */
483 ret = ptokens_to_field_path(cur_ptoken, field_path, type, INT_MAX);
484
485 end:
486 return ret;
487 }
488
489 /*
490 * Converts a known relative path token list to a field path object
491 * within the resolving context `ctx`.
492 *
493 * `ptokens` is owned by the caller. `field_path` is an output parameter
494 * owned by the caller that must be filled here.
495 */
496 static
497 int relative_ptokens_to_field_path(GList *ptokens,
498 struct bt_ctf_field_path *field_path,
499 struct resolve_context *ctx)
500 {
501 int ret = 0;
502 int parent_pos_in_stack;
503 struct bt_ctf_field_path *tail_field_path = bt_ctf_field_path_create();
504
505 if (!tail_field_path) {
506 _printf_error("Cannot create field path\n");
507 ret = -1;
508 goto end;
509 }
510
511 parent_pos_in_stack = type_stack_size(ctx->type_stack) - 1;
512
513 while (parent_pos_in_stack >= 0) {
514 struct bt_ctf_field_type *parent_type =
515 type_stack_at(ctx->type_stack,
516 parent_pos_in_stack)->type;
517 int cur_index = type_stack_at(ctx->type_stack,
518 parent_pos_in_stack)->index;
519
520 /* Locate target from current parent type */
521 ret = ptokens_to_field_path(ptokens, tail_field_path,
522 parent_type, cur_index);
523 if (ret) {
524 /* Not found... yet */
525 bt_ctf_field_path_clear(tail_field_path);
526 } else {
527 /* Found: stitch tail field path to head field path */
528 int i = 0;
529 int tail_field_path_len =
530 tail_field_path->indexes->len;
531
532 while (BT_TRUE) {
533 struct bt_ctf_field_type *cur_type =
534 type_stack_at(ctx->type_stack, i)->type;
535 int index = type_stack_at(
536 ctx->type_stack, i)->index;
537
538 if (cur_type == parent_type) {
539 break;
540 }
541
542 g_array_append_val(field_path->indexes,
543 index);
544 i++;
545 }
546
547 for (i = 0; i < tail_field_path_len; i++) {
548 int index = g_array_index(
549 tail_field_path->indexes,
550 int, i);
551
552 g_array_append_val(field_path->indexes,
553 index);
554 }
555 break;
556 }
557
558 parent_pos_in_stack--;
559 }
560
561 if (parent_pos_in_stack < 0) {
562 /* Not found: look in previous scopes */
563 field_path->root--;
564
565 while (field_path->root >= BT_CTF_SCOPE_TRACE_PACKET_HEADER) {
566 struct bt_ctf_field_type *root_type;
567 bt_ctf_field_path_clear(field_path);
568
569 root_type = get_type_from_ctx(ctx, field_path->root);
570 if (!root_type) {
571 field_path->root--;
572 continue;
573 }
574
575 /* Locate target in previous scope */
576 ret = ptokens_to_field_path(ptokens, field_path,
577 root_type, INT_MAX);
578 if (ret) {
579 /* Not found yet */
580 field_path->root--;
581 continue;
582 }
583
584 /* Found */
585 break;
586 }
587 }
588
589 end:
590 BT_PUT(tail_field_path);
591 return ret;
592 }
593
594 /*
595 * Converts a path string to a field path object within the resolving
596 * context `ctx`.
597 *
598 * Return value is owned by the caller on success.
599 */
600 static
601 struct bt_ctf_field_path *pathstr_to_field_path(const char *pathstr,
602 struct resolve_context *ctx)
603 {
604 int ret;
605 enum bt_ctf_scope root_scope;
606 GList *ptokens = NULL;
607 struct bt_ctf_field_path *field_path = NULL;
608
609 /* Create field path */
610 field_path = bt_ctf_field_path_create();
611 if (!field_path) {
612 _printf_error("Cannot create field path\n");
613 ret = -1;
614 goto end;
615 }
616
617 /* Convert path string to path tokens */
618 ptokens = pathstr_to_ptokens(pathstr);
619 if (!ptokens) {
620 _printf_error("Cannot convert path string \"%s\" to path tokens\n",
621 pathstr);
622 ret = -1;
623 goto end;
624 }
625
626 /* Absolute or relative path? */
627 root_scope = get_root_scope_from_absolute_pathstr(pathstr);
628
629 if (root_scope == BT_CTF_SCOPE_UNKNOWN) {
630 /* Relative path: start with current root scope */
631 field_path->root = ctx->root_scope;
632 ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
633 if (ret) {
634 _printf_error("Cannot get relative field path of path string \"%s\"\n",
635 pathstr);
636 _printf_error(" Starting at root scope %d, finished at root scope %d\n",
637 ctx->root_scope, field_path->root);
638 goto end;
639 }
640 } else if (root_scope == BT_CTF_SCOPE_ENV) {
641 _printf_error("Sequence field types referring the trace environment are not supported as of this version\n");
642 ret = -1;
643 goto end;
644 } else {
645 /* Absolute path: use found root scope */
646 field_path->root = root_scope;
647 ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
648 if (ret) {
649 _printf_error("Cannot get absolute field path of path string \"%s\"\n",
650 pathstr);
651 _printf_error(" Looking in root scope %d\n", root_scope);
652 goto end;
653 }
654 }
655
656 end:
657 if (ret) {
658 BT_PUT(field_path);
659 }
660
661 ptokens_destroy(ptokens);
662
663 return field_path;
664 }
665
666 /*
667 * Retrieves a field type by following the field path `field_path` in
668 * the resolving context `ctx`.
669 *
670 * Return value is owned by the caller on success.
671 */
672 static
673 struct bt_ctf_field_type *field_path_to_field_type(
674 struct bt_ctf_field_path *field_path,
675 struct resolve_context *ctx)
676 {
677 int i;
678 struct bt_ctf_field_type *type;
679
680 /* Start with root type */
681 type = get_type_from_ctx(ctx, field_path->root);
682 bt_get(type);
683 if (!type) {
684 /* Error: root type is not available */
685 _printf_error("Root type with scope type %d is not available\n",
686 field_path->root);
687 goto error;
688 }
689
690 /* Locate target */
691 for (i = 0; i < field_path->indexes->len; i++) {
692 struct bt_ctf_field_type *child_type;
693 int child_index =
694 g_array_index(field_path->indexes, int, i);
695
696 /* Get child field type */
697 child_type = bt_ctf_field_type_get_field_at_index(type,
698 child_index);
699 if (!child_type) {
700 _printf_error("Cannot get field type field at index %d\n",
701 child_index);
702 goto error;
703 }
704
705 /* Move child type to current type */
706 BT_MOVE(type, child_type);
707 }
708
709 return type;
710
711 error:
712 BT_PUT(type);
713 return type;
714 }
715
716 /*
717 * Returns the equivalent field path object of the context type stack.
718 *
719 * Return value is owned by the caller on success.
720 */
721 static
722 struct bt_ctf_field_path *get_ctx_stack_field_path(struct resolve_context *ctx)
723 {
724 int i;
725 struct bt_ctf_field_path *field_path;
726
727 /* Create field path */
728 field_path = bt_ctf_field_path_create();
729 if (!field_path) {
730 _printf_error("Cannot create field path\n");
731 goto error;
732 }
733
734 field_path->root = ctx->root_scope;
735
736 for (i = 0; i < type_stack_size(ctx->type_stack); i++) {
737 struct type_stack_frame *frame;
738
739 frame = type_stack_at(ctx->type_stack, i);
740 g_array_append_val(field_path->indexes, frame->index);
741 }
742
743 return field_path;
744
745 error:
746 BT_PUT(field_path);
747 return field_path;
748 }
749
750 /*
751 * Returns the lowest common ancestor of two field path objects
752 * having the same root scope.
753 *
754 * `field_path1` and `field_path2` are owned by the caller.
755 */
756 int get_field_paths_lca_index(struct bt_ctf_field_path *field_path1,
757 struct bt_ctf_field_path *field_path2)
758 {
759 int lca_index = 0;
760 int field_path1_len, field_path2_len;
761
762 /*
763 * Start from both roots and find the first mismatch.
764 */
765 assert(field_path1->root == field_path2->root);
766 field_path1_len = field_path1->indexes->len;
767 field_path2_len = field_path2->indexes->len;
768
769 while (BT_TRUE) {
770 int target_index, ctx_index;
771
772 if (lca_index == field_path2_len ||
773 lca_index == field_path1_len) {
774 /*
775 * This means that both field paths never split.
776 * This is invalid because the target cannot be
777 * an ancestor of the source.
778 */
779 _printf_error("In source and target: one is an ancestor of the other\n");
780 lca_index = -1;
781 break;
782 }
783
784 target_index = g_array_index(field_path1->indexes, int,
785 lca_index);
786 ctx_index = g_array_index(field_path2->indexes, int,
787 lca_index);
788
789 if (target_index != ctx_index) {
790 /* LCA index is the previous */
791 break;
792 }
793
794 lca_index++;
795 }
796
797 return lca_index;
798 }
799
800 /*
801 * Validates a target field path.
802 *
803 * `target_field_path` and `target_type` are owned by the caller.
804 */
805 static
806 int validate_target_field_path(struct bt_ctf_field_path *target_field_path,
807 struct bt_ctf_field_type *target_type,
808 struct resolve_context *ctx)
809 {
810 int ret = 0;
811 struct bt_ctf_field_path *ctx_field_path;
812 int target_field_path_len = target_field_path->indexes->len;
813 int lca_index;
814 int ctx_cur_field_type_id;
815 int target_type_id;
816
817 /* Get context field path */
818 ctx_field_path = get_ctx_stack_field_path(ctx);
819 if (!ctx_field_path) {
820 _printf_error("Cannot get source field path\n");
821 ret = -1;
822 goto end;
823 }
824
825 /*
826 * Make sure the target is not a root.
827 */
828 if (target_field_path_len == 0) {
829 _printf_error("Target field path's length is 0 (targeting the root)\n");
830 ret = -1;
831 goto end;
832 }
833
834 /*
835 * Make sure the root of the target field path is not located
836 * after the context field path's root.
837 */
838 if (target_field_path->root > ctx_field_path->root) {
839 _printf_error("Target is located after source\n");
840 ret = -1;
841 goto end;
842 }
843
844 if (target_field_path->root == ctx_field_path->root) {
845 int target_index, ctx_index;
846
847 /*
848 * Find the index of the lowest common ancestor of both field
849 * paths.
850 */
851 lca_index = get_field_paths_lca_index(target_field_path,
852 ctx_field_path);
853 if (lca_index < 0) {
854 _printf_error("Cannot get least common ancestor\n");
855 ret = -1;
856 goto end;
857 }
858
859 /*
860 * Make sure the target field path is located before the
861 * context field path.
862 */
863 target_index = g_array_index(target_field_path->indexes,
864 int, lca_index);
865 ctx_index = g_array_index(ctx_field_path->indexes,
866 int, lca_index);
867
868 if (target_index >= ctx_index) {
869 _printf_error("Target index (%d) is greater or equal to source index (%d) in LCA\n",
870 target_index, ctx_index);
871 ret = -1;
872 goto end;
873 }
874 }
875
876 /*
877 * Make sure the target type has the right type and properties.
878 */
879 ctx_cur_field_type_id = bt_ctf_field_type_get_type_id(
880 ctx->cur_field_type);
881 target_type_id = bt_ctf_field_type_get_type_id(target_type);
882
883 if (ctx_cur_field_type_id == CTF_TYPE_VARIANT) {
884 if (target_type_id != CTF_TYPE_ENUM) {
885 _printf_error("Variant type's tag field type is not an enumeration\n");
886 ret = -1;
887 goto end;
888 }
889 } else if (ctx_cur_field_type_id == CTF_TYPE_SEQUENCE) {
890 if (target_type_id != CTF_TYPE_INTEGER ||
891 bt_ctf_field_type_integer_get_signed(
892 target_type)) {
893 _printf_error("Sequence type's length field type is not an unsigned integer\n");
894 ret = -1;
895 goto end;
896 }
897 } else {
898 assert(BT_FALSE);
899 }
900
901 end:
902 BT_PUT(ctx_field_path);
903 return ret;
904 }
905
906 /*
907 * Resolves a variant or sequence field type `type`.
908 *
909 * `type` is owned by the caller.
910 */
911 static
912 int resolve_sequence_or_variant_type(struct bt_ctf_field_type *type,
913 struct resolve_context *ctx)
914 {
915 int ret = 0;
916 const char *pathstr;
917 int type_id = bt_ctf_field_type_get_type_id(type);
918 struct bt_ctf_field_path *target_field_path = NULL;
919 struct bt_ctf_field_type *target_type = NULL;
920
921 /* Get path string */
922 switch (type_id) {
923 case CTF_TYPE_SEQUENCE:
924 pathstr =
925 bt_ctf_field_type_sequence_get_length_field_name(type);
926 break;
927 case CTF_TYPE_VARIANT:
928 pathstr =
929 bt_ctf_field_type_variant_get_tag_name(type);
930 break;
931 default:
932 assert(BT_FALSE);
933 ret = -1;
934 goto end;
935 }
936
937 /* Get target field path out of path string */
938 target_field_path = pathstr_to_field_path(pathstr, ctx);
939 if (!target_field_path) {
940 _printf_error("Cannot get target field path for path string \"%s\"\n",
941 pathstr);
942 ret = -1;
943 goto end;
944 }
945
946 /* Get target field type */
947 target_type = field_path_to_field_type(target_field_path, ctx);
948 if (!target_type) {
949 _printf_error("Cannot get target field type for path string \"%s\"\n",
950 pathstr);
951 ret = -1;
952 goto end;
953 }
954
955 ret = validate_target_field_path(target_field_path, target_type, ctx);
956 if (ret) {
957 _printf_error("Invalid target field path for path string \"%s\"\n",
958 pathstr);
959 goto end;
960 }
961
962 /* Set target field path and target field type */
963 if (type_id == CTF_TYPE_SEQUENCE) {
964 ret = bt_ctf_field_type_sequence_set_length_field_path(
965 type, target_field_path);
966 if (ret) {
967 _printf_error("Cannot set sequence field type's length field path\n");
968 goto end;
969 }
970 } else if (type_id == CTF_TYPE_VARIANT) {
971 ret = bt_ctf_field_type_variant_set_tag_field_path(
972 type, target_field_path);
973 if (ret) {
974 _printf_error("Cannot set variant field type's tag field path\n");
975 goto end;
976 }
977
978 ret = bt_ctf_field_type_variant_set_tag_field_type(
979 type, target_type);
980 if (ret) {
981 _printf_error("Cannot set variant field type's tag field type\n");
982 goto end;
983 }
984 } else {
985 assert(BT_FALSE);
986 }
987
988 end:
989 BT_PUT(target_field_path);
990 BT_PUT(target_type);
991 return ret;
992 }
993
994 /*
995 * Resolves a field type `type`.
996 *
997 * `type` is owned by the caller.
998 */
999 static
1000 int resolve_type(struct bt_ctf_field_type *type, struct resolve_context *ctx)
1001 {
1002 int ret = 0;
1003 int type_id;
1004
1005 if (!type) {
1006 /* Type is not available; still valid */
1007 goto end;
1008 }
1009
1010 type_id = bt_ctf_field_type_get_type_id(type);
1011 ctx->cur_field_type = type;
1012
1013 /* Resolve sequence/variant field type */
1014 switch (type_id) {
1015 case CTF_TYPE_SEQUENCE:
1016 case CTF_TYPE_VARIANT:
1017 ret = resolve_sequence_or_variant_type(type, ctx);
1018 if (ret) {
1019 _printf_error("Cannot resolve sequence or variant field type's length/tag\n");
1020 goto end;
1021 }
1022 break;
1023 default:
1024 break;
1025 }
1026
1027 /* Recurse into compound types */
1028 switch (type_id) {
1029 case CTF_TYPE_STRUCT:
1030 case CTF_TYPE_VARIANT:
1031 case CTF_TYPE_SEQUENCE:
1032 case CTF_TYPE_ARRAY:
1033 {
1034 int field_count, f_index;
1035
1036 ret = type_stack_push(ctx->type_stack, type);
1037 if (ret) {
1038 _printf_error("Cannot push field type on type stack\n");
1039 _printf_error(" Stack size: %zu\n",
1040 type_stack_size(ctx->type_stack));
1041 goto end;
1042 }
1043
1044 field_count = bt_ctf_field_type_get_field_count(type);
1045 if (field_count < 0) {
1046 _printf_error("Cannot get field type field count\n");
1047 ret = field_count;
1048 goto end;
1049 }
1050
1051 for (f_index = 0; f_index < field_count; f_index++) {
1052 struct bt_ctf_field_type *child_type =
1053 bt_ctf_field_type_get_field_at_index(type,
1054 f_index);
1055
1056 if (!child_type) {
1057 _printf_error("Cannot get field type field at index %d/%d\n",
1058 f_index, field_count);
1059 ret = -1;
1060 goto end;
1061 }
1062
1063 if (type_id == CTF_TYPE_ARRAY ||
1064 type_id == CTF_TYPE_SEQUENCE) {
1065 type_stack_peek(ctx->type_stack)->index = -1;
1066 } else {
1067 type_stack_peek(ctx->type_stack)->index =
1068 f_index;
1069 }
1070
1071 ret = resolve_type(child_type, ctx);
1072 BT_PUT(child_type);
1073 if (ret) {
1074 goto end;
1075 }
1076 }
1077
1078 type_stack_pop(ctx->type_stack);
1079 break;
1080 }
1081 default:
1082 break;
1083 }
1084
1085 end:
1086 return ret;
1087 }
1088
1089 /*
1090 * Resolves the root field type corresponding to the scope `root_scope`.
1091 */
1092 static
1093 int resolve_root_type(enum bt_ctf_scope root_scope, struct resolve_context *ctx)
1094 {
1095 int ret;
1096
1097 assert(type_stack_size(ctx->type_stack) == 0);
1098 ctx->root_scope = root_scope;
1099 ret = resolve_type(get_type_from_ctx(ctx, root_scope), ctx);
1100 ctx->root_scope = BT_CTF_SCOPE_UNKNOWN;
1101
1102 return ret;
1103 }
1104
1105 BT_HIDDEN
1106 int bt_ctf_resolve_types(
1107 struct bt_value *environment,
1108 struct bt_ctf_field_type *packet_header_type,
1109 struct bt_ctf_field_type *packet_context_type,
1110 struct bt_ctf_field_type *event_header_type,
1111 struct bt_ctf_field_type *stream_event_ctx_type,
1112 struct bt_ctf_field_type *event_context_type,
1113 struct bt_ctf_field_type *event_payload_type,
1114 enum bt_ctf_resolve_flag flags)
1115 {
1116 int ret = 0;
1117 struct resolve_context ctx = {
1118 .environment = environment,
1119 .scopes = {
1120 packet_header_type,
1121 packet_context_type,
1122 event_header_type,
1123 stream_event_ctx_type,
1124 event_context_type,
1125 event_payload_type,
1126 },
1127 .root_scope = BT_CTF_SCOPE_UNKNOWN,
1128 };
1129
1130 /* Initialize type stack */
1131 ctx.type_stack = type_stack_create();
1132 if (!ctx.type_stack) {
1133 printf_error("Cannot create type stack\n");
1134 ret = -1;
1135 goto end;
1136 }
1137
1138 /* Resolve packet header type */
1139 if (flags & BT_CTF_RESOLVE_FLAG_PACKET_HEADER) {
1140 ret = resolve_root_type(BT_CTF_SCOPE_TRACE_PACKET_HEADER, &ctx);
1141 if (ret) {
1142 _printf_error("Cannot resolve trace packet header type\n");
1143 goto end;
1144 }
1145 }
1146
1147 /* Resolve packet context type */
1148 if (flags & BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT) {
1149 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_PACKET_CONTEXT, &ctx);
1150 if (ret) {
1151 _printf_error("Cannot resolve stream packet context type\n");
1152 goto end;
1153 }
1154 }
1155
1156 /* Resolve event header type */
1157 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_HEADER) {
1158 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_HEADER, &ctx);
1159 if (ret) {
1160 _printf_error("Cannot resolve stream event header type\n");
1161 goto end;
1162 }
1163 }
1164
1165 /* Resolve stream event context type */
1166 if (flags & BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX) {
1167 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_CONTEXT, &ctx);
1168 if (ret) {
1169 _printf_error("Cannot resolve stream event context type\n");
1170 goto end;
1171 }
1172 }
1173
1174 /* Resolve event context type */
1175 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT) {
1176 ret = resolve_root_type(BT_CTF_SCOPE_EVENT_CONTEXT, &ctx);
1177 if (ret) {
1178 _printf_error("Cannot resolve event context type\n");
1179 goto end;
1180 }
1181 }
1182
1183 /* Resolve event payload type */
1184 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD) {
1185 ret = resolve_root_type(BT_CTF_SCOPE_EVENT_FIELDS, &ctx);
1186 if (ret) {
1187 _printf_error("Cannot resolve event payload type\n");
1188 goto end;
1189 }
1190 }
1191
1192 end:
1193 type_stack_destroy(ctx.type_stack);
1194
1195 return ret;
1196 }
This page took 0.066457 seconds and 5 git commands to generate.