+ g_hash_table_insert(scanner->cs->types, id, id);
+}
+
+static struct ctf_node *make_node(struct ctf_scanner *scanner,
+ enum node_type type)
+{
+ struct ctf_node *node;
+
+ node = objstack_alloc(scanner->objstack, sizeof(*node));
+ if (!node) {
+ printfl_fatal(yyget_lineno(scanner->scanner), "out of memory");
+ return &error_node;
+ }
+ node->type = type;
+ node->lineno = yyget_lineno(scanner->scanner);
+ BT_INIT_LIST_HEAD(&node->tmp_head);
+ bt_list_add(&node->siblings, &node->tmp_head);
+
+ switch (type) {
+ case NODE_ROOT:
+ node->type = NODE_ERROR;
+ printfn_fatal(node, "trying to create root node");
+ break;
+
+ case NODE_EVENT:
+ BT_INIT_LIST_HEAD(&node->u.event.declaration_list);
+ break;
+ case NODE_STREAM:
+ BT_INIT_LIST_HEAD(&node->u.stream.declaration_list);
+ break;
+ case NODE_ENV:
+ BT_INIT_LIST_HEAD(&node->u.env.declaration_list);
+ break;
+ case NODE_TRACE:
+ BT_INIT_LIST_HEAD(&node->u.trace.declaration_list);
+ break;
+ case NODE_CLOCK:
+ BT_INIT_LIST_HEAD(&node->u.clock.declaration_list);
+ break;
+ case NODE_CALLSITE:
+ BT_INIT_LIST_HEAD(&node->u.callsite.declaration_list);
+ break;
+
+ case NODE_CTF_EXPRESSION:
+ BT_INIT_LIST_HEAD(&node->u.ctf_expression.left);
+ BT_INIT_LIST_HEAD(&node->u.ctf_expression.right);
+ break;
+ case NODE_UNARY_EXPRESSION:
+ break;
+
+ case NODE_TYPEDEF:
+ BT_INIT_LIST_HEAD(&node->u._typedef.type_declarators);
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ BT_INIT_LIST_HEAD(&node->u.typealias_target.type_declarators);
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ BT_INIT_LIST_HEAD(&node->u.typealias_alias.type_declarators);
+ break;
+ case NODE_TYPEALIAS:
+ break;
+
+ case NODE_TYPE_SPECIFIER:
+ break;
+ case NODE_TYPE_SPECIFIER_LIST:
+ BT_INIT_LIST_HEAD(&node->u.type_specifier_list.head);
+ break;
+ case NODE_POINTER:
+ break;
+ case NODE_TYPE_DECLARATOR:
+ BT_INIT_LIST_HEAD(&node->u.type_declarator.pointers);
+ break;
+
+ case NODE_FLOATING_POINT:
+ BT_INIT_LIST_HEAD(&node->u.floating_point.expressions);
+ break;
+ case NODE_INTEGER:
+ BT_INIT_LIST_HEAD(&node->u.integer.expressions);
+ break;
+ case NODE_STRING:
+ BT_INIT_LIST_HEAD(&node->u.string.expressions);
+ break;
+ case NODE_ENUMERATOR:
+ BT_INIT_LIST_HEAD(&node->u.enumerator.values);
+ break;
+ case NODE_ENUM:
+ BT_INIT_LIST_HEAD(&node->u._enum.enumerator_list);
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ BT_INIT_LIST_HEAD(&node->u.struct_or_variant_declaration.type_declarators);
+ break;
+ case NODE_VARIANT:
+ BT_INIT_LIST_HEAD(&node->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ BT_INIT_LIST_HEAD(&node->u._struct.declaration_list);
+ BT_INIT_LIST_HEAD(&node->u._struct.min_align);
+ break;
+
+ case NODE_UNKNOWN:
+ default:
+ node->type = NODE_ERROR;
+ printfn_fatal(node, "unknown node type '%d'", (int) type);
+ break;
+ }
+
+ return node;
+}
+
+static int reparent_ctf_expression(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_EVENT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.event.declaration_list);
+ break;
+ case NODE_STREAM:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.stream.declaration_list);
+ break;
+ case NODE_ENV:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.env.declaration_list);
+ break;
+ case NODE_TRACE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.trace.declaration_list);
+ break;
+ case NODE_CLOCK:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
+ break;
+ case NODE_CALLSITE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+ break;
+ case NODE_FLOATING_POINT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.floating_point.expressions);
+ break;
+ case NODE_INTEGER:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.integer.expressions);
+ break;
+ case NODE_STRING:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.string.expressions);
+ break;
+
+ case NODE_ROOT:
+ case NODE_CTF_EXPRESSION:
+ case NODE_TYPEDEF:
+ case NODE_TYPEALIAS_TARGET:
+ case NODE_TYPEALIAS_ALIAS:
+ case NODE_TYPEALIAS:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_TYPE_SPECIFIER_LIST:
+ case NODE_POINTER:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUMERATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ case NODE_VARIANT:
+ case NODE_STRUCT:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int reparent_typedef(struct ctf_node *node, struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.declaration_list);
+ break;
+ case NODE_EVENT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.event.declaration_list);
+ break;
+ case NODE_STREAM:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.stream.declaration_list);
+ break;
+ case NODE_ENV:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.env.declaration_list);
+ break;
+ case NODE_TRACE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.trace.declaration_list);
+ break;
+ case NODE_CLOCK:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
+ break;
+ case NODE_CALLSITE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+ break;
+ case NODE_VARIANT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u._struct.declaration_list);
+ break;
+
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_TYPEDEF:
+ case NODE_TYPEALIAS_TARGET:
+ case NODE_TYPEALIAS_ALIAS:
+ case NODE_TYPEALIAS:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_TYPE_SPECIFIER_LIST:
+ case NODE_POINTER:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUMERATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type %d", parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int reparent_typealias(struct ctf_node *node, struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.declaration_list);
+ break;
+ case NODE_EVENT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.event.declaration_list);
+ break;
+ case NODE_STREAM:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.stream.declaration_list);
+ break;
+ case NODE_ENV:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.env.declaration_list);
+ break;
+ case NODE_TRACE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.trace.declaration_list);
+ break;
+ case NODE_CLOCK:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
+ break;
+ case NODE_CALLSITE:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+ break;
+ case NODE_VARIANT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u._struct.declaration_list);
+ break;
+
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_TYPEDEF:
+ case NODE_TYPEALIAS_TARGET:
+ case NODE_TYPEALIAS_ALIAS:
+ case NODE_TYPEALIAS:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_TYPE_SPECIFIER_LIST:
+ case NODE_POINTER:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUMERATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int reparent_type_specifier(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_TYPE_SPECIFIER_LIST:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.type_specifier_list.head);
+ break;
+
+ case NODE_TYPE_SPECIFIER:
+ case NODE_EVENT:
+ case NODE_STREAM:
+ case NODE_ENV:
+ case NODE_TRACE:
+ case NODE_CLOCK:
+ case NODE_CALLSITE:
+ case NODE_VARIANT:
+ case NODE_STRUCT:
+ case NODE_TYPEDEF:
+ case NODE_TYPEALIAS_TARGET:
+ case NODE_TYPEALIAS_ALIAS:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ case NODE_TYPEALIAS:
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_POINTER:
+ case NODE_ENUMERATOR:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int reparent_type_specifier_list(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ bt_list_add_tail(&node->siblings, &parent->u.root.declaration_list);
+ break;
+ case NODE_EVENT:
+ bt_list_add_tail(&node->siblings, &parent->u.event.declaration_list);
+ break;
+ case NODE_STREAM:
+ bt_list_add_tail(&node->siblings, &parent->u.stream.declaration_list);
+ break;
+ case NODE_ENV:
+ bt_list_add_tail(&node->siblings, &parent->u.env.declaration_list);
+ break;
+ case NODE_TRACE:
+ bt_list_add_tail(&node->siblings, &parent->u.trace.declaration_list);
+ break;
+ case NODE_CLOCK:
+ bt_list_add_tail(&node->siblings, &parent->u.clock.declaration_list);
+ break;
+ case NODE_CALLSITE:
+ bt_list_add_tail(&node->siblings, &parent->u.callsite.declaration_list);
+ break;
+ case NODE_VARIANT:
+ bt_list_add_tail(&node->siblings, &parent->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ bt_list_add_tail(&node->siblings, &parent->u._struct.declaration_list);
+ break;
+ case NODE_TYPEDEF:
+ parent->u._typedef.type_specifier_list = node;
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ parent->u.typealias_target.type_specifier_list = node;
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ parent->u.typealias_alias.type_specifier_list = node;
+ break;
+ case NODE_ENUM:
+ parent->u._enum.container_type = node;
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ parent->u.struct_or_variant_declaration.type_specifier_list = node;
+ break;
+ case NODE_TYPE_DECLARATOR:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_TYPEALIAS:
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_POINTER:
+ case NODE_ENUMERATOR:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int reparent_type_declarator(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_TYPE_DECLARATOR:
+ parent->u.type_declarator.type = TYPEDEC_NESTED;
+ parent->u.type_declarator.u.nested.type_declarator = node;
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.struct_or_variant_declaration.type_declarators);
+ break;
+ case NODE_TYPEDEF:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u._typedef.type_declarators);
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.typealias_target.type_declarators);
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.typealias_alias.type_declarators);
+ break;
+
+ case NODE_ROOT:
+ case NODE_EVENT:
+ case NODE_STREAM:
+ case NODE_ENV:
+ case NODE_TRACE:
+ case NODE_CLOCK:
+ case NODE_CALLSITE:
+ case NODE_VARIANT:
+ case NODE_STRUCT:
+ case NODE_TYPEALIAS:
+ case NODE_ENUM:
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_TYPE_SPECIFIER_LIST:
+ case NODE_POINTER:
+ case NODE_ENUMERATOR:
+ case NODE_UNARY_EXPRESSION:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * set_parent_node
+ *
+ * Link node to parent. Returns 0 on success, -EPERM if it is not permitted to
+ * create the link declared by the input, -ENOENT if node or parent is NULL,
+ * -EINVAL if there is an internal structure problem.
+ */
+static int set_parent_node(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ if (!node || !parent)
+ return -ENOENT;
+
+ /* Note: Linking to parent will be done only by an external visitor */
+
+ switch (node->type) {
+ case NODE_ROOT:
+ printfn_fatal(node, "trying to reparent root node");
+ return -EINVAL;
+
+ case NODE_EVENT:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.event);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_STREAM:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.stream);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_ENV:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.env);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_TRACE:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.trace);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_CLOCK:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.clock);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_CALLSITE:
+ if (parent->type == NODE_ROOT) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.root.callsite);
+ } else {
+ return -EPERM;
+ }
+ break;
+
+ case NODE_CTF_EXPRESSION:
+ return reparent_ctf_expression(node, parent);
+ case NODE_UNARY_EXPRESSION:
+ if (parent->type == NODE_TYPE_DECLARATOR)
+ parent->u.type_declarator.bitfield_len = node;
+ else
+ return -EPERM;
+ break;
+
+ case NODE_TYPEDEF:
+ return reparent_typedef(node, parent);
+ case NODE_TYPEALIAS_TARGET:
+ if (parent->type == NODE_TYPEALIAS)
+ parent->u.typealias.target = node;
+ else
+ return -EINVAL;
+ case NODE_TYPEALIAS_ALIAS:
+ if (parent->type == NODE_TYPEALIAS)
+ parent->u.typealias.alias = node;
+ else
+ return -EINVAL;
+ case NODE_TYPEALIAS:
+ return reparent_typealias(node, parent);
+
+ case NODE_POINTER:
+ if (parent->type == NODE_TYPE_DECLARATOR) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.type_declarator.pointers);
+ } else
+ return -EPERM;
+ break;
+ case NODE_TYPE_DECLARATOR:
+ return reparent_type_declarator(node, parent);
+
+ case NODE_TYPE_SPECIFIER_LIST:
+ return reparent_type_specifier_list(node, parent);
+
+ case NODE_TYPE_SPECIFIER:
+ return reparent_type_specifier(node, parent);
+
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_ENUM:
+ case NODE_VARIANT:
+ case NODE_STRUCT:
+ return -EINVAL; /* Dealt with internally within grammar */
+
+ case NODE_ENUMERATOR:
+ if (parent->type == NODE_ENUM) {
+ _bt_list_splice_tail(&node->tmp_head, &parent->u._enum.enumerator_list);
+ } else {
+ return -EPERM;
+ }
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ switch (parent->type) {
+ case NODE_STRUCT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u._struct.declaration_list);
+ break;
+ case NODE_VARIANT:
+ _bt_list_splice_tail(&node->tmp_head, &parent->u.variant.declaration_list);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case NODE_UNKNOWN:
+ default:
+ printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;