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