First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / parser / scan.c
blob55c7eb55f9493362c84fbc7e373f12ff4d8371fe
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
28 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
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:
37 * The above copyright notice and this permission notice shall be included in
38 * all copies or substantial portions of the Software.
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.
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).
55 /* View/edit this file with tab stops set to 4 */
57 #ifdef HAVE_XORG_CONFIG_H
58 #include <xorg-config.h>
59 #endif
61 #include <ctype.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <stdarg.h>
68 #if !defined(X_NOT_POSIX)
69 #if defined(_POSIX_SOURCE)
70 #include <limits.h>
71 #else
72 #define _POSIX_SOURCE
73 #include <limits.h>
74 #undef _POSIX_SOURCE
75 #endif /* _POSIX_SOURCE */
76 #endif /* !X_NOT_POSIX */
77 #if !defined(PATH_MAX)
78 #if defined(MAXPATHLEN)
79 #define PATH_MAX MAXPATHLEN
80 #else
81 #define PATH_MAX 1024
82 #endif /* MAXPATHLEN */
83 #endif /* !PATH_MAX */
85 #if !defined(MAXHOSTNAMELEN)
86 #define MAXHOSTNAMELEN 32
87 #endif /* !MAXHOSTNAMELEN */
89 #include "Configint.h"
90 #include "xf86tokens.h"
92 #define CONFIG_BUF_LEN 1024
94 static int StringToToken (char *, xf86ConfigSymTabRec *);
96 static FILE *configFile = NULL;
97 static const char **builtinConfig = NULL;
98 static int builtinIndex = 0;
99 static int configPos = 0; /* current readers position */
100 static int configLineNo = 0; /* linenumber */
101 static char *configBuf, *configRBuf; /* buffer for lines */
102 static char *configPath; /* path to config file */
103 static char *configSection = NULL; /* name of current section being parsed */
104 static int pushToken = LOCK_TOKEN;
105 static int eol_seen = 0; /* private state to handle comments */
106 LexRec val;
109 * xf86strToUL --
111 * A portable, but restricted, version of strtoul(). It only understands
112 * hex, octal, and decimal. But it's good enough for our needs.
114 static unsigned int
115 xf86strToUL (char *str)
117 int base = 10;
118 char *p = str;
119 unsigned int tot = 0;
121 if (*p == '0')
123 p++;
124 if ((*p == 'x') || (*p == 'X'))
126 p++;
127 base = 16;
129 else
130 base = 8;
132 while (*p)
134 if ((*p >= '0') && (*p <= ((base == 8) ? '7' : '9')))
136 tot = tot * base + (*p - '0');
138 else if ((base == 16) && (*p >= 'a') && (*p <= 'f'))
140 tot = tot * base + 10 + (*p - 'a');
142 else if ((base == 16) && (*p >= 'A') && (*p <= 'F'))
144 tot = tot * base + 10 + (*p - 'A');
146 else
148 return (tot);
150 p++;
152 return (tot);
156 * xf86getNextLine --
158 * read from the configFile FILE stream until we encounter a new
159 * line; this is effectively just a big wrapper for fgets(3).
161 * xf86getToken() assumes that we will read up to the next
162 * newline; we need to grow configBuf and configRBuf as needed to
163 * support that.
166 static char*
167 xf86getNextLine(void)
169 static int configBufLen = CONFIG_BUF_LEN;
170 char *tmpConfigBuf, *tmpConfigRBuf;
171 int c, i, pos = 0, eolFound = 0;
172 char *ret = NULL;
175 * reallocate the string if it was grown last time (i.e., is no
176 * longer CONFIG_BUF_LEN); we malloc the new strings first, so
177 * that if either of the mallocs fail, we can fall back on the
178 * existing buffer allocations
181 if (configBufLen != CONFIG_BUF_LEN) {
183 tmpConfigBuf = xf86confmalloc(CONFIG_BUF_LEN);
184 tmpConfigRBuf = xf86confmalloc(CONFIG_BUF_LEN);
186 if (!tmpConfigBuf || !tmpConfigRBuf) {
189 * at least one of the mallocs failed; keep the old buffers
190 * and free any partial allocations
193 xf86conffree(tmpConfigBuf);
194 xf86conffree(tmpConfigRBuf);
196 } else {
199 * malloc succeeded; free the old buffers and use the new
200 * buffers
203 configBufLen = CONFIG_BUF_LEN;
205 xf86conffree(configBuf);
206 xf86conffree(configRBuf);
208 configBuf = tmpConfigBuf;
209 configRBuf = tmpConfigRBuf;
213 /* read in another block of chars */
215 do {
216 ret = fgets(configBuf + pos, configBufLen - pos - 1, configFile);
218 if (!ret) break;
220 /* search for EOL in the new block of chars */
222 for (i = pos; i < (configBufLen - 1); i++) {
223 c = configBuf[i];
225 if (c == '\0') break;
227 if ((c == '\n') || (c == '\r')) {
228 eolFound = 1;
229 break;
234 * if we didn't find EOL, then grow the string and
235 * read in more
238 if (!eolFound) {
240 tmpConfigBuf = xf86confrealloc(configBuf, configBufLen + CONFIG_BUF_LEN);
241 tmpConfigRBuf = xf86confrealloc(configRBuf, configBufLen + CONFIG_BUF_LEN);
243 if (!tmpConfigBuf || !tmpConfigRBuf) {
246 * at least one of the reallocations failed; use the
247 * new allocation that succeeded, but we have to
248 * fallback to the previous configBufLen size and use
249 * the string we have, even though we don't have an
250 * EOL
253 if (tmpConfigBuf) configBuf = tmpConfigBuf;
254 if (tmpConfigRBuf) configRBuf = tmpConfigRBuf;
256 break;
258 } else {
260 /* reallocation succeeded */
262 configBuf = tmpConfigBuf;
263 configRBuf = tmpConfigRBuf;
264 pos = i;
265 configBufLen += CONFIG_BUF_LEN;
269 } while (!eolFound);
271 return (ret);
275 * xf86getToken --
276 * Read next Token from the config file. Handle the global variable
277 * pushToken.
280 xf86getToken (xf86ConfigSymTabRec * tab)
282 int c, i;
285 * First check whether pushToken has a different value than LOCK_TOKEN.
286 * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the
287 * oth * case the next token must be read from the input.
289 if (pushToken == EOF_TOKEN)
290 return (EOF_TOKEN);
291 else if (pushToken == LOCK_TOKEN)
294 * eol_seen is only set for the first token after a newline.
296 eol_seen = 0;
298 c = configBuf[configPos];
301 * Get start of next Token. EOF is handled,
302 * whitespaces are skipped.
305 again:
306 if (!c)
308 char *ret;
309 if (configFile)
310 ret = xf86getNextLine();
311 else {
312 if (builtinConfig[builtinIndex] == NULL)
313 ret = NULL;
314 else {
315 ret = strncpy(configBuf, builtinConfig[builtinIndex],
316 CONFIG_BUF_LEN);
317 builtinIndex++;
320 if (ret == NULL)
322 return (pushToken = EOF_TOKEN);
324 configLineNo++;
325 configPos = 0;
326 eol_seen = 1;
329 i = 0;
330 for (;;) {
331 c = configBuf[configPos++];
332 configRBuf[i++] = c;
333 switch (c) {
334 case ' ':
335 case '\t':
336 case '\r':
337 continue;
338 case '\n':
339 i = 0;
340 continue;
342 break;
344 if (c == '\0')
345 goto again;
347 if (c == '#')
351 configRBuf[i++] = (c = configBuf[configPos++]);
353 while ((c != '\n') && (c != '\r') && (c != '\0'));
354 configRBuf[i] = '\0';
355 /* XXX no private copy.
356 * Use xf86addComment when setting a comment.
358 val.str = configRBuf;
359 return (COMMENT);
362 /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */
363 else if ((c == ',') && !isalpha (configBuf[configPos]))
365 return COMMA;
367 else if ((c == '-') && !isalpha (configBuf[configPos]))
369 return DASH;
373 * Numbers are returned immediately ...
375 if (isdigit (c))
377 int base;
379 if (c == '0')
380 if ((configBuf[configPos] == 'x') ||
381 (configBuf[configPos] == 'X'))
382 base = 16;
383 else
384 base = 8;
385 else
386 base = 10;
388 configRBuf[0] = c;
389 i = 1;
390 while (isdigit (c = configBuf[configPos++]) ||
391 (c == '.') || (c == 'x') || (c == 'X') ||
392 ((base == 16) && (((c >= 'a') && (c <= 'f')) ||
393 ((c >= 'A') && (c <= 'F')))))
394 configRBuf[i++] = c;
395 configPos--; /* GJA -- one too far */
396 configRBuf[i] = '\0';
397 val.num = xf86strToUL (configRBuf);
398 val.realnum = atof (configRBuf);
399 return (NUMBER);
403 * All Strings START with a \" ...
405 else if (c == '\"')
407 i = -1;
410 configRBuf[++i] = (c = configBuf[configPos++]);
412 while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
413 configRBuf[i] = '\0';
414 val.str = xf86confmalloc (strlen (configRBuf) + 1);
415 strcpy (val.str, configRBuf); /* private copy ! */
416 return (STRING);
420 * ... and now we MUST have a valid token. The search is
421 * handled later along with the pushed tokens.
423 else
425 configRBuf[0] = c;
426 i = 0;
429 configRBuf[++i] = (c = configBuf[configPos++]);;
431 while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#'));
432 --configPos;
433 configRBuf[i] = '\0';
434 i = 0;
438 else
442 * Here we deal with pushed tokens. Reinitialize pushToken again. If
443 * the pushed token was NUMBER || STRING return them again ...
445 int temp = pushToken;
446 pushToken = LOCK_TOKEN;
448 if (temp == COMMA || temp == DASH)
449 return (temp);
450 if (temp == NUMBER || temp == STRING)
451 return (temp);
455 * Joop, at last we have to lookup the token ...
457 if (tab)
459 i = 0;
460 while (tab[i].token != -1)
461 if (xf86nameCompare (configRBuf, tab[i].name) == 0)
462 return (tab[i].token);
463 else
464 i++;
467 return (ERROR_TOKEN); /* Error catcher */
471 xf86getSubToken (char **comment)
473 int token;
475 for (;;) {
476 token = xf86getToken(NULL);
477 if (token == COMMENT) {
478 if (comment)
479 *comment = xf86addComment(*comment, val.str);
481 else
482 return (token);
484 /*NOTREACHED*/
488 xf86getSubTokenWithTab (char **comment, xf86ConfigSymTabRec *tab)
490 int token;
492 for (;;) {
493 token = xf86getToken(tab);
494 if (token == COMMENT) {
495 if (comment)
496 *comment = xf86addComment(*comment, val.str);
498 else
499 return (token);
501 /*NOTREACHED*/
504 void
505 xf86unGetToken (int token)
507 pushToken = token;
510 char *
511 xf86tokenString (void)
513 return configRBuf;
517 xf86pathIsAbsolute(const char *path)
519 if (path && path[0] == '/')
520 return 1;
521 return 0;
524 /* A path is "safe" if it is relative and if it contains no ".." elements. */
526 xf86pathIsSafe(const char *path)
528 if (xf86pathIsAbsolute(path))
529 return 0;
531 /* Compare with ".." */
532 if (!strcmp(path, ".."))
533 return 0;
535 /* Look for leading "../" */
536 if (!strncmp(path, "../", 3))
537 return 0;
539 /* Look for trailing "/.." */
540 if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/.."))
541 return 0;
543 /* Look for "/../" */
544 if (strstr(path, "/../"))
545 return 0;
547 return 1;
551 * This function substitutes the following escape sequences:
553 * %A cmdline argument as an absolute path (must be absolute to match)
554 * %R cmdline argument as a relative path
555 * %S cmdline argument as a "safe" path (relative, and no ".." elements)
556 * %X default config file name ("xorg.conf")
557 * %H hostname
558 * %E config file environment ($XORGCONFIG) as an absolute path
559 * %F config file environment ($XORGCONFIG) as a relative path
560 * %G config file environment ($XORGCONFIG) as a safe path
561 * %D $HOME
562 * %P projroot
563 * %M major version number
564 * %% %
567 #ifndef XCONFIGFILE
568 #define XCONFIGFILE "xorg.conf"
569 #endif
570 #ifndef PROJECTROOT
571 #define PROJECTROOT "/usr/X11R6"
572 #endif
573 #ifndef XCONFENV
574 #define XCONFENV "XORGCONFIG"
575 #endif
576 #define XFREE86CFGFILE "XF86Config"
577 #ifndef XF86_VERSION_MAJOR
578 #ifdef XVERSION
579 #if XVERSION > 40000000
580 #define XF86_VERSION_MAJOR (XVERSION / 10000000)
581 #else
582 #define XF86_VERSION_MAJOR (XVERSION / 1000)
583 #endif
584 #else
585 #define XF86_VERSION_MAJOR 4
586 #endif
587 #endif
589 #define BAIL_OUT do { \
590 xf86conffree(result); \
591 return NULL; \
592 } while (0)
594 #define CHECK_LENGTH do { \
595 if (l > PATH_MAX) { \
596 BAIL_OUT; \
598 } while (0)
600 #define APPEND_STR(s) do { \
601 if (strlen(s) + l > PATH_MAX) { \
602 BAIL_OUT; \
603 } else { \
604 strcpy(result + l, s); \
605 l += strlen(s); \
607 } while (0)
609 static char *
610 DoSubstitution(const char *template, const char *cmdline, const char *projroot,
611 int *cmdlineUsed, int *envUsed, char *XConfigFile)
613 char *result;
614 int i, l;
615 static const char *env = NULL, *home = NULL;
616 static char *hostname = NULL;
617 static char majorvers[3] = "";
619 if (!template)
620 return NULL;
622 if (cmdlineUsed)
623 *cmdlineUsed = 0;
624 if (envUsed)
625 *envUsed = 0;
627 result = xf86confmalloc(PATH_MAX + 1);
628 l = 0;
629 for (i = 0; template[i]; i++) {
630 if (template[i] != '%') {
631 result[l++] = template[i];
632 CHECK_LENGTH;
633 } else {
634 switch (template[++i]) {
635 case 'A':
636 if (cmdline && xf86pathIsAbsolute(cmdline)) {
637 APPEND_STR(cmdline);
638 if (cmdlineUsed)
639 *cmdlineUsed = 1;
640 } else
641 BAIL_OUT;
642 break;
643 case 'R':
644 if (cmdline && !xf86pathIsAbsolute(cmdline)) {
645 APPEND_STR(cmdline);
646 if (cmdlineUsed)
647 *cmdlineUsed = 1;
648 } else
649 BAIL_OUT;
650 break;
651 case 'S':
652 if (cmdline && xf86pathIsSafe(cmdline)) {
653 APPEND_STR(cmdline);
654 if (cmdlineUsed)
655 *cmdlineUsed = 1;
656 } else
657 BAIL_OUT;
658 break;
659 case 'X':
660 APPEND_STR(XConfigFile);
661 break;
662 case 'H':
663 if (!hostname) {
664 if ((hostname = xf86confmalloc(MAXHOSTNAMELEN + 1))) {
665 if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
666 hostname[MAXHOSTNAMELEN] = '\0';
667 } else {
668 xf86conffree(hostname);
669 hostname = NULL;
673 if (hostname)
674 APPEND_STR(hostname);
675 break;
676 case 'E':
677 if (!env)
678 env = getenv(XCONFENV);
679 if (env && xf86pathIsAbsolute(env)) {
680 APPEND_STR(env);
681 if (envUsed)
682 *envUsed = 1;
683 } else
684 BAIL_OUT;
685 break;
686 case 'F':
687 if (!env)
688 env = getenv(XCONFENV);
689 if (env && !xf86pathIsAbsolute(env)) {
690 APPEND_STR(env);
691 if (envUsed)
692 *envUsed = 1;
693 } else
694 BAIL_OUT;
695 break;
696 case 'G':
697 if (!env)
698 env = getenv(XCONFENV);
699 if (env && xf86pathIsSafe(env)) {
700 APPEND_STR(env);
701 if (envUsed)
702 *envUsed = 1;
703 } else
704 BAIL_OUT;
705 break;
706 case 'D':
707 if (!home)
708 home = getenv("HOME");
709 if (home && xf86pathIsAbsolute(home))
710 APPEND_STR(home);
711 else
712 BAIL_OUT;
713 break;
714 case 'P':
715 if (projroot && xf86pathIsAbsolute(projroot))
716 APPEND_STR(projroot);
717 else
718 BAIL_OUT;
719 break;
720 case 'M':
721 if (!majorvers[0]) {
722 if (XF86_VERSION_MAJOR < 0 || XF86_VERSION_MAJOR > 99) {
723 fprintf(stderr, "XF86_VERSION_MAJOR is out of range\n");
724 BAIL_OUT;
725 } else
726 sprintf(majorvers, "%d", XF86_VERSION_MAJOR);
728 APPEND_STR(majorvers);
729 break;
730 case '%':
731 result[l++] = '%';
732 CHECK_LENGTH;
733 break;
734 default:
735 fprintf(stderr, "invalid escape %%%c found in path template\n",
736 template[i]);
737 BAIL_OUT;
738 break;
742 #ifdef DEBUG
743 fprintf(stderr, "Converted `%s' to `%s'\n", template, result);
744 #endif
745 return result;
749 * xf86openConfigFile --
751 * This function take a config file search path (optional), a command-line
752 * specified file name (optional) and the ProjectRoot path (optional) and
753 * locates and opens a config file based on that information. If a
754 * command-line file name is specified, then this function fails if none
755 * of the located files.
757 * The return value is a pointer to the actual name of the file that was
758 * opened. When no file is found, the return value is NULL.
760 * The escape sequences allowed in the search path are defined above.
764 #ifndef DEFAULT_CONF_PATH
765 #define DEFAULT_CONF_PATH "/etc/X11/%S," \
766 "%P/etc/X11/%S," \
767 "/etc/X11/%G," \
768 "%P/etc/X11/%G," \
769 "/etc/X11/%X-%M," \
770 "/etc/X11/%X," \
771 "/etc/%X," \
772 "%P/etc/X11/%X.%H," \
773 "%P/etc/X11/%X-%M," \
774 "%P/etc/X11/%X," \
775 "%P/lib/X11/%X.%H," \
776 "%P/lib/X11/%X-%M," \
777 "%P/lib/X11/%X"
778 #endif
780 const char *
781 xf86openConfigFile(const char *path, const char *cmdline, const char *projroot)
783 char *pathcopy;
784 const char *template;
785 int cmdlineUsed = 0;
787 configFile = NULL;
788 configPos = 0; /* current readers position */
789 configLineNo = 0; /* linenumber */
790 pushToken = LOCK_TOKEN;
792 if (!path || !path[0])
793 path = DEFAULT_CONF_PATH;
794 pathcopy = xf86confmalloc(strlen(path) + 1);
795 strcpy(pathcopy, path);
796 if (!projroot || !projroot[0])
797 projroot = PROJECTROOT;
799 template = strtok(pathcopy, ",");
801 /* First, search for a config file. */
802 while (template && !configFile) {
803 if ((configPath = DoSubstitution(template, cmdline, projroot,
804 &cmdlineUsed, NULL,
805 XCONFIGFILE))) {
806 if ((configFile = fopen(configPath, "r")) != 0) {
807 if (cmdline && !cmdlineUsed) {
808 fclose(configFile);
809 configFile = NULL;
813 if (configPath && !configFile) {
814 xf86conffree(configPath);
815 configPath = NULL;
817 template = strtok(NULL, ",");
820 /* Then search for fallback */
821 if (!configFile) {
822 strcpy(pathcopy, path);
823 template = strtok(pathcopy, ",");
825 while (template && !configFile) {
826 if ((configPath = DoSubstitution(template, cmdline, projroot,
827 &cmdlineUsed, NULL,
828 XFREE86CFGFILE))) {
829 if ((configFile = fopen(configPath, "r")) != 0) {
830 if (cmdline && !cmdlineUsed) {
831 fclose(configFile);
832 configFile = NULL;
836 if (configPath && !configFile) {
837 xf86conffree(configPath);
838 configPath = NULL;
840 template = strtok(NULL, ",");
844 xf86conffree(pathcopy);
845 if (!configFile) {
847 return NULL;
850 configBuf = xf86confmalloc (CONFIG_BUF_LEN);
851 configRBuf = xf86confmalloc (CONFIG_BUF_LEN);
852 configBuf[0] = '\0'; /* sanity ... */
854 return configPath;
857 void
858 xf86closeConfigFile (void)
860 xf86conffree (configPath);
861 configPath = NULL;
862 xf86conffree (configRBuf);
863 configRBuf = NULL;
864 xf86conffree (configBuf);
865 configBuf = NULL;
867 if (configFile) {
868 fclose (configFile);
869 configFile = NULL;
870 } else {
871 builtinConfig = NULL;
872 builtinIndex = 0;
876 void
877 xf86setBuiltinConfig(const char *config[])
879 builtinConfig = config;
880 configPath = xf86configStrdup("<builtin configuration>");
881 configBuf = xf86confmalloc (CONFIG_BUF_LEN);
882 configRBuf = xf86confmalloc (CONFIG_BUF_LEN);
883 configBuf[0] = '\0'; /* sanity ... */
887 void
888 xf86parseError (char *format,...)
890 va_list ap;
892 ErrorF ("Parse error on line %d of section %s in file %s\n\t",
893 configLineNo, configSection, configPath);
894 va_start (ap, format);
895 VErrorF (format, ap);
896 va_end (ap);
898 ErrorF ("\n");
901 void
902 xf86validationError (char *format,...)
904 va_list ap;
906 ErrorF ("Data incomplete in file %s\n\t", configPath);
907 va_start (ap, format);
908 VErrorF (format, ap);
909 va_end (ap);
911 ErrorF ("\n");
914 void
915 xf86setSection (char *section)
917 if (configSection)
918 xf86conffree(configSection);
919 configSection = xf86confmalloc(strlen (section) + 1);
920 strcpy (configSection, section);
924 * xf86getToken --
925 * Lookup a string if it is actually a token in disguise.
928 xf86getStringToken (xf86ConfigSymTabRec * tab)
930 return StringToToken (val.str, tab);
933 static int
934 StringToToken (char *str, xf86ConfigSymTabRec * tab)
936 int i;
938 for (i = 0; tab[i].token != -1; i++)
940 if (!xf86nameCompare (tab[i].name, str))
941 return tab[i].token;
943 return (ERROR_TOKEN);
948 * Compare two names. The characters '_', ' ', and '\t' are ignored
949 * in the comparison.
952 xf86nameCompare (const char *s1, const char *s2)
954 char c1, c2;
956 if (!s1 || *s1 == 0) {
957 if (!s2 || *s2 == 0)
958 return (0);
959 else
960 return (1);
963 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
964 s1++;
965 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
966 s2++;
967 c1 = (isupper (*s1) ? tolower (*s1) : *s1);
968 c2 = (isupper (*s2) ? tolower (*s2) : *s2);
969 while (c1 == c2)
971 if (c1 == '\0')
972 return (0);
973 s1++;
974 s2++;
975 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
976 s1++;
977 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
978 s2++;
979 c1 = (isupper (*s1) ? tolower (*s1) : *s1);
980 c2 = (isupper (*s2) ? tolower (*s2) : *s2);
982 return (c1 - c2);
985 char *
986 xf86addComment(char *cur, char *add)
988 char *str;
989 int len, curlen, iscomment, hasnewline = 0, endnewline;
991 if (add == NULL || add[0] == '\0')
992 return (cur);
994 if (cur) {
995 curlen = strlen(cur);
996 if (curlen)
997 hasnewline = cur[curlen - 1] == '\n';
998 eol_seen = 0;
1000 else
1001 curlen = 0;
1003 str = add;
1004 iscomment = 0;
1005 while (*str) {
1006 if (*str != ' ' && *str != '\t')
1007 break;
1008 ++str;
1010 iscomment = (*str == '#');
1012 len = strlen(add);
1013 endnewline = add[len - 1] == '\n';
1014 len += 1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
1016 if ((str = xf86confrealloc(cur, len + curlen)) == NULL)
1017 return (cur);
1019 cur = str;
1021 if (eol_seen || (curlen && !hasnewline))
1022 cur[curlen++] = '\n';
1023 if (!iscomment)
1024 cur[curlen++] = '#';
1025 strcpy(cur + curlen, add);
1026 if (!endnewline)
1027 strcat(cur, "\n");
1029 return (cur);