compose: correctly parse modifier syntax

As described in:
http://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=ddf3b09bb262d01b56fbaade421ac85b0e60a69f

Signed-off-by: Ran Benita <ran234@gmail.com>
master
Ran Benita 2015-03-24 16:40:29 +02:00
parent c8c41c0160
commit 8e1fed6c68
2 changed files with 35 additions and 18 deletions

View File

@ -113,8 +113,9 @@ cached_keysym_from_name(struct keysym_from_name_cache *cache,
* COMMENT ::= "#" {<any character except null or newline>} * COMMENT ::= "#" {<any character except null or newline>}
* LHS ::= EVENT { EVENT } * LHS ::= EVENT { EVENT }
* EVENT ::= [MODIFIER_LIST] "<" keysym ">" * EVENT ::= [MODIFIER_LIST] "<" keysym ">"
* MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None" * MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None"
* MODIFIER ::= ["~"] modifier_name * MODIFIER ::= ["~"] MODIFIER_NAME
* MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta")
* RHS ::= ( STRING | keysym | STRING keysym ) * RHS ::= ( STRING | keysym | STRING keysym )
* STRING ::= '"' { CHAR } '"' * STRING ::= '"' { CHAR } '"'
* CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
@ -357,8 +358,9 @@ struct production {
bool has_keysym; bool has_keysym;
bool has_string; bool has_string;
xkb_mod_mask_t mods; /* The matching is as follows: (active_mods & modmask) == mods. */
xkb_mod_mask_t modmask; xkb_mod_mask_t modmask;
xkb_mod_mask_t mods;
}; };
static uint32_t static uint32_t
@ -456,6 +458,9 @@ add_production(struct xkb_compose_table *table, struct scanner *s,
} }
} }
/* Should match resolve_modifier(). */
#define ALL_MODS_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
static xkb_mod_index_t static xkb_mod_index_t
resolve_modifier(const char *name) resolve_modifier(const char *name)
{ {
@ -587,15 +592,16 @@ lhs_tok:
} }
goto rhs; goto rhs;
case TOK_IDENT: case TOK_IDENT:
if (!streq(val.string.str, "None")) { if (streq(val.string.str, "None")) {
scanner_err(s, "unrecognized identifier \"%s\"", val.string.str);
goto error;
}
production.mods = 0; production.mods = 0;
/* XXX Should only include the mods in resolve_mods(). */ production.modmask = ALL_MODS_MASK;
production.modmask = 0xff;
goto lhs_keysym; goto lhs_keysym;
}
goto lhs_mod_list_tok;
case TOK_TILDE:
goto lhs_mod_list_tok;
case TOK_BANG: case TOK_BANG:
production.modmask = ALL_MODS_MASK;
goto lhs_mod_list; goto lhs_mod_list;
default: default:
goto lhs_keysym_tok; goto lhs_keysym_tok;
@ -625,21 +631,22 @@ lhs_keysym_tok:
goto unexpected; goto unexpected;
} }
lhs_mod_list: { lhs_mod_list:
tok = lex(s, &val);
lhs_mod_list_tok: {
bool tilde = false; bool tilde = false;
xkb_mod_index_t mod; xkb_mod_index_t mod;
tok = lex(s, &val); if (tok != TOK_TILDE && tok != TOK_IDENT)
goto lhs_keysym_tok;
if (tok == TOK_TILDE) { if (tok == TOK_TILDE) {
tilde = true; tilde = true;
tok = lex(s, &val); tok = lex(s, &val);
} }
if (tok != TOK_IDENT) { if (tok != TOK_IDENT)
if (tilde || production.modmask == 0)
goto unexpected; goto unexpected;
goto lhs_keysym_tok;
}
mod = resolve_modifier(val.string.str); mod = resolve_modifier(val.string.str);
if (mod == XKB_MOD_INVALID) { if (mod == XKB_MOD_INVALID) {

View File

@ -434,6 +434,16 @@ test_modifier_syntax(struct xkb_context *ctx)
assert(test_compose_seq_buffer(ctx, assert(test_compose_seq_buffer(ctx,
"None <A> : X \n" "None <A> : X \n"
"Shift <B> : Y \n"
"Ctrl <C> : Y \n"
"Alt <D> : Y \n"
"Caps <E> : Y \n"
"Lock <F> : Y \n"
"Shift Ctrl <G> : Y \n"
"~Shift <H> : Y \n"
"~Shift Ctrl <I> : Y \n"
"Shift ~Ctrl <J> : Y \n"
"Shift ~Ctrl ~Alt <K> : Y \n"
"! Shift <B> : Y \n" "! Shift <B> : Y \n"
"! Ctrl <C> : Y \n" "! Ctrl <C> : Y \n"
"! Alt <D> : Y \n" "! Alt <D> : Y \n"
@ -454,7 +464,7 @@ test_modifier_syntax(struct xkb_context *ctx)
"! None <A> : X \n" "! None <A> : X \n"
"! Foo <B> : X \n" "! Foo <B> : X \n"
"None ! Shift <C> : X \n" "None ! Shift <C> : X \n"
"! <D> : X \n" "! ! <D> : X \n"
"! ~ <E> : X \n" "! ~ <E> : X \n"
"! ! <F> : X \n" "! ! <F> : X \n"
"! Ctrl ! Ctrl <G> : X \n" "! Ctrl ! Ctrl <G> : X \n"