+/*
+ * Returns the index at which the paths differ.
+ * If the value returned equals len, it means the paths are identical
+ * from index 0 to len-1.
+ */
+static int compare_paths(GArray *a, GArray *b, int len)
+{
+ int i;
+
+ assert(len <= a->len);
+ assert(len <= b->len);
+
+ for (i = 0; i < len; i++) {
+ GQuark qa, qb;
+
+ qa = g_array_index(a, GQuark, i);
+ qb = g_array_index(b, GQuark, i);
+ if (qa != qb)
+ return i;
+ }
+ return i;
+}
+
+static int is_path_child_of(GArray *path, GArray *maybe_parent)
+{
+ if (path->len <= maybe_parent->len)
+ return 0;
+ if (compare_paths(path, maybe_parent, maybe_parent->len)
+ == maybe_parent->len)
+ return 1;
+ else
+ return 0;
+}
+
+static struct definition_scope *
+ get_definition_scope(struct definition *definition)
+{
+ switch (definition->declaration->id) {
+ case CTF_TYPE_STRUCT:
+ {
+ struct definition_struct *def =
+ container_of(definition, struct definition_struct, p);
+ return def->scope;
+ }
+ case CTF_TYPE_VARIANT:
+ {
+ struct definition_variant *def =
+ container_of(definition, struct definition_variant, p);
+ return def->scope;
+ }
+ case CTF_TYPE_ARRAY:
+ {
+ struct definition_array *def =
+ container_of(definition, struct definition_array, p);
+ return def->scope;
+ }
+ case CTF_TYPE_SEQUENCE:
+ {
+ struct definition_sequence *def =
+ container_of(definition, struct definition_sequence, p);
+ return def->scope;
+ }
+
+ case CTF_TYPE_INTEGER:
+ case CTF_TYPE_FLOAT:
+ case CTF_TYPE_ENUM:
+ case CTF_TYPE_STRING:
+ case CTF_TYPE_UNKNOWN:
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * OK, here is the fun. We want to lookup a field that is:
+ * - either in the same dynamic scope:
+ * - either in the current scope, but prior to the current field.
+ * - or in a parent scope (or parent of parent ...) still in a field
+ * prior to the current field position within the parents.
+ * - or in a different dynamic scope:
+ * - either in a upper dynamic scope (walk down a targeted scope from
+ * the dynamic scope root)
+ * - or in a lower dynamic scope (failure)
+ * The dynamic scope roots are linked together, so we can access the
+ * parent dynamic scope from the child dynamic scope by walking up to
+ * the parent.
+ * If we cannot find such a field that is prior to our current path, we
+ * return NULL.
+ *
+ * cur_path: the path leading to the variant definition.
+ * lookup_path: the path leading to the enum we want to look for.
+ * scope: the definition scope containing the variant definition.
+ */