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