/*
*
* Copyright (c) 1997 Metro Link Incorporated
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Metro Link shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from Metro Link.
*
*/
/*
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#if !defined(X_NOT_POSIX)
#if defined(_POSIX_SOURCE)
#include <limits.h>
#else
#define _POSIX_SOURCE
#include <limits.h>
#endif /* _POSIX_SOURCE */
#endif /* !X_NOT_POSIX */
#if !defined(PATH_MAX)
#if defined(MAXPATHLEN)
#else
#endif /* MAXPATHLEN */
#endif /* !PATH_MAX */
#if !defined(MAXHOSTNAMELEN)
#endif /* !MAXHOSTNAMELEN */
#include "xf86Parser.h" /* Public function, etc. declarations */
#include "Configint.h"
#include "configProcs.h" /* Private function, etc. declarations */
#include "xf86tokens.h"
#if defined(SMI_FBCONFIG)
#include "fbc_error.h" /* Error reporting */
#include "fbc_line_er.h" /* External Representation of config lines */
#endif
#if !defined(xf86printErrorF) /* Could write prog name & variable fmt msg */
#endif
static int StringToToken (char *, xf86ConfigSymTabRec *);
static int builtinIndex = 0;
#if !defined(SMI_FBCONFIG)
#else
#endif
#ifdef __UNIXOS2__
extern char *__XOS2RedirRoot(char *path);
#endif
/*
* xf86strToUL --
*
* A portable, but restricted, version of strtoul(). It only understands
* hex, octal, and decimal. But it's good enough for our needs.
*/
unsigned int
{
char *p = str;
unsigned int tot = 0;
if (*p == '0')
{
p++;
if ((*p == 'x') || (*p == 'X'))
{
p++;
base = 16;
}
else
base = 8;
}
while (*p)
{
{
}
{
}
{
}
else
{
return (tot);
}
p++;
}
return (tot);
}
/*
* xf86getNextLine()
*
* Read from the configFile FILE stream until we encounter a newline;
* this is a wrapper for fgets(3) that can handle arbitrarily long
* input lines.
*
* Callers, such as xf86getToken(), assume that we will read up to the
* next newline; we need to grow configBuf as necessary to support that.
*/
char *
{
char *tmpConfigBuf;
/*
* Reallocate the buffer if it was grown last time (i.e., is no
* longer CONFIG_BUF_LEN); we malloc the new buffer first, so
* that if the malloc() fails, we can fall back to use the
* existing buffer.
*
* [Might want to wait and shrink the buffer after reading the line.]
*/
if (*configBufLen != CONFIG_BUF_LEN) {
if (tmpConfigBuf != NULL) {
/*
* The malloc() succeeded; free the old buffer and use
* the new buffer.
*/
}
}
/* read in another block of chars */
do {
break;
}
/* search for EOL in the new block of chars */
c = (*configBuf)[i];
if (c == '\0') break;
if ((c == '\n') || (c == '\r')) {
eolFound = 1;
break;
}
}
/*
* if we didn't find EOL, then grow the buffer and
* read in more
*/
if (!eolFound) {
if (tmpConfigBuf == NULL) {
/*
* The reallocation failed; we have to fall
* back to the previous configBufLen size and
* use the string we have, even though we don't
* have an EOL.
*/
break;
} else {
/* reallocation succeeded */
pos = i;
}
}
} while (!eolFound);
return (ret);
}
/*
* xf86getToken --
* Read next Token from the config file. Handle the global variable
* pushToken. If a pointer to a symbol table has been provided
* (tab != NULL), the table may be searched for a match with the
* token. If all attempts to recognize the token fail, an
* ERROR_TOKEN code is returned.
*/
int
{
int c, i;
char *tmpConfigRBuf;
/*
* First check whether pushToken has a different value than LOCK_TOKEN.
* Otherwise the next token must be read from the input.
*/
return (EOF_TOKEN);
else if (pushToken == LOCK_TOKEN)
{
/*
* eol_seen is only set for the first token after a newline.
*/
eol_seen = 0;
/*
* Get start of next Token. EOF is handled,
* whitespaces are skipped.
*/
if (!c)
{
char *ret;
if (configFile != NULL) {
#if defined(SMI_FBCONFIG)
#endif
#if defined(SMI_FBCONFIG)
}
#endif
} else {
else {
builtinIndex++;
}
}
{
}
configLineNo++;
configPos = 0;
eol_seen = 1;
}
/*
* Make the token buffer the same size as the input line
* buffer. We malloc() the new token buffer first, so
* that if the malloc() fails, we can fall back to use the
* existing token buffer.
*/
if (configRBufLen != configBufLen) {
if (tmpConfigRBuf != NULL) {
/*
* The malloc() succeeded; free the old buffer
* and use the new buffer.
*/
}
}
/*
* Start scanning the new token, which may include whitespace
*/
i = 0;
for (;;) {
configRBuf[i++] = c;
switch (c) {
case ' ':
case '\t':
case '\r':
continue;
case '\n':
i = 0;
continue;
}
break;
}
if (c == '\0')
goto again; /* [Should be a do-while loop] */
if (c == '#')
{
do
{
}
while ((c != '\n') && (c != '\r') && (c != '\0'));
configRBuf[i] = '\0';
/* XXX no private copy.
* Use xf86addComment when setting a comment.
*/
return (COMMENT);
}
/* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */
{
return COMMA;
}
{
return DASH;
}
/*
* Numbers are returned immediately ...
*/
if (isdigit (c))
{
int base;
if (c == '0')
base = 16;
else
base = 8;
else
base = 10;
configRBuf[0] = c;
i = 1;
(c == '.') || (c == 'x') || (c == 'X') ||
((c >= 'A') && (c <= 'F')))))
configRBuf[i++] = c;
configPos--; /* GJA -- one too far */
configRBuf[i] = '\0';
return (NUMBER);
}
/*
* All Strings START with a \" ...
*/
else if (c == '\"')
{
i = -1;
do
{
}
while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
configRBuf[i] = '\0';
return (STRING);
}
/*
* ... and now we MUST have a valid token. The search is
* handled later along with the pushed tokens.
*/
else
{
configRBuf[0] = c;
i = 0;
do
{
}
while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#'));
--configPos;
configRBuf[i] = '\0';
i = 0;
}
}
else
{
/*
* Here we deal with pushed tokens. Reinitialize pushToken again. If
* the pushed token was NUMBER || STRING return them again ...
*/
return (temp);
return (temp);
}
/*
* Joop, at last we have to lookup the token ...
*/
if (tab)
{
i = 0;
else
i++;
}
return (ERROR_TOKEN); /* Error catcher */
}
/*
* xf86getSubToken()
*
* Read tokens from the configuration file until a non-COMMENT
* token is encountered. No symbol table is provided for token
* lookup. Unless no comment pointer is provided by the caller,
* append any COMMENT text to the dynamically grown string of
* comments. Return the code for the non-COMMENT token.
*/
int
{
int token;
for (;;) {
if (comment)
}
else
return (token);
}
/*NOTREACHED*/
}
/*
* xf86getSubTokenWithTab()
*
* Read tokens from the configuration file until a non-COMMENT
* token is encountered. A symbol table is provided for token
* lookup. Unless no comment pointer is provided by the caller,
* append any COMMENT text to the dynamically grown string of
* comments. Return the code for the non-COMMENT token.
*/
int
{
int token;
for (;;) {
if (comment)
}
else
return (token);
}
/*NOTREACHED*/
}
void
{
}
char *
xf86tokenString (void)
{
return configRBuf;
}
int
{
return 1;
#ifdef __UNIXOS2__
return 1;
#endif
return 0;
}
/* A path is "safe" if it is relative and if it contains no ".." elements. */
int
{
if (xf86pathIsAbsolute(path))
return 0;
/* Compare with ".." */
return 0;
/* Look for leading "../" */
return 0;
/* Look for trailing "/.." */
return 0;
/* Look for "/../" */
return 0;
return 1;
}
/*
* This function substitutes the following escape sequences:
*
* %A cmdline argument as an absolute path (must be absolute to match)
* %R cmdline argument as a relative path
* %S cmdline argument as a "safe" path (relative, and no ".." elements)
* %X default config file name ("xorg.conf")
* %H hostname
* %E config file environment ($XORGCONFIG) as an absolute path
* %F config file environment ($XORGCONFIG) as a relative path
* %G config file environment ($XORGCONFIG) as a safe path
* %D $HOME
* %P projroot
* %M major version number
* %% %
* %& UNIXOS2 only: prepend X11ROOT env var
*/
#ifndef XCONFIGFILE
#endif
#ifndef PROJECTROOT
#endif
#ifndef XCONFENV
#endif
#ifndef XF86_VERSION_MAJOR
#ifdef XVERSION
#if XVERSION > 40000000
#else
#endif
#else
#endif
#endif
#define BAIL_OUT do { \
xf86conffree(result); \
return NULL; \
} while (0)
#define CHECK_LENGTH do { \
if (l > PATH_MAX) { \
BAIL_OUT; \
} \
} while (0)
#define APPEND_STR(s) do { \
BAIL_OUT; \
} else { \
l += strlen(s); \
} \
} while (0)
static char *
{
char *result;
int i, l;
#ifdef __UNIXOS2__
#endif
if (!template)
return NULL;
if (cmdlineUsed)
*cmdlineUsed = 0;
if (envUsed)
*envUsed = 0;
l = 0;
for (i = 0; template[i]; i++) {
if (template[i] != '%') {
} else {
switch (template[++i]) {
case 'A':
if (cmdlineUsed)
*cmdlineUsed = 1;
} else
break;
case 'R':
if (cmdlineUsed)
*cmdlineUsed = 1;
} else
break;
case 'S':
if (cmdlineUsed)
*cmdlineUsed = 1;
} else
break;
case 'X':
break;
case 'H':
if (!hostname) {
} else {
}
}
}
if (hostname)
break;
case 'E':
if (!env)
if (envUsed)
*envUsed = 1;
} else
break;
case 'F':
if (!env)
if (envUsed)
*envUsed = 1;
} else
break;
case 'G':
if (!env)
if (envUsed)
*envUsed = 1;
} else
break;
case 'D':
if (!home)
else
break;
case 'P':
else
break;
case 'M':
if (!majorvers[0]) {
} else
}
break;
case '%':
result[l++] = '%';
break;
#ifdef __UNIXOS2__
case '&':
if (!x11root)
if (x11root)
else
break;
#endif
default:
template[i]);
break;
}
}
}
#ifdef DEBUG
#endif
result[l] = '\0';
return result;
}
/*
* xf86openConfigFileIn()
*
* This function takes a config file search path (optional), a command-line
* specified file name (optional) and the ProjectRoot path (optional) and
* locates and opens a config file based on that information. This
* function will fail if a command-line file name is specified and there
* is no %A, %R, or %S escape sequence in the effective search path.
*
* The return value is a pointer to the actual name of the file that was
* opened. When no file is found, the return value is NULL.
*
* The escape sequences allowed in the search path are defined above. The
* default search path is defined below.
*/
#ifndef DEFAULT_CONF_PATH
"/etc/%X," \
#endif
#if !defined(SMI_FBCONFIG)
static
#endif
const char *
const char *path, /* Search path, else NULL */
const char *cmdline, /* File path (%A,%R,%S), else NULL */
const char *projroot) /* Project root path (%P), else NULL */
{
const char *const Xfile[] = {
}; /* Substitutions for %X */
char *pathcopy;
const char *template;
int cmdlineUsed = 0;
/* Initialize global variables for the scanner */
configLineNo = 0; /* Config file current line number */
configPos = 0; /* Index of current char in line buf */
}
/* Be sure there's a non-empty search path and a scratch buffer */
}
return (NULL);
}
/* Be sure there's a non-empty project root to substitute for %P */
}
/* Repeat for each config filename that can be substituted for %X */
/* Repeat for each comma-separated pathname template */
/* Construct a config pathname from the template */
&cmdlineUsed, NULL,
*XConfigFile);
if (configPath == NULL) {
continue; /* No memory */
}
/* Open the path unless a provided name wasn't used */
if (configFile != NULL) {
break; /* Success */
}
}
/* Discard the failed config pathname */
configPath = NULL;
}
if (configFile != NULL) {
break; /* Success */
}
}
return (configPath);
}
/*
* xf86openConfigFile()
*
* This function takes a config file search path (optional), a command-line
* specified file name (optional) and the ProjectRoot path (optional) and
* locates and opens a config file based on that information. This
* function will fail if a command-line file name is specified and there
* is no %A, %R, or %S escape sequence in the effective search path.
*
* The return value is a pointer to the actual name of the file that was
* opened. When no file is found, the return value is NULL.
*
* The escape sequences allowed in the search path are defined above.
*/
const char *
{
return (NULL);
}
return (configPath);
}
/*
* xf86confScanFree()
*
* Release all dynamically allocated memory used to scan the
* configuration file.
*/
void
xf86confScanFree(void)
{
configPath = NULL;
configRBuf = NULL;
}
/*
* xf86closeConfigFile()
*
* Release all dynamically allocated memory used to scan the
* configuration file. Close the input configuration file, else
* discard the in-memory configuration text.
*/
void
xf86closeConfigFile (void)
{
if (configFile != NULL) {
configFile = NULL;
} else {
builtinIndex = 0;
}
}
void
{
}
void
{
xf86printErrorF("Parse error on line %d of section %s in file %s\n\t",
ErrorF ("\n");
}
void
{
xf86printErrorF("Parse warning on line %d of section %s in file %s\n\t",
ErrorF ("\n");
}
void
{
ErrorF ("\n");
}
void
{
if (configSection)
}
/*
* xf86getToken --
* Lookup a string if it is actually a token in disguise.
*/
int
{
}
static int
{
int i;
{
}
return (ERROR_TOKEN);
}
/*
* xf86nameCompareResumable()
*
* Compare two name-like strings pointed to by s1 and s2. Ignore
* alphabetic case and the characters, '_', ' ', and '\t'. If s2
* matches the initial characters of s1 then return a pointer to the
* next character of s1 via s1resume (where further comparison could
* be resumed). Otherwise return NULL via s1resume. Return the
* conventional negative, zero, or positive value to indicate the
* result of the basic comparison.
*/
static int
{
return (0);
}
return (-1); /* Behave as if NULL < non-NULL */
}
return (1); /* Behave as if non-NULL > NULL */
}
do {
s1 += 1;
}
s2 += 1;
}
if (*s2 == '\0') {
/* s1 matches s2 or contains s2 as a prefix */
return (0);
}
s1++;
s2++;
}
/*
* The strings don't match
*/
}
/*
* xf86nameCompare()
*
* Compare two name-like strings pointed to by s1 and s2. Ignore
* alphabetic case and the characters, '_', ' ', and '\t'. Return
* the conventional negative, zero, or positive value to indicate the
* result of the comparison.
*/
int
{
/*
* Compare the name strings, s1 and s2
*/
if (result == 0) {
/*
* Determine whether s2 matches all of or just part of s1
*
* Note that s1resume will not be NULL if result is
* zero.
*/
}
/*
* Return the final result of the comparison
*/
return (result);
}
/*
* xf86lookupBoolOption()
*
* Look up an option name in an array of known Boolean option names.
* Note that a Boolean option name can have a "No" prefix. If found,
* return the array subscript of the Boolean option name. Otherwise
* return -1.
*/
static int
const char *const bool_option_names[], const char *opt_name)
{
int i; /* Index into option name array */
/*
* Look up the option name, which can be negated using a "No" prefix
*/
/*
* See whether this is a plain instance of the option name
*/
return (i); /* Have a match */
}
/*
* See whether this is a negated instance of the option name
*/
}
return (i); /* Have a match */
}
}
/*
* Not the name of a known Boolean option
*/
return (-1);
}
/*
* xf86optionNameCompare()
*
* Compare two option names pointed to by s1 and s2. Ignore
* alphabetic case and the characters, '_', ' ', and '\t'. For names
* of known Boolean options (provided via bool_option_names[]), any
* "No" prefix is ignored. Return the usual negative, zero, or
* positive values to indicate the results of the comparison.
*
* To see why we want a list of known Boolean option names, consider
* these ponderables:
* * Can we tell from this hypothetical example whether "Tables"
* is the name of a Boolean option, which could be negated?
* Option "Tables" 1
* * Can we tell whether "Notables" is the opposite of "Tables"?
* * Is the opposite of the documented Boolean option,
* "NoTrapSignals", intended to be "NoNoTrapSignals" or
* "TrapSignals"? Ditto for "NoPM" and "NoInt10".
*/
int
{
int i; /* Index of option name, else -1 */
return (0); /* Known Boolean option names match */
}
}
char *
{
char *str;
return (cur);
if (cur) {
if (curlen)
eol_seen = 0;
}
else
curlen = 0;
iscomment = 0;
while (*str) {
break;
++str;
}
return (cur);
if (!iscomment)
if (!endnewline)
return (cur);
}