InputClass.c revision 35c4bbdf
1/*
2 * Copyright (c) 2009 Dan Nicholson
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifdef HAVE_XORG_CONFIG_H
27#include <xorg-config.h>
28#endif
29
30#include <string.h>
31#include "os.h"
32#include "xf86Parser.h"
33#include "xf86tokens.h"
34#include "Configint.h"
35
36
37static
38xf86ConfigSymTabRec InputClassTab[] = {
39    {ENDSECTION, "endsection"},
40    {IDENTIFIER, "identifier"},
41    {OPTION, "option"},
42    {DRIVER, "driver"},
43    {MATCH_PRODUCT, "matchproduct"},
44    {MATCH_VENDOR, "matchvendor"},
45    {MATCH_DEVICE_PATH, "matchdevicepath"},
46    {MATCH_OS, "matchos"},
47    {MATCH_PNPID, "matchpnpid"},
48    {MATCH_USBID, "matchusbid"},
49    {MATCH_DRIVER, "matchdriver"},
50    {MATCH_TAG, "matchtag"},
51    {MATCH_LAYOUT, "matchlayout"},
52    {MATCH_IS_KEYBOARD, "matchiskeyboard"},
53    {MATCH_IS_POINTER, "matchispointer"},
54    {MATCH_IS_JOYSTICK, "matchisjoystick"},
55    {MATCH_IS_TABLET, "matchistablet"},
56    {MATCH_IS_TOUCHPAD, "matchistouchpad"},
57    {MATCH_IS_TOUCHSCREEN, "matchistouchscreen"},
58    {-1, ""},
59};
60
61static void
62xf86freeInputClassList(XF86ConfInputClassPtr ptr)
63{
64    XF86ConfInputClassPtr prev;
65
66    while (ptr) {
67        xf86MatchGroup *group, *next;
68        char **list;
69
70        TestFree(ptr->identifier);
71        TestFree(ptr->driver);
72
73        xorg_list_for_each_entry_safe(group, next, &ptr->match_product, entry) {
74            xorg_list_del(&group->entry);
75            for (list = group->values; *list; list++)
76                free(*list);
77            free(group);
78        }
79        xorg_list_for_each_entry_safe(group, next, &ptr->match_vendor, entry) {
80            xorg_list_del(&group->entry);
81            for (list = group->values; *list; list++)
82                free(*list);
83            free(group);
84        }
85        xorg_list_for_each_entry_safe(group, next, &ptr->match_device, entry) {
86            xorg_list_del(&group->entry);
87            for (list = group->values; *list; list++)
88                free(*list);
89            free(group);
90        }
91        xorg_list_for_each_entry_safe(group, next, &ptr->match_os, entry) {
92            xorg_list_del(&group->entry);
93            for (list = group->values; *list; list++)
94                free(*list);
95            free(group);
96        }
97        xorg_list_for_each_entry_safe(group, next, &ptr->match_pnpid, entry) {
98            xorg_list_del(&group->entry);
99            for (list = group->values; *list; list++)
100                free(*list);
101            free(group);
102        }
103        xorg_list_for_each_entry_safe(group, next, &ptr->match_usbid, entry) {
104            xorg_list_del(&group->entry);
105            for (list = group->values; *list; list++)
106                free(*list);
107            free(group);
108        }
109        xorg_list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
110            xorg_list_del(&group->entry);
111            for (list = group->values; *list; list++)
112                free(*list);
113            free(group);
114        }
115        xorg_list_for_each_entry_safe(group, next, &ptr->match_tag, entry) {
116            xorg_list_del(&group->entry);
117            for (list = group->values; *list; list++)
118                free(*list);
119            free(group);
120        }
121        xorg_list_for_each_entry_safe(group, next, &ptr->match_layout, entry) {
122            xorg_list_del(&group->entry);
123            for (list = group->values; *list; list++)
124                free(*list);
125            free(group);
126        }
127
128        TestFree(ptr->comment);
129        xf86optionListFree(ptr->option_lst);
130
131        prev = ptr;
132        ptr = ptr->list.next;
133        free(prev);
134    }
135}
136
137#define CLEANUP xf86freeInputClassList
138
139#define TOKEN_SEP "|"
140
141static void
142add_group_entry(struct xorg_list *head, char **values)
143{
144    xf86MatchGroup *group;
145
146    group = malloc(sizeof(*group));
147    if (group) {
148        group->values = values;
149        xorg_list_add(&group->entry, head);
150    }
151}
152
153XF86ConfInputClassPtr
154xf86parseInputClassSection(void)
155{
156    int has_ident = FALSE;
157    int token;
158
159    parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec)
160
161        /* Initialize MatchGroup lists */
162        xorg_list_init(&ptr->match_product);
163    xorg_list_init(&ptr->match_vendor);
164    xorg_list_init(&ptr->match_device);
165    xorg_list_init(&ptr->match_os);
166    xorg_list_init(&ptr->match_pnpid);
167    xorg_list_init(&ptr->match_usbid);
168    xorg_list_init(&ptr->match_driver);
169    xorg_list_init(&ptr->match_tag);
170    xorg_list_init(&ptr->match_layout);
171
172    while ((token = xf86getToken(InputClassTab)) != ENDSECTION) {
173        switch (token) {
174        case COMMENT:
175            ptr->comment = xf86addComment(ptr->comment, xf86_lex_val.str);
176            break;
177        case IDENTIFIER:
178            if (xf86getSubToken(&(ptr->comment)) != STRING)
179                Error(QUOTE_MSG, "Identifier");
180            if (has_ident == TRUE)
181                Error(MULTIPLE_MSG, "Identifier");
182            ptr->identifier = xf86_lex_val.str;
183            has_ident = TRUE;
184            break;
185        case DRIVER:
186            if (xf86getSubToken(&(ptr->comment)) != STRING)
187                Error(QUOTE_MSG, "Driver");
188            if (strcmp(xf86_lex_val.str, "keyboard") == 0) {
189                ptr->driver = strdup("kbd");
190                free(xf86_lex_val.str);
191            }
192            else
193                ptr->driver = xf86_lex_val.str;
194            break;
195        case OPTION:
196            ptr->option_lst = xf86parseOption(ptr->option_lst);
197            break;
198        case MATCH_PRODUCT:
199            if (xf86getSubToken(&(ptr->comment)) != STRING)
200                Error(QUOTE_MSG, "MatchProduct");
201            add_group_entry(&ptr->match_product,
202                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
203            free(xf86_lex_val.str);
204            break;
205        case MATCH_VENDOR:
206            if (xf86getSubToken(&(ptr->comment)) != STRING)
207                Error(QUOTE_MSG, "MatchVendor");
208            add_group_entry(&ptr->match_vendor,
209                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
210            free(xf86_lex_val.str);
211            break;
212        case MATCH_DEVICE_PATH:
213            if (xf86getSubToken(&(ptr->comment)) != STRING)
214                Error(QUOTE_MSG, "MatchDevicePath");
215            add_group_entry(&ptr->match_device,
216                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
217            free(xf86_lex_val.str);
218            break;
219        case MATCH_OS:
220            if (xf86getSubToken(&(ptr->comment)) != STRING)
221                Error(QUOTE_MSG, "MatchOS");
222            add_group_entry(&ptr->match_os, xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
223            free(xf86_lex_val.str);
224            break;
225        case MATCH_PNPID:
226            if (xf86getSubToken(&(ptr->comment)) != STRING)
227                Error(QUOTE_MSG, "MatchPnPID");
228            add_group_entry(&ptr->match_pnpid,
229                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
230            free(xf86_lex_val.str);
231            break;
232        case MATCH_USBID:
233            if (xf86getSubToken(&(ptr->comment)) != STRING)
234                Error(QUOTE_MSG, "MatchUSBID");
235            add_group_entry(&ptr->match_usbid,
236                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
237            free(xf86_lex_val.str);
238            break;
239        case MATCH_DRIVER:
240            if (xf86getSubToken(&(ptr->comment)) != STRING)
241                Error(QUOTE_MSG, "MatchDriver");
242            add_group_entry(&ptr->match_driver,
243                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
244            free(xf86_lex_val.str);
245            break;
246        case MATCH_TAG:
247            if (xf86getSubToken(&(ptr->comment)) != STRING)
248                Error(QUOTE_MSG, "MatchTag");
249            add_group_entry(&ptr->match_tag, xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
250            free(xf86_lex_val.str);
251            break;
252        case MATCH_LAYOUT:
253            if (xf86getSubToken(&(ptr->comment)) != STRING)
254                Error(QUOTE_MSG, "MatchLayout");
255            add_group_entry(&ptr->match_layout,
256                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
257            free(xf86_lex_val.str);
258            break;
259        case MATCH_IS_KEYBOARD:
260            if (xf86getSubToken(&(ptr->comment)) != STRING)
261                Error(QUOTE_MSG, "MatchIsKeyboard");
262            ptr->is_keyboard.set = xf86getBoolValue(&ptr->is_keyboard.val,
263                                                    xf86_lex_val.str);
264            free(xf86_lex_val.str);
265            if (!ptr->is_keyboard.set)
266                Error(BOOL_MSG, "MatchIsKeyboard");
267            break;
268        case MATCH_IS_POINTER:
269            if (xf86getSubToken(&(ptr->comment)) != STRING)
270                Error(QUOTE_MSG, "MatchIsPointer");
271            ptr->is_pointer.set = xf86getBoolValue(&ptr->is_pointer.val,
272                                                   xf86_lex_val.str);
273            free(xf86_lex_val.str);
274            if (!ptr->is_pointer.set)
275                Error(BOOL_MSG, "MatchIsPointer");
276            break;
277        case MATCH_IS_JOYSTICK:
278            if (xf86getSubToken(&(ptr->comment)) != STRING)
279                Error(QUOTE_MSG, "MatchIsJoystick");
280            ptr->is_joystick.set = xf86getBoolValue(&ptr->is_joystick.val,
281                                                    xf86_lex_val.str);
282            free(xf86_lex_val.str);
283            if (!ptr->is_joystick.set)
284                Error(BOOL_MSG, "MatchIsJoystick");
285            break;
286        case MATCH_IS_TABLET:
287            if (xf86getSubToken(&(ptr->comment)) != STRING)
288                Error(QUOTE_MSG, "MatchIsTablet");
289            ptr->is_tablet.set = xf86getBoolValue(&ptr->is_tablet.val, xf86_lex_val.str);
290            free(xf86_lex_val.str);
291            if (!ptr->is_tablet.set)
292                Error(BOOL_MSG, "MatchIsTablet");
293            break;
294        case MATCH_IS_TOUCHPAD:
295            if (xf86getSubToken(&(ptr->comment)) != STRING)
296                Error(QUOTE_MSG, "MatchIsTouchpad");
297            ptr->is_touchpad.set = xf86getBoolValue(&ptr->is_touchpad.val,
298                                                    xf86_lex_val.str);
299            free(xf86_lex_val.str);
300            if (!ptr->is_touchpad.set)
301                Error(BOOL_MSG, "MatchIsTouchpad");
302            break;
303        case MATCH_IS_TOUCHSCREEN:
304            if (xf86getSubToken(&(ptr->comment)) != STRING)
305                Error(QUOTE_MSG, "MatchIsTouchscreen");
306            ptr->is_touchscreen.set = xf86getBoolValue(&ptr->is_touchscreen.val,
307                                                       xf86_lex_val.str);
308            free(xf86_lex_val.str);
309            if (!ptr->is_touchscreen.set)
310                Error(BOOL_MSG, "MatchIsTouchscreen");
311            break;
312        case EOF_TOKEN:
313            Error(UNEXPECTED_EOF_MSG);
314            break;
315        default:
316            Error(INVALID_KEYWORD_MSG, xf86tokenString());
317            break;
318        }
319    }
320
321    if (!has_ident)
322        Error(NO_IDENT_MSG);
323
324#ifdef DEBUG
325    printf("InputClass section parsed\n");
326#endif
327
328    return ptr;
329}
330
331void
332xf86printInputClassSection(FILE * cf, XF86ConfInputClassPtr ptr)
333{
334    const xf86MatchGroup *group;
335    char *const *cur;
336
337    while (ptr) {
338        fprintf(cf, "Section \"InputClass\"\n");
339        if (ptr->comment)
340            fprintf(cf, "%s", ptr->comment);
341        if (ptr->identifier)
342            fprintf(cf, "\tIdentifier      \"%s\"\n", ptr->identifier);
343        if (ptr->driver)
344            fprintf(cf, "\tDriver          \"%s\"\n", ptr->driver);
345
346        xorg_list_for_each_entry(group, &ptr->match_product, entry) {
347            fprintf(cf, "\tMatchProduct    \"");
348            for (cur = group->values; *cur; cur++)
349                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
350                        *cur);
351            fprintf(cf, "\"\n");
352        }
353        xorg_list_for_each_entry(group, &ptr->match_vendor, entry) {
354            fprintf(cf, "\tMatchVendor     \"");
355            for (cur = group->values; *cur; cur++)
356                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
357                        *cur);
358            fprintf(cf, "\"\n");
359        }
360        xorg_list_for_each_entry(group, &ptr->match_device, entry) {
361            fprintf(cf, "\tMatchDevicePath \"");
362            for (cur = group->values; *cur; cur++)
363                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
364                        *cur);
365            fprintf(cf, "\"\n");
366        }
367        xorg_list_for_each_entry(group, &ptr->match_os, entry) {
368            fprintf(cf, "\tMatchOS         \"");
369            for (cur = group->values; *cur; cur++)
370                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
371                        *cur);
372            fprintf(cf, "\"\n");
373        }
374        xorg_list_for_each_entry(group, &ptr->match_pnpid, entry) {
375            fprintf(cf, "\tMatchPnPID      \"");
376            for (cur = group->values; *cur; cur++)
377                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
378                        *cur);
379            fprintf(cf, "\"\n");
380        }
381        xorg_list_for_each_entry(group, &ptr->match_usbid, entry) {
382            fprintf(cf, "\tMatchUSBID      \"");
383            for (cur = group->values; *cur; cur++)
384                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
385                        *cur);
386            fprintf(cf, "\"\n");
387        }
388        xorg_list_for_each_entry(group, &ptr->match_driver, entry) {
389            fprintf(cf, "\tMatchDriver     \"");
390            for (cur = group->values; *cur; cur++)
391                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
392                        *cur);
393            fprintf(cf, "\"\n");
394        }
395        xorg_list_for_each_entry(group, &ptr->match_tag, entry) {
396            fprintf(cf, "\tMatchTag        \"");
397            for (cur = group->values; *cur; cur++)
398                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
399                        *cur);
400            fprintf(cf, "\"\n");
401        }
402        xorg_list_for_each_entry(group, &ptr->match_layout, entry) {
403            fprintf(cf, "\tMatchLayout     \"");
404            for (cur = group->values; *cur; cur++)
405                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
406                        *cur);
407            fprintf(cf, "\"\n");
408        }
409
410        if (ptr->is_keyboard.set)
411            fprintf(cf, "\tIsKeyboard      \"%s\"\n",
412                    ptr->is_keyboard.val ? "yes" : "no");
413        if (ptr->is_pointer.set)
414            fprintf(cf, "\tIsPointer       \"%s\"\n",
415                    ptr->is_pointer.val ? "yes" : "no");
416        if (ptr->is_joystick.set)
417            fprintf(cf, "\tIsJoystick      \"%s\"\n",
418                    ptr->is_joystick.val ? "yes" : "no");
419        if (ptr->is_tablet.set)
420            fprintf(cf, "\tIsTablet        \"%s\"\n",
421                    ptr->is_tablet.val ? "yes" : "no");
422        if (ptr->is_touchpad.set)
423            fprintf(cf, "\tIsTouchpad      \"%s\"\n",
424                    ptr->is_touchpad.val ? "yes" : "no");
425        if (ptr->is_touchscreen.set)
426            fprintf(cf, "\tIsTouchscreen   \"%s\"\n",
427                    ptr->is_touchscreen.val ? "yes" : "no");
428        xf86printOptionList(cf, ptr->option_lst, 1);
429        fprintf(cf, "EndSection\n\n");
430        ptr = ptr->list.next;
431    }
432}
433