+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:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (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:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (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:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (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:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (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:
+ fprintf(stderr, "[error] %s: trying to reparent root node\n", __func__);
+ 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:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+__attribute__((visibility("hidden")))