Version 1.0.0-rc6
[babeltrace.git] / types / types.c
CommitLineData
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 30static
78af2bcd
MD
31GQuark 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
45static
46struct 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 54struct 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 69int 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
86static
e1151715 87struct 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 */
100static 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
118static int is_path_child_of(GArray *path, GArray *maybe_parent)
119{
98df1c9f
MD
120 int i, ret;
121
122 if (babeltrace_debug) {
123 int 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 }
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;
146end:
147 if (babeltrace_debug)
148 printf("%s\n", ret ? "Yes" : "No");
149 return ret;
05c749e5
MD
150}
151
152static 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 178struct 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
222lookup:
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 257int 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 274void declaration_ref(struct declaration *declaration)
4c8bfb7e 275{
f6625916 276 declaration->ref++;
4c8bfb7e
MD
277}
278
f6625916 279void 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 287void definition_ref(struct definition *definition)
d1708134 288{
e1151715 289 definition->ref++;
d1708134
MD
290}
291
e1151715 292void 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
300struct 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 321void 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 330static
f6625916
MD
331struct 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
338struct 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
352int 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
378static
a0720417 379struct 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 387struct 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 402int 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
429static
f6625916
MD
430struct 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
438struct 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
453int 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
479static 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
494GQuark 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;
500 int i;
98df1c9f 501 int need_dot = 0;
31262354
MD
502
503 str = g_string_new("");
98df1c9f
MD
504 if (root_name) {
505 g_string_append(str, root_name);
506 need_dot = 1;
507 } else if (parent_scope) {
31262354
MD
508 for (i = 0; i < parent_scope->scope_path->len; i++) {
509 GQuark q = g_array_index(parent_scope->scope_path,
510 GQuark, i);
b7e35bad
MD
511 if (!q)
512 continue;
98df1c9f
MD
513 if (need_dot)
514 g_string_append(str, ".");
31262354 515 g_string_append(str, g_quark_to_string(q));
98df1c9f 516 need_dot = 1;
31262354
MD
517 }
518 }
98df1c9f
MD
519 if (field_name) {
520 if (need_dot)
521 g_string_append(str, ".");
b7e35bad 522 g_string_append(str, g_quark_to_string(field_name));
98df1c9f 523 }
31262354 524 c_str = g_string_free(str, FALSE);
b7e35bad
MD
525 if (c_str[0] == '\0')
526 return 0;
31262354 527 path = g_quark_from_string(c_str);
98df1c9f 528 printf_debug("new definition path: %s\n", c_str);
31262354
MD
529 g_free(c_str);
530 return path;
531}
532
9e29e16e
MD
533struct definition_scope *
534 new_definition_scope(struct definition_scope *parent_scope,
98df1c9f 535 GQuark field_name, const char *root_name)
9e29e16e
MD
536{
537 struct definition_scope *scope;
9e29e16e 538
98df1c9f
MD
539 if (root_name) {
540 scope = _new_definition_scope(parent_scope, 0);
541 append_scope_path(root_name, scope->scope_path);
542 } else {
543 int scope_path_len = 1;
544
545 assert(parent_scope);
9e29e16e 546 scope_path_len += parent_scope->scope_path->len;
98df1c9f
MD
547 scope = _new_definition_scope(parent_scope, scope_path_len);
548 memcpy(scope->scope_path->data, parent_scope->scope_path->data,
05c749e5 549 sizeof(GQuark) * (scope_path_len - 1));
98df1c9f
MD
550 g_array_index(scope->scope_path, GQuark, scope_path_len - 1) =
551 field_name;
552 }
553 if (babeltrace_debug) {
554 int i, need_dot = 0;
555
556 printf_debug("new definition scope: ");
557 for (i = 0; i < scope->scope_path->len; need_dot = 1, i++)
558 printf("%s%s", need_dot ? "." : "",
559 g_quark_to_string(g_array_index(scope->scope_path, GQuark, i)));
560 printf("\n");
561 }
c054553d
MD
562 return scope;
563}
564
d00d17d1 565/*
d60cb676 566 * in: path (dot separated), out: q (GArray of GQuark)
d00d17d1 567 */
d00d17d1
MD
568void append_scope_path(const char *path, GArray *q)
569{
570 const char *ptrbegin, *ptrend = path;
571 GQuark quark;
572
573 for (;;) {
574 char *str;
575 size_t len;
576
577 ptrbegin = ptrend;
578 ptrend = strchr(ptrbegin, '.');
579 if (!ptrend)
580 break;
581 len = ptrend - ptrbegin;
582 /* Don't accept two consecutive dots */
583 assert(len != 0);
584 str = g_new(char, len + 1); /* include \0 */
585 memcpy(str, ptrbegin, len);
586 str[len] = '\0';
587 quark = g_quark_from_string(str);
588 g_array_append_val(q, quark);
589 g_free(str);
427c09b7 590 ptrend++; /* skip current dot */
d00d17d1
MD
591 }
592 /* last. Check for trailing dot (and discard). */
593 if (ptrbegin[0] != '\0') {
594 quark = g_quark_from_string(ptrbegin);
595 g_array_append_val(q, quark);
596 }
597}
598
e1151715 599void free_definition_scope(struct definition_scope *scope)
c054553d 600{
05c749e5 601 g_array_free(scope->scope_path, TRUE);
e1151715 602 g_hash_table_destroy(scope->definitions);
c054553d 603 g_free(scope);
d1708134 604}
a35173fe 605
04ae3991 606struct definition *lookup_definition(const struct definition *definition,
a35173fe
MD
607 const char *field_name)
608{
609 struct definition_scope *scope = get_definition_scope(definition);
610
611 if (!scope)
612 return NULL;
613
614 return lookup_field_definition_scope(g_quark_from_string(field_name),
615 scope);
616}
617
04ae3991 618struct definition_integer *lookup_integer(const struct definition *definition,
a35173fe
MD
619 const char *field_name,
620 int signedness)
621{
622 struct definition *lookup;
623 struct definition_integer *lookup_integer;
624
625 lookup = lookup_definition(definition, field_name);
626 if (!lookup)
627 return NULL;
628 if (lookup->declaration->id != CTF_TYPE_INTEGER)
629 return NULL;
630 lookup_integer = container_of(lookup, struct definition_integer, p);
631 if (lookup_integer->declaration->signedness != signedness)
632 return NULL;
633 return lookup_integer;
634}
635
04ae3991 636struct definition_enum *lookup_enum(const struct definition *definition,
a35173fe
MD
637 const char *field_name,
638 int signedness)
639{
640 struct definition *lookup;
641 struct definition_enum *lookup_enum;
642
643 lookup = lookup_definition(definition, field_name);
644 if (!lookup)
645 return NULL;
646 if (lookup->declaration->id != CTF_TYPE_ENUM)
647 return NULL;
648 lookup_enum = container_of(lookup, struct definition_enum, p);
649 if (lookup_enum->integer->declaration->signedness != signedness)
650 return NULL;
651 return lookup_enum;
652}
653
04ae3991 654struct definition *lookup_variant(const struct definition *definition,
a35173fe
MD
655 const char *field_name)
656{
657 struct definition *lookup;
658 struct definition_variant *lookup_variant;
659
660 lookup = lookup_definition(definition, field_name);
661 if (!lookup)
662 return NULL;
663 if (lookup->declaration->id != CTF_TYPE_VARIANT)
664 return NULL;
665 lookup_variant = container_of(lookup, struct definition_variant, p);
666 lookup = variant_get_current_field(lookup_variant);
667 assert(lookup);
668 return lookup;
669}
This page took 0.057291 seconds and 4 git commands to generate.