4 * BabelTrace - Converter
8 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
21 #include <babeltrace/format.h>
22 #include <babeltrace/babeltrace.h>
28 GQuark
prefix_quark(const char *prefix
, GQuark quark
)
33 str
= g_string_new(prefix
);
34 g_string_append(str
, g_quark_to_string(quark
));
35 nq
= g_quark_from_string(g_string_free(str
, FALSE
));
41 lookup_declaration_scope(GQuark declaration_name
,
42 struct declaration_scope
*scope
)
44 return g_hash_table_lookup(scope
->typedef_declarations
,
45 (gconstpointer
) (unsigned long) declaration_name
);
48 struct declaration
*lookup_declaration(GQuark declaration_name
,
49 struct declaration_scope
*scope
)
51 struct declaration
*declaration
;
54 declaration
= lookup_declaration_scope(declaration_name
,
58 scope
= scope
->parent_scope
;
63 int register_declaration(GQuark name
, struct declaration
*declaration
,
64 struct declaration_scope
*scope
)
69 /* Only lookup in local scope */
70 if (lookup_declaration_scope(name
, scope
))
73 g_hash_table_insert(scope
->typedef_declarations
,
74 (gpointer
) (unsigned long) name
,
76 declaration_ref(declaration
);
82 lookup_field_definition_scope(GQuark field_name
,
83 struct definition_scope
*scope
)
85 return g_hash_table_lookup(scope
->definitions
,
86 (gconstpointer
) (unsigned long) field_name
);
90 * Returns the index at which the paths differ.
91 * If the value returned equals len, it means the paths are identical
92 * from index 0 to len-1.
94 static int compare_paths(GArray
*a
, GArray
*b
, int len
)
98 assert(len
<= a
->len
);
99 assert(len
<= b
->len
);
101 for (i
= 0; i
< len
; i
++) {
104 qa
= g_array_index(a
, GQuark
, i
);
105 qb
= g_array_index(b
, GQuark
, i
);
112 static int is_path_child_of(GArray
*path
, GArray
*maybe_parent
)
116 if (babeltrace_debug
) {
119 printf_debug("Is path \"");
120 for (i
= 0; i
< path
->len
; need_dot
= 1, i
++)
121 printf("%s%s", need_dot
? "." : "",
122 g_quark_to_string(g_array_index(path
, GQuark
, i
)));
124 printf("\" child of \"");
125 for (i
= 0; i
< maybe_parent
->len
; need_dot
= 1, i
++)
126 printf("%s%s", need_dot
? "." : "",
127 g_quark_to_string(g_array_index(maybe_parent
, GQuark
, i
)));
131 if (path
->len
<= maybe_parent
->len
) {
135 if (compare_paths(path
, maybe_parent
, maybe_parent
->len
)
136 == maybe_parent
->len
)
141 if (babeltrace_debug
)
142 printf("%s\n", ret
? "Yes" : "No");
146 static struct definition_scope
*
147 get_definition_scope(struct definition
*definition
)
149 switch (definition
->declaration
->id
) {
150 case CTF_TYPE_STRUCT
:
152 struct definition_struct
*def
=
153 container_of(definition
, struct definition_struct
, p
);
156 case CTF_TYPE_VARIANT
:
158 struct definition_variant
*def
=
159 container_of(definition
, struct definition_variant
, p
);
164 struct definition_array
*def
=
165 container_of(definition
, struct definition_array
, p
);
168 case CTF_TYPE_SEQUENCE
:
170 struct definition_sequence
*def
=
171 container_of(definition
, struct definition_sequence
, p
);
175 case CTF_TYPE_INTEGER
:
178 case CTF_TYPE_STRING
:
179 case CTF_TYPE_UNKNOWN
:
186 * OK, here is the fun. We want to lookup a field that is:
187 * - either in the same dynamic scope:
188 * - either in the current scope, but prior to the current field.
189 * - or in a parent scope (or parent of parent ...) still in a field
190 * prior to the current field position within the parents.
191 * - or in a different dynamic scope:
192 * - either in a upper dynamic scope (walk down a targeted scope from
193 * the dynamic scope root)
194 * - or in a lower dynamic scope (failure)
195 * The dynamic scope roots are linked together, so we can access the
196 * parent dynamic scope from the child dynamic scope by walking up to
198 * If we cannot find such a field that is prior to our current path, we
201 * cur_path: the path leading to the variant definition.
202 * lookup_path: the path leading to the enum we want to look for.
203 * scope: the definition scope containing the variant definition.
206 lookup_definition(GArray
*cur_path
,
208 struct definition_scope
*scope
)
210 struct definition
*definition
, *lookup_definition
;
214 /* Going up in the hierarchy. Check where we come from. */
215 assert(is_path_child_of(cur_path
, scope
->scope_path
));
216 assert(cur_path
->len
- scope
->scope_path
->len
== 1);
219 * First, check if the target name is size one, present in
220 * our parent path, located prior to us.
222 if (lookup_path
->len
== 1) {
223 last
= g_array_index(lookup_path
, GQuark
, 0);
224 lookup_definition
= lookup_field_definition_scope(last
, scope
);
225 last
= g_array_index(cur_path
, GQuark
, cur_path
->len
- 1);
226 definition
= lookup_field_definition_scope(last
, scope
);
228 if (lookup_definition
&& lookup_definition
->index
< definition
->index
)
229 return lookup_definition
;
235 if (is_path_child_of(cur_path
, scope
->scope_path
) &&
236 cur_path
->len
- scope
->scope_path
->len
== 1) {
237 last
= g_array_index(cur_path
, GQuark
, cur_path
->len
- 1);
238 definition
= lookup_field_definition_scope(last
, scope
);
240 index
= definition
->index
;
243 * Getting to a dynamic scope parent. We are
244 * guaranteed that the parent is entirely
245 * located before the child.
250 if (is_path_child_of(lookup_path
, scope
->scope_path
)) {
251 /* Means we can lookup the field in this scope */
252 last
= g_array_index(lookup_path
, GQuark
,
253 scope
->scope_path
->len
);
254 lookup_definition
= lookup_field_definition_scope(last
, scope
);
255 if (!lookup_definition
|| ((index
!= -1) && lookup_definition
->index
>= index
))
257 /* Found it! And it is prior to the current field. */
258 if (lookup_path
->len
- scope
->scope_path
->len
== 1) {
260 return lookup_definition
;
262 scope
= get_definition_scope(lookup_definition
);
263 /* Check if the definition has a sub-scope */
267 * Don't compare index anymore, because we are
268 * going within a scope that has been validated
269 * to be entirely prior to the current scope.
276 /* lookup_path is within an upper scope */
277 cur_path
= scope
->scope_path
;
278 scope
= scope
->parent_scope
;
284 int register_field_definition(GQuark field_name
, struct definition
*definition
,
285 struct definition_scope
*scope
)
287 if (!scope
|| !field_name
)
290 /* Only lookup in local scope */
291 if (lookup_field_definition_scope(field_name
, scope
))
294 g_hash_table_insert(scope
->definitions
,
295 (gpointer
) (unsigned long) field_name
,
297 /* Don't keep reference on definition */
301 void declaration_ref(struct declaration
*declaration
)
306 void declaration_unref(struct declaration
*declaration
)
310 if (!--declaration
->ref
)
311 declaration
->declaration_free(declaration
);
314 void definition_ref(struct definition
*definition
)
319 void definition_unref(struct definition
*definition
)
323 if (!--definition
->ref
)
324 definition
->declaration
->definition_free(definition
);
327 struct declaration_scope
*
328 new_declaration_scope(struct declaration_scope
*parent_scope
)
330 struct declaration_scope
*scope
= g_new(struct declaration_scope
, 1);
332 scope
->typedef_declarations
= g_hash_table_new_full(g_direct_hash
,
333 g_direct_equal
, NULL
,
334 (GDestroyNotify
) definition_unref
);
335 scope
->struct_declarations
= g_hash_table_new_full(g_direct_hash
,
336 g_direct_equal
, NULL
,
337 (GDestroyNotify
) declaration_unref
);
338 scope
->variant_declarations
= g_hash_table_new_full(g_direct_hash
,
339 g_direct_equal
, NULL
,
340 (GDestroyNotify
) declaration_unref
);
341 scope
->enum_declarations
= g_hash_table_new_full(g_direct_hash
,
342 g_direct_equal
, NULL
,
343 (GDestroyNotify
) declaration_unref
);
344 scope
->parent_scope
= parent_scope
;
348 void free_declaration_scope(struct declaration_scope
*scope
)
350 g_hash_table_destroy(scope
->enum_declarations
);
351 g_hash_table_destroy(scope
->variant_declarations
);
352 g_hash_table_destroy(scope
->struct_declarations
);
353 g_hash_table_destroy(scope
->typedef_declarations
);
358 struct declaration_struct
*lookup_struct_declaration_scope(GQuark struct_name
,
359 struct declaration_scope
*scope
)
361 return g_hash_table_lookup(scope
->struct_declarations
,
362 (gconstpointer
) (unsigned long) struct_name
);
365 struct declaration_struct
*lookup_struct_declaration(GQuark struct_name
,
366 struct declaration_scope
*scope
)
368 struct declaration_struct
*declaration
;
371 declaration
= lookup_struct_declaration_scope(struct_name
, scope
);
374 scope
= scope
->parent_scope
;
379 int register_struct_declaration(GQuark struct_name
,
380 struct declaration_struct
*struct_declaration
,
381 struct declaration_scope
*scope
)
389 /* Only lookup in local scope */
390 if (lookup_struct_declaration_scope(struct_name
, scope
))
393 g_hash_table_insert(scope
->struct_declarations
,
394 (gpointer
) (unsigned long) struct_name
,
396 declaration_ref(&struct_declaration
->p
);
398 /* Also add in typedef/typealias scopes */
399 prefix_name
= prefix_quark("struct ", struct_name
);
400 ret
= register_declaration(prefix_name
, &struct_declaration
->p
, scope
);
406 struct declaration_untagged_variant
*
407 lookup_variant_declaration_scope(GQuark variant_name
,
408 struct declaration_scope
*scope
)
410 return g_hash_table_lookup(scope
->variant_declarations
,
411 (gconstpointer
) (unsigned long) variant_name
);
414 struct declaration_untagged_variant
*
415 lookup_variant_declaration(GQuark variant_name
,
416 struct declaration_scope
*scope
)
418 struct declaration_untagged_variant
*declaration
;
421 declaration
= lookup_variant_declaration_scope(variant_name
, scope
);
424 scope
= scope
->parent_scope
;
429 int register_variant_declaration(GQuark variant_name
,
430 struct declaration_untagged_variant
*untagged_variant_declaration
,
431 struct declaration_scope
*scope
)
439 /* Only lookup in local scope */
440 if (lookup_variant_declaration_scope(variant_name
, scope
))
443 g_hash_table_insert(scope
->variant_declarations
,
444 (gpointer
) (unsigned long) variant_name
,
445 untagged_variant_declaration
);
446 declaration_ref(&untagged_variant_declaration
->p
);
448 /* Also add in typedef/typealias scopes */
449 prefix_name
= prefix_quark("variant ", variant_name
);
450 ret
= register_declaration(prefix_name
,
451 &untagged_variant_declaration
->p
, scope
);
457 struct declaration_enum
*
458 lookup_enum_declaration_scope(GQuark enum_name
,
459 struct declaration_scope
*scope
)
461 return g_hash_table_lookup(scope
->enum_declarations
,
462 (gconstpointer
) (unsigned long) enum_name
);
465 struct declaration_enum
*
466 lookup_enum_declaration(GQuark enum_name
,
467 struct declaration_scope
*scope
)
469 struct declaration_enum
*declaration
;
472 declaration
= lookup_enum_declaration_scope(enum_name
, scope
);
475 scope
= scope
->parent_scope
;
480 int register_enum_declaration(GQuark enum_name
,
481 struct declaration_enum
*enum_declaration
,
482 struct declaration_scope
*scope
)
490 /* Only lookup in local scope */
491 if (lookup_enum_declaration_scope(enum_name
, scope
))
494 g_hash_table_insert(scope
->enum_declarations
,
495 (gpointer
) (unsigned long) enum_name
,
497 declaration_ref(&enum_declaration
->p
);
499 /* Also add in typedef/typealias scopes */
500 prefix_name
= prefix_quark("enum ", enum_name
);
501 ret
= register_declaration(prefix_name
, &enum_declaration
->p
, scope
);
506 static struct definition_scope
*
507 _new_definition_scope(struct definition_scope
*parent_scope
,
510 struct definition_scope
*scope
= g_new(struct definition_scope
, 1);
512 scope
->definitions
= g_hash_table_new(g_direct_hash
,
514 scope
->parent_scope
= parent_scope
;
515 scope
->scope_path
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
),
517 g_array_set_size(scope
->scope_path
, scope_path_len
);
521 GQuark
new_definition_path(struct definition_scope
*parent_scope
,
522 GQuark field_name
, const char *root_name
)
530 str
= g_string_new("");
532 g_string_append(str
, root_name
);
534 } else if (parent_scope
) {
535 for (i
= 0; i
< parent_scope
->scope_path
->len
; i
++) {
536 GQuark q
= g_array_index(parent_scope
->scope_path
,
541 g_string_append(str
, ".");
542 g_string_append(str
, g_quark_to_string(q
));
548 g_string_append(str
, ".");
549 g_string_append(str
, g_quark_to_string(field_name
));
551 c_str
= g_string_free(str
, FALSE
);
552 if (c_str
[0] == '\0')
554 path
= g_quark_from_string(c_str
);
555 printf_debug("new definition path: %s\n", c_str
);
560 struct definition_scope
*
561 new_definition_scope(struct definition_scope
*parent_scope
,
562 GQuark field_name
, const char *root_name
)
564 struct definition_scope
*scope
;
567 scope
= _new_definition_scope(parent_scope
, 0);
568 append_scope_path(root_name
, scope
->scope_path
);
570 int scope_path_len
= 1;
572 assert(parent_scope
);
573 scope_path_len
+= parent_scope
->scope_path
->len
;
574 scope
= _new_definition_scope(parent_scope
, scope_path_len
);
575 memcpy(scope
->scope_path
->data
, parent_scope
->scope_path
->data
,
576 sizeof(GQuark
) * (scope_path_len
- 1));
577 g_array_index(scope
->scope_path
, GQuark
, scope_path_len
- 1) =
580 if (babeltrace_debug
) {
583 printf_debug("new definition scope: ");
584 for (i
= 0; i
< scope
->scope_path
->len
; need_dot
= 1, i
++)
585 printf("%s%s", need_dot
? "." : "",
586 g_quark_to_string(g_array_index(scope
->scope_path
, GQuark
, i
)));
593 * in: path (dot separated), out: q (GArray of GQuark)
595 void append_scope_path(const char *path
, GArray
*q
)
597 const char *ptrbegin
, *ptrend
= path
;
605 ptrend
= strchr(ptrbegin
, '.');
608 len
= ptrend
- ptrbegin
;
609 /* Don't accept two consecutive dots */
611 str
= g_new(char, len
+ 1); /* include \0 */
612 memcpy(str
, ptrbegin
, len
);
614 quark
= g_quark_from_string(str
);
615 g_array_append_val(q
, quark
);
617 ptrend
++; /* skip current dot */
619 /* last. Check for trailing dot (and discard). */
620 if (ptrbegin
[0] != '\0') {
621 quark
= g_quark_from_string(ptrbegin
);
622 g_array_append_val(q
, quark
);
626 void free_definition_scope(struct definition_scope
*scope
)
628 g_array_free(scope
->scope_path
, TRUE
);
629 g_hash_table_destroy(scope
->definitions
);