[PATCH] xfree86: Allow InputClass entries to specify match type
Peter Hutterer
peter.hutterer at who-t.net
Sun Dec 5 21:29:00 PST 2010
On Thu, Dec 02, 2010 at 06:19:15AM -0800, Dan Nicholson wrote:
> The InputClass Match* entries are currently hardwired to offer a certain
> variant of comparison for matching. For example, the MatchProduct entry
> uses substring match. Add a second optional argument to the entry to
> allow the match type to be specified.
>
> MatchProduct "foo*" "pattern"
>
> The available match types are "string", "istring", "substring",
> "isubstring", "path" and "pattern". See xorg.conf(5) for more details.
> If no type is supplied, the previous default is used.
I wonder if it is possible to support sed- or grep-like matching instead of
adding match types like this?
something like?
MatchProduct "s/pattern/i"
Cheers,
Peter
> Signed-off-by: Dan Nicholson <dbn.lists at gmail.com>
> ---
> Sorry, I know this is late, but I've been sitting on this for months
> and forgot to send it. A rebased it to current HEAD, but it's been a
> while since I actually tested it. I can't see anything that's changed
> in the affected areas that would break it, though. Too late for 1.10?
>
> hw/xfree86/common/xf86Xinput.c | 51 ++++++++++++---
> hw/xfree86/doc/man/xorg.conf.man.pre | 88 ++++++++++++++++++++------
> hw/xfree86/parser/InputClass.c | 115 +++++++++++++++++++++++-----------
> hw/xfree86/parser/xf86Parser.h | 12 ++++
> 4 files changed, 199 insertions(+), 67 deletions(-)
>
> diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
> index 81bb707..ac87119 100644
> --- a/hw/xfree86/common/xf86Xinput.c
> +++ b/hw/xfree86/common/xf86Xinput.c
> @@ -450,6 +450,12 @@ match_substring(const char *attr, const char *pattern)
> return (strstr(attr, pattern)) ? 0 : -1;
> }
>
> +static int
> +match_isubstring(const char *attr, const char *pattern)
> +{
> + return (strcasestr(attr, pattern)) ? 0 : -1;
> +}
> +
> #ifdef HAVE_FNMATCH_H
> static int
> match_pattern(const char *attr, const char *pattern)
> @@ -475,8 +481,7 @@ match_path_pattern(const char *attr, const char *pattern)
> * If a pattern in each list entry is matched, return TRUE.
> */
> static Bool
> -MatchAttrToken(const char *attr, struct list *patterns,
> - int (*compare)(const char *attr, const char *pattern))
> +MatchAttrToken(const char *attr, struct list *patterns)
> {
> const xf86MatchGroup *group;
>
> @@ -495,6 +500,32 @@ MatchAttrToken(const char *attr, struct list *patterns,
> list_for_each_entry(group, patterns, entry) {
> char * const *cur;
> Bool match = FALSE;
> + int (*compare)(const char *attr, const char *pattern);
> +
> + switch (group->type) {
> + case MATCH_STRING:
> + compare = strcmp;
> + break;
> + case MATCH_ISTRING:
> + compare = strcasecmp;
> + break;
> + case MATCH_SUBSTRING:
> + compare = match_substring;
> + break;
> + case MATCH_ISUBSTRING:
> + compare = match_isubstring;
> + break;
> + case MATCH_PATH:
> + compare = match_path_pattern;
> + break;
> + case MATCH_PATTERN:
> + compare = match_pattern;
> + break;
> + default:
> + /* this shouldn't happen */
> + xf86Msg(X_ERROR, "Unrecognized match type %d\n", group->type);
> + return FALSE;
> + }
>
> for (cur = group->values; *cur; cur++)
> if ((*compare)(attr, *cur) == 0) {
> @@ -518,31 +549,31 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev,
> const InputAttributes *attrs)
> {
> /* MatchProduct substring */
> - if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring))
> + if (!MatchAttrToken(attrs->product, &iclass->match_product))
> return FALSE;
>
> /* MatchVendor substring */
> - if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring))
> + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor))
> return FALSE;
>
> /* MatchDevicePath pattern */
> - if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern))
> + if (!MatchAttrToken(attrs->device, &iclass->match_device))
> return FALSE;
>
> /* MatchOS case-insensitive string */
> - if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp))
> + if (!MatchAttrToken(HostOS(), &iclass->match_os))
> return FALSE;
>
> /* MatchPnPID pattern */
> - if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern))
> + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid))
> return FALSE;
>
> /* MatchUSBID pattern */
> - if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern))
> + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid))
> return FALSE;
>
> /* MatchDriver string */
> - if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp))
> + if (!MatchAttrToken(idev->driver, &iclass->match_driver))
> return FALSE;
>
> /*
> @@ -556,7 +587,7 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev,
> if (!attrs->tags)
> return FALSE;
> for (tag = attrs->tags, match = FALSE; *tag; tag++) {
> - if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) {
> + if (MatchAttrToken(*tag, &iclass->match_tag)) {
> match = TRUE;
> break;
> }
> diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
> index ba876c0..db9a955 100644
> --- a/hw/xfree86/doc/man/xorg.conf.man.pre
> +++ b/hw/xfree86/doc/man/xorg.conf.man.pre
> @@ -1068,59 +1068,109 @@ attribute. For example:
> .B "EndSection"
> .fi
> .RE
> +.PP
> +An optional second argument to the entry specifies the type of matching
> +used. The recognized match types are:
> +.RS 4
> +.TP 16
> +.B \*qstring\*q
> +case-sensitive string
> +.TP 16
> +.B \*qistring\*q
> +case-insensitive string
> +.TP 16
> +.B \*qsubstring\*q
> +case-sensitive substring
> +.TP 16
> +.B \*qisubstring\*q
> +case-insensitive substring
> +.TP 16
> +.B \*qpath\*q
> +shell path pattern on systems providing
> +.BR fnmatch (3)
> +or
> +.B \*qsubstring\*q
> +matching otherwise
> +.TP 16
> +.B \*qpattern\*q
> +shell wildcard pattern on systems providing
> +.BR fnmatch (3)
> +or
> +.B \*qsubstring\*q
> +matching otherwise
> +.RE
> +.PP
> +Here is an example showing the optional nature of the match type:
> +.PP
> +.RS 4
> +.nf
> +.B "MatchVendor \*qfoo*\*q \*qpattern\*q # use the pattern match"
> +.B "MatchVendor \*qfoo\*q # use the default substring match"
> +.fi
> +.RE
> +.PP
> +The available match entries of this type are:
> .TP 7
> .BI "MatchProduct \*q" matchproduct \*q
> -This entry can be used to check if the substring
> +This entry can be used to check
> .RI \*q matchproduct \*q
> -occurs in the device's product name.
> +against the device's product name. The default match type is
> +.BR \*qsubstring\*q .
> .TP 7
> .BI "MatchVendor \*q" matchvendor \*q
> -This entry can be used to check if the substring
> +This entry can be used to check
> .RI \*q matchvendor \*q
> -occurs in the device's vendor name.
> +against the device's vendor name. The default match type is
> +.BR \*qsubstring\*q .
> .TP 7
> .BI "MatchDevicePath \*q" matchdevice \*q
> -This entry can be used to check if the device file matches the
> +This entry can be used to check if
> .RI \*q matchdevice \*q
> -pathname pattern.
> +matches the device file. The default match type is
> +.BR \*qpath\*q .
> .TP 7
> .BI "MatchOS \*q" matchos \*q
> -This entry can be used to check if the operating system matches the
> -case-insensitive
> +This entry can be used to check if the operating system matches
> .RI \*q matchos \*q
> string. This entry is only supported on platforms providing the
> .BR uname (2)
> -system call.
> +system call. The default match type is
> +.BR \*qistring\*q .
> .TP 7
> .BI "MatchPnPID \*q" matchpnp \*q
> The device's Plug and Play (PnP) ID can be checked against the
> .RI \*q matchpnp \*q
> -shell wildcard pattern.
> +string. The default match type is
> +.BR \*qpattern\*q .
> .TP 7
> .BI "MatchUSBID \*q" matchusb \*q
> The device's USB ID can be checked against the
> .RI \*q matchusb \*q
> -shell wildcard pattern. The ID is constructed as lowercase hexadecimal numbers
> -separated by a ':'. This is the same format as the
> +string. The ID is constructed as lowercase hexadecimal numbers separated by a
> +':'. This is the same format as the
> .BR lsusb (8)
> -program.
> +program. The default match type is
> +.BR \*qpattern\*q .
> .TP 7
> .BI "MatchDriver \*q" matchdriver \*q
> -Check the case-sensitive string
> +Check the string
> .RI \*q matchdriver \*q
> against the currently configured driver of the device. Ordering of sections
> using this entry is important since it will not match unless the driver has
> been set by the config backend or a previous
> .B InputClass
> -section.
> +section. The default match type is
> +.BR \*qstring\*q .
> .TP 7
> .BI "MatchTag \*q" matchtag \*q
> -This entry can be used to check if tags assigned by the config backend
> -matches the
> +This entry can be used to check if any of the tags assigned by the config
> +backend match the
> .RI \*q matchtag \*q
> -pattern. A match is found if at least one of the tags given in
> +string. A match is found if at least one of the tags given in
> .RI \*q matchtag \*q
> -matches at least one of the tags assigned by the backend.
> +matches at least one of the tags assigned by the backend. The default match
> +type is
> +.BR \*qstring\*q .
> .PP
> The second type of entry is used to match device types. These entries take a
> boolean argument similar to
> diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
> index 9f88e7e..8cd9613 100644
> --- a/hw/xfree86/parser/InputClass.c
> +++ b/hw/xfree86/parser/InputClass.c
> @@ -65,16 +65,47 @@ xf86ConfigSymTabRec InputClassTab[] =
>
> #define TOKEN_SEP "|"
>
> -static void
> -add_group_entry(struct list *head, char **values)
> +static Bool
> +parse_match_entry(struct list *head, xf86MatchType def_type, const char *str)
> {
> xf86MatchGroup *group;
> + int token;
> +
> + if (xf86getToken(NULL) != STRING) {
> + xf86parseError(QUOTE_MSG, str);
> + return FALSE;
> + }
> +
> + group = XNFalloc(sizeof(*group));
> + group->values = xstrtokenize(val.str, TOKEN_SEP);
> + group->type = def_type;
> + list_add(&group->entry, head);
> +
> + /* See if an alternate match type is specified */
> + if ((token = xf86getToken(NULL)) != STRING) {
> + xf86unGetToken(token);
> + return TRUE;
> + }
>
> - group = malloc(sizeof(*group));
> - if (group) {
> - group->values = values;
> - list_add(&group->entry, head);
> + /* Check the specified match type */
> + if (strcasecmp(val.str, "string"))
> + group->type = MATCH_STRING;
> + else if (strcasecmp(val.str, "istring"))
> + group->type = MATCH_ISTRING;
> + else if (strcasecmp(val.str, "substring"))
> + group->type = MATCH_SUBSTRING;
> + else if (strcasecmp(val.str, "isubstring"))
> + group->type = MATCH_ISUBSTRING;
> + else if (strcasecmp(val.str, "path"))
> + group->type = MATCH_PATH;
> + else if (strcasecmp(val.str, "pattern"))
> + group->type = MATCH_PATTERN;
> + else {
> + xf86parseError("Match type \"%s\" is not valid.", val.str);
> + return FALSE;
> }
> +
> + return TRUE;
> }
>
> XF86ConfInputClassPtr
> @@ -122,52 +153,60 @@ xf86parseInputClassSection(void)
> ptr->option_lst = xf86parseOption(ptr->option_lst);
> break;
> case MATCH_PRODUCT:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchProduct");
> - add_group_entry(&ptr->match_product,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_product, MATCH_SUBSTRING,
> + "MatchProduct")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_VENDOR:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchVendor");
> - add_group_entry(&ptr->match_vendor,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_vendor, MATCH_SUBSTRING,
> + "MatchVendor")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> 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));
> + if (!parse_match_entry(&ptr->match_device, MATCH_PATH,
> + "MatchDevicePath")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_OS:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchOS");
> - add_group_entry(&ptr->match_os,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_os, MATCH_ISTRING,
> + "MatchOS")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_PNPID:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchPnPID");
> - add_group_entry(&ptr->match_pnpid,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_pnpid, MATCH_PATTERN,
> + "MatchPnPID")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_USBID:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchUSBID");
> - add_group_entry(&ptr->match_usbid,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_usbid, MATCH_PATTERN,
> + "MatchUSBID")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_DRIVER:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchDriver");
> - add_group_entry(&ptr->match_driver,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_driver, MATCH_STRING,
> + "MatchDriver")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_TAG:
> - if (xf86getSubToken(&(ptr->comment)) != STRING)
> - Error(QUOTE_MSG, "MatchTag");
> - add_group_entry(&ptr->match_tag,
> - xstrtokenize(val.str, TOKEN_SEP));
> + if (!parse_match_entry(&ptr->match_tag, MATCH_STRING,
> + "MatchTag")) {
> + xf86freeInputClassList(ptr);
> + return NULL;
> + }
> break;
> case MATCH_IS_KEYBOARD:
> if (xf86getSubToken(&(ptr->comment)) != STRING)
> diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
> index 4f279f1..2082ea3 100644
> --- a/hw/xfree86/parser/xf86Parser.h
> +++ b/hw/xfree86/parser/xf86Parser.h
> @@ -338,9 +338,21 @@ typedef struct
> }
> xf86TriState;
>
> +typedef enum
> +{
> + MATCH_STRING,
> + MATCH_ISTRING,
> + MATCH_SUBSTRING,
> + MATCH_ISUBSTRING,
> + MATCH_PATH,
> + MATCH_PATTERN,
> +}
> +xf86MatchType;
> +
> typedef struct
> {
> struct list entry;
> + xf86MatchType type;
> char **values;
> }
> xf86MatchGroup;
> --
> 1.7.2.3
More information about the xorg-devel
mailing list