Resolve keysyms early in parser

Instead of having the parser passing strings to the AST, and
symbols/compat etc. resolving them themselves. This simplifies the code
a bit, and makes it possible to print where exactly in the file the bad
keysym originates from.

The previous lazy approach had an advantage of not needlessly resolving
keysyms from unrelated maps. However, I think reporting these errors in
*any* map is better, and the parser is also a bit smarter then old
xkbcomp and doesn't parse many useless maps. So there's no discernible
speed/memory difference with this change.

Signed-off-by: Ran Benita <ran234@gmail.com>
master
Ran Benita 2013-11-27 13:49:13 +02:00
parent ba7530fa90
commit 9dc5b8cb60
7 changed files with 64 additions and 81 deletions

View File

@ -201,7 +201,7 @@ BoolVarCreate(xkb_atom_t nameToken, unsigned set)
}
InterpDef *
InterpCreate(char *sym, ExprDef *match)
InterpCreate(xkb_keysym_t sym, ExprDef *match)
{
InterpDef *def = malloc(sizeof(*def));
if (!def)
@ -329,7 +329,7 @@ ActionCreate(xkb_atom_t name, ExprDef *args)
}
ExprDef *
CreateKeysymList(char *sym)
CreateKeysymList(xkb_keysym_t sym)
{
ExprDef *def;
@ -360,7 +360,7 @@ CreateMultiKeysymList(ExprDef *list)
}
ExprDef *
AppendKeysymList(ExprDef *list, char *sym)
AppendKeysymList(ExprDef *list, xkb_keysym_t sym)
{
size_t nSyms = darray_size(list->value.list.syms);
@ -549,8 +549,6 @@ err:
static void
FreeExpr(ExprDef *expr)
{
char **sym;
if (!expr)
return;
@ -581,8 +579,6 @@ FreeExpr(ExprDef *expr)
break;
case EXPR_KEYSYM_LIST:
darray_foreach(sym, expr->value.list.syms)
free(*sym);
darray_free(expr->value.list.syms);
darray_free(expr->value.list.symsMapIndex);
darray_free(expr->value.list.symsNumEntries);
@ -640,7 +636,6 @@ FreeStmt(ParseCommon *stmt)
FreeStmt(&u.keyType->body->common);
break;
case STMT_INTERP:
free(u.interp->sym);
FreeStmt(&u.interp->match->common);
FreeStmt(&u.interp->def->common);
break;

View File

@ -56,7 +56,7 @@ VarDef *
BoolVarCreate(xkb_atom_t nameToken, unsigned set);
InterpDef *
InterpCreate(char *sym, ExprDef *match);
InterpCreate(xkb_keysym_t sym, ExprDef *match);
KeyTypeDef *
KeyTypeCreate(xkb_atom_t name, VarDef *body);
@ -83,13 +83,13 @@ ExprDef *
CreateMultiKeysymList(ExprDef *list);
ExprDef *
CreateKeysymList(char *sym);
CreateKeysymList(xkb_keysym_t sym);
ExprDef *
AppendMultiKeysymList(ExprDef *list, ExprDef *append);
ExprDef *
AppendKeysymList(ExprDef *list, char *sym);
AppendKeysymList(ExprDef *list, xkb_keysym_t sym);
IncludeStmt *
IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge);

View File

@ -181,7 +181,7 @@ typedef struct _Expr {
struct _Expr *args;
} action;
struct {
darray(char *) syms;
darray(xkb_keysym_t) syms;
darray(int) symsMapIndex;
darray(unsigned int) symsNumEntries;
} list;
@ -252,7 +252,7 @@ typedef struct {
typedef struct {
ParseCommon common;
enum merge_mode merge;
char *sym;
xkb_keysym_t sym;
ExprDef *match;
VarDef *def;
} InterpDef;

View File

@ -840,15 +840,7 @@ HandleInterpDef(CompatInfo *info, InterpDef *def, enum merge_mode merge)
si = info->default_interp;
si.merge = merge = (def->merge == MERGE_DEFAULT ? merge : def->merge);
if (!LookupKeysym(def->sym, &si.interp.sym)) {
log_err(info->keymap->ctx,
"Could not resolve keysym %s; "
"Symbol interpretation ignored\n",
def->sym);
return false;
}
si.interp.sym = def->sym;
si.interp.match = pred;
si.interp.mods = mods;

View File

@ -43,11 +43,47 @@ struct parser_param {
};
static void
_xkbcommon_error(struct parser_param *param, const char *msg)
parser_error(struct parser_param *param, const char *msg)
{
scanner_error(param->scanner, msg);
}
static void
parser_warn(struct parser_param *param, const char *msg)
{
scanner_warn(param->scanner, msg);
}
static void
_xkbcommon_error(struct parser_param *param, const char *msg)
{
parser_error(param, msg);
}
static bool
resolve_keysym(const char *str, xkb_keysym_t *sym_rtrn)
{
xkb_keysym_t sym;
if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
*sym_rtrn = XKB_KEY_NoSymbol;
return true;
}
if (istreq(str, "none") || istreq(str, "voidsymbol")) {
*sym_rtrn = XKB_KEY_VoidSymbol;
return true;
}
sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS);
if (sym != XKB_KEY_NoSymbol) {
*sym_rtrn = sym;
return true;
}
return false;
}
#define scanner param->scanner
%}
@ -137,6 +173,7 @@ _xkbcommon_error(struct parser_param *param, const char *msg)
xkb_atom_t sval;
enum merge_mode merge;
enum xkb_map_flags mapFlags;
xkb_keysym_t keysym;
ParseCommon *any;
ExprDef *expr;
VarDef *var;
@ -163,8 +200,9 @@ _xkbcommon_error(struct parser_param *param, const char *msg)
%type <file_type> XkbCompositeType FileType
%type <uval> DoodadType
%type <mapFlags> Flag Flags OptFlags
%type <str> MapName OptMapName KeySym
%type <str> MapName OptMapName
%type <sval> FieldSpec Ident Element String
%type <keysym> KeySym
%type <any> DeclList Decl
%type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
%type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
@ -707,18 +745,23 @@ KeySyms : OBRACE KeySymList CBRACE
{ $$ = $2; }
;
KeySym : IDENT { $$ = $1; }
| SECTION { $$ = strdup("section"); }
KeySym : IDENT
{
if (!resolve_keysym($1, &$$))
parser_warn(param, "unrecognized keysym");
free($1);
}
| SECTION { $$ = XKB_KEY_section; }
| Integer
{
if ($1 < 10) { /* XK_0 .. XK_9 */
$$ = malloc(2);
$$[0] = $1 + '0';
$$[1] = '\0';
if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
$$ = XKB_KEY_0 + $1;
}
else {
$$ = malloc(17);
snprintf($$, 17, "0x%x", $1);
char buf[17];
snprintf(buf, sizeof(buf), "0x%x", $1);
if (!resolve_keysym(buf, &$$))
parser_warn(param, "unrecognized keysym");
}
}
;

View File

@ -626,30 +626,6 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return true;
}
bool
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn)
{
xkb_keysym_t sym;
if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
*sym_rtrn = XKB_KEY_NoSymbol;
return true;
}
if (istreq(str, "none") || istreq(str, "voidsymbol")) {
*sym_rtrn = XKB_KEY_VoidSymbol;
return true;
}
sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS);
if (sym != XKB_KEY_NoSymbol) {
*sym_rtrn = sym;
return true;
}
return false;
}
static bool
AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
ExprDef *value)
@ -703,28 +679,8 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms));
for (j = 0; j < leveli->num_syms; j++) {
char *sym_name = darray_item(value->value.list.syms,
sym_index + j);
xkb_keysym_t keysym;
if (!LookupKeysym(sym_name, &keysym)) {
const char *group_name = "unnamed";
if (ndx < darray_size(info->group_names) &&
darray_item(info->group_names, ndx))
group_name = xkb_atom_text(info->keymap->ctx,
darray_item(info->group_names,
ndx));
log_warn(info->keymap->ctx,
"Could not resolve keysym %s for key %s, group %u (%s), level %u\n",
sym_name, KeyInfoText(info, keyi), ndx + 1,
group_name, i);
ClearLevelInfo(leveli);
leveli->num_syms = 0;
break;
}
xkb_keysym_t keysym = darray_item(value->value.list.syms,
sym_index + j);
if (leveli->num_syms == 1) {
if (keysym == XKB_KEY_NoSymbol)

View File

@ -79,9 +79,6 @@ bool
CompileKeymap(XkbFile *file, struct xkb_keymap *keymap,
enum merge_mode merge);
bool
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
/***====================================================================***/
static inline bool