From 8e1fed6c68ca23d8a6f31c30e36417f4c07274b1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 24 Mar 2015 16:40:29 +0200 Subject: [PATCH] compose: correctly parse modifier syntax As described in: http://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=ddf3b09bb262d01b56fbaade421ac85b0e60a69f Signed-off-by: Ran Benita --- src/compose/parser.c | 41 ++++++++++++++++++++++++----------------- test/compose.c | 12 +++++++++++- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/compose/parser.c b/src/compose/parser.c index 95f0fdd..9e936a9 100644 --- a/src/compose/parser.c +++ b/src/compose/parser.c @@ -113,8 +113,9 @@ cached_keysym_from_name(struct keysym_from_name_cache *cache, * COMMENT ::= "#" {} * LHS ::= EVENT { EVENT } * EVENT ::= [MODIFIER_LIST] "<" keysym ">" - * MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None" - * MODIFIER ::= ["~"] modifier_name + * MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None" + * MODIFIER ::= ["~"] MODIFIER_NAME + * MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta") * RHS ::= ( STRING | keysym | STRING keysym ) * STRING ::= '"' { CHAR } '"' * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR @@ -357,8 +358,9 @@ struct production { bool has_keysym; 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 mods; }; 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 resolve_modifier(const char *name) { @@ -587,15 +592,16 @@ lhs_tok: } goto rhs; case TOK_IDENT: - if (!streq(val.string.str, "None")) { - scanner_err(s, "unrecognized identifier \"%s\"", val.string.str); - goto error; + if (streq(val.string.str, "None")) { + production.mods = 0; + production.modmask = ALL_MODS_MASK; + goto lhs_keysym; } - production.mods = 0; - /* XXX Should only include the mods in resolve_mods(). */ - production.modmask = 0xff; - goto lhs_keysym; + goto lhs_mod_list_tok; + case TOK_TILDE: + goto lhs_mod_list_tok; case TOK_BANG: + production.modmask = ALL_MODS_MASK; goto lhs_mod_list; default: goto lhs_keysym_tok; @@ -625,21 +631,22 @@ lhs_keysym_tok: goto unexpected; } -lhs_mod_list: { +lhs_mod_list: + tok = lex(s, &val); +lhs_mod_list_tok: { bool tilde = false; xkb_mod_index_t mod; - tok = lex(s, &val); + if (tok != TOK_TILDE && tok != TOK_IDENT) + goto lhs_keysym_tok; + if (tok == TOK_TILDE) { tilde = true; tok = lex(s, &val); } - if (tok != TOK_IDENT) { - if (tilde || production.modmask == 0) - goto unexpected; - goto lhs_keysym_tok; - } + if (tok != TOK_IDENT) + goto unexpected; mod = resolve_modifier(val.string.str); if (mod == XKB_MOD_INVALID) { diff --git a/test/compose.c b/test/compose.c index 9bbef18..d9f3629 100644 --- a/test/compose.c +++ b/test/compose.c @@ -434,6 +434,16 @@ test_modifier_syntax(struct xkb_context *ctx) assert(test_compose_seq_buffer(ctx, "None : X \n" + "Shift : Y \n" + "Ctrl : Y \n" + "Alt : Y \n" + "Caps : Y \n" + "Lock : Y \n" + "Shift Ctrl : Y \n" + "~Shift : Y \n" + "~Shift Ctrl : Y \n" + "Shift ~Ctrl : Y \n" + "Shift ~Ctrl ~Alt : Y \n" "! Shift : Y \n" "! Ctrl : Y \n" "! Alt : Y \n" @@ -454,7 +464,7 @@ test_modifier_syntax(struct xkb_context *ctx) "! None : X \n" "! Foo : X \n" "None ! Shift : X \n" - "! : X \n" + "! ! : X \n" "! ~ : X \n" "! ! : X \n" "! Ctrl ! Ctrl : X \n" -- 2.7.4