4 * BabelTrace - Converter
8 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
10 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
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
31 #include <babeltrace/format.h>
32 #include <babeltrace/babeltrace-internal.h>
33 #include <babeltrace/types.h>
39 GQuark
prefix_quark(const char *prefix
, GQuark quark
)
45 str
= g_string_new(prefix
);
46 g_string_append(str
, g_quark_to_string(quark
));
47 quark_str
= g_string_free(str
, FALSE
);
48 nq
= g_quark_from_string(quark_str
);
54 struct bt_declaration
*
55 bt_lookup_declaration_scope(GQuark declaration_name
,
56 struct declaration_scope
*scope
)
58 return g_hash_table_lookup(scope
->typedef_declarations
,
59 (gconstpointer
) (unsigned long) declaration_name
);
62 struct bt_declaration
*bt_lookup_declaration(GQuark declaration_name
,
63 struct declaration_scope
*scope
)
65 struct bt_declaration
*declaration
;
68 declaration
= bt_lookup_declaration_scope(declaration_name
,
72 scope
= scope
->parent_scope
;
77 int bt_register_declaration(GQuark name
, struct bt_declaration
*declaration
,
78 struct declaration_scope
*scope
)
83 /* Only lookup in local scope */
84 if (bt_lookup_declaration_scope(name
, scope
))
87 g_hash_table_insert(scope
->typedef_declarations
,
88 (gpointer
) (unsigned long) name
,
90 bt_declaration_ref(declaration
);
95 struct bt_definition
*
96 lookup_field_definition_scope(GQuark field_name
,
97 struct definition_scope
*scope
)
99 return g_hash_table_lookup(scope
->definitions
,
100 (gconstpointer
) (unsigned long) field_name
);
104 * Returns the index at which the paths differ.
105 * If the value returned equals len, it means the paths are identical
106 * from index 0 to len-1.
108 static int compare_paths(GArray
*a
, GArray
*b
, int len
)
112 assert(len
<= a
->len
);
113 assert(len
<= b
->len
);
115 for (i
= 0; i
< len
; i
++) {
118 qa
= g_array_index(a
, GQuark
, i
);
119 qb
= g_array_index(b
, GQuark
, i
);
126 static int is_path_child_of(GArray
*path
, GArray
*maybe_parent
)
130 if (babeltrace_debug
) {
133 printf_debug("Is path \"");
134 for (i
= 0; i
< path
->len
; need_dot
= 1, i
++)
135 printf("%s%s", need_dot
? "." : "",
136 g_quark_to_string(g_array_index(path
, GQuark
, i
)));
138 printf("\" child of \"");
139 for (i
= 0; i
< maybe_parent
->len
; need_dot
= 1, i
++)
140 printf("%s%s", need_dot
? "." : "",
141 g_quark_to_string(g_array_index(maybe_parent
, GQuark
, i
)));
145 if (path
->len
<= maybe_parent
->len
) {
149 if (compare_paths(path
, maybe_parent
, maybe_parent
->len
)
150 == maybe_parent
->len
)
155 if (babeltrace_debug
)
156 printf("%s\n", ret
? "Yes" : "No");
160 static struct definition_scope
*
161 get_definition_scope(const struct bt_definition
*definition
)
163 return definition
->scope
;
167 * OK, here is the fun. We want to lookup a field that is:
168 * - either in the same dynamic scope:
169 * - either in the current scope, but prior to the current field.
170 * - or in a parent scope (or parent of parent ...) still in a field
171 * prior to the current field position within the parents.
172 * - or in a different dynamic scope:
173 * - either in a upper dynamic scope (walk down a targeted scope from
174 * the dynamic scope root)
175 * - or in a lower dynamic scope (failure)
176 * The dynamic scope roots are linked together, so we can access the
177 * parent dynamic scope from the child dynamic scope by walking up to
179 * If we cannot find such a field that is prior to our current path, we
182 * cur_path: the path leading to the variant definition.
183 * lookup_path: the path leading to the enum we want to look for.
184 * scope: the definition scope containing the variant definition.
186 struct bt_definition
*
187 bt_lookup_path_definition(GArray
*cur_path
,
189 struct definition_scope
*scope
)
191 struct bt_definition
*definition
, *lookup_definition
;
195 /* Going up in the hierarchy. Check where we come from. */
196 assert(is_path_child_of(cur_path
, scope
->scope_path
));
197 assert(cur_path
->len
- scope
->scope_path
->len
== 1);
200 * First, check if the target name is size one, present in
201 * our parent path, located prior to us.
203 if (lookup_path
->len
== 1) {
204 last
= g_array_index(lookup_path
, GQuark
, 0);
205 lookup_definition
= lookup_field_definition_scope(last
, scope
);
206 last
= g_array_index(cur_path
, GQuark
, cur_path
->len
- 1);
207 definition
= lookup_field_definition_scope(last
, scope
);
209 if (lookup_definition
&& lookup_definition
->index
< definition
->index
)
210 return lookup_definition
;
216 if (is_path_child_of(cur_path
, scope
->scope_path
) &&
217 cur_path
->len
- scope
->scope_path
->len
== 1) {
218 last
= g_array_index(cur_path
, GQuark
, cur_path
->len
- 1);
219 definition
= lookup_field_definition_scope(last
, scope
);
221 index
= definition
->index
;
224 * Getting to a dynamic scope parent. We are
225 * guaranteed that the parent is entirely
226 * located before the child.
231 if (is_path_child_of(lookup_path
, scope
->scope_path
)) {
232 /* Means we can lookup the field in this scope */
233 last
= g_array_index(lookup_path
, GQuark
,
234 scope
->scope_path
->len
);
235 lookup_definition
= lookup_field_definition_scope(last
, scope
);
236 if (!lookup_definition
|| ((index
!= -1) && lookup_definition
->index
>= index
))
238 /* Found it! And it is prior to the current field. */
239 if (lookup_path
->len
- scope
->scope_path
->len
== 1) {
241 return lookup_definition
;
243 scope
= get_definition_scope(lookup_definition
);
244 /* Check if the definition has a sub-scope */
248 * Don't compare index anymore, because we are
249 * going within a scope that has been validated
250 * to be entirely prior to the current scope.
257 /* lookup_path is within an upper scope */
258 cur_path
= scope
->scope_path
;
259 scope
= scope
->parent_scope
;
265 int bt_register_field_definition(GQuark field_name
, struct bt_definition
*definition
,
266 struct definition_scope
*scope
)
268 if (!scope
|| !field_name
)
271 /* Only lookup in local scope */
272 if (lookup_field_definition_scope(field_name
, scope
))
275 g_hash_table_insert(scope
->definitions
,
276 (gpointer
) (unsigned long) field_name
,
278 /* Don't keep reference on definition */
282 void bt_declaration_ref(struct bt_declaration
*declaration
)
287 void bt_declaration_unref(struct bt_declaration
*declaration
)
291 if (!--declaration
->ref
)
292 declaration
->declaration_free(declaration
);
295 void bt_definition_ref(struct bt_definition
*definition
)
300 void bt_definition_unref(struct bt_definition
*definition
)
304 if (!--definition
->ref
)
305 definition
->declaration
->definition_free(definition
);
308 struct declaration_scope
*
309 bt_new_declaration_scope(struct declaration_scope
*parent_scope
)
311 struct declaration_scope
*scope
= g_new(struct declaration_scope
, 1);
313 scope
->typedef_declarations
= g_hash_table_new_full(g_direct_hash
,
314 g_direct_equal
, NULL
,
315 (GDestroyNotify
) bt_declaration_unref
);
316 scope
->struct_declarations
= g_hash_table_new_full(g_direct_hash
,
317 g_direct_equal
, NULL
,
318 (GDestroyNotify
) bt_declaration_unref
);
319 scope
->variant_declarations
= g_hash_table_new_full(g_direct_hash
,
320 g_direct_equal
, NULL
,
321 (GDestroyNotify
) bt_declaration_unref
);
322 scope
->enum_declarations
= g_hash_table_new_full(g_direct_hash
,
323 g_direct_equal
, NULL
,
324 (GDestroyNotify
) bt_declaration_unref
);
325 scope
->parent_scope
= parent_scope
;
329 void bt_free_declaration_scope(struct declaration_scope
*scope
)
331 g_hash_table_destroy(scope
->enum_declarations
);
332 g_hash_table_destroy(scope
->variant_declarations
);
333 g_hash_table_destroy(scope
->struct_declarations
);
334 g_hash_table_destroy(scope
->typedef_declarations
);
339 struct declaration_struct
*bt_lookup_struct_declaration_scope(GQuark struct_name
,
340 struct declaration_scope
*scope
)
342 return g_hash_table_lookup(scope
->struct_declarations
,
343 (gconstpointer
) (unsigned long) struct_name
);
346 struct declaration_struct
*bt_lookup_struct_declaration(GQuark struct_name
,
347 struct declaration_scope
*scope
)
349 struct declaration_struct
*declaration
;
352 declaration
= bt_lookup_struct_declaration_scope(struct_name
, scope
);
355 scope
= scope
->parent_scope
;
360 int bt_register_struct_declaration(GQuark struct_name
,
361 struct declaration_struct
*struct_declaration
,
362 struct declaration_scope
*scope
)
370 /* Only lookup in local scope */
371 if (bt_lookup_struct_declaration_scope(struct_name
, scope
))
374 g_hash_table_insert(scope
->struct_declarations
,
375 (gpointer
) (unsigned long) struct_name
,
377 bt_declaration_ref(&struct_declaration
->p
);
379 /* Also add in typedef/typealias scopes */
380 prefix_name
= prefix_quark("struct ", struct_name
);
381 ret
= bt_register_declaration(prefix_name
, &struct_declaration
->p
, scope
);
387 struct declaration_untagged_variant
*
388 bt_lookup_variant_declaration_scope(GQuark variant_name
,
389 struct declaration_scope
*scope
)
391 return g_hash_table_lookup(scope
->variant_declarations
,
392 (gconstpointer
) (unsigned long) variant_name
);
395 struct declaration_untagged_variant
*
396 bt_lookup_variant_declaration(GQuark variant_name
,
397 struct declaration_scope
*scope
)
399 struct declaration_untagged_variant
*declaration
;
402 declaration
= bt_lookup_variant_declaration_scope(variant_name
, scope
);
405 scope
= scope
->parent_scope
;
410 int bt_register_variant_declaration(GQuark variant_name
,
411 struct declaration_untagged_variant
*untagged_variant_declaration
,
412 struct declaration_scope
*scope
)
420 /* Only lookup in local scope */
421 if (bt_lookup_variant_declaration_scope(variant_name
, scope
))
424 g_hash_table_insert(scope
->variant_declarations
,
425 (gpointer
) (unsigned long) variant_name
,
426 untagged_variant_declaration
);
427 bt_declaration_ref(&untagged_variant_declaration
->p
);
429 /* Also add in typedef/typealias scopes */
430 prefix_name
= prefix_quark("variant ", variant_name
);
431 ret
= bt_register_declaration(prefix_name
,
432 &untagged_variant_declaration
->p
, scope
);
438 struct declaration_enum
*
439 bt_lookup_enum_declaration_scope(GQuark enum_name
,
440 struct declaration_scope
*scope
)
442 return g_hash_table_lookup(scope
->enum_declarations
,
443 (gconstpointer
) (unsigned long) enum_name
);
446 struct declaration_enum
*
447 bt_lookup_enum_declaration(GQuark enum_name
,
448 struct declaration_scope
*scope
)
450 struct declaration_enum
*declaration
;
453 declaration
= bt_lookup_enum_declaration_scope(enum_name
, scope
);
456 scope
= scope
->parent_scope
;
461 int bt_register_enum_declaration(GQuark enum_name
,
462 struct declaration_enum
*enum_declaration
,
463 struct declaration_scope
*scope
)
471 /* Only lookup in local scope */
472 if (bt_lookup_enum_declaration_scope(enum_name
, scope
))
475 g_hash_table_insert(scope
->enum_declarations
,
476 (gpointer
) (unsigned long) enum_name
,
478 bt_declaration_ref(&enum_declaration
->p
);
480 /* Also add in typedef/typealias scopes */
481 prefix_name
= prefix_quark("enum ", enum_name
);
482 ret
= bt_register_declaration(prefix_name
, &enum_declaration
->p
, scope
);
487 static struct definition_scope
*
488 _bt_new_definition_scope(struct definition_scope
*parent_scope
,
491 struct definition_scope
*scope
= g_new(struct definition_scope
, 1);
493 scope
->definitions
= g_hash_table_new(g_direct_hash
,
495 scope
->parent_scope
= parent_scope
;
496 scope
->scope_path
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
),
498 g_array_set_size(scope
->scope_path
, scope_path_len
);
502 GQuark
bt_new_definition_path(struct definition_scope
*parent_scope
,
503 GQuark field_name
, const char *root_name
)
510 str
= g_string_new("");
512 g_string_append(str
, root_name
);
514 } else if (parent_scope
) {
517 for (i
= 0; i
< parent_scope
->scope_path
->len
; i
++) {
518 GQuark q
= g_array_index(parent_scope
->scope_path
,
523 g_string_append(str
, ".");
524 g_string_append(str
, g_quark_to_string(q
));
530 g_string_append(str
, ".");
531 g_string_append(str
, g_quark_to_string(field_name
));
533 c_str
= g_string_free(str
, FALSE
);
534 if (c_str
[0] == '\0')
536 path
= g_quark_from_string(c_str
);
537 printf_debug("new definition path: %s\n", c_str
);
542 struct definition_scope
*
543 bt_new_definition_scope(struct definition_scope
*parent_scope
,
544 GQuark field_name
, const char *root_name
)
546 struct definition_scope
*scope
;
549 scope
= _bt_new_definition_scope(parent_scope
, 0);
550 bt_append_scope_path(root_name
, scope
->scope_path
);
552 int scope_path_len
= 1;
554 assert(parent_scope
);
555 scope_path_len
+= parent_scope
->scope_path
->len
;
556 scope
= _bt_new_definition_scope(parent_scope
, scope_path_len
);
557 memcpy(scope
->scope_path
->data
, parent_scope
->scope_path
->data
,
558 sizeof(GQuark
) * (scope_path_len
- 1));
559 g_array_index(scope
->scope_path
, GQuark
, scope_path_len
- 1) =
562 if (babeltrace_debug
) {
565 printf_debug("new definition scope: ");
566 for (i
= 0; i
< scope
->scope_path
->len
; need_dot
= 1, i
++)
567 printf("%s%s", need_dot
? "." : "",
568 g_quark_to_string(g_array_index(scope
->scope_path
, GQuark
, i
)));
575 * in: path (dot separated), out: q (GArray of GQuark)
577 void bt_append_scope_path(const char *path
, GArray
*q
)
579 const char *ptrbegin
, *ptrend
= path
;
587 ptrend
= strchr(ptrbegin
, '.');
590 len
= ptrend
- ptrbegin
;
591 /* Don't accept two consecutive dots */
593 str
= g_new(char, len
+ 1); /* include \0 */
594 memcpy(str
, ptrbegin
, len
);
596 quark
= g_quark_from_string(str
);
597 g_array_append_val(q
, quark
);
599 ptrend
++; /* skip current dot */
601 /* last. Check for trailing dot (and discard). */
602 if (ptrbegin
[0] != '\0') {
603 quark
= g_quark_from_string(ptrbegin
);
604 g_array_append_val(q
, quark
);
608 void bt_free_definition_scope(struct definition_scope
*scope
)
610 g_array_free(scope
->scope_path
, TRUE
);
611 g_hash_table_destroy(scope
->definitions
);
615 struct bt_definition
*bt_lookup_definition(const struct bt_definition
*definition
,
616 const char *field_name
)
618 struct definition_scope
*scope
= get_definition_scope(definition
);
623 return lookup_field_definition_scope(g_quark_from_string(field_name
),
627 struct definition_integer
*bt_lookup_integer(const struct bt_definition
*definition
,
628 const char *field_name
,
631 struct bt_definition
*lookup
;
632 struct definition_integer
*lookup_integer
;
634 lookup
= bt_lookup_definition(definition
, field_name
);
637 if (lookup
->declaration
->id
!= CTF_TYPE_INTEGER
)
639 lookup_integer
= container_of(lookup
, struct definition_integer
, p
);
640 if (lookup_integer
->declaration
->signedness
!= signedness
)
642 return lookup_integer
;
645 struct definition_enum
*bt_lookup_enum(const struct bt_definition
*definition
,
646 const char *field_name
,
649 struct bt_definition
*lookup
;
650 struct definition_enum
*lookup_enum
;
652 lookup
= bt_lookup_definition(definition
, field_name
);
655 if (lookup
->declaration
->id
!= CTF_TYPE_ENUM
)
657 lookup_enum
= container_of(lookup
, struct definition_enum
, p
);
658 if (lookup_enum
->integer
->declaration
->signedness
!= signedness
)
663 struct bt_definition
*bt_lookup_variant(const struct bt_definition
*definition
,
664 const char *field_name
)
666 struct bt_definition
*lookup
;
667 struct definition_variant
*bt_lookup_variant
;
669 lookup
= bt_lookup_definition(definition
, field_name
);
672 if (lookup
->declaration
->id
!= CTF_TYPE_VARIANT
)
674 bt_lookup_variant
= container_of(lookup
, struct definition_variant
, p
);
675 lookup
= bt_variant_get_current_field(bt_lookup_variant
);