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