- break;
- case TYPEDEC_NESTED:
- if (node->u.type_declarator.u.nested.type_declarator) {
- print_tabs(fd, depth);
- fprintf(fd, "<type_declarator>\n");
- ret = ctf_visitor_print_xml(fd, depth + 1,
- node->u.type_declarator.u.nested.type_declarator);
- if (ret)
- return ret;
- print_tabs(fd, depth);
- fprintf(fd, "</type_declarator>\n");
- }
- if (node->u.type_declarator.u.nested.length) {
- print_tabs(fd, depth);
- fprintf(fd, "<length>\n");
- ret = ctf_visitor_print_xml(fd, depth + 1,
- node->u.type_declarator.u.nested.length);
- if (ret)
- return ret;
- print_tabs(fd, depth);
- fprintf(fd, "</length>\n");
- }
- if (node->u.type_declarator.u.nested.abstract_array) {
- print_tabs(fd, depth);
- fprintf(fd, "<length>\n");
- print_tabs(fd, depth);
- fprintf(fd, "</length>\n");
- }
- if (node->u.type_declarator.bitfield_len) {
- print_tabs(fd, depth);
- fprintf(fd, "<bitfield_len>\n");
- ret = ctf_visitor_print_xml(fd, depth + 1,
- node->u.type_declarator.bitfield_len);
- if (ret)
- return ret;
- print_tabs(fd, depth);
- fprintf(fd, "</bitfield_len>\n");
+ }
+
+ if (!node_type_declarator)
+ return nested_declaration;
+
+ if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) {
+ if (node_type_declarator->u.type_declarator.u.id)
+ *field_name = g_quark_from_string(node_type_declarator->u.type_declarator.u.id);
+ else
+ *field_name = 0;
+ return nested_declaration;
+ } else {
+ struct declaration *declaration;
+ struct ctf_node *first;
+
+ /* TYPEDEC_NESTED */
+
+ if (!nested_declaration) {
+ fprintf(fd, "[error] %s: nested type is unknown.\n", __func__);
+ return NULL;
+ }
+
+ /* create array/sequence, pass nested_declaration as child. */
+ if (cds_list_empty(&node_type_declarator->u.type_declarator.u.nested.length)) {
+ fprintf(fd, "[error] %s: expecting length field reference or value.\n", __func__);
+ return NULL;
+ }
+ first = _cds_list_first_entry(&node_type_declarator->u.type_declarator.u.nested.length,
+ struct ctf_node, siblings);
+ assert(first->type == NODE_UNARY_EXPRESSION);
+
+ switch (first->u.unary_expression.type) {
+ case UNARY_UNSIGNED_CONSTANT:
+ {
+ struct declaration_array *array_declaration;
+ size_t len;
+
+ len = first->u.unary_expression.u.unsigned_constant;
+ array_declaration = array_declaration_new(len, nested_declaration,
+ declaration_scope);
+
+ if (!array_declaration) {
+ fprintf(fd, "[error] %s: cannot create array declaration.\n", __func__);
+ return NULL;
+ }
+ declaration = &array_declaration->p;
+ break;
+ }
+ case UNARY_STRING:
+ {
+ /* Lookup unsigned integer definition, create sequence */
+ char *length_name = concatenate_unary_strings(&node_type_declarator->u.type_declarator.u.nested.length);
+ struct declaration_sequence *sequence_declaration;
+
+ sequence_declaration = sequence_declaration_new(length_name, nested_declaration, declaration_scope);
+ if (!sequence_declaration) {
+ fprintf(fd, "[error] %s: cannot create sequence declaration.\n", __func__);
+ return NULL;
+ }
+ declaration = &sequence_declaration->p;
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ /* Pass it as content of outer container */
+ declaration = ctf_type_declarator_visit(fd, depth,
+ type_specifier_list, field_name,
+ node_type_declarator->u.type_declarator.u.nested.type_declarator,
+ declaration_scope, declaration, trace);
+ return declaration;
+ }
+}
+
+static
+int ctf_struct_type_declarators_visit(FILE *fd, int depth,
+ struct declaration_struct *struct_declaration,
+ struct ctf_node *type_specifier_list,
+ struct cds_list_head *type_declarators,
+ struct declaration_scope *declaration_scope,
+ struct ctf_trace *trace)
+{
+ struct ctf_node *iter;
+ GQuark field_name;
+
+ cds_list_for_each_entry(iter, type_declarators, siblings) {
+ struct declaration *field_declaration;
+
+ field_declaration = ctf_type_declarator_visit(fd, depth,
+ type_specifier_list,
+ &field_name, iter,
+ struct_declaration->scope,
+ NULL, trace);
+ if (!field_declaration) {
+ fprintf(fd, "[error] %s: unable to find struct field declaration type\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Check if field with same name already exists */
+ if (struct_declaration_lookup_field_index(struct_declaration, field_name) >= 0) {
+ fprintf(fd, "[error] %s: duplicate field %s in struct\n", __func__, g_quark_to_string(field_name));
+ return -EINVAL;
+ }
+
+ struct_declaration_add_field(struct_declaration,
+ g_quark_to_string(field_name),
+ field_declaration);
+ }
+ return 0;
+}
+
+static
+int ctf_variant_type_declarators_visit(FILE *fd, int depth,
+ struct declaration_untagged_variant *untagged_variant_declaration,
+ struct ctf_node *type_specifier_list,
+ struct cds_list_head *type_declarators,
+ struct declaration_scope *declaration_scope,
+ struct ctf_trace *trace)
+{
+ struct ctf_node *iter;
+ GQuark field_name;
+
+ cds_list_for_each_entry(iter, type_declarators, siblings) {
+ struct declaration *field_declaration;
+
+ field_declaration = ctf_type_declarator_visit(fd, depth,
+ type_specifier_list,
+ &field_name, iter,
+ untagged_variant_declaration->scope,
+ NULL, trace);
+ if (!field_declaration) {
+ fprintf(fd, "[error] %s: unable to find variant field declaration type\n", __func__);
+ return -EINVAL;
+ }
+ untagged_variant_declaration_add_field(untagged_variant_declaration,
+ g_quark_to_string(field_name),
+ field_declaration);
+ }
+ return 0;
+}
+
+static
+int ctf_typedef_visit(FILE *fd, int depth, struct declaration_scope *scope,
+ struct ctf_node *type_specifier_list,
+ struct cds_list_head *type_declarators,
+ struct ctf_trace *trace)
+{
+ struct ctf_node *iter;
+ GQuark identifier;
+
+ cds_list_for_each_entry(iter, type_declarators, siblings) {
+ struct declaration *type_declaration;
+ int ret;
+
+ type_declaration = ctf_type_declarator_visit(fd, depth,
+ type_specifier_list,
+ &identifier, iter,
+ scope, NULL, trace);
+ if (!type_declaration) {
+ fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
+ return -EINVAL;
+ }
+ /*
+ * Don't allow typedef and typealias of untagged
+ * variants.
+ */
+ if (type_declaration->id == CTF_TYPE_UNTAGGED_VARIANT) {
+ fprintf(fd, "[error] %s: typedef of untagged variant is not permitted.\n", __func__);
+ declaration_unref(type_declaration);
+ return -EPERM;