[PATCH 4/7] xfree86: Allow multiple arguments to InputClass matches
Peter Hutterer
peter.hutterer at who-t.net
Tue Feb 9 21:36:47 PST 2010
From: Dan Nicholson <dbn.lists at gmail.com>
In order to keep the number of InputClass sections manageable, allow
matches to contain multiple arguments. The arguments will be separated
by the '|' character. This allows a policy to apply to multiple types of
devices. For example:
Section "InputClass"
Identifier "Inverted Mice"
MatchProduct "Crazy Mouse|Silly Mouse"
Option "InvertX" "yes"
EndSection
This applies to the MatchProduct, MatchVendor and MatchDevicePath
entries. Currently there is no way to escape characters, so names or
patterns cannot contain '|'.
Signed-off-by: Dan Nicholson <dbn.lists at gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
---
hw/xfree86/common/xf86Xinput.c | 51 ++++++++++++++----
hw/xfree86/doc/man/xorg.conf.man.pre | 9 ++-
hw/xfree86/parser/InputClass.c | 99 +++++++++++++++++++++++++++++----
hw/xfree86/parser/xf86Parser.h | 6 +-
4 files changed, 136 insertions(+), 29 deletions(-)
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index b37dae6..8ac9d26 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -502,20 +502,49 @@ AddOtherInputDevices(void)
static Bool
InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
{
- if (iclass->match_product &&
- (!attrs->product || !strstr(attrs->product, iclass->match_product)))
- return FALSE;
- if (iclass->match_vendor &&
- (!attrs->vendor || !strstr(attrs->vendor, iclass->match_vendor)))
- return FALSE;
- if (iclass->match_device &&
+ char **cur;
+ Bool match;
+
+ if (iclass->match_product) {
+ if (!attrs->product)
+ return FALSE;
+ /* see if any of the values match */
+ for (cur = iclass->match_product, match = FALSE; *cur; cur++)
+ if (strstr(attrs->product, *cur)) {
+ match = TRUE;
+ break;
+ }
+ if (!match)
+ return FALSE;
+ }
+ if (iclass->match_vendor) {
+ if (!attrs->vendor)
+ return FALSE;
+ /* see if any of the values match */
+ for (cur = iclass->match_vendor, match = FALSE; *cur; cur++)
+ if (strstr(attrs->vendor, *cur)) {
+ match = TRUE;
+ break;
+ }
+ if (!match)
+ return FALSE;
+ }
+ if (iclass->match_device) {
+ if (!attrs->device)
+ return FALSE;
+ /* see if any of the values match */
+ for (cur = iclass->match_device, match = FALSE; *cur; cur++)
#ifdef HAVE_FNMATCH_H
- (!attrs->device ||
- fnmatch(iclass->match_device, attrs->device, 0) != 0))
+ if (fnmatch(*cur, attrs->device, 0) == 0) {
#else
- (!attrs->device || !strstr(attrs->device, iclass->match_device)))
+ if (strstr(attrs->device, *cur)) {
#endif
- return FALSE;
+ match = TRUE;
+ break;
+ }
+ if (!match)
+ return FALSE;
+ }
if (iclass->is_keyboard.set &&
iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
return FALSE;
diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
index ee91b9a..69f4751 100644
--- a/hw/xfree86/doc/man/xorg.conf.man.pre
+++ b/hw/xfree86/doc/man/xorg.conf.man.pre
@@ -1039,17 +1039,20 @@ The allowed matching entries are shown below.
.BI "MatchProduct \*q" matchproduct \*q
This entry can be used to check if the substring
.RI \*q matchproduct \*q
-occurs in the device's product name.
+occurs in the device's product name. Multiple substrings can be matched by
+separating arguments with a '|' character.
.TP 7
.BI "MatchVendor \*q" matchvendor \*q
This entry can be used to check if the substring
.RI \*q matchvendor \*q
-occurs in the device's vendor name.
+occurs in the device's vendor name. Multiple substrings can be matched by
+separating arguments with a '|' character.
.TP 7
.BI "MatchDevicePath \*q" matchdevice \*q
This entry can be used to check if the device file matches the
.RI \*q matchdevice \*q
-pathname pattern.
+pathname pattern. Multiple patterns can be matched by separating arguments
+with a '|' character.
.TP 7
.BI "MatchIsKeyboard \*q" bool \*q
.TP 7
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index 1c98160..8041740 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -29,6 +29,8 @@
#include <xorg-config.h>
#endif
+#include <string.h>
+#include "os.h"
#include "xf86Parser.h"
#include "xf86tokens.h"
#include "Configint.h"
@@ -56,6 +58,46 @@ xf86ConfigSymTabRec InputClassTab[] =
#define CLEANUP xf86freeInputClassList
+#define TOKEN_SEP "|"
+
+/*
+ * Tokenize a string into a NULL terminated array of strings. Always returns
+ * an allocated array unless an error occurs.
+ */
+static char **
+tokenize(const char *str)
+{
+ char **list, **nlist;
+ char *tok, *tmp;
+ unsigned num = 0, n;
+
+ list = calloc(1, sizeof(*list));
+ if (!list)
+ return NULL;
+ tmp = strdup(str);
+ if (!tmp)
+ goto error;
+ for (tok = strtok(tmp, TOKEN_SEP); tok; tok = strtok(NULL, TOKEN_SEP)) {
+ nlist = realloc(list, (num + 2) * sizeof(*list));
+ if (!nlist)
+ goto error;
+ list = nlist;
+ list[num] = strdup(tok);
+ if (!list[num])
+ goto error;
+ list[++num] = NULL;
+ }
+ free(tmp);
+ return list;
+
+error:
+ TestFree(tmp);
+ for (n = 0; n < num; n++)
+ free(list[n]);
+ TestFree(list);
+ return NULL;
+}
+
XF86ConfInputClassPtr
xf86parseInputClassSection(void)
{
@@ -91,17 +133,17 @@ xf86parseInputClassSection(void)
case MATCH_PRODUCT:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchProduct");
- ptr->match_product = val.str;
+ ptr->match_product = tokenize(val.str);
break;
case MATCH_VENDOR:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchVendor");
- ptr->match_vendor = val.str;
+ ptr->match_vendor = tokenize(val.str);
break;
case MATCH_DEVICE_PATH:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchDevicePath");
- ptr->match_device = val.str;
+ ptr->match_device = tokenize(val.str);
break;
case MATCH_IS_KEYBOARD:
if (xf86getSubToken(&(ptr->comment)) != STRING)
@@ -173,6 +215,8 @@ xf86parseInputClassSection(void)
void
xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
{
+ char **list;
+
while (ptr) {
fprintf(cf, "Section \"InputClass\"\n");
if (ptr->comment)
@@ -181,12 +225,30 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
if (ptr->driver)
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
- if (ptr->match_product)
- fprintf(cf, "\tMatchProduct \"%s\"\n", ptr->match_product);
- if (ptr->match_vendor)
- fprintf(cf, "\tMatchVendor \"%s\"\n", ptr->match_vendor);
- if (ptr->match_device)
- fprintf(cf, "\tMatchDevicePath \"%s\"\n", ptr->match_device);
+ if (ptr->match_product) {
+ fprintf(cf, "\tMatchProduct \"");
+ for (list = ptr->match_product; *list; list++)
+ fprintf(cf, "%s%s",
+ list == ptr->match_product ? "" : TOKEN_SEP,
+ *list);
+ fprintf(cf, "\"\n");
+ }
+ if (ptr->match_vendor) {
+ fprintf(cf, "\tMatchVendor \"");
+ for (list = ptr->match_vendor; *list; list++)
+ fprintf(cf, "%s%s",
+ list == ptr->match_vendor ? "" : TOKEN_SEP,
+ *list);
+ fprintf(cf, "\"\n");
+ }
+ if (ptr->match_device) {
+ fprintf(cf, "\tMatchDevicePath \"");
+ for (list = ptr->match_device; *list; list++)
+ fprintf(cf, "%s%s",
+ list == ptr->match_device ? "" : TOKEN_SEP,
+ *list);
+ fprintf(cf, "\"\n");
+ }
if (ptr->is_keyboard.set)
fprintf(cf, "\tIsKeyboard \"%s\"\n",
ptr->is_keyboard.val ? "yes" : "no");
@@ -215,13 +277,26 @@ void
xf86freeInputClassList (XF86ConfInputClassPtr ptr)
{
XF86ConfInputClassPtr prev;
+ char **list;
while (ptr) {
TestFree(ptr->identifier);
TestFree(ptr->driver);
- TestFree(ptr->match_product);
- TestFree(ptr->match_vendor);
- TestFree(ptr->match_device);
+ if (ptr->match_product) {
+ for (list = ptr->match_product; *list; list++)
+ free(*list);
+ free(ptr->match_product);
+ }
+ if (ptr->match_vendor) {
+ for (list = ptr->match_vendor; *list; list++)
+ free(*list);
+ free(ptr->match_vendor);
+ }
+ if (ptr->match_device) {
+ for (list = ptr->match_device; *list; list++)
+ free(*list);
+ free(ptr->match_device);
+ }
TestFree(ptr->comment);
xf86optionListFree(ptr->option_lst);
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index 5e8351f..b6d40a1 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -343,9 +343,9 @@ typedef struct
GenericListRec list;
char *identifier;
char *driver;
- char *match_product;
- char *match_vendor;
- char *match_device;
+ char **match_product;
+ char **match_vendor;
+ char **match_device;
xf86TriState is_keyboard;
xf86TriState is_pointer;
xf86TriState is_joystick;
--
1.6.6
More information about the xorg-devel
mailing list