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 <ran234@gmail.com>
[daniels: Updated to current sources.]
{
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)
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;
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",
#endif
void
-CheckDefaultMap(XkbFile * maps)
+CheckDefaultMap(XkbFile * maps, const char *fileName)
{
XkbFile *dflt, *tmp;
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)"));
}
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;
#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 */
);
extern unsigned StmtSetMerge(ParseCommon * /* stmt */ ,
- unsigned /* merge */
+ unsigned /* merge */,
+ YYLTYPE * /* loc */,
+ void * /* scanner */
);
#ifdef DEBUG
#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 */ ,
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 */
err:
FreeXKBFile(file);
- free(scanFile);
XkbcFreeAllAtoms();
return xkb;
}
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;
}
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;
}
#include "XKBcommonint.h"
#include "xkbmisc.h"
-extern char *scanFile;
-
#define TypeUnknown 0
#define TypeBoolean 1
#define TypeInt 2
********************************************************/
+%{
+#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
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>
-extern int yylex(void);
-extern FILE *yyin;
-%}
%right EQUALS
%left PLUS MINUS
%left TIMES DIVIDE
%union {
int ival;
unsigned uval;
+ int64_t num;
char *str;
Atom sval;
ParseCommon *any;
void *geom;
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
%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
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
| 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;
}
}
;
{ $$= CreateKeysymList($1); }
;
-KeySym : IDENT { $$= strdup(scanBuf); }
+KeySym : IDENT { $$= $1; }
| SECTION { $$= strdup("section"); }
| Integer
{
| 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
#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
"//"[^\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 */
return ERROR_TOK;
}
- *s++ = result;
+ *yyextra->s++ = result;
}
<S_STR,S_KEY>\\[0-9]+ {
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;
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;
}
%%
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;
}