*
* 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,
* and/or sell copies of the Software, and to permit persons to whom the
* 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,
* and/or sell copies of the Software, and to permit persons to whom the
* 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).
*/
#include "xf86Parser.h"
#include "xf86tokens.h"
#include "Configint.h"
extern LexRec val;
static XConfigSymTabRec TopLevelTab[] =
{
{SECTION, "section"},
{-1, ""},
};
#define CLEANUP xconfigFreeConfig
#define READ_HANDLE_RETURN(f,func) \
if ((ptr->f=func) == NULL) { \
xconfigFreeConfig(&ptr); \
return XCONFIG_RETURN_PARSE_ERROR; \
}
#define READ_HANDLE_LIST(field,func,type) \
{ \
type p = func(); \
if (p == NULL) { \
xconfigFreeConfig(&ptr); \
return XCONFIG_RETURN_PARSE_ERROR; \
} else { \
xconfigAddListItem((GenericListPtr *)(&ptr->field), \
(GenericListPtr) p); \
} \
}
#define READ_ERROR(a,b) \
do { \
xconfigErrorMsg(ParseErrorMsg, a, b); \
xconfigFreeConfig(&ptr); \
return XCONFIG_RETURN_PARSE_ERROR; \
} while (0)
* xconfigReadConfigFile() - read the open XConfig file, returning the
* parsed data as XConfigPtr.
*/
XConfigError xconfigReadConfigFile(XConfigPtr *configPtr)
{
int token;
XConfigPtr ptr = NULL;
*configPtr = NULL;
ptr = xconfigAlloc(sizeof(XConfigRec));
while ((token = xconfigGetToken(TopLevelTab)) != EOF_TOKEN) {
switch (token) {
case COMMENT:
ptr->comment = xconfigAddComment(ptr->comment, val.str);
break;
case SECTION:
if (xconfigGetSubToken(&(ptr->comment)) != STRING) {
xconfigErrorMsg(ParseErrorMsg, QUOTE_MSG, "Section");
xconfigFreeConfig(&ptr);
return XCONFIG_RETURN_PARSE_ERROR;
}
xconfigSetSection(val.str);
if (xconfigNameCompare(val.str, "files") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_RETURN(files, xconfigParseFilesSection());
}
else if (xconfigNameCompare(val.str, "serverflags") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_RETURN(flags, xconfigParseFlagsSection());
}
else if (xconfigNameCompare(val.str, "keyboard") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(inputs, xconfigParseKeyboardSection,
XConfigInputPtr);
}
else if (xconfigNameCompare(val.str, "pointer") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(inputs, xconfigParsePointerSection,
XConfigInputPtr);
}
else if (xconfigNameCompare(val.str, "videoadaptor") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(videoadaptors,
xconfigParseVideoAdaptorSection,
XConfigVideoAdaptorPtr);
}
else if (xconfigNameCompare(val.str, "device") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(devices, xconfigParseDeviceSection,
XConfigDevicePtr);
}
else if (xconfigNameCompare(val.str, "monitor") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(monitors, xconfigParseMonitorSection,
XConfigMonitorPtr);
}
else if (xconfigNameCompare(val.str, "modes") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(modes, xconfigParseModesSection,
XConfigModesPtr);
}
else if (xconfigNameCompare(val.str, "screen") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(screens, xconfigParseScreenSection,
XConfigScreenPtr);
}
else if (xconfigNameCompare(val.str, "inputdevice") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(inputs, xconfigParseInputSection,
XConfigInputPtr);
}
else if ((xconfigNameCompare(val.str, "inputclass") == 0))
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(inputclasses, xconfigParseInputClassSection,
XConfigInputClassPtr);
}
else if (xconfigNameCompare(val.str, "module") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_RETURN(modules, xconfigParseModuleSection());
}
else if (xconfigNameCompare(val.str, "serverlayout") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(layouts, xconfigParseLayoutSection,
XConfigLayoutPtr);
}
else if (xconfigNameCompare(val.str, "vendor") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_LIST(vendors, xconfigParseVendorSection,
XConfigVendorPtr);
}
else if (xconfigNameCompare(val.str, "dri") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_RETURN(dri, xconfigParseDRISection());
}
else if (xconfigNameCompare (val.str, "extensions") == 0)
{
free(val.str);
val.str = NULL;
READ_HANDLE_RETURN(extensions, xconfigParseExtensionsSection());
}
else
{
READ_ERROR(INVALID_SECTION_MSG, xconfigTokenString());
free(val.str);
val.str = NULL;
}
break;
default:
READ_ERROR(INVALID_KEYWORD_MSG, xconfigTokenString());
free(val.str);
val.str = NULL;
}
}
if (xconfigValidateConfig(ptr)) {
ptr->filename = strdup(xconfigGetConfigFileName());
*configPtr = ptr;
return XCONFIG_RETURN_SUCCESS;
} else {
xconfigFreeConfig(&ptr);
return XCONFIG_RETURN_VALIDATION_ERROR;
}
}
#undef CLEANUP
* This function resolves name references and reports errors if the named
* objects cannot be found.
*/
int xconfigValidateConfig(XConfigPtr p)
{
if (!xconfigValidateDevice(p))
return FALSE;
if (!xconfigValidateScreen(p))
return FALSE;
if (!xconfigValidateInput(p))
return FALSE;
if (!xconfigValidateLayout(p))
return FALSE;
return(TRUE);
}
* This function fixes up any problems that it finds in the config,
* when possible.
*/
int xconfigSanitizeConfig(XConfigPtr p,
const char *screenName,
GenerateOptions *gop)
{
if (!xconfigSanitizeScreen(p))
return FALSE;
if (!xconfigSanitizeLayout(p, screenName, gop))
return FALSE;
return TRUE;
}
* adds an item to the end of the linked list. Any record whose first field
* is a GenericListRec can be cast to this type and used with this function.
*/
void xconfigAddListItem (GenericListPtr *pHead, GenericListPtr new)
{
GenericListPtr p = *pHead;
GenericListPtr last = NULL;
while (p) {
last = p;
p = p->next;
}
if (last) {
last->next = new;
} else {
*pHead = new;
}
}
* removes an item from the linked list (but does not delete it). Any record
* whose first field is a GenericListRec can be cast to this type and used
* with this function.
*/
void xconfigRemoveListItem (GenericListPtr *pHead, GenericListPtr item)
{
GenericListPtr cur = *pHead;
GenericListPtr prev = NULL;
while (cur) {
if (cur == item) {
if (prev) {
prev->next = item->next;
} else {
*pHead = item->next;
}
return;
}
prev = cur;
cur = cur->next;
}
}
* Test if one chained list contains the other.
* In this case both list have the same endpoint (provided they don't loop)
*/
int
xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2)
{
GenericListPtr p = list_1;
GenericListPtr last_1 = NULL, last_2 = NULL;
while (p) {
last_1 = p;
p = p->next;
}
p = list_2;
while (p) {
last_2 = p;
p = p->next;
}
return (!(last_1 == last_2));
}
void
xconfigFreeConfig (XConfigPtr *p)
{
if (p == NULL || *p == NULL)
return;
xconfigFreeFiles (&((*p)->files));
xconfigFreeModules (&((*p)->modules));
xconfigFreeFlags (&((*p)->flags));
xconfigFreeMonitorList (&((*p)->monitors));
xconfigFreeModesList (&((*p)->modes));
xconfigFreeVideoAdaptorList (&((*p)->videoadaptors));
xconfigFreeDeviceList (&((*p)->devices));
xconfigFreeScreenList (&((*p)->screens));
xconfigFreeLayoutList (&((*p)->layouts));
xconfigFreeInputList (&((*p)->inputs));
xconfigFreeVendorList (&((*p)->vendors));
xconfigFreeDRI (&((*p)->dri));
TEST_FREE((*p)->comment);
free (*p);
*p = NULL;
}