From 7de8808cf86ee8922f261d4cd6ee91aa0fa103b1 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 21 Feb 2011 01:15:07 -0500 Subject: [PATCH] Add XML dump visitor Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/Makefile.am | 4 +- formats/ctf/metadata/ctf-ast.h | 10 +- formats/ctf/metadata/ctf-parser-test.c | 9 +- formats/ctf/metadata/ctf-visitor-xml.c | 596 +++++++++++++++++++++++++ 4 files changed, 613 insertions(+), 6 deletions(-) create mode 100644 formats/ctf/metadata/ctf-visitor-xml.c diff --git a/formats/ctf/metadata/Makefile.am b/formats/ctf/metadata/Makefile.am index 48df5ac2..a75e10c6 100644 --- a/formats/ctf/metadata/Makefile.am +++ b/formats/ctf/metadata/Makefile.am @@ -7,4 +7,6 @@ noinst_LIBRARIES = libctf-parser.a libctf_parser_a_SOURCES = ctf-lexer.l ctf-parser.y bin_PROGRAMS = ctf-parser-test -ctf_parser_test_SOURCES = ctf-parser-test.c ctf-lexer.l ctf-parser.y +ctf_parser_test_SOURCES = \ + ctf-parser-test.c ctf-visitor-xml.c \ + ctf-lexer.l ctf-parser.y diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 7dcf9f96..692cc7b5 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -107,8 +107,8 @@ struct ctf_node { * string literals and character constants. */ char *string; - uint64_t unsigned_constant; int64_t signed_constant; + uint64_t unsigned_constant; struct ctf_node *sbrac_exp; } u; enum { @@ -204,15 +204,15 @@ struct ctf_node { struct cds_list_head type_declarators; } struct_or_variant_declaration; struct { - /* list of typedef, typealias and declarations */ - struct cds_list_head declaration_list; char *name; char *choice; + /* list of typedef, typealias and declarations */ + struct cds_list_head declaration_list; } variant; struct { + char *name; /* list of typedef, typealias and declarations */ struct cds_list_head declaration_list; - char *name; } _struct; } u; }; @@ -222,4 +222,6 @@ struct ctf_ast { struct cds_list_head allocated_nodes; }; +int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node); + #endif /* _CTF_PARSER_H */ diff --git a/formats/ctf/metadata/ctf-parser-test.c b/formats/ctf/metadata/ctf-parser-test.c index 33fda7d1..cfd847d0 100644 --- a/formats/ctf/metadata/ctf-parser-test.c +++ b/formats/ctf/metadata/ctf-parser-test.c @@ -28,6 +28,7 @@ extern int yydebug; int main(int argc, char **argv) { struct ctf_scanner *scanner; + int ret = 0; yydebug = 1; scanner = ctf_scanner_alloc(stdin); @@ -36,8 +37,14 @@ int main(int argc, char **argv) return -1; } ctf_scanner_append_ast(scanner); + + if (ctf_visitor_print_xml(stdout, 0, &scanner->ast->root)) { + fprintf(stderr, "error visiting AST for XML output\n"); + ret = -1; + } ctf_scanner_free(scanner); - return 0; + + return ret; } diff --git a/formats/ctf/metadata/ctf-visitor-xml.c b/formats/ctf/metadata/ctf-visitor-xml.c new file mode 100644 index 00000000..60ad8c9c --- /dev/null +++ b/formats/ctf/metadata/ctf-visitor-xml.c @@ -0,0 +1,596 @@ +/* + * ctf-visitor-xml.c + * + * Common Trace Format Metadata Visitor (XML dump). + * + * Copyright 2010 - Mathieu Desnoyers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ctf-scanner.h" +#include "ctf-parser.h" +#include "ctf-ast.h" + +#define printf_dbg(fmt, args...) fprintf(stderr, "%s: " fmt, __func__, ## args) + +static void print_tabs(FILE *fd, int depth) +{ + int i; + + for (i = 0; i < depth; i++) + fprintf(fd, "\t"); +} + +int ctf_visitor_print_unary_expression(FILE *fd, int depth, struct ctf_node *node) +{ + int ret = 0; + + switch (node->u.unary_expression.type) { + case UNARY_STRING: + print_tabs(fd, depth); + fprintf(fd, "u.unary_expression.u.string); + fprintf(fd, "/>\n"); + break; + case UNARY_SIGNED_CONSTANT: + print_tabs(fd, depth); + fprintf(fd, "u.unary_expression.u.signed_constant); + fprintf(fd, "/>\n"); + break; + case UNARY_UNSIGNED_CONSTANT: + print_tabs(fd, depth); + fprintf(fd, "u.unary_expression.u.signed_constant); + fprintf(fd, "/>\n"); + break; + case UNARY_SBRAC: + print_tabs(fd, depth); + fprintf(fd, ""); + ret = ctf_visitor_print_unary_expression(fd, depth + 1, + node->u.unary_expression.u.sbrac_exp); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, ""); + break; + + case UNARY_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown expression type %d\n", __func__, + (int) node->u.unary_expression.type); + return -EINVAL; + } + switch (node->u.unary_expression.link) { + case UNARY_LINK_UNKNOWN: + break; + case UNARY_DOTLINK: + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case UNARY_ARROWLINK: + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + default: + fprintf(stderr, "[error] %s: unknown expression link type %d\n", __func__, + (int) node->u.unary_expression.link); + return -EINVAL; + } + return 0; +} + +int ctf_visitor_print_type_specifier(FILE *fd, int depth, struct ctf_node *node) +{ + print_tabs(fd, depth); + fprintf(fd, "u.type_specifier.type) { + case TYPESPEC_VOID: + fprintf(fd, "void"); + break; + case TYPESPEC_CHAR: + fprintf(fd, "char"); + break; + case TYPESPEC_SHORT: + fprintf(fd, "short"); + break; + case TYPESPEC_INT: + fprintf(fd, "int"); + break; + case TYPESPEC_LONG: + fprintf(fd, "long"); + break; + case TYPESPEC_FLOAT: + fprintf(fd, "float"); + break; + case TYPESPEC_DOUBLE: + fprintf(fd, "double"); + break; + case TYPESPEC_SIGNED: + fprintf(fd, "signed"); + break; + case TYPESPEC_UNSIGNED: + fprintf(fd, "unsigned"); + break; + case TYPESPEC_BOOL: + fprintf(fd, "bool"); + break; + case TYPESPEC_COMPLEX: + fprintf(fd, "complex"); + break; + case TYPESPEC_CONST: + fprintf(fd, "const"); + break; + case TYPESPEC_ID_TYPE: + fprintf(fd, "%s", node->u.type_specifier.id_type); + break; + + case TYPESPEC_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown type specifier %d\n", __func__, + (int) node->u.type_specifier.type); + return -EINVAL; + } + fprintf(fd, "\"/>\n"); + return 0; +} + +int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node) +{ + int ret = 0; + struct ctf_node *iter; + + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + switch (node->u.type_declarator.type) { + case TYPEDEC_ID: + print_tabs(fd, depth); + fprintf(fd, "u.type_declarator.u.id); + fprintf(fd, "<\" />\n"); + break; + case TYPEDEC_NESTED: + if (node->u.type_declarator.u.nested.type_declarator) { + print_tabs(fd, depth); + fprintf(fd, "\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, "\n"); + } + if (node->u.type_declarator.u.nested.length) { + print_tabs(fd, depth); + fprintf(fd, "\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, "\n"); + } + if (node->u.type_declarator.u.nested.abstract_array) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + if (node->u.type_declarator.bitfield_len) { + print_tabs(fd, depth); + fprintf(fd, "\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, "\n"); + } + break; + case TYPEDEC_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown type declarator %d\n", __func__, + (int) node->u.type_declarator.type); + return -EINVAL; + } + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + return 0; +} + +int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node) +{ + int ret = 0; + struct ctf_node *iter; + + switch (node->type) { + case NODE_ROOT: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.root._typedef, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.typealias, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.trace, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.event, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + + case NODE_EVENT: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STREAM: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_TRACE: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + + case NODE_CTF_EXPRESSION: + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, node->u.ctf_expression.left); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, node->u.ctf_expression.right); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_UNARY_EXPRESSION: + return ctf_visitor_print_unary_expression(fd, depth, node); + + case NODE_TYPEDEF: + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._typedef.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._typedef.type_declarators, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_TYPEALIAS_TARGET: + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.typealias_target.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_TYPEALIAS_ALIAS: + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.typealias_alias.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_TYPEALIAS: + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.target); + if (ret) + return ret; + ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.alias); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + + case NODE_TYPE_SPECIFIER: + ret = ctf_visitor_print_type_specifier(fd, depth, node); + if (ret) + return ret; + break; + case NODE_POINTER: + print_tabs(fd, depth); + if (node->u.pointer.const_qualifier) + fprintf(fd, "\n"); + else + fprintf(fd, "\n"); + break; + case NODE_TYPE_DECLARATOR: + ret = ctf_visitor_print_type_declarator(fd, depth, node); + if (ret) + return ret; + break; + + case NODE_FLOATING_POINT: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_INTEGER: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRING: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_ENUMERATOR: + print_tabs(fd, depth); + fprintf(fd, "u.enumerator.id) + fprintf(fd, " id=\"%s\"", node->u.enumerator.id); + fprintf(fd, ">\n"); + if (node->u.enumerator.values) { + ret = ctf_visitor_print_xml(fd, depth + 1, + node->u.enumerator.values); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, ""); + break; + case NODE_ENUM: + print_tabs(fd, depth); + if (node->u._struct.name) + fprintf(fd, "\n", + node->u._enum.enum_id); + else + fprintf(fd, "\n"); + depth++; + + if (node->u._enum.container_type) { + print_tabs(fd, depth); + fprintf(fd, ""); + ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, ""); + } + + print_tabs(fd, depth); + fprintf(fd, ""); + cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, ""); + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_VARIANT: + print_tabs(fd, depth); + fprintf(fd, "u.variant.name) + fprintf(fd, " name=\"%s\"", node->u.variant.name); + if (node->u.variant.choice) + fprintf(fd, " choice=\"%s\"", node->u.variant.choice); + fprintf(fd, ">\n"); + cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRUCT: + print_tabs(fd, depth); + if (node->u._struct.name) + fprintf(fd, "\n", + node->u._struct.name); + else + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + + case NODE_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown node type %d\n", __func__, + (int) node->type); + return -EINVAL; + } + return ret; +} -- 2.34.1