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 {NOTRAPSIGNALS, "notrapsignals"},
69 {DONTZAP, "dontzap"},
70 {DONTZOOM, "dontzoom"},
71 {DISABLEVIDMODE, "disablevidmodeextension"},
72 {ALLOWNONLOCAL, "allownonlocalxvidtune"},
73 {DISABLEMODINDEV, "disablemodindev"},
74 {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
75 {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
76 {OPTION, "option"},
77 {BLANKTIME, "blanktime"},
78 {STANDBYTIME, "standbytime"},
79 {SUSPENDTIME, "suspendtime"},
80 {OFFTIME, "offtime"},
81 {DEFAULTLAYOUT, "defaultserverlayout"},
82 {-1, ""},
83 };
84
85 #define CLEANUP xf86freeFlags
86
87 XF86ConfFlagsPtr
xf86parseFlagsSection(void)88 xf86parseFlagsSection(void)
89 {
90 int token;
91
92 parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
93
94 while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
95 int hasvalue = FALSE;
96 int strvalue = FALSE;
97 int tokentype;
98
99 switch (token) {
100 case COMMENT:
101 ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
102 break;
103 /*
104 * these old keywords are turned into standard generic options.
105 * we fall through here on purpose
106 */
107 case DEFAULTLAYOUT:
108 strvalue = TRUE;
109 case BLANKTIME:
110 case STANDBYTIME:
111 case SUSPENDTIME:
112 case OFFTIME:
113 hasvalue = TRUE;
114 case NOTRAPSIGNALS:
115 case DONTZAP:
116 case DONTZOOM:
117 case DISABLEVIDMODE:
118 case ALLOWNONLOCAL:
119 case DISABLEMODINDEV:
120 case MODINDEVALLOWNONLOCAL:
121 case ALLOWMOUSEOPENFAIL:
122 {
123 int i = 0;
124
125 while (ServerFlagsTab[i].token != -1) {
126 char *tmp;
127
128 if (ServerFlagsTab[i].token == token) {
129 char *valstr = NULL;
130
131 tmp = strdup(ServerFlagsTab[i].name);
132 if (hasvalue) {
133 tokentype = xf86getSubToken(&(ptr->flg_comment));
134 if (strvalue) {
135 if (tokentype != STRING)
136 Error(QUOTE_MSG, tmp);
137 valstr = xf86_lex_val.str;
138 }
139 else {
140 if (tokentype != NUMBER)
141 Error(NUMBER_MSG, tmp);
142 if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
143 valstr = NULL;
144 }
145 }
146 ptr->flg_option_lst = xf86addNewOption
147 (ptr->flg_option_lst, tmp, valstr);
148 }
149 i++;
150 }
151 }
152 break;
153 case OPTION:
154 ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
155 break;
156
157 case EOF_TOKEN:
158 Error(UNEXPECTED_EOF_MSG);
159 break;
160 default:
161 Error(INVALID_KEYWORD_MSG, xf86tokenString());
162 break;
163 }
164 }
165
166 #ifdef DEBUG
167 printf("Flags section parsed\n");
168 #endif
169
170 return ptr;
171 }
172
173 #undef CLEANUP
174
175 void
xf86printServerFlagsSection(FILE * f,XF86ConfFlagsPtr flags)176 xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
177 {
178 XF86OptionPtr p;
179
180 if ((!flags) || (!flags->flg_option_lst))
181 return;
182 p = flags->flg_option_lst;
183 fprintf(f, "Section \"ServerFlags\"\n");
184 if (flags->flg_comment)
185 fprintf(f, "%s", flags->flg_comment);
186 xf86printOptionList(f, p, 1);
187 fprintf(f, "EndSection\n\n");
188 }
189
190 static XF86OptionPtr
addNewOption2(XF86OptionPtr head,char * name,char * _val,int used)191 addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
192 {
193 XF86OptionPtr new, old = NULL;
194
195 /* Don't allow duplicates, free old strings */
196 if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
197 new = old;
198 free(new->opt_name);
199 free(new->opt_val);
200 }
201 else
202 new = calloc(1, sizeof(*new));
203 new->opt_name = name;
204 new->opt_val = _val;
205 new->opt_used = used;
206
207 if (old)
208 return head;
209 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
210 }
211
212 XF86OptionPtr
xf86addNewOption(XF86OptionPtr head,char * name,char * _val)213 xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
214 {
215 return addNewOption2(head, name, _val, 0);
216 }
217
218 void
xf86freeFlags(XF86ConfFlagsPtr flags)219 xf86freeFlags(XF86ConfFlagsPtr flags)
220 {
221 if (flags == NULL)
222 return;
223 xf86optionListFree(flags->flg_option_lst);
224 TestFree(flags->flg_comment);
225 free(flags);
226 }
227
228 XF86OptionPtr
xf86optionListDup(XF86OptionPtr opt)229 xf86optionListDup(XF86OptionPtr opt)
230 {
231 XF86OptionPtr newopt = NULL;
232 char *_val;
233
234 while (opt) {
235 _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
236 newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
237 newopt->opt_used = opt->opt_used;
238 if (opt->opt_comment)
239 newopt->opt_comment = strdup(opt->opt_comment);
240 opt = opt->list.next;
241 }
242 return newopt;
243 }
244
245 void
xf86optionListFree(XF86OptionPtr opt)246 xf86optionListFree(XF86OptionPtr opt)
247 {
248 XF86OptionPtr prev;
249
250 while (opt) {
251 TestFree(opt->opt_name);
252 TestFree(opt->opt_val);
253 TestFree(opt->opt_comment);
254 prev = opt;
255 opt = opt->list.next;
256 free(prev);
257 }
258 }
259
260 char *
xf86optionName(XF86OptionPtr opt)261 xf86optionName(XF86OptionPtr opt)
262 {
263 if (opt)
264 return opt->opt_name;
265 return 0;
266 }
267
268 char *
xf86optionValue(XF86OptionPtr opt)269 xf86optionValue(XF86OptionPtr opt)
270 {
271 if (opt)
272 return opt->opt_val;
273 return 0;
274 }
275
276 XF86OptionPtr
xf86newOption(char * name,char * value)277 xf86newOption(char *name, char *value)
278 {
279 XF86OptionPtr opt;
280
281 opt = calloc(1, sizeof(*opt));
282 if (!opt)
283 return NULL;
284
285 opt->opt_used = 0;
286 opt->list.next = 0;
287 opt->opt_name = name;
288 opt->opt_val = value;
289
290 return opt;
291 }
292
293 XF86OptionPtr
xf86nextOption(XF86OptionPtr list)294 xf86nextOption(XF86OptionPtr list)
295 {
296 if (!list)
297 return NULL;
298 return list->list.next;
299 }
300
301 /*
302 * this function searches the given option list for the named option and
303 * returns a pointer to the option rec if found. If not found, it returns
304 * NULL
305 */
306
307 XF86OptionPtr
xf86findOption(XF86OptionPtr list,const char * name)308 xf86findOption(XF86OptionPtr list, const char *name)
309 {
310 while (list) {
311 if (xf86nameCompare(list->opt_name, name) == 0)
312 return list;
313 list = list->list.next;
314 }
315 return NULL;
316 }
317
318 /*
319 * this function searches the given option list for the named option. If
320 * found and the option has a parameter, a pointer to the parameter is
321 * returned. If the option does not have a parameter an empty string is
322 * returned. If the option is not found, a NULL is returned.
323 */
324
325 const char *
xf86findOptionValue(XF86OptionPtr list,const char * name)326 xf86findOptionValue(XF86OptionPtr list, const char *name)
327 {
328 XF86OptionPtr p = xf86findOption(list, name);
329
330 if (p) {
331 if (p->opt_val)
332 return p->opt_val;
333 else
334 return "";
335 }
336 return NULL;
337 }
338
339 XF86OptionPtr
xf86optionListCreate(const char ** options,int count,int used)340 xf86optionListCreate(const char **options, int count, int used)
341 {
342 XF86OptionPtr p = NULL;
343 char *t1, *t2;
344 int i;
345
346 if (count == -1) {
347 for (count = 0; options[count]; count++);
348 }
349 if ((count % 2) != 0) {
350 fprintf(stderr,
351 "xf86optionListCreate: count must be an even number.\n");
352 return NULL;
353 }
354 for (i = 0; i < count; i += 2) {
355 t1 = strdup(options[i]);
356 t2 = strdup(options[i + 1]);
357 p = addNewOption2(p, t1, t2, used);
358 }
359
360 return p;
361 }
362
363 /* the 2 given lists are merged. If an option with the same name is present in
364 * both, the option from the user list - specified in the second argument -
365 * is used. The end result is a single valid list of options. Duplicates
366 * are freed, and the original lists are no longer guaranteed to be complete.
367 */
368 XF86OptionPtr
xf86optionListMerge(XF86OptionPtr head,XF86OptionPtr tail)369 xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
370 {
371 XF86OptionPtr a, b, ap = NULL, bp = NULL;
372
373 a = tail;
374 b = head;
375 while (tail && b) {
376 if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
377 if (b == head)
378 head = a;
379 else
380 bp->list.next = a;
381 if (a == tail)
382 tail = a->list.next;
383 else
384 ap->list.next = a->list.next;
385 a->list.next = b->list.next;
386 b->list.next = NULL;
387 xf86optionListFree(b);
388 b = a->list.next;
389 bp = a;
390 a = tail;
391 ap = NULL;
392 }
393 else {
394 ap = a;
395 if (!(a = a->list.next)) {
396 a = tail;
397 bp = b;
398 b = b->list.next;
399 ap = NULL;
400 }
401 }
402 }
403
404 if (head) {
405 for (a = head; a->list.next; a = a->list.next);
406 a->list.next = tail;
407 }
408 else
409 head = tail;
410
411 return head;
412 }
413
414 char *
xf86uLongToString(unsigned long i)415 xf86uLongToString(unsigned long i)
416 {
417 char *s;
418
419 if (asprintf(&s, "%lu", i) == -1)
420 return NULL;
421 return s;
422 }
423
424 XF86OptionPtr
xf86parseOption(XF86OptionPtr head)425 xf86parseOption(XF86OptionPtr head)
426 {
427 XF86OptionPtr option, cnew, old;
428 char *name, *comment = NULL;
429 int token;
430
431 if ((token = xf86getSubToken(&comment)) != STRING) {
432 xf86parseError(BAD_OPTION_MSG);
433 free(comment);
434 return head;
435 }
436
437 name = xf86_lex_val.str;
438 if ((token = xf86getSubToken(&comment)) == STRING) {
439 option = xf86newOption(name, xf86_lex_val.str);
440 option->opt_comment = comment;
441 if ((token = xf86getToken(NULL)) == COMMENT)
442 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
443 else
444 xf86unGetToken(token);
445 }
446 else {
447 option = xf86newOption(name, NULL);
448 option->opt_comment = comment;
449 if (token == COMMENT)
450 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
451 else
452 xf86unGetToken(token);
453 }
454
455 old = NULL;
456
457 /* Don't allow duplicates */
458 if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
459 cnew = old;
460 free(option->opt_name);
461 TestFree(option->opt_val);
462 TestFree(option->opt_comment);
463 free(option);
464 }
465 else
466 cnew = option;
467
468 if (old == NULL)
469 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
470
471 return head;
472 }
473
474 void
xf86printOptionList(FILE * fp,XF86OptionPtr list,int tabs)475 xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
476 {
477 int i;
478
479 if (!list)
480 return;
481 while (list) {
482 for (i = 0; i < tabs; i++)
483 fputc('\t', fp);
484 if (list->opt_val)
485 fprintf(fp, "Option \"%s\" \"%s\"", list->opt_name,
486 list->opt_val);
487 else
488 fprintf(fp, "Option \"%s\"", list->opt_name);
489 if (list->opt_comment)
490 fprintf(fp, "%s", list->opt_comment);
491 else
492 fputc('\n', fp);
493 list = list->list.next;
494 }
495 }
496