%{
/*
- * ctf.y
+ * ctf-parser.y
*
* Common Trace Format Metadata Grammar.
+ *
+ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdio.h>
#include <assert.h>
#include <helpers/list.h>
#include <glib.h>
+#include <errno.h>
+#include "ctf-scanner.h"
#include "ctf-parser.h"
#include "ctf-ast.h"
-#define printf_dbg(fmt, args...) fprintf(stderr, "%s: " fmt, __func__, args)
-#define printf_dbg_noarg(fmt) fprintf(stderr, "%s: " fmt, __func__)
+#define printf_dbg(fmt, args...) fprintf(stderr, "%s: " fmt, __func__, ## args)
-int yyparse(void);
-int yylex(void);
+int yyparse(struct ctf_scanner *scanner);
+int yylex(union YYSTYPE *yyval, struct ctf_scanner *scanner);
+int yylex_init_extra(struct ctf_scanner *scanner, yyscan_t * ptr_yy_globals);
+int yylex_destroy(yyscan_t yyscanner) ;
+void yyset_in(FILE * in_str, yyscan_t scanner);
-static CDS_LIST_HEAD(allocated_strings);
int yydebug;
-struct scope;
-struct scope {
- struct scope *parent;
- GHashTable *types;
-};
-
struct gc_string {
struct cds_list_head gc;
char s[];
};
-struct scope root_scope;
-struct scope *cs = &root_scope; /* current scope */
-
char *strredup(char **dest, const char *src)
{
size_t len = strlen(src) + 1;
return *dest;
}
-static struct gc_string *gc_string_alloc(size_t len)
+static struct gc_string *gc_string_alloc(struct ctf_scanner *scanner, size_t len)
{
struct gc_string *gstr;
gstr = malloc(sizeof(*gstr) + len);
- cds_list_add(&gstr->gc, &allocated_strings);
+ cds_list_add(&gstr->gc, &scanner->allocated_strings);
return gstr;
}
-void setstring(const char *src)
+void setstring(struct ctf_scanner *scanner, YYSTYPE *lvalp, const char *src)
{
- yylval.gs = gc_string_alloc(strlen(src) + 1);
- strcpy(yylval.gs->s, src);
+ lvalp->gs = gc_string_alloc(scanner, strlen(src) + 1);
+ strcpy(lvalp->gs->s, src);
}
-static void init_scope(struct scope *scope, struct scope *parent)
+static void init_scope(struct ctf_scanner_scope *scope,
+ struct ctf_scanner_scope *parent)
{
scope->parent = parent;
scope->types = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify) free, NULL);
}
-static void finalize_scope(struct scope *scope)
+static void finalize_scope(struct ctf_scanner_scope *scope)
{
g_hash_table_destroy(scope->types);
}
-static void push_scope(void)
+static void push_scope(struct ctf_scanner *scanner)
{
- struct scope *ns;
+ struct ctf_scanner_scope *ns;
- printf_dbg_noarg("push scope\n");
- ns = malloc(sizeof(struct scope));
- init_scope(ns, cs);
- cs = ns;
+ printf_dbg("push scope\n");
+ ns = malloc(sizeof(struct ctf_scanner_scope));
+ init_scope(ns, scanner->cs);
+ scanner->cs = ns;
}
-static void pop_scope(void)
+static void pop_scope(struct ctf_scanner *scanner)
{
- struct scope *os;
+ struct ctf_scanner_scope *os;
- printf_dbg_noarg("pop scope\n");
- os = cs;
- cs = os->parent;
+ printf_dbg("pop scope\n");
+ os = scanner->cs;
+ scanner->cs = os->parent;
finalize_scope(os);
free(os);
}
-int lookup_type(struct scope *s, const char *id)
+static int lookup_type(struct ctf_scanner_scope *s, const char *id)
{
int ret;
return ret;
}
-int is_type(const char *id)
+int is_type(struct ctf_scanner *scanner, const char *id)
{
- struct scope *it;
+ struct ctf_scanner_scope *it;
int ret = 0;
- for (it = cs; it != NULL; it = it->parent) {
+ for (it = scanner->cs; it != NULL; it = it->parent) {
if (lookup_type(it, id)) {
ret = 1;
break;
return ret;
}
-static void add_type(const char *id)
+static void add_type(struct ctf_scanner *scanner, const char *id)
{
char *type_id = NULL;
printf_dbg("add type %s\n", id);
- if (lookup_type(cs, id))
+ if (lookup_type(scanner->cs, id))
return;
strredup(&type_id, id);
- g_hash_table_insert(cs->types, type_id, type_id);
+ g_hash_table_insert(scanner->cs->types, type_id, type_id);
+}
+
+static struct ctf_node *make_node(struct ctf_scanner *scanner,
+ enum node_type type)
+{
+ struct ctf_ast *ast = ctf_scanner_get_ast(scanner);
+ struct ctf_node *node;
+
+ node = malloc(sizeof(*node));
+ if (!node)
+ return NULL;
+ memset(node, 0, sizeof(*node));
+ node->type = type;
+ CDS_INIT_LIST_HEAD(&node->siblings);
+ cds_list_add(&node->gc, &ast->allocated_nodes);
+
+ switch (type) {
+ case NODE_ROOT:
+ fprintf(stderr, "[error] %s: trying to create root node\n", __func__);
+ break;
+
+ case NODE_EVENT:
+ CDS_INIT_LIST_HEAD(&node->u.event._typedef);
+ CDS_INIT_LIST_HEAD(&node->u.event.typealias);
+ CDS_INIT_LIST_HEAD(&node->u.event.ctf_expression);
+ CDS_INIT_LIST_HEAD(&node->u.event.declaration_specifier);
+ break;
+ case NODE_STREAM:
+ CDS_INIT_LIST_HEAD(&node->u.stream._typedef);
+ CDS_INIT_LIST_HEAD(&node->u.stream.typealias);
+ CDS_INIT_LIST_HEAD(&node->u.stream.ctf_expression);
+ CDS_INIT_LIST_HEAD(&node->u.stream.declaration_specifier);
+ break;
+ case NODE_TRACE:
+ CDS_INIT_LIST_HEAD(&node->u.trace._typedef);
+ CDS_INIT_LIST_HEAD(&node->u.trace.typealias);
+ CDS_INIT_LIST_HEAD(&node->u.trace.ctf_expression);
+ CDS_INIT_LIST_HEAD(&node->u.trace.declaration_specifier);
+ break;
+
+ case NODE_CTF_EXPRESSION:
+ break;
+
+ case NODE_TYPEDEF:
+ CDS_INIT_LIST_HEAD(&node->u._typedef.type_declarators);
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ CDS_INIT_LIST_HEAD(&node->u.typealias_target.type_declarators);
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ CDS_INIT_LIST_HEAD(&node->u.typealias_alias.type_declarators);
+ break;
+ case NODE_TYPEALIAS:
+ break;
+
+ case NODE_TYPE_SPECIFIER:
+ break;
+ case NODE_DECLARATION_SPECIFIER:
+ CDS_INIT_LIST_HEAD(&node->u.declaration_specifier.type_specifiers);
+ break;
+ case NODE_POINTER:
+ break;
+ case NODE_TYPE_DECLARATOR:
+ CDS_INIT_LIST_HEAD(&node->u.type_declarator.pointers);
+ break;
+
+ case NODE_FLOATING_POINT:
+ CDS_INIT_LIST_HEAD(&node->u.floating_point.expressions);
+ break;
+ case NODE_INTEGER:
+ CDS_INIT_LIST_HEAD(&node->u.integer.expressions);
+ break;
+ case NODE_STRING:
+ CDS_INIT_LIST_HEAD(&node->u.string.expressions);
+ break;
+ case NODE_ENUMERATOR:
+ break;
+ case NODE_ENUM:
+ CDS_INIT_LIST_HEAD(&node->u._enum.enumerator_list);
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ CDS_INIT_LIST_HEAD(&node->u.struct_or_variant_declaration.type_declarators);
+ break;
+ case NODE_VARIANT:
+ CDS_INIT_LIST_HEAD(&node->u.variant._typedef);
+ CDS_INIT_LIST_HEAD(&node->u.variant.typealias);
+ CDS_INIT_LIST_HEAD(&node->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ CDS_INIT_LIST_HEAD(&node->u._struct._typedef);
+ CDS_INIT_LIST_HEAD(&node->u._struct.typealias);
+ CDS_INIT_LIST_HEAD(&node->u._struct.declaration_list);
+ break;
+
+ case NODE_UNKNOWN:
+ default:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (int) type);
+ break;
+ }
+
+ return node;
+}
+
+static int reparent_ctf_expression(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_EVENT:
+ cds_list_add(&node->siblings, &parent->u.event.ctf_expression);
+ break;
+ case NODE_STREAM:
+ cds_list_add(&node->siblings, &parent->u.stream.ctf_expression);
+ break;
+ case NODE_TRACE:
+ cds_list_add(&node->siblings, &parent->u.trace.ctf_expression);
+ break;
+ case NODE_FLOATING_POINT:
+ cds_list_add(&node->siblings, &parent->u.floating_point.expressions);
+ break;
+ case NODE_INTEGER:
+ cds_list_add(&node->siblings, &parent->u.integer.expressions);
+ break;
+ case NODE_STRING:
+ cds_list_add(&node->siblings, &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_DECLARATION_SPECIFIER:
+ 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:
+ 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_typedef(struct ctf_node *node, struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ cds_list_add(&node->siblings, &parent->u.root._typedef);
+ break;
+ case NODE_EVENT:
+ cds_list_add(&node->siblings, &parent->u.event._typedef);
+ break;
+ case NODE_STREAM:
+ cds_list_add(&node->siblings, &parent->u.stream._typedef);
+ break;
+ case NODE_TRACE:
+ cds_list_add(&node->siblings, &parent->u.trace._typedef);
+ break;
+ case NODE_VARIANT:
+ cds_list_add(&node->siblings, &parent->u.variant._typedef);
+ break;
+ case NODE_STRUCT:
+ cds_list_add(&node->siblings, &parent->u._struct._typedef);
+ 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_DECLARATION_SPECIFIER:
+ case NODE_POINTER:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUMERATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ 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_typealias(struct ctf_node *node, struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ cds_list_add(&node->siblings, &parent->u.root.typealias);
+ break;
+ case NODE_EVENT:
+ cds_list_add(&node->siblings, &parent->u.event.typealias);
+ break;
+ case NODE_STREAM:
+ cds_list_add(&node->siblings, &parent->u.stream.typealias);
+ break;
+ case NODE_TRACE:
+ cds_list_add(&node->siblings, &parent->u.trace.typealias);
+ break;
+ case NODE_VARIANT:
+ cds_list_add(&node->siblings, &parent->u.variant.typealias);
+ break;
+ case NODE_STRUCT:
+ cds_list_add(&node->siblings, &parent->u._struct.typealias);
+ 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_DECLARATION_SPECIFIER:
+ case NODE_POINTER:
+ case NODE_TYPE_DECLARATOR:
+ case NODE_ENUMERATOR:
+ case NODE_ENUM:
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ 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_declaration_specifier(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ switch (parent->type) {
+ case NODE_ROOT:
+ cds_list_add(&node->siblings, &parent->u.root.declaration_specifier);
+ break;
+ case NODE_EVENT:
+ cds_list_add(&node->siblings, &parent->u.event.declaration_specifier);
+ break;
+ case NODE_STREAM:
+ cds_list_add(&node->siblings, &parent->u.stream.declaration_specifier);
+ break;
+ case NODE_TRACE:
+ cds_list_add(&node->siblings, &parent->u.trace.declaration_specifier);
+ break;
+ case NODE_VARIANT:
+ cds_list_add(&node->siblings, &parent->u.variant.declaration_list);
+ break;
+ case NODE_STRUCT:
+ cds_list_add(&node->siblings, &parent->u._struct.declaration_list);
+ break;
+ case NODE_TYPEDEF:
+ parent->u._typedef.declaration_specifier = node;
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ parent->u.typealias_target.declaration_specifier = node;
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ parent->u.typealias_alias.declaration_specifier = node;
+ break;
+ case NODE_TYPE_DECLARATOR:
+ parent->u.type_declarator.type = TYPEDEC_NESTED;
+ parent->u.type_declarator.u.nested.length.type = TYPEDEC_TYPE_TYPE;
+ parent->u.type_declarator.u.nested.length.u.declaration_specifier = node;
+ break;
+ case NODE_ENUM:
+ parent->u._enum.container_type.type = ENUM_TYPE_TYPE;
+ parent->u._enum.container_type.u.declaration_specifier = node;
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ parent->u.struct_or_variant_declaration.declaration_specifier = node;
+ break;
+ case NODE_TYPEALIAS:
+ case NODE_FLOATING_POINT:
+ case NODE_INTEGER:
+ case NODE_STRING:
+ case NODE_CTF_EXPRESSION:
+ case NODE_TYPE_SPECIFIER:
+ case NODE_DECLARATION_SPECIFIER:
+ case NODE_POINTER:
+ case NODE_ENUMERATOR:
+ 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:
+ cds_list_add(&node->siblings, &parent->u.struct_or_variant_declaration.type_declarators);
+ break;
+ case NODE_TYPEDEF:
+ cds_list_add(&node->siblings, &parent->u._typedef.type_declarators);
+ break;
+ case NODE_TYPEALIAS_TARGET:
+ cds_list_add(&node->siblings, &parent->u.typealias_target.type_declarators);
+ break;
+ case NODE_TYPEALIAS_ALIAS:
+ cds_list_add(&node->siblings, &parent->u.typealias_alias.type_declarators);
+ break;
+
+ case NODE_ROOT:
+ case NODE_EVENT:
+ case NODE_STREAM:
+ case NODE_TRACE:
+ 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_DECLARATION_SPECIFIER:
+ case NODE_POINTER:
+ case NODE_ENUMERATOR:
+ return -EPERM;
+
+ case NODE_UNKNOWN:
+ default:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * reparent node
+ *
+ * Relink node to new 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 reparent_node(struct ctf_node *node,
+ struct ctf_node *parent)
+{
+ if (!node || !parent)
+ return -ENOENT;
+
+ /* Unlink from old parent */
+ cds_list_del(&node->siblings);
+
+ /* Link to new parent */
+ node->parent = parent;
+
+ 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)
+ cds_list_add(&node->siblings, &parent->u.root.event);
+ else
+ return -EPERM;
+ break;
+ case NODE_STREAM:
+ if (parent->type == NODE_ROOT)
+ cds_list_add(&node->siblings, &parent->u.root.stream);
+ else
+ return -EPERM;
+ break;
+ case NODE_TRACE:
+ if (parent->type == NODE_ROOT)
+ cds_list_add(&node->siblings, &parent->u.root.trace);
+ else
+ return -EPERM;
+ break;
+
+ case NODE_CTF_EXPRESSION:
+ return reparent_ctf_expression(node, parent);
+
+ 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_TYPE_SPECIFIER:
+ if (parent->type == NODE_DECLARATION_SPECIFIER)
+ cds_list_add(&node->siblings, &parent->u.declaration_specifier.type_specifiers);
+ else
+ return -EPERM;
+ break;
+ case NODE_DECLARATION_SPECIFIER:
+ return reparent_declaration_specifier(node, parent);
+ case NODE_POINTER:
+ if (parent->type == NODE_TYPE_DECLARATOR)
+ cds_list_add(&node->siblings, &parent->u.type_declarator.pointers);
+ else
+ return -EPERM;
+ break;
+ case NODE_TYPE_DECLARATOR:
+ return reparent_type_declarator(node, parent);
+
+ case NODE_FLOATING_POINT:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_FLOATING_POINT;
+ parent->u.type_specifier.u.floating_point = node;
+ } else
+ return -EPERM;
+ break;
+ case NODE_INTEGER:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_INTEGER;
+ parent->u.type_specifier.u.integer = node;
+ } else
+ return -EPERM;
+ break;
+ case NODE_STRING:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_STRING;
+ parent->u.type_specifier.u.string = node;
+ } else
+ return -EPERM;
+ break;
+ case NODE_ENUMERATOR:
+ if (parent->type == NODE_ENUM)
+ cds_list_add(&node->siblings, &parent->u._enum.enumerator_list);
+ else
+ return -EPERM;
+ break;
+ case NODE_ENUM:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_ENUM;
+ parent->u.type_specifier.u._enum = node;
+ } else
+ return -EPERM;
+ break;
+ case NODE_STRUCT_OR_VARIANT_DECLARATION:
+ switch (parent->type) {
+ case NODE_STRUCT:
+ cds_list_add(&node->siblings, &parent->u.variant.declaration_list);
+ break;
+ case NODE_VARIANT:
+ cds_list_add(&node->siblings, &parent->u._struct.declaration_list);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case NODE_VARIANT:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_VARIANT;
+ parent->u.type_specifier.u.variant = node;
+ } else
+ return -EPERM;
+ break;
+ case NODE_STRUCT:
+ if (parent->type == NODE_TYPE_SPECIFIER) {
+ parent->u.type_specifier.type = TYPESPEC_STRUCT;
+ parent->u.type_specifier.u._struct = node;
+ } else
+ return -EPERM;
+ break;
+
+ case NODE_UNKNOWN:
+ default:
+ fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ (int) parent->type);
+ return -EINVAL;
+ }
+ return 0;
}
-void yyerror(const char *str)
+void yyerror(struct ctf_scanner *scanner, const char *str)
{
fprintf(stderr, "error %s\n", str);
}
return 1;
}
-static void free_strings(void)
+static void free_strings(struct cds_list_head *list)
{
struct gc_string *gstr, *tmp;
- cds_list_for_each_entry_safe(gstr, tmp, &allocated_strings, gc)
+ cds_list_for_each_entry_safe(gstr, tmp, list, gc)
free(gstr);
}
-int main(int argc, char **argv)
+static struct ctf_ast *ctf_ast_alloc(void)
{
- yydebug = 1;
- init_scope(&root_scope, NULL);
- yyparse();
- finalize_scope(&root_scope);
- free_strings();
- return 0;
-}
+ struct ctf_ast *ast;
+
+ ast = malloc(sizeof(*ast));
+ if (!ast)
+ return NULL;
+ memset(ast, 0, sizeof(*ast));
+ CDS_INIT_LIST_HEAD(&ast->allocated_nodes);
+ ast->root.type = NODE_ROOT;
+ CDS_INIT_LIST_HEAD(&ast->root.siblings);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root._typedef);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root.typealias);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root.declaration_specifier);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root.trace);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root.stream);
+ CDS_INIT_LIST_HEAD(&ast->root.u.root.event);
+ return ast;
+}
+
+static void ctf_ast_free(struct ctf_ast *ast)
+{
+ struct ctf_node *node, *tmp;
+
+ cds_list_for_each_entry_safe(node, tmp, &ast->allocated_nodes, gc)
+ free(node);
+}
+
+int ctf_scanner_append_ast(struct ctf_scanner *scanner)
+{
+ return yyparse(scanner);
+}
+
+struct ctf_scanner *ctf_scanner_alloc(FILE *input)
+{
+ struct ctf_scanner *scanner;
+ int ret;
+
+ scanner = malloc(sizeof(*scanner));
+ if (!scanner)
+ return NULL;
+ memset(scanner, 0, sizeof(*scanner));
+
+ ret = yylex_init_extra(scanner, &scanner->scanner);
+ if (ret) {
+ fprintf(stderr, "yylex_init error\n");
+ goto cleanup_scanner;
+ }
+ yyset_in(input, scanner);
+
+ scanner->ast = ctf_ast_alloc();
+ if (!scanner->ast)
+ goto cleanup_lexer;
+ init_scope(&scanner->root_scope, NULL);
+ CDS_INIT_LIST_HEAD(&scanner->allocated_strings);
+
+ return scanner;
+
+cleanup_lexer:
+ ret = yylex_destroy(scanner->scanner);
+ if (!ret)
+ fprintf(stderr, "yylex_destroy error\n");
+cleanup_scanner:
+ free(scanner);
+ return NULL;
+}
+
+void ctf_scanner_free(struct ctf_scanner *scanner)
+{
+ int ret;
+
+ finalize_scope(&scanner->root_scope);
+ free_strings(&scanner->allocated_strings);
+ ctf_ast_free(scanner->ast);
+ ret = yylex_destroy(scanner->scanner);
+ if (ret)
+ fprintf(stderr, "yylex_destroy error\n");
+ free(scanner);
+}
%}
+%define api.pure
+ /* %locations */
+%parse-param {struct ctf_scanner *scanner}
+%lex-param {struct ctf_scanner *scanner}
%start file
-/* %glr-parser */
%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE ESCSEQ CHAR_STRING_TOKEN LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW STAR PLUS MINUS LT GT TYPEASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA CONST CHAR DOUBLE ENUM EVENT FLOATING_POINT FLOAT INTEGER INT LONG SHORT SIGNED STREAM STRING STRUCT TRACE TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT
%token <gs> IDENTIFIER ID_TYPE
%token ERROR
struct ctf_node *n;
}
-/* %token <c>UPPERCASE_L LOWERCASE_L _U _NONDIGIT */
-/*%type <n> decl type_decl event_decl stream_decl trace_decl type_def
-%type <n> event_attrib field_attrib assign_attrib
-%type <n> event_attrib_list attrib_list field_list appendval_list
-%type <n> field value type_expr typename typename_postfix
-%type <gs> typename_prefix identifier */
+%type <n> event_declaration
+%type <n> ctf_assignment_expression_list
+%type <n> ctf_assignment_expression
+
%%
file:
event_declaration:
event_declaration_begin event_declaration_end
| event_declaration_begin ctf_assignment_expression_list event_declaration_end
+ {
+ $$ = make_node(scanner, NODE_EVENT);
+ /* TODO */
+ }
;
event_declaration_begin:
EVENT LBRAC
- {
- push_scope();
- }
+ { push_scope(scanner); }
;
event_declaration_end:
RBRAC SEMICOLON
- {
- pop_scope();
- }
+ { pop_scope(scanner); }
;
stream_declaration_begin:
STREAM LBRAC
- {
- push_scope();
- }
+ { push_scope(scanner); }
;
stream_declaration_end:
RBRAC SEMICOLON
- {
- pop_scope();
- }
+ { pop_scope(scanner); }
;
trace_declaration_begin:
TRACE LBRAC
- {
- push_scope();
- }
+ { push_scope(scanner); }
;
trace_declaration_end:
RBRAC SEMICOLON
- {
- pop_scope();
- }
+ { pop_scope(scanner); }
;
declaration_specifiers:
struct_declaration_begin:
LBRAC
- {
- push_scope();
- }
+ { push_scope(scanner); }
;
struct_declaration_end:
RBRAC
- {
- pop_scope();
- }
+ { pop_scope(scanner); }
;
variant_type_specifier:
variant_declaration_begin:
LBRAC
- {
- push_scope();
- }
+ { push_scope(scanner); }
;
variant_declaration_end:
RBRAC
- {
- pop_scope();
- }
+ { pop_scope(scanner); }
;
type_specifier_or_integer_constant:
direct_type_declarator:
IDENTIFIER
- {
- add_type($1->s);
- }
+ { add_type(scanner, $1->s); }
| LPAREN type_declarator RPAREN
| direct_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC
;
direct_abstract_type_declarator:
/* empty */
| IDENTIFIER
- {
- add_type($1->s);
- }
+ { add_type(scanner, $1->s); }
| LPAREN abstract_type_declarator RPAREN
| direct_abstract_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC
| direct_abstract_type_declarator LSBRAC RSBRAC
ctf_assignment_expression:
unary_expression EQUAL unary_expression
+ {
+ $$ = make_node(scanner, NODE_CTF_EXPRESSION);
+ /* TODO */
+
+ }
| unary_expression TYPEASSIGN type_specifier
| declaration_specifiers TYPEDEF declaration_specifiers type_declarator_list
| TYPEDEF declaration_specifiers type_declarator_list