[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