Make CTF metadata parser reentrant
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 7 Feb 2011 06:16:21 +0000 (01:16 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 7 Feb 2011 06:16:21 +0000 (01:16 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
configure.ac
formats/ctf/metadata/Makefile.am
formats/ctf/metadata/ctf-ast.h
formats/ctf/metadata/ctf-lexer.l
formats/ctf/metadata/ctf-parser-test.c [new file with mode: 0644]
formats/ctf/metadata/ctf-parser.y
formats/ctf/metadata/ctf-scanner.h [new file with mode: 0644]

index 1f1d28449f9865399f49f94998d43ca93873d85c..5743cada9d03bef1d3b4e4738fbca811ffee54bb 100644 (file)
@@ -37,7 +37,8 @@ pkg_modules="gmodule-2.0 >= 2.0.0"
 PKG_CHECK_MODULES(GMODULE, [$pkg_modules])
 AC_SUBST(PACKAGE_LIBS)
 
-PACKAGE_CFLAGS="$GMODULE_CFLAGS"
+LIBS="$LIBS $GMODULE_LIBS"
+PACKAGE_CFLAGS="$GMODULE_CFLAGS -Wall -Wformat"
 AC_SUBST(PACKAGE_CFLAGS)
 
 AC_CONFIG_FILES([
index fac978cce68bef88377d9246ff27708b525bd3a0..48df5ac2c0d565b5c6345bde98c74f70d82548a1 100644 (file)
@@ -5,3 +5,6 @@ AM_YFLAGS = -t -d
 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
index b839b2c694991cec9d2347d33cc20fef7dd1aa04..34d00367fc396ab93af2775c1dd677c6a563ae59 100644 (file)
@@ -2,6 +2,18 @@
 #define _CTF_PARSER_H
 
 #include <helpers/list.h>
+#include <stdio.h>
+#include <glib.h>
+
+// the parameter name (of the reentrant 'yyparse' function)
+// data is a pointer to a 'SParserParam' structure
+//#define YYPARSE_PARAM        scanner
+
+// the argument for the 'yylex' function
+#define YYLEX_PARAM    ((struct ctf_scanner *) scanner)->scanner
+
+struct ctf_node;
+struct ctf_parser;
 
 enum node_type {
        NODE_UNKNOWN,
@@ -14,8 +26,6 @@ enum node_type {
        NR_NODE_TYPES,
 };
 
-struct ctf_node;
-
 struct ctf_node {
        enum node_type type;
        char *str;
@@ -27,6 +37,14 @@ struct ctf_node {
        struct cds_list_head gc;
 };
 
-int is_type(const char *id);
+struct scope;
+struct scope {
+       struct scope *parent;
+       GHashTable *types;
+};
+
+struct ctf_ast {
+       struct ctf_node root;
+};
 
 #endif /* _CTF_PARSER_H */
index d2151a72e1e9fb2218c027ab99f4c914d2d6ff0e..21e5efa415bac5151c45f1cb46cf7b95dcd18527 100644 (file)
@@ -1,13 +1,20 @@
 %{
 #include <stdio.h>
+#include "ctf-scanner.h"
 #include "ctf-parser.h"
 #include "ctf-ast.h"
 
-extern YYSTYPE yylval;
-extern void setstring(const char *src);
+extern void setstring(struct ctf_scanner *scanner, YYSTYPE *lvalp, const char *src);
+
+#define printf_dbg(fmt, args...)       fprintf(stderr, "%s: " fmt, __func__, args)
+#define printf_dbg_noarg(fmt)  fprintf(stderr, "%s: " fmt, __func__)
+
 %}
 
 %x comment_ml comment_sl string_lit char_const
+%option reentrant yylineno noyywrap bison-bridge
+%option extra-type="struct ctf_scanner *"
+       /* bison-locations */
 INTEGER_SUFFIX                 [ \n\t]*(U|UL|ULL|LU|LLU|Ul|Ull|lU|llU|u|uL|uLL|Lu|LLu|ul|ull|lu|llu)
 DIGIT                          [0-9]
 NONDIGIT                       [a-zA-Z_]
@@ -92,7 +99,7 @@ _Imaginary                    return _IMAGINARY;
 [1-9]{DIGIT}*{INTEGER_SUFFIX}? return DECIMAL_CONSTANT;
 0{OCTALDIGIT}*{INTEGER_SUFFIX}?        return OCTAL_CONSTANT;
 0[xX]{HEXDIGIT}+{INTEGER_SUFFIX}?      return HEXADECIMAL_CONSTANT;
-{IDENTIFIER}                   printf_dbg("<IDENTIFIER %s>\n", yytext); setstring(yytext); if (is_type(yytext)) return ID_TYPE; else return IDENTIFIER;
+{IDENTIFIER}                   printf_dbg("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); if (is_type(yyextra, yytext)) return ID_TYPE; else return IDENTIFIER;
 [ \t\n]+                       ; /* ignore */
 .                              return ERROR;
 %%
diff --git a/formats/ctf/metadata/ctf-parser-test.c b/formats/ctf/metadata/ctf-parser-test.c
new file mode 100644 (file)
index 0000000..d2d4031
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include "ctf-scanner.h"
+#include "ctf-parser.h"
+#include "ctf-ast.h"
+
+extern int yydebug;
+
+int main(int argc, char **argv)
+{
+       struct ctf_scanner *scanner;
+
+       yydebug = 1;
+       scanner = ctf_scanner_alloc(stdin);
+       if (!scanner) {
+               fprintf(stderr, "Error allocating scanner\n");
+               return -1;
+       }
+       ctf_scanner_append_ast(scanner);
+       ctf_scanner_free(scanner);
+       return 0;
+} 
+
+
index 0d7c9c17fe618ec68f562ca94e506ebae77a1604..1f7420ea5d34187b77b76a6c2cc02006ad40865c 100644 (file)
 #include <assert.h>
 #include <helpers/list.h>
 #include <glib.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__)
 
-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;
@@ -49,19 +43,19 @@ char *strredup(char **dest, const char *src)
        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)
@@ -76,28 +70,28 @@ static void finalize_scope(struct scope *scope)
        g_hash_table_destroy(scope->types);
 }
 
-static void push_scope(void)
+static void push_scope(struct ctf_scanner *scanner)
 {
        struct scope *ns;
 
        printf_dbg_noarg("push scope\n");
        ns = malloc(sizeof(struct scope));
-       init_scope(ns, cs);
-       cs = ns;
+       init_scope(ns, scanner->cs);
+       scanner->cs = ns;
 }
 
-static void pop_scope(void)
+static void pop_scope(struct ctf_scanner *scanner)
 {
        struct scope *os;
 
        printf_dbg_noarg("pop scope\n");
-       os = cs;
-       cs = os->parent;
+       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 scope *s, const char *id)
 {
        int ret;
 
@@ -106,12 +100,12 @@ int lookup_type(struct scope *s, const char *id)
        return ret;
 }
 
-int is_type(const char *id)
+int is_type(struct ctf_scanner *scanner, const char *id)
 {
        struct 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;
@@ -121,18 +115,18 @@ int is_type(const char *id)
        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);
 }
 
-void yyerror(const char *str)
+void yyerror(struct ctf_scanner *scanner, const char *str)
 {
        fprintf(stderr, "error %s\n", str);
 }
@@ -142,26 +136,87 @@ int yywrap(void)
        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));
+       return ast;
+}
+
+static void ctf_ast_free(struct ctf_ast *ast)
+{
+}
+
+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
 %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
@@ -283,14 +338,14 @@ event_declaration:
 event_declaration_begin:
                EVENT LBRAC
                {
-                       push_scope();
+                       push_scope(scanner);
                }
        ;
 
 event_declaration_end:
                RBRAC SEMICOLON
                {
-                       pop_scope();
+                       pop_scope(scanner);
                }
        ;
 
@@ -303,14 +358,14 @@ stream_declaration:
 stream_declaration_begin:
                STREAM LBRAC
                {
-                       push_scope();
+                       push_scope(scanner);
                }
        ;
 
 stream_declaration_end:
                RBRAC SEMICOLON
                {
-                       pop_scope();
+                       pop_scope(scanner);
                }
        ;
 
@@ -323,14 +378,14 @@ trace_declaration:
 trace_declaration_begin:
                TRACE LBRAC
                {
-                       push_scope();
+                       push_scope(scanner);
                }
        ;
 
 trace_declaration_end:
                RBRAC SEMICOLON
                {
-                       pop_scope();
+                       pop_scope(scanner);
                }
        ;
 
@@ -386,14 +441,14 @@ struct_type_specifier:
 struct_declaration_begin:
                LBRAC
                {
-                       push_scope();
+                       push_scope(scanner);
                }
        ;
 
 struct_declaration_end:
                RBRAC
                {
-                       pop_scope();
+                       pop_scope(scanner);
                }
        ;
 
@@ -416,14 +471,14 @@ variant_type_specifier:
 variant_declaration_begin:
                LBRAC
                {
-                       push_scope();
+                       push_scope(scanner);
                }
        ;
 
 variant_declaration_end:
                RBRAC
                {
-                       pop_scope();
+                       pop_scope(scanner);
                }
        ;
 
@@ -540,7 +595,7 @@ type_declarator:
 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
@@ -555,7 +610,7 @@ 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
diff --git a/formats/ctf/metadata/ctf-scanner.h b/formats/ctf/metadata/ctf-scanner.h
new file mode 100644 (file)
index 0000000..07b5df7
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _CTF_SCANNER_H
+#define _CTF_SCANNER_H
+
+#include <stdio.h>
+#include "ctf-ast.h"
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+struct ctf_scanner {
+       yyscan_t scanner;
+       struct ctf_ast *ast;
+       struct scope root_scope;
+       struct scope *cs;
+       struct cds_list_head allocated_strings;
+};
+
+struct ctf_scanner *ctf_scanner_alloc(FILE *input);
+void ctf_scanner_free(struct ctf_scanner *scanner);
+int ctf_scanner_append_ast(struct ctf_scanner *scanner);
+
+static inline
+struct ctf_ast *ctf_scanner_get_ast(struct ctf_scanner *scanner)
+{
+       return scanner->ast;
+}
+
+int is_type(struct ctf_scanner *scanner, const char *id);
+
+#endif /* _CTF_SCANNER_H */
This page took 0.047261 seconds and 4 git commands to generate.