1 /*
2 * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28 /*
29 * Author: David Dawes <dawes@xfree86.org>
30 *
31 * This file includes public option handling functions.
32 */
33
34 #ifdef HAVE_XORG_CONFIG_H
35 #include <xorg-config.h>
36 #endif
37
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include <X11/X.h>
41 #include "os.h"
42 #include "xf86.h"
43 #include "xf86Opt.h"
44 #include "xf86Xinput.h"
45 #include "xf86Optrec.h"
46 #include "xf86Parser.h"
47 #include "xf86platformBus.h" /* For OutputClass functions */
48 #include "optionstr.h"
49
50 static Bool ParseOptionValue(int scrnIndex, XF86OptionPtr options,
51 OptionInfoPtr p, Bool markUsed);
52
53 /*
54 * xf86CollectOptions collects the options from each of the config file
55 * sections used by the screen and puts the combined list in pScrn->options.
56 * This function requires that the following have been initialised:
57 *
58 * pScrn->confScreen
59 * pScrn->Entities[i]->device
60 * pScrn->display
61 * pScrn->monitor
62 *
63 * The extraOpts parameter may optionally contain a list of additional options
64 * to include.
65 *
66 * The order of precedence for options is:
67 *
68 * extraOpts, display, confScreen, monitor, device, outputClassOptions
69 */
70
71 void
xf86CollectOptions(ScrnInfoPtr pScrn,XF86OptionPtr extraOpts)72 xf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts)
73 {
74 XF86OptionPtr tmp;
75 XF86OptionPtr extras = (XF86OptionPtr) extraOpts;
76 GDevPtr device;
77
78 int i;
79
80 pScrn->options = NULL;
81
82 for (i = pScrn->numEntities - 1; i >= 0; i--) {
83 xf86MergeOutputClassOptions(pScrn->entityList[i], &pScrn->options);
84
85 device = xf86GetDevFromEntity(pScrn->entityList[i],
86 pScrn->entityInstanceList[i]);
87 if (device && device->options) {
88 tmp = xf86optionListDup(device->options);
89 if (pScrn->options)
90 pScrn->options = xf86optionListMerge(pScrn->options, tmp);
91 else
92 pScrn->options = tmp;
93 }
94 }
95 if (pScrn->monitor->options) {
96 tmp = xf86optionListDup(pScrn->monitor->options);
97 if (pScrn->options)
98 pScrn->options = xf86optionListMerge(pScrn->options, tmp);
99 else
100 pScrn->options = tmp;
101 }
102 if (pScrn->confScreen->options) {
103 tmp = xf86optionListDup(pScrn->confScreen->options);
104 if (pScrn->options)
105 pScrn->options = xf86optionListMerge(pScrn->options, tmp);
106 else
107 pScrn->options = tmp;
108 }
109 if (pScrn->display->options) {
110 tmp = xf86optionListDup(pScrn->display->options);
111 if (pScrn->options)
112 pScrn->options = xf86optionListMerge(pScrn->options, tmp);
113 else
114 pScrn->options = tmp;
115 }
116 if (extras) {
117 tmp = xf86optionListDup(extras);
118 if (pScrn->options)
119 pScrn->options = xf86optionListMerge(pScrn->options, tmp);
120 else
121 pScrn->options = tmp;
122 }
123 }
124
125 /*
126 * xf86CollectInputOptions collects extra options for an InputDevice (other
127 * than those added by the config backend).
128 * The options are merged into the existing ones and thus take precedence
129 * over the others.
130 */
131
132 void
xf86CollectInputOptions(InputInfoPtr pInfo,const char ** defaultOpts)133 xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts)
134 {
135 if (defaultOpts) {
136 XF86OptionPtr tmp = xf86optionListCreate(defaultOpts, -1, 0);
137
138 if (pInfo->options)
139 pInfo->options = xf86optionListMerge(tmp, pInfo->options);
140 else
141 pInfo->options = tmp;
142 }
143 }
144
145 /**
146 * Duplicate the option list passed in. The returned pointer will be a newly
147 * allocated option list and must be freed by the caller.
148 */
149 XF86OptionPtr
xf86OptionListDuplicate(XF86OptionPtr options)150 xf86OptionListDuplicate(XF86OptionPtr options)
151 {
152 XF86OptionPtr o = NULL;
153
154 while (options) {
155 o = xf86AddNewOption(o, xf86OptionName(options),
156 xf86OptionValue(options));
157 options = xf86nextOption(options);
158 }
159
160 return o;
161 }
162
163 /* Created for new XInput stuff -- essentially extensions to the parser */
164
165 static int
LookupIntOption(XF86OptionPtr optlist,const char * name,int deflt,Bool markUsed)166 LookupIntOption(XF86OptionPtr optlist, const char *name, int deflt,
167 Bool markUsed)
168 {
169 OptionInfoRec o;
170
171 o.name = name;
172 o.type = OPTV_INTEGER;
173 if (ParseOptionValue(-1, optlist, &o, markUsed))
174 deflt = o.value.num;
175 return deflt;
176 }
177
178 static double
LookupRealOption(XF86OptionPtr optlist,const char * name,double deflt,Bool markUsed)179 LookupRealOption(XF86OptionPtr optlist, const char *name, double deflt,
180 Bool markUsed)
181 {
182 OptionInfoRec o;
183
184 o.name = name;
185 o.type = OPTV_REAL;
186 if (ParseOptionValue(-1, optlist, &o, markUsed))
187 deflt = o.value.realnum;
188 return deflt;
189 }
190
191 static char *
LookupStrOption(XF86OptionPtr optlist,const char * name,const char * deflt,Bool markUsed)192 LookupStrOption(XF86OptionPtr optlist, const char *name, const char *deflt,
193 Bool markUsed)
194 {
195 OptionInfoRec o;
196
197 o.name = name;
198 o.type = OPTV_STRING;
199 if (ParseOptionValue(-1, optlist, &o, markUsed))
200 deflt = o.value.str;
201 if (deflt)
202 return strdup(deflt);
203 else
204 return NULL;
205 }
206
207 static int
LookupBoolOption(XF86OptionPtr optlist,const char * name,int deflt,Bool markUsed)208 LookupBoolOption(XF86OptionPtr optlist, const char *name, int deflt,
209 Bool markUsed)
210 {
211 OptionInfoRec o;
212
213 o.name = name;
214 o.type = OPTV_BOOLEAN;
215 if (ParseOptionValue(-1, optlist, &o, markUsed))
216 deflt = o.value.bool;
217 return deflt;
218 }
219
220 static double
LookupPercentOption(XF86OptionPtr optlist,const char * name,double deflt,Bool markUsed)221 LookupPercentOption(XF86OptionPtr optlist, const char *name, double deflt,
222 Bool markUsed)
223 {
224 OptionInfoRec o;
225
226 o.name = name;
227 o.type = OPTV_PERCENT;
228 if (ParseOptionValue(-1, optlist, &o, markUsed))
229 deflt = o.value.realnum;
230 return deflt;
231 }
232
233 /* These xf86Set* functions are intended for use by non-screen specific code */
234
235 int
xf86SetIntOption(XF86OptionPtr optlist,const char * name,int deflt)236 xf86SetIntOption(XF86OptionPtr optlist, const char *name, int deflt)
237 {
238 return LookupIntOption(optlist, name, deflt, TRUE);
239 }
240
241 double
xf86SetRealOption(XF86OptionPtr optlist,const char * name,double deflt)242 xf86SetRealOption(XF86OptionPtr optlist, const char *name, double deflt)
243 {
244 return LookupRealOption(optlist, name, deflt, TRUE);
245 }
246
247 char *
xf86SetStrOption(XF86OptionPtr optlist,const char * name,const char * deflt)248 xf86SetStrOption(XF86OptionPtr optlist, const char *name, const char *deflt)
249 {
250 return LookupStrOption(optlist, name, deflt, TRUE);
251 }
252
253 int
xf86SetBoolOption(XF86OptionPtr optlist,const char * name,int deflt)254 xf86SetBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
255 {
256 return LookupBoolOption(optlist, name, deflt, TRUE);
257 }
258
259 double
xf86SetPercentOption(XF86OptionPtr optlist,const char * name,double deflt)260 xf86SetPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
261 {
262 return LookupPercentOption(optlist, name, deflt, TRUE);
263 }
264
265 /*
266 * These are like the Set*Option functions, but they don't mark the options
267 * as used.
268 */
269 int
xf86CheckIntOption(XF86OptionPtr optlist,const char * name,int deflt)270 xf86CheckIntOption(XF86OptionPtr optlist, const char *name, int deflt)
271 {
272 return LookupIntOption(optlist, name, deflt, FALSE);
273 }
274
275 double
xf86CheckRealOption(XF86OptionPtr optlist,const char * name,double deflt)276 xf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt)
277 {
278 return LookupRealOption(optlist, name, deflt, FALSE);
279 }
280
281 char *
xf86CheckStrOption(XF86OptionPtr optlist,const char * name,const char * deflt)282 xf86CheckStrOption(XF86OptionPtr optlist, const char *name, const char *deflt)
283 {
284 return LookupStrOption(optlist, name, deflt, FALSE);
285 }
286
287 int
xf86CheckBoolOption(XF86OptionPtr optlist,const char * name,int deflt)288 xf86CheckBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
289 {
290 return LookupBoolOption(optlist, name, deflt, FALSE);
291 }
292
293 double
xf86CheckPercentOption(XF86OptionPtr optlist,const char * name,double deflt)294 xf86CheckPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
295 {
296 return LookupPercentOption(optlist, name, deflt, FALSE);
297 }
298
299 /*
300 * xf86AddNewOption() has the required property of replacing the option value
301 * if the option is already present.
302 */
303 XF86OptionPtr
xf86ReplaceIntOption(XF86OptionPtr optlist,const char * name,const int val)304 xf86ReplaceIntOption(XF86OptionPtr optlist, const char *name, const int val)
305 {
306 char tmp[16];
307
308 snprintf(tmp, sizeof(tmp), "%i", val);
309 return xf86AddNewOption(optlist, name, tmp);
310 }
311
312 XF86OptionPtr
xf86ReplaceRealOption(XF86OptionPtr optlist,const char * name,const double val)313 xf86ReplaceRealOption(XF86OptionPtr optlist, const char *name, const double val)
314 {
315 char tmp[32];
316
317 snprintf(tmp, sizeof(tmp), "%f", val);
318 return xf86AddNewOption(optlist, name, tmp);
319 }
320
321 XF86OptionPtr
xf86ReplaceBoolOption(XF86OptionPtr optlist,const char * name,const Bool val)322 xf86ReplaceBoolOption(XF86OptionPtr optlist, const char *name, const Bool val)
323 {
324 return xf86AddNewOption(optlist, name, val ? "True" : "False");
325 }
326
327 XF86OptionPtr
xf86ReplacePercentOption(XF86OptionPtr optlist,const char * name,const double val)328 xf86ReplacePercentOption(XF86OptionPtr optlist, const char *name,
329 const double val)
330 {
331 char tmp[16];
332
333 snprintf(tmp, sizeof(tmp), "%lf%%", val);
334 return xf86AddNewOption(optlist, name, tmp);
335 }
336
337 XF86OptionPtr
xf86ReplaceStrOption(XF86OptionPtr optlist,const char * name,const char * val)338 xf86ReplaceStrOption(XF86OptionPtr optlist, const char *name, const char *val)
339 {
340 return xf86AddNewOption(optlist, name, val);
341 }
342
343 XF86OptionPtr
xf86AddNewOption(XF86OptionPtr head,const char * name,const char * val)344 xf86AddNewOption(XF86OptionPtr head, const char *name, const char *val)
345 {
346 /* XXX These should actually be allocated in the parser library. */
347 char *tmp = val ? strdup(val) : NULL;
348 char *tmp_name = strdup(name);
349
350 return xf86addNewOption(head, tmp_name, tmp);
351 }
352
353 XF86OptionPtr
xf86NewOption(char * name,char * value)354 xf86NewOption(char *name, char *value)
355 {
356 return xf86newOption(name, value);
357 }
358
359 XF86OptionPtr
xf86NextOption(XF86OptionPtr list)360 xf86NextOption(XF86OptionPtr list)
361 {
362 return xf86nextOption(list);
363 }
364
365 XF86OptionPtr
xf86OptionListCreate(const char ** options,int count,int used)366 xf86OptionListCreate(const char **options, int count, int used)
367 {
368 return xf86optionListCreate(options, count, used);
369 }
370
371 XF86OptionPtr
xf86OptionListMerge(XF86OptionPtr head,XF86OptionPtr tail)372 xf86OptionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
373 {
374 return xf86optionListMerge(head, tail);
375 }
376
377 void
xf86OptionListFree(XF86OptionPtr opt)378 xf86OptionListFree(XF86OptionPtr opt)
379 {
380 xf86optionListFree(opt);
381 }
382
383 char *
xf86OptionName(XF86OptionPtr opt)384 xf86OptionName(XF86OptionPtr opt)
385 {
386 return xf86optionName(opt);
387 }
388
389 char *
xf86OptionValue(XF86OptionPtr opt)390 xf86OptionValue(XF86OptionPtr opt)
391 {
392 return xf86optionValue(opt);
393 }
394
395 void
xf86OptionListReport(XF86OptionPtr parm)396 xf86OptionListReport(XF86OptionPtr parm)
397 {
398 XF86OptionPtr opts = parm;
399
400 while (opts) {
401 if (xf86optionValue(opts))
402 xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n",
403 xf86optionName(opts), xf86optionValue(opts));
404 else
405 xf86ErrorFVerb(5, "\tOption \"%s\"\n", xf86optionName(opts));
406 opts = xf86nextOption(opts);
407 }
408 }
409
410 /* End of XInput-caused section */
411
412 XF86OptionPtr
xf86FindOption(XF86OptionPtr options,const char * name)413 xf86FindOption(XF86OptionPtr options, const char *name)
414 {
415 return xf86findOption(options, name);
416 }
417
418 const char *
xf86FindOptionValue(XF86OptionPtr options,const char * name)419 xf86FindOptionValue(XF86OptionPtr options, const char *name)
420 {
421 return xf86findOptionValue(options, name);
422 }
423
424 void
xf86MarkOptionUsed(XF86OptionPtr option)425 xf86MarkOptionUsed(XF86OptionPtr option)
426 {
427 if (option != NULL)
428 option->opt_used = TRUE;
429 }
430
431 void
xf86MarkOptionUsedByName(XF86OptionPtr options,const char * name)432 xf86MarkOptionUsedByName(XF86OptionPtr options, const char *name)
433 {
434 XF86OptionPtr opt;
435
436 opt = xf86findOption(options, name);
437 if (opt != NULL)
438 opt->opt_used = TRUE;
439 }
440
441 Bool
xf86CheckIfOptionUsed(XF86OptionPtr option)442 xf86CheckIfOptionUsed(XF86OptionPtr option)
443 {
444 if (option != NULL)
445 return option->opt_used;
446 else
447 return FALSE;
448 }
449
450 Bool
xf86CheckIfOptionUsedByName(XF86OptionPtr options,const char * name)451 xf86CheckIfOptionUsedByName(XF86OptionPtr options, const char *name)
452 {
453 XF86OptionPtr opt;
454
455 opt = xf86findOption(options, name);
456 if (opt != NULL)
457 return opt->opt_used;
458 else
459 return FALSE;
460 }
461
462 void
xf86ShowUnusedOptions(int scrnIndex,XF86OptionPtr opt)463 xf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr opt)
464 {
465 while (opt) {
466 if (opt->opt_name && !opt->opt_used) {
467 xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n",
468 opt->opt_name);
469 }
470 opt = opt->list.next;
471 }
472 }
473
474 static Bool
GetBoolValue(OptionInfoPtr p,const char * s)475 GetBoolValue(OptionInfoPtr p, const char *s)
476 {
477 return xf86getBoolValue(&p->value.bool, s);
478 }
479
480 static Bool
ParseOptionValue(int scrnIndex,XF86OptionPtr options,OptionInfoPtr p,Bool markUsed)481 ParseOptionValue(int scrnIndex, XF86OptionPtr options, OptionInfoPtr p,
482 Bool markUsed)
483 {
484 const char *s;
485 char *end;
486 Bool wasUsed = FALSE;
487
488 if ((s = xf86findOptionValue(options, p->name)) != NULL) {
489 if (markUsed) {
490 wasUsed = xf86CheckIfOptionUsedByName(options, p->name);
491 xf86MarkOptionUsedByName(options, p->name);
492 }
493 switch (p->type) {
494 case OPTV_INTEGER:
495 if (*s == '\0') {
496 if (markUsed) {
497 xf86DrvMsg(scrnIndex, X_WARNING,
498 "Option \"%s\" requires an integer value\n",
499 p->name);
500 }
501 p->found = FALSE;
502 }
503 else {
504 p->value.num = strtoul(s, &end, 0);
505 if (*end == '\0') {
506 p->found = TRUE;
507 }
508 else {
509 if (markUsed) {
510 xf86DrvMsg(scrnIndex, X_WARNING,
511 "Option \"%s\" requires an integer value\n",
512 p->name);
513 }
514 p->found = FALSE;
515 }
516 }
517 break;
518 case OPTV_STRING:
519 if (*s == '\0') {
520 if (markUsed) {
521 xf86DrvMsg(scrnIndex, X_WARNING,
522 "Option \"%s\" requires a string value\n",
523 p->name);
524 }
525 p->found = FALSE;
526 }
527 else {
528 p->value.str = s;
529 p->found = TRUE;
530 }
531 break;
532 case OPTV_ANYSTR:
533 p->value.str = s;
534 p->found = TRUE;
535 break;
536 case OPTV_REAL:
537 if (*s == '\0') {
538 if (markUsed) {
539 xf86DrvMsg(scrnIndex, X_WARNING,
540 "Option \"%s\" requires a floating point "
541 "value\n", p->name);
542 }
543 p->found = FALSE;
544 }
545 else {
546 p->value.realnum = strtod(s, &end);
547 if (*end == '\0') {
548 p->found = TRUE;
549 }
550 else {
551 if (markUsed) {
552 xf86DrvMsg(scrnIndex, X_WARNING,
553 "Option \"%s\" requires a floating point "
554 "value\n", p->name);
555 }
556 p->found = FALSE;
557 }
558 }
559 break;
560 case OPTV_BOOLEAN:
561 if (GetBoolValue(p, s)) {
562 p->found = TRUE;
563 }
564 else {
565 if (markUsed) {
566 xf86DrvMsg(scrnIndex, X_WARNING,
567 "Option \"%s\" requires a boolean value\n",
568 p->name);
569 }
570 p->found = FALSE;
571 }
572 break;
573 case OPTV_PERCENT:
574 {
575 char tmp = 0;
576
577 /* awkward match, but %% doesn't increase the match counter,
578 * hence 100 looks the same as 100% to the caller of sccanf
579 */
580 if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') {
581 if (markUsed) {
582 xf86DrvMsg(scrnIndex, X_WARNING,
583 "Option \"%s\" requires a percent value\n",
584 p->name);
585 }
586 p->found = FALSE;
587 }
588 else {
589 p->found = TRUE;
590 }
591 }
592 break;
593 case OPTV_FREQ:
594 if (*s == '\0') {
595 if (markUsed) {
596 xf86DrvMsg(scrnIndex, X_WARNING,
597 "Option \"%s\" requires a frequency value\n",
598 p->name);
599 }
600 p->found = FALSE;
601 }
602 else {
603 double freq = strtod(s, &end);
604 int units = 0;
605
606 if (end != s) {
607 p->found = TRUE;
608 if (!xf86NameCmp(end, "Hz"))
609 units = 1;
610 else if (!xf86NameCmp(end, "kHz") || !xf86NameCmp(end, "k"))
611 units = 1000;
612 else if (!xf86NameCmp(end, "MHz") || !xf86NameCmp(end, "M"))
613 units = 1000000;
614 else {
615 if (markUsed) {
616 xf86DrvMsg(scrnIndex, X_WARNING,
617 "Option \"%s\" requires a frequency value\n",
618 p->name);
619 }
620 p->found = FALSE;
621 }
622 if (p->found)
623 freq *= (double) units;
624 }
625 else {
626 if (markUsed) {
627 xf86DrvMsg(scrnIndex, X_WARNING,
628 "Option \"%s\" requires a frequency value\n",
629 p->name);
630 }
631 p->found = FALSE;
632 }
633 if (p->found) {
634 p->value.freq.freq = freq;
635 p->value.freq.units = units;
636 }
637 }
638 break;
639 case OPTV_NONE:
640 /* Should never get here */
641 p->found = FALSE;
642 break;
643 }
644 if (p->found && markUsed) {
645 int verb = 2;
646
647 if (wasUsed)
648 verb = 4;
649 xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name);
650 if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
651 xf86ErrorFVerb(verb, " \"%s\"", s);
652 }
653 xf86ErrorFVerb(verb, "\n");
654 }
655 }
656 else if (p->type == OPTV_BOOLEAN) {
657 /* Look for matches with options with or without a "No" prefix. */
658 char *n, *newn;
659 OptionInfoRec opt;
660
661 n = xf86NormalizeName(p->name);
662 if (!n) {
663 p->found = FALSE;
664 return FALSE;
665 }
666 if (strncmp(n, "no", 2) == 0) {
667 newn = n + 2;
668 }
669 else {
670 free(n);
671 if (asprintf(&n, "No%s", p->name) == -1) {
672 p->found = FALSE;
673 return FALSE;
674 }
675 newn = n;
676 }
677 if ((s = xf86findOptionValue(options, newn)) != NULL) {
678 if (markUsed)
679 xf86MarkOptionUsedByName(options, newn);
680 if (GetBoolValue(&opt, s)) {
681 p->value.bool = !opt.value.bool;
682 p->found = TRUE;
683 }
684 else {
685 xf86DrvMsg(scrnIndex, X_WARNING,
686 "Option \"%s\" requires a boolean value\n", newn);
687 p->found = FALSE;
688 }
689 }
690 else {
691 p->found = FALSE;
692 }
693 if (p->found && markUsed) {
694 xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
695 if (*s != 0) {
696 xf86ErrorFVerb(2, " \"%s\"", s);
697 }
698 xf86ErrorFVerb(2, "\n");
699 }
700 free(n);
701 }
702 else {
703 p->found = FALSE;
704 }
705 return p->found;
706 }
707
708 void
xf86ProcessOptions(int scrnIndex,XF86OptionPtr options,OptionInfoPtr optinfo)709 xf86ProcessOptions(int scrnIndex, XF86OptionPtr options, OptionInfoPtr optinfo)
710 {
711 OptionInfoPtr p;
712
713 for (p = optinfo; p->name != NULL; p++) {
714 ParseOptionValue(scrnIndex, options, p, TRUE);
715 }
716 }
717
718 OptionInfoPtr
xf86TokenToOptinfo(const OptionInfoRec * table,int token)719 xf86TokenToOptinfo(const OptionInfoRec * table, int token)
720 {
721 const OptionInfoRec *p, *match = NULL, *set = NULL;
722
723 if (!table) {
724 ErrorF("xf86TokenToOptinfo: table is NULL\n");
725 return NULL;
726 }
727
728 for (p = table; p->token >= 0; p++) {
729 if (p->token == token) {
730 match = p;
731 if (p->found)
732 set = p;
733 }
734 }
735
736 if (set)
737 return (OptionInfoPtr) set;
738 else if (match)
739 return (OptionInfoPtr) match;
740 else
741 return NULL;
742 }
743
744 const char *
xf86TokenToOptName(const OptionInfoRec * table,int token)745 xf86TokenToOptName(const OptionInfoRec * table, int token)
746 {
747 const OptionInfoRec *p;
748
749 p = xf86TokenToOptinfo(table, token);
750 return p ? p->name : NULL;
751 }
752
753 Bool
xf86IsOptionSet(const OptionInfoRec * table,int token)754 xf86IsOptionSet(const OptionInfoRec * table, int token)
755 {
756 OptionInfoPtr p;
757
758 p = xf86TokenToOptinfo(table, token);
759 return p && p->found;
760 }
761
762 const char *
xf86GetOptValString(const OptionInfoRec * table,int token)763 xf86GetOptValString(const OptionInfoRec * table, int token)
764 {
765 OptionInfoPtr p;
766
767 p = xf86TokenToOptinfo(table, token);
768 if (p && p->found)
769 return p->value.str;
770 else
771 return NULL;
772 }
773
774 Bool
xf86GetOptValInteger(const OptionInfoRec * table,int token,int * value)775 xf86GetOptValInteger(const OptionInfoRec * table, int token, int *value)
776 {
777 OptionInfoPtr p;
778
779 p = xf86TokenToOptinfo(table, token);
780 if (p && p->found) {
781 *value = p->value.num;
782 return TRUE;
783 }
784 else
785 return FALSE;
786 }
787
788 Bool
xf86GetOptValULong(const OptionInfoRec * table,int token,unsigned long * value)789 xf86GetOptValULong(const OptionInfoRec * table, int token, unsigned long *value)
790 {
791 OptionInfoPtr p;
792
793 p = xf86TokenToOptinfo(table, token);
794 if (p && p->found) {
795 *value = p->value.num;
796 return TRUE;
797 }
798 else
799 return FALSE;
800 }
801
802 Bool
xf86GetOptValReal(const OptionInfoRec * table,int token,double * value)803 xf86GetOptValReal(const OptionInfoRec * table, int token, double *value)
804 {
805 OptionInfoPtr p;
806
807 p = xf86TokenToOptinfo(table, token);
808 if (p && p->found) {
809 *value = p->value.realnum;
810 return TRUE;
811 }
812 else
813 return FALSE;
814 }
815
816 Bool
xf86GetOptValFreq(const OptionInfoRec * table,int token,OptFreqUnits expectedUnits,double * value)817 xf86GetOptValFreq(const OptionInfoRec * table, int token,
818 OptFreqUnits expectedUnits, double *value)
819 {
820 OptionInfoPtr p;
821
822 p = xf86TokenToOptinfo(table, token);
823 if (p && p->found) {
824 if (p->value.freq.units > 0) {
825 /* Units give, so the scaling is known. */
826 switch (expectedUnits) {
827 case OPTUNITS_HZ:
828 *value = p->value.freq.freq;
829 break;
830 case OPTUNITS_KHZ:
831 *value = p->value.freq.freq / 1000.0;
832 break;
833 case OPTUNITS_MHZ:
834 *value = p->value.freq.freq / 1000000.0;
835 break;
836 }
837 }
838 else {
839 /* No units given, so try to guess the scaling. */
840 switch (expectedUnits) {
841 case OPTUNITS_HZ:
842 *value = p->value.freq.freq;
843 break;
844 case OPTUNITS_KHZ:
845 if (p->value.freq.freq > 1000.0)
846 *value = p->value.freq.freq / 1000.0;
847 else
848 *value = p->value.freq.freq;
849 break;
850 case OPTUNITS_MHZ:
851 if (p->value.freq.freq > 1000000.0)
852 *value = p->value.freq.freq / 1000000.0;
853 else if (p->value.freq.freq > 1000.0)
854 *value = p->value.freq.freq / 1000.0;
855 else
856 *value = p->value.freq.freq;
857 }
858 }
859 return TRUE;
860 }
861 else
862 return FALSE;
863 }
864
865 Bool
xf86GetOptValBool(const OptionInfoRec * table,int token,Bool * value)866 xf86GetOptValBool(const OptionInfoRec * table, int token, Bool *value)
867 {
868 OptionInfoPtr p;
869
870 p = xf86TokenToOptinfo(table, token);
871 if (p && p->found) {
872 *value = p->value.bool;
873 return TRUE;
874 }
875 else
876 return FALSE;
877 }
878
879 Bool
xf86ReturnOptValBool(const OptionInfoRec * table,int token,Bool def)880 xf86ReturnOptValBool(const OptionInfoRec * table, int token, Bool def)
881 {
882 OptionInfoPtr p;
883
884 p = xf86TokenToOptinfo(table, token);
885 if (p && p->found) {
886 return p->value.bool;
887 }
888 else
889 return def;
890 }
891
892 int
xf86NameCmp(const char * s1,const char * s2)893 xf86NameCmp(const char *s1, const char *s2)
894 {
895 return xf86nameCompare(s1, s2);
896 }
897
898 char *
xf86NormalizeName(const char * s)899 xf86NormalizeName(const char *s)
900 {
901 char *ret, *q;
902 const char *p;
903
904 if (s == NULL)
905 return NULL;
906
907 ret = malloc(strlen(s) + 1);
908 for (p = s, q = ret; *p != 0; p++) {
909 switch (*p) {
910 case '_':
911 case ' ':
912 case '\t':
913 continue;
914 default:
915 if (isupper(*p))
916 *q++ = tolower(*p);
917 else
918 *q++ = *p;
919 }
920 }
921 *q = '\0';
922 return ret;
923 }
924