From 34d3acc4fc9f020b0e2616a29a339b5c546a05c1 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 7 Feb 2011 01:16:21 -0500 Subject: [PATCH] Make CTF metadata parser reentrant Signed-off-by: Mathieu Desnoyers --- configure.ac | 3 +- formats/ctf/metadata/Makefile.am | 3 + formats/ctf/metadata/ctf-ast.h | 24 +++- formats/ctf/metadata/ctf-lexer.l | 13 +- formats/ctf/metadata/ctf-parser-test.c | 25 ++++ formats/ctf/metadata/ctf-parser.y | 159 +++++++++++++++++-------- formats/ctf/metadata/ctf-scanner.h | 32 +++++ 7 files changed, 200 insertions(+), 59 deletions(-) create mode 100644 formats/ctf/metadata/ctf-parser-test.c create mode 100644 formats/ctf/metadata/ctf-scanner.h diff --git a/configure.ac b/configure.ac index 1f1d2844..5743cada 100644 --- a/configure.ac +++ b/configure.ac @@ -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([ diff --git a/formats/ctf/metadata/Makefile.am b/formats/ctf/metadata/Makefile.am index fac978cc..48df5ac2 100644 --- a/formats/ctf/metadata/Makefile.am +++ b/formats/ctf/metadata/Makefile.am @@ -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 diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index b839b2c6..34d00367 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -2,6 +2,18 @@ #define _CTF_PARSER_H #include +#include +#include + +// 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 */ diff --git a/formats/ctf/metadata/ctf-lexer.l b/formats/ctf/metadata/ctf-lexer.l index d2151a72..21e5efa4 100644 --- a/formats/ctf/metadata/ctf-lexer.l +++ b/formats/ctf/metadata/ctf-lexer.l @@ -1,13 +1,20 @@ %{ #include +#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("\n", yytext); setstring(yytext); if (is_type(yytext)) return ID_TYPE; else return IDENTIFIER; +{IDENTIFIER} printf_dbg("\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 index 00000000..d2d4031e --- /dev/null +++ b/formats/ctf/metadata/ctf-parser-test.c @@ -0,0 +1,25 @@ +#include +#include +#include +#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; +} + + diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index 0d7c9c17..1f7420ea 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -12,32 +12,26 @@ #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) #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 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 index 00000000..07b5df7c --- /dev/null +++ b/formats/ctf/metadata/ctf-scanner.h @@ -0,0 +1,32 @@ +#ifndef _CTF_SCANNER_H +#define _CTF_SCANNER_H + +#include +#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 */ -- 2.34.1