135c4bbdfSmrg/*
205b261ecSmrg * Copyright (c) 1997  Metro Link Incorporated
335c4bbdfSmrg *
405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
535c4bbdfSmrg * copy of this software and associated documentation files (the "Software"),
605b261ecSmrg * to deal in the Software without restriction, including without limitation
705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
905b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1035c4bbdfSmrg *
1105b261ecSmrg * The above copyright notice and this permission notice shall be included in
1205b261ecSmrg * all copies or substantial portions of the Software.
1335c4bbdfSmrg *
1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1705b261ecSmrg * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1805b261ecSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1905b261ecSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2005b261ecSmrg * SOFTWARE.
2135c4bbdfSmrg *
2205b261ecSmrg * Except as contained in this notice, the name of the Metro Link shall not be
2305b261ecSmrg * used in advertising or otherwise to promote the sale, use or other dealings
2405b261ecSmrg * in this Software without prior written authorization from Metro Link.
2535c4bbdfSmrg *
2605b261ecSmrg */
2705b261ecSmrg/*
2805b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
2905b261ecSmrg *
3005b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
3105b261ecSmrg * copy of this software and associated documentation files (the "Software"),
3205b261ecSmrg * to deal in the Software without restriction, including without limitation
3305b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
3405b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
3505b261ecSmrg * Software is furnished to do so, subject to the following conditions:
3605b261ecSmrg *
3705b261ecSmrg * The above copyright notice and this permission notice shall be included in
3805b261ecSmrg * all copies or substantial portions of the Software.
3905b261ecSmrg *
4005b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4105b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4205b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
4305b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
4405b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4505b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4605b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
4705b261ecSmrg *
4805b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
4905b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
5005b261ecSmrg * the sale, use or other dealings in this Software without prior written
5105b261ecSmrg * authorization from the copyright holder(s) and author(s).
5205b261ecSmrg */
5305b261ecSmrg
5405b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
5505b261ecSmrg#include <xorg-config.h>
5605b261ecSmrg#endif
5705b261ecSmrg
5805b261ecSmrg#include "xf86Parser.h"
5905b261ecSmrg#include "xf86tokens.h"
6005b261ecSmrg#include "Configint.h"
614642e01fSmrg#include <X11/Xfuncproto.h>
629ace9065Smrg#include "Xprintf.h"
6335c4bbdfSmrg#include "optionstr.h"
6435c4bbdfSmrg
6535c4bbdfSmrg
661b5d61b8Smrgstatic const xf86ConfigSymTabRec ServerFlagsTab[] = {
6735c4bbdfSmrg    {ENDSECTION, "endsection"},
6835c4bbdfSmrg    {DONTZAP, "dontzap"},
6935c4bbdfSmrg    {DONTZOOM, "dontzoom"},
7035c4bbdfSmrg    {DISABLEVIDMODE, "disablevidmodeextension"},
7135c4bbdfSmrg    {ALLOWNONLOCAL, "allownonlocalxvidtune"},
7235c4bbdfSmrg    {DISABLEMODINDEV, "disablemodindev"},
7335c4bbdfSmrg    {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
7435c4bbdfSmrg    {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
7535c4bbdfSmrg    {OPTION, "option"},
7635c4bbdfSmrg    {BLANKTIME, "blanktime"},
7735c4bbdfSmrg    {STANDBYTIME, "standbytime"},
7835c4bbdfSmrg    {SUSPENDTIME, "suspendtime"},
7935c4bbdfSmrg    {OFFTIME, "offtime"},
8035c4bbdfSmrg    {DEFAULTLAYOUT, "defaultserverlayout"},
8135c4bbdfSmrg    {-1, ""},
8205b261ecSmrg};
8305b261ecSmrg
8405b261ecSmrg#define CLEANUP xf86freeFlags
8505b261ecSmrg
8605b261ecSmrgXF86ConfFlagsPtr
8735c4bbdfSmrgxf86parseFlagsSection(void)
8805b261ecSmrg{
8935c4bbdfSmrg    int token;
9035c4bbdfSmrg
9135c4bbdfSmrg    parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
9235c4bbdfSmrg
9335c4bbdfSmrg        while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
9435c4bbdfSmrg        int hasvalue = FALSE;
9535c4bbdfSmrg        int strvalue = FALSE;
9635c4bbdfSmrg        int tokentype;
9735c4bbdfSmrg
9835c4bbdfSmrg        switch (token) {
9935c4bbdfSmrg        case COMMENT:
10035c4bbdfSmrg            ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
10158cf2af7Smrg            free(xf86_lex_val.str);
10258cf2af7Smrg            xf86_lex_val.str = NULL;
10335c4bbdfSmrg            break;
10435c4bbdfSmrg            /*
10535c4bbdfSmrg             * these old keywords are turned into standard generic options.
10635c4bbdfSmrg             * we fall through here on purpose
10735c4bbdfSmrg             */
10835c4bbdfSmrg        case DEFAULTLAYOUT:
10935c4bbdfSmrg            strvalue = TRUE;
11035c4bbdfSmrg        case BLANKTIME:
11135c4bbdfSmrg        case STANDBYTIME:
11235c4bbdfSmrg        case SUSPENDTIME:
11335c4bbdfSmrg        case OFFTIME:
11435c4bbdfSmrg            hasvalue = TRUE;
11535c4bbdfSmrg        case DONTZAP:
11635c4bbdfSmrg        case DONTZOOM:
11735c4bbdfSmrg        case DISABLEVIDMODE:
11835c4bbdfSmrg        case ALLOWNONLOCAL:
11935c4bbdfSmrg        case DISABLEMODINDEV:
12035c4bbdfSmrg        case MODINDEVALLOWNONLOCAL:
12135c4bbdfSmrg        case ALLOWMOUSEOPENFAIL:
12235c4bbdfSmrg        {
12335c4bbdfSmrg            int i = 0;
12435c4bbdfSmrg
12535c4bbdfSmrg            while (ServerFlagsTab[i].token != -1) {
12635c4bbdfSmrg                char *tmp;
12735c4bbdfSmrg
12835c4bbdfSmrg                if (ServerFlagsTab[i].token == token) {
12935c4bbdfSmrg                    char *valstr = NULL;
13035c4bbdfSmrg
13135c4bbdfSmrg                    tmp = strdup(ServerFlagsTab[i].name);
13235c4bbdfSmrg                    if (hasvalue) {
13335c4bbdfSmrg                        tokentype = xf86getSubToken(&(ptr->flg_comment));
13435c4bbdfSmrg                        if (strvalue) {
13535c4bbdfSmrg                            if (tokentype != STRING)
13635c4bbdfSmrg                                Error(QUOTE_MSG, tmp);
13735c4bbdfSmrg                            valstr = xf86_lex_val.str;
13835c4bbdfSmrg                        }
13935c4bbdfSmrg                        else {
14035c4bbdfSmrg                            if (tokentype != NUMBER)
14135c4bbdfSmrg                                Error(NUMBER_MSG, tmp);
14235c4bbdfSmrg                            if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
14335c4bbdfSmrg                                valstr = NULL;
14435c4bbdfSmrg                        }
14535c4bbdfSmrg                    }
14635c4bbdfSmrg                    ptr->flg_option_lst = xf86addNewOption
14735c4bbdfSmrg                        (ptr->flg_option_lst, tmp, valstr);
14835c4bbdfSmrg                }
14935c4bbdfSmrg                i++;
15035c4bbdfSmrg            }
15135c4bbdfSmrg        }
15235c4bbdfSmrg            break;
15335c4bbdfSmrg        case OPTION:
15435c4bbdfSmrg            ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
15535c4bbdfSmrg            break;
15635c4bbdfSmrg
15735c4bbdfSmrg        case EOF_TOKEN:
15835c4bbdfSmrg            Error(UNEXPECTED_EOF_MSG);
15935c4bbdfSmrg            break;
16035c4bbdfSmrg        default:
16135c4bbdfSmrg            Error(INVALID_KEYWORD_MSG, xf86tokenString());
16235c4bbdfSmrg            break;
16335c4bbdfSmrg        }
16435c4bbdfSmrg    }
16505b261ecSmrg
16605b261ecSmrg#ifdef DEBUG
16735c4bbdfSmrg    printf("Flags section parsed\n");
16805b261ecSmrg#endif
16905b261ecSmrg
17035c4bbdfSmrg    return ptr;
17105b261ecSmrg}
17205b261ecSmrg
17305b261ecSmrg#undef CLEANUP
17405b261ecSmrg
17505b261ecSmrgvoid
17635c4bbdfSmrgxf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
17705b261ecSmrg{
17835c4bbdfSmrg    XF86OptionPtr p;
17935c4bbdfSmrg
18035c4bbdfSmrg    if ((!flags) || (!flags->flg_option_lst))
18135c4bbdfSmrg        return;
18235c4bbdfSmrg    p = flags->flg_option_lst;
18335c4bbdfSmrg    fprintf(f, "Section \"ServerFlags\"\n");
18435c4bbdfSmrg    if (flags->flg_comment)
18535c4bbdfSmrg        fprintf(f, "%s", flags->flg_comment);
18635c4bbdfSmrg    xf86printOptionList(f, p, 1);
18735c4bbdfSmrg    fprintf(f, "EndSection\n\n");
18805b261ecSmrg}
18905b261ecSmrg
19005b261ecSmrgstatic XF86OptionPtr
19135c4bbdfSmrgaddNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
19205b261ecSmrg{
19335c4bbdfSmrg    XF86OptionPtr new, old = NULL;
19435c4bbdfSmrg
19535c4bbdfSmrg    /* Don't allow duplicates, free old strings */
19635c4bbdfSmrg    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
19735c4bbdfSmrg        new = old;
19835c4bbdfSmrg        free(new->opt_name);
19935c4bbdfSmrg        free(new->opt_val);
20035c4bbdfSmrg    }
20135c4bbdfSmrg    else
20235c4bbdfSmrg        new = calloc(1, sizeof(*new));
20335c4bbdfSmrg    new->opt_name = name;
20435c4bbdfSmrg    new->opt_val = _val;
20535c4bbdfSmrg    new->opt_used = used;
20635c4bbdfSmrg
20735c4bbdfSmrg    if (old)
20835c4bbdfSmrg        return head;
20935c4bbdfSmrg    return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
21005b261ecSmrg}
21105b261ecSmrg
21205b261ecSmrgXF86OptionPtr
21335c4bbdfSmrgxf86addNewOption(XF86OptionPtr head, char *name, char *_val)
21405b261ecSmrg{
21535c4bbdfSmrg    return addNewOption2(head, name, _val, 0);
21605b261ecSmrg}
21705b261ecSmrg
21805b261ecSmrgvoid
21935c4bbdfSmrgxf86freeFlags(XF86ConfFlagsPtr flags)
22005b261ecSmrg{
22135c4bbdfSmrg    if (flags == NULL)
22235c4bbdfSmrg        return;
22335c4bbdfSmrg    xf86optionListFree(flags->flg_option_lst);
22435c4bbdfSmrg    TestFree(flags->flg_comment);
22535c4bbdfSmrg    free(flags);
22605b261ecSmrg}
22705b261ecSmrg
22805b261ecSmrgXF86OptionPtr
22935c4bbdfSmrgxf86optionListDup(XF86OptionPtr opt)
23005b261ecSmrg{
23135c4bbdfSmrg    XF86OptionPtr newopt = NULL;
23235c4bbdfSmrg    char *_val;
23335c4bbdfSmrg
23435c4bbdfSmrg    while (opt) {
23535c4bbdfSmrg        _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
23635c4bbdfSmrg        newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
23735c4bbdfSmrg        newopt->opt_used = opt->opt_used;
23835c4bbdfSmrg        if (opt->opt_comment)
23935c4bbdfSmrg            newopt->opt_comment = strdup(opt->opt_comment);
24035c4bbdfSmrg        opt = opt->list.next;
24135c4bbdfSmrg    }
24235c4bbdfSmrg    return newopt;
24305b261ecSmrg}
24405b261ecSmrg
24505b261ecSmrgvoid
24635c4bbdfSmrgxf86optionListFree(XF86OptionPtr opt)
24705b261ecSmrg{
24835c4bbdfSmrg    XF86OptionPtr prev;
24935c4bbdfSmrg
25035c4bbdfSmrg    while (opt) {
25135c4bbdfSmrg        TestFree(opt->opt_name);
25235c4bbdfSmrg        TestFree(opt->opt_val);
25335c4bbdfSmrg        TestFree(opt->opt_comment);
25435c4bbdfSmrg        prev = opt;
25535c4bbdfSmrg        opt = opt->list.next;
25635c4bbdfSmrg        free(prev);
25735c4bbdfSmrg    }
25805b261ecSmrg}
25905b261ecSmrg
26005b261ecSmrgchar *
26105b261ecSmrgxf86optionName(XF86OptionPtr opt)
26205b261ecSmrg{
26335c4bbdfSmrg    if (opt)
26435c4bbdfSmrg        return opt->opt_name;
26535c4bbdfSmrg    return 0;
26605b261ecSmrg}
26705b261ecSmrg
26805b261ecSmrgchar *
26905b261ecSmrgxf86optionValue(XF86OptionPtr opt)
27005b261ecSmrg{
27135c4bbdfSmrg    if (opt)
27235c4bbdfSmrg        return opt->opt_val;
27335c4bbdfSmrg    return 0;
27405b261ecSmrg}
27505b261ecSmrg
27605b261ecSmrgXF86OptionPtr
27705b261ecSmrgxf86newOption(char *name, char *value)
27805b261ecSmrg{
27935c4bbdfSmrg    XF86OptionPtr opt;
28005b261ecSmrg
28135c4bbdfSmrg    opt = calloc(1, sizeof(*opt));
28235c4bbdfSmrg    if (!opt)
28335c4bbdfSmrg        return NULL;
28405b261ecSmrg
28535c4bbdfSmrg    opt->opt_used = 0;
28635c4bbdfSmrg    opt->list.next = 0;
28735c4bbdfSmrg    opt->opt_name = name;
28835c4bbdfSmrg    opt->opt_val = value;
28905b261ecSmrg
29035c4bbdfSmrg    return opt;
29105b261ecSmrg}
29205b261ecSmrg
29305b261ecSmrgXF86OptionPtr
29405b261ecSmrgxf86nextOption(XF86OptionPtr list)
29505b261ecSmrg{
29635c4bbdfSmrg    if (!list)
29735c4bbdfSmrg        return NULL;
29835c4bbdfSmrg    return list->list.next;
29905b261ecSmrg}
30005b261ecSmrg
30105b261ecSmrg/*
30205b261ecSmrg * this function searches the given option list for the named option and
30305b261ecSmrg * returns a pointer to the option rec if found. If not found, it returns
30405b261ecSmrg * NULL
30505b261ecSmrg */
30605b261ecSmrg
30705b261ecSmrgXF86OptionPtr
30835c4bbdfSmrgxf86findOption(XF86OptionPtr list, const char *name)
30905b261ecSmrg{
31035c4bbdfSmrg    while (list) {
31135c4bbdfSmrg        if (xf86nameCompare(list->opt_name, name) == 0)
31235c4bbdfSmrg            return list;
31335c4bbdfSmrg        list = list->list.next;
31435c4bbdfSmrg    }
31535c4bbdfSmrg    return NULL;
31605b261ecSmrg}
31705b261ecSmrg
31805b261ecSmrg/*
31905b261ecSmrg * this function searches the given option list for the named option. If
32005b261ecSmrg * found and the option has a parameter, a pointer to the parameter is
32105b261ecSmrg * returned.  If the option does not have a parameter an empty string is
32205b261ecSmrg * returned.  If the option is not found, a NULL is returned.
32305b261ecSmrg */
32405b261ecSmrg
32535c4bbdfSmrgconst char *
32635c4bbdfSmrgxf86findOptionValue(XF86OptionPtr list, const char *name)
32705b261ecSmrg{
32835c4bbdfSmrg    XF86OptionPtr p = xf86findOption(list, name);
32935c4bbdfSmrg
33035c4bbdfSmrg    if (p) {
33135c4bbdfSmrg        if (p->opt_val)
33235c4bbdfSmrg            return p->opt_val;
33335c4bbdfSmrg        else
33435c4bbdfSmrg            return "";
33535c4bbdfSmrg    }
33635c4bbdfSmrg    return NULL;
33705b261ecSmrg}
33805b261ecSmrg
33905b261ecSmrgXF86OptionPtr
34035c4bbdfSmrgxf86optionListCreate(const char **options, int count, int used)
34105b261ecSmrg{
34235c4bbdfSmrg    XF86OptionPtr p = NULL;
34335c4bbdfSmrg    char *t1, *t2;
34435c4bbdfSmrg    int i;
34535c4bbdfSmrg
34635c4bbdfSmrg    if (count == -1) {
34735c4bbdfSmrg        for (count = 0; options[count]; count++);
34835c4bbdfSmrg    }
34935c4bbdfSmrg    if ((count % 2) != 0) {
35035c4bbdfSmrg        fprintf(stderr,
35135c4bbdfSmrg                "xf86optionListCreate: count must be an even number.\n");
35235c4bbdfSmrg        return NULL;
35335c4bbdfSmrg    }
35435c4bbdfSmrg    for (i = 0; i < count; i += 2) {
35535c4bbdfSmrg        t1 = strdup(options[i]);
35635c4bbdfSmrg        t2 = strdup(options[i + 1]);
35735c4bbdfSmrg        p = addNewOption2(p, t1, t2, used);
35835c4bbdfSmrg    }
35935c4bbdfSmrg
36035c4bbdfSmrg    return p;
36105b261ecSmrg}
36205b261ecSmrg
36305b261ecSmrg/* the 2 given lists are merged. If an option with the same name is present in
36405b261ecSmrg * both, the option from the user list - specified in the second argument -
36505b261ecSmrg * is used. The end result is a single valid list of options. Duplicates
36605b261ecSmrg * are freed, and the original lists are no longer guaranteed to be complete.
36705b261ecSmrg */
36805b261ecSmrgXF86OptionPtr
36935c4bbdfSmrgxf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
37005b261ecSmrg{
37135c4bbdfSmrg    XF86OptionPtr a, b, ap = NULL, bp = NULL;
37235c4bbdfSmrg
37335c4bbdfSmrg    a = tail;
37435c4bbdfSmrg    b = head;
37535c4bbdfSmrg    while (tail && b) {
37635c4bbdfSmrg        if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
37735c4bbdfSmrg            if (b == head)
37835c4bbdfSmrg                head = a;
37935c4bbdfSmrg            else
38035c4bbdfSmrg                bp->list.next = a;
38135c4bbdfSmrg            if (a == tail)
38235c4bbdfSmrg                tail = a->list.next;
38335c4bbdfSmrg            else
38435c4bbdfSmrg                ap->list.next = a->list.next;
38535c4bbdfSmrg            a->list.next = b->list.next;
38635c4bbdfSmrg            b->list.next = NULL;
38735c4bbdfSmrg            xf86optionListFree(b);
38835c4bbdfSmrg            b = a->list.next;
38935c4bbdfSmrg            bp = a;
39035c4bbdfSmrg            a = tail;
39135c4bbdfSmrg            ap = NULL;
39235c4bbdfSmrg        }
39335c4bbdfSmrg        else {
39435c4bbdfSmrg            ap = a;
39535c4bbdfSmrg            if (!(a = a->list.next)) {
39635c4bbdfSmrg                a = tail;
39735c4bbdfSmrg                bp = b;
39835c4bbdfSmrg                b = b->list.next;
39935c4bbdfSmrg                ap = NULL;
40035c4bbdfSmrg            }
40135c4bbdfSmrg        }
40235c4bbdfSmrg    }
40335c4bbdfSmrg
40435c4bbdfSmrg    if (head) {
40535c4bbdfSmrg        for (a = head; a->list.next; a = a->list.next);
40635c4bbdfSmrg        a->list.next = tail;
40735c4bbdfSmrg    }
40835c4bbdfSmrg    else
40935c4bbdfSmrg        head = tail;
41035c4bbdfSmrg
41135c4bbdfSmrg    return head;
41205b261ecSmrg}
41305b261ecSmrg
41405b261ecSmrgchar *
41505b261ecSmrgxf86uLongToString(unsigned long i)
41605b261ecSmrg{
41735c4bbdfSmrg    char *s;
41805b261ecSmrg
41935c4bbdfSmrg    if (asprintf(&s, "%lu", i) == -1)
42035c4bbdfSmrg        return NULL;
42135c4bbdfSmrg    return s;
42205b261ecSmrg}
42305b261ecSmrg
42405b261ecSmrgXF86OptionPtr
42505b261ecSmrgxf86parseOption(XF86OptionPtr head)
42605b261ecSmrg{
42735c4bbdfSmrg    XF86OptionPtr option, cnew, old;
42835c4bbdfSmrg    char *name, *comment = NULL;
42935c4bbdfSmrg    int token;
43035c4bbdfSmrg
43135c4bbdfSmrg    if ((token = xf86getSubToken(&comment)) != STRING) {
43235c4bbdfSmrg        xf86parseError(BAD_OPTION_MSG);
43335c4bbdfSmrg        free(comment);
43435c4bbdfSmrg        return head;
43535c4bbdfSmrg    }
43635c4bbdfSmrg
43735c4bbdfSmrg    name = xf86_lex_val.str;
43835c4bbdfSmrg    if ((token = xf86getSubToken(&comment)) == STRING) {
43935c4bbdfSmrg        option = xf86newOption(name, xf86_lex_val.str);
44035c4bbdfSmrg        option->opt_comment = comment;
44158cf2af7Smrg        if ((token = xf86getToken(NULL)) == COMMENT) {
44235c4bbdfSmrg            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
44358cf2af7Smrg            free(xf86_lex_val.str);
44458cf2af7Smrg            xf86_lex_val.str = NULL;
44558cf2af7Smrg        } else {
44635c4bbdfSmrg            xf86unGetToken(token);
44758cf2af7Smrg        }
44835c4bbdfSmrg    }
44935c4bbdfSmrg    else {
45035c4bbdfSmrg        option = xf86newOption(name, NULL);
45135c4bbdfSmrg        option->opt_comment = comment;
45258cf2af7Smrg        if (token == COMMENT) {
45335c4bbdfSmrg            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
45458cf2af7Smrg            free(xf86_lex_val.str);
45558cf2af7Smrg            xf86_lex_val.str = NULL;
45658cf2af7Smrg        } else {
45735c4bbdfSmrg            xf86unGetToken(token);
45858cf2af7Smrg        }
45935c4bbdfSmrg    }
46035c4bbdfSmrg
46135c4bbdfSmrg    old = NULL;
46235c4bbdfSmrg
46335c4bbdfSmrg    /* Don't allow duplicates */
46435c4bbdfSmrg    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
46535c4bbdfSmrg        cnew = old;
46635c4bbdfSmrg        free(option->opt_name);
46735c4bbdfSmrg        TestFree(option->opt_val);
46835c4bbdfSmrg        TestFree(option->opt_comment);
46935c4bbdfSmrg        free(option);
47035c4bbdfSmrg    }
47135c4bbdfSmrg    else
47235c4bbdfSmrg        cnew = option;
47335c4bbdfSmrg
47435c4bbdfSmrg    if (old == NULL)
47535c4bbdfSmrg        return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
47635c4bbdfSmrg
47735c4bbdfSmrg    return head;
47805b261ecSmrg}
47905b261ecSmrg
48005b261ecSmrgvoid
48135c4bbdfSmrgxf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
48205b261ecSmrg{
48335c4bbdfSmrg    int i;
48435c4bbdfSmrg
48535c4bbdfSmrg    if (!list)
48635c4bbdfSmrg        return;
48735c4bbdfSmrg    while (list) {
48835c4bbdfSmrg        for (i = 0; i < tabs; i++)
48935c4bbdfSmrg            fputc('\t', fp);
49035c4bbdfSmrg        if (list->opt_val)
49135c4bbdfSmrg            fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name,
49235c4bbdfSmrg                    list->opt_val);
49335c4bbdfSmrg        else
49435c4bbdfSmrg            fprintf(fp, "Option	    \"%s\"", list->opt_name);
49535c4bbdfSmrg        if (list->opt_comment)
49635c4bbdfSmrg            fprintf(fp, "%s", list->opt_comment);
49735c4bbdfSmrg        else
49835c4bbdfSmrg            fputc('\n', fp);
49935c4bbdfSmrg        list = list->list.next;
50035c4bbdfSmrg    }
50105b261ecSmrg}
502