[PATCH 2/2 v2] xserver: Use extended regular expressions in Match entries
Oleh Nykyforchyn
oleh.nyk at gmail.com
Sun Oct 30 05:03:55 PDT 2011
Small fixes:
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,
an InputClass with
MatchLayout "regex:/^Seat[0-5]$/"
is applied to a device only in layouts Seat0, Seat1, ..., Seat5. In particular,
this can allow for path matching on systems without fnmatch(). A regular
expression is compiled only before its first use.
Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>
---
hw/xfree86/common/xf86Xinput.c | 23 +++++++++++++++++++--
hw/xfree86/man/xorg.conf.man | 19 ++++++++++++++++++
hw/xfree86/parser/InputClass.c | 41 ++++++++++++++++++++++++++++++++++++---
hw/xfree86/parser/xf86Parser.h | 7 +++++-
message | 11 ++++++++++
5 files changed, 93 insertions(+), 8 deletions(-)
create mode 100644 message
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index d39ab89..88909ed 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -474,7 +474,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)
@@ -505,9 +507,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 996798f..31b4cfc 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -1146,6 +1146,25 @@ if no named
.B ServerLayout
sections have been found.
.PP
+To apply more sophicticated conditions, an entire attribute can be matched
+against an extended regular expression (see
+.BR regex (7)
+):
+.PP
+.RS 4
+.nf
+.B " # product string must start with Experimental
+.B " # and end with Device
+.B " MatchProduct \*qregex:_^Experimental.*Device$_\*q"
+.fi
+.RE
+.PP
+Such a pattern is prefixed with "regex:", and the next character, which
+may be arbitrary, is used as a two-side delimiter, i.e. the regular
+expression starts after it and lasts until its next occurrence, or to
+the end of the argument, if the delimiting character has not been found
+again.
+.PP
The second type of entry is used to match device types. These entries take a
boolean argument similar to
.B Option
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index f4b080f..eba97f8 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -66,6 +66,8 @@ xf86ConfigSymTabRec InputClassTab[] =
#define TOKEN_SEP "|"
+#define REGEX_PREFIX "regex:"
+
static void
free_group(xf86MatchGroup *group)
{
@@ -74,6 +76,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);
@@ -103,11 +109,32 @@ create_group(const char *str,
}
list_add(&pattern->entry, &group->patterns);
- pattern->mode = pref_mode;
-
- n = strcspn(str, TOKEN_SEP);
+ /* Check if there is a mode prefix */
+ if (!strncmp(str,REGEX_PREFIX,strlen(REGEX_PREFIX))) {
+ pattern->mode = MATCH_IS_REGEX;
+ str += strlen(REGEX_PREFIX);
+ if (*str) {
+ char *last;
+ last = strchr(str+1, *str);
+ if (last)
+ n = (last-str)-1;
+ else
+ n = strlen(str+1);
+ pattern->str = strndup(str+1, n);
+ str += n+1;
+ if (*str) str++;
+ }
+ else
+ pattern->str = NULL;
+ }
+ else {
+ pattern->mode = pref_mode;
+ n = strcspn(str, TOKEN_SEP);
+ pattern->str = strndup(str, n);
+ str += n;
+ }
- if ((pattern->str = strndup(str, n)) == NULL)
+ if (pattern->str == NULL)
pattern->mode = MATCH_IS_INVALID;
if (*str != '\0') {
@@ -319,10 +346,16 @@ print_pattern(FILE * cf, const xf86MatchPattern *pattern)
if (pattern->mode == MATCH_IS_INVALID)
fprintf(cf, "invalid:");
+ else
+ if (pattern->mode == MATCH_IS_REGEX)
+ /* FIXME: Hope there is no '_' in the pattern */
+ fprintf(cf, REGEX_PREFIX "_");
if (pattern->str)
fprintf(cf, "%s", pattern->str);
else
fprintf(cf, "(none)");
+ if (pattern->mode == MATCH_IS_REGEX)
+ fprintf(cf, "_");
if (pattern->entry.next)
fprintf(cf, "%s", TOKEN_SEP);
}
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index b02923f..294ae30 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;
@@ -362,6 +366,7 @@ typedef struct
struct list entry;
xf86MatchMode mode;
char *str;
+ regex_t *regex;
}
xf86MatchPattern;
diff --git a/message b/message
new file mode 100644
index 0000000..c31c11f
--- /dev/null
+++ b/message
@@ -0,0 +1,11 @@
+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,
+an InputClass with
+ MatchLayout "regex:/^Seat[0-5]$/"
+is applied to a device only in layouts Seat0, Seat1, ..., Seat5. In particular,
+this can allow for path matching on systems without fnmatch(). A regular
+expression is compiled only before its first use.
+
--
1.7.4.4
--
Oleh Nykyforchyn <oleh.nyk at gmail.com>
More information about the xorg-devel
mailing list