/* * * 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; }