1 /*
2 * Copyright (c) 1997 Metro Link Incorporated
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the Metro Link shall not be
23 * used in advertising or otherwise to promote the sale, use or other dealings
24 * in this Software without prior written authorization from Metro Link.
25 *
26 */
27 /*
28 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29 *
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
36 *
37 * The above copyright notice and this permission notice shall be included in
38 * all copies or substantial portions of the Software.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 * OTHER DEALINGS IN THE SOFTWARE.
47 *
48 * Except as contained in this notice, the name of the copyright holder(s)
49 * and author(s) shall not be used in advertising or otherwise to promote
50 * the sale, use or other dealings in this Software without prior written
51 * authorization from the copyright holder(s) and author(s).
52 */
53
54 #ifdef HAVE_XORG_CONFIG_H
55 #include <xorg-config.h>
56 #endif
57
58 #include "xf86Parser.h"
59 #include "xf86tokens.h"
60 #include "Configint.h"
61 #include <X11/Xfuncproto.h>
62 #include "Xprintf.h"
63 #include "optionstr.h"
64
65
66 static const xf86ConfigSymTabRec ServerFlagsTab[] = {
67 {ENDSECTION, "endsection"},
68 {DONTZAP, "dontzap"},
69 {DONTZOOM, "dontzoom"},
70 {DISABLEVIDMODE, "disablevidmodeextension"},
71 {ALLOWNONLOCAL, "allownonlocalxvidtune"},
72 {DISABLEMODINDEV, "disablemodindev"},
73 {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
74 {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
75 {OPTION, "option"},
76 {BLANKTIME, "blanktime"},
77 {STANDBYTIME, "standbytime"},
78 {SUSPENDTIME, "suspendtime"},
79 {OFFTIME, "offtime"},
80 {DEFAULTLAYOUT, "defaultserverlayout"},
81 {-1, ""},
82 };
83
84 #define CLEANUP xf86freeFlags
85
86 XF86ConfFlagsPtr
xf86parseFlagsSection(void)87 xf86parseFlagsSection(void)
88 {
89 int token;
90
91 parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
92
93 while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
94 int hasvalue = FALSE;
95 int strvalue = FALSE;
96 int tokentype;
97
98 switch (token) {
99 case COMMENT:
100 ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
101 break;
102 /*
103 * these old keywords are turned into standard generic options.
104 * we fall through here on purpose
105 */
106 case DEFAULTLAYOUT:
107 strvalue = TRUE;
108 case BLANKTIME:
109 case STANDBYTIME:
110 case SUSPENDTIME:
111 case OFFTIME:
112 hasvalue = TRUE;
113 case DONTZAP:
114 case DONTZOOM:
115 case DISABLEVIDMODE:
116 case ALLOWNONLOCAL:
117 case DISABLEMODINDEV:
118 case MODINDEVALLOWNONLOCAL:
119 case ALLOWMOUSEOPENFAIL:
120 {
121 int i = 0;
122
123 while (ServerFlagsTab[i].token != -1) {
124 char *tmp;
125
126 if (ServerFlagsTab[i].token == token) {
127 char *valstr = NULL;
128
129 tmp = strdup(ServerFlagsTab[i].name);
130 if (hasvalue) {
131 tokentype = xf86getSubToken(&(ptr->flg_comment));
132 if (strvalue) {
133 if (tokentype != STRING)
134 Error(QUOTE_MSG, tmp);
135 valstr = xf86_lex_val.str;
136 }
137 else {
138 if (tokentype != NUMBER)
139 Error(NUMBER_MSG, tmp);
140 if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
141 valstr = NULL;
142 }
143 }
144 ptr->flg_option_lst = xf86addNewOption
145 (ptr->flg_option_lst, tmp, valstr);
146 }
147 i++;
148 }
149 }
150 break;
151 case OPTION:
152 ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
153 break;
154
155 case EOF_TOKEN:
156 Error(UNEXPECTED_EOF_MSG);
157 break;
158 default:
159 Error(INVALID_KEYWORD_MSG, xf86tokenString());
160 break;
161 }
162 }
163
164 #ifdef DEBUG
165 printf("Flags section parsed\n");
166 #endif
167
168 return ptr;
169 }
170
171 #undef CLEANUP
172
173 void
xf86printServerFlagsSection(FILE * f,XF86ConfFlagsPtr flags)174 xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
175 {
176 XF86OptionPtr p;
177
178 if ((!flags) || (!flags->flg_option_lst))
179 return;
180 p = flags->flg_option_lst;
181 fprintf(f, "Section \"ServerFlags\"\n");
182 if (flags->flg_comment)
183 fprintf(f, "%s", flags->flg_comment);
184 xf86printOptionList(f, p, 1);
185 fprintf(f, "EndSection\n\n");
186 }
187
188 static XF86OptionPtr
addNewOption2(XF86OptionPtr head,char * name,char * _val,int used)189 addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
190 {
191 XF86OptionPtr new, old = NULL;
192
193 /* Don't allow duplicates, free old strings */
194 if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
195 new = old;
196 free(new->opt_name);
197 free(new->opt_val);
198 }
199 else
200 new = calloc(1, sizeof(*new));
201 new->opt_name = name;
202 new->opt_val = _val;
203 new->opt_used = used;
204
205 if (old)
206 return head;
207 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
208 }
209
210 XF86OptionPtr
xf86addNewOption(XF86OptionPtr head,char * name,char * _val)211 xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
212 {
213 return addNewOption2(head, name, _val, 0);
214 }
215
216 void
xf86freeFlags(XF86ConfFlagsPtr flags)217 xf86freeFlags(XF86ConfFlagsPtr flags)
218 {
219 if (flags == NULL)
220 return;
221 xf86optionListFree(flags->flg_option_lst);
222 TestFree(flags->flg_comment);
223 free(flags);
224 }
225
226 XF86OptionPtr
xf86optionListDup(XF86OptionPtr opt)227 xf86optionListDup(XF86OptionPtr opt)
228 {
229 XF86OptionPtr newopt = NULL;
230 char *_val;
231
232 while (opt) {
233 _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
234 newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
235 newopt->opt_used = opt->opt_used;
236 if (opt->opt_comment)
237 newopt->opt_comment = strdup(opt->opt_comment);
238 opt = opt->list.next;
239 }
240 return newopt;
241 }
242
243 void
xf86optionListFree(XF86OptionPtr opt)244 xf86optionListFree(XF86OptionPtr opt)
245 {
246 XF86OptionPtr prev;
247
248 while (opt) {
249 TestFree(opt->opt_name);
250 TestFree(opt->opt_val);
251 TestFree(opt->opt_comment);
252 prev = opt;
253 opt = opt->list.next;
254 free(prev);
255 }
256 }
257
258 char *
xf86optionName(XF86OptionPtr opt)259 xf86optionName(XF86OptionPtr opt)
260 {
261 if (opt)
262 return opt->opt_name;
263 return 0;
264 }
265
266 char *
xf86optionValue(XF86OptionPtr opt)267 xf86optionValue(XF86OptionPtr opt)
268 {
269 if (opt)
270 return opt->opt_val;
271 return 0;
272 }
273
274 XF86OptionPtr
xf86newOption(char * name,char * value)275 xf86newOption(char *name, char *value)
276 {
277 XF86OptionPtr opt;
278
279 opt = calloc(1, sizeof(*opt));
280 if (!opt)
281 return NULL;
282
283 opt->opt_used = 0;
284 opt->list.next = 0;
285 opt->opt_name = name;
286 opt->opt_val = value;
287
288 return opt;
289 }
290
291 XF86OptionPtr
xf86nextOption(XF86OptionPtr list)292 xf86nextOption(XF86OptionPtr list)
293 {
294 if (!list)
295 return NULL;
296 return list->list.next;
297 }
298
299 /*
300 * this function searches the given option list for the named option and
301 * returns a pointer to the option rec if found. If not found, it returns
302 * NULL
303 */
304
305 XF86OptionPtr
xf86findOption(XF86OptionPtr list,const char * name)306 xf86findOption(XF86OptionPtr list, const char *name)
307 {
308 while (list) {
309 if (xf86nameCompare(list->opt_name, name) == 0)
310 return list;
311 list = list->list.next;
312 }
313 return NULL;
314 }
315
316 /*
317 * this function searches the given option list for the named option. If
318 * found and the option has a parameter, a pointer to the parameter is
319 * returned. If the option does not have a parameter an empty string is
320 * returned. If the option is not found, a NULL is returned.
321 */
322
323 const char *
xf86findOptionValue(XF86OptionPtr list,const char * name)324 xf86findOptionValue(XF86OptionPtr list, const char *name)
325 {
326 XF86OptionPtr p = xf86findOption(list, name);
327
328 if (p) {
329 if (p->opt_val)
330 return p->opt_val;
331 else
332 return "";
333 }
334 return NULL;
335 }
336
337 XF86OptionPtr
xf86optionListCreate(const char ** options,int count,int used)338 xf86optionListCreate(const char **options, int count, int used)
339 {
340 XF86OptionPtr p = NULL;
341 char *t1, *t2;
342 int i;
343
344 if (count == -1) {
345 for (count = 0; options[count]; count++);
346 }
347 if ((count % 2) != 0) {
348 fprintf(stderr,
349 "xf86optionListCreate: count must be an even number.\n");
350 return NULL;
351 }
352 for (i = 0; i < count; i += 2) {
353 t1 = strdup(options[i]);
354 t2 = strdup(options[i + 1]);
355 p = addNewOption2(p, t1, t2, used);
356 }
357
358 return p;
359 }
360
361 /* the 2 given lists are merged. If an option with the same name is present in
362 * both, the option from the user list - specified in the second argument -
363 * is used. The end result is a single valid list of options. Duplicates
364 * are freed, and the original lists are no longer guaranteed to be complete.
365 */
366 XF86OptionPtr
xf86optionListMerge(XF86OptionPtr head,XF86OptionPtr tail)367 xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
368 {
369 XF86OptionPtr a, b, ap = NULL, bp = NULL;
370
371 a = tail;
372 b = head;
373 while (tail && b) {
374 if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
375 if (b == head)
376 head = a;
377 else
378 bp->list.next = a;
379 if (a == tail)
380 tail = a->list.next;
381 else
382 ap->list.next = a->list.next;
383 a->list.next = b->list.next;
384 b->list.next = NULL;
385 xf86optionListFree(b);
386 b = a->list.next;
387 bp = a;
388 a = tail;
389 ap = NULL;
390 }
391 else {
392 ap = a;
393 if (!(a = a->list.next)) {
394 a = tail;
395 bp = b;
396 b = b->list.next;
397 ap = NULL;
398 }
399 }
400 }
401
402 if (head) {
403 for (a = head; a->list.next; a = a->list.next);
404 a->list.next = tail;
405 }
406 else
407 head = tail;
408
409 return head;
410 }
411
412 char *
xf86uLongToString(unsigned long i)413 xf86uLongToString(unsigned long i)
414 {
415 char *s;
416
417 if (asprintf(&s, "%lu", i) == -1)
418 return NULL;
419 return s;
420 }
421
422 XF86OptionPtr
xf86parseOption(XF86OptionPtr head)423 xf86parseOption(XF86OptionPtr head)
424 {
425 XF86OptionPtr option, cnew, old;
426 char *name, *comment = NULL;
427 int token;
428
429 if ((token = xf86getSubToken(&comment)) != STRING) {
430 xf86parseError(BAD_OPTION_MSG);
431 free(comment);
432 return head;
433 }
434
435 name = xf86_lex_val.str;
436 if ((token = xf86getSubToken(&comment)) == STRING) {
437 option = xf86newOption(name, xf86_lex_val.str);
438 option->opt_comment = comment;
439 if ((token = xf86getToken(NULL)) == COMMENT)
440 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
441 else
442 xf86unGetToken(token);
443 }
444 else {
445 option = xf86newOption(name, NULL);
446 option->opt_comment = comment;
447 if (token == COMMENT)
448 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
449 else
450 xf86unGetToken(token);
451 }
452
453 old = NULL;
454
455 /* Don't allow duplicates */
456 if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
457 cnew = old;
458 free(option->opt_name);
459 TestFree(option->opt_val);
460 TestFree(option->opt_comment);
461 free(option);
462 }
463 else
464 cnew = option;
465
466 if (old == NULL)
467 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
468
469 return head;
470 }
471
472 void
xf86printOptionList(FILE * fp,XF86OptionPtr list,int tabs)473 xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
474 {
475 int i;
476
477 if (!list)
478 return;
479 while (list) {
480 for (i = 0; i < tabs; i++)
481 fputc('\t', fp);
482 if (list->opt_val)
483 fprintf(fp, "Option \"%s\" \"%s\"", list->opt_name,
484 list->opt_val);
485 else
486 fprintf(fp, "Option \"%s\"", list->opt_name);
487 if (list->opt_comment)
488 fprintf(fp, "%s", list->opt_comment);
489 else
490 fputc('\n', fp);
491 list = list->list.next;
492 }
493 }
494