1 /*
2  *
3  * Copyright (c) 1997  Metro Link Incorporated
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Except as contained in this notice, the name of the Metro Link shall not be
24  * used in advertising or otherwise to promote the sale, use or other dealings
25  * in this Software without prior written authorization from Metro Link.
26  *
27  */
28 /*
29  * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
30  *
31  * Permission is hereby granted, free of charge, to any person obtaining a
32  * copy of this software and associated documentation files (the "Software"),
33  * to deal in the Software without restriction, including without limitation
34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35  * and/or sell copies of the Software, and to permit persons to whom the
36  * Software is furnished to do so, subject to the following conditions:
37  *
38  * The above copyright notice and this permission notice shall be included in
39  * all copies or substantial portions of the Software.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47  * OTHER DEALINGS IN THE SOFTWARE.
48  *
49  * Except as contained in this notice, the name of the copyright holder(s)
50  * and author(s) shall not be used in advertising or otherwise to promote
51  * the sale, use or other dealings in this Software without prior written
52  * authorization from the copyright holder(s) and author(s).
53  */
54 
55 #ifdef HAVE_XORG_CONFIG_H
56 #include <xorg-config.h>
57 #endif
58 
59 #include "xf86Config.h"
60 #include "xf86Parser.h"
61 #include "xf86tokens.h"
62 #include "Configint.h"
63 
64 
65 static const xf86ConfigSymTabRec TopLevelTab[] = {
66     {SECTION, "section"},
67     {-1, ""},
68 };
69 
70 #define CLEANUP xf86freeConfig
71 
72 /*
73  * This function resolves name references and reports errors if the named
74  * objects cannot be found.
75  */
76 static int
xf86validateConfig(XF86ConfigPtr p)77 xf86validateConfig(XF86ConfigPtr p)
78 {
79     if (!xf86validateScreen(p))
80         return FALSE;
81     if (!xf86validateInput(p))
82         return FALSE;
83     if (!xf86validateLayout(p))
84         return FALSE;
85 
86     return TRUE;
87 }
88 
89 XF86ConfigPtr
xf86readConfigFile(void)90 xf86readConfigFile(void)
91 {
92     int token;
93     XF86ConfigPtr ptr = NULL;
94 
95     if ((ptr = xf86allocateConfig()) == NULL) {
96         return NULL;
97     }
98 
99     while ((token = xf86getToken(TopLevelTab)) != EOF_TOKEN) {
100         switch (token) {
101         case COMMENT:
102             ptr->conf_comment = xf86addComment(ptr->conf_comment, xf86_lex_val.str);
103             break;
104         case SECTION:
105             if (xf86getSubToken(&(ptr->conf_comment)) != STRING) {
106                 xf86parseError(QUOTE_MSG, "Section");
107                 CLEANUP(ptr);
108                 return NULL;
109             }
110             xf86setSection(xf86_lex_val.str);
111             if (xf86nameCompare(xf86_lex_val.str, "files") == 0) {
112                 free(xf86_lex_val.str);
113                 xf86_lex_val.str = NULL;
114                 HANDLE_RETURN(conf_files, xf86parseFilesSection());
115             }
116             else if (xf86nameCompare(xf86_lex_val.str, "serverflags") == 0) {
117                 free(xf86_lex_val.str);
118                 xf86_lex_val.str = NULL;
119                 HANDLE_RETURN(conf_flags, xf86parseFlagsSection());
120             }
121             else if (xf86nameCompare(xf86_lex_val.str, "pointer") == 0) {
122                 free(xf86_lex_val.str);
123                 xf86_lex_val.str = NULL;
124                 HANDLE_LIST(conf_input_lst, xf86parsePointerSection,
125                             XF86ConfInputPtr);
126             }
127             else if (xf86nameCompare(xf86_lex_val.str, "videoadaptor") == 0) {
128                 free(xf86_lex_val.str);
129                 xf86_lex_val.str = NULL;
130                 HANDLE_LIST(conf_videoadaptor_lst, xf86parseVideoAdaptorSection,
131                             XF86ConfVideoAdaptorPtr);
132             }
133             else if (xf86nameCompare(xf86_lex_val.str, "device") == 0) {
134                 free(xf86_lex_val.str);
135                 xf86_lex_val.str = NULL;
136                 HANDLE_LIST(conf_device_lst, xf86parseDeviceSection,
137                             XF86ConfDevicePtr);
138             }
139             else if (xf86nameCompare(xf86_lex_val.str, "monitor") == 0) {
140                 free(xf86_lex_val.str);
141                 xf86_lex_val.str = NULL;
142                 HANDLE_LIST(conf_monitor_lst, xf86parseMonitorSection,
143                             XF86ConfMonitorPtr);
144             }
145             else if (xf86nameCompare(xf86_lex_val.str, "modes") == 0) {
146                 free(xf86_lex_val.str);
147                 xf86_lex_val.str = NULL;
148                 HANDLE_LIST(conf_modes_lst, xf86parseModesSection,
149                             XF86ConfModesPtr);
150             }
151             else if (xf86nameCompare(xf86_lex_val.str, "screen") == 0) {
152                 free(xf86_lex_val.str);
153                 xf86_lex_val.str = NULL;
154                 HANDLE_LIST(conf_screen_lst, xf86parseScreenSection,
155                             XF86ConfScreenPtr);
156             }
157             else if (xf86nameCompare(xf86_lex_val.str, "inputdevice") == 0) {
158                 free(xf86_lex_val.str);
159                 xf86_lex_val.str = NULL;
160                 HANDLE_LIST(conf_input_lst, xf86parseInputSection,
161                             XF86ConfInputPtr);
162             }
163             else if (xf86nameCompare(xf86_lex_val.str, "inputclass") == 0) {
164                 free(xf86_lex_val.str);
165                 xf86_lex_val.str = NULL;
166                 HANDLE_LIST(conf_inputclass_lst,
167                             xf86parseInputClassSection, XF86ConfInputClassPtr);
168             }
169             else if (xf86nameCompare(xf86_lex_val.str, "outputclass") == 0) {
170                 free(xf86_lex_val.str);
171                 xf86_lex_val.str = NULL;
172                 HANDLE_LIST(conf_outputclass_lst, xf86parseOutputClassSection,
173                             XF86ConfOutputClassPtr);
174             }
175             else if (xf86nameCompare(xf86_lex_val.str, "module") == 0) {
176                 free(xf86_lex_val.str);
177                 xf86_lex_val.str = NULL;
178                 HANDLE_RETURN(conf_modules, xf86parseModuleSection());
179             }
180             else if (xf86nameCompare(xf86_lex_val.str, "serverlayout") == 0) {
181                 free(xf86_lex_val.str);
182                 xf86_lex_val.str = NULL;
183                 HANDLE_LIST(conf_layout_lst, xf86parseLayoutSection,
184                             XF86ConfLayoutPtr);
185             }
186             else if (xf86nameCompare(xf86_lex_val.str, "vendor") == 0) {
187                 free(xf86_lex_val.str);
188                 xf86_lex_val.str = NULL;
189                 HANDLE_LIST(conf_vendor_lst, xf86parseVendorSection,
190                             XF86ConfVendorPtr);
191             }
192             else if (xf86nameCompare(xf86_lex_val.str, "dri") == 0) {
193                 free(xf86_lex_val.str);
194                 xf86_lex_val.str = NULL;
195                 HANDLE_RETURN(conf_dri, xf86parseDRISection());
196             }
197             else if (xf86nameCompare(xf86_lex_val.str, "extensions") == 0) {
198                 free(xf86_lex_val.str);
199                 xf86_lex_val.str = NULL;
200                 HANDLE_RETURN(conf_extensions, xf86parseExtensionsSection());
201             }
202             else {
203                 free(xf86_lex_val.str);
204                 xf86_lex_val.str = NULL;
205                 Error(INVALID_SECTION_MSG, xf86tokenString());
206             }
207             break;
208         default:
209             free(xf86_lex_val.str);
210             xf86_lex_val.str = NULL;
211             Error(INVALID_KEYWORD_MSG, xf86tokenString());
212         }
213     }
214 
215     if (xf86validateConfig(ptr))
216         return ptr;
217     else {
218         CLEANUP(ptr);
219         return NULL;
220     }
221 }
222 
223 #undef CLEANUP
224 
225 /*
226  * adds an item to the end of the linked list. Any record whose first field
227  * is a GenericListRec can be cast to this type and used with this function.
228  * A pointer to the head of the list is returned to handle the addition of
229  * the first item.
230  */
231 GenericListPtr
xf86addListItem(GenericListPtr head,GenericListPtr new)232 xf86addListItem(GenericListPtr head, GenericListPtr new)
233 {
234     GenericListPtr p = head;
235     GenericListPtr last = NULL;
236 
237     while (p) {
238         last = p;
239         p = p->next;
240     }
241 
242     if (last) {
243         last->next = new;
244         return head;
245     }
246     else
247         return new;
248 }
249 
250 /*
251  * Test if one chained list contains the other.
252  * In this case both list have the same endpoint (provided they don't loop)
253  */
254 int
xf86itemNotSublist(GenericListPtr list_1,GenericListPtr list_2)255 xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2)
256 {
257     GenericListPtr p = list_1;
258     GenericListPtr last_1 = NULL, last_2 = NULL;
259 
260     while (p) {
261         last_1 = p;
262         p = p->next;
263     }
264 
265     p = list_2;
266     while (p) {
267         last_2 = p;
268         p = p->next;
269     }
270 
271     return (!(last_1 == last_2));
272 }
273 
274 /*
275  * Conditionally allocate config struct, but only allocate it
276  * if it's not already there.  In either event, return the pointer
277  * to the global config struct.
278  */
xf86allocateConfig(void)279 XF86ConfigPtr xf86allocateConfig(void)
280 {
281     if (!xf86configptr) {
282         xf86configptr = calloc(1, sizeof(XF86ConfigRec));
283     }
284     return xf86configptr;
285 }
286 
287 void
xf86freeConfig(XF86ConfigPtr p)288 xf86freeConfig(XF86ConfigPtr p)
289 {
290     if (p == NULL)
291         return;
292 
293     xf86freeFiles(p->conf_files);
294     xf86freeModules(p->conf_modules);
295     xf86freeFlags(p->conf_flags);
296     xf86freeMonitorList(p->conf_monitor_lst);
297     xf86freeModesList(p->conf_modes_lst);
298     xf86freeVideoAdaptorList(p->conf_videoadaptor_lst);
299     xf86freeDeviceList(p->conf_device_lst);
300     xf86freeScreenList(p->conf_screen_lst);
301     xf86freeLayoutList(p->conf_layout_lst);
302     xf86freeInputList(p->conf_input_lst);
303     xf86freeVendorList(p->conf_vendor_lst);
304     xf86freeDRI(p->conf_dri);
305     xf86freeExtensions(p->conf_extensions);
306     TestFree(p->conf_comment);
307 
308     free(p);
309 }
310