Flags.c revision 58cf2af7
1/*
2 * Copyright (c) 1997  Metro Link Incorporated
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 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the Metro Link shall not be
23 * used in advertising or otherwise to promote the sale, use or other dealings
24 * in this Software without prior written authorization from Metro Link.
25 *
26 */
27/*
28 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29 *
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
36 *
37 * The above copyright notice and this permission notice shall be included in
38 * all copies or substantial portions of the Software.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
43 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 * OTHER DEALINGS IN THE SOFTWARE.
47 *
48 * Except as contained in this notice, the name of the copyright holder(s)
49 * and author(s) shall not be used in advertising or otherwise to promote
50 * the sale, use or other dealings in this Software without prior written
51 * authorization from the copyright holder(s) and author(s).
52 */
53
54#ifdef HAVE_XORG_CONFIG_H
55#include <xorg-config.h>
56#endif
57
58#include "xf86Parser.h"
59#include "xf86tokens.h"
60#include "Configint.h"
61#include <X11/Xfuncproto.h>
62#include "Xprintf.h"
63#include "optionstr.h"
64
65
66static const xf86ConfigSymTabRec ServerFlagsTab[] = {
67    {ENDSECTION, "endsection"},
68    {DONTZAP, "dontzap"},
69    {DONTZOOM, "dontzoom"},
70    {DISABLEVIDMODE, "disablevidmodeextension"},
71    {ALLOWNONLOCAL, "allownonlocalxvidtune"},
72    {DISABLEMODINDEV, "disablemodindev"},
73    {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
74    {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
75    {OPTION, "option"},
76    {BLANKTIME, "blanktime"},
77    {STANDBYTIME, "standbytime"},
78    {SUSPENDTIME, "suspendtime"},
79    {OFFTIME, "offtime"},
80    {DEFAULTLAYOUT, "defaultserverlayout"},
81    {-1, ""},
82};
83
84#define CLEANUP xf86freeFlags
85
86XF86ConfFlagsPtr
87xf86parseFlagsSection(void)
88{
89    int token;
90
91    parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
92
93        while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
94        int hasvalue = FALSE;
95        int strvalue = FALSE;
96        int tokentype;
97
98        switch (token) {
99        case COMMENT:
100            ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
101            free(xf86_lex_val.str);
102            xf86_lex_val.str = NULL;
103            break;
104            /*
105             * these old keywords are turned into standard generic options.
106             * we fall through here on purpose
107             */
108        case DEFAULTLAYOUT:
109            strvalue = TRUE;
110        case BLANKTIME:
111        case STANDBYTIME:
112        case SUSPENDTIME:
113        case OFFTIME:
114            hasvalue = TRUE;
115        case DONTZAP:
116        case DONTZOOM:
117        case DISABLEVIDMODE:
118        case ALLOWNONLOCAL:
119        case DISABLEMODINDEV:
120        case MODINDEVALLOWNONLOCAL:
121        case ALLOWMOUSEOPENFAIL:
122        {
123            int i = 0;
124
125            while (ServerFlagsTab[i].token != -1) {
126                char *tmp;
127
128                if (ServerFlagsTab[i].token == token) {
129                    char *valstr = NULL;
130
131                    tmp = strdup(ServerFlagsTab[i].name);
132                    if (hasvalue) {
133                        tokentype = xf86getSubToken(&(ptr->flg_comment));
134                        if (strvalue) {
135                            if (tokentype != STRING)
136                                Error(QUOTE_MSG, tmp);
137                            valstr = xf86_lex_val.str;
138                        }
139                        else {
140                            if (tokentype != NUMBER)
141                                Error(NUMBER_MSG, tmp);
142                            if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
143                                valstr = NULL;
144                        }
145                    }
146                    ptr->flg_option_lst = xf86addNewOption
147                        (ptr->flg_option_lst, tmp, valstr);
148                }
149                i++;
150            }
151        }
152            break;
153        case OPTION:
154            ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
155            break;
156
157        case EOF_TOKEN:
158            Error(UNEXPECTED_EOF_MSG);
159            break;
160        default:
161            Error(INVALID_KEYWORD_MSG, xf86tokenString());
162            break;
163        }
164    }
165
166#ifdef DEBUG
167    printf("Flags section parsed\n");
168#endif
169
170    return ptr;
171}
172
173#undef CLEANUP
174
175void
176xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
177{
178    XF86OptionPtr p;
179
180    if ((!flags) || (!flags->flg_option_lst))
181        return;
182    p = flags->flg_option_lst;
183    fprintf(f, "Section \"ServerFlags\"\n");
184    if (flags->flg_comment)
185        fprintf(f, "%s", flags->flg_comment);
186    xf86printOptionList(f, p, 1);
187    fprintf(f, "EndSection\n\n");
188}
189
190static XF86OptionPtr
191addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
192{
193    XF86OptionPtr new, old = NULL;
194
195    /* Don't allow duplicates, free old strings */
196    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
197        new = old;
198        free(new->opt_name);
199        free(new->opt_val);
200    }
201    else
202        new = calloc(1, sizeof(*new));
203    new->opt_name = name;
204    new->opt_val = _val;
205    new->opt_used = used;
206
207    if (old)
208        return head;
209    return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
210}
211
212XF86OptionPtr
213xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
214{
215    return addNewOption2(head, name, _val, 0);
216}
217
218void
219xf86freeFlags(XF86ConfFlagsPtr flags)
220{
221    if (flags == NULL)
222        return;
223    xf86optionListFree(flags->flg_option_lst);
224    TestFree(flags->flg_comment);
225    free(flags);
226}
227
228XF86OptionPtr
229xf86optionListDup(XF86OptionPtr opt)
230{
231    XF86OptionPtr newopt = NULL;
232    char *_val;
233
234    while (opt) {
235        _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
236        newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
237        newopt->opt_used = opt->opt_used;
238        if (opt->opt_comment)
239            newopt->opt_comment = strdup(opt->opt_comment);
240        opt = opt->list.next;
241    }
242    return newopt;
243}
244
245void
246xf86optionListFree(XF86OptionPtr opt)
247{
248    XF86OptionPtr prev;
249
250    while (opt) {
251        TestFree(opt->opt_name);
252        TestFree(opt->opt_val);
253        TestFree(opt->opt_comment);
254        prev = opt;
255        opt = opt->list.next;
256        free(prev);
257    }
258}
259
260char *
261xf86optionName(XF86OptionPtr opt)
262{
263    if (opt)
264        return opt->opt_name;
265    return 0;
266}
267
268char *
269xf86optionValue(XF86OptionPtr opt)
270{
271    if (opt)
272        return opt->opt_val;
273    return 0;
274}
275
276XF86OptionPtr
277xf86newOption(char *name, char *value)
278{
279    XF86OptionPtr opt;
280
281    opt = calloc(1, sizeof(*opt));
282    if (!opt)
283        return NULL;
284
285    opt->opt_used = 0;
286    opt->list.next = 0;
287    opt->opt_name = name;
288    opt->opt_val = value;
289
290    return opt;
291}
292
293XF86OptionPtr
294xf86nextOption(XF86OptionPtr list)
295{
296    if (!list)
297        return NULL;
298    return list->list.next;
299}
300
301/*
302 * this function searches the given option list for the named option and
303 * returns a pointer to the option rec if found. If not found, it returns
304 * NULL
305 */
306
307XF86OptionPtr
308xf86findOption(XF86OptionPtr list, const char *name)
309{
310    while (list) {
311        if (xf86nameCompare(list->opt_name, name) == 0)
312            return list;
313        list = list->list.next;
314    }
315    return NULL;
316}
317
318/*
319 * this function searches the given option list for the named option. If
320 * found and the option has a parameter, a pointer to the parameter is
321 * returned.  If the option does not have a parameter an empty string is
322 * returned.  If the option is not found, a NULL is returned.
323 */
324
325const char *
326xf86findOptionValue(XF86OptionPtr list, const char *name)
327{
328    XF86OptionPtr p = xf86findOption(list, name);
329
330    if (p) {
331        if (p->opt_val)
332            return p->opt_val;
333        else
334            return "";
335    }
336    return NULL;
337}
338
339XF86OptionPtr
340xf86optionListCreate(const char **options, int count, int used)
341{
342    XF86OptionPtr p = NULL;
343    char *t1, *t2;
344    int i;
345
346    if (count == -1) {
347        for (count = 0; options[count]; count++);
348    }
349    if ((count % 2) != 0) {
350        fprintf(stderr,
351                "xf86optionListCreate: count must be an even number.\n");
352        return NULL;
353    }
354    for (i = 0; i < count; i += 2) {
355        t1 = strdup(options[i]);
356        t2 = strdup(options[i + 1]);
357        p = addNewOption2(p, t1, t2, used);
358    }
359
360    return p;
361}
362
363/* the 2 given lists are merged. If an option with the same name is present in
364 * both, the option from the user list - specified in the second argument -
365 * is used. The end result is a single valid list of options. Duplicates
366 * are freed, and the original lists are no longer guaranteed to be complete.
367 */
368XF86OptionPtr
369xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
370{
371    XF86OptionPtr a, b, ap = NULL, bp = NULL;
372
373    a = tail;
374    b = head;
375    while (tail && b) {
376        if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
377            if (b == head)
378                head = a;
379            else
380                bp->list.next = a;
381            if (a == tail)
382                tail = a->list.next;
383            else
384                ap->list.next = a->list.next;
385            a->list.next = b->list.next;
386            b->list.next = NULL;
387            xf86optionListFree(b);
388            b = a->list.next;
389            bp = a;
390            a = tail;
391            ap = NULL;
392        }
393        else {
394            ap = a;
395            if (!(a = a->list.next)) {
396                a = tail;
397                bp = b;
398                b = b->list.next;
399                ap = NULL;
400            }
401        }
402    }
403
404    if (head) {
405        for (a = head; a->list.next; a = a->list.next);
406        a->list.next = tail;
407    }
408    else
409        head = tail;
410
411    return head;
412}
413
414char *
415xf86uLongToString(unsigned long i)
416{
417    char *s;
418
419    if (asprintf(&s, "%lu", i) == -1)
420        return NULL;
421    return s;
422}
423
424XF86OptionPtr
425xf86parseOption(XF86OptionPtr head)
426{
427    XF86OptionPtr option, cnew, old;
428    char *name, *comment = NULL;
429    int token;
430
431    if ((token = xf86getSubToken(&comment)) != STRING) {
432        xf86parseError(BAD_OPTION_MSG);
433        free(comment);
434        return head;
435    }
436
437    name = xf86_lex_val.str;
438    if ((token = xf86getSubToken(&comment)) == STRING) {
439        option = xf86newOption(name, xf86_lex_val.str);
440        option->opt_comment = comment;
441        if ((token = xf86getToken(NULL)) == COMMENT) {
442            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
443            free(xf86_lex_val.str);
444            xf86_lex_val.str = NULL;
445        } else {
446            xf86unGetToken(token);
447        }
448    }
449    else {
450        option = xf86newOption(name, NULL);
451        option->opt_comment = comment;
452        if (token == COMMENT) {
453            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
454            free(xf86_lex_val.str);
455            xf86_lex_val.str = NULL;
456        } else {
457            xf86unGetToken(token);
458        }
459    }
460
461    old = NULL;
462
463    /* Don't allow duplicates */
464    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
465        cnew = old;
466        free(option->opt_name);
467        TestFree(option->opt_val);
468        TestFree(option->opt_comment);
469        free(option);
470    }
471    else
472        cnew = option;
473
474    if (old == NULL)
475        return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
476
477    return head;
478}
479
480void
481xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
482{
483    int i;
484
485    if (!list)
486        return;
487    while (list) {
488        for (i = 0; i < tabs; i++)
489            fputc('\t', fp);
490        if (list->opt_val)
491            fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name,
492                    list->opt_val);
493        else
494            fprintf(fp, "Option	    \"%s\"", list->opt_name);
495        if (list->opt_comment)
496            fprintf(fp, "%s", list->opt_comment);
497        else
498            fputc('\n', fp);
499        list = list->list.next;
500    }
501}
502