From f93711bd82452e770ade4d8bf41a67e6028da531 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 5 Apr 2007 05:25:11 +0000 Subject: [PATCH] changed the API around a bit to be more flexible removed some ghastly unneeded stuff from the Translator added Logger::LogFatal, experimental --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40669 --- core/CoreConfig.cpp | 49 ++++++++++++------------------- core/CoreConfig.h | 2 +- core/Logger.cpp | 65 +++++++++++++++++++++++++++++++----------- core/Logger.h | 16 ++++++++--- core/Translator.cpp | 40 ++++++++++++++++++++++---- core/Translator.h | 10 +++++-- core/sm_globals.h | 29 ++++++++++++------- core/sm_stringutil.cpp | 39 ++++++++++++------------- core/sm_stringutil.h | 1 + core/sourcemod.cpp | 24 ++++++++++------ core/sourcemod.h | 6 +++- 11 files changed, 179 insertions(+), 102 deletions(-) diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index 0a5850dc..362b23e9 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -22,7 +22,7 @@ #ifdef PLATFORM_WINDOWS ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file"); -#else +#elif defined PLATFORM_LINUX ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file"); #endif @@ -45,21 +45,13 @@ void CoreConfig::OnRootConsoleCommand(const char *command, unsigned int argcount const char *option = engine->Cmd_Argv(2); const char *value = engine->Cmd_Argv(3); - CoreConfigErr err = SetConfigOption(option, value); + char error[255]; - switch (err) + ConfigResult err = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error)); + + if (err == ConfigResult_Reject) { - case CoreConfig_NoRuntime: - g_RootMenu.ConsolePrint("[SM] Cannot set \"%s\" while SourceMod is running.", option); - break; - case CoreConfig_InvalidValue: - g_RootMenu.ConsolePrint("[SM] Invalid value \"%s\" specified for configuration option \"%s\"", value, option); - break; - case CoreConfig_InvalidOption: - g_RootMenu.ConsolePrint("[SM] Invalid configuration option specified: %s", option); - break; - default: - break; + g_Logger.LogError("Could not set config option \"%s\" to \"%s\" (error: %s)", option, value, error); } return; @@ -90,44 +82,39 @@ void CoreConfig::Initialize() != SMCParse_Okay) { /* :TODO: This won't actually log or print anything :( - So fix that somehow */ - g_Logger.LogError("[SM] Error encountered parsing core config file: %s", g_TextParser.GetSMCErrorString(err)); + const char *error = g_TextParser.GetSMCErrorString(err); + g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : ""); } } SMCParseResult CoreConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes) { - CoreConfigErr err = SetConfigOption(key, value); + char error[255]; + ConfigResult err = SetConfigOption(key, value, ConfigSource_File, error, sizeof(error)); - if (err == CoreConfig_InvalidOption) + if (err == ConfigResult_Reject) { - g_Logger.LogError("[SM] Warning: Ignoring invalid option \"%s\" in configuration file.", key); - } else if (err == CoreConfig_InvalidValue) { - g_Logger.LogError("[SM] Warning encountered parsing core configuration file."); - g_Logger.LogError("[SM] Invalid value \"%s\" specified for option \"%s\"", value, key); + /* This is a fatal error */ + g_Logger.LogFatal("%s", error); } return SMCParse_Continue; } -CoreConfigErr CoreConfig::SetConfigOption(const char *option, const char *value) +ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength) { - CoreConfigErr err = CoreConfig_TOTAL; - CoreConfigErr currentErr; + ConfigResult result; /* Notify! */ SMGlobalClass *pBase = SMGlobalClass::head; while (pBase) { - currentErr = pBase->OnSourceModConfigChanged(option, value); - - /* Lowest error code has priority */ - if (currentErr < err) + if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore) { - err = currentErr; + return result; } - pBase = pBase->m_pGlobalClassNext; } - return err; + return ConfigResult_Ignore; } diff --git a/core/CoreConfig.h b/core/CoreConfig.h index b08888a2..da83d46d 100644 --- a/core/CoreConfig.h +++ b/core/CoreConfig.h @@ -42,7 +42,7 @@ private: /** * Sets configuration option by notifying SourceMod components that rely on core.cfg */ - CoreConfigErr SetConfigOption(const char *option, const char *value); + ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength); }; extern CoreConfig g_CoreConfig; diff --git a/core/Logger.cpp b/core/Logger.cpp index 9ce90b61..15a5fb94 100644 --- a/core/Logger.cpp +++ b/core/Logger.cpp @@ -15,6 +15,7 @@ #include #include "sourcemod.h" #include "sourcemm_api.h" +#include "sm_stringutil.h" #include "Logger.h" #include "systems/LibrarySys.h" #include "sm_version.h" @@ -25,31 +26,39 @@ Logger g_Logger; * :TODO: This should be creating the log folder if it doesn't exist */ -CoreConfigErr Logger::OnSourceModConfigChanged(const char *option, const char *value) +ConfigResult Logger::OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) { - if (strcasecmp(option, "Logging") == 0) + if (strcasecmp(key, "Logging") == 0) { bool state = true; if (strcasecmp(value, "on") == 0) { - state = true; } else if (strcasecmp(value, "off") == 0) { state = false; } else { - return CoreConfig_InvalidValue; + UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\""); + return ConfigResult_Reject; } - if (m_FirstPass) + if (source == ConfigSource_Console) { - m_InitialState = state; - m_FirstPass = false; + if (state && !m_Active) + { + EnableLogging(); + } else if (!state && m_Active) { + DisableLogging(); + } } else { - state ? g_Logger.EnableLogging() : g_Logger.DisableLogging(); + m_InitialState = state; } - return CoreConfig_Okay; - } else if (strcasecmp(option, "LogMode") == 0) { + return ConfigResult_Accept; + } else if (strcasecmp(key, "LogMode") == 0) { if (strcasecmp(value, "daily") == 0) { m_Mode = LoggingMode_Daily; @@ -58,18 +67,19 @@ CoreConfigErr Logger::OnSourceModConfigChanged(const char *option, const char *v } else if (strcasecmp(value, "game") == 0) { m_Mode = LoggingMode_Game; } else { - return CoreConfig_InvalidValue; + UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]"); + return ConfigResult_Reject; } - return CoreConfig_Okay; + return ConfigResult_Accept; } - return CoreConfig_InvalidOption; + return ConfigResult_Ignore; } void Logger::OnSourceModStartup(bool late) { - InitLogger(m_Mode, m_InitialState); + InitLogger(m_Mode); } void Logger::OnSourceModAllShutdown() @@ -155,10 +165,10 @@ void Logger::_CloseFile() m_ErrFileName.clear(); } -void Logger::InitLogger(LoggingMode mode, bool startlogging) +void Logger::InitLogger(LoggingMode mode) { m_Mode = mode; - m_Active = startlogging; + m_Active = m_InitialState; time_t t; time(&t); @@ -173,7 +183,7 @@ void Logger::InitLogger(LoggingMode mode, bool startlogging) { case LoggingMode_PerMap: { - if (!startlogging) + if (!m_Active) { m_DelayedStart = true; } @@ -414,3 +424,24 @@ void Logger::DisableLogging() LogMessage("Logging disabled manually by user."); m_Active = false; } + +void Logger::LogFatal(const char *msg, ...) +{ + char path[PLATFORM_MAX_PATH]; + g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); + FILE *fp = fopen(path, "at"); + if (!fp) + { + /* We're just doomed, aren't we... */ + return; + } + + va_list ap; + va_start(ap, msg); + vfprintf(fp, msg, ap); + va_end(ap); + + fputs("\n", fp); + + fclose(fp); +} diff --git a/core/Logger.h b/core/Logger.h index bc81bdf1..b469c71b 100644 --- a/core/Logger.h +++ b/core/Logger.h @@ -36,18 +36,27 @@ enum LoggingMode class Logger : public SMGlobalClass { public: - Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), m_InitialState(true), m_FirstPass(true) {} + Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), + m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), + m_InitialState(true) + { + } public: //SMGlobalClass - CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); + ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength); void OnSourceModStartup(bool late); void OnSourceModAllShutdown(); public: - void InitLogger(LoggingMode mode, bool startlogging); + void InitLogger(LoggingMode mode); void CloseLogger(); void EnableLogging(); void DisableLogging(); void LogMessage(const char *msg, ...); void LogError(const char *msg, ...); + void LogFatal(const char *msg, ...); void MapChange(const char *mapname); const char *GetLogFileName(LogType type) const; LoggingMode GetLoggingMode() const; @@ -66,7 +75,6 @@ private: bool m_DelayedStart; bool m_DailyPrintHdr; bool m_InitialState; - bool m_FirstPass; }; extern Logger g_Logger; diff --git a/core/Translator.cpp b/core/Translator.cpp index 6f90bfba..fd909a6f 100644 --- a/core/Translator.cpp +++ b/core/Translator.cpp @@ -604,15 +604,30 @@ Translator::~Translator() delete m_pStringTab; } -CoreConfigErr Translator::OnSourceModConfigChanged(const char *option, const char *value) +ConfigResult Translator::OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) { - if (strcasecmp(option, "ServerLang") == 0) + if (strcasecmp(value, "ServerLang") == 0) { + if (source == ConfigSource_Console) + { + unsigned int index; + if (!GetLanguageByCode(value, &index)) + { + UTIL_Format(error, maxlength, "Language code \"%s\" is not registered", value); + return ConfigResult_Reject; + } + } + strncopy(m_ServerLangCode, value, sizeof(m_ServerLangCode)); - return CoreConfig_Okay; + + return ConfigResult_Accept; } - return CoreConfig_InvalidOption; + return ConfigResult_Ignore; } void Translator::OnSourceModAllInitialized() @@ -837,7 +852,20 @@ TransError Translator::CoreTrans(int client, return Trans_Okay; } -const char *Translator::GetServerLanguageCode() const +unsigned int Translator::GetServerLanguageCode() { - return m_ServerLangCode; + void *serverLang; + + /* :TODO: there is absolutely no reason this shouldn't be cached + * I don't even know why it was returning a string originally + */ + + if (!sm_trie_retrieve(m_pLCodeLookup, m_ServerLangCode, &serverLang)) + { + g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English"); + strncopy(m_ServerLangCode, "en", sizeof(m_ServerLangCode)); + return 0; + } + + return (unsigned int)serverLang; } diff --git a/core/Translator.h b/core/Translator.h index 73a5eab1..65836dc6 100644 --- a/core/Translator.h +++ b/core/Translator.h @@ -49,6 +49,8 @@ struct Translation int *fmt_order; /**< Format phrase order. */ }; +#define LANGUAGE_ENGLISH 0 + enum TransError { Trans_Okay = 0, @@ -100,7 +102,11 @@ public: Translator(); ~Translator(); public: // SMGlobalClass - CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); + ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength); void OnSourceModAllInitialized(); public: // ITextListener_SMC void ReadSMC_ParseStart(); @@ -121,7 +127,7 @@ public: const char *phrase, void **params, size_t *outlen=NULL); - const char *GetServerLanguageCode() const; + unsigned int GetServerLanguageCode(); private: bool AddLanguage(const char *langcode, const char *description); private: diff --git a/core/sm_globals.h b/core/sm_globals.h index 213c76d6..bedf9d9e 100644 --- a/core/sm_globals.h +++ b/core/sm_globals.h @@ -28,16 +28,19 @@ using namespace SourcePawn; using namespace SourceMod; /** -* @brief Lists error codes possible from attempting to set a core configuration option. -*/ -enum CoreConfigErr + * @brief Lists error codes possible from attempting to set a core configuration option. + */ +enum ConfigResult { - CoreConfig_Okay = 0, /**< No error */ - CoreConfig_NoRuntime = 1, /**< Cannot set config option while SourceMod is running */ - CoreConfig_InvalidValue = 2, /**< Invalid value specified for config option */ - CoreConfig_InvalidOption = 3, /**< Invalid config option specified */ - /* -------------------- */ - CoreConfig_TOTAL /**< Total number of core config error codes */ + ConfigResult_Accept = 0, + ConfigResult_Reject = 1, + ConfigResult_Ignore = 2 +}; + +enum ConfigSource +{ + ConfigSource_File = 0, + ConfigSource_Console = 1, }; /** @@ -83,9 +86,13 @@ public: * @note This is called once BEFORE OnSourceModStartup() when SourceMod is loading * @note It can then be called again when the 'sm config' command is used */ - virtual CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value) + virtual ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) { - return CoreConfig_InvalidOption; + return ConfigResult_Ignore; } private: SMGlobalClass *m_pGlobalClassNext; diff --git a/core/sm_stringutil.cpp b/core/sm_stringutil.cpp index b8d9f914..5682645b 100644 --- a/core/sm_stringutil.cpp +++ b/core/sm_stringutil.cpp @@ -73,24 +73,9 @@ size_t Translate(char *buffer, size_t maxlen, IPluginContext *pCtx, const char * try_serverlang: if (target == LANG_SERVER) { - langname = g_Translator.GetServerLanguageCode(); - if (!TryServerLanguage(langname ? langname : "en", &langid)) - { - pCtx->ThrowNativeError("Translation failure: English language not found"); - goto error_out; - } - } else if ((target >= 1) && (target <= g_Players.GetMaxClients())) { - langname = g_Translator.GetServerLanguageCode(); /* :TODO: read player's lang */ - if (!langname || !g_Translator.GetLanguageByCode(langname, &langid)) - { - if (langname && !strcmp(langname, "en")) - { - pCtx->ThrowNativeError("Translation failure: English language not found"); - goto error_out; - } - target = LANG_SERVER; - goto try_serverlang; - } + langid = g_Translator.GetServerLanguageCode(); + } else if ((target >= 1) && (target <= g_Players.GetMaxClients())) { + langid = g_Translator.GetServerLanguageCode(); } else { pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target); goto error_out; @@ -102,9 +87,8 @@ try_serverlang: { target = LANG_SERVER; goto try_serverlang; - } else { - if (!g_Translator.GetLanguageByCode("en", &langid) - || !TryTranslation(pl, key, langid, langcount, &pTrans)) + } else if (langid != LANGUAGE_ENGLISH) { + if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans)) { pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key); goto error_out; @@ -900,6 +884,19 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) } } +size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap) +{ + size_t len = vsnprintf(buffer, maxlength, fmt, ap); + + if (len >= maxlength) + { + buffer[maxlength - 1] = '\0'; + return (maxlength - 1); + } else { + return len; + } +} + char *sm_strdup(const char *str) { char *ptr = new char[strlen(str)+1]; diff --git a/core/sm_stringutil.h b/core/sm_stringutil.h index df72ecc6..2515dd1c 100644 --- a/core/sm_stringutil.h +++ b/core/sm_stringutil.h @@ -30,6 +30,7 @@ const char *stristr(const char *str, const char *substr); unsigned int strncopy(char *dest, const char *src, size_t count); size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args); size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); +size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap); char *sm_strdup(const char *str); #endif // _INCLUDE_SOURCEMOD_STRINGUTIL_H_ diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 516fe270..73d234c3 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -69,24 +69,32 @@ SourceModBase::SourceModBase() m_GotBasePath = false; } -CoreConfigErr SourceModBase::OnSourceModConfigChanged(const char *option, const char *value) +ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) { - if (strcasecmp(option, "BasePath") == 0) + if (strcasecmp(value, "BasePath") == 0) { + if (source == ConfigSource_Console) + { + UTIL_Format(error, maxlength, "Cannot be set at runtime"); + return ConfigResult_Reject; + } + if (!m_GotBasePath) { g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), value); g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), value); m_GotBasePath = true; - - return CoreConfig_Okay; - } else { - return CoreConfig_NoRuntime; } + + return ConfigResult_Accept; } - return CoreConfig_InvalidOption; + return ConfigResult_Ignore; } bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late) @@ -97,7 +105,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late) g_CoreConfig.Initialize(); /* This shouldn't happen, but can't hurt to be safe */ - if (!m_GotBasePath || !g_LibSys.PathExists(m_SMBaseDir)) + if (!g_LibSys.PathExists(m_SMBaseDir) || !m_GotBasePath) { g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str()); g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod"); diff --git a/core/sourcemod.h b/core/sourcemod.h index 878670d8..57ef3ef7 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -78,7 +78,11 @@ public: */ void SetAuthChecking(bool set); public: // SMGlobalClass - CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); + ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength); public: // ISourceMod const char *GetModPath() const; const char *GetSourceModPath() const;