xserver: hw/xfree86/{common,parser}: use pattern groups for devices matching to classes

It is patch 3/5 of a series that refactors matching input and output devices to classes and
extends possibilities to describe them, in particular, it allows use of regular expressions.

This patch defines a function MatchAddrToken that actually matches an attribute against
a list of pattern groups (in fact, Match... lines). It is used to check whether a particular
input/optput class should be applied to a device, thus replacing the tangled and difficult
to control code in InputClass.c and OutputClass.c.

Signed-off-by: Oleh Nykyforchyn <oleh.nyk@gmail.com>
This commit is contained in:
Oleh Nykyforchyn
2025-07-23 17:35:54 +03:00
committed by Enrico Weigelt
parent f7a892d7d0
commit d4a7263940
7 changed files with 251 additions and 243 deletions

View File

@@ -528,82 +528,96 @@ HostOS(void)
#endif
}
static int
match_substring(const char *attr, const char *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
#ifdef HAVE_FNMATCH_H
static int
match_path_pattern(const char *attr, const char *pattern)
{
return fnmatch(pattern, attr, FNM_PATHNAME);
}
#else
#define match_path_pattern match_substring
#endif
/*
* If no Layout section is found, xf86ServerLayout.id becomes "(implicit)"
* It is convenient that "" in patterns means "no explicit layout"
* Match an attribute against a pattern. Matching mode is
* determined by pattern->mode member.
*/
static int
match_string_implicit(const char *attr, const char *pattern)
match_token(const char *attr, xf86MatchPattern *pattern)
{
if (strlen(pattern)) {
return strcmp(attr, pattern);
}
else {
return strcmp(attr, "(implicit)");
if ((!pattern) || (!attr))
return 0;
switch (pattern->mode)
{
case MATCH_IS_INVALID:
return 0;
case MATCH_EXACT:
return (strcmp(attr, pattern->str)) ? 0 : -1;
case MATCH_EXACT_NOCASE:
return (strcasecmp(attr, pattern->str)) ? 0 : -1;
case MATCH_AS_SUBSTRING:
return (strstr(attr, pattern->str)) ? -1 : 0;
case MATCH_AS_SUBSTRING_NOCASE:
return (strcasestr(attr, pattern->str)) ? -1 : 0;
case MATCH_AS_FILENAME:
#ifdef HAVE_FNMATCH_H
return (fnmatch(pattern->str, attr, 0)) ? 0 : -1;
#else
LogMessageVerb(X_WARNING, 1, "Filename matching requested but unavailable for \"%s\", resorting to search for substring\n", pattern->str);
pattern->mode = MATCH_AS_SUBSTRING;
return (strcmp(attr, pattern->str)) ? 0 : -1;
#endif
case MATCH_AS_PATHNAME:
#ifdef HAVE_FNMATCH_H
return (fnmatch(pattern->str, attr, FNM_PATHNAME)) ? 0 : -1;
#else
LogMessageVerb(X_WARNING, 1, "Pathname matching requested but unavailable for \"%s\", resorting to search for substring\n", pattern->str);
pattern->mode = MATCH_AS_SUBSTRING;
return (strcmp(attr, pattern->str)) ? 0 : -1;
#endif
case MATCH_SUBSTRINGS_SEQUENCE:
default:
{
char* str = pattern->str;
while (*str) {
attr=strstr(attr, str);
if (!attr) return 0;
attr += strlen(str);
str += strlen(str);
str++;
}
}
return -1;
}
}
/*
* 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 xorg_list *patterns,
int (*compare) (const char *attr, const char *pattern))
Bool
MatchAttrToken(const char *attr, struct xorg_list *groups)
{
const xf86MatchGroup *group;
xf86MatchGroup *group;
xf86MatchPattern *pattern;
/* If there are no patterns, accept the match */
if (xorg_list_is_empty(patterns))
/* If there are no groups, accept the match */
if (xorg_list_is_empty(groups))
return TRUE;
/* If there are groups but no attribute, reject the match */
if (!attr)
return FALSE;
/*
* 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.
*/
xorg_list_for_each_entry(group, patterns, entry) {
char *const *cur;
Bool is_negated = group->is_negated;
Bool match = is_negated;
xorg_list_for_each_entry(group, groups, entry) {
Bool match = FALSE;
/* If there's a pattern but no attribute, we reject the match for a
* MatchFoo directive, and accept it for a NoMatchFoo directive
*/
if (!attr)
return is_negated;
for (cur = group->values; *cur; cur++)
if ((*compare) (attr, *cur) == 0) {
match = !is_negated;
break;
}
if (!match)
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
/* It is enough to find one pattern matched by the attribute */
match = ((!match_token(attr, pattern)) == pattern->is_negated);
if (match)
goto group_done;
}
group_done:
if (match == group->is_negated)
return FALSE;
}
@@ -619,34 +633,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;
/*
@@ -660,7 +674,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;
}
@@ -669,12 +683,17 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev,
return FALSE;
}
/* MatchLayout string */
if (!xorg_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 &&

View File

@@ -22,4 +22,6 @@ void xf86AddInputEventDrainCallback(CallbackProcPtr callback, void *param);
void xf86RemoveInputEventDrainCallback(CallbackProcPtr callback, void *param);
Bool MatchAttrToken(const char *attr, struct xorg_list *groups);
#endif /* _XSERVER__XF86XINPUT_H */

View File

@@ -54,6 +54,7 @@
#include "xf86Bus.h"
#include "Pci.h"
#include "xf86platformBus.h"
#include "xf86Xinput_priv.h"
#include "xf86Config.h"
#include "xf86Crtc.h"
@@ -176,50 +177,13 @@ xf86_check_platform_slot(const struct xf86_platform_device *pd)
return TRUE;
}
static Bool
MatchToken(const char *value, struct xorg_list *patterns,
int (*compare)(const char *, const char *))
{
const xf86MatchGroup *group;
/* If there are no patterns, accept the match */
if (xorg_list_is_empty(patterns))
return TRUE;
/* If there are patterns but no attribute, reject the match */
if (!value)
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.
*/
xorg_list_for_each_entry(group, patterns, entry) {
Bool match = FALSE;
char *const *cur;
for (cur = group->values; *cur; cur++) {
if ((*compare)(value, *cur) == 0) {
match = TRUE;
break;
}
}
if (!match)
return FALSE;
}
/* All the entries in the list matched the attribute */
return TRUE;
}
static Bool
OutputClassMatches(const XF86ConfOutputClassPtr oclass,
struct xf86_platform_device *dev)
{
char *driver = dev->attribs->driver;
if (!MatchToken(driver, &oclass->match_driver, strcmp))
if (!MatchAttrToken(driver, &oclass->match_driver))
return FALSE;
return TRUE;

View File

@@ -100,30 +100,13 @@ xf86freeInputClassList(XF86ConfInputClassPtr ptr)
#define CLEANUP xf86freeInputClassList
#define TOKEN_SEP "|"
enum MatchType {
MATCH_NORMAL,
MATCH_NEGATED,
};
static void
add_group_entry(struct xorg_list *head, char **values, enum MatchType type)
{
xf86MatchGroup *group = calloc(1, sizeof(xf86MatchGroup));
if (group) {
group->is_negated = (type == MATCH_NEGATED);
group->values = values;
xorg_list_add(&group->entry, head);
}
}
XF86ConfInputClassPtr
xf86parseInputClassSection(void)
{
int has_ident = FALSE;
int token;
enum MatchType matchtype;
Bool negated;
xf86MatchGroup *group;
parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec)
@@ -139,7 +122,7 @@ xf86parseInputClassSection(void)
xorg_list_init(&ptr->match_layout);
while ((token = xf86getToken(InputClassTab)) != ENDSECTION) {
matchtype = MATCH_NORMAL;
negated = FALSE;
switch (token) {
case COMMENT:
@@ -169,103 +152,121 @@ xf86parseInputClassSection(void)
ptr->option_lst = xf86parseOption(ptr->option_lst);
break;
case NOMATCH_PRODUCT:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_PRODUCT:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchProduct");
add_group_entry(&ptr->match_product,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_AS_SUBSTRING, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_product);
free(xf86_lex_val.str);
}
break;
case NOMATCH_VENDOR:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_VENDOR:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchVendor");
add_group_entry(&ptr->match_vendor,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_AS_SUBSTRING, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_vendor);
free(xf86_lex_val.str);
}
break;
case NOMATCH_DEVICE_PATH:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_DEVICE_PATH:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchDevicePath");
add_group_entry(&ptr->match_device,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_AS_PATHNAME, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_device);
free(xf86_lex_val.str);
}
break;
case NOMATCH_OS:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_OS:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchOS");
add_group_entry(&ptr->match_os, xstrtokenize(xf86_lex_val.str,
TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_EXACT_NOCASE, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_os);
free(xf86_lex_val.str);
}
break;
case NOMATCH_PNPID:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_PNPID:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchPnPID");
add_group_entry(&ptr->match_pnpid,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_AS_FILENAME, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_pnpid);
free(xf86_lex_val.str);
}
break;
case NOMATCH_USBID:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_USBID:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchUSBID");
add_group_entry(&ptr->match_usbid,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_AS_FILENAME, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_usbid);
free(xf86_lex_val.str);
}
break;
case NOMATCH_DRIVER:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_DRIVER:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchDriver");
add_group_entry(&ptr->match_driver,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_EXACT, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_driver);
free(xf86_lex_val.str);
}
break;
case NOMATCH_TAG:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_TAG:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchTag");
add_group_entry(&ptr->match_tag, xstrtokenize(xf86_lex_val.str,
TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_EXACT, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_tag);
free(xf86_lex_val.str);
}
break;
case NOMATCH_LAYOUT:
matchtype = MATCH_NEGATED;
negated = TRUE;
/* fallthrough */
case MATCH_LAYOUT:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchLayout");
add_group_entry(&ptr->match_layout,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
matchtype);
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_EXACT, negated);
if (group)
xorg_list_add(&group->entry, &ptr->match_layout);
free(xf86_lex_val.str);
}
break;
case MATCH_IS_KEYBOARD:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
@@ -348,10 +349,11 @@ xf86parseInputClassSection(void)
}
void
xf86printInputClassSection(FILE * cf, XF86ConfInputClassPtr ptr)
xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
{
const xf86MatchGroup *group;
char *const *cur;
const xf86MatchPattern *pattern;
Bool not_first;
while (ptr) {
fprintf(cf, "Section \"InputClass\"\n");
@@ -363,69 +365,95 @@ xf86printInputClassSection(FILE * cf, XF86ConfInputClassPtr ptr)
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchProduct \"");
else fprintf(cf, "\tMatchProduct \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchVendor \"");
else fprintf(cf, "\tMatchVendor \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchDevicePath \"");
else fprintf(cf, "\tMatchDevicePath \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchOS \"");
else fprintf(cf, "\tMatchOS \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchPnPID \"");
else fprintf(cf, "\tMatchPnPID \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchUSBID \"");
else fprintf(cf, "\tMatchUSBID \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchDriver \"");
else fprintf(cf, "\tMatchDriver \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchTAG \"");
else fprintf(cf, "\tMatchTAG \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
xorg_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);
if (group->is_negated) fprintf(cf, "\tNoMatchLayout \"");
else fprintf(cf, "\tMatchLayout \"");
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}
if (ptr->is_keyboard.set)
fprintf(cf, "\tIsKeyboard \"%s\"\n",
ptr->is_keyboard.val ? "yes" : "no");

View File

@@ -66,23 +66,12 @@ xf86freeOutputClassList(XF86ConfOutputClassPtr ptr)
#define CLEANUP xf86freeOutputClassList
#define TOKEN_SEP "|"
static void
add_group_entry(struct xorg_list *head, char **values)
{
xf86MatchGroup *group = calloc(1, sizeof(xf86MatchGroup));
if (group) {
group->values = values;
xorg_list_add(&group->entry, head);
}
}
XF86ConfOutputClassPtr
xf86parseOutputClassSection(void)
{
int has_ident = FALSE;
int token;
xf86MatchGroup *group;
parsePrologue(XF86ConfOutputClassPtr, XF86ConfOutputClassRec)
@@ -129,9 +118,12 @@ xf86parseOutputClassSection(void)
case MATCH_DRIVER:
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
Error(QUOTE_MSG, "MatchDriver");
add_group_entry(&ptr->match_driver,
xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
free(xf86_lex_val.str);
else {
group = xf86createMatchGroup(xf86_lex_val.str, MATCH_EXACT, FALSE);
if (group)
xorg_list_add(&group->entry, &ptr->match_driver);
free(xf86_lex_val.str);
}
break;
case EOF_TOKEN:
Error(UNEXPECTED_EOF_MSG);
@@ -151,11 +143,13 @@ xf86parseOutputClassSection(void)
return ptr;
}
void
xf86printOutputClassSection(FILE * cf, XF86ConfOutputClassPtr ptr)
{
const xf86MatchGroup *group;
char *const *cur;
const xf86MatchPattern *pattern;
Bool not_first;
while (ptr) {
fprintf(cf, "Section \"OutputClass\"\n");
@@ -168,9 +162,11 @@ xf86printOutputClassSection(FILE * cf, XF86ConfOutputClassPtr ptr)
xorg_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);
not_first = FALSE;
xorg_list_for_each_entry(pattern, &group->patterns, entry) {
xf86printMatchPattern(cf, pattern, not_first);
not_first = TRUE;
}
fprintf(cf, "\"\n");
}

View File

@@ -304,7 +304,6 @@ typedef struct {
typedef struct {
struct xorg_list entry;
char **values;
struct xorg_list patterns;
Bool is_negated;
} xf86MatchGroup;

View File

@@ -28,12 +28,12 @@ int xf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout);
static inline void xf86freeMatchGroup(xf86MatchGroup *group)
{
xorg_list_del(&group->entry);
if (group->values) {
for (char **list = group->values; *list; list++) {
free(*list);
*list = NULL;
}
group->values = NULL;
xf86MatchPattern *pattern, *next_pattern;
xorg_list_for_each_entry_safe(pattern, next_pattern, &group->patterns, entry) {
xorg_list_del(&pattern->entry);
if (pattern->str)
free(pattern->str);
free(pattern);
}
free(group);
}