[PATCH] regular expression support (was Re: [PATCH xfree86] Signed-off-by: Oleh Nykyforchyn)
walter harms
wharms at bfs.de
Fri May 27 06:16:19 PDT 2011
Am 27.05.2011 07:56, schrieb Peter Hutterer:
> 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
>
i am a big fan of memory saving but is
* list = calloc(3, sizeof(*list));
realy useful here ? list[3] would ok also.
i realy like asprintf() but i guess that shold work also:
list[1] = stdup(str + 3);
>> + return list;
>> +
>> + error:
>> + if (list[0]) free(list[0]);
>> + if (list[1]) free(list[1]);
>> + free(list);
it should be save to avoid if() here.
>> + 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
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>
More information about the xorg-devel
mailing list