From bb6ca7682c933404d2fd27c58f4838d8b271f93f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 27 Mar 2012 22:41:22 +0100 Subject: [PATCH] Make parser and scanner reentrant All global state is removed from the parser and scanner. This makes use of the standard facilities in Bison and Flex for reentrant/pure scanner/lexer and location tracking. Signed-off-by: Ran Benita [daniels: Updated to current sources.] --- src/xkbcomp/misc.c | 12 +--- src/xkbcomp/parseutils.c | 8 +-- src/xkbcomp/parseutils.h | 35 +++++++----- src/xkbcomp/xkbcomp.c | 7 +-- src/xkbcomp/xkbcomp.h | 2 - src/xkbcomp/xkbparse.y | 92 ++++++++++++++++++------------- src/xkbcomp/xkbscan.l | 139 +++++++++++++++++++++++++++-------------------- 7 files changed, 162 insertions(+), 133 deletions(-) diff --git a/src/xkbcomp/misc.c b/src/xkbcomp/misc.c index 5c9c13a..7bb05a5 100644 --- a/src/xkbcomp/misc.c +++ b/src/xkbcomp/misc.c @@ -56,8 +56,6 @@ ProcessIncludeFile(struct xkb_context *context, { FILE *file; XkbFile *rtrn, *mapToUse, *next; - char oldFile[1024] = {0}; - int oldLine = lineNum; file = XkbFindFileInPath(context, stmt->file, file_type, &stmt->path); if (file == NULL) @@ -66,16 +64,9 @@ ProcessIncludeFile(struct xkb_context *context, XkbDirectoryForInclude(file_type)); return False; } - if (scanFile) - strcpy(oldFile, scanFile); - else - memset(oldFile, 0, sizeof(oldFile)); - oldLine = lineNum; - setScanState(stmt->file, 1); /* parse the file */ - if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL)) + if ((XKBParseFile(file, stmt->file, &rtrn) == 0) || (rtrn == NULL)) { - setScanState(oldFile, oldLine); ERROR("Error interpreting include file \"%s\"\n", stmt->file); fclose(file); return False; @@ -114,7 +105,6 @@ ProcessIncludeFile(struct xkb_context *context, stmt->file); ACTION("Using first defined map, \"%s\"\n", rtrn->name); } - setScanState(oldFile, oldLine); if (mapToUse->type != file_type) { ERROR("Include file wrong type (expected %s, got %s)\n", diff --git a/src/xkbcomp/parseutils.c b/src/xkbcomp/parseutils.c index 1d66986..1392514 100644 --- a/src/xkbcomp/parseutils.c +++ b/src/xkbcomp/parseutils.c @@ -552,7 +552,7 @@ PrintStmtAddrs(ParseCommon * stmt) #endif void -CheckDefaultMap(XkbFile * maps) +CheckDefaultMap(XkbFile * maps, const char *fileName) { XkbFile *dflt, *tmp; @@ -569,7 +569,7 @@ CheckDefaultMap(XkbFile * maps) if (warningLevel > 2) { WARN("Multiple default components in %s\n", - (scanFile ? scanFile : "(unknown)")); + (fileName ? fileName : "(unknown)")); ACTION("Using %s, ignoring %s\n", (dflt->name ? dflt->name : "(first)"), (tmp->name ? tmp->name : "(subsequent)")); @@ -603,11 +603,11 @@ CreateXKBFile(int type, char *name, ParseCommon * defs, unsigned flags) } unsigned -StmtSetMerge(ParseCommon * stmt, unsigned merge) +StmtSetMerge(ParseCommon * stmt, unsigned merge, YYLTYPE *loc, void *scanner) { if ((merge == MergeAltForm) && (stmt->stmtType != StmtKeycodeDef)) { - yyerror("illegal use of 'alternate' merge mode"); + yyerror(loc, scanner, "illegal use of 'alternate' merge mode"); merge = MergeDefault; } return merge; diff --git a/src/xkbcomp/parseutils.h b/src/xkbcomp/parseutils.h index 89458df..1e7ac65 100644 --- a/src/xkbcomp/parseutils.h +++ b/src/xkbcomp/parseutils.h @@ -28,13 +28,19 @@ #define XKBPARSE_H 1 #include "xkbcomp.h" +#include "xkbparse.h" -extern char scanBuf[1024]; -extern int scanInt; -extern unsigned long scanULong; -extern int lineNum; +struct parser_param { + void *scanner; + XkbFile *rtrn; +}; -extern XkbFile *rtrnValue; +struct scanner_extra { + char *scanFile; + /* FIXME: This can overflow! */ + char scanBuf[8192]; + char *s; +}; extern ParseCommon *AppendStmt(ParseCommon * /* to */ , ParseCommon * /* append */ @@ -123,7 +129,9 @@ extern IncludeStmt *IncludeCreate(char * /* str */ , ); extern unsigned StmtSetMerge(ParseCommon * /* stmt */ , - unsigned /* merge */ + unsigned /* merge */, + YYLTYPE * /* loc */, + void * /* scanner */ ); #ifdef DEBUG @@ -132,12 +140,14 @@ extern void PrintStmtAddrs(ParseCommon * /* stmt */ #endif extern int XKBParseFile(FILE * /* file */ , + const char * /* fileName */, XkbFile ** /* pRtrn */ ); -extern int XKBParseString(const char *string, XkbFile ** pRtrn); +extern int XKBParseString(const char *string, const char *fileName, + XkbFile ** pRtrn); -extern void CheckDefaultMap(XkbFile * maps); +extern void CheckDefaultMap(XkbFile * maps, const char *fileName); extern XkbFile *CreateXKBFile(int /* type */ , char * /* name */ , @@ -147,14 +157,9 @@ extern XkbFile *CreateXKBFile(int /* type */ , extern void FreeXKBFile(XkbFile *file); -extern void yyerror(const char * /* msg */ - ); - -extern void setScanState(const char * /* file */ , - int /* line */ - ); - extern void FreeStmt(ParseCommon * /* stmt */ ); +extern void yyerror(struct YYLTYPE *loc, void *scanner, const char *msg); + #endif /* XKBPARSE_H */ diff --git a/src/xkbcomp/xkbcomp.c b/src/xkbcomp/xkbcomp.c index bf03626..051c51f 100644 --- a/src/xkbcomp/xkbcomp.c +++ b/src/xkbcomp/xkbcomp.c @@ -212,7 +212,6 @@ compile_keymap(struct xkb_context *context, XkbFile *file) err: FreeXKBFile(file); - free(scanFile); XkbcFreeAllAtoms(); return xkb; } @@ -273,8 +272,7 @@ xkb_map_new_from_string(struct xkb_context *context, return NULL; } - setScanState("input", 1); - if (!XKBParseString(string, &file) || !file) { + if (!XKBParseString(string, "input", &file) || !file) { ERROR("failed to parse input xkb file\n"); return NULL; } @@ -306,8 +304,7 @@ xkb_map_new_from_fd(struct xkb_context *context, return NULL; } - setScanState("input", 1); - if (!XKBParseFile(fptr, &file) || !file) { + if (!XKBParseFile(fptr, "(unknown file)", &file) || !file) { ERROR("failed to parse input xkb file\n"); return NULL; } diff --git a/src/xkbcomp/xkbcomp.h b/src/xkbcomp/xkbcomp.h index 4a6212b..cdbc6ed 100644 --- a/src/xkbcomp/xkbcomp.h +++ b/src/xkbcomp/xkbcomp.h @@ -33,8 +33,6 @@ #include "XKBcommonint.h" #include "xkbmisc.h" -extern char *scanFile; - #define TypeUnknown 0 #define TypeBoolean 1 #define TypeInt 2 diff --git a/src/xkbcomp/xkbparse.y b/src/xkbcomp/xkbparse.y index 9db7ee5..b6131e6 100644 --- a/src/xkbcomp/xkbparse.y +++ b/src/xkbcomp/xkbparse.y @@ -24,6 +24,26 @@ ********************************************************/ +%{ +#define DEBUG 1 +#ifdef DEBUG +#define YYDEBUG 1 +#endif +#include "parseutils.h" +#include "xkbmisc.h" +#include +#include + +extern int yylex(union YYSTYPE *val, struct YYLTYPE *loc, void *scanner); + +#define scanner param->scanner +%} + +%define api.pure +%locations +%lex-param { void *scanner } +%parse-param { struct parser_param *param } + %token END_OF_FILE 0 ERROR_TOK 255 @@ -88,19 +108,7 @@ KEYPAD_KEYS 75 FUNCTION_KEYS 76 ALTERNATE_GROUP 77 -%{ -#define DEBUG 1 -#ifdef DEBUG -#define YYDEBUG 1 -#endif -#include "parseutils.h" -#include "xkbmisc.h" -#include -#include -extern int yylex(void); -extern FILE *yyin; -%} %right EQUALS %left PLUS MINUS %left TIMES DIVIDE @@ -110,6 +118,7 @@ extern FILE *yyin; %union { int ival; unsigned uval; + int64_t num; char *str; Atom sval; ParseCommon *any; @@ -128,6 +137,8 @@ extern FILE *yyin; void *geom; XkbFile *file; } +%type INTEGER FLOAT +%type IDENT KEYNAME STRING %type Number Integer Float SignedNumber %type XkbCompositeType FileType MergeMode OptMergeMode %type DoodadType Flag Flags OptFlags KeyCode @@ -154,11 +165,11 @@ extern FILE *yyin; %type XkbCompositeMap XkbCompMapList %% XkbFile : XkbCompMapList - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } | XkbMapConfigList - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } | XkbConfig - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } ; XkbCompMapList : XkbCompMapList XkbCompositeMap @@ -254,57 +265,57 @@ DeclList : DeclList Decl Decl : OptMergeMode VarDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode VModDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode InterpretDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode KeyNameDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode KeyAliasDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode KeyTypeDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode SymbolsDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode ModMapDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode GroupCompatDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode IndicatorMapDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode IndicatorNameDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode ShapeDecl @@ -319,11 +330,12 @@ Decl : OptMergeMode VarDecl | MergeMode STRING { if ($1==MergeAltForm) { - yyerror("cannot use 'alternate' to include other maps"); - $$= &IncludeCreate(scanBuf,MergeDefault)->common; + yyerror(&@1, scanner, + "cannot use 'alternate' to include other maps"); + $$= &IncludeCreate($2,MergeDefault)->common; } else { - $$= &IncludeCreate(scanBuf,$1)->common; + $$= &IncludeCreate($2,$1)->common; } } ; @@ -713,7 +725,7 @@ KeySymList : KeySymList COMMA KeySym { $$= CreateKeysymList($1); } ; -KeySym : IDENT { $$= strdup(scanBuf); } +KeySym : IDENT { $$= $1; } | SECTION { $$= strdup("section"); } | Integer { @@ -733,32 +745,36 @@ SignedNumber : MINUS Number { $$= -$2; } | Number { $$= $1; } ; -Number : FLOAT { $$= scanInt; } - | INTEGER { $$= scanInt*XkbGeomPtsPerMM; } +Number : FLOAT { $$= $1; } + | INTEGER { $$= $1*XkbGeomPtsPerMM; } ; Float : FLOAT { $$= 0; } ; -Integer : INTEGER { $$= scanInt; } +Integer : INTEGER { $$= $1; } ; -KeyCode : INTEGER { $$= scanULong; } +KeyCode : INTEGER { $$= $1; } ; -KeyName : KEYNAME { $$= strdup(scanBuf); } +KeyName : KEYNAME { $$= $1; } ; -Ident : IDENT { $$= xkb_intern_atom(scanBuf); } +Ident : IDENT { $$= xkb_intern_atom($1); free($1); } | DEFAULT { $$= xkb_intern_atom("default"); } ; -String : STRING { $$= xkb_intern_atom(scanBuf); } +String : STRING { $$= xkb_intern_atom($1); free($1); } ; OptMapName : MapName { $$= $1; } | { $$= NULL; } ; -MapName : STRING { $$= strdup(scanBuf); } +MapName : STRING { $$= $1; } ; + +%% + +#undef scanner diff --git a/src/xkbcomp/xkbscan.l b/src/xkbcomp/xkbscan.l index 599a388..9e08a76 100644 --- a/src/xkbcomp/xkbscan.l +++ b/src/xkbcomp/xkbscan.l @@ -31,25 +31,26 @@ #include "utils.h" #include "parseutils.h" -#include "xkbparse.h" -char *scanFile = NULL; -int lineNum = 0; -int scanInt; -unsigned long scanULong; +extern int yyparse(struct parser_param *param); -static char *s; -char scanBuf[1024]; - -extern int yyparse(void); +#define YY_USER_ACTION { \ + yylloc->first_line = yylineno; \ + yylloc->last_line = yylineno; \ +} %} +%option reentrant +%option extra-type="struct scanner_extra *" +%option bison-bridge bison-locations +%option never-interactive nounistd %option case-insensitive %option yylineno %option noyywrap %option never-interactive +%option nowarn %option noinput %option nounput @@ -60,11 +61,21 @@ extern int yyparse(void); "//"[^\n]* "#"[^\n]* -\" s = scanBuf; BEGIN(S_STR); -\< s = scanBuf; BEGIN(S_KEY); +\" yyextra->s = yyextra->scanBuf; BEGIN(S_STR); +\< yyextra->s = yyextra->scanBuf; BEGIN(S_KEY); -\" BEGIN(INITIAL); *s = '\0'; return STRING; -\> BEGIN(INITIAL); *s = '\0'; return KEYNAME; +\" { + BEGIN(INITIAL); + *yyextra->s = '\0'; + yylval->str = strdup(yyextra->scanBuf); + return STRING; + } +\> { + BEGIN(INITIAL); + *yyextra->s = '\0'; + yylval->str = strdup(yyextra->scanBuf); + return KEYNAME; + } \\[0-7]{1,3} { /* octal escape sequence */ @@ -77,7 +88,7 @@ extern int yyparse(void); return ERROR_TOK; } - *s++ = result; + *yyextra->s++ = result; } \\[0-9]+ { @@ -85,15 +96,15 @@ extern int yyparse(void); return ERROR_TOK; } -\\n *s++ = '\n'; -\\t *s++ = '\t'; -\\r *s++ = '\r'; -\\b *s++ = '\b'; -\\f *s++ = '\f'; -\\v *s++ = '\v'; -\\e *s++ = '\033'; +\\n *yyextra->s++ = '\n'; +\\t *yyextra->s++ = '\t'; +\\r *yyextra->s++ = '\r'; +\\b *yyextra->s++ = '\b'; +\\f *yyextra->s++ = '\f'; +\\v *yyextra->s++ = '\v'; +\\e *yyextra->s++ = '\033'; -. *s++ = yytext[0]; +. *yyextra->s++ = yytext[0]; xkb_keymap return XKB_KEYMAP; xkb_keycodes return XKB_KEYCODES; @@ -141,19 +152,18 @@ keypad_keys return KEYPAD_KEYS; function_keys return FUNCTION_KEYS; alternate_group return ALTERNATE_GROUP; -[a-zA-Z_][a-zA-Z_0-9]* memcpy(scanBuf, yytext, yyleng + 1); return IDENT; +[a-zA-Z_][a-zA-Z_0-9]* yylval->str = strdup(yytext); return IDENT; 0x[a-fA-F0-9]+ | [0-9]+ { char *end; - scanInt = strtol(yytext, &end, 0); - scanULong = strtoul(yytext, &end, 0); + yylval->num = strtoul(yytext, &end, 0); return INTEGER; } [0-9]+\.[0-9]+ { char *end; - scanInt = strtod(yytext, &end) * XkbGeomPtsPerMM; + yylval->num = strtod(yytext, &end) * XkbGeomPtsPerMM; return FLOAT; } @@ -184,62 +194,75 @@ alternate_group return ALTERNATE_GROUP; %% void -yyerror(const char *msg) +yyerror(YYLTYPE *loc, void *scanner, const char *msg) { - if (warningLevel>0) { - fprintf(stderr,"%s: line %d of %s\n",msg,yylineno, - (scanFile?scanFile:"(unknown)")); - if (warningLevel>3) - fprintf(stderr,"last scanned symbol is: %s\n",scanBuf); + struct scanner_extra *extra = yyget_extra(scanner); + + if (warningLevel > 0) { + fprintf(stderr, "%s: line %d of %s\n", msg, loc->first_line, + extra->scanFile ? extra->scanFile : "(unknown)"); + if (warningLevel > 3) + fprintf(stderr, "last scanned symbol is: %s\n", extra->scanBuf); } return; } -void setScanState(const char *file, int lineno) -{ - yylineno = 1; - free(scanFile); - scanFile = strdup(file); -} - int -XKBParseString(const char *string, XkbFile ** pRtrn) +XKBParseString(const char *string, const char *fileName, XkbFile **pRtrn) { YY_BUFFER_STATE state; + struct parser_param param; + struct scanner_extra extra; + int ret; *pRtrn = NULL; if (string == NULL) - return 1; + return 1; - state = yy_scan_string(string); - rtrnValue = NULL; - if (yyparse() != 0) - return 0; + memset(&extra, 0, sizeof(extra)); + ret = yylex_init_extra(&extra, ¶m.scanner); + if (ret != 0) + return 0; + extra.scanFile = strdup(fileName); + + state = yy_scan_string(string, param.scanner); + ret = yyparse(¶m); + yy_delete_buffer(state, param.scanner); + yylex_destroy(param.scanner); + free(extra.scanFile); + if (ret) + return 0; - yy_delete_buffer(state); - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - *pRtrn = rtrnValue; - CheckDefaultMap(rtrnValue); - rtrnValue = NULL; + CheckDefaultMap(param.rtrn, fileName); + *pRtrn = param.rtrn; return 1; } int -XKBParseFile(FILE * file, XkbFile ** pRtrn) +XKBParseFile(FILE * file, const char *fileName, XkbFile ** pRtrn) { + int ret; + struct parser_param param; + struct scanner_extra extra; + *pRtrn = NULL; if (!file) return 1; - yyin = file; - rtrnValue = NULL; - if (yyparse() != 0) + memset(&extra, 0, sizeof(extra)); + if (yylex_init_extra(&extra, ¶m.scanner) != 0) + return 0; + extra.scanFile = strdup(fileName); + + yyset_in(file, param.scanner); + ret = yyparse(¶m); + yylex_destroy(param.scanner); + free(extra.scanFile); + if (ret) return 0; - yylex_destroy(); - *pRtrn = rtrnValue; - CheckDefaultMap(rtrnValue); - rtrnValue = NULL; + CheckDefaultMap(param.rtrn, fileName); + *pRtrn = param.rtrn; return 1; } -- 2.7.4