Commit | Line | Data |
---|---|---|
6dc2ca62 | 1 | /* |
b1a2f580 | 2 | * types.c |
ccd7e1c8 | 3 | * |
d79865b9 | 4 | * BabelTrace - Converter |
6dc2ca62 MD |
5 | * |
6 | * Types registry. | |
7 | * | |
64fa3fec MD |
8 | * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation |
9 | * | |
10 | * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
de0ba614 | 11 | * |
ccd7e1c8 MD |
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: | |
de0ba614 | 18 | * |
ccd7e1c8 MD |
19 | * The above copyright notice and this permission notice shall be included in |
20 | * all copies or substantial portions of the Software. | |
6dc2ca62 MD |
21 | */ |
22 | ||
4c8bfb7e | 23 | #include <babeltrace/format.h> |
70bd0a12 | 24 | #include <babeltrace/babeltrace-internal.h> |
3122e6f0 | 25 | #include <babeltrace/types.h> |
6a36ddca | 26 | #include <limits.h> |
6dc2ca62 | 27 | #include <glib.h> |
d1708134 MD |
28 | #include <errno.h> |
29 | ||
c054553d | 30 | static |
78af2bcd MD |
31 | GQuark prefix_quark(const char *prefix, GQuark quark) |
32 | { | |
33 | GQuark nq; | |
34 | GString *str; | |
15d4fe3c | 35 | char *quark_str; |
78af2bcd MD |
36 | |
37 | str = g_string_new(prefix); | |
38 | g_string_append(str, g_quark_to_string(quark)); | |
15d4fe3c JD |
39 | quark_str = g_string_free(str, FALSE); |
40 | nq = g_quark_from_string(quark_str); | |
41 | g_free(quark_str); | |
78af2bcd MD |
42 | return nq; |
43 | } | |
44 | ||
45 | static | |
46 | struct declaration * | |
47 | lookup_declaration_scope(GQuark declaration_name, | |
f6625916 | 48 | struct declaration_scope *scope) |
d1708134 | 49 | { |
f6625916 MD |
50 | return g_hash_table_lookup(scope->typedef_declarations, |
51 | (gconstpointer) (unsigned long) declaration_name); | |
d1708134 MD |
52 | } |
53 | ||
78af2bcd | 54 | struct declaration *lookup_declaration(GQuark declaration_name, |
f6625916 | 55 | struct declaration_scope *scope) |
c054553d | 56 | { |
78af2bcd | 57 | struct declaration *declaration; |
c054553d MD |
58 | |
59 | while (scope) { | |
78af2bcd MD |
60 | declaration = lookup_declaration_scope(declaration_name, |
61 | scope); | |
62 | if (declaration) | |
63 | return declaration; | |
c054553d MD |
64 | scope = scope->parent_scope; |
65 | } | |
66 | return NULL; | |
67 | } | |
68 | ||
78af2bcd | 69 | int register_declaration(GQuark name, struct declaration *declaration, |
f6625916 | 70 | struct declaration_scope *scope) |
d1708134 | 71 | { |
64893f33 | 72 | if (!name) |
6ee5115e MD |
73 | return -EPERM; |
74 | ||
c054553d | 75 | /* Only lookup in local scope */ |
78af2bcd | 76 | if (lookup_declaration_scope(name, scope)) |
d1708134 MD |
77 | return -EEXIST; |
78 | ||
f6625916 | 79 | g_hash_table_insert(scope->typedef_declarations, |
64893f33 | 80 | (gpointer) (unsigned long) name, |
f6625916 MD |
81 | declaration); |
82 | declaration_ref(declaration); | |
ac88af75 MD |
83 | return 0; |
84 | } | |
85 | ||
86 | static | |
e1151715 | 87 | struct definition * |
f6625916 MD |
88 | lookup_field_definition_scope(GQuark field_name, |
89 | struct definition_scope *scope) | |
ac88af75 | 90 | { |
e1151715 | 91 | return g_hash_table_lookup(scope->definitions, |
ac88af75 MD |
92 | (gconstpointer) (unsigned long) field_name); |
93 | } | |
94 | ||
05c749e5 MD |
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 | { | |
08c82b90 | 120 | int ret; |
98df1c9f MD |
121 | |
122 | if (babeltrace_debug) { | |
08c82b90 | 123 | int i, need_dot = 0; |
98df1c9f MD |
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 | } | |
05c749e5 MD |
141 | if (compare_paths(path, maybe_parent, maybe_parent->len) |
142 | == maybe_parent->len) | |
98df1c9f | 143 | ret = 1; |
05c749e5 | 144 | else |
98df1c9f MD |
145 | ret = 0; |
146 | end: | |
147 | if (babeltrace_debug) | |
148 | printf("%s\n", ret ? "Yes" : "No"); | |
149 | return ret; | |
05c749e5 MD |
150 | } |
151 | ||
152 | static struct definition_scope * | |
04ae3991 | 153 | get_definition_scope(const struct definition *definition) |
05c749e5 | 154 | { |
a35173fe | 155 | return definition->scope; |
05c749e5 MD |
156 | } |
157 | ||
158 | /* | |
159 | * OK, here is the fun. We want to lookup a field that is: | |
9e29e16e MD |
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. | |
05c749e5 MD |
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 | */ | |
e1151715 | 178 | struct definition * |
a35173fe MD |
179 | lookup_path_definition(GArray *cur_path, |
180 | GArray *lookup_path, | |
181 | struct definition_scope *scope) | |
ac88af75 | 182 | { |
05c749e5 MD |
183 | struct definition *definition, *lookup_definition; |
184 | GQuark last; | |
185 | int index; | |
ac88af75 | 186 | |
98df1c9f MD |
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); | |
05c749e5 MD |
198 | last = g_array_index(cur_path, GQuark, cur_path->len - 1); |
199 | definition = lookup_field_definition_scope(last, scope); | |
200 | assert(definition); | |
98df1c9f MD |
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 | } | |
05c749e5 MD |
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 { | |
05c749e5 MD |
249 | /* lookup_path is within an upper scope */ |
250 | cur_path = scope->scope_path; | |
251 | scope = scope->parent_scope; | |
252 | } | |
ac88af75 MD |
253 | } |
254 | return NULL; | |
255 | } | |
256 | ||
e1151715 | 257 | int register_field_definition(GQuark field_name, struct definition *definition, |
f6625916 | 258 | struct definition_scope *scope) |
ac88af75 | 259 | { |
98df1c9f | 260 | if (!scope || !field_name) |
ac88af75 MD |
261 | return -EPERM; |
262 | ||
263 | /* Only lookup in local scope */ | |
e1151715 | 264 | if (lookup_field_definition_scope(field_name, scope)) |
ac88af75 MD |
265 | return -EEXIST; |
266 | ||
e1151715 | 267 | g_hash_table_insert(scope->definitions, |
ac88af75 | 268 | (gpointer) (unsigned long) field_name, |
e1151715 | 269 | definition); |
98df1c9f | 270 | /* Don't keep reference on definition */ |
d1708134 MD |
271 | return 0; |
272 | } | |
273 | ||
f6625916 | 274 | void declaration_ref(struct declaration *declaration) |
4c8bfb7e | 275 | { |
f6625916 | 276 | declaration->ref++; |
4c8bfb7e MD |
277 | } |
278 | ||
f6625916 | 279 | void declaration_unref(struct declaration *declaration) |
4c8bfb7e | 280 | { |
ff00cad2 MD |
281 | if (!declaration) |
282 | return; | |
f6625916 MD |
283 | if (!--declaration->ref) |
284 | declaration->declaration_free(declaration); | |
4c8bfb7e MD |
285 | } |
286 | ||
e1151715 | 287 | void definition_ref(struct definition *definition) |
d1708134 | 288 | { |
e1151715 | 289 | definition->ref++; |
d1708134 MD |
290 | } |
291 | ||
e1151715 | 292 | void definition_unref(struct definition *definition) |
d1708134 | 293 | { |
ff00cad2 MD |
294 | if (!definition) |
295 | return; | |
e1151715 | 296 | if (!--definition->ref) |
f6625916 | 297 | definition->declaration->definition_free(definition); |
c054553d MD |
298 | } |
299 | ||
f6625916 MD |
300 | struct declaration_scope * |
301 | new_declaration_scope(struct declaration_scope *parent_scope) | |
c054553d | 302 | { |
f6625916 | 303 | struct declaration_scope *scope = g_new(struct declaration_scope, 1); |
c054553d | 304 | |
f6625916 | 305 | scope->typedef_declarations = g_hash_table_new_full(g_direct_hash, |
c13cbf74 | 306 | g_direct_equal, NULL, |
7d11cac6 | 307 | (GDestroyNotify) declaration_unref); |
f6625916 | 308 | scope->struct_declarations = g_hash_table_new_full(g_direct_hash, |
c13cbf74 | 309 | g_direct_equal, NULL, |
f6625916 MD |
310 | (GDestroyNotify) declaration_unref); |
311 | scope->variant_declarations = g_hash_table_new_full(g_direct_hash, | |
c13cbf74 | 312 | g_direct_equal, NULL, |
f6625916 MD |
313 | (GDestroyNotify) declaration_unref); |
314 | scope->enum_declarations = g_hash_table_new_full(g_direct_hash, | |
c054553d | 315 | g_direct_equal, NULL, |
f6625916 | 316 | (GDestroyNotify) declaration_unref); |
64893f33 MD |
317 | scope->parent_scope = parent_scope; |
318 | return scope; | |
319 | } | |
320 | ||
f6625916 | 321 | void free_declaration_scope(struct declaration_scope *scope) |
64893f33 | 322 | { |
f6625916 MD |
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); | |
64893f33 MD |
327 | g_free(scope); |
328 | } | |
329 | ||
c13cbf74 | 330 | static |
f6625916 MD |
331 | struct declaration_struct *lookup_struct_declaration_scope(GQuark struct_name, |
332 | struct declaration_scope *scope) | |
c13cbf74 | 333 | { |
f6625916 | 334 | return g_hash_table_lookup(scope->struct_declarations, |
c13cbf74 MD |
335 | (gconstpointer) (unsigned long) struct_name); |
336 | } | |
337 | ||
f6625916 MD |
338 | struct declaration_struct *lookup_struct_declaration(GQuark struct_name, |
339 | struct declaration_scope *scope) | |
c13cbf74 | 340 | { |
f6625916 | 341 | struct declaration_struct *declaration; |
c13cbf74 MD |
342 | |
343 | while (scope) { | |
f6625916 MD |
344 | declaration = lookup_struct_declaration_scope(struct_name, scope); |
345 | if (declaration) | |
346 | return declaration; | |
c13cbf74 MD |
347 | scope = scope->parent_scope; |
348 | } | |
349 | return NULL; | |
350 | } | |
351 | ||
f6625916 MD |
352 | int register_struct_declaration(GQuark struct_name, |
353 | struct declaration_struct *struct_declaration, | |
354 | struct declaration_scope *scope) | |
c13cbf74 | 355 | { |
78af2bcd MD |
356 | GQuark prefix_name; |
357 | int ret; | |
358 | ||
c13cbf74 MD |
359 | if (!struct_name) |
360 | return -EPERM; | |
361 | ||
362 | /* Only lookup in local scope */ | |
f6625916 | 363 | if (lookup_struct_declaration_scope(struct_name, scope)) |
c13cbf74 MD |
364 | return -EEXIST; |
365 | ||
f6625916 | 366 | g_hash_table_insert(scope->struct_declarations, |
c13cbf74 | 367 | (gpointer) (unsigned long) struct_name, |
f6625916 MD |
368 | struct_declaration); |
369 | declaration_ref(&struct_declaration->p); | |
78af2bcd MD |
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); | |
c13cbf74 MD |
375 | return 0; |
376 | } | |
377 | ||
378 | static | |
a0720417 | 379 | struct declaration_untagged_variant * |
f6625916 MD |
380 | lookup_variant_declaration_scope(GQuark variant_name, |
381 | struct declaration_scope *scope) | |
c13cbf74 | 382 | { |
f6625916 | 383 | return g_hash_table_lookup(scope->variant_declarations, |
c13cbf74 MD |
384 | (gconstpointer) (unsigned long) variant_name); |
385 | } | |
386 | ||
a0720417 | 387 | struct declaration_untagged_variant * |
f6625916 MD |
388 | lookup_variant_declaration(GQuark variant_name, |
389 | struct declaration_scope *scope) | |
c13cbf74 | 390 | { |
a0720417 | 391 | struct declaration_untagged_variant *declaration; |
c13cbf74 MD |
392 | |
393 | while (scope) { | |
f6625916 MD |
394 | declaration = lookup_variant_declaration_scope(variant_name, scope); |
395 | if (declaration) | |
396 | return declaration; | |
c13cbf74 MD |
397 | scope = scope->parent_scope; |
398 | } | |
399 | return NULL; | |
400 | } | |
401 | ||
f6625916 | 402 | int register_variant_declaration(GQuark variant_name, |
a0720417 | 403 | struct declaration_untagged_variant *untagged_variant_declaration, |
f6625916 | 404 | struct declaration_scope *scope) |
c13cbf74 | 405 | { |
78af2bcd MD |
406 | GQuark prefix_name; |
407 | int ret; | |
408 | ||
c13cbf74 MD |
409 | if (!variant_name) |
410 | return -EPERM; | |
411 | ||
412 | /* Only lookup in local scope */ | |
f6625916 | 413 | if (lookup_variant_declaration_scope(variant_name, scope)) |
c13cbf74 MD |
414 | return -EEXIST; |
415 | ||
f6625916 | 416 | g_hash_table_insert(scope->variant_declarations, |
c13cbf74 | 417 | (gpointer) (unsigned long) variant_name, |
a0720417 MD |
418 | untagged_variant_declaration); |
419 | declaration_ref(&untagged_variant_declaration->p); | |
78af2bcd MD |
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); | |
c13cbf74 MD |
426 | return 0; |
427 | } | |
428 | ||
429 | static | |
f6625916 MD |
430 | struct declaration_enum * |
431 | lookup_enum_declaration_scope(GQuark enum_name, | |
432 | struct declaration_scope *scope) | |
c13cbf74 | 433 | { |
f6625916 | 434 | return g_hash_table_lookup(scope->enum_declarations, |
c13cbf74 MD |
435 | (gconstpointer) (unsigned long) enum_name); |
436 | } | |
437 | ||
f6625916 MD |
438 | struct declaration_enum * |
439 | lookup_enum_declaration(GQuark enum_name, | |
440 | struct declaration_scope *scope) | |
c13cbf74 | 441 | { |
f6625916 | 442 | struct declaration_enum *declaration; |
c13cbf74 MD |
443 | |
444 | while (scope) { | |
f6625916 MD |
445 | declaration = lookup_enum_declaration_scope(enum_name, scope); |
446 | if (declaration) | |
447 | return declaration; | |
c13cbf74 MD |
448 | scope = scope->parent_scope; |
449 | } | |
450 | return NULL; | |
451 | } | |
452 | ||
f6625916 MD |
453 | int register_enum_declaration(GQuark enum_name, |
454 | struct declaration_enum *enum_declaration, | |
455 | struct declaration_scope *scope) | |
c13cbf74 | 456 | { |
78af2bcd MD |
457 | GQuark prefix_name; |
458 | int ret; | |
459 | ||
c13cbf74 MD |
460 | if (!enum_name) |
461 | return -EPERM; | |
462 | ||
463 | /* Only lookup in local scope */ | |
f6625916 | 464 | if (lookup_enum_declaration_scope(enum_name, scope)) |
c13cbf74 MD |
465 | return -EEXIST; |
466 | ||
f6625916 | 467 | g_hash_table_insert(scope->enum_declarations, |
c13cbf74 | 468 | (gpointer) (unsigned long) enum_name, |
f6625916 MD |
469 | enum_declaration); |
470 | declaration_ref(&enum_declaration->p); | |
78af2bcd MD |
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); | |
c13cbf74 MD |
476 | return 0; |
477 | } | |
478 | ||
9e29e16e MD |
479 | static struct definition_scope * |
480 | _new_definition_scope(struct definition_scope *parent_scope, | |
481 | int scope_path_len) | |
64893f33 | 482 | { |
e1151715 | 483 | struct definition_scope *scope = g_new(struct definition_scope, 1); |
64893f33 | 484 | |
98df1c9f MD |
485 | scope->definitions = g_hash_table_new(g_direct_hash, |
486 | g_direct_equal); | |
c054553d | 487 | scope->parent_scope = parent_scope; |
05c749e5 MD |
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); | |
9e29e16e MD |
491 | return scope; |
492 | } | |
493 | ||
98df1c9f MD |
494 | GQuark new_definition_path(struct definition_scope *parent_scope, |
495 | GQuark field_name, const char *root_name) | |
31262354 MD |
496 | { |
497 | GQuark path; | |
498 | GString *str; | |
499 | gchar *c_str; | |
98df1c9f | 500 | int need_dot = 0; |
31262354 MD |
501 | |
502 | str = g_string_new(""); | |
98df1c9f MD |
503 | if (root_name) { |
504 | g_string_append(str, root_name); | |
505 | need_dot = 1; | |
506 | } else if (parent_scope) { | |
08c82b90 MD |
507 | int i; |
508 | ||
31262354 MD |
509 | for (i = 0; i < parent_scope->scope_path->len; i++) { |
510 | GQuark q = g_array_index(parent_scope->scope_path, | |
511 | GQuark, i); | |
b7e35bad MD |
512 | if (!q) |
513 | continue; | |
98df1c9f MD |
514 | if (need_dot) |
515 | g_string_append(str, "."); | |
31262354 | 516 | g_string_append(str, g_quark_to_string(q)); |
98df1c9f | 517 | need_dot = 1; |
31262354 MD |
518 | } |
519 | } | |
98df1c9f MD |
520 | if (field_name) { |
521 | if (need_dot) | |
522 | g_string_append(str, "."); | |
b7e35bad | 523 | g_string_append(str, g_quark_to_string(field_name)); |
98df1c9f | 524 | } |
31262354 | 525 | c_str = g_string_free(str, FALSE); |
b7e35bad MD |
526 | if (c_str[0] == '\0') |
527 | return 0; | |
31262354 | 528 | path = g_quark_from_string(c_str); |
98df1c9f | 529 | printf_debug("new definition path: %s\n", c_str); |
31262354 MD |
530 | g_free(c_str); |
531 | return path; | |
532 | } | |
533 | ||
9e29e16e MD |
534 | struct definition_scope * |
535 | new_definition_scope(struct definition_scope *parent_scope, | |
98df1c9f | 536 | GQuark field_name, const char *root_name) |
9e29e16e MD |
537 | { |
538 | struct definition_scope *scope; | |
9e29e16e | 539 | |
98df1c9f MD |
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); | |
9e29e16e | 547 | scope_path_len += parent_scope->scope_path->len; |
98df1c9f MD |
548 | scope = _new_definition_scope(parent_scope, scope_path_len); |
549 | memcpy(scope->scope_path->data, parent_scope->scope_path->data, | |
05c749e5 | 550 | sizeof(GQuark) * (scope_path_len - 1)); |
98df1c9f MD |
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 | } | |
c054553d MD |
563 | return scope; |
564 | } | |
565 | ||
d00d17d1 | 566 | /* |
d60cb676 | 567 | * in: path (dot separated), out: q (GArray of GQuark) |
d00d17d1 | 568 | */ |
d00d17d1 MD |
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); | |
427c09b7 | 591 | ptrend++; /* skip current dot */ |
d00d17d1 MD |
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 | ||
e1151715 | 600 | void free_definition_scope(struct definition_scope *scope) |
c054553d | 601 | { |
05c749e5 | 602 | g_array_free(scope->scope_path, TRUE); |
e1151715 | 603 | g_hash_table_destroy(scope->definitions); |
c054553d | 604 | g_free(scope); |
d1708134 | 605 | } |
a35173fe | 606 | |
04ae3991 | 607 | struct definition *lookup_definition(const struct definition *definition, |
a35173fe MD |
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 | ||
04ae3991 | 619 | struct definition_integer *lookup_integer(const struct definition *definition, |
a35173fe MD |
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 | ||
04ae3991 | 637 | struct definition_enum *lookup_enum(const struct definition *definition, |
a35173fe MD |
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 | ||
04ae3991 | 655 | struct definition *lookup_variant(const struct definition *definition, |
a35173fe MD |
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 | } |