[PATCH xfree86] Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>

Oleh Nykyforchyn oleh.nyk at gmail.com
Tue May 24 08:42:00 PDT 2011


On Tue, 24 May 2011 05:54:33 -0700
Dan Nicholson <dbn.lists at gmail.com> wrote:

> The man page does say what type of matching each uses, but it's still
> not that discoverable.
You are right, it's my fault that I missed this info.

> > What do You think about such an approach?
> 
> Frankly, I'm not crazy about it for two reasons. First, it's another
> magic sequence to parse out and handle and attempt to explain to
> people. The |regex| syntax is something new that no one would know
> about. The only regex syntax I can think of that applies and people
> are familiar with is awk's /regex/, and the /s would conflict with
> other valid uses of the argument.
We can point everybody to 'man 7 regex'.

> Second, what if I as a user have the
> reasonable thought that I want to have multiple regexs to match
> against like the non-regex matching? MatchProduct "foo|bar" works, but
> why not MatchProduct "|foo|bar|"? 
"foo|bar" is a pretty legal regex, hence the both variants are equivalent.

> Not to mention that you can
> currently have "|foo|" and the code will just treat it as a single
> normal argument (run that through strtok with '|' as the delimiter).
You are right again. But my suggestion is to remove outmost '|' _before_
running strtok().

> To put it in programming terms, which of the following two APIs would
> you want to use?
> 
> 1. Single overloaded argument which changes behavior based on certain values
> 
> 2. Optional second argument that specifies the desired behavior
> 
> I'm pretty sure I'm going with #2. I can't see a reason why "put in
> magic characters to get a regex" is better than "add an argument
> specifying a regex". What am I missing?
Tastes differ, probably most people will prefer Your version.

Just for tryout, here is a quick version of a patch, which implements
my idea (seems to work for me on Linux, over the three my previous patches). 



Add option to use extended regex expresssions in Match* statements

If a pattern list is of the form "|str|", then str is treated
as a single extended regular expression (with two |-s dropped)

Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>
---
 hw/xfree86/common/xf86Xinput.c |   26 +++++++++++++++
 hw/xfree86/parser/InputClass.c |   67 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 88cf292..54583ff 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -85,6 +85,9 @@
 #include <ptrveloc.h>          /* dix pointer acceleration */
 #include <xserver-properties.h>
 
+#include <sys/types.h>  /* MatchAttrToken */
+#include <regex.h>
+
 #ifdef XFreeXDGA
 #include "dgaproc.h"
 #endif
@@ -509,6 +512,29 @@ MatchAttrToken(const char *attr, struct list *patterns,
         char * const *cur;
         Bool match = FALSE;
 
+        cur = group->values;
+        if ((cur[0]) && (!*cur[0]) && /* cur[0] == "" */
+            (cur[1]) &&               /* cur[1] == regex */
+            (cur[2]) && (!*cur[2]) && /* cur[2] == "" */
+            (cur[3] == NULL)) {
+            /* Treat this statement as a regex match */
+            regex_t buf;
+            int r;
+            r = regcomp(&buf, cur[1], REG_EXTENDED | REG_NOSUB);
+            if (r) { /* bad regex */
+                regfree(&buf);
+                xf86Msg(X_ERROR, "Wrong regex: \"%s\"\n", cur[1]);
+                return FALSE;
+            }
+            xf86Msg(X_CONFIG, "Applying regex \"%s\" to attribute \"%s\"\n", cur[1], attr);
+            r = regexec(&buf, attr, 0, NULL, 0);
+            regfree(&buf);
+            if (r)
+                return FALSE;
+            else
+                return TRUE;
+        }
+
         for (cur = group->values; *cur; cur++) {
             if (**cur == '!') {
             /*
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index 3f80170..3977b33 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -66,6 +66,55 @@ xf86ConfigSymTabRec InputClassTab[] =
 
 #define TOKEN_SEP "|"
 
+/*
+ * Tokenize a string into a NULL terminated array of strings. The same that
+ * xstrtokenize unless the first and the last chars of str are in separators,
+ * then treat str as "[sep]regex[sep]", drop the two outmost chars and return
+ * {"", regex, "", NULL}.
+ */
+static char**
+rstrtokenize(const char *str, const char *separators)
+{
+    unsigned n;
+
+    if (!str)
+        return NULL;
+    n = strlen(str);
+    if ((n > 1) && strchr(separators, str[0]) && strchr(separators, str[n-1])){
+        char **list;
+        /* int r; */
+        /* regex_t buf; */
+
+        list = calloc(4, sizeof(*list));
+        if (!list)
+            return NULL;
+        list[0] = strdup("");
+        list[1] = calloc(n-1, sizeof(char));
+        list[2] = strdup("");
+        if (!list[0] || !list[1] || !list[2])
+            goto error;
+        strncpy(list[1], str+1, n-2);
+/*
+ *        // Verify in advance or wait until match?
+ *        r = regcomp(&buf, list[1], REG_EXTENDED);
+ *        regfree(&buf);
+ *        if (r) {
+ *            xf86Message(X_ERROR, "Wrong regex: \"%s\"\n", list[1]);
+ *            goto error;
+ *        }
+ */
+        return list;
+
+    error:
+        if (list[0]) free(list[0]);
+        if (list[1]) free(list[1]);
+        if (list[2]) free(list[2]);
+        free(list);
+        return NULL;
+    }
+    return xstrtokenize(str, separators);
+}
+
 static void
 add_group_entry(struct list *head, char **values)
 {
@@ -127,55 +176,55 @@ xf86parseInputClassSection(void)
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchProduct");
             add_group_entry(&ptr->match_product,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_VENDOR:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchVendor");
             add_group_entry(&ptr->match_vendor,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_DEVICE_PATH:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchDevicePath");
             add_group_entry(&ptr->match_device,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_OS:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchOS");
             add_group_entry(&ptr->match_os,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_PNPID:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchPnPID");
             add_group_entry(&ptr->match_pnpid,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_USBID:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchUSBID");
             add_group_entry(&ptr->match_usbid,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_DRIVER:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchDriver");
             add_group_entry(&ptr->match_driver,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_TAG:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchTag");
             add_group_entry(&ptr->match_tag,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_LAYOUT:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchLayout");
             add_group_entry(&ptr->match_layout,
-                            xstrtokenize(val.str, TOKEN_SEP));
+                            rstrtokenize(val.str, TOKEN_SEP));
             break;
         case MATCH_IS_KEYBOARD:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
-- 
1.6.4

-- 
Oleh Nykyforchyn <oleh.nyk at gmail.com>


More information about the xorg-devel mailing list