~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/parser/scan.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/hw/xfree86/parser/scan.c,v 1.30 2003/11/03 05:11:52 tsi Exp $ */
 
2
/* 
 
3
 * 
 
4
 * Copyright (c) 1997  Metro Link Incorporated
 
5
 * 
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the "Software"), 
 
8
 * to deal in the Software without restriction, including without limitation
 
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
10
 * and/or sell copies of the Software, and to permit persons to whom the
 
11
 * Software is furnished to do so, subject to the following conditions:
 
12
 * 
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 * 
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
19
 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
20
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 
21
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
22
 * SOFTWARE.
 
23
 * 
 
24
 * Except as contained in this notice, the name of the Metro Link shall not be
 
25
 * used in advertising or otherwise to promote the sale, use or other dealings
 
26
 * in this Software without prior written authorization from Metro Link.
 
27
 * 
 
28
 */
 
29
/*
 
30
 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
 
31
 *
 
32
 * Permission is hereby granted, free of charge, to any person obtaining a
 
33
 * copy of this software and associated documentation files (the "Software"),
 
34
 * to deal in the Software without restriction, including without limitation
 
35
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
36
 * and/or sell copies of the Software, and to permit persons to whom the
 
37
 * Software is furnished to do so, subject to the following conditions:
 
38
 *
 
39
 * The above copyright notice and this permission notice shall be included in
 
40
 * all copies or substantial portions of the Software.
 
41
 *
 
42
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
43
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
44
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
45
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
46
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
47
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
48
 * OTHER DEALINGS IN THE SOFTWARE.
 
49
 *
 
50
 * Except as contained in this notice, the name of the copyright holder(s)
 
51
 * and author(s) shall not be used in advertising or otherwise to promote
 
52
 * the sale, use or other dealings in this Software without prior written
 
53
 * authorization from the copyright holder(s) and author(s).
 
54
 */
 
55
 
 
56
 
 
57
/* View/edit this file with tab stops set to 4 */
 
58
 
 
59
#ifdef HAVE_XORG_CONFIG_H
 
60
#include <xorg-config.h>
 
61
#endif
 
62
 
 
63
#include <ctype.h>
 
64
#include <stdio.h>
 
65
#include <stdlib.h>
 
66
#include <string.h>
 
67
#include <unistd.h>
 
68
#include <stdarg.h>
 
69
 
 
70
#if !defined(X_NOT_POSIX)
 
71
#if defined(_POSIX_SOURCE)
 
72
#include <limits.h>
 
73
#else
 
74
#define _POSIX_SOURCE
 
75
#include <limits.h>
 
76
#undef _POSIX_SOURCE
 
77
#endif /* _POSIX_SOURCE */
 
78
#endif /* !X_NOT_POSIX */
 
79
#if !defined(PATH_MAX)
 
80
#if defined(MAXPATHLEN)
 
81
#define PATH_MAX MAXPATHLEN
 
82
#else
 
83
#define PATH_MAX 1024
 
84
#endif /* MAXPATHLEN */
 
85
#endif /* !PATH_MAX */
 
86
 
 
87
#if !defined(MAXHOSTNAMELEN)
 
88
#define MAXHOSTNAMELEN 32
 
89
#endif /* !MAXHOSTNAMELEN */
 
90
 
 
91
#include "Configint.h"
 
92
#include "xf86tokens.h"
 
93
 
 
94
#define CONFIG_BUF_LEN     1024
 
95
 
 
96
static int StringToToken (char *, xf86ConfigSymTabRec *);
 
97
 
 
98
static FILE *configFile = NULL;
 
99
static const char **builtinConfig = NULL;
 
100
static int builtinIndex = 0;
 
101
static int configPos = 0;               /* current readers position */
 
102
static int configLineNo = 0;    /* linenumber */
 
103
static char *configBuf, *configRBuf;    /* buffer for lines */
 
104
static char *configPath;                /* path to config file */
 
105
static char *configSection = NULL;      /* name of current section being parsed */
 
106
static int pushToken = LOCK_TOKEN;
 
107
static int eol_seen = 0;                /* private state to handle comments */
 
108
LexRec val;
 
109
 
 
110
#ifdef __UNIXOS2__
 
111
extern char *__XOS2RedirRoot(char *path);
 
112
#endif
 
113
 
 
114
/* 
 
115
 * xf86strToUL --
 
116
 *
 
117
 *  A portable, but restricted, version of strtoul().  It only understands
 
118
 *  hex, octal, and decimal.  But it's good enough for our needs.
 
119
 */
 
120
unsigned int
 
121
xf86strToUL (char *str)
 
122
{
 
123
        int base = 10;
 
124
        char *p = str;
 
125
        unsigned int tot = 0;
 
126
 
 
127
        if (*p == '0')
 
128
        {
 
129
                p++;
 
130
                if ((*p == 'x') || (*p == 'X'))
 
131
                {
 
132
                        p++;
 
133
                        base = 16;
 
134
                }
 
135
                else
 
136
                        base = 8;
 
137
        }
 
138
        while (*p)
 
139
        {
 
140
                if ((*p >= '0') && (*p <= ((base == 8) ? '7' : '9')))
 
141
                {
 
142
                        tot = tot * base + (*p - '0');
 
143
                }
 
144
                else if ((base == 16) && (*p >= 'a') && (*p <= 'f'))
 
145
                {
 
146
                        tot = tot * base + 10 + (*p - 'a');
 
147
                }
 
148
                else if ((base == 16) && (*p >= 'A') && (*p <= 'F'))
 
149
                {
 
150
                        tot = tot * base + 10 + (*p - 'A');
 
151
                }
 
152
                else
 
153
                {
 
154
                        return (tot);
 
155
                }
 
156
                p++;
 
157
        }
 
158
        return (tot);
 
159
}
 
160
 
 
161
/* 
 
162
 * xf86getToken --
 
163
 *      Read next Token form the config file. Handle the global variable
 
164
 *      pushToken.
 
165
 */
 
166
int
 
167
xf86getToken (xf86ConfigSymTabRec * tab)
 
168
{
 
169
        int c, i;
 
170
 
 
171
        /* 
 
172
         * First check whether pushToken has a different value than LOCK_TOKEN.
 
173
         * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the
 
174
         * oth * case the next token must be read from the input.
 
175
         */
 
176
        if (pushToken == EOF_TOKEN)
 
177
                return (EOF_TOKEN);
 
178
        else if (pushToken == LOCK_TOKEN)
 
179
        {
 
180
                /*
 
181
                 * eol_seen is only set for the first token after a newline.
 
182
                 */
 
183
                eol_seen = 0;
 
184
 
 
185
                c = configBuf[configPos];
 
186
 
 
187
                /* 
 
188
                 * Get start of next Token. EOF is handled,
 
189
                 * whitespaces are skipped. 
 
190
                 */
 
191
 
 
192
again:
 
193
                if (!c)
 
194
                {
 
195
                        char *ret;
 
196
                        if (configFile)
 
197
                                ret = fgets (configBuf, CONFIG_BUF_LEN - 1, configFile);
 
198
                        else {
 
199
                                if (builtinConfig[builtinIndex] == NULL)
 
200
                                        ret = NULL;
 
201
                                else {
 
202
                                        ret = strncpy(configBuf, builtinConfig[builtinIndex],
 
203
                                                        CONFIG_BUF_LEN);
 
204
                                        builtinIndex++;
 
205
                                }
 
206
                        }
 
207
                        if (ret == NULL)
 
208
                        {
 
209
                                return (pushToken = EOF_TOKEN);
 
210
                        }
 
211
                        configLineNo++;
 
212
                        configPos = 0;
 
213
                        eol_seen = 1;
 
214
                }
 
215
 
 
216
                i = 0;
 
217
                for (;;) {
 
218
                        c = configBuf[configPos++];
 
219
                        configRBuf[i++] = c;
 
220
                        switch (c) {
 
221
                                case ' ':
 
222
                                case '\t':
 
223
                                case '\r':
 
224
                                        continue;
 
225
                                case '\n':
 
226
                                        i = 0;
 
227
                                        continue;
 
228
                        }
 
229
                        break;
 
230
                }
 
231
                if (c == '\0')
 
232
                        goto again;
 
233
 
 
234
                if (c == '#')
 
235
                {
 
236
                        do
 
237
                        {
 
238
                                configRBuf[i++] = (c = configBuf[configPos++]);
 
239
                        }
 
240
                        while ((c != '\n') && (c != '\r') && (c != '\0'));
 
241
                        configRBuf[i] = '\0';
 
242
                        /* XXX no private copy.
 
243
                         * Use xf86addComment when setting a comment.
 
244
                         */
 
245
                        val.str = configRBuf;
 
246
                        return (COMMENT);
 
247
                }
 
248
 
 
249
                /* GJA -- handle '-' and ','  * Be careful: "-hsync" is a keyword. */
 
250
                else if ((c == ',') && !isalpha (configBuf[configPos]))
 
251
                {
 
252
                        return COMMA;
 
253
                }
 
254
                else if ((c == '-') && !isalpha (configBuf[configPos]))
 
255
                {
 
256
                        return DASH;
 
257
                }
 
258
 
 
259
                /* 
 
260
                 * Numbers are returned immediately ...
 
261
                 */
 
262
                if (isdigit (c))
 
263
                {
 
264
                        int base;
 
265
 
 
266
                        if (c == '0')
 
267
                                if ((configBuf[configPos] == 'x') ||
 
268
                                        (configBuf[configPos] == 'X'))
 
269
                                        base = 16;
 
270
                                else
 
271
                                        base = 8;
 
272
                        else
 
273
                                base = 10;
 
274
 
 
275
                        configRBuf[0] = c;
 
276
                        i = 1;
 
277
                        while (isdigit (c = configBuf[configPos++]) ||
 
278
                                   (c == '.') || (c == 'x') || (c == 'X') ||
 
279
                                   ((base == 16) && (((c >= 'a') && (c <= 'f')) ||
 
280
                                                                         ((c >= 'A') && (c <= 'F')))))
 
281
                                configRBuf[i++] = c;
 
282
                        configPos--;            /* GJA -- one too far */
 
283
                        configRBuf[i] = '\0';
 
284
                        val.num = xf86strToUL (configRBuf);
 
285
                        val.realnum = atof (configRBuf);
 
286
                        return (NUMBER);
 
287
                }
 
288
 
 
289
                /* 
 
290
                 * All Strings START with a \" ...
 
291
                 */
 
292
                else if (c == '\"')
 
293
                {
 
294
                        i = -1;
 
295
                        do
 
296
                        {
 
297
                                configRBuf[++i] = (c = configBuf[configPos++]);
 
298
                        }
 
299
                        while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
 
300
                        configRBuf[i] = '\0';
 
301
                        val.str = xf86confmalloc (strlen (configRBuf) + 1);
 
302
                        strcpy (val.str, configRBuf);   /* private copy ! */
 
303
                        return (STRING);
 
304
                }
 
305
 
 
306
                /* 
 
307
                 * ... and now we MUST have a valid token.  The search is
 
308
                 * handled later along with the pushed tokens.
 
309
                 */
 
310
                else
 
311
                {
 
312
                        configRBuf[0] = c;
 
313
                        i = 0;
 
314
                        do
 
315
                        {
 
316
                                configRBuf[++i] = (c = configBuf[configPos++]);;
 
317
                        }
 
318
                        while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#'));
 
319
                        --configPos;
 
320
                        configRBuf[i] = '\0';
 
321
                        i = 0;
 
322
                }
 
323
 
 
324
        }
 
325
        else
 
326
        {
 
327
 
 
328
                /* 
 
329
                 * Here we deal with pushed tokens. Reinitialize pushToken again. If
 
330
                 * the pushed token was NUMBER || STRING return them again ...
 
331
                 */
 
332
                int temp = pushToken;
 
333
                pushToken = LOCK_TOKEN;
 
334
 
 
335
                if (temp == COMMA || temp == DASH)
 
336
                        return (temp);
 
337
                if (temp == NUMBER || temp == STRING)
 
338
                        return (temp);
 
339
        }
 
340
 
 
341
        /* 
 
342
         * Joop, at last we have to lookup the token ...
 
343
         */
 
344
        if (tab)
 
345
        {
 
346
                i = 0;
 
347
                while (tab[i].token != -1)
 
348
                        if (xf86nameCompare (configRBuf, tab[i].name) == 0)
 
349
                                return (tab[i].token);
 
350
                        else
 
351
                                i++;
 
352
        }
 
353
 
 
354
        return (ERROR_TOKEN);           /* Error catcher */
 
355
}
 
356
 
 
357
int
 
358
xf86getSubToken (char **comment)
 
359
{
 
360
        int token;
 
361
 
 
362
        for (;;) {
 
363
                token = xf86getToken(NULL);
 
364
                if (token == COMMENT) {
 
365
                        if (comment)
 
366
                                *comment = xf86addComment(*comment, val.str);
 
367
                }
 
368
                else
 
369
                        return (token);
 
370
        }
 
371
        /*NOTREACHED*/
 
372
}
 
373
 
 
374
int
 
375
xf86getSubTokenWithTab (char **comment, xf86ConfigSymTabRec *tab)
 
376
{
 
377
        int token;
 
378
 
 
379
        for (;;) {
 
380
                token = xf86getToken(tab);
 
381
                if (token == COMMENT) {
 
382
                        if (comment)
 
383
                                *comment = xf86addComment(*comment, val.str);
 
384
                }
 
385
                else
 
386
                        return (token);
 
387
        }
 
388
        /*NOTREACHED*/
 
389
}
 
390
 
 
391
void
 
392
xf86unGetToken (int token)
 
393
{
 
394
        pushToken = token;
 
395
}
 
396
 
 
397
char *
 
398
xf86tokenString (void)
 
399
{
 
400
        return configRBuf;
 
401
}
 
402
 
 
403
int
 
404
xf86pathIsAbsolute(const char *path)
 
405
{
 
406
        if (path && path[0] == '/')
 
407
                return 1;
 
408
#ifdef __UNIXOS2__
 
409
        if (path && (path[0] == '\\' || (path[1] == ':')))
 
410
                return 1;
 
411
#endif
 
412
        return 0;
 
413
}
 
414
 
 
415
/* A path is "safe" if it is relative and if it contains no ".." elements. */
 
416
int
 
417
xf86pathIsSafe(const char *path)
 
418
{
 
419
        if (xf86pathIsAbsolute(path))
 
420
                return 0;
 
421
 
 
422
        /* Compare with ".." */
 
423
        if (!strcmp(path, ".."))
 
424
                return 0;
 
425
 
 
426
        /* Look for leading "../" */
 
427
        if (!strncmp(path, "../", 3))
 
428
                return 0;
 
429
 
 
430
        /* Look for trailing "/.." */
 
431
        if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/.."))
 
432
                return 0;
 
433
 
 
434
        /* Look for "/../" */
 
435
        if (strstr(path, "/../"))
 
436
                return 0;
 
437
 
 
438
        return 1;
 
439
}
 
440
 
 
441
/*
 
442
 * This function substitutes the following escape sequences:
 
443
 *
 
444
 *    %A    cmdline argument as an absolute path (must be absolute to match)
 
445
 *    %R    cmdline argument as a relative path
 
446
 *    %S    cmdline argument as a "safe" path (relative, and no ".." elements)
 
447
 *    %X    default config file name ("xorg.conf")
 
448
 *    %H    hostname
 
449
 *    %E    config file environment ($XORGCONFIG) as an absolute path
 
450
 *    %F    config file environment ($XORGCONFIG) as a relative path
 
451
 *    %G    config file environment ($XORGCONFIG) as a safe path
 
452
 *    %D    $HOME
 
453
 *    %P    projroot
 
454
 *    %M    major version number
 
455
 *    %%    %
 
456
 *    %&    UNIXOS2 only: prepend X11ROOT env var
 
457
 */
 
458
 
 
459
#ifndef XCONFIGFILE
 
460
#define XCONFIGFILE     "xorg.conf"
 
461
#endif
 
462
#ifndef PROJECTROOT
 
463
#define PROJECTROOT     "/usr/X11R6"
 
464
#endif
 
465
#ifndef XCONFENV
 
466
#define XCONFENV        "XORGCONFIG"
 
467
#endif
 
468
#define XFREE86CFGFILE "XF86Config"
 
469
#ifndef XF86_VERSION_MAJOR
 
470
#ifdef XVERSION
 
471
#if XVERSION > 40000000
 
472
#define XF86_VERSION_MAJOR      (XVERSION / 10000000)
 
473
#else
 
474
#define XF86_VERSION_MAJOR      (XVERSION / 1000)
 
475
#endif
 
476
#else
 
477
#define XF86_VERSION_MAJOR      4
 
478
#endif
 
479
#endif
 
480
 
 
481
#define BAIL_OUT                do {                                                                    \
 
482
                                                        xf86conffree(result);                           \
 
483
                                                        return NULL;                                            \
 
484
                                                } while (0)
 
485
 
 
486
#define CHECK_LENGTH    do {                                                                    \
 
487
                                                        if (l > PATH_MAX) {                                     \
 
488
                                                                BAIL_OUT;                                               \
 
489
                                                        }                                                                       \
 
490
                                                } while (0)
 
491
 
 
492
#define APPEND_STR(s)   do {                                                                    \
 
493
                                                        if (strlen(s) + l > PATH_MAX) {         \
 
494
                                                                BAIL_OUT;                                               \
 
495
                                                        } else {                                                        \
 
496
                                                                strcpy(result + l, s);                  \
 
497
                                                                l += strlen(s);                                 \
 
498
                                                        }                                                                       \
 
499
                                                } while (0)
 
500
 
 
501
static char *
 
502
DoSubstitution(const char *template, const char *cmdline, const char *projroot,
 
503
                                int *cmdlineUsed, int *envUsed, char *XConfigFile)
 
504
{
 
505
        char *result;
 
506
        int i, l;
 
507
        static const char *env = NULL, *home = NULL;
 
508
        static char *hostname = NULL;
 
509
        static char majorvers[3] = "";
 
510
#ifdef __UNIXOS2__
 
511
        static char *x11root = NULL;
 
512
#endif
 
513
 
 
514
        if (!template)
 
515
                return NULL;
 
516
 
 
517
        if (cmdlineUsed)
 
518
                *cmdlineUsed = 0;
 
519
        if (envUsed)
 
520
                *envUsed = 0;
 
521
 
 
522
        result = xf86confmalloc(PATH_MAX + 1);
 
523
        l = 0;
 
524
        for (i = 0; template[i]; i++) {
 
525
                if (template[i] != '%') {
 
526
                        result[l++] = template[i];
 
527
                        CHECK_LENGTH;
 
528
                } else {
 
529
                        switch (template[++i]) {
 
530
                        case 'A':
 
531
                                if (cmdline && xf86pathIsAbsolute(cmdline)) {
 
532
                                        APPEND_STR(cmdline);
 
533
                                        if (cmdlineUsed)
 
534
                                                *cmdlineUsed = 1;
 
535
                                } else
 
536
                                        BAIL_OUT;
 
537
                                break;
 
538
                        case 'R':
 
539
                                if (cmdline && !xf86pathIsAbsolute(cmdline)) {
 
540
                                        APPEND_STR(cmdline);
 
541
                                        if (cmdlineUsed)
 
542
                                                *cmdlineUsed = 1;
 
543
                                } else 
 
544
                                        BAIL_OUT;
 
545
                                break;
 
546
                        case 'S':
 
547
                                if (cmdline && xf86pathIsSafe(cmdline)) {
 
548
                                        APPEND_STR(cmdline);
 
549
                                        if (cmdlineUsed)
 
550
                                                *cmdlineUsed = 1;
 
551
                                } else 
 
552
                                        BAIL_OUT;
 
553
                                break;
 
554
                        case 'X':
 
555
                                APPEND_STR(XConfigFile);
 
556
                                break;
 
557
                        case 'H':
 
558
                                if (!hostname) {
 
559
                                        if ((hostname = xf86confmalloc(MAXHOSTNAMELEN + 1))) {
 
560
                                                if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
 
561
                                                        hostname[MAXHOSTNAMELEN] = '\0';
 
562
                                                } else {
 
563
                                                        xf86conffree(hostname);
 
564
                                                        hostname = NULL;
 
565
                                                }
 
566
                                        }
 
567
                                }
 
568
                                if (hostname)
 
569
                                        APPEND_STR(hostname);
 
570
                                break;
 
571
                        case 'E':
 
572
                                if (!env)
 
573
                                        env = getenv(XCONFENV);
 
574
                                if (env && xf86pathIsAbsolute(env)) {
 
575
                                        APPEND_STR(env);
 
576
                                        if (envUsed)
 
577
                                                *envUsed = 1;
 
578
                                } else
 
579
                                        BAIL_OUT;
 
580
                                break;
 
581
                        case 'F':
 
582
                                if (!env)
 
583
                                        env = getenv(XCONFENV);
 
584
                                if (env && !xf86pathIsAbsolute(env)) {
 
585
                                        APPEND_STR(env);
 
586
                                        if (envUsed)
 
587
                                                *envUsed = 1;
 
588
                                } else
 
589
                                        BAIL_OUT;
 
590
                                break;
 
591
                        case 'G':
 
592
                                if (!env)
 
593
                                        env = getenv(XCONFENV);
 
594
                                if (env && xf86pathIsSafe(env)) {
 
595
                                        APPEND_STR(env);
 
596
                                        if (envUsed)
 
597
                                                *envUsed = 1;
 
598
                                } else
 
599
                                        BAIL_OUT;
 
600
                                break;
 
601
                        case 'D':
 
602
                                if (!home)
 
603
                                        home = getenv("HOME");
 
604
                                if (home && xf86pathIsAbsolute(home))
 
605
                                        APPEND_STR(home);
 
606
                                else
 
607
                                        BAIL_OUT;
 
608
                                break;
 
609
                        case 'P':
 
610
                                if (projroot && xf86pathIsAbsolute(projroot))
 
611
                                        APPEND_STR(projroot);
 
612
                                else
 
613
                                        BAIL_OUT;
 
614
                                break;
 
615
                        case 'M':
 
616
                                if (!majorvers[0]) {
 
617
                                        if (XF86_VERSION_MAJOR < 0 || XF86_VERSION_MAJOR > 99) {
 
618
                                                fprintf(stderr, "XF86_VERSION_MAJOR is out of range\n");
 
619
                                                BAIL_OUT;
 
620
                                        } else
 
621
                                                sprintf(majorvers, "%d", XF86_VERSION_MAJOR);
 
622
                                }
 
623
                                APPEND_STR(majorvers);
 
624
                                break;
 
625
                        case '%':
 
626
                                result[l++] = '%';
 
627
                                CHECK_LENGTH;
 
628
                                break;
 
629
#ifdef __UNIXOS2__
 
630
                        case '&':
 
631
                                if (!x11root)
 
632
                                        x11root = getenv("X11ROOT");
 
633
                                if (x11root)
 
634
                                        APPEND_STR(x11root);
 
635
                                else
 
636
                                        BAIL_OUT;
 
637
                                break;
 
638
#endif
 
639
                        default:
 
640
                                fprintf(stderr, "invalid escape %%%c found in path template\n",
 
641
                                                template[i]);
 
642
                                BAIL_OUT;
 
643
                                break;
 
644
                        }
 
645
                }
 
646
        }
 
647
#ifdef DEBUG
 
648
        fprintf(stderr, "Converted `%s' to `%s'\n", template, result);
 
649
#endif
 
650
        return result;
 
651
}
 
652
 
 
653
/* 
 
654
 * xf86openConfigFile --
 
655
 *
 
656
 * This function take a config file search path (optional), a command-line
 
657
 * specified file name (optional) and the ProjectRoot path (optional) and
 
658
 * locates and opens a config file based on that information.  If a
 
659
 * command-line file name is specified, then this function fails if none
 
660
 * of the located files.
 
661
 *
 
662
 * The return value is a pointer to the actual name of the file that was
 
663
 * opened.  When no file is found, the return value is NULL.
 
664
 *
 
665
 * The escape sequences allowed in the search path are defined above.
 
666
 *  
 
667
 */
 
668
 
 
669
#ifndef DEFAULT_CONF_PATH
 
670
#define DEFAULT_CONF_PATH       "/etc/X11/%S," \
 
671
                                                        "%P/etc/X11/%S," \
 
672
                                                        "/etc/X11/%G," \
 
673
                                                        "%P/etc/X11/%G," \
 
674
                                                        "/etc/X11/%X-%M," \
 
675
                                                        "/etc/X11/%X," \
 
676
                                                        "/etc/%X," \
 
677
                                                        "%P/etc/X11/%X.%H," \
 
678
                                                        "%P/etc/X11/%X-%M," \
 
679
                                                        "%P/etc/X11/%X," \
 
680
                                                        "%P/lib/X11/%X.%H," \
 
681
                                                        "%P/lib/X11/%X-%M," \
 
682
                                                        "%P/lib/X11/%X"
 
683
#endif
 
684
 
 
685
const char *
 
686
xf86openConfigFile(const char *path, const char *cmdline, const char *projroot)
 
687
{
 
688
        char *pathcopy;
 
689
        const char *template;
 
690
        int cmdlineUsed = 0;
 
691
 
 
692
        configFile = NULL;
 
693
        configPos = 0;          /* current readers position */
 
694
        configLineNo = 0;       /* linenumber */
 
695
        pushToken = LOCK_TOKEN;
 
696
 
 
697
        if (!path || !path[0])
 
698
                path = DEFAULT_CONF_PATH;
 
699
        pathcopy = xf86confmalloc(strlen(path) + 1);
 
700
        strcpy(pathcopy, path);
 
701
        if (!projroot || !projroot[0])
 
702
                projroot = PROJECTROOT;
 
703
 
 
704
        template = strtok(pathcopy, ",");
 
705
 
 
706
        /* First, search for a config file. */
 
707
        while (template && !configFile) {
 
708
                if ((configPath = DoSubstitution(template, cmdline, projroot,
 
709
                                                 &cmdlineUsed, NULL,
 
710
                                                 XCONFIGFILE))) {
 
711
                        if ((configFile = fopen(configPath, "r")) != 0) {
 
712
                                if (cmdline && !cmdlineUsed) {
 
713
                                        fclose(configFile);
 
714
                                        configFile = NULL;
 
715
                                }
 
716
                        }
 
717
                }
 
718
                if (configPath && !configFile) {
 
719
                        xf86conffree(configPath);
 
720
                        configPath = NULL;
 
721
                }
 
722
                template = strtok(NULL, ",");
 
723
        }
 
724
        
 
725
        /* Then search for fallback */
 
726
        if (!configFile) {
 
727
            strcpy(pathcopy, path);
 
728
            template = strtok(pathcopy, ",");
 
729
 
 
730
            while (template && !configFile) {
 
731
                if ((configPath = DoSubstitution(template, cmdline, projroot,
 
732
                                                 &cmdlineUsed, NULL,
 
733
                                                 XFREE86CFGFILE))) {
 
734
                    if ((configFile = fopen(configPath, "r")) != 0) {
 
735
                        if (cmdline && !cmdlineUsed) {
 
736
                            fclose(configFile);
 
737
                            configFile = NULL;
 
738
                        }
 
739
                    }
 
740
                }
 
741
                if (configPath && !configFile) {
 
742
                    xf86conffree(configPath);
 
743
                    configPath = NULL;
 
744
                }
 
745
                template = strtok(NULL, ",");
 
746
            }
 
747
        }
 
748
        
 
749
        xf86conffree(pathcopy);
 
750
        if (!configFile) {
 
751
 
 
752
                return NULL;
 
753
        }
 
754
 
 
755
        configBuf = xf86confmalloc (CONFIG_BUF_LEN);
 
756
        configRBuf = xf86confmalloc (CONFIG_BUF_LEN);
 
757
        configBuf[0] = '\0';            /* sanity ... */
 
758
 
 
759
        return configPath;
 
760
}
 
761
 
 
762
void
 
763
xf86closeConfigFile (void)
 
764
{
 
765
        xf86conffree (configPath);
 
766
        configPath = NULL;
 
767
        xf86conffree (configRBuf);
 
768
        configRBuf = NULL;
 
769
        xf86conffree (configBuf);
 
770
        configBuf = NULL;
 
771
 
 
772
        if (configFile) {
 
773
                fclose (configFile);
 
774
                configFile = NULL;
 
775
        } else {
 
776
                builtinConfig = NULL;
 
777
                builtinIndex = 0;
 
778
        }
 
779
}
 
780
 
 
781
void
 
782
xf86setBuiltinConfig(const char *config[])
 
783
{
 
784
        builtinConfig = config;
 
785
        configPath = xf86configStrdup("<builtin configuration>");
 
786
        configBuf = xf86confmalloc (CONFIG_BUF_LEN);
 
787
        configRBuf = xf86confmalloc (CONFIG_BUF_LEN);
 
788
        configBuf[0] = '\0';            /* sanity ... */
 
789
 
 
790
}
 
791
 
 
792
void
 
793
xf86parseError (char *format,...)
 
794
{
 
795
        va_list ap;
 
796
 
 
797
        ErrorF ("Parse error on line %d of section %s in file %s\n\t",
 
798
                 configLineNo, configSection, configPath);
 
799
        va_start (ap, format);
 
800
        VErrorF (format, ap);
 
801
        va_end (ap);
 
802
 
 
803
        ErrorF ("\n");
 
804
}
 
805
 
 
806
void
 
807
xf86parseWarning (char *format,...)
 
808
{
 
809
        va_list ap;
 
810
 
 
811
        ErrorF ("Parse warning on line %d of section %s in file %s\n\t",
 
812
                 configLineNo, configSection, configPath);
 
813
        va_start (ap, format);
 
814
        VErrorF (format, ap);
 
815
        va_end (ap);
 
816
 
 
817
        ErrorF ("\n");
 
818
}
 
819
 
 
820
void
 
821
xf86validationError (char *format,...)
 
822
{
 
823
        va_list ap;
 
824
 
 
825
        ErrorF ("Data incomplete in file %s\n\t", configPath);
 
826
        va_start (ap, format);
 
827
        VErrorF (format, ap);
 
828
        va_end (ap);
 
829
 
 
830
        ErrorF ("\n");
 
831
}
 
832
 
 
833
void
 
834
xf86setSection (char *section)
 
835
{
 
836
        if (configSection)
 
837
                xf86conffree(configSection);
 
838
        configSection = xf86confmalloc(strlen (section) + 1);
 
839
        strcpy (configSection, section);
 
840
}
 
841
 
 
842
/* 
 
843
 * xf86getToken --
 
844
 *  Lookup a string if it is actually a token in disguise.
 
845
 */
 
846
int
 
847
xf86getStringToken (xf86ConfigSymTabRec * tab)
 
848
{
 
849
        return StringToToken (val.str, tab);
 
850
}
 
851
 
 
852
static int
 
853
StringToToken (char *str, xf86ConfigSymTabRec * tab)
 
854
{
 
855
        int i;
 
856
 
 
857
        for (i = 0; tab[i].token != -1; i++)
 
858
        {
 
859
                if (!xf86nameCompare (tab[i].name, str))
 
860
                        return tab[i].token;
 
861
        }
 
862
        return (ERROR_TOKEN);
 
863
}
 
864
 
 
865
 
 
866
/* 
 
867
 * Compare two names.  The characters '_', ' ', and '\t' are ignored
 
868
 * in the comparison.
 
869
 */
 
870
int
 
871
xf86nameCompare (const char *s1, const char *s2)
 
872
{
 
873
        char c1, c2;
 
874
 
 
875
        if (!s1 || *s1 == 0) {
 
876
                if (!s2 || *s2 == 0)
 
877
                        return (0);
 
878
                else
 
879
                        return (1);
 
880
                }
 
881
 
 
882
        while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
 
883
                s1++;
 
884
        while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
 
885
                s2++;
 
886
        c1 = (isupper (*s1) ? tolower (*s1) : *s1);
 
887
        c2 = (isupper (*s2) ? tolower (*s2) : *s2);
 
888
        while (c1 == c2)
 
889
        {
 
890
                if (c1 == '\0')
 
891
                        return (0);
 
892
                s1++;
 
893
                s2++;
 
894
                while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
 
895
                        s1++;
 
896
                while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
 
897
                        s2++;
 
898
                c1 = (isupper (*s1) ? tolower (*s1) : *s1);
 
899
                c2 = (isupper (*s2) ? tolower (*s2) : *s2);
 
900
        }
 
901
        return (c1 - c2);
 
902
}
 
903
 
 
904
char *
 
905
xf86addComment(char *cur, char *add)
 
906
{
 
907
        char *str;
 
908
        int len, curlen, iscomment, hasnewline = 0, endnewline;
 
909
 
 
910
        if (add == NULL || add[0] == '\0')
 
911
                return (cur);
 
912
 
 
913
        if (cur) {
 
914
                curlen = strlen(cur);
 
915
                if (curlen)
 
916
                    hasnewline = cur[curlen - 1] == '\n';
 
917
                eol_seen = 0;
 
918
        }
 
919
        else
 
920
                curlen = 0;
 
921
 
 
922
        str = add;
 
923
        iscomment = 0;
 
924
        while (*str) {
 
925
            if (*str != ' ' && *str != '\t')
 
926
                break;
 
927
            ++str;
 
928
        }
 
929
        iscomment = (*str == '#');
 
930
 
 
931
        len = strlen(add);
 
932
        endnewline = add[len - 1] == '\n';
 
933
        len +=  1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
 
934
 
 
935
        if ((str = xf86confrealloc(cur, len + curlen)) == NULL)
 
936
                return (cur);
 
937
 
 
938
        cur = str;
 
939
 
 
940
        if (eol_seen || (curlen && !hasnewline))
 
941
                cur[curlen++] = '\n';
 
942
        if (!iscomment)
 
943
                cur[curlen++] = '#';
 
944
        strcpy(cur + curlen, add);
 
945
        if (!endnewline)
 
946
                strcat(cur, "\n");
 
947
 
 
948
        return (cur);
 
949
}