Flags.c revision ed6184df
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            break;
102            /*
103             * these old keywords are turned into standard generic options.
104             * we fall through here on purpose
105             */
106        case DEFAULTLAYOUT:
107            strvalue = TRUE;
108        case BLANKTIME:
109        case STANDBYTIME:
110        case SUSPENDTIME:
111        case OFFTIME:
112            hasvalue = TRUE;
113        case DONTZAP:
114        case DONTZOOM:
115        case DISABLEVIDMODE:
116        case ALLOWNONLOCAL:
117        case DISABLEMODINDEV:
118        case MODINDEVALLOWNONLOCAL:
119        case ALLOWMOUSEOPENFAIL:
120        {
121            int i = 0;
122
123            while (ServerFlagsTab[i].token != -1) {
124                char *tmp;
125
126                if (ServerFlagsTab[i].token == token) {
127                    char *valstr = NULL;
128
129                    tmp = strdup(ServerFlagsTab[i].name);
130                    if (hasvalue) {
131                        tokentype = xf86getSubToken(&(ptr->flg_comment));
132                        if (strvalue) {
133                            if (tokentype != STRING)
134                                Error(QUOTE_MSG, tmp);
135                            valstr = xf86_lex_val.str;
136                        }
137                        else {
138                            if (tokentype != NUMBER)
139                                Error(NUMBER_MSG, tmp);
140                            if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
141                                valstr = NULL;
142                        }
143                    }
144                    ptr->flg_option_lst = xf86addNewOption
145                        (ptr->flg_option_lst, tmp, valstr);
146                }
147                i++;
148            }
149        }
150            break;
151        case OPTION:
152            ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
153            break;
154
155        case EOF_TOKEN:
156            Error(UNEXPECTED_EOF_MSG);
157            break;
158        default:
159            Error(INVALID_KEYWORD_MSG, xf86tokenString());
160            break;
161        }
162    }
163
164#ifdef DEBUG
165    printf("Flags section parsed\n");
166#endif
167
168    return ptr;
169}
170
171#undef CLEANUP
172
173void
174xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
175{
176    XF86OptionPtr p;
177
178    if ((!flags) || (!flags->flg_option_lst))
179        return;
180    p = flags->flg_option_lst;
181    fprintf(f, "Section \"ServerFlags\"\n");
182    if (flags->flg_comment)
183        fprintf(f, "%s", flags->flg_comment);
184    xf86printOptionList(f, p, 1);
185    fprintf(f, "EndSection\n\n");
186}
187
188static XF86OptionPtr
189addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
190{
191    XF86OptionPtr new, old = NULL;
192
193    /* Don't allow duplicates, free old strings */
194    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
195        new = old;
196        free(new->opt_name);
197        free(new->opt_val);
198    }
199    else
200        new = calloc(1, sizeof(*new));
201    new->opt_name = name;
202    new->opt_val = _val;
203    new->opt_used = used;
204
205    if (old)
206        return head;
207    return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
208}
209
210XF86OptionPtr
211xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
212{
213    return addNewOption2(head, name, _val, 0);
214}
215
216void
217xf86freeFlags(XF86ConfFlagsPtr flags)
218{
219    if (flags == NULL)
220        return;
221    xf86optionListFree(flags->flg_option_lst);
222    TestFree(flags->flg_comment);
223    free(flags);
224}
225
226XF86OptionPtr
227xf86optionListDup(XF86OptionPtr opt)
228{
229    XF86OptionPtr newopt = NULL;
230    char *_val;
231
232    while (opt) {
233        _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
234        newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
235        newopt->opt_used = opt->opt_used;
236        if (opt->opt_comment)
237            newopt->opt_comment = strdup(opt->opt_comment);
238        opt = opt->list.next;
239    }
240    return newopt;
241}
242
243void
244xf86optionListFree(XF86OptionPtr opt)
245{
246    XF86OptionPtr prev;
247
248    while (opt) {
249        TestFree(opt->opt_name);
250        TestFree(opt->opt_val);
251        TestFree(opt->opt_comment);
252        prev = opt;
253        opt = opt->list.next;
254        free(prev);
255    }
256}
257
258char *
259xf86optionName(XF86OptionPtr opt)
260{
261    if (opt)
262        return opt->opt_name;
263    return 0;
264}
265
266char *
267xf86optionValue(XF86OptionPtr opt)
268{
269    if (opt)
270        return opt->opt_val;
271    return 0;
272}
273
274XF86OptionPtr
275xf86newOption(char *name, char *value)
276{
277    XF86OptionPtr opt;
278
279    opt = calloc(1, sizeof(*opt));
280    if (!opt)
281        return NULL;
282
283    opt->opt_used = 0;
284    opt->list.next = 0;
285    opt->opt_name = name;
286    opt->opt_val = value;
287
288    return opt;
289}
290
291XF86OptionPtr
292xf86nextOption(XF86OptionPtr list)
293{
294    if (!list)
295        return NULL;
296    return list->list.next;
297}
298
299/*
300 * this function searches the given option list for the named option and
301 * returns a pointer to the option rec if found. If not found, it returns
302 * NULL
303 */
304
305XF86OptionPtr
306xf86findOption(XF86OptionPtr list, const char *name)
307{
308    while (list) {
309        if (xf86nameCompare(list->opt_name, name) == 0)
310            return list;
311        list = list->list.next;
312    }
313    return NULL;
314}
315
316/*
317 * this function searches the given option list for the named option. If
318 * found and the option has a parameter, a pointer to the parameter is
319 * returned.  If the option does not have a parameter an empty string is
320 * returned.  If the option is not found, a NULL is returned.
321 */
322
323const char *
324xf86findOptionValue(XF86OptionPtr list, const char *name)
325{
326    XF86OptionPtr p = xf86findOption(list, name);
327
328    if (p) {
329        if (p->opt_val)
330            return p->opt_val;
331        else
332            return "";
333    }
334    return NULL;
335}
336
337XF86OptionPtr
338xf86optionListCreate(const char **options, int count, int used)
339{
340    XF86OptionPtr p = NULL;
341    char *t1, *t2;
342    int i;
343
344    if (count == -1) {
345        for (count = 0; options[count]; count++);
346    }
347    if ((count % 2) != 0) {
348        fprintf(stderr,
349                "xf86optionListCreate: count must be an even number.\n");
350        return NULL;
351    }
352    for (i = 0; i < count; i += 2) {
353        t1 = strdup(options[i]);
354        t2 = strdup(options[i + 1]);
355        p = addNewOption2(p, t1, t2, used);
356    }
357
358    return p;
359}
360
361/* the 2 given lists are merged. If an option with the same name is present in
362 * both, the option from the user list - specified in the second argument -
363 * is used. The end result is a single valid list of options. Duplicates
364 * are freed, and the original lists are no longer guaranteed to be complete.
365 */
366XF86OptionPtr
367xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
368{
369    XF86OptionPtr a, b, ap = NULL, bp = NULL;
370
371    a = tail;
372    b = head;
373    while (tail && b) {
374        if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
375            if (b == head)
376                head = a;
377            else
378                bp->list.next = a;
379            if (a == tail)
380                tail = a->list.next;
381            else
382                ap->list.next = a->list.next;
383            a->list.next = b->list.next;
384            b->list.next = NULL;
385            xf86optionListFree(b);
386            b = a->list.next;
387            bp = a;
388            a = tail;
389            ap = NULL;
390        }
391        else {
392            ap = a;
393            if (!(a = a->list.next)) {
394                a = tail;
395                bp = b;
396                b = b->list.next;
397                ap = NULL;
398            }
399        }
400    }
401
402    if (head) {
403        for (a = head; a->list.next; a = a->list.next);
404        a->list.next = tail;
405    }
406    else
407        head = tail;
408
409    return head;
410}
411
412char *
413xf86uLongToString(unsigned long i)
414{
415    char *s;
416
417    if (asprintf(&s, "%lu", i) == -1)
418        return NULL;
419    return s;
420}
421
422XF86OptionPtr
423xf86parseOption(XF86OptionPtr head)
424{
425    XF86OptionPtr option, cnew, old;
426    char *name, *comment = NULL;
427    int token;
428
429    if ((token = xf86getSubToken(&comment)) != STRING) {
430        xf86parseError(BAD_OPTION_MSG);
431        free(comment);
432        return head;
433    }
434
435    name = xf86_lex_val.str;
436    if ((token = xf86getSubToken(&comment)) == STRING) {
437        option = xf86newOption(name, xf86_lex_val.str);
438        option->opt_comment = comment;
439        if ((token = xf86getToken(NULL)) == COMMENT)
440            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
441        else
442            xf86unGetToken(token);
443    }
444    else {
445        option = xf86newOption(name, NULL);
446        option->opt_comment = comment;
447        if (token == COMMENT)
448            option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
449        else
450            xf86unGetToken(token);
451    }
452
453    old = NULL;
454
455    /* Don't allow duplicates */
456    if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
457        cnew = old;
458        free(option->opt_name);
459        TestFree(option->opt_val);
460        TestFree(option->opt_comment);
461        free(option);
462    }
463    else
464        cnew = option;
465
466    if (old == NULL)
467        return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
468
469    return head;
470}
471
472void
473xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
474{
475    int i;
476
477    if (!list)
478        return;
479    while (list) {
480        for (i = 0; i < tabs; i++)
481            fputc('\t', fp);
482        if (list->opt_val)
483            fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name,
484                    list->opt_val);
485        else
486            fprintf(fp, "Option	    \"%s\"", list->opt_name);
487        if (list->opt_comment)
488            fprintf(fp, "%s", list->opt_comment);
489        else
490            fputc('\n', fp);
491        list = list->list.next;
492    }
493}
494