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