skamonkey@3513: /**
skamonkey@3513: * vim: set ts=4 :
skamonkey@3513: * =============================================================================
skamonkey@3513: * SourceMod
skamonkey@3513: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
skamonkey@3513: * =============================================================================
skamonkey@3513: *
skamonkey@3513: * This program is free software; you can redistribute it and/or modify it under
skamonkey@3513: * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3513: * Free Software Foundation.
skamonkey@3513: *
skamonkey@3513: * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3513: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3513: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
skamonkey@3513: * details.
skamonkey@3513: *
skamonkey@3513: * You should have received a copy of the GNU General Public License along with
skamonkey@3513: * this program. If not, see .
skamonkey@3513: *
skamonkey@3513: * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3513: * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3513: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3513: * by the Valve Corporation. You must obey the GNU General Public License in
skamonkey@3513: * all respects for all other code used. Additionally, AlliedModders LLC grants
skamonkey@3513: * this exception to all derivative works. AlliedModders LLC defines further
skamonkey@3513: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3513: * or .
skamonkey@3513: *
skamonkey@3513: * Version: $Id$
skamonkey@3513: */
skamonkey@3513:
skamonkey@3513: #include
skamonkey@3513: #include
skamonkey@3513: #include "GameConfigs.h"
skamonkey@3513:
skamonkey@3513: #define PSTATE_NONE 0
skamonkey@3513: #define PSTATE_GAMES 1
skamonkey@3513: #define PSTATE_GAMEDEFS 2
skamonkey@3513: #define PSTATE_GAMEDEFS_OFFSETS 3
skamonkey@3513: #define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
skamonkey@3513: #define PSTATE_GAMEDEFS_KEYS 5
skamonkey@3513: #define PSTATE_GAMEDEFS_SUPPORTED 6
skamonkey@3513: #define PSTATE_GAMEDEFS_SIGNATURES 7
skamonkey@3513: #define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
skamonkey@3513: #define PSTATE_GAMEDEFS_CRC 9
skamonkey@3513: #define PSTATE_GAMEDEFS_CRC_BINARY 10
skamonkey@3513: #define PSTATE_GAMEDEFS_CUSTOM 11
skamonkey@3574: #define PSTATE_GAMEDEFS_OPTIONS 12
skamonkey@3513:
skamonkey@3513: #define WIN 0
skamonkey@3513: #define LIN 1
skamonkey@3513:
skamonkey@3513: #define PLATFORM_NAME "linux"
skamonkey@3513: #define PLATFORM_SERVER_BINARY "server_i486.so"
skamonkey@3513:
skamonkey@3513: Offset *tempOffset;
skamonkey@3513: Sig *tempSig;
skamonkey@3513:
skamonkey@3513: unsigned int s_ServerBinCRC;
skamonkey@3513: bool s_ServerBinCRC_Ok = false;
skamonkey@3513:
skamonkey@3513: bool DoesGameMatch(const char *value)
skamonkey@3513: {
skamonkey@3513: if (strcmp(value, game) == 0)
skamonkey@3513: {
skamonkey@3513: return true;
skamonkey@3513: }
skamonkey@3513: return false;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: bool DoesEngineMatch(const char *value)
skamonkey@3513: {
skamonkey@3513: if (strcmp(value, engine) == 0)
skamonkey@3513: {
skamonkey@3513: return true;
skamonkey@3513: }
skamonkey@3513: return false;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: CGameConfig::CGameConfig()
skamonkey@3513: {
skamonkey@3513: m_pStrings = new BaseStringTable(512);
skamonkey@3513: m_RefCount = 0;
skamonkey@3513:
skamonkey@3513: m_CustomLevel = 0;
skamonkey@3513: m_CustomHandler = NULL;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: CGameConfig::~CGameConfig()
skamonkey@3513: {
skamonkey@3513: delete m_pStrings;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
skamonkey@3513: {
skamonkey@3513: if (m_IgnoreLevel)
skamonkey@3513: {
skamonkey@3513: m_IgnoreLevel++;
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: switch (m_ParseState)
skamonkey@3513: {
skamonkey@3513: case PSTATE_NONE:
skamonkey@3513: {
skamonkey@3513: if (strcmp(name, "Games") == 0)
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMES;
skamonkey@3513: } else {
skamonkey@3513: m_IgnoreLevel++;
skamonkey@3513: }
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMES:
skamonkey@3513: {
skamonkey@3513: if (strcmp(name, "*") == 0 ||
skamonkey@3513: strcmp(name, "#default") == 0 ||
skamonkey@3513: DoesGameMatch(name))
skamonkey@3513: {
skamonkey@3513: bShouldBeReadingDefault = true;
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513: strncopy(m_Game, name, sizeof(m_Game));
skamonkey@3513: } else {
skamonkey@3513: m_IgnoreLevel++;
skamonkey@3513: }
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS:
skamonkey@3513: {
skamonkey@3513: if (strcmp(name, "Offsets") == 0)
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
skamonkey@3513: }
skamonkey@3513: else if (strcmp(name, "Keys") == 0)
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_KEYS;
skamonkey@3513: }
skamonkey@3574: else if (strcmp(name, "Options") == 0)
skamonkey@3574: {
skamonkey@3574: m_ParseState = PSTATE_GAMEDEFS_OPTIONS;
skamonkey@3574: }
skamonkey@3513: else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0))
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
skamonkey@3513: /* Ignore this section unless we get a game. */
skamonkey@3513: bShouldBeReadingDefault = false;
skamonkey@3513: had_game = false;
skamonkey@3513: matched_game = false;
skamonkey@3513: had_engine = false;
skamonkey@3513: matched_engine = false;
skamonkey@3513: }
skamonkey@3513: else if (strcmp(name, "Signatures") == 0)
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
skamonkey@3513: }
skamonkey@3694: else
skamonkey@3694: {
skamonkey@3694: m_IgnoreLevel++;
skamonkey@3694: }
skamonkey@3513:
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_OFFSETS:
skamonkey@3513: {
skamonkey@3513: m_Prop[0] = '\0';
skamonkey@3513: m_Class[0] = '\0';
skamonkey@3513: tempOffset = new Offset();
skamonkey@3513: tempOffset->setName(name);
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_SIGNATURES:
skamonkey@3513: {
skamonkey@3513: tempSig = new Sig();
skamonkey@3513: tempSig->setName(name);
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: /* No sub-sections allowed:
skamonkey@3513: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
skamonkey@3513: case PSTATE_GAMEDEFS_KEYS:
skamonkey@3513: case PSTATE_GAMEDEFS_SUPPORTED:
skamonkey@3513: case PSTATE_GAMEDEFS_SIGNATURES_SIG:
skamonkey@3513: case PSTATE_GAMEDEFS_CRC_BINARY:
skamonkey@3513: */
skamonkey@3513: default:
skamonkey@3513: {
skamonkey@3513: /* If we don't know what we got, start ignoring */
skamonkey@3513: m_IgnoreLevel++;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
skamonkey@3513: {
skamonkey@3513: if (m_IgnoreLevel)
skamonkey@3513: {
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: if (m_ParseState == PSTATE_GAMEDEFS_OFFSETS_OFFSET)
skamonkey@3513: {
skamonkey@3513: if (strcmp(key, "class") == 0)
skamonkey@3513: {
skamonkey@3513: strncopy(m_Class, value, sizeof(m_Class));
skamonkey@3513: } else if (strcmp(key, "prop") == 0) {
skamonkey@3513: strncopy(m_Prop, value, sizeof(m_Prop));
skamonkey@3513: } else {
skamonkey@3513: int val = atoi(value);
skamonkey@3513: if (strcmp(key, "windows") == 0) tempOffset->setWin(val);
skamonkey@3513: else if (strcmp(key, "linux") == 0) tempOffset->setLin(val);
skamonkey@3513: }
skamonkey@3513: } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
skamonkey@3513: m_Keys.replace(key, m_pStrings->AddString(value));
skamonkey@3574: } else if (m_ParseState == PSTATE_GAMEDEFS_OPTIONS) {
skamonkey@3574: m_Options.replace(key, m_pStrings->AddString(value));
skamonkey@3513: } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
skamonkey@3513: if (strcmp(key, "game") == 0)
skamonkey@3513: {
skamonkey@3513: had_game = true;
skamonkey@3513: if (DoesGameMatch(value))
skamonkey@3513: {
skamonkey@3513: matched_game = true;
skamonkey@3513: }
skamonkey@3513: if ((!had_engine && matched_game) || (matched_engine && matched_game))
skamonkey@3513: {
skamonkey@3513: bShouldBeReadingDefault = true;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: else if (strcmp(key, "engine") == 0)
skamonkey@3513: {
skamonkey@3513: had_engine = true;
skamonkey@3513: if (DoesEngineMatch(value))
skamonkey@3513: {
skamonkey@3513: matched_engine = true;
skamonkey@3513: }
skamonkey@3513: if ((!had_game && matched_engine) || (matched_game && matched_engine))
skamonkey@3513: {
skamonkey@3513: bShouldBeReadingDefault = true;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: } else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
skamonkey@3513: if (strcmp(key, "windows") == 0) tempSig->setWin(value);
skamonkey@3513: else if (strcmp(key, "linux") == 0) tempSig->setLin(value);
skamonkey@3513: else if (strcmp(key, "library") == 0) tempSig->setLib(value);
skamonkey@3513: } else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
skamonkey@3513: if (strcmp(key, PLATFORM_NAME) == 0
skamonkey@3513: && s_ServerBinCRC_Ok
skamonkey@3513: && !bShouldBeReadingDefault)
skamonkey@3513: {
skamonkey@3513: unsigned int crc = 0;
skamonkey@3513: sscanf(value, "%08X", &crc);
skamonkey@3513: if (s_ServerBinCRC == crc)
skamonkey@3513: {
skamonkey@3513: bShouldBeReadingDefault = true;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: } else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
skamonkey@3513: return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
skamonkey@3513: {
skamonkey@3513: if (m_IgnoreLevel)
skamonkey@3513: {
skamonkey@3513: m_IgnoreLevel--;
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: if (m_CustomLevel)
skamonkey@3513: {
skamonkey@3513: m_CustomLevel--;
skamonkey@3513: m_CustomHandler->ReadSMC_LeavingSection(states);
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: switch (m_ParseState)
skamonkey@3513: {
skamonkey@3513: case PSTATE_GAMES:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_NONE;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMES;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_CUSTOM:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513: m_CustomHandler->ReadSMC_ParseEnd(false, false);
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_KEYS:
skamonkey@3513: case PSTATE_GAMEDEFS_OFFSETS:
skamonkey@3574: case PSTATE_GAMEDEFS_OPTIONS:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
skamonkey@3513: {
skamonkey@3513: for (list::iterator it = m_Offsets.begin(); it != m_Offsets.end(); it++)
skamonkey@3513: {
skamonkey@3513: if (strcmp(it->name, tempOffset->name) == 0)
skamonkey@3513: {
skamonkey@3513: m_Offsets.erase(it);
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: m_Offsets.push_back(*tempOffset);
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_CRC:
skamonkey@3513: case PSTATE_GAMEDEFS_SUPPORTED:
skamonkey@3513: {
skamonkey@3513: if (!bShouldBeReadingDefault)
skamonkey@3513: {
skamonkey@3513: /* If we shouldn't read the rest of this section, set the ignore level. */
skamonkey@3513: m_IgnoreLevel = 1;
skamonkey@3513: m_ParseState = PSTATE_GAMES;
skamonkey@3513: } else {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513: }
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_CRC_BINARY:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_CRC;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_SIGNATURES:
skamonkey@3513: {
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: case PSTATE_GAMEDEFS_SIGNATURES_SIG:
skamonkey@3513: {
skamonkey@3513: m_Sigs.push_back(*tempSig);
skamonkey@3513: m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
skamonkey@3513:
skamonkey@3513: break;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: #define MSTATE_NONE 0
skamonkey@3513: #define MSTATE_MAIN 1
skamonkey@3513: #define MSTATE_FILE 2
skamonkey@3513:
skamonkey@3513: class MasterReader : public ITextListener_SMC
skamonkey@3513: {
skamonkey@3513: public:
skamonkey@3513: virtual void ReadSMC_ParseStart()
skamonkey@3513: {
skamonkey@3513: state = MSTATE_NONE;
skamonkey@3513: ignoreLevel = 0;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: virtual SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
skamonkey@3513: {
skamonkey@3513: if (ignoreLevel)
skamonkey@3513: {
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: if (state == MSTATE_NONE)
skamonkey@3513: {
skamonkey@3513: if (strcmp(name, "Game Master") == 0)
skamonkey@3513: {
skamonkey@3513: state = MSTATE_MAIN;
skamonkey@3513: }
skamonkey@3513: else
skamonkey@3513: {
skamonkey@3513: ignoreLevel++;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: else if (state == MSTATE_MAIN)
skamonkey@3513: {
skamonkey@3513: strncopy(cur_file, name, sizeof(cur_file));
skamonkey@3513: had_engine = false;
skamonkey@3513: matched_engine = false;
skamonkey@3513: had_game = false;
skamonkey@3513: matched_game = false;
skamonkey@3513: state = MSTATE_FILE;
skamonkey@3513: }
skamonkey@3513: else if (state == MSTATE_FILE)
skamonkey@3513: {
skamonkey@3513: ignoreLevel++;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: virtual SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
skamonkey@3513: {
skamonkey@3513: if (ignoreLevel || state != MSTATE_FILE)
skamonkey@3513: {
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: if (strcmp(key, "engine") == 0)
skamonkey@3513: {
skamonkey@3513: had_engine = true;
skamonkey@3513: if (DoesEngineMatch(value))
skamonkey@3513: {
skamonkey@3513: matched_engine = true;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513: else if (strcmp(key, "game") == 0)
skamonkey@3513: {
skamonkey@3513: had_game = true;
skamonkey@3513: if (DoesGameMatch(value))
skamonkey@3513: {
skamonkey@3513: matched_game = true;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: virtual SMCResult ReadSMC_LeavingSection(const SMCStates *states)
skamonkey@3513: {
skamonkey@3513: if (ignoreLevel)
skamonkey@3513: {
skamonkey@3513: ignoreLevel--;
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: if (state == MSTATE_FILE)
skamonkey@3513: {
skamonkey@3513: /* The four success conditions:
skamonkey@3513: * 1. Needed nothing.
skamonkey@3513: * 2. Needed game only.
skamonkey@3513: * 3. Needed engine only.
skamonkey@3513: * 4. Needed both engine and game.
skamonkey@3513: * Final result is minimized via k-map.
skamonkey@3513: */
skamonkey@3513:
skamonkey@3513: if ((!had_engine && !had_game) ||
skamonkey@3513: (!had_engine && matched_game) ||
skamonkey@3513: (!had_game && matched_engine) ||
skamonkey@3513: (matched_engine && matched_game))
skamonkey@3513: {
skamonkey@3513: fileList->push_back(cur_file);
skamonkey@3513: }
skamonkey@3513: state = MSTATE_MAIN;
skamonkey@3513: }
skamonkey@3513: else if (state == MSTATE_MAIN)
skamonkey@3513: {
skamonkey@3513: state = MSTATE_NONE;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return SMCResult_Continue;
skamonkey@3513: }
skamonkey@3513: public:
skamonkey@3513: list *fileList;
skamonkey@3513: unsigned int state;
skamonkey@3513: unsigned int ignoreLevel;
skamonkey@3513: char cur_file[PLATFORM_MAX_PATH];
skamonkey@3513: bool had_engine;
skamonkey@3513: bool matched_engine;
skamonkey@3513: bool had_game;
skamonkey@3513: bool matched_game;
skamonkey@3513: };
skamonkey@3513:
skamonkey@3513: static MasterReader master_reader;
skamonkey@3513:
skamonkey@3513: bool CGameConfig::Reparse(char *error, size_t maxlength)
skamonkey@3513: {
skamonkey@3513: /* Reset cached data */
skamonkey@3513: m_pStrings->Reset();
skamonkey@3513: m_Offsets.clear();
skamonkey@3513: m_Sigs.clear();
skamonkey@3513: m_Keys.clear();
skamonkey@3574: m_Options.clear();
skamonkey@3513:
skamonkey@3513: char path[PLATFORM_MAX_PATH];
skamonkey@3513:
skamonkey@3513: /* See if we can use the extended gamedata format. */
skamonkey@3513: //TODO pass in path to gamedata somehow
skamonkey@3513:
skamonkey@3513: /* Otherwise, it's time to parse the master. */
skamonkey@3513: SMCError err;
skamonkey@3513: SMCStates state = {0, 0};
skamonkey@3513: list fileList;
skamonkey@3513: master_reader.fileList = &fileList;
skamonkey@3513:
skamonkey@3513: err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength);
skamonkey@3513: if (err != SMCError_Okay)
skamonkey@3513: {
skamonkey@3513: const char *msg = textparsers->GetSMCErrorString(err);
skamonkey@3513:
skamonkey@3513: printf("[SM] Error parsing master gameconf file \"%s\":", path);
skamonkey@3513: printf("[SM] Error %d on line %d, col %d: %s",
skamonkey@3513: err,
skamonkey@3513: state.line,
skamonkey@3513: state.col,
skamonkey@3513: msg ? msg : "Unknown error");
skamonkey@3513: exit(PARSE_ERROR);
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: /* Go through each file we found and parse it. */
skamonkey@3513: list::iterator iter;
skamonkey@3513: for (iter = fileList.begin(); iter != fileList.end(); iter++)
skamonkey@3513: {
skamonkey@3513: UTIL_Format(path, sizeof(path), "%s/%s", m_File, *iter);
skamonkey@3513: if (!EnterFile(path, error, maxlength))
skamonkey@3513: {
skamonkey@3513: return false;
skamonkey@3513: }
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return true;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
skamonkey@3513: {
skamonkey@3513: SMCError err;
skamonkey@3513: SMCStates state = {0, 0};
skamonkey@3513:
skamonkey@3513: /* Initialize parse states */
skamonkey@3513: m_IgnoreLevel = 0;
skamonkey@3513: bShouldBeReadingDefault = true;
skamonkey@3513: m_ParseState = PSTATE_NONE;
skamonkey@3513:
skamonkey@3513: if ((err=textparsers->ParseSMCFile(file, this, &state, error, maxlength))
skamonkey@3513: != SMCError_Okay)
skamonkey@3513: {
skamonkey@3513: const char *msg;
skamonkey@3513:
skamonkey@3513: msg = textparsers->GetSMCErrorString(err);
skamonkey@3513:
skamonkey@3513: printf("[SM] Error parsing gameconfig file \"%s\":\n", file);
skamonkey@3513: printf("[SM] Error %d on line %d, col %d: %s\n",
skamonkey@3513: err,
skamonkey@3513: state.line,
skamonkey@3513: state.col,
skamonkey@3513: msg ? msg : "Unknown error");
skamonkey@3513:
skamonkey@3513: if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM)
skamonkey@3513: {
skamonkey@3513: //error occurred while parsing a custom section
skamonkey@3513: m_CustomHandler->ReadSMC_ParseEnd(true, true);
skamonkey@3513: m_CustomHandler = NULL;
skamonkey@3513: m_CustomLevel = 0;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: exit(PARSE_ERROR);
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: return true;
skamonkey@3513: }
skamonkey@3513:
skamonkey@3513: const char *CGameConfig::GetKeyValue(const char *key)
skamonkey@3513: {
skamonkey@3513: int *pkey;
skamonkey@3513: if ((pkey = m_Keys.retrieve(key)) == NULL)
skamonkey@3513: return NULL;
skamonkey@3513: return m_pStrings->GetString(*pkey);
skamonkey@3513: }
skamonkey@3513:
skamonkey@3574: const char *CGameConfig::GetOptionValue(const char *key)
skamonkey@3574: {
skamonkey@3574: int *pkey;
skamonkey@3574: if ((pkey = m_Options.retrieve(key)) == NULL)
skamonkey@3574: return NULL;
skamonkey@3574: return m_pStrings->GetString(*pkey);
skamonkey@3574: }
skamonkey@3574:
skamonkey@3513: list CGameConfig::GetOffsets() { return m_Offsets; }
skamonkey@3513: list CGameConfig::GetSigs() { return m_Sigs; }
skamonkey@3513: