Small fixes: Make a match group a list of patterns instead of an array of string, to unify with other structures in the parser, to prepare for introduction of regular expression in Match* statements, and to keep a matching mode field in a pattern together with a pattern string. This allows to join all match_* functions in InputClass.c into one "multi-mode" function.
Signed-off-by: Oleh Nykyforchyn <oleh....@gmail.com> --- hw/xfree86/common/xf86Xinput.c | 130 +++++++++++++------------ hw/xfree86/parser/InputClass.c | 211 +++++++++++++++++++++++++--------------- hw/xfree86/parser/xf86Parser.h | 22 ++++- 3 files changed, 221 insertions(+), 142 deletions(-) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 425b359..d39ab89 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -472,79 +472,76 @@ HostOS(void) #endif } +/* + * Match an attribute against a pattern. Matching mode is + * determined by pattern->mode member. + */ static int -match_substring(const char *attr, const char *pattern) +match_token(const char *attr, xf86MatchPattern *pattern) { - return (strstr(attr, pattern)) ? 0 : -1; -} - -#ifdef HAVE_FNMATCH_H -static int -match_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, 0); -} -#else -#define match_pattern match_substring -#endif + if (!pattern) + return 0; + switch (pattern->mode) + { + case MATCH_IS_INVALID: + return 0; + case MATCH_IS_STRCMP: + return (strcmp(attr, pattern->str)) ? 0 : -1; + case MATCH_IS_STRCASECMP: + return (strcasecmp(attr, pattern->str)) ? 0 : -1; + case MATCH_IS_STRSTR: + return (strstr(attr, pattern->str)) ? -1 : 0; + case MATCH_IS_STRCASESTR: + return (strcasestr(attr, pattern->str)) ? -1 : 0; #ifdef HAVE_FNMATCH_H -static int -match_path_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, FNM_PATHNAME); -} + case MATCH_IS_FILENAME: + return (fnmatch(pattern->str, attr, 0)) ? 0 : -1; + case MATCH_IS_PATHNAME: + return (fnmatch(pattern->str, attr, FNM_PATHNAME)) ? 0 : -1; #else -#define match_path_pattern match_substring + case MATCH_IS_FILENAME: + return (strstr(attr, pattern->str)) ? -1 : 0; + case MATCH_IS_PATHNAME: + return (strstr(attr, pattern->str)) ? -1 : 0; #endif - -/* - * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" - * It is convenient that "" in patterns means "no explicit layout" - */ -static int -match_string_implicit(const char *attr, const char *pattern) -{ - if (strlen(pattern)) { - return strcmp(attr, pattern); - } else { - return strcmp(attr,"(implicit)"); + default: + /* Impossible */ + return 0; } } /* - * Match an attribute against a list of NULL terminated arrays of patterns. - * If a pattern in each list entry is matched, return TRUE. + * Match an attribute against a list of xf86MatchGroup's. + * Return TRUE only if each list entry is successful. */ static Bool -MatchAttrToken(const char *attr, struct list *patterns, - int (*compare)(const char *attr, const char *pattern)) +MatchAttrToken(const char *attr, struct list *groups) { - const xf86MatchGroup *group; + xf86MatchGroup *group; + xf86MatchPattern *pattern; - /* If there are no patterns, accept the match */ - if (list_is_empty(patterns)) + /* If there are no groups, accept the match */ + if (list_is_empty(groups)) return TRUE; - /* If there are patterns but no attribute, reject the match */ + /* If there are groups but no attribute, reject the match */ if (!attr) return FALSE; /* - * Otherwise, iterate the list of patterns ensuring each entry has a - * match. Each list entry is a separate Match line of the same type. + * Otherwise, iterate the list of groups ensuring each entry has a + * match. Each list entry is a list of patterns obtained from + * a separate Match line. */ - list_for_each_entry(group, patterns, entry) { - char * const *cur; + list_for_each_entry(group, groups, entry) { Bool match = FALSE; - for (cur = group->values; *cur; cur++) - if ((*compare)(attr, *cur) == 0) { - match = TRUE; - break; - } - if (!match) - return FALSE; + list_for_each_entry(pattern, &group->patterns, entry) { + match = match || match_token(attr, pattern); + if (match) break; + } + if (!match) return FALSE; } /* All the entries in the list matched the attribute */ @@ -559,32 +556,34 @@ static Bool InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, const InputAttributes *attrs) { + const char *layout; + /* 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; /* @@ -598,7 +597,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; } @@ -607,12 +606,17 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, return FALSE; } - /* MatchLayout string */ - if (!list_is_empty(&iclass->match_layout)) { - if (!MatchAttrToken(xf86ConfigLayout.id, - &iclass->match_layout, match_string_implicit)) + /* MatchLayout string + * + * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" + * It is convenient that "" in patterns means "no explicit layout" + */ + if (strcmp(xf86ConfigLayout.id,"(implicit)")) + layout = xf86ConfigLayout.id; + else + layout = ""; + if (!MatchAttrToken(layout, &iclass->match_layout)) return FALSE; - } /* MatchIs* booleans */ if (iclass->is_keyboard.set && diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c index 3f80170..f4b080f 100644 --- a/hw/xfree86/parser/InputClass.c +++ b/hw/xfree86/parser/InputClass.c @@ -67,15 +67,55 @@ xf86ConfigSymTabRec InputClassTab[] = #define TOKEN_SEP "|" static void -add_group_entry(struct list *head, char **values) +free_group(xf86MatchGroup *group) { + xf86MatchPattern *pattern, *next_pattern; + list_for_each_entry_safe(pattern, next_pattern, &group->patterns, entry) { + list_del(&pattern->entry); + if (pattern->str) + free(pattern->str); + free(pattern); + } + free(group); +} + +static +xf86MatchGroup* +create_group(const char *str, + xf86MatchMode pref_mode) +{ + xf86MatchPattern *pattern; xf86MatchGroup *group; + unsigned n; + + if (!str) + return NULL; group = malloc(sizeof(*group)); - if (group) { - group->values = values; - list_add(&group->entry, head); + if (!group) return NULL; + list_init(&group->patterns); + + again: + /* start new pattern */ + if ((pattern = calloc(sizeof(*pattern),1)) == NULL) { + free_group(group); + return NULL; } + list_add(&pattern->entry, &group->patterns); + + pattern->mode = pref_mode; + + n = strcspn(str, TOKEN_SEP); + + if ((pattern->str = strndup(str, n)) == NULL) + pattern->mode = MATCH_IS_INVALID; + + if (*str != '\0') { + str ++; + goto again; + } + + return group; } XF86ConfInputClassPtr @@ -83,6 +123,7 @@ xf86parseInputClassSection(void) { int has_ident = FALSE; int token; + xf86MatchGroup *group; parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec) @@ -126,56 +167,83 @@ xf86parseInputClassSection(void) case MATCH_PRODUCT: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchProduct"); - add_group_entry(&ptr->match_product, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRSTR); + if (group) + list_add(&group->entry, &ptr->match_product); + else + Error(QUOTE_MSG, "MatchProduct"); break; case MATCH_VENDOR: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchVendor"); - add_group_entry(&ptr->match_vendor, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRSTR); + if (group) + list_add(&group->entry, &ptr->match_vendor); + else + Error(QUOTE_MSG, "MatchVendor"); 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)); + group = create_group(val.str, MATCH_IS_PATHNAME); + if (group) + list_add(&group->entry, &ptr->match_device); + else + Error(QUOTE_MSG, "MatchDevicePath"); break; case MATCH_OS: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchOS"); - add_group_entry(&ptr->match_os, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRCASECMP); + if (group) + list_add(&group->entry, &ptr->match_os); + else + Error(QUOTE_MSG, "MatchOS"); break; case MATCH_PNPID: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchPnPID"); - add_group_entry(&ptr->match_pnpid, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_FILENAME); + if (group) + list_add(&group->entry, &ptr->match_pnpid); + else + Error(QUOTE_MSG, "MatchPnPID"); break; case MATCH_USBID: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchUSBID"); - add_group_entry(&ptr->match_usbid, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_FILENAME); + if (group) + list_add(&group->entry, &ptr->match_usbid); + else + Error(QUOTE_MSG, "MatchUSBID"); break; case MATCH_DRIVER: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchDriver"); - add_group_entry(&ptr->match_driver, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRCMP); + if (group) + list_add(&group->entry, &ptr->match_driver); + else + Error(QUOTE_MSG, "MatchDriver"); break; case MATCH_TAG: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchTag"); - add_group_entry(&ptr->match_tag, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRCMP); + if (group) + list_add(&group->entry, &ptr->match_tag); + else + Error(QUOTE_MSG, "MatchTag"); break; case MATCH_LAYOUT: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchLayout"); - add_group_entry(&ptr->match_layout, - xstrtokenize(val.str, TOKEN_SEP)); + group = create_group(val.str, MATCH_IS_STRCMP); + if (group) + list_add(&group->entry, &ptr->match_layout); + else + Error(QUOTE_MSG, "MatchLayout"); break; case MATCH_IS_KEYBOARD: if (xf86getSubToken(&(ptr->comment)) != STRING) @@ -244,11 +312,26 @@ xf86parseInputClassSection(void) return ptr; } +static void +print_pattern(FILE * cf, const xf86MatchPattern *pattern) +{ + if (!pattern) return; + + if (pattern->mode == MATCH_IS_INVALID) + fprintf(cf, "invalid:"); + if (pattern->str) + fprintf(cf, "%s", pattern->str); + else + fprintf(cf, "(none)"); + if (pattern->entry.next) + fprintf(cf, "%s", TOKEN_SEP); +} + void xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) { const xf86MatchGroup *group; - char * const *cur; + const xf86MatchPattern *pattern; while (ptr) { fprintf(cf, "Section \"InputClass\"\n"); @@ -261,65 +344,56 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) list_for_each_entry(group, &ptr->match_product, entry) { fprintf(cf, "\tMatchProduct \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_vendor, entry) { fprintf(cf, "\tMatchVendor \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_device, entry) { fprintf(cf, "\tMatchDevicePath \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_os, entry) { fprintf(cf, "\tMatchOS \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_pnpid, entry) { fprintf(cf, "\tMatchPnPID \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_usbid, entry) { fprintf(cf, "\tMatchUSBID \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_driver, entry) { fprintf(cf, "\tMatchDriver \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_tag, entry) { fprintf(cf, "\tMatchTag \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } list_for_each_entry(group, &ptr->match_layout, entry) { fprintf(cf, "\tMatchLayout \""); - for (cur = group->values; *cur; cur++) - fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, - *cur); + list_for_each_entry(pattern, &group->patterns, entry) + print_pattern(cf, pattern); fprintf(cf, "\"\n"); } @@ -354,64 +428,45 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr) while (ptr) { xf86MatchGroup *group, *next; - char **list; TestFree(ptr->identifier); TestFree(ptr->driver); list_for_each_entry_safe(group, next, &ptr->match_product, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_vendor, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_device, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_os, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_pnpid, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_usbid, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_driver, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_tag, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } list_for_each_entry_safe(group, next, &ptr->match_layout, entry) { list_del(&group->entry); - for (list = group->values; *list; list++) - free(*list); - free(group); + free_group(group); } TestFree(ptr->comment); diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h index a8785c5..b02923f 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -341,10 +341,30 @@ xf86TriState; typedef struct { struct list entry; - char **values; + struct list patterns; } xf86MatchGroup; +typedef enum +{ + MATCH_IS_INVALID, + MATCH_IS_STRCMP, + MATCH_IS_STRCASECMP, + MATCH_IS_STRSTR, + MATCH_IS_STRCASESTR, + MATCH_IS_FILENAME, + MATCH_IS_PATHNAME +} +xf86MatchMode; + +typedef struct +{ + struct list entry; + xf86MatchMode mode; + char *str; +} +xf86MatchPattern; + typedef struct { GenericListRec list; -- 1.7.4.4 -- Oleh Nykyforchyn <oleh....@gmail.com> _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel