3ffe7e2f1b83d0e92efb5d2796f15406ccaf9b98
[babeltrace.git] / types / types.c
1 /*
2 * types.c
3 *
4 * BabelTrace - Converter
5 *
6 * Types registry.
7 *
8 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
9 *
10 * Author: Mathieu Desnoyers <mathieu.desnoyers@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
23 #include <babeltrace/format.h>
24 #include <babeltrace/babeltrace-internal.h>
25 #include <babeltrace/types.h>
26 #include <limits.h>
27 #include <glib.h>
28 #include <errno.h>
29
30 static
31 GQuark prefix_quark(const char *prefix, GQuark quark)
32 {
33 GQuark nq;
34 GString *str;
35 char *quark_str;
36
37 str = g_string_new(prefix);
38 g_string_append(str, g_quark_to_string(quark));
39 quark_str = g_string_free(str, FALSE);
40 nq = g_quark_from_string(quark_str);
41 g_free(quark_str);
42 return nq;
43 }
44
45 static
46 struct declaration *
47 lookup_declaration_scope(GQuark declaration_name,
48 struct declaration_scope *scope)
49 {
50 return g_hash_table_lookup(scope->typedef_declarations,
51 (gconstpointer) (unsigned long) declaration_name);
52 }
53
54 struct declaration *lookup_declaration(GQuark declaration_name,
55 struct declaration_scope *scope)
56 {
57 struct declaration *declaration;
58
59 while (scope) {
60 declaration = lookup_declaration_scope(declaration_name,
61 scope);
62 if (declaration)
63 return declaration;
64 scope = scope->parent_scope;
65 }
66 return NULL;
67 }
68
69 int register_declaration(GQuark name, struct declaration *declaration,
70 struct declaration_scope *scope)
71 {
72 if (!name)
73 return -EPERM;
74
75 /* Only lookup in local scope */
76 if (lookup_declaration_scope(name, scope))
77 return -EEXIST;
78
79 g_hash_table_insert(scope->typedef_declarations,
80 (gpointer) (unsigned long) name,
81 declaration);
82 declaration_ref(declaration);
83 return 0;
84 }
85
86 static
87 struct definition *
88 lookup_field_definition_scope(GQuark field_name,
89 struct definition_scope *scope)
90 {
91 return g_hash_table_lookup(scope->definitions,
92 (gconstpointer) (unsigned long) field_name);
93 }
94
95 /*
96 * Returns the index at which the paths differ.
97 * If the value returned equals len, it means the paths are identical
98 * from index 0 to len-1.
99 */
100 static int compare_paths(GArray *a, GArray *b, int len)
101 {
102 int i;
103
104 assert(len <= a->len);
105 assert(len <= b->len);
106
107 for (i = 0; i < len; i++) {
108 GQuark qa, qb;
109
110 qa = g_array_index(a, GQuark, i);
111 qb = g_array_index(b, GQuark, i);
112 if (qa != qb)
113 return i;
114 }
115 return i;
116 }
117
118 static int is_path_child_of(GArray *path, GArray *maybe_parent)
119 {
120 int ret;
121
122 if (babeltrace_debug) {
123 int i, need_dot = 0;
124
125 printf_debug("Is path \"");
126 for (i = 0; i < path->len; need_dot = 1, i++)
127 printf("%s%s", need_dot ? "." : "",
128 g_quark_to_string(g_array_index(path, GQuark, i)));
129 need_dot = 0;
130 printf("\" child of \"");
131 for (i = 0; i < maybe_parent->len; need_dot = 1, i++)
132 printf("%s%s", need_dot ? "." : "",
133 g_quark_to_string(g_array_index(maybe_parent, GQuark, i)));
134 printf("\" ? ");
135 }
136
137 if (path->len <= maybe_parent->len) {
138 ret = 0;
139 goto end;
140 }
141 if (compare_paths(path, maybe_parent, maybe_parent->len)
142 == maybe_parent->len)
143 ret = 1;
144 else
145 ret = 0;
146 end:
147 if (babeltrace_debug)
148 printf("%s\n", ret ? "Yes" : "No");
149 return ret;
150 }
151
152 static struct definition_scope *
153 get_definition_scope(const struct definition *definition)
154 {
155 return definition->scope;
156 }
157
158 /*
159 * OK, here is the fun. We want to lookup a field that is:
160 * - either in the same dynamic scope:
161 * - either in the current scope, but prior to the current field.
162 * - or in a parent scope (or parent of parent ...) still in a field
163 * prior to the current field position within the parents.
164 * - or in a different dynamic scope:
165 * - either in a upper dynamic scope (walk down a targeted scope from
166 * the dynamic scope root)
167 * - or in a lower dynamic scope (failure)
168 * The dynamic scope roots are linked together, so we can access the
169 * parent dynamic scope from the child dynamic scope by walking up to
170 * the parent.
171 * If we cannot find such a field that is prior to our current path, we
172 * return NULL.
173 *
174 * cur_path: the path leading to the variant definition.
175 * lookup_path: the path leading to the enum we want to look for.
176 * scope: the definition scope containing the variant definition.
177 */
178 struct definition *
179 lookup_path_definition(GArray *cur_path,
180 GArray *lookup_path,
181 struct definition_scope *scope)
182 {
183 struct definition *definition, *lookup_definition;
184 GQuark last;
185 int index;
186
187 /* Going up in the hierarchy. Check where we come from. */
188 assert(is_path_child_of(cur_path, scope->scope_path));
189 assert(cur_path->len - scope->scope_path->len == 1);
190
191 /*
192 * First, check if the target name is size one, present in
193 * our parent path, located prior to us.
194 */
195 if (lookup_path->len == 1) {
196 last = g_array_index(lookup_path, GQuark, 0);
197 lookup_definition = lookup_field_definition_scope(last, scope);
198 last = g_array_index(cur_path, GQuark, cur_path->len - 1);
199 definition = lookup_field_definition_scope(last, scope);
200 assert(definition);
201 if (lookup_definition && lookup_definition->index < definition->index)
202 return lookup_definition;
203 else
204 return NULL;
205 }
206
207 while (scope) {
208 if (is_path_child_of(cur_path, scope->scope_path) &&
209 cur_path->len - scope->scope_path->len == 1) {
210 last = g_array_index(cur_path, GQuark, cur_path->len - 1);
211 definition = lookup_field_definition_scope(last, scope);
212 assert(definition);
213 index = definition->index;
214 } else {
215 /*
216 * Getting to a dynamic scope parent. We are
217 * guaranteed that the parent is entirely
218 * located before the child.
219 */
220 index = -1;
221 }
222 lookup:
223 if (is_path_child_of(lookup_path, scope->scope_path)) {
224 /* Means we can lookup the field in this scope */
225 last = g_array_index(lookup_path, GQuark,
226 scope->scope_path->len);
227 lookup_definition = lookup_field_definition_scope(last, scope);
228 if (!lookup_definition || ((index != -1) && lookup_definition->index >= index))
229 return NULL;
230 /* Found it! And it is prior to the current field. */
231 if (lookup_path->len - scope->scope_path->len == 1) {
232 /* Direct child */
233 return lookup_definition;
234 } else {
235 scope = get_definition_scope(lookup_definition);
236 /* Check if the definition has a sub-scope */
237 if (!scope)
238 return NULL;
239 /*
240 * Don't compare index anymore, because we are
241 * going within a scope that has been validated
242 * to be entirely prior to the current scope.
243 */
244 cur_path = NULL;
245 index = -1;
246 goto lookup;
247 }
248 } else {
249 /* lookup_path is within an upper scope */
250 cur_path = scope->scope_path;
251 scope = scope->parent_scope;
252 }
253 }
254 return NULL;
255 }
256
257 int register_field_definition(GQuark field_name, struct definition *definition,
258 struct definition_scope *scope)
259 {
260 if (!scope || !field_name)
261 return -EPERM;
262
263 /* Only lookup in local scope */
264 if (lookup_field_definition_scope(field_name, scope))
265 return -EEXIST;
266
267 g_hash_table_insert(scope->definitions,
268 (gpointer) (unsigned long) field_name,
269 definition);
270 /* Don't keep reference on definition */
271 return 0;
272 }
273
274 void declaration_ref(struct declaration *declaration)
275 {
276 declaration->ref++;
277 }
278
279 void declaration_unref(struct declaration *declaration)
280 {
281 if (!declaration)
282 return;
283 if (!--declaration->ref)
284 declaration->declaration_free(declaration);
285 }
286
287 void definition_ref(struct definition *definition)
288 {
289 definition->ref++;
290 }
291
292 void definition_unref(struct definition *definition)
293 {
294 if (!definition)
295 return;
296 if (!--definition->ref)
297 definition->declaration->definition_free(definition);
298 }
299
300 struct declaration_scope *
301 new_declaration_scope(struct declaration_scope *parent_scope)
302 {
303 struct declaration_scope *scope = g_new(struct declaration_scope, 1);
304
305 scope->typedef_declarations = g_hash_table_new_full(g_direct_hash,
306 g_direct_equal, NULL,
307 (GDestroyNotify) declaration_unref);
308 scope->struct_declarations = g_hash_table_new_full(g_direct_hash,
309 g_direct_equal, NULL,
310 (GDestroyNotify) declaration_unref);
311 scope->variant_declarations = g_hash_table_new_full(g_direct_hash,
312 g_direct_equal, NULL,
313 (GDestroyNotify) declaration_unref);
314 scope->enum_declarations = g_hash_table_new_full(g_direct_hash,
315 g_direct_equal, NULL,
316 (GDestroyNotify) declaration_unref);
317 scope->parent_scope = parent_scope;
318 return scope;
319 }
320
321 void free_declaration_scope(struct declaration_scope *scope)
322 {
323 g_hash_table_destroy(scope->enum_declarations);
324 g_hash_table_destroy(scope->variant_declarations);
325 g_hash_table_destroy(scope->struct_declarations);
326 g_hash_table_destroy(scope->typedef_declarations);
327 g_free(scope);
328 }
329
330 static
331 struct declaration_struct *lookup_struct_declaration_scope(GQuark struct_name,
332 struct declaration_scope *scope)
333 {
334 return g_hash_table_lookup(scope->struct_declarations,
335 (gconstpointer) (unsigned long) struct_name);
336 }
337
338 struct declaration_struct *lookup_struct_declaration(GQuark struct_name,
339 struct declaration_scope *scope)
340 {
341 struct declaration_struct *declaration;
342
343 while (scope) {
344 declaration = lookup_struct_declaration_scope(struct_name, scope);
345 if (declaration)
346 return declaration;
347 scope = scope->parent_scope;
348 }
349 return NULL;
350 }
351
352 int register_struct_declaration(GQuark struct_name,
353 struct declaration_struct *struct_declaration,
354 struct declaration_scope *scope)
355 {
356 GQuark prefix_name;
357 int ret;
358
359 if (!struct_name)
360 return -EPERM;
361
362 /* Only lookup in local scope */
363 if (lookup_struct_declaration_scope(struct_name, scope))
364 return -EEXIST;
365
366 g_hash_table_insert(scope->struct_declarations,
367 (gpointer) (unsigned long) struct_name,
368 struct_declaration);
369 declaration_ref(&struct_declaration->p);
370
371 /* Also add in typedef/typealias scopes */
372 prefix_name = prefix_quark("struct ", struct_name);
373 ret = register_declaration(prefix_name, &struct_declaration->p, scope);
374 assert(!ret);
375 return 0;
376 }
377
378 static
379 struct declaration_untagged_variant *
380 lookup_variant_declaration_scope(GQuark variant_name,
381 struct declaration_scope *scope)
382 {
383 return g_hash_table_lookup(scope->variant_declarations,
384 (gconstpointer) (unsigned long) variant_name);
385 }
386
387 struct declaration_untagged_variant *
388 lookup_variant_declaration(GQuark variant_name,
389 struct declaration_scope *scope)
390 {
391 struct declaration_untagged_variant *declaration;
392
393 while (scope) {
394 declaration = lookup_variant_declaration_scope(variant_name, scope);
395 if (declaration)
396 return declaration;
397 scope = scope->parent_scope;
398 }
399 return NULL;
400 }
401
402 int register_variant_declaration(GQuark variant_name,
403 struct declaration_untagged_variant *untagged_variant_declaration,
404 struct declaration_scope *scope)
405 {
406 GQuark prefix_name;
407 int ret;
408
409 if (!variant_name)
410 return -EPERM;
411
412 /* Only lookup in local scope */
413 if (lookup_variant_declaration_scope(variant_name, scope))
414 return -EEXIST;
415
416 g_hash_table_insert(scope->variant_declarations,
417 (gpointer) (unsigned long) variant_name,
418 untagged_variant_declaration);
419 declaration_ref(&untagged_variant_declaration->p);
420
421 /* Also add in typedef/typealias scopes */
422 prefix_name = prefix_quark("variant ", variant_name);
423 ret = register_declaration(prefix_name,
424 &untagged_variant_declaration->p, scope);
425 assert(!ret);
426 return 0;
427 }
428
429 static
430 struct declaration_enum *
431 lookup_enum_declaration_scope(GQuark enum_name,
432 struct declaration_scope *scope)
433 {
434 return g_hash_table_lookup(scope->enum_declarations,
435 (gconstpointer) (unsigned long) enum_name);
436 }
437
438 struct declaration_enum *
439 lookup_enum_declaration(GQuark enum_name,
440 struct declaration_scope *scope)
441 {
442 struct declaration_enum *declaration;
443
444 while (scope) {
445 declaration = lookup_enum_declaration_scope(enum_name, scope);
446 if (declaration)
447 return declaration;
448 scope = scope->parent_scope;
449 }
450 return NULL;
451 }
452
453 int register_enum_declaration(GQuark enum_name,
454 struct declaration_enum *enum_declaration,
455 struct declaration_scope *scope)
456 {
457 GQuark prefix_name;
458 int ret;
459
460 if (!enum_name)
461 return -EPERM;
462
463 /* Only lookup in local scope */
464 if (lookup_enum_declaration_scope(enum_name, scope))
465 return -EEXIST;
466
467 g_hash_table_insert(scope->enum_declarations,
468 (gpointer) (unsigned long) enum_name,
469 enum_declaration);
470 declaration_ref(&enum_declaration->p);
471
472 /* Also add in typedef/typealias scopes */
473 prefix_name = prefix_quark("enum ", enum_name);
474 ret = register_declaration(prefix_name, &enum_declaration->p, scope);
475 assert(!ret);
476 return 0;
477 }
478
479 static struct definition_scope *
480 _new_definition_scope(struct definition_scope *parent_scope,
481 int scope_path_len)
482 {
483 struct definition_scope *scope = g_new(struct definition_scope, 1);
484
485 scope->definitions = g_hash_table_new(g_direct_hash,
486 g_direct_equal);
487 scope->parent_scope = parent_scope;
488 scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark),
489 scope_path_len);
490 g_array_set_size(scope->scope_path, scope_path_len);
491 return scope;
492 }
493
494 GQuark new_definition_path(struct definition_scope *parent_scope,
495 GQuark field_name, const char *root_name)
496 {
497 GQuark path;
498 GString *str;
499 gchar *c_str;
500 int need_dot = 0;
501
502 str = g_string_new("");
503 if (root_name) {
504 g_string_append(str, root_name);
505 need_dot = 1;
506 } else if (parent_scope) {
507 int i;
508
509 for (i = 0; i < parent_scope->scope_path->len; i++) {
510 GQuark q = g_array_index(parent_scope->scope_path,
511 GQuark, i);
512 if (!q)
513 continue;
514 if (need_dot)
515 g_string_append(str, ".");
516 g_string_append(str, g_quark_to_string(q));
517 need_dot = 1;
518 }
519 }
520 if (field_name) {
521 if (need_dot)
522 g_string_append(str, ".");
523 g_string_append(str, g_quark_to_string(field_name));
524 }
525 c_str = g_string_free(str, FALSE);
526 if (c_str[0] == '\0')
527 return 0;
528 path = g_quark_from_string(c_str);
529 printf_debug("new definition path: %s\n", c_str);
530 g_free(c_str);
531 return path;
532 }
533
534 struct definition_scope *
535 new_definition_scope(struct definition_scope *parent_scope,
536 GQuark field_name, const char *root_name)
537 {
538 struct definition_scope *scope;
539
540 if (root_name) {
541 scope = _new_definition_scope(parent_scope, 0);
542 append_scope_path(root_name, scope->scope_path);
543 } else {
544 int scope_path_len = 1;
545
546 assert(parent_scope);
547 scope_path_len += parent_scope->scope_path->len;
548 scope = _new_definition_scope(parent_scope, scope_path_len);
549 memcpy(scope->scope_path->data, parent_scope->scope_path->data,
550 sizeof(GQuark) * (scope_path_len - 1));
551 g_array_index(scope->scope_path, GQuark, scope_path_len - 1) =
552 field_name;
553 }
554 if (babeltrace_debug) {
555 int i, need_dot = 0;
556
557 printf_debug("new definition scope: ");
558 for (i = 0; i < scope->scope_path->len; need_dot = 1, i++)
559 printf("%s%s", need_dot ? "." : "",
560 g_quark_to_string(g_array_index(scope->scope_path, GQuark, i)));
561 printf("\n");
562 }
563 return scope;
564 }
565
566 /*
567 * in: path (dot separated), out: q (GArray of GQuark)
568 */
569 void append_scope_path(const char *path, GArray *q)
570 {
571 const char *ptrbegin, *ptrend = path;
572 GQuark quark;
573
574 for (;;) {
575 char *str;
576 size_t len;
577
578 ptrbegin = ptrend;
579 ptrend = strchr(ptrbegin, '.');
580 if (!ptrend)
581 break;
582 len = ptrend - ptrbegin;
583 /* Don't accept two consecutive dots */
584 assert(len != 0);
585 str = g_new(char, len + 1); /* include \0 */
586 memcpy(str, ptrbegin, len);
587 str[len] = '\0';
588 quark = g_quark_from_string(str);
589 g_array_append_val(q, quark);
590 g_free(str);
591 ptrend++; /* skip current dot */
592 }
593 /* last. Check for trailing dot (and discard). */
594 if (ptrbegin[0] != '\0') {
595 quark = g_quark_from_string(ptrbegin);
596 g_array_append_val(q, quark);
597 }
598 }
599
600 void free_definition_scope(struct definition_scope *scope)
601 {
602 g_array_free(scope->scope_path, TRUE);
603 g_hash_table_destroy(scope->definitions);
604 g_free(scope);
605 }
606
607 struct definition *lookup_definition(const struct definition *definition,
608 const char *field_name)
609 {
610 struct definition_scope *scope = get_definition_scope(definition);
611
612 if (!scope)
613 return NULL;
614
615 return lookup_field_definition_scope(g_quark_from_string(field_name),
616 scope);
617 }
618
619 struct definition_integer *lookup_integer(const struct definition *definition,
620 const char *field_name,
621 int signedness)
622 {
623 struct definition *lookup;
624 struct definition_integer *lookup_integer;
625
626 lookup = lookup_definition(definition, field_name);
627 if (!lookup)
628 return NULL;
629 if (lookup->declaration->id != CTF_TYPE_INTEGER)
630 return NULL;
631 lookup_integer = container_of(lookup, struct definition_integer, p);
632 if (lookup_integer->declaration->signedness != signedness)
633 return NULL;
634 return lookup_integer;
635 }
636
637 struct definition_enum *lookup_enum(const struct definition *definition,
638 const char *field_name,
639 int signedness)
640 {
641 struct definition *lookup;
642 struct definition_enum *lookup_enum;
643
644 lookup = lookup_definition(definition, field_name);
645 if (!lookup)
646 return NULL;
647 if (lookup->declaration->id != CTF_TYPE_ENUM)
648 return NULL;
649 lookup_enum = container_of(lookup, struct definition_enum, p);
650 if (lookup_enum->integer->declaration->signedness != signedness)
651 return NULL;
652 return lookup_enum;
653 }
654
655 struct definition *lookup_variant(const struct definition *definition,
656 const char *field_name)
657 {
658 struct definition *lookup;
659 struct definition_variant *lookup_variant;
660
661 lookup = lookup_definition(definition, field_name);
662 if (!lookup)
663 return NULL;
664 if (lookup->declaration->id != CTF_TYPE_VARIANT)
665 return NULL;
666 lookup_variant = container_of(lookup, struct definition_variant, p);
667 lookup = variant_get_current_field(lookup_variant);
668 assert(lookup);
669 return lookup;
670 }
This page took 0.066217 seconds and 3 git commands to generate.