[PATCH] regular expression support (was Re: [PATCH xfree86] Signed-off-by: Oleh Nykyforchyn)
Peter Hutterer
peter.hutterer at who-t.net
Thu May 26 22:56:01 PDT 2011
On Wed, May 25, 2011 at 03:08:32PM +0300, Oleh Nykyforchyn wrote:
> On Wed, 25 May 2011 16:14:42 +1000
> Peter Hutterer <peter.hutterer at who-t.net> wrote:
>
> > I believe | is used frequently in regular expressions, so using it as
> > decision over regex or simple is dangerous. we can't use slash either, there
> > are likely a few configurations out there already.
> > My suggestion is simply prefixing with "re:". I guess there's very few
> > configurations out there that need exactly that match and it makes it very
> > clear that this match is a regular expression
> >
> > MatchProduct "re:[^ a-z]{4}|(x|y)"
>
> Nice, short and intuitive. I modified my patch to use this idea, and the code
> is simpler and clearer now. A piece of Xorg.0.log and the result is below:
>
> [ 2959.284] (II) config/udev: Adding input device Power Button (/dev/input/event2)
> [ 2959.285] (**) Applying regex ".implicit." to attribute "Radeon"
> [ 2959.285] (**) Applying regex "^R.d[a-z]*$" to attribute "Radeon"
> [ 2959.285] (**) Applying regex ".implicit." to attribute "Radeon"
> [ 2959.285] (**) Applying regex "^R.d[a-z]*$" to attribute "Radeon"
> [ 2959.285] (**) Power Button: Applying InputClass "Keyboard0"
>
> Statements were:
> MatchLayout "re:.implicit."
> MatchLayout "re:^R.d[a-z]*$"
> To tell the truth, I have no idea why each match is repeated twice, but it works.
>
> The patch itself:
> ---------------------------------------
>
> Add option to use extended regex expresssions in Match* statements
>
> If a pattern list is of the form "re:str", then str is treated
> as a single extended regular expression
>
> Signed-off-by: Oleh Nykyforchyn <oleh.nyk at gmail.com>
> ---
> hw/xfree86/common/xf86Xinput.c | 25 +++++++++++++++++++
> hw/xfree86/parser/InputClass.c | 53 +++++++++++++++++++++++++++++++++-------
> 2 files changed, 69 insertions(+), 9 deletions(-)
>
> diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
> index 88cf292..0b90b5b 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,28 @@ MatchAttrToken(const char *attr, struct list *patterns,
> char * const *cur;
> Bool match = FALSE;
>
> + cur = group->values;
> + if ((cur[0]) && (!*cur[0]) && /* cur[0] == "", can never come out of strtok() */
> + (cur[1]) && /* cur[1] == regex */
> + (cur[2] == NULL)) {
urgh, this seems a bit hacked on. any chance we can have a define, enum,
special return value so we don't rely on magic value combinations?
patterns is a xf86MatchGroup struct, we could extend this with a enum type {
MATCH_TYPE_NORMAL, MATCH_TYPE_REGEX } or somesuch.
> + /* 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..78a9446 100644
> --- a/hw/xfree86/parser/InputClass.c
> +++ b/hw/xfree86/parser/InputClass.c
> @@ -66,6 +66,39 @@ xf86ConfigSymTabRec InputClassTab[] =
>
> #define TOKEN_SEP "|"
>
> +/*
> + * Tokenize a string into a NULL terminated array of strings. The same that
> + * xstrtokenize unless the string starts with "re:", then the rest of
> + * the string is treated as a single extended regex, and
> + * {"", regex, NULL} is returned.
> + */
> +static char**
> +rstrtokenize(const char *str, const char *separators)
> +{
> + if (!str)
> + return NULL;
> + if (!strncmp(str,"re:",3)){
> + char **list;
> +
> + list = calloc(3, sizeof(*list));
> + if (!list)
> + return NULL;
> + list[0] = strdup("");
> + list[1] = calloc(strlen(str)-2, sizeof(char));
> + if (!list[0] || !list[1])
> + goto error;
> + strcpy(list[1], str+3);
list[1] = xasprintf("%s", str + 3)
would be simpler here.
Dan, any comments?
Cheers,
Peter
> + return list;
> +
> + error:
> + if (list[0]) free(list[0]);
> + if (list[1]) free(list[1]);
> + free(list);
> + return NULL;
> + }
> + return xstrtokenize(str, separators);
> +}
> +
> static void
> add_group_entry(struct list *head, char **values)
> {
> @@ -127,55 +160,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
More information about the xorg-devel
mailing list