[PATCH 3/3 v2'] xserver: Use extended regular expressions in Match entries
Oleh Nykyforchyn
oleh.nyk at gmail.com
Fri Jun 17 06:58:09 PDT 2011
xserver: Use extended regular expressions in Match entries
Together with "simple" matching modes (via strcmp() or fnmatch() etc), which
are natural for different types on input device attributes, it will be allowed
to match against extended regular expressions (cf. man 7 regex). For example,
MatchProduct "!regex:^USB" "regex:Optical Mouse$"
matches non-USB optical mice. Regex patterns can be arbitarily mixed with
"simple" ones.
Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>
---
hw/xfree86/common/xf86Xinput.c | 23 ++++++++++++++++++++---
hw/xfree86/man/xorg.conf.man | 17 +++++++++++++++--
hw/xfree86/parser/InputClass.c | 24 +++++++++++++++++++++---
hw/xfree86/parser/xf86Parser.h | 7 ++++++-
4 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 2cd1508..c417821 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -445,7 +445,9 @@ HostOS(void)
/*
* Match an attribute against a pattern. Matching mode is
- * determined by pattern->mode member.
+ * determined by pattern->mode member. If the mode is REGEX,
+ * then regex_t is allocated and compiled only during
+ * the first call, to save time and memory.
*/
static int
match_token(const char *attr, xf86MatchPattern *pattern)
@@ -476,9 +478,24 @@ match_token(const char *attr, xf86MatchPattern *pattern)
case MATCH_IS_PATHNAME:
return (strstr(attr, pattern->str)) ? -1 : 0;
#endif
+ case MATCH_IS_REGEX:
default:
- /* Impossible */
- return 0;
+ if (pattern->regex == NULL) {
+ int r;
+ if ((pattern->regex = malloc(sizeof(regex_t))) == NULL) {
+ pattern->mode = MATCH_IS_INVALID;
+ return 0;
+ }
+ r = regcomp(pattern->regex, pattern->str, REG_EXTENDED | REG_NOSUB);
+ if (r) { /* Wrong regex */
+ regfree(pattern->regex);
+ free(pattern->regex);
+ xf86Msg(X_ERROR, "Wrong regex: \"%s\"\n", pattern->str);
+ pattern->mode = MATCH_IS_INVALID;
+ return 0;
+ }
+ }
+ return (regexec(pattern->regex, attr,0, NULL, 0)) ? 0 : -1;
}
}
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index d88db61..c4324f2 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -1162,12 +1162,25 @@ if no named
.B ServerLayout
sections have been found.
.PP
-Finally, it is allowed to join via '|' any adjacent patterns, so a match
+To apply a more specific condition, e.g. to select devices with product
+names that start with "Advanced" and end with "Gadget", extended regular
+expressions (see
+.BR regex (7)
+), prefixed by "regex:", can be used as patterns:
+.PP
+.RS 4
+.nf
+.B " MatchProduct \*qregex:^Advanced.*Gadget$\*q"
+.fi
+.RE
+.PP
+Finally, it is allowed to join via '|' any adjacent patterns, except
+regular expressions, in which '|' has a special meaning, so a match
entry can look like
.PP
.RS 4
.nf
-.B " MatchProduct \*q!USB|Optical Mouse|Touchpad\*q"
+.B " MatchProduct \*q!regex:^USB\*q \*qOptical Mouse|Touchpad\*q"
.fi
.RE
.PP
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index dc641d1..2ca1e57 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -68,6 +68,8 @@ xf86ConfigSymTabRec InputClassTab[] =
#define NEG_FLAG '!'
+#define REGEX_PREFIX "regex:"
+
static void
add_to_group(xf86MatchGroup **group, const char *str,
@@ -98,12 +100,21 @@ add_to_group(xf86MatchGroup **group, const char *str,
str++;
}
- pattern->mode = pref_mode;
+ /* Check if there is a mode prefix */
+ if (!strncmp(str,REGEX_PREFIX,strlen(REGEX_PREFIX))) {
+ pattern->mode = MATCH_IS_REGEX;
+ str += strlen(REGEX_PREFIX);
+ }
+ else
+ pattern->mode = pref_mode;
- if ((next = index(str, TOKEN_SEP)))
+ if ((pattern->mode != MATCH_IS_REGEX) &&
+ (next = index(str, TOKEN_SEP)))
n = next-str;
- else
+ else {
n = strlen(str);
+ next = NULL;
+ }
if ((pattern->str = strndup(str, n)) == NULL)
pattern->mode = MATCH_IS_INVALID;
@@ -122,6 +133,10 @@ free_group(xf86MatchGroup *group)
list_del(&pattern->entry);
if (pattern->str)
free(pattern->str);
+ if ((pattern->mode == MATCH_IS_REGEX) && pattern->regex) {
+ regfree(pattern->regex);
+ free(pattern->regex);
+ }
free(pattern);
}
free(group);
@@ -341,6 +356,9 @@ print_pattern(FILE * cf, const xf86MatchPattern *pattern)
fprintf(cf, "%c", NEG_FLAG);
if (pattern->mode == MATCH_IS_INVALID)
fprintf(cf, "invalid:");
+ else
+ if (pattern->mode == MATCH_IS_REGEX)
+ fprintf(cf, "regex:");
if (pattern->str)
fprintf(cf, "%s\"", pattern->str);
else
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index faf5ab8..2d98992 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -68,6 +68,9 @@
#include "xf86Optrec.h"
#include "list.h"
+#include <sys/types.h>
+#include <regex.h>
+
#define HAVE_PARSER_DECLS
typedef struct
@@ -353,7 +356,8 @@ typedef enum
MATCH_IS_STRSTR,
MATCH_IS_STRCASESTR,
MATCH_IS_FILENAME,
- MATCH_IS_PATHNAME
+ MATCH_IS_PATHNAME,
+ MATCH_IS_REGEX
}
xf86MatchMode;
@@ -363,6 +367,7 @@ typedef struct
Bool is_negated;
xf86MatchMode mode;
char *str;
+ regex_t *regex;
}
xf86MatchPattern;
--
1.6.4
--
Oleh Nykyforchyn <oleh.nyk at gmail.com>
More information about the xorg-devel
mailing list