[PATCH 2/3] xserver: Introduce negated conditions in Match patterns

Oleh Nykyforchyn oleh.nyk at gmail.com
Thu Jun 9 07:56:57 PDT 2011


xserver: Introduce negated conditions in Match patterns

When processing input devices, it is useful to determine not only which
attributes are to be accepted, but also which are to be rejected. Hence we introduce
an '!' prefix, before a pattern, which means that if an attribute matches this
pattern, then the respective device is rejected by this InputClass. To allow
statements like
    MatchVendor "!Asus|!Logitech"
(I did not want to offend any vendor), we also accept the rule of "last pattern":
if the end of an entry is reached, then the last pattern is decisive.

Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>
---
 hw/xfree86/common/xf86Xinput.c |   15 ++++++++++++---
 hw/xfree86/man/xorg.conf.man   |   19 ++++++++++++-------
 hw/xfree86/parser/InputClass.c |   10 ++++++++++
 hw/xfree86/parser/xf86Parser.h |    1 +
 4 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6e796ae..42ab747 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -509,10 +509,19 @@ MatchAttrToken(const char *attr, struct list *groups)
         Bool match = FALSE;
 
         list_for_each_entry(pattern, &group->patterns, entry) {
-            if (match_token(attr, pattern)) {
-                match = TRUE;
-                break;
+            match = match_token(attr, pattern);
+            if (match) {                  /* success? */
+                if (pattern->is_negated)  /* negated pattern matched */
+                    match = FALSE;        /* failure */
+                break;                    /* leave the entry */
+            }
+            else {
+                if (pattern->is_negated)  /* at least negated pattern not */
+                    match = TRUE;         /*   matched - partial success */
+                /* else non-negated pattern not matched */
+                /*  match = FALSE;         */
             }
+             /* no success yet, continue */
         }
         if (!match)
             return FALSE;
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index df35178..d88db61 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -1072,9 +1072,13 @@ There are two types of match entries used in
 sections. The first allows attributes of the device to be matched against
 various patterns. An entry can be constructed to match attributes from
 different devices by supplying several (at least one) patterns, which are
-applied to each attribute in the order of appearance in the entry. Hence
+applied to each attribute in the order of appearance in the entry. Usually,
 an attribute that matches a pattern is accepted, and further patterns
-are not considered.
+are not considered. A pattern prepended with '!' is negated, which means
+that an attribute that matches it is rejected (this does not affect
+attributes accepted by previous patterns). If the end of an entry is
+reached, everything is determined by the last (not matched) pattern: if it
+is negated, the attribute is accepted, otherwise it is rejected.
 .PP
 Multiple entries of the same type may appear in one
 .B InputClass
@@ -1085,9 +1089,10 @@ attribute. For example:
 .nf
 .B  "Section \*qInputClass\*q"
 .B  "    Identifier   \*qMy Class\*q"
-.B  "    # product string must contain example
-.B  "    # and either gizmo or gadget
-.B  "    MatchProduct \*qexample\*q
+.B  "    # product string must not contain wrong,
+.B  "    # must contain example, and
+.B  "    # either gizmo or gadget
+.B  "    MatchProduct \*q!wrong\*q \*qexample\*q
 .B  "    MatchProduct \*qgizmo\*q \*qgadget\*q
 .I  "    ..."
 .B  "EndSection"
@@ -1162,11 +1167,11 @@ entry can look like
 .PP
 .RS 4
 .nf
-.B  "    MatchProduct \*qUSB Optical Mouse|Touchpad\*q"
+.B  "    MatchProduct \*q!USB|Optical Mouse|Touchpad\*q"
 .fi
 .RE
 .PP
-and select USB optical mice and touchpads.
+and select non-USB optical mice and touchpads.
 
 The second type of entry is used to match device types. These entries take a
 boolean argument similar to
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index c1a9a13..3475de2 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -66,6 +66,8 @@ xf86ConfigSymTabRec InputClassTab[] =
 
 #define TOKEN_SEP '|'
 
+#define NEG_FLAG '!'
+
 
 static void
 add_to_group(xf86MatchGroup **group, const char *str,
@@ -90,6 +92,12 @@ add_to_group(xf86MatchGroup **group, const char *str,
         return;
     list_add(&pattern->entry, &(*group)->patterns);
 
+    /* Pattern starting with '!' should NOT be matched */
+    if (*str == NEG_FLAG) {
+        pattern->is_negated = TRUE;
+        str++;
+    }
+
     pattern->mode = pref_mode;
 
     if ((next = index(str, TOKEN_SEP)))
@@ -329,6 +337,8 @@ print_pattern(FILE * cf, const xf86MatchPattern *pattern)
     if (!pattern) return;
 
     fprintf(cf, "\"");
+    if (pattern->is_negated)
+        fprintf(cf, "%c", NEG_FLAG);
     if (pattern->mode == MATCH_IS_INVALID)
         fprintf(cf, "invalid:");
     if (pattern->str)
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index b02923f..faf5ab8 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -360,6 +360,7 @@ xf86MatchMode;
 typedef struct
 {
 	struct list entry;
+	Bool is_negated;
 	xf86MatchMode mode;
 	char *str;
 }
-- 
1.6.4



More information about the xorg-devel mailing list