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