diff --git a/src/entry.c b/src/entry.c index e68ccfa..22b2788 100644 --- a/src/entry.c +++ b/src/entry.c @@ -121,6 +121,7 @@ int xcb_xrm_entry_parse(const char *_str, xcb_xrm_entry_t **_entry, bool resourc xcb_xrm_component_t *last; char *value; char *value_walk; + xcb_xrm_binding_type_t binding_type; xcb_xrm_entry_parser_state_t state = { .chunk = CS_INITIAL, @@ -166,8 +167,19 @@ int xcb_xrm_entry_parse(const char *_str, xcb_xrm_entry_t **_entry, bool resourc goto done_error; } + /* Subsequent bindings must be collapsed into a loose binding if at + * least one was a loose binding and a tight binding otherwise. */ + binding_type = (*walk == '*') ? BT_LOOSE : BT_TIGHT; + while (*(walk + 1) == '.' || *(walk + 1) == '*') { + walk++; + + if (*walk == '*') { + binding_type = BT_LOOSE; + } + } + xcb_xrm_finalize_component(entry, &state); - state.current_binding_type = (*walk == '.') ? BT_TIGHT : BT_LOOSE; + state.current_binding_type = binding_type; break; case '?': state.chunk = MAX(state.chunk, CS_COMPONENTS); diff --git a/tests/tests_match.c b/tests/tests_match.c index b2b2495..1841232 100644 --- a/tests/tests_match.c +++ b/tests/tests_match.c @@ -95,6 +95,7 @@ static int test_get_resource(void) { err |= check_get_resource("First.?.third: 1", "First.second.third", "", "1", false); err |= check_get_resource("First.?.?.fourth: 1", "First.second.third.fourth", "", "1", false); err |= check_get_resource("*second: 1", "First.second", "", "1", false); + err |= check_get_resource(".second: 1", "First.second", "", NULL, false); err |= check_get_resource("*third: 1", "First.second.third", "", "1", false); err |= check_get_resource("First*second: 1", "First.second", "", "1", false); err |= check_get_resource("First*third: 1", "First.second.third", "", "1", false); @@ -110,6 +111,17 @@ static int test_get_resource(void) { err |= check_get_resource("First:", "First", "", "", false); err |= check_get_resource("First: ", "First", "", "", false); err |= check_get_resource("First: \t ", "First", "", "", false); + /* Consecutive bindings */ + err |= check_get_resource("*.bar: 1", "foo.foo.bar", "", "1", false); + err |= check_get_resource("...bar: 1", "foo.bar", "", NULL, false); + err |= check_get_resource("...bar: 1", "foo.foo.foo.bar", "", NULL, false); + err |= check_get_resource("***bar: 1", "foo.bar", "", "1", false); + err |= check_get_resource(".*.bar: 1", "foo.bar", "", "1", false); + err |= check_get_resource(".*.bar: 1", "foo.foo.bar", "", "1", false); + err |= check_get_resource("..*bar: 1", "foo.foo.foo.foo.bar", "", "1", false); + err |= check_get_resource("a.*.z: 1", "a.b.c.d.e.f.z", "", "1", false); + err |= check_get_resource("a...z: 1", "a.z", "", "1", false); + err |= check_get_resource("a...z: 1", "a.b.z", "", NULL, false); /* Matching among multiple entries */ err |= check_get_resource( "First: 1\n"