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 <[email protected]> --- src/xkbcomp/compat.c | 3 +- src/xkbcomp/keytypes.c | 3 +- src/xkbcomp/listing.c | 3 +- src/xkbcomp/misc.c | 12 +--- src/xkbcomp/parseutils.c | 8 +-- src/xkbcomp/parseutils.h | 38 ++++++------ src/xkbcomp/xkbcomp.c | 6 +- src/xkbcomp/xkbcomp.h | 2 - src/xkbcomp/xkbparse.y | 97 +++++++++++++++++------------ src/xkbcomp/xkbscan.l | 155 +++++++++++++++++++++++++--------------------- 10 files changed, 171 insertions(+), 156 deletions(-) diff --git a/src/xkbcomp/compat.c b/src/xkbcomp/compat.c index 9b268e6..620e8ff 100644 --- a/src/xkbcomp/compat.c +++ b/src/xkbcomp/compat.c @@ -820,8 +820,7 @@ CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge, else { WSGO("Couldn't allocate space for compat name\n"); - ACTION("Name \"%s\" (from %s) NOT assigned\n", - scanFile, info.name); + ACTION("Name \"%s\" NOT assigned\n", info.name); } } size = info.nInterps * sizeof(struct xkb_sym_interpret); diff --git a/src/xkbcomp/keytypes.c b/src/xkbcomp/keytypes.c index 71f6075..3e2e91e 100644 --- a/src/xkbcomp/keytypes.c +++ b/src/xkbcomp/keytypes.c @@ -1189,8 +1189,7 @@ CompileKeyTypes(XkbFile *file, struct xkb_desc * xkb, unsigned merge) else { WSGO("Couldn't allocate space for types name\n"); - ACTION("Name \"%s\" (from %s) NOT assigned\n", - scanFile, info.name); + ACTION("Name \"%s\" NOT assigned\n", info.name); } } i = info.nTypes; diff --git a/src/xkbcomp/listing.c b/src/xkbcomp/listing.c index dbedca6..a3ff89e 100644 --- a/src/xkbcomp/listing.c +++ b/src/xkbcomp/listing.c @@ -235,8 +235,7 @@ ParseComponents(CompPair *cp, char *path, char *map, int *max, unsigned strip) return 0; } - setScanState(path, 1); - if (!XKBParseFile(inputFile, &rtrn) || !rtrn) { + if (!XKBParseFile(inputFile, path, &rtrn) || !rtrn) { if (oldWarningLevel > 5) WARN("Couldn't parse file \"%s\"\n", path); fclose(inputFile); diff --git a/src/xkbcomp/misc.c b/src/xkbcomp/misc.c index 35f947c..ed98b9f 100644 --- a/src/xkbcomp/misc.c +++ b/src/xkbcomp/misc.c @@ -54,8 +54,6 @@ ProcessIncludeFile(IncludeStmt * stmt, { FILE *file; XkbFile *rtrn, *mapToUse; - char oldFile[1024] = {0}; - int oldLine = lineNum; rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path); if (rtrn == NULL) @@ -69,18 +67,11 @@ ProcessIncludeFile(IncludeStmt * stmt, XkbDirectoryForInclude(file_type)); return False; } - if (scanFile) - strcpy(oldFile, scanFile); - else - memset(oldFile, 0, sizeof(oldFile)); - oldLine = lineNum; - setScanState(stmt->file, 1); if (debugFlags & 2) INFO("About to parse include file %s\n", stmt->file); /* 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; @@ -109,7 +100,6 @@ ProcessIncludeFile(IncludeStmt * stmt, 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 65de324..099863b 100644 --- a/src/xkbcomp/parseutils.c +++ b/src/xkbcomp/parseutils.c @@ -739,7 +739,7 @@ PrintStmtAddrs(ParseCommon * stmt) #endif void -CheckDefaultMap(XkbFile * maps) +CheckDefaultMap(XkbFile * maps, const char *fileName) { XkbFile *dflt, *tmp; @@ -756,7 +756,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)")); @@ -791,11 +791,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 64d01e0..d2a92a5 100644 --- a/src/xkbcomp/parseutils.h +++ b/src/xkbcomp/parseutils.h @@ -28,13 +28,7 @@ #define XKBPARSE_H 1 #include "xkbcomp.h" - -extern char scanBuf[1024]; -extern int scanInt; -extern unsigned long scanULong; -extern int lineNum; - -extern XkbFile *rtrnValue; +#include "xkbparse.h" #ifdef DEBUG #define d(str) fprintf(stderr,"%s\n",str); @@ -166,7 +160,9 @@ extern IncludeStmt *IncludeCreate(char * /* str */ , ); extern unsigned StmtSetMerge(ParseCommon * /* stmt */ , - unsigned /* merge */ + unsigned /* merge */, + YYLTYPE * /* loc */, + void * /* scanner */ ); #ifdef DEBUG @@ -175,12 +171,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 */ , @@ -188,16 +186,18 @@ extern XkbFile *CreateXKBFile(int /* type */ , unsigned /* flags */ ); -extern void yyerror(const char * /* s */ - ); +struct parser_param { + void *scanner; + XkbFile *rtrn; +}; -extern int yylex(void); -extern int yyparse(void); - -extern void setScanState(char * /* file */ , - int /* line */ - ); +struct scanner_extra { + char *scanFile; + /* FIXME: This can overflow. */ + char scanBuf[1024]; + char *s; +}; -extern const char *yystring; +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 cc3b52d..8f74c3b 100644 --- a/src/xkbcomp/xkbcomp.c +++ b/src/xkbcomp/xkbcomp.c @@ -297,8 +297,7 @@ xkb_compile_keymap_from_string(const char *string, const char *mapName) 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; } @@ -316,8 +315,7 @@ xkb_compile_keymap_from_file(FILE *inputFile, const char *mapName) return NULL; } - setScanState("input", 1); - if (!XKBParseFile(inputFile, &file) || !file) { + if (!XKBParseFile(inputFile, "input", &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 502b0ba..d2d69c6 100644 --- a/src/xkbcomp/xkbcomp.h +++ b/src/xkbcomp/xkbcomp.h @@ -39,8 +39,6 @@ #include "xkbcommon/xkbcommon.h" #include "XKBcommonint.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 60c445b..a369039 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 <X11/keysym.h> +#include <stdlib.h> + +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,17 +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 <X11/keysym.h> -#include <stdlib.h> -%} %right EQUALS %left PLUS MINUS %left TIMES DIVIDE @@ -108,6 +118,7 @@ %union { int ival; unsigned uval; + int64_t num; char *str; Atom sval; ParseCommon *any; @@ -133,6 +144,8 @@ DoodadDef *doodad; XkbFile *file; } +%type <num> INTEGER FLOAT +%type <str> IDENT KEYNAME STRING %type <ival> Number Integer Float SignedNumber %type <uval> XkbCompositeType FileType MergeMode OptMergeMode %type <uval> DoodadType Flag Flags OptFlags KeyCode @@ -164,11 +177,11 @@ %type <file> XkbCompositeMap XkbCompMapList %% XkbFile : XkbCompMapList - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } | XkbMapConfigList - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } | XkbConfig - { $$= rtrnValue= $1; } + { $$= param->rtrn= $1; } ; XkbCompMapList : XkbCompMapList XkbCompositeMap @@ -237,82 +250,82 @@ 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 { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode SectionDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | OptMergeMode DoodadDecl { - $2->merge= StmtSetMerge(&$2->common,$1); + $2->merge= StmtSetMerge(&$2->common,$1,&@1,scanner); $$= &$2->common; } | 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; } } ; @@ -719,7 +732,7 @@ KeySymList : KeySymList COMMA KeySym { $$= CreateKeysymList($1); } ; -KeySym : IDENT { $$= strdup(scanBuf); } +KeySym : IDENT { $$= $1; } | SECTION { $$= strdup("section"); } | Integer { @@ -739,32 +752,36 @@ SignedNumber : MINUS Number { $$= -$2; } | Number { $$= $1; } ; -Number : FLOAT { $$= scanInt; } - | INTEGER { $$= scanInt*XkbGeomPtsPerMM; } +Number : FLOAT { $$= $1; } + | INTEGER { $$= $1*XkbGeomPtsPerMM; } ; -Float : FLOAT { $$= scanInt; } +Float : FLOAT { $$= $1; } ; -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 3c98131..dfa6e50 100644 --- a/src/xkbcomp/xkbscan.l +++ b/src/xkbcomp/xkbscan.l @@ -31,26 +31,26 @@ #include <X11/Xos.h> #include "parseutils.h" -#include "xkbparse.h" #include "utils.h" -const char *yystring; -char *scanFile = NULL; -int lineNum = 0; +extern int yyparse(struct parser_param *param); -int scanInt; -unsigned long scanULong; - -static char *s; -char scanBuf[1024]; - -#define BUFSIZE 4096 +#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 warn +%option noinput nounput %x S_STR S_KEY @@ -59,11 +59,21 @@ char scanBuf[1024]; "//"[^\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); -<S_STR>\" BEGIN(INITIAL); *s = '\0'; return STRING; -<S_KEY>\> BEGIN(INITIAL); *s = '\0'; return KEYNAME; +<S_STR>\" { + BEGIN(INITIAL); + *yyextra->s = '\0'; + yylval->str = strdup(yyextra->scanBuf); + return STRING; + } +<S_KEY>\> { + BEGIN(INITIAL); + *yyextra->s = '\0'; + yylval->str = strdup(yyextra->scanBuf); + return KEYNAME; + } <S_STR,S_KEY>\\[0-7]{1,3} { /* octal escape sequence */ @@ -76,7 +86,7 @@ char scanBuf[1024]; return ERROR_TOK; } - *s++ = result; + *yyextra->s++ = result; } <S_STR,S_KEY>\\[0-9]+ { @@ -84,15 +94,15 @@ char scanBuf[1024]; return ERROR_TOK; } -<S_STR,S_KEY>\\n *s++ = '\n'; -<S_STR,S_KEY>\\t *s++ = '\t'; -<S_STR,S_KEY>\\r *s++ = '\r'; -<S_STR,S_KEY>\\b *s++ = '\b'; -<S_STR,S_KEY>\\f *s++ = '\f'; -<S_STR,S_KEY>\\v *s++ = '\v'; -<S_STR,S_KEY>\\e *s++ = '\033'; +<S_STR,S_KEY>\\n *yyextra->s++ = '\n'; +<S_STR,S_KEY>\\t *yyextra->s++ = '\t'; +<S_STR,S_KEY>\\r *yyextra->s++ = '\r'; +<S_STR,S_KEY>\\b *yyextra->s++ = '\b'; +<S_STR,S_KEY>\\f *yyextra->s++ = '\f'; +<S_STR,S_KEY>\\v *yyextra->s++ = '\v'; +<S_STR,S_KEY>\\e *yyextra->s++ = '\033'; -<S_STR,S_KEY>. *s++ = yytext[0]; +<S_STR,S_KEY>. *yyextra->s++ = yytext[0]; xkb_keymap return XKB_KEYMAP; xkb_keycodes return XKB_KEYCODES; @@ -140,19 +150,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; } @@ -183,66 +192,72 @@ alternate_group return ALTERNATE_GROUP; %% void -yyerror(const char *s) +yyerror(YYLTYPE *loc, void *scanner, const char *msg) { + struct scanner_extra *extra = yyget_extra(scanner); + if (warningLevel>0) { - (void)fprintf(stderr,"%s: line %d of %s\n",s,yylineno, - (scanFile?scanFile:"(unknown)")); - if ((warningLevel>3)) - (void)fprintf(stderr,"last scanned symbol is: %s\n",scanBuf); + 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(char *file, int lineno) -{ - yylineno = 1; - if (scanFile) - free(scanFile); - scanFile = strdup(file); } int -XKBParseString(const char *string, XkbFile ** pRtrn) +XKBParseString(const char *string, const char *fileName, XkbFile ** pRtrn) { + int ret; + struct parser_param param; + struct scanner_extra extra; YY_BUFFER_STATE state; *pRtrn = NULL; if (string == NULL) - return 1; - - state = yy_scan_string(string); - rtrnValue = NULL; - if (yyparse() != 0) - return 0; + return 1; - yy_delete_buffer(state); - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - *pRtrn = rtrnValue; - CheckDefaultMap(rtrnValue); - rtrnValue = NULL; + memset(&extra, 0, sizeof(extra)); + if (yylex_init_extra(&extra, ¶m.scanner) != 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; + CheckDefaultMap(param.rtrn, fileName); + *pRtrn = param.rtrn; return 1; } int -XKBParseFile(FILE * file, XkbFile ** pRtrn) +XKBParseFile(FILE * file, const char *fileName, XkbFile ** pRtrn) { - if (file) - { - yyin = file; - yystring = NULL; - rtrnValue = NULL; - if (yyparse() == 0) - { - *pRtrn = rtrnValue; - CheckDefaultMap(rtrnValue); - rtrnValue = NULL; - return 1; - } - *pRtrn = NULL; - return 0; - } + int ret; + struct parser_param param; + struct scanner_extra extra; + *pRtrn = NULL; + if (file == NULL) + return 1; + + 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; + + CheckDefaultMap(param.rtrn, fileName); + *pRtrn = param.rtrn; return 1; } -- 1.7.9.2 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
