diff --git a/AMBuildScript b/AMBuildScript index b4541d3c..d2a5772b 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -190,7 +190,7 @@ class SMConfig(object): cxx.cflags += ['-Wno-unused-result'] if have_clang: cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] - if (builder.target_platform == 'mac' and cxx.version >= '5.1') or cxx.version >= '3.4': + if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': cxx.cxxflags += ['-Wno-deprecated-register'] else: cxx.cxxflags += ['-Wno-deprecated'] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index ea14268e..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,6 +0,0 @@ -Contributing ------------- - -Please visit [our wiki](https://wiki.alliedmods.net/Contributing_to_SourceMod) for information on how to contribute to Sourcemod. - -As a sidenote, [Travis](https://travis-ci.org/alliedmodders/sourcemod) will automatically build your PR to make sure it compiles on Linux. diff --git a/core/AMBuilder b/core/AMBuilder index 7eb37f84..d9f62d83 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -31,7 +31,6 @@ project.sources += [ 'smn_console.cpp', 'UserMessages.cpp', 'MenuManager.cpp', - 'smn_core.cpp', 'smn_hudtext.cpp', 'smn_usermsgs.cpp', 'MenuStyle_Base.cpp', diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index 80d3f703..e93c6cc3 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -383,7 +383,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, { if (!m_CmdGrps.add(i, group)) return false; - i->value = NoAddRef(new CommandGroup()); + i->value = new CommandGroup(); } Ref cmdgroup = i->value; diff --git a/core/ConsoleDetours.cpp b/core/ConsoleDetours.cpp index 6c406666..fba52721 100644 --- a/core/ConsoleDetours.cpp +++ b/core/ConsoleDetours.cpp @@ -195,7 +195,7 @@ class GenericCommandHooker : public IConCommandLinkListener size_t index; if (!FindVtable(vtable, index)) { - g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName()); + logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName()); return; } @@ -219,7 +219,7 @@ public: if (dispatch.thisptroffs < 0) { - g_Logger.LogError("Command filter could not determine ConCommand layout"); + logger->LogError("Command filter could not determine ConCommand layout"); return false; } @@ -228,7 +228,7 @@ public: if (!vtables.size()) { - g_Logger.LogError("Command filter could not find any cvars!"); + logger->LogError("Command filter could not find any cvars!"); return false; } diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index 42c30ab1..1cce9f4d 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -262,7 +262,7 @@ void CoreConfig::Initialize() { /* :TODO: This won't actually log or print anything :( - So fix that somehow */ const char *error = textparsers->GetSMCErrorString(err); - g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : ""); + logger->LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : ""); } } @@ -274,7 +274,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, if (err == ConfigResult_Reject) { /* This is a fatal error */ - g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error); + logger->LogFatal("Config error (key: %s) (value: %s) %s", key, value, error); } return SMCResult_Continue; @@ -469,7 +469,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) } else { - g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename()); + logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename()); return can_create; } } diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index da8935fe..9cc3bc51 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -168,7 +168,7 @@ void CHalfLife2::InitLogicalEntData() if (!addr) { // Key exists so notify if lookup fails, but try other method. - g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown"); + logger->LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown"); } else { @@ -186,7 +186,7 @@ void CHalfLife2::InitLogicalEntData() int offset; if (!g_pGameConf->GetOffset("gEntList", &offset)) { - g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only"); + logger->LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only"); return; } @@ -198,7 +198,7 @@ void CHalfLife2::InitLogicalEntData() // If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset)) { - g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only"); + logger->LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only"); g_EntList = NULL; return; } @@ -211,7 +211,7 @@ void CHalfLife2::InitLogicalEntData() if (!g_EntList && !g_pEntInfoList) { - g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only"); + logger->LogError("Failed lookup of gEntList - Reverting to networkable entities only"); return; } } @@ -225,7 +225,7 @@ void CHalfLife2::InitCommandLine() ke::AutoPtr lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error))); if (lib == NULL) { - g_Logger.LogError("Could not load %s: %s", TIER0_NAME, error); + logger->LogError("Could not load %s: %s", TIER0_NAME, error); return; } @@ -242,7 +242,7 @@ void CHalfLife2::InitCommandLine() ke::AutoPtr lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error))); if (lib == NULL) { - g_Logger.LogError("Could not load %s: %s", VSTDLIB_NAME, error); + logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error); return; } @@ -251,7 +251,7 @@ void CHalfLife2::InitCommandLine() if (m_pGetCommandLine == NULL) { - g_Logger.LogError("Could not locate any command line functionality"); + logger->LogError("Could not locate any command line functionality"); } } diff --git a/core/Logger.cpp b/core/Logger.cpp index 20668fc4..9dd402d3 100644 --- a/core/Logger.cpp +++ b/core/Logger.cpp @@ -39,61 +39,12 @@ #include "logic_bridge.h" #include -Logger g_Logger; +bool g_in_game_log_hook = false; + +static LoggerCore g_LoggerCore; SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *); -/** - * :TODO: This should be creating the log folder if it doesn't exist - */ - -ConfigResult Logger::OnSourceModConfigChanged(const char *key, - const char *value, - ConfigSource source, - char *error, - size_t maxlength) -{ - if (strcasecmp(key, "Logging") == 0) - { - bool state; - - if (strcasecmp(value, "on") == 0) - { - state = true; - } else if (strcasecmp(value, "off") == 0) { - state = false; - } else { - UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\""); - return ConfigResult_Reject; - } - - if (source == ConfigSource_Console) - { - state ? EnableLogging() : DisableLogging(); - } else { - m_InitialState = state; - } - - return ConfigResult_Accept; - } else if (strcasecmp(key, "LogMode") == 0) { - if (strcasecmp(value, "daily") == 0) - { - m_Mode = LoggingMode_Daily; - } else if (strcasecmp(value, "map") == 0) { - m_Mode = LoggingMode_PerMap; - } else if (strcasecmp(value, "game") == 0) { - m_Mode = LoggingMode_Game; - } else { - UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]"); - return ConfigResult_Reject; - } - - return ConfigResult_Accept; - } - - return ConfigResult_Ignore; -} - static void HookLogPrint(const char *message) { g_in_game_log_hook = true; @@ -104,477 +55,16 @@ static void HookLogPrint(const char *message) RETURN_META(MRES_SUPERCEDE); } -void Logger::OnSourceModStartup(bool late) +void LoggerCore::OnSourceModStartup(bool late) { - InitLogger(m_Mode); - SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); } -void Logger::OnSourceModAllShutdown() +void LoggerCore::OnSourceModAllShutdown() { - CloseLogger(); SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); } -void Logger::OnSourceModLevelChange(const char *mapName) -{ - MapChange(mapName); -} - -void Logger::_NewMapFile() -{ - if (!m_Active) - { - return; - } - - /* Append "Log file closed" to previous log file */ - _CloseFile(); - - char _filename[256]; - int i = 0; - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - while (true) - { - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i); - FILE *fp = fopen(_filename, "r"); - if (!fp) - { - break; - } - fclose(fp); - i++; - } - m_NrmFileName.assign(_filename); - - FILE *fp = fopen(m_NrmFileName.c_str(), "w"); - if (!fp) - { - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; - return; - } else { - char date[32]; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); - fclose(fp); - } -} - -void Logger::_CloseFile() -{ - if (!m_Active) - { - return; - } - - FILE *fp = NULL; - if (!m_NrmFileName.empty()) - { - fp = fopen(m_NrmFileName.c_str(), "r+"); - if (fp) - { - fseek(fp, 0, SEEK_END); - LogMessage("Log file closed."); - fclose(fp); - } - m_NrmFileName.clear(); - } - - if (!m_ErrMapStart) - { - return; - } - fp = fopen(m_ErrFileName.c_str(), "r+"); - if (fp) - { - fseek(fp, 0, SEEK_END); - LogError("Error log file session closed."); - fclose(fp); - } - m_ErrFileName.clear(); -} - -void Logger::InitLogger(LoggingMode mode) -{ - m_Mode = mode; - m_Active = m_InitialState; - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - m_NrmCurDay = curtime->tm_mday; - m_ErrCurDay = curtime->tm_mday; - - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrFileName.assign(_filename); - - switch (m_Mode) - { - case LoggingMode_PerMap: - { - if (!m_Active) - { - m_DelayedStart = true; - } - break; - } - case LoggingMode_Daily: - { - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_NrmFileName.assign(_filename); - m_DailyPrintHdr = true; - break; - } - default: - { - /* do nothing... */ - break; - } - } -} - -void Logger::CloseLogger() -{ - _CloseFile(); -} - -void Logger::LogToOpenFile(FILE *fp, const char *msg, ...) -{ - if (!m_Active) - { - return; - } - - va_list ap; - va_start(ap, msg); - LogToOpenFileEx(fp, msg, ap); - va_end(ap); -} - -void Logger::LogToFileOnly(FILE *fp, const char *msg, ...) -{ - if (!m_Active) - { - return; - } - - va_list ap; - va_start(ap, msg); - LogToFileOnlyEx(fp, msg, ap); - va_end(ap); -} - -void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) -{ - if (!m_Active) - { - return; - } - - static ConVar *sv_logecho = icvar->FindVar("sv_logecho"); - - char buffer[3072]; - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - - char date[32]; - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - - fprintf(fp, "L %s: %s\n", date, buffer); - - if (!sv_logecho || sv_logecho->GetBool()) - { - g_SMAPI->ConPrintf("L %s: %s\n", date, buffer); - } -} - -void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) -{ - if (!m_Active) - { - return; - } - - char buffer[3072]; - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - - char date[32]; - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - - fprintf(fp, "L %s: %s\n", date, buffer); - fflush(fp); -} - -void Logger::LogMessage(const char *vafmt, ...) -{ - va_list ap; - va_start(ap, vafmt); - LogMessageEx(vafmt, ap); - va_end(ap); -} - -void Logger::LogMessageEx(const char *vafmt, va_list ap) -{ - if (!m_Active) - { - return; - } - - if (m_Mode == LoggingMode_Game) - { - _PrintToGameLog(vafmt, ap); - return; - } - - if (m_DelayedStart) - { - m_DelayedStart = false; - _NewMapFile(); - } - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - FILE *fp = NULL; - if (m_Mode == LoggingMode_PerMap) - { - fp = fopen(m_NrmFileName.c_str(), "a+"); - if (!fp) - { - _NewMapFile(); - fp = fopen(m_NrmFileName.c_str(), "a+"); - if (!fp) - { - goto print_error; - } - } - } else { - if (m_NrmCurDay != curtime->tm_mday) - { - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_NrmFileName.assign(_filename); - m_NrmCurDay = curtime->tm_mday; - m_DailyPrintHdr = true; - } - fp = fopen(m_NrmFileName.c_str(), "a+"); - } - - if (fp) - { - if (m_DailyPrintHdr) - { - char date[32]; - m_DailyPrintHdr = false; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION); - } - LogToOpenFileEx(fp, vafmt, ap); - fclose(fp); - } else { - goto print_error; - } - - return; -print_error: - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; -} - -void Logger::LogError(const char *vafmt, ...) -{ - va_list ap; - va_start(ap, vafmt); - LogErrorEx(vafmt, ap); - va_end(ap); -} - -void Logger::LogErrorEx(const char *vafmt, va_list ap) -{ - if (!m_Active) - { - return; - } - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - if (curtime->tm_mday != m_ErrCurDay) - { - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrFileName.assign(_filename); - m_ErrCurDay = curtime->tm_mday; - m_ErrMapStart = false; - } - - FILE *fp = fopen(m_ErrFileName.c_str(), "a+"); - if (fp) - { - if (!m_ErrMapStart) - { - char date[32]; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod error session started\n", date); - fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrMapStart = true; - } - LogToOpenFileEx(fp, vafmt, ap); - fclose(fp); - } - else - { - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; - return; - } -} - -void Logger::MapChange(const char *mapname) -{ - m_CurMapName.assign(mapname); - - switch (m_Mode) - { - case LoggingMode_Daily: - { - LogMessage("-------- Mapchange to %s --------", mapname); - break; - } - case LoggingMode_PerMap: - { - _NewMapFile(); - break; - } - default: - { - /* Do nothing... */ - break; - } - } - - if (m_ErrMapStart) - { - LogError("Error log file session closed."); - } - m_ErrMapStart = false; -} - -void Logger::_PrintToGameLog(const char *fmt, va_list ap) -{ - char msg[3072]; - size_t len; - - len = vsnprintf(msg, sizeof(msg)-2, fmt, ap); - len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len; - - msg[len++] = '\n'; - msg[len] = '\0'; - - Engine_LogPrintWrapper(msg); -} - -const char *Logger::GetLogFileName(LogType type) const -{ - switch (type) - { - case LogType_Normal: - { - return m_NrmFileName.c_str(); - } - case LogType_Error: - { - return m_ErrFileName.c_str(); - } - default: - { - return ""; - } - } -} - -LoggingMode Logger::GetLoggingMode() const -{ - return m_Mode; -} - -void Logger::EnableLogging() -{ - if (m_Active) - { - return; - } - m_Active = true; - LogMessage("[SM] Logging enabled manually by user."); -} - -void Logger::DisableLogging() -{ - if (!m_Active) - { - return; - } - LogMessage("[SM] Logging disabled manually by user."); - m_Active = false; -} - -void Logger::LogFatal(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - LogFatalEx(msg, ap); - va_end(ap); -} - -void Logger::LogFatalEx(const char *msg, va_list ap) -{ - /* :TODO: make this print all pretty-like - * In fact, the pretty log printing function should be abstracted. - * It's already implemented twice which is bad. - */ - - char path[PLATFORM_MAX_PATH]; - - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); - - FILE *fp = fopen(path, "at"); - if (fp) - { - m_Active = true; - LogToOpenFileEx(fp, msg, ap); - m_Active = false; - fclose(fp); - } -} - -bool g_in_game_log_hook = false; - void Engine_LogPrintWrapper(const char *msg) { if (g_in_game_log_hook) diff --git a/core/Logger.h b/core/Logger.h index 834492e9..a12dc9ef 100644 --- a/core/Logger.h +++ b/core/Logger.h @@ -38,76 +38,13 @@ using namespace SourceHook; -enum LogType +class LoggerCore : public SMGlobalClass { - LogType_Normal, - LogType_Error -}; - -enum LoggingMode -{ - LoggingMode_Daily, - LoggingMode_PerMap, - LoggingMode_Game -}; - -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) - { - } public: //SMGlobalClass - ConfigResult OnSourceModConfigChanged(const char *key, - const char *value, - ConfigSource source, - char *error, - size_t maxlength); void OnSourceModStartup(bool late); void OnSourceModAllShutdown(); - void OnSourceModLevelChange(const char *mapName); -public: - void InitLogger(LoggingMode mode); - void CloseLogger(); - void EnableLogging(); - void DisableLogging(); - void LogMessage(const char *msg, ...); - void LogMessageEx(const char *msg, va_list ap); - void LogError(const char *msg, ...); - void LogErrorEx(const char *msg, va_list ap); - void LogFatal(const char *msg, ...); - void LogFatalEx(const char *msg, va_list ap); - void LogToOpenFile(FILE *fp, const char *msg, ...); - void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); - /* This version does not print to console, and is thus thread-safe */ - void LogToFileOnly(FILE *fp, const char *msg, ...); - void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap); - void MapChange(const char *mapname); - const char *GetLogFileName(LogType type) const; - LoggingMode GetLoggingMode() const; -private: - void _CloseFile(); - void _NewMapFile(); - void _PrintToGameLog(const char *fmt, va_list ap); -private: - String m_NrmFileName; - String m_ErrFileName; - String m_CurMapName; - LoggingMode m_Mode; - int m_NrmCurDay; - int m_ErrCurDay; - bool m_ErrMapStart; - bool m_Active; - bool m_DelayedStart; - bool m_DailyPrintHdr; - bool m_InitialState; }; void Engine_LogPrintWrapper(const char *msg); -extern bool g_in_game_log_hook; -extern Logger g_Logger; - #endif // _INCLUDE_SOURCEMOD_CLOGGER_H_ diff --git a/core/NextMap.cpp b/core/NextMap.cpp index 92243008..126f8f66 100644 --- a/core/NextMap.cpp +++ b/core/NextMap.cpp @@ -36,6 +36,7 @@ #include "sm_stringutil.h" #include "sourcehook.h" #include "sm_srvcmds.h" +#include "logic_bridge.h" NextMapManager g_NextMap; @@ -130,7 +131,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const { if (g_forcedChange) { - g_Logger.LogMessage("[SM] Changed map to \"%s\"", map); + logger->LogMessage("[SM] Changed map to \"%s\"", map); RETURN_META(MRES_IGNORED); } @@ -141,7 +142,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const RETURN_META(MRES_IGNORED); } - g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap); + logger->LogMessage("[SM] Changed map to \"%s\"", newmap); UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap); UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index bc2c1038..587db7e5 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -1238,7 +1238,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0') { unsigned int accountId = pPlayer->GetSteamAccountID(); - g_Logger.LogMessage("\"%s<%d><>\" has bad networkid (id \"%s\") (ip \"%s\")", + logger->LogMessage("\"%s<%d><>\" has bad networkid (id \"%s\") (ip \"%s\")", new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress()); pPlayer->Kick("NetworkID spoofing detected."); diff --git a/core/logic/AMBuilder b/core/logic/AMBuilder index b38a0965..17a8eb3a 100644 --- a/core/logic/AMBuilder +++ b/core/logic/AMBuilder @@ -66,6 +66,8 @@ binary.sources += [ 'sm_trie.cpp', 'smn_console.cpp', 'ProfileTools.cpp', + 'Logger.cpp', + 'smn_core.cpp', ] if builder.target_platform == 'windows': binary.sources += ['thread/WinThreads.cpp'] diff --git a/core/logic/AdminCache.cpp b/core/logic/AdminCache.cpp index dc1094a5..a10ae6d1 100644 --- a/core/logic/AdminCache.cpp +++ b/core/logic/AdminCache.cpp @@ -198,11 +198,11 @@ private: if (!m_bFileNameLogged) { - smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); + logger->LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); m_bFileNameLogged = true; } - smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); + logger->LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); } private: bool m_bFileNameLogged; diff --git a/core/logic/Database.cpp b/core/logic/Database.cpp index e691bf28..99c13f10 100644 --- a/core/logic/Database.cpp +++ b/core/logic/Database.cpp @@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName) ke::AutoLock lock(&m_ConfigLock); if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay) { - smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename); + logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename); if (err != SMCError_Custom) { const char *txt = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Line %d: %s", states.line, txt); + logger->LogError("[SM] Line %d: %s", states.line, txt); } } } @@ -541,7 +541,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio) { if (!s_OneTimeThreaderErrorMsg) { - smcore.LogError("[SM] Unable to create db threader (error unknown)"); + logger->LogError("[SM] Unable to create db threader (error unknown)"); s_OneTimeThreaderErrorMsg = true; } m_Worker = NULL; diff --git a/core/logic/DebugReporter.cpp b/core/logic/DebugReporter.cpp index efeea02d..ef5863ba 100644 --- a/core/logic/DebugReporter.cpp +++ b/core/logic/DebugReporter.cpp @@ -32,6 +32,7 @@ #include #include #include "DebugReporter.h" +#include "Logger.h" DebugReport g_DbgReporter; @@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...) smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); va_end(ap); - smcore.Log("[SM] %s", buffer); + g_Logger.LogMessage("[SM] %s", buffer); } void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...) @@ -71,12 +72,12 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, if (error) { - smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); + g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); } else { - smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); + g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); } - smcore.LogError("[SM] %s", buffer); + g_Logger.LogError("[SM] %s", buffer); if (func_idx != -1) { @@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, sp_public_t *function; if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE) { - smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name); + g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name); } } } @@ -106,18 +107,18 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr if (error) { - smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); + g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); } else { - smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); + g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); } - smcore.LogError("[SM] %s", buffer); + g_Logger.LogError("[SM] %s", buffer); IPluginDebugInfo *pDebug; if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL) { - smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); - smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", + g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); + g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", _GetPluginIndex(pContext)); return; } @@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr const char *name; if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE) { - smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name); + g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name); } else { - smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr); + g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr); } } @@ -139,7 +140,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro if (n_err != SP_ERROR_NATIVE) { - smcore.LogError("[SM] Plugin encountered error %d: %s", + g_Logger.LogError("[SM] Plugin encountered error %d: %s", n_err, error->GetErrorString()); } @@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro const char *custerr; if ((custerr=error->GetCustomErrorString()) != NULL) { - smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr); + g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr); } else { - smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname); + g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname); } } if (!error->DebugInfoAvailable()) { - smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); - smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", + g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); + g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", _GetPluginIndex(ctx)); return; } CallStackInfo stk_info; int i = 0; - smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname); + g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname); while (error->GetTraceInfo(&stk_info)) { - smcore.LogError("[SM] [%d] Line %d, %s::%s()", + g_Logger.LogError("[SM] [%d] Line %d, %s::%s()", i++, stk_info.line, stk_info.filename, diff --git a/core/logic/ExtensionSys.cpp b/core/logic/ExtensionSys.cpp index 87f3c5e6..be327768 100644 --- a/core/logic/ExtensionSys.cpp +++ b/core/logic/ExtensionSys.cpp @@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn { if (bErrorOnMissing || libsys->IsPathFile(p->GetPath())) { - smcore.LogError("[SM] Unable to load extension \"%s\": %s", path, error); + logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error); } p->SetError(error); @@ -1360,6 +1360,24 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount, } } +void CExtensionManager::CallOnCoreMapEnd() +{ + IExtensionInterface *pAPI; + List::iterator iter; + + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + { + if ((pAPI = (*iter)->GetAPI()) == NULL) + { + continue; + } + if (pAPI->GetExtensionVersion() > 7) + { + pAPI->OnCoreMapEnd(); + } + } +} + const CVector *CExtensionManager::ListExtensions() { CVector *list = new CVector(); diff --git a/core/logic/ExtensionSys.h b/core/logic/ExtensionSys.h index 76dab140..33a40dcd 100644 --- a/core/logic/ExtensionSys.h +++ b/core/logic/ExtensionSys.h @@ -173,6 +173,7 @@ public: void AddLibrary(IExtension *pSource, const char *library); bool LibraryExists(const char *library); void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax); + void CallOnCoreMapEnd(); void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface); const CVector *ListExtensions(); void FreeExtensionList(const CVector *list); diff --git a/core/logic/GameConfigs.cpp b/core/logic/GameConfigs.cpp index f13e9d30..8c122425 100644 --- a/core/logic/GameConfigs.cpp +++ b/core/logic/GameConfigs.cpp @@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n if (error[0] != '\0') { m_IgnoreLevel = 1; - smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); - smcore.LogError("[SM] %s", error); + logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); + logger->LogError("[SM] %s", error); } else { m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY; } @@ -335,8 +335,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n { if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0) { - smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile); - smcore.LogError("[SM] Unrecognized platform \"%s\"", name); + logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile); + logger->LogError("[SM] Unrecognized platform \"%s\"", name); } m_IgnoreLevel = 1; } @@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key } else { - smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile); + logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile); } } else if (strcmp(key, "signature") == 0) { strncopy(m_AddressSignature, value, sizeof(m_AddressSignature)); @@ -503,7 +503,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0) && (!m_Offsets.retrieve(m_offset))) { - smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", + logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", m_Class, m_Prop, m_CurFile, @@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) void *final_addr = NULL; if (addrInBase == NULL) { - smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", + logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", s_TempSig.library, m_CurFile); } @@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) if (VirtualQuery(addrInBase, &mem, sizeof(mem))) final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]); else - smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); + logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); #elif defined PLATFORM_POSIX Dl_info info; /* GNU only: returns 0 on error, inconsistent! >:[ */ @@ -585,12 +585,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) final_addr = dlsym(handle, &s_TempSig.sig[1]); dlclose(handle); } else { - smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", + logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", s_TempSig.library, m_File); } } else { - smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", + logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); } @@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) { const char *msg = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path); - smcore.LogError("[SM] Error %d on line %d, col %d: %s", + logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path); + logger->LogError("[SM] Error %d on line %d, col %d: %s", err, state.line, state.col, @@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) { const char *msg = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); - smcore.LogError("[SM] Error %d on line %d, col %d: %s", + logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); + logger->LogError("[SM] Error %d on line %d, col %d: %s", err, state.line, state.col, @@ -1082,6 +1082,7 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon } pConfig = new CGameConfig(file); + pConfig->AddRef(); /* :HACKHACK: Don't parse the main config file */ bool retval = true; diff --git a/core/logic/HandleSys.cpp b/core/logic/HandleSys.cpp index 2c43b9cc..4ec90627 100644 --- a/core/logic/HandleSys.cpp +++ b/core/logic/HandleSys.cpp @@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa } #define HANDLE_LOG_VERY_BAD(message, ...) \ - smcore.LogFatal(message, ##__VA_ARGS__); \ - smcore.LogError(message, ##__VA_ARGS__); + logger->LogFatal(message, ##__VA_ARGS__); \ + logger->LogError(message, ##__VA_ARGS__); bool HandleSystem::TryAndFreeSomeHandles() { diff --git a/core/logic/Logger.cpp b/core/logic/Logger.cpp new file mode 100644 index 00000000..c522b56d --- /dev/null +++ b/core/logic/Logger.cpp @@ -0,0 +1,551 @@ +/** + * vim: set ts=4 sw=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include +#include +#include "Logger.h" +#include +#include + +Logger g_Logger; + +/** + * :TODO: This should be creating the log folder if it doesn't exist + */ + +ConfigResult Logger::OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) +{ + if (strcasecmp(key, "Logging") == 0) + { + bool state; + + if (strcasecmp(value, "on") == 0) + { + state = true; + } else if (strcasecmp(value, "off") == 0) { + state = false; + } else { + smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\""); + return ConfigResult_Reject; + } + + if (source == ConfigSource_Console) + { + state ? EnableLogging() : DisableLogging(); + } else { + m_InitialState = state; + } + + return ConfigResult_Accept; + } else if (strcasecmp(key, "LogMode") == 0) { + if (strcasecmp(value, "daily") == 0) + { + m_Mode = LoggingMode_Daily; + } else if (strcasecmp(value, "map") == 0) { + m_Mode = LoggingMode_PerMap; + } else if (strcasecmp(value, "game") == 0) { + m_Mode = LoggingMode_Game; + } else { + smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]"); + return ConfigResult_Reject; + } + + return ConfigResult_Accept; + } + + return ConfigResult_Ignore; +} + +void Logger::OnSourceModStartup(bool late) +{ + InitLogger(m_Mode); +} + +void Logger::OnSourceModAllShutdown() +{ + CloseLogger(); +} + +void Logger::OnSourceModLevelChange(const char *mapName) +{ + MapChange(mapName); +} + +void Logger::_NewMapFile() +{ + if (!m_Active) + { + return; + } + + /* Append "Log file closed" to previous log file */ + _CloseFile(); + + char _filename[256]; + int i = 0; + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + while (true) + { + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i); + FILE *fp = fopen(_filename, "r"); + if (!fp) + { + break; + } + fclose(fp); + i++; + } + m_NrmFileName.assign(_filename); + + FILE *fp = fopen(m_NrmFileName.c_str(), "w"); + if (!fp) + { + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; + return; + } else { + char date[32]; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); + fclose(fp); + } +} + +void Logger::_CloseFile() +{ + if (!m_Active) + { + return; + } + + FILE *fp = NULL; + if (!m_NrmFileName.empty()) + { + fp = fopen(m_NrmFileName.c_str(), "r+"); + if (fp) + { + fseek(fp, 0, SEEK_END); + LogMessage("Log file closed."); + fclose(fp); + } + m_NrmFileName.clear(); + } + + if (!m_ErrMapStart) + { + return; + } + fp = fopen(m_ErrFileName.c_str(), "r+"); + if (fp) + { + fseek(fp, 0, SEEK_END); + LogError("Error log file session closed."); + fclose(fp); + } + m_ErrFileName.clear(); +} + +void Logger::InitLogger(LoggingMode mode) +{ + m_Mode = mode; + m_Active = m_InitialState; + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + m_NrmCurDay = curtime->tm_mday; + m_ErrCurDay = curtime->tm_mday; + + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrFileName.assign(_filename); + + switch (m_Mode) + { + case LoggingMode_PerMap: + { + if (!m_Active) + { + m_DelayedStart = true; + } + break; + } + case LoggingMode_Daily: + { + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_NrmFileName.assign(_filename); + m_DailyPrintHdr = true; + break; + } + default: + { + /* do nothing... */ + break; + } + } +} + +void Logger::CloseLogger() +{ + _CloseFile(); +} + +void Logger::LogToOpenFile(FILE *fp, const char *msg, ...) +{ + if (!m_Active) + { + return; + } + + va_list ap; + va_start(ap, msg); + LogToOpenFileEx(fp, msg, ap); + va_end(ap); +} + +void Logger::LogToFileOnly(FILE *fp, const char *msg, ...) +{ + if (!m_Active) + { + return; + } + + va_list ap; + va_start(ap, msg); + LogToFileOnlyEx(fp, msg, ap); + va_end(ap); +} + +void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) +{ + if (!m_Active) + { + return; + } + + static ConVar *sv_logecho = smcore.FindConVar("sv_logecho"); + + char buffer[3072]; + smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); + + char date[32]; + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + + fprintf(fp, "L %s: %s\n", date, buffer); + + if (!sv_logecho || smcore.GetCvarBool(sv_logecho)) + { + static char conBuffer[4096]; + smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer); + smcore.ConPrint(conBuffer); + } +} + +void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) +{ + if (!m_Active) + { + return; + } + + char buffer[3072]; + smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); + + char date[32]; + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + + fprintf(fp, "L %s: %s\n", date, buffer); + fflush(fp); +} + +void Logger::LogMessage(const char *vafmt, ...) +{ + va_list ap; + va_start(ap, vafmt); + LogMessageEx(vafmt, ap); + va_end(ap); +} + +void Logger::LogMessageEx(const char *vafmt, va_list ap) +{ + if (!m_Active) + { + return; + } + + if (m_Mode == LoggingMode_Game) + { + _PrintToGameLog(vafmt, ap); + return; + } + + if (m_DelayedStart) + { + m_DelayedStart = false; + _NewMapFile(); + } + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + FILE *fp = NULL; + if (m_Mode == LoggingMode_PerMap) + { + fp = fopen(m_NrmFileName.c_str(), "a+"); + if (!fp) + { + _NewMapFile(); + fp = fopen(m_NrmFileName.c_str(), "a+"); + if (!fp) + { + goto print_error; + } + } + } else { + if (m_NrmCurDay != curtime->tm_mday) + { + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_NrmFileName.assign(_filename); + m_NrmCurDay = curtime->tm_mday; + m_DailyPrintHdr = true; + } + fp = fopen(m_NrmFileName.c_str(), "a+"); + } + + if (fp) + { + if (m_DailyPrintHdr) + { + char date[32]; + m_DailyPrintHdr = false; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION); + } + LogToOpenFileEx(fp, vafmt, ap); + fclose(fp); + } else { + goto print_error; + } + + return; +print_error: + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; +} + +void Logger::LogError(const char *vafmt, ...) +{ + va_list ap; + va_start(ap, vafmt); + LogErrorEx(vafmt, ap); + va_end(ap); +} + +void Logger::LogErrorEx(const char *vafmt, va_list ap) +{ + if (!m_Active) + { + return; + } + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + if (curtime->tm_mday != m_ErrCurDay) + { + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrFileName.assign(_filename); + m_ErrCurDay = curtime->tm_mday; + m_ErrMapStart = false; + } + + FILE *fp = fopen(m_ErrFileName.c_str(), "a+"); + if (fp) + { + if (!m_ErrMapStart) + { + char date[32]; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod error session started\n", date); + fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrMapStart = true; + } + LogToOpenFileEx(fp, vafmt, ap); + fclose(fp); + } + else + { + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; + return; + } +} + +void Logger::MapChange(const char *mapname) +{ + m_CurMapName.assign(mapname); + + switch (m_Mode) + { + case LoggingMode_Daily: + { + LogMessage("-------- Mapchange to %s --------", mapname); + break; + } + case LoggingMode_PerMap: + { + _NewMapFile(); + break; + } + default: + { + /* Do nothing... */ + break; + } + } + + if (m_ErrMapStart) + { + LogError("Error log file session closed."); + } + m_ErrMapStart = false; +} + +void Logger::_PrintToGameLog(const char *fmt, va_list ap) +{ + char msg[3072]; + size_t len; + + len = vsnprintf(msg, sizeof(msg)-2, fmt, ap); + len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len; + + msg[len++] = '\n'; + msg[len] = '\0'; + + smcore.LogToGame(msg); +} + +const char *Logger::GetLogFileName(LogType type) const +{ + switch (type) + { + case LogType_Normal: + { + return m_NrmFileName.c_str(); + } + case LogType_Error: + { + return m_ErrFileName.c_str(); + } + default: + { + return ""; + } + } +} + +LoggingMode Logger::GetLoggingMode() const +{ + return m_Mode; +} + +void Logger::EnableLogging() +{ + if (m_Active) + { + return; + } + m_Active = true; + LogMessage("[SM] Logging enabled manually by user."); +} + +void Logger::DisableLogging() +{ + if (!m_Active) + { + return; + } + LogMessage("[SM] Logging disabled manually by user."); + m_Active = false; +} + +void Logger::LogFatal(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + LogFatalEx(msg, ap); + va_end(ap); +} + +void Logger::LogFatalEx(const char *msg, va_list ap) +{ + /* :TODO: make this print all pretty-like + * In fact, the pretty log printing function should be abstracted. + * It's already implemented twice which is bad. + */ + + char path[PLATFORM_MAX_PATH]; + + g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); + + FILE *fp = fopen(path, "at"); + if (fp) + { + m_Active = true; + LogToOpenFileEx(fp, msg, ap); + m_Active = false; + fclose(fp); + } +} diff --git a/core/logic/Logger.h b/core/logic/Logger.h new file mode 100644 index 00000000..8d8ebcee --- /dev/null +++ b/core/logic/Logger.h @@ -0,0 +1,111 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_ +#define _INCLUDE_SOURCEMOD_CLOGGER_H_ + +#include +#include + +#include "common_logic.h" + +using namespace SourceHook; + +enum LogType +{ + LogType_Normal, + LogType_Error +}; + +enum LoggingMode +{ + LoggingMode_Daily, + LoggingMode_PerMap, + LoggingMode_Game +}; + +class Logger : public SMGlobalClass, public ILogger +{ +public: + Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), + m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), + m_InitialState(true) + { + } +public: //SMGlobalClass + ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength); + void OnSourceModStartup(bool late); + void OnSourceModAllShutdown(); + void OnSourceModLevelChange(const char *mapName); +public: + void InitLogger(LoggingMode mode); + void CloseLogger(); + void EnableLogging(); + void DisableLogging(); + void LogMessage(const char *msg, ...); + void LogMessageEx(const char *msg, va_list ap); + void LogError(const char *msg, ...); + void LogErrorEx(const char *msg, va_list ap); + void LogFatal(const char *msg, ...); + void LogFatalEx(const char *msg, va_list ap); + void LogToOpenFile(FILE *fp, const char *msg, ...); + void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); + /* This version does not print to console, and is thus thread-safe */ + void LogToFileOnly(FILE *fp, const char *msg, ...); + void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap); + void MapChange(const char *mapname); + const char *GetLogFileName(LogType type) const; + LoggingMode GetLoggingMode() const; +private: + void _CloseFile(); + void _NewMapFile(); + void _PrintToGameLog(const char *fmt, va_list ap); +private: + String m_NrmFileName; + String m_ErrFileName; + String m_CurMapName; + LoggingMode m_Mode; + int m_NrmCurDay; + int m_ErrCurDay; + bool m_ErrMapStart; + bool m_Active; + bool m_DelayedStart; + bool m_DailyPrintHdr; + bool m_InitialState; +}; + +extern Logger g_Logger; + +#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_ diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 2e7f45e4..c53d4fe3 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -42,6 +42,7 @@ #include "GameConfigs.h" #include "common_logic.h" #include "Translator.h" +#include "Logger.h" CPluginManager g_PluginSys; HandleType_t g_PluginType = 0; @@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa { char error[256]; libsys->GetPlatformError(error, sizeof(error)); - smcore.LogError("[SM] Failure reading from plugins path: %s", localpath); - smcore.LogError("[SM] Platform returned error: %s", error); + g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath); + g_Logger.LogError("[SM] Platform returned error: %s", error); return; } @@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de } else { if (bulletinUrl[0] != '\0') { - smcore.Log("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl); + g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl); } else { - smcore.Log("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename()); + g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename()); } } } @@ -1094,7 +1095,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin) if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure) { - smcore.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error); + g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error); pl->SetErrorState( pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(), "%s", @@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass() error[0] = '\0'; if (!RunSecondPass(pPlugin, error, sizeof(error))) { - smcore.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); + g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); pPlugin->SetErrorState(Plugin_Failed, "%s", error); } } diff --git a/core/logic/ShareSys.cpp b/core/logic/ShareSys.cpp index 77769662..ddde22a5 100644 --- a/core/logic/ShareSys.cpp +++ b/core/logic/ShareSys.cpp @@ -375,7 +375,7 @@ PassRef ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nat if (i.found()) return NULL; - Ref entry = Newborn(new Native(pOwner, ntv)); + Ref entry = new Native(pOwner, ntv); m_NtvCache.insert(ntv->name, entry); return entry; } @@ -415,7 +415,7 @@ PassRef ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext()); - entry = Newborn(new Native(owner, fake.take())); + entry = new Native(owner, fake.take()); m_NtvCache.insert(name, entry); return entry; diff --git a/core/logic/Translator.cpp b/core/logic/Translator.cpp index c2910921..a1fdaf42 100644 --- a/core/logic/Translator.cpp +++ b/core/logic/Translator.cpp @@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...) if (!m_FileLogged) { - smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); + logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); m_FileLogged = true; } - smcore.LogError("[SM] %s", buffer); + logger->LogError("[SM] %s", buffer); } void CPhraseFile::ReparseFile() @@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile() msg = m_ParseError.c_str(); } - smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); - smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); + logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); + logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); } const char *code; @@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile() msg = m_ParseError.c_str(); } - smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"", + logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"", code, m_File.c_str()); - smcore.LogError("[SM] Error (line %d, column %d): %s", + logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); @@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase() str_err = m_CustomError.c_str(); } - smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path); - smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); + logger->LogError("[SM] Failed to parse language header file: \"%s\"", path); + logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); } if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang)) { - smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); + logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH; @@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase() if (!m_Languages.size()) { - smcore.LogError("[SM] Fatal error, no languages found! Translation will not work."); + logger->LogError("[SM] Fatal error, no languages found! Translation will not work."); } for (size_t i=0; iLogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name); } return SMCResult_Continue; @@ -1025,11 +1025,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned { if (fail_phrase != NULL) { - smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase); + logger->LogError("[SM] Could not find core phrase: %s", fail_phrase); } else { - smcore.LogError("[SM] Unknown fatal error while translating a core phrase."); + logger->LogError("[SM] Unknown fatal error while translating a core phrase."); } return false; diff --git a/core/logic/common_logic.cpp b/core/logic/common_logic.cpp index 7c988b5f..868f66df 100644 --- a/core/logic/common_logic.cpp +++ b/core/logic/common_logic.cpp @@ -50,6 +50,7 @@ #include "ForwardSys.h" #include "AdminCache.h" #include "ProfileTools.h" +#include "Logger.h" sm_core_t smcore; IHandleSys *handlesys = &g_HandleSys; @@ -72,6 +73,8 @@ ISourcePawnEngine *g_pSourcePawn; ISourcePawnEngine2 *g_pSourcePawn2; CNativeOwner g_CoreNatives; IScriptManager *scripts = &g_PluginSys; +IExtensionSys *extsys = &g_Extensions; +ILogger *logger = &g_Logger; static void AddCorePhraseFile(const char *filename) { @@ -140,6 +143,7 @@ static sm_logic_t logic = &g_Forwards, &g_Admins, NULL, + &g_Logger, -1.0f }; diff --git a/core/logic/common_logic.h b/core/logic/common_logic.h index f008d4e3..45f9fc64 100644 --- a/core/logic/common_logic.h +++ b/core/logic/common_logic.h @@ -53,6 +53,8 @@ extern IPlayerManager *playerhelpers; extern IAdminSystem *adminsys; extern IGameHelpers *gamehelpers; extern IScriptManager *scripts; +extern IExtensionSys *extsys; +extern ILogger *logger; #endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */ diff --git a/core/logic/intercom.h b/core/logic/intercom.h index 5d86853d..2fa40410 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -52,7 +52,7 @@ using namespace SourceHook; * Add 1 to the RHS of this expression to bump the intercom file * This is to prevent mismatching core/logic binaries */ -#define SM_LOGIC_MAGIC (0x0F47C0DE - 28) +#define SM_LOGIC_MAGIC (0x0F47C0DE - 29) #if defined SM_LOGIC class IVEngineServer @@ -211,6 +211,15 @@ public: virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0; virtual const CVector *ListExtensions() = 0; virtual void FreeExtensionList(const CVector *list) = 0; + virtual void CallOnCoreMapEnd() = 0; +}; + +class ILogger +{ +public: + virtual void LogMessage(const char *msg, ...) = 0; + virtual void LogError(const char *msg, ...) = 0; + virtual void LogFatal(const char *msg, ...) = 0; }; class AutoPluginList @@ -273,13 +282,10 @@ struct sm_core_t ConVar * (*FindConVar)(const char*); unsigned int (*strncopy)(char*, const char*, size_t); char * (*TrimWhitespace)(char *, size_t &); - void (*LogError)(const char*, ...); - void (*LogFatal)(const char*, ...); - void (*Log)(const char*, ...); - void (*LogToFile)(FILE *fp, const char*, ...); void (*LogToGame)(const char *message); void (*ConPrint)(const char *message); const char * (*GetCvarString)(ConVar*); + bool (*GetCvarBool)(ConVar*); size_t (*Format)(char*, size_t, const char*, ...); size_t (*FormatArgs)(char*, size_t, const char*,va_list ap); bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **, @@ -325,7 +331,7 @@ struct sm_logic_t char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool); size_t (*DecodeHexString)(unsigned char *, size_t, const char *); IGameConfig * (*GetCoreGameConfig)(); - bool (*OnLogPrint)(const char *msg); // true to supercede + bool (*OnLogPrint)(const char *msg); // true to supersede IDebugListener *debugger; void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...); void (*AddNatives)(sp_nativeinfo_t *natives); @@ -339,6 +345,7 @@ struct sm_logic_t IForwardManager *forwardsys; IAdminSystem *adminsys; IdentityToken_t *core_ident; + ILogger *logger; float sentinel; }; diff --git a/core/logic/smn_adt_trie.cpp b/core/logic/smn_adt_trie.cpp index ab70f8cc..989df0f4 100644 --- a/core/logic/smn_adt_trie.cpp +++ b/core/logic/smn_adt_trie.cpp @@ -163,7 +163,7 @@ private: cell_t data_; }; -struct CellTrie : public ke::Refcounted +struct CellTrie { StringHashMap map; }; @@ -204,8 +204,7 @@ public: //IHandleTypeDispatch { if (type == htCellTrie) { - CellTrie *pTrie = (CellTrie *)object; - pTrie->Release(); + delete (CellTrie *)object; } else { TrieSnapshot *snapshot = (TrieSnapshot *)object; delete snapshot; diff --git a/core/smn_core.cpp b/core/logic/smn_core.cpp similarity index 88% rename from core/smn_core.cpp rename to core/logic/smn_core.cpp index 4d301db4..50eb0e5d 100644 --- a/core/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -32,14 +32,14 @@ #include #include #include -#include "sm_stringutil.h" -#include "sm_globals.h" -#include "sourcemod.h" -#include "LibrarySys.h" -#include "TimerSys.h" +#include "common_logic.h" #include "Logger.h" + +#include +#include + +#include #include -#include "logic_bridge.h" #if defined PLATFORM_WINDOWS #include @@ -50,9 +50,11 @@ #endif HandleType_t g_PlIter; -ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules"); + IForward *g_OnLogAction = NULL; +static ConVar *sm_datetime_format = NULL; + class CoreNativeHelpers : public SMGlobalClass, public IHandleTypeDispatch @@ -75,6 +77,8 @@ public: Param_Cell, Param_Cell, Param_String); + + sm_datetime_format = smcore.FindConVar("sm_datetime_format"); } void OnHandleDestroy(HandleType_t type, void *object) { @@ -119,14 +123,14 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess g_Logger.LogMessage("[%s] %s", logtag, message); } - -static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) + + static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) { char buffer[512]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1); if (pContext->GetLastNativeError() == SP_ERROR_NONE) { @@ -138,7 +142,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) static cell_t GetTime(IPluginContext *pContext, const cell_t *params) { - time_t t = GetAdjustedTime(); + time_t t = g_pSM->GetAdjustedTime(); cell_t *addr; pContext->LocalToPhysAddr(params[1], &addr); @@ -168,14 +172,14 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params) if (format == NULL) { - format = const_cast(sm_datetime_format.GetString()); + format = const_cast(smcore.GetCvarString(sm_datetime_format)); } #if defined SUBPLATFORM_SECURECRT _invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter); #endif - time_t t = (params[4] == -1) ? GetAdjustedTime() : (time_t)params[4]; + time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4]; size_t written = strftime(buffer, params[2], format, localtime(&t)); #if defined SUBPLATFORM_SECURECRT @@ -384,7 +388,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params) { char buffer[2048]; - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { pPlugin->SetErrorState(Plugin_Error, "%s", str); @@ -433,14 +437,14 @@ static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params) static char temp_file[PLATFORM_MAX_PATH]; char *ptr; - g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename()); + libsys->GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename()); if ((ptr = strstr(temp_str, ".smx")) != NULL) { *ptr = '\0'; } /* We have the raw filename! */ - UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str); + g_pSM->Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str); cfg = temp_file; } @@ -506,8 +510,8 @@ static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params) static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params) { char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -527,7 +531,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params) pContext->LocalToString(params[1], &file); char path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file); FILE *fp = fopen(path, "at"); if (!fp) @@ -536,8 +540,8 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params) } char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -560,7 +564,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params) pContext->LocalToString(params[1], &file); char path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file); FILE *fp = fopen(path, "at"); if (!fp) @@ -569,8 +573,8 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params) } char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -653,10 +657,10 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params) char default_message[255]; SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3); if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0') { - UTIL_Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name); + g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name); msg = default_message; } pPlugin->SetErrorState(Plugin_Error, "%s", msg); @@ -743,19 +747,19 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params) REGISTER_NATIVES(coreNatives) { - {"AutoExecConfig", AutoExecConfig}, - {"GetPluginFilename", GetPluginFilename}, - {"GetPluginInfo", GetPluginInfo}, - {"GetPluginIterator", GetPluginIterator}, - {"GetPluginStatus", GetPluginStatus}, - {"GetSysTickCount", GetSysTickCount}, + {"ThrowError", ThrowError}, {"GetTime", GetTime}, - {"IsPluginDebugging", IsPluginDebugging}, + {"FormatTime", FormatTime}, + {"GetPluginIterator", GetPluginIterator}, {"MorePlugins", MorePlugins}, {"ReadPlugin", ReadPlugin}, - {"ThrowError", ThrowError}, + {"GetPluginStatus", GetPluginStatus}, + {"GetPluginFilename", GetPluginFilename}, + {"IsPluginDebugging", IsPluginDebugging}, + {"GetPluginInfo", GetPluginInfo}, {"SetFailState", SetFailState}, - {"FormatTime", FormatTime}, + {"GetSysTickCount", GetSysTickCount}, + {"AutoExecConfig", AutoExecConfig}, {"MarkNativeAsOptional", MarkNativeAsOptional}, {"RegPluginLibrary", RegPluginLibrary}, {"LibraryExists", LibraryExists}, @@ -770,5 +774,4 @@ REGISTER_NATIVES(coreNatives) {"LoadFromAddress", LoadFromAddress}, {"StoreToAddress", StoreToAddress}, {NULL, NULL}, -}; - +}; \ No newline at end of file diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 26575acf..82430e52 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -38,6 +38,21 @@ #include #include #include "common_logic.h" +#include "Logger.h" + +#if defined PLATFORM_WINDOWS +#include + +#define FPERM_U_READ 0x0100 /* User can read. */ +#define FPERM_U_WRITE 0x0080 /* User can write. */ +#define FPERM_U_EXEC 0x0040 /* User can exec. */ +#define FPERM_G_READ 0x0020 /* Group can read. */ +#define FPERM_G_WRITE 0x0010 /* Group can write. */ +#define FPERM_G_EXEC 0x0008 /* Group can exec. */ +#define FPERM_O_READ 0x0004 /* Anyone can read. */ +#define FPERM_O_WRITE 0x0002 /* Anyone can write. */ +#define FPERM_O_EXEC 0x0001 /* Anyone can exec. */ +#endif HandleType_t g_FileType; HandleType_t g_DirType; @@ -465,6 +480,31 @@ static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params) #endif } +static cell_t sm_SetFilePermissions(IPluginContext *pContext, const cell_t *params) +{ + char *name; + char realpath[PLATFORM_MAX_PATH]; + + pContext->LocalToString(params[1], &name); + g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); + +#if defined PLATFORM_WINDOWS + int mask = 0; + if (params[2] & FPERM_U_WRITE || params[2] & FPERM_G_WRITE || params[2] & FPERM_O_WRITE) + { + mask |= _S_IWRITE; + } + if (params[2] & FPERM_U_READ || params[2] & FPERM_G_READ || params[2] & FPERM_O_READ || + params[2] & FPERM_U_EXEC || params[2] & FPERM_G_EXEC || params[2] & FPERM_O_EXEC) + { + mask |= _S_IREAD; + } + return _chmod(realpath, mask) == 0; +#else + return chmod(realpath, params[2]) == 0; +#endif +} + static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params) { char *name; @@ -598,7 +638,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.Log("[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -616,7 +656,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.LogError("[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -669,7 +709,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.LogToFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -699,7 +739,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params) return 0; } - smcore.LogToFile(pFile, "%s", buffer); + g_Logger.LogToOpenFile(pFile, "%s", buffer); return 1; } @@ -971,5 +1011,6 @@ REGISTER_NATIVES(filesystem) {"AddGameLogHook", sm_AddGameLogHook}, {"RemoveGameLogHook", sm_RemoveGameLogHook}, {"CreateDirectory", sm_CreateDirectory}, + {"SetFilePermissions", sm_SetFilePermissions}, {NULL, NULL}, }; diff --git a/core/logic/smn_maplists.cpp b/core/logic/smn_maplists.cpp index 00a19a95..9faba5d8 100644 --- a/core/logic/smn_maplists.cpp +++ b/core/logic/smn_maplists.cpp @@ -202,8 +202,8 @@ public: { errmsg = "Unknown error"; } - smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile); - smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg); + logger->LogError("[SM] Could not parse file \"%s\"", m_ConfigFile); + logger->LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg); } else { diff --git a/core/logic/smn_players.cpp b/core/logic/smn_players.cpp index 55d4fcbf..47288f0a 100644 --- a/core/logic/smn_players.cpp +++ b/core/logic/smn_players.cpp @@ -120,7 +120,7 @@ public: //ICommandTargetProcessor Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL); AutoHandleCloner ahc(hndl, sec); if (ahc.getClone() == BAD_HANDLE) { - smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__); + logger->LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__); delete array; return false; } diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 057f660c..13fba9fe 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -86,6 +86,7 @@ IExtensionSys *extsys; IHandleSys *handlesys; IForwardManager *forwardsys; IAdminSystem *adminsys; +ILogger *logger; class VEngineServer_Logic : public IVEngineServer_Logic { @@ -251,46 +252,13 @@ static VPlayerInfo_Logic logic_playerinfo; static ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)"); static ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection"); +static ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules"); static ConVar *find_convar(const char *name) { return icvar->FindVar(name); } -static void log_error(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - g_Logger.LogErrorEx(fmt, ap); - va_end(ap); -} - -static void log_fatal(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - g_Logger.LogFatalEx(fmt, ap); - va_end(ap); -} - -static void log_message(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - g_Logger.LogMessageEx(fmt, ap); - va_end(ap); -} - -static void log_to_file(FILE *fp, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - g_Logger.LogToOpenFileEx(fp, fmt, ap); - va_end(ap); -} - static void log_to_game(const char *message) { Engine_LogPrintWrapper(message); @@ -306,6 +274,11 @@ static const char *get_cvar_string(ConVar* cvar) return cvar->GetString(); } +static bool get_cvar_bool(ConVar* cvar) +{ + return cvar->GetBool(); +} + static bool get_game_name(char *buffer, size_t maxlength) { KeyValues *pGameInfo = new KeyValues("GameInfo"); @@ -561,13 +534,10 @@ static sm_core_t core_bridge = find_convar, strncopy, UTIL_TrimWhitespace, - log_error, - log_fatal, - log_message, - log_to_file, log_to_game, conprint, get_cvar_string, + get_cvar_bool, UTIL_Format, UTIL_FormatArgs, gnprintf, @@ -636,6 +606,7 @@ void InitLogicBridge() handlesys = logicore.handlesys; forwardsys = logicore.forwardsys; adminsys = logicore.adminsys; + logger = logicore.logger; } bool StartLogicBridge(char *error, size_t maxlength) diff --git a/core/logic_bridge.h b/core/logic_bridge.h index 76372a7c..34f6de1a 100644 --- a/core/logic_bridge.h +++ b/core/logic_bridge.h @@ -48,5 +48,6 @@ extern IExtensionSys *extsys; extern IHandleSys *handlesys; extern IForwardManager *forwardsys; extern IAdminSystem *adminsys; +extern ILogger *logger; #endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */ diff --git a/core/smn_console.cpp b/core/smn_console.cpp index d92fc492..eda2529b 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -1216,7 +1216,7 @@ static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params) if (strcasecmp(name, "sm") == 0) { - g_Logger.LogError("Request to register \"sm\" command denied."); + logger->LogError("Request to register \"sm\" command denied."); return 0; } diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index 306965a8..15a679a4 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -167,7 +167,7 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface) /* This shouldn't happen */ if (!iface) { - g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater."); + logger->LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater."); return; } diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index f31b7af6..5d68eb1d 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -395,6 +395,7 @@ void SourceModBase::LevelShutdown() { g_pOnMapEnd->Execute(NULL); } + extsys->CallOnCoreMapEnd(); g_Timers.RemoveMapChangeTimers(); @@ -572,9 +573,9 @@ void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...) if (tag) { - g_Logger.LogMessage("[%s] %s", tag, buffer); + logger->LogMessage("[%s] %s", tag, buffer); } else { - g_Logger.LogMessage("%s", buffer); + logger->LogMessage("%s", buffer); } } @@ -591,9 +592,9 @@ void SourceModBase::LogError(IExtension *pExt, const char *format, ...) if (tag) { - g_Logger.LogError("[%s] %s", tag, buffer); + logger->LogError("[%s] %s", tag, buffer); } else { - g_Logger.LogError("%s", buffer); + logger->LogError("%s", buffer); } } diff --git a/extensions/clientprefs/extension.cpp b/extensions/clientprefs/extension.cpp index 96a3173b..7ff5eee2 100644 --- a/extensions/clientprefs/extension.cpp +++ b/extensions/clientprefs/extension.cpp @@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect() char error[256]; int errCode = 0; - Database = Newborn(Driver->Connect(DBInfo, true, error, sizeof(error))); + Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error))); if (!Database) { diff --git a/extensions/regex/extension.cpp b/extensions/regex/extension.cpp index 5f7b6f17..7265a056 100644 --- a/extensions/regex/extension.cpp +++ b/extensions/regex/extension.cpp @@ -106,7 +106,7 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params) if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None) { - return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err); + return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err); } if (!x) @@ -159,7 +159,7 @@ static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params) if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None) { - return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err); + return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err); } if (!x) diff --git a/gamedata/sdkhooks.games/game.fof.txt b/gamedata/sdkhooks.games/game.fof.txt index 53ab5a4a..be2cf534 100644 --- a/gamedata/sdkhooks.games/game.fof.txt +++ b/gamedata/sdkhooks.games/game.fof.txt @@ -12,9 +12,9 @@ } "FireBullets" { - "windows" "112" - "linux" "113" - "mac" "113" + "windows" "113" + "linux" "114" + "mac" "114" } "OnTakeDamage" { @@ -24,15 +24,15 @@ } "PreThink" { - "windows" "331" - "linux" "332" - "mac" "332" + "windows" "333" + "linux" "334" + "mac" "334" } "PostThink" { - "windows" "332" - "linux" "333" - "mac" "333" + "windows" "334" + "linux" "335" + "mac" "335" } "SetTransmit" { @@ -78,39 +78,39 @@ } "VPhysicsUpdate" { - "windows" "157" - "linux" "158" - "mac" "158" + "windows" "158" + "linux" "159" + "mac" "159" } "Weapon_CanSwitchTo" { - "windows" "265" - "linux" "266" - "mac" "266" + "windows" "267" + "linux" "268" + "mac" "268" } "Weapon_CanUse" { - "windows" "259" - "linux" "260" - "mac" "260" + "windows" "261" + "linux" "262" + "mac" "262" } "Weapon_Drop" + { + "windows" "264" + "linux" "265" + "mac" "265" + } + "Weapon_Equip" { "windows" "262" "linux" "263" "mac" "263" } - "Weapon_Equip" - { - "windows" "260" - "linux" "261" - "mac" "261" - } "Weapon_Switch" { - "windows" "263" - "linux" "264" - "mac" "264" + "windows" "265" + "linux" "266" + "mac" "266" } } } diff --git a/gamedata/sdkhooks.games/game.nmrih.txt b/gamedata/sdkhooks.games/game.nmrih.txt index 3705bf19..4eedd98b 100644 --- a/gamedata/sdkhooks.games/game.nmrih.txt +++ b/gamedata/sdkhooks.games/game.nmrih.txt @@ -30,9 +30,9 @@ } "PreThink" { - "windows" "344" - "linux" "345" - "mac" "345" + "windows" "345" + "linux" "346" + "mac" "346" } "PostThink" { diff --git a/gamedata/sdktools.games/engine.sdk2013.txt b/gamedata/sdktools.games/engine.sdk2013.txt index a02236eb..f0a13025 100644 --- a/gamedata/sdktools.games/engine.sdk2013.txt +++ b/gamedata/sdktools.games/engine.sdk2013.txt @@ -48,21 +48,6 @@ } } - /* No longer necessary. Remove later. */ - "#default" - { - "Signatures" - { - "EntityFactory" - { - "library" "server" - "windows" "\xB8\x01\x00\x00\x00\x84\x2A\x2A\x2A\x2A\x2A\x75\x1D\x09\x2A\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x04\xB8\x2A\x2A\x2A\x2A\xC3" - "linux" "@_Z23EntityFactoryDictionaryv" - "mac" "@_Z23EntityFactoryDictionaryv" - } - } - } - /* SetUserInfo data */ "#default" { diff --git a/gamedata/sdktools.games/game.fof.txt b/gamedata/sdktools.games/game.fof.txt index 186a700d..68e56046 100644 --- a/gamedata/sdktools.games/game.fof.txt +++ b/gamedata/sdktools.games/game.fof.txt @@ -131,57 +131,57 @@ { "GiveNamedItem" { - "windows" "400" - "linux" "401" - "mac" "401" + "windows" "402" + "linux" "403" + "mac" "403" } "RemovePlayerItem" + { + "windows" "271" + "linux" "272" + "mac" "272" + } + "Weapon_GetSlot" { "windows" "269" "linux" "270" "mac" "270" } - "Weapon_GetSlot" - { - "windows" "267" - "linux" "268" - "mac" "268" - } "Ignite" { - "windows" "208" - "linux" "209" - "mac" "209" + "windows" "210" + "linux" "211" + "mac" "211" } "Extinguish" { - "windows" "212" - "linux" "213" - "mac" "213" + "windows" "214" + "linux" "215" + "mac" "215" } "Teleport" { - "windows" "108" - "linux" "109" - "mac" "109" + "windows" "109" + "linux" "110" + "mac" "110" } "CommitSuicide" { - "windows" "442" - "linux" "442" - "mac" "442" + "windows" "444" + "linux" "444" + "mac" "444" } "GetVelocity" { - "windows" "140" - "linux" "141" - "mac" "141" + "windows" "141" + "linux" "142" + "mac" "142" } "EyeAngles" { - "windows" "131" - "linux" "132" - "mac" "132" + "windows" "132" + "linux" "133" + "mac" "133" } "AcceptInput" { @@ -197,9 +197,9 @@ } "WeaponEquip" { - "windows" "260" - "linux" "261" - "mac" "261" + "windows" "262" + "linux" "263" + "mac" "263" } "Activate" { @@ -209,15 +209,15 @@ } "PlayerRunCmd" { - "windows" "418" - "linux" "419" - "mac" "419" + "windows" "420" + "linux" "421" + "mac" "421" } "GiveAmmo" { - "windows" "251" - "linux" "252" - "mac" "252" + "windows" "253" + "linux" "254" + "mac" "254" } } } diff --git a/gamedata/sdktools.games/game.nmrih.txt b/gamedata/sdktools.games/game.nmrih.txt index 3ee6c98e..a9c5e7f2 100644 --- a/gamedata/sdktools.games/game.nmrih.txt +++ b/gamedata/sdktools.games/game.nmrih.txt @@ -131,9 +131,9 @@ { "GiveNamedItem" { - "windows" "412" - "linux" "413" - "mac" "413" + "windows" "413" + "linux" "414" + "mac" "414" } "RemovePlayerItem" { @@ -167,9 +167,9 @@ } "CommitSuicide" { - "windows" "451" - "linux" "451" - "mac" "451" + "windows" "452" + "linux" "452" + "mac" "452" } "GetVelocity" { @@ -209,9 +209,9 @@ } "PlayerRunCmd" { - "windows" "430" - "linux" "431" - "mac" "431" + "windows" "431" + "linux" "432" + "mac" "432" } "GiveAmmo" { diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 4da32671..c25ed8ac 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -376,6 +376,15 @@ native bool:RemoveDir(const String:path[]); */ native bool:CreateDirectory(const String:path[], mode); +/** + * Changes a file or directories permissions. + * + * @param path Path to the file. + * @param mode Permissions to set. + * @return True on success, false otherwise. + */ +native bool:SetFilePermissions(const String:path[], mode); + /** * Returns a file timestamp as a unix timestamp. * diff --git a/plugins/include/tf2.inc b/plugins/include/tf2.inc index 743675ee..7e079be4 100644 --- a/plugins/include/tf2.inc +++ b/plugins/include/tf2.inc @@ -153,6 +153,10 @@ enum TFCond TFCond_HalloweenTiny, TFCond_HalloweenInHell, TFCond_HalloweenGhostMode, + + TFCond_DodgeChance = 79, + TFCond_Parachute, + TFCond_BlastJumping, }; const Float:TFCondDuration_Infinite = -1.0; @@ -447,5 +451,6 @@ public __ext_tf2_SetNTVOptional() MarkNativeAsOptional("TF2_GetClass"); MarkNativeAsOptional("TF2_IsPlayerInDuel"); MarkNativeAsOptional("TF2_IsHolidayActive"); + MarkNativeAsOptional("TF2_RemoveWearable"); } #endif diff --git a/plugins/include/tf2_stocks.inc b/plugins/include/tf2_stocks.inc index e0f250f6..43f69e24 100644 --- a/plugins/include/tf2_stocks.inc +++ b/plugins/include/tf2_stocks.inc @@ -249,6 +249,7 @@ enum { TF_WEAPON_SPELLBOOK, TF_WEAPON_SPELLBOOK_PROJECTILE, TF_WEAPON_SNIPERRIFLE_CLASSIC, + TF_WEAPON_PARACHUTE, }; // TF2 Weapon Loadout Slots diff --git a/public/IExtensionSys.h b/public/IExtensionSys.h index 3c63e7e3..8e008b0e 100644 --- a/public/IExtensionSys.h +++ b/public/IExtensionSys.h @@ -135,8 +135,9 @@ namespace SourceMod * * V6 - added TestFeature() to IShareSys. * V7 - added OnDependenciesDropped() to IExtensionInterface. + * V8 - added OnCoreMapEnd() to IExtensionInterface. */ - #define SMINTERFACE_EXTENSIONAPI_VERSION 7 + #define SMINTERFACE_EXTENSIONAPI_VERSION 8 /** * @brief The interface an extension must expose. @@ -325,6 +326,15 @@ namespace SourceMod virtual void OnDependenciesDropped() { } + + /** + * @brief Called on level shutdown + * + */ + + virtual void OnCoreMapEnd() + { + } }; /** diff --git a/public/amtl/am-refcounting-threadsafe.h b/public/amtl/am-refcounting-threadsafe.h index a37b39d4..785ba62b 100644 --- a/public/amtl/am-refcounting-threadsafe.h +++ b/public/amtl/am-refcounting-threadsafe.h @@ -35,12 +35,15 @@ namespace ke { +// See the comment above Refcounted for more information. This class is +// identical, except changing the reference count is guaranteed to be atomic +// with respect to other threads changing the reference count. template class RefcountedThreadsafe { public: RefcountedThreadsafe() - : refcount_(1) + : refcount_(0) { } diff --git a/public/amtl/am-refcounting.h b/public/amtl/am-refcounting.h index 71a6f554..028d6df5 100644 --- a/public/amtl/am-refcounting.h +++ b/public/amtl/am-refcounting.h @@ -37,18 +37,28 @@ namespace ke { template class Ref; -// Holds a refcounted T without addrefing it. This is similar to PassRef<> -// below, but is intended only for freshly allocated objects which start -// with reference count 1, and we don't want to add an extra ref just by -// assigning to PassRef<> or Ref<>. +// Objects in AMTL inheriting from Refcounted will have an initial refcount +// of 0. However, in some systems (such as COM), the initial refcount is 1, +// or functions may return raw pointers that have been AddRef'd. In these +// cases it would be a mistake to use Ref<> or PassRef<>, since the object +// would leak an extra reference. +// +// This container holds a refcounted object without addrefing it. This is +// intended only for interacting with functions which return an object that +// has been manually AddRef'd. Note that this will perform a Release(), so +// so it is necessary to assign it to retain the object. template -class Newborn +class AlreadyRefed { public: - Newborn(T *t) + AlreadyRefed(T *t) : thing_(t) { } + ~AlreadyRefed() { + if (thing_) + thing_->Release(); + } T *release() const { return ReturnAndVoid(thing_); @@ -59,10 +69,10 @@ class Newborn }; template -static inline Newborn -NoAddRef(T *t) +static inline AlreadyRefed +AdoptRef(T *t) { - return Newborn(t); + return AlreadyRefed(t); } // When returning a value, we'd rather not be needlessly changing the refcount, @@ -81,7 +91,14 @@ class PassRef { } - PassRef(const Newborn &other) + PassRef(const AlreadyRefed &other) + : thing_(other.release()) + { + // Don't addref, newborn means already addref'd. + } + + template + PassRef(const AlreadyRefed &other) : thing_(other.release()) { // Don't addref, newborn means already addref'd. @@ -134,7 +151,7 @@ class PassRef private: // Disallowed operators. PassRef &operator =(T *other); - PassRef &operator =(Newborn &other); + PassRef &operator =(AlreadyRefed &other); void AddRef() { if (thing_) @@ -149,13 +166,18 @@ class PassRef mutable T *thing_; }; -// Classes which are refcounted should inherit from this. +// Classes which are refcounted should inherit from this. Note that reference +// counts start at 0 in AMTL, rather than 1. This avoids the complexity of +// having to adopt the initial ref upon allocation. However, this also means +// invoking Release() on a newly allocated object is illegal. Newborn objects +// must either be assigned to a Ref or PassRef (NOT an AdoptRef/AlreadyRefed), +// or must be deleted using |delete|. template class Refcounted { public: Refcounted() - : refcount_(1) + : refcount_(0) { } @@ -217,7 +239,12 @@ class Ref : thing_(other.release()) { } - Ref(const Newborn &other) + Ref(const AlreadyRefed &other) + : thing_(other.release()) + { + } + template + Ref(const AlreadyRefed &other) : thing_(other.release()) { } @@ -255,7 +282,7 @@ class Ref } template - Ref &operator =(const Newborn &other) { + Ref &operator =(const AlreadyRefed &other) { Release(); thing_ = other.release(); return *this; diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h index ba57ff6d..4dcfe4c1 100644 --- a/public/sourcepawn/sp_vm_types.h +++ b/public/sourcepawn/sp_vm_types.h @@ -36,8 +36,8 @@ * @file sp_vm_types.h * @brief Contains all run-time SourcePawn structures. */ - -#include "sp_file_headers.h" +#include +#include typedef uint32_t ucell_t; /**< Unsigned 32bit integer */ typedef int32_t cell_t; /**< Basic 32bit signed integer type for plugins */ @@ -189,10 +189,25 @@ typedef struct sp_debug_line_s uint32_t line; /**< Line number */ } sp_debug_line_t; -/** - * @brief These structures are equivalent. - */ -typedef sp_fdbg_arraydim_t sp_debug_arraydim_t; +// Occurs after an fdbg_symbol entry, for each dimension. +typedef struct sp_debug_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_debug_arraydim_t; + +// Same as from . +typedef struct sp_debug_symbol_raw_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_debug_symbol_raw_t; /** * @brief The majority of this struct is already located in the parent @@ -200,11 +215,11 @@ typedef sp_fdbg_arraydim_t sp_debug_arraydim_t; */ typedef struct sp_debug_symbol_s { - uint32_t codestart; /**< Relocated code address */ - uint32_t codeend; /**< Relocated code end address */ - const char * name; /**< Relocated name */ - sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */ - sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */ + uint32_t codestart; /**< Relocated code address */ + uint32_t codeend; /**< Relocated code end address */ + const char * name; /**< Relocated name */ + sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */ + sp_debug_symbol_raw_t *sym; /**< Pointer to original symbol */ } sp_debug_symbol_t; #endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H diff --git a/sourcepawn/compiler/AMBuilder b/sourcepawn/compiler/AMBuilder index 2752a06c..4d13ec91 100644 --- a/sourcepawn/compiler/AMBuilder +++ b/sourcepawn/compiler/AMBuilder @@ -42,6 +42,7 @@ binary = SM.Program(builder, 'spcomp') compiler = binary.compiler compiler.includes += [ os.path.join(builder.sourcePath, 'public'), + os.path.join(builder.sourcePath, 'public', 'amtl'), os.path.join(builder.sourcePath, 'public', 'sourcepawn'), os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'), os.path.join(builder.buildPath, 'includes'), @@ -50,7 +51,8 @@ compiler.includes += [ compiler.sourcedeps += packed_includes if compiler.cc.behavior == 'gcc': - compiler.cflags += ['-std=c99', '-Wno-format'] + compiler.cflags += ['-Wno-format'] + compiler.c_only_flags += ['-std=c99'] if builder.target_platform == 'linux': compiler.postlink += ['-lgcc', '-lm'] elif compiler.cc.behavior == 'msvc': @@ -58,10 +60,10 @@ elif compiler.cc.behavior == 'msvc': compiler.linkflags.append('/SUBSYSTEM:CONSOLE') compiler.cxxflags.remove('/TP') +compiler.defines += ['HAVE_STDINT_H'] if builder.target_platform == 'linux': compiler.defines += [ 'LINUX', - 'HAVE_STDINT_H', 'AMX_ANSIONLY', 'ENABLE_BINRELOC', '_GNU_SOURCE' @@ -69,32 +71,31 @@ if builder.target_platform == 'linux': elif builder.target_platform == 'mac': compiler.defines += [ 'DARWIN', - 'HAVE_STDINT_H', 'AMX_ANSIONLY', 'ENABLE_BINRELOC', 'HAVE_SAFESTR' ] binary.sources += [ - 'libpawnc.c', - 'lstring.c', - 'memfile.c', - 'pawncc.c', - 'sc1.c', - 'sc2.c', - 'sc3.c', - 'sc4.c', - 'sc5.c', - 'sc6.c', - 'sc7.c', - 'scexpand.c', - 'sci18n.c', - 'sclist.c', - 'scmemfil.c', - 'scstate.c', - 'sctracker.c', - 'scvars.c', - 'sp_file.c', + 'libpawnc.cpp', + 'lstring.cpp', + 'memfile.cpp', + 'pawncc.cpp', + 'sc1.cpp', + 'sc2.cpp', + 'sc3.cpp', + 'sc4.cpp', + 'sc5.cpp', + 'sc6.cpp', + 'sc7.cpp', + 'scexpand.cpp', + 'sci18n.cpp', + 'sclist.cpp', + 'scmemfil.cpp', + 'scstate.cpp', + 'sctracker.cpp', + 'scvars.cpp', + 'sp_file.cpp', 'zlib/adler32.c', 'zlib/compress.c', 'zlib/crc32.c', @@ -107,7 +108,7 @@ binary.sources += [ 'zlib/trees.c', 'zlib/uncompr.c', 'zlib/zutil.c', - 'sp_symhash.c' + 'sp_symhash.cpp' ] if builder.target_platform != 'windows': binary.sources.append('binreloc.c') diff --git a/sourcepawn/compiler/amx.h b/sourcepawn/compiler/amx.h index b8de039a..7ed08dce 100644 --- a/sourcepawn/compiler/amx.h +++ b/sourcepawn/compiler/amx.h @@ -34,8 +34,12 @@ #include #endif +#if defined HAVE_STDINT_H +# include +# include +#endif + #if defined __GNUC__ - #include #if !defined HAVE_STDINT_H #define HAVE_STDINT_H #endif diff --git a/sourcepawn/compiler/amxdbg.h b/sourcepawn/compiler/amxdbg.h index 475e91db..5726d78b 100644 --- a/sourcepawn/compiler/amxdbg.h +++ b/sourcepawn/compiler/amxdbg.h @@ -1,173 +1,173 @@ -/* Abstract Machine for the Pawn compiler, debugger support - * - * This file contains extra definitions that are convenient for debugger - * support. - * - * Copyright (c) ITB CompuPhase, 2005 - * - * This software is provided "as-is", without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef AMXDBG_H_INCLUDED -#define AMXDBG_H_INCLUDED - -#ifndef AMX_H_INCLUDED - #include "amx.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Some compilers do not support the #pragma align, which should be fine. Some - * compilers give a warning on unknown #pragmas, which is not so fine... - */ -#if defined SN_TARGET_PS2 || defined __GNUC__ - #define AMX_NO_ALIGN -#endif - -#if defined __GNUC__ - #define PACKED __attribute__((packed)) -#else - #define PACKED -#endif - -#if !defined AMX_NO_ALIGN - #if defined LINUX || defined __FreeBSD__ - #pragma pack(1) /* structures must be packed (byte-aligned) */ - #elif defined MACOS && defined __MWERKS__ - #pragma options align=mac68k - #else - #pragma pack(push) - #pragma pack(1) /* structures must be packed (byte-aligned) */ - #if defined __TURBOC__ - #pragma option -a- /* "pack" pragma for older Borland compilers */ - #endif - #endif -#endif - -typedef struct tagAMX_DBG_HDR { - int32_t size PACKED; /* size of the debug information chunk */ - uint16_t magic PACKED; /* signature, must be 0xf1ef */ - char file_version; /* file format version */ - char amx_version; /* required version of the AMX */ - int16_t flags PACKED; /* currently unused */ - int16_t files PACKED; /* number of entries in the "file" table */ - int32_t lines PACKED; /* number of entries in the "line" table */ - int32_t symbols PACKED; /* number of entries in the "symbol" table */ - int16_t tags PACKED; /* number of entries in the "tag" table */ - int16_t automatons PACKED; /* number of entries in the "automaton" table */ - int16_t states PACKED; /* number of entries in the "state" table */ -} PACKED AMX_DBG_HDR; -#define AMX_DBG_MAGIC 0xf1ef - -typedef struct tagAMX_DBG_FILE { - ucell address PACKED; /* address in the code segment where generated code (for this file) starts */ - const char name[1]; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_FILE; - -typedef struct tagAMX_DBG_LINE { - ucell address PACKED; /* address in the code segment where generated code (for this line) starts */ - int32_t line PACKED; /* line number */ -} PACKED AMX_DBG_LINE; - -typedef struct tagAMX_DBG_SYMBOL { - ucell address PACKED; /* address in the data segment or relative to the frame */ - int16_t tag PACKED; /* tag for the symbol */ - ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */ - ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */ - char ident; /* kind of symbol (function/variable) */ - char vclass; /* class of symbol (global/local) */ - int16_t dim PACKED; /* number of dimensions */ - const char name[1]; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_SYMBOL; - -typedef struct tagAMX_DBG_SYMDIM { - int16_t tag PACKED; /* tag for the array dimension */ - ucell size PACKED; /* size of the array dimension */ -} PACKED AMX_DBG_SYMDIM; - -typedef struct tagAMX_DBG_TAG { - int16_t tag PACKED; /* tag id */ - const char name[1]; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_TAG; - -typedef struct tagAMX_DBG_MACHINE { - int16_t automaton PACKED; /* automaton id */ - ucell address PACKED; /* address of state variable */ - const char name[1]; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_MACHINE; - -typedef struct tagAMX_DBG_STATE { - int16_t state PACKED; /* state id */ - int16_t automaton PACKED; /* automaton id */ - const char name[1]; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_STATE; - -typedef struct tagAMX_DBG { - AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */ - AMX_DBG_FILE _FAR **filetbl PACKED; - AMX_DBG_LINE _FAR *linetbl PACKED; - AMX_DBG_SYMBOL _FAR **symboltbl PACKED; - AMX_DBG_TAG _FAR **tagtbl PACKED; - AMX_DBG_MACHINE _FAR **automatontbl PACKED; - AMX_DBG_STATE _FAR **statetbl PACKED; -} PACKED AMX_DBG; - -#if !defined iVARIABLE - #define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */ - #define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */ - #define iARRAY 3 - #define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */ - #define iFUNCTN 9 -#endif - - -int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg); -int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr); - -int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename); -int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname); -int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line); - -int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address); -int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address); -int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name); -int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name); -int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name); -int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym); -int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim); - - -#if !defined AMX_NO_ALIGN - #if defined LINUX || defined __FreeBSD__ - #pragma pack() /* reset default packing */ - #elif defined MACOS && defined __MWERKS__ - #pragma options align=reset - #else - #pragma pack(pop) /* reset previous packing */ - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* AMXDBG_H_INCLUDED */ - +/* Abstract Machine for the Pawn compiler, debugger support + * + * This file contains extra definitions that are convenient for debugger + * support. + * + * Copyright (c) ITB CompuPhase, 2005 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Version: $Id$ + */ + +#ifndef AMXDBG_H_INCLUDED +#define AMXDBG_H_INCLUDED + +#ifndef AMX_H_INCLUDED + #include "amx.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Some compilers do not support the #pragma align, which should be fine. Some + * compilers give a warning on unknown #pragmas, which is not so fine... + */ +#if defined SN_TARGET_PS2 || defined __GNUC__ + #define AMX_NO_ALIGN +#endif + +#if defined __GNUC__ + #define PACKED __attribute__((packed)) +#else + #define PACKED +#endif + +#if !defined AMX_NO_ALIGN + #if defined LINUX || defined __FreeBSD__ + #pragma pack(1) /* structures must be packed (byte-aligned) */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=mac68k + #else + #pragma pack(push) + #pragma pack(1) /* structures must be packed (byte-aligned) */ + #if defined __TURBOC__ + #pragma option -a- /* "pack" pragma for older Borland compilers */ + #endif + #endif +#endif + +typedef struct tagAMX_DBG_HDR { + int32_t size PACKED; /* size of the debug information chunk */ + uint16_t magic PACKED; /* signature, must be 0xf1ef */ + char file_version; /* file format version */ + char amx_version; /* required version of the AMX */ + int16_t flags PACKED; /* currently unused */ + int16_t files PACKED; /* number of entries in the "file" table */ + int32_t lines PACKED; /* number of entries in the "line" table */ + int32_t symbols PACKED; /* number of entries in the "symbol" table */ + int16_t tags PACKED; /* number of entries in the "tag" table */ + int16_t automatons PACKED; /* number of entries in the "automaton" table */ + int16_t states PACKED; /* number of entries in the "state" table */ +} PACKED AMX_DBG_HDR; +#define AMX_DBG_MAGIC 0xf1ef + +typedef struct tagAMX_DBG_FILE { + ucell address PACKED; /* address in the code segment where generated code (for this file) starts */ + char name[1]; /* ASCII string, zero-terminated */ +} PACKED AMX_DBG_FILE; + +typedef struct tagAMX_DBG_LINE { + ucell address PACKED; /* address in the code segment where generated code (for this line) starts */ + int32_t line PACKED; /* line number */ +} PACKED AMX_DBG_LINE; + +typedef struct tagAMX_DBG_SYMBOL { + ucell address PACKED; /* address in the data segment or relative to the frame */ + int16_t tag PACKED; /* tag for the symbol */ + ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */ + ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */ + char ident; /* kind of symbol (function/variable) */ + char vclass; /* class of symbol (global/local) */ + int16_t dim PACKED; /* number of dimensions */ + char name[1]; /* ASCII string, zero-terminated */ +} PACKED AMX_DBG_SYMBOL; + +typedef struct tagAMX_DBG_SYMDIM { + int16_t tag PACKED; /* tag for the array dimension */ + ucell size PACKED; /* size of the array dimension */ +} PACKED AMX_DBG_SYMDIM; + +typedef struct tagAMX_DBG_TAG { + int16_t tag PACKED; /* tag id */ + char name[1]; /* ASCII string, zero-terminated */ +} PACKED AMX_DBG_TAG; + +typedef struct tagAMX_DBG_MACHINE { + int16_t automaton PACKED; /* automaton id */ + ucell address PACKED; /* address of state variable */ + char name[1]; /* ASCII string, zero-terminated */ +} PACKED AMX_DBG_MACHINE; + +typedef struct tagAMX_DBG_STATE { + int16_t state PACKED; /* state id */ + int16_t automaton PACKED; /* automaton id */ + char name[1]; /* ASCII string, zero-terminated */ +} PACKED AMX_DBG_STATE; + +typedef struct tagAMX_DBG { + AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */ + AMX_DBG_FILE _FAR **filetbl PACKED; + AMX_DBG_LINE _FAR *linetbl PACKED; + AMX_DBG_SYMBOL _FAR **symboltbl PACKED; + AMX_DBG_TAG _FAR **tagtbl PACKED; + AMX_DBG_MACHINE _FAR **automatontbl PACKED; + AMX_DBG_STATE _FAR **statetbl PACKED; +} PACKED AMX_DBG; + +#if !defined iVARIABLE + #define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */ + #define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */ + #define iARRAY 3 + #define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */ + #define iFUNCTN 9 +#endif + + +int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg); +int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr); + +int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename); +int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname); +int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line); + +int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address); +int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address); +int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name); +int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name); +int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name); +int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym); +int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim); + + +#if !defined AMX_NO_ALIGN + #if defined LINUX || defined __FreeBSD__ + #pragma pack() /* reset default packing */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=reset + #else + #pragma pack(pop) /* reset previous packing */ + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* AMXDBG_H_INCLUDED */ + diff --git a/sourcepawn/compiler/libpawnc.c b/sourcepawn/compiler/libpawnc.c deleted file mode 100644 index f0953d9e..00000000 --- a/sourcepawn/compiler/libpawnc.c +++ /dev/null @@ -1,409 +0,0 @@ -// vim: set sts=8 ts=4 sw=4 tw=99 noet: -/* LIBPAWNC.C - * - * A "glue file" for building the Pawn compiler as a DLL or shared library. - * - * Copyright (c) ITB CompuPhase, 2000-2006 - * - * This software is provided "as-is", without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ -#include -#include -#include -#include -#include -#include "sc.h" -#include "memfile.h" - -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN -#include -#include -#endif - -/* pc_printf() - * Called for general purpose "console" output. This function prints general - * purpose messages; errors go through pc_error(). The function is modelled - * after printf(). - */ -int pc_printf(const char *message,...) -{ - int ret; - va_list argptr; - - va_start(argptr,message); - ret=vprintf(message,argptr); - va_end(argptr); - - return ret; -} - -/* pc_error() - * Called for producing error output. - * number the error number (as documented in the manual) - * message a string describing the error with embedded %d and %s tokens - * filename the name of the file currently being parsed - * firstline the line number at which the expression started on which - * the error was found, or -1 if there is no "starting line" - * lastline the line number at which the error was detected - * argptr a pointer to the first of a series of arguments (for macro - * "va_arg") - * Return: - * If the function returns 0, the parser attempts to continue compilation. - * On a non-zero return value, the parser aborts. - */ -int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr) -{ -static char *prefix[3]={ "error", "fatal error", "warning" }; - - if (number!=0) { - char *pre; - int idx; - - if (number < 160) - idx = 0; - else if (number < 200) - idx = 1; - else - idx = 2; - - pre=prefix[idx]; - if (firstline>=0) - fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number); - else - fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number); - } /* if */ - vfprintf(stdout,message,argptr); - fflush(stdout); - return 0; -} - -typedef struct src_file_s { - FILE *fp; // Set if writing. - char *buffer; // IO buffer. - char *pos; // IO position. - char *end; // End of buffer. - size_t maxlength; // Maximum length of the writable buffer. -} src_file_t; - -/* pc_opensrc() - * Opens a source file (or include file) for reading. The "file" does not have - * to be a physical file, one might compile from memory. - * filename the name of the "file" to read from - * Return: - * The function must return a pointer, which is used as a "magic cookie" to - * all I/O functions. When failing to open the file for reading, the - * function must return NULL. - * Note: - * Several "source files" may be open at the same time. Specifically, one - * file can be open for reading and another for writing. - */ -void *pc_opensrc(char *filename) -{ - FILE *fp = NULL; - long length; - src_file_t *src = NULL; - -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN - struct stat fileInfo; - if (stat(filename, &fileInfo) != 0) { - return NULL; - } - - if (S_ISDIR(fileInfo.st_mode)) { - return NULL; - } -#endif - - if ((fp = fopen(filename, "rb")) == NULL) - return NULL; - if (fseek(fp, 0, SEEK_END) == -1) - goto err; - if ((length = ftell(fp)) == -1) - goto err; - if (fseek(fp, 0, SEEK_SET) == -1) - goto err; - - if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL) - goto err; - if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL) - goto err; - if (fread(src->buffer, length, 1, fp) != 1) - goto err; - - src->pos = src->buffer; - src->end = src->buffer + length; - fclose(fp); - return src; - -err: - pc_closesrc(src); - fclose(fp); - return NULL; -} - -/* pc_createsrc() - * Creates/overwrites a source file for writing. The "file" does not have - * to be a physical file, one might compile from memory. - * filename the name of the "file" to create - * Return: - * The function must return a pointer which is used as a "magic cookie" to - * all I/O functions. When failing to open the file for reading, the - * function must return NULL. - * Note: - * Several "source files" may be open at the same time. Specifically, one - * file can be open for reading and another for writing. - */ -void *pc_createsrc(char *filename) -{ - src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t)); - if (!src) - return NULL; - if ((src->fp = fopen(filename, "wt")) == NULL) { - pc_closesrc(src); - return NULL; - } - - src->maxlength = 1024; - if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) { - pc_closesrc(src); - return NULL; - } - - src->pos = src->buffer; - src->end = src->buffer + src->maxlength; - return src; -} - -/* pc_closesrc() - * Closes a source file (or include file). The "handle" parameter has the - * value that pc_opensrc() returned in an earlier call. - */ -void pc_closesrc(void *handle) -{ - src_file_t *src = (src_file_t *)handle; - if (!src) - return; - if (src->fp) { - fwrite(src->buffer, src->pos - src->buffer, 1, src->fp); - fclose(src->fp); - } - free(src->buffer); - free(src); -} - -/* pc_readsrc() - * Reads a single line from the source file (or up to a maximum number of - * characters if the line in the input file is too long). - */ -char *pc_readsrc(void *handle,unsigned char *target,int maxchars) -{ - src_file_t *src = (src_file_t *)handle; - char *outptr = (char *)target; - char *outend = outptr + maxchars; - - assert(!src->fp); - - if (src->pos == src->end) - return NULL; - - while (outptr < outend && src->pos < src->end) { - char c = *src->pos++; - *outptr++ = c; - - if (c == '\n') - break; - if (c == '\r') { - // Handle CRLF. - if (src->pos < src->end && *src->pos == '\n') { - src->pos++; - if (outptr < outend) - *outptr++ = '\n'; - } - break; - } - } - - // Caller passes in a buffer of size >= maxchars+1. - *outptr = '\0'; - return (char *)target; -} - -/* pc_writesrc() - * Writes to to the source file. There is no automatic line ending; to end a - * line, write a "\n". - */ -int pc_writesrc(void *handle,unsigned char *source) -{ - char *str = (char *)source; - size_t len = strlen(str); - src_file_t *src = (src_file_t *)handle; - - assert(src->fp && src->maxlength); - - if (src->pos + len > src->end) { - char *newbuf; - size_t newmax = src->maxlength; - size_t newlen = (src->pos - src->buffer) + len; - while (newmax < newlen) { - // Grow by 1.5X - newmax += newmax + newmax / 2; - if (newmax < src->maxlength) - abort(); - } - - newbuf = (char *)realloc(src->buffer, newmax); - if (!newbuf) - abort(); - src->pos = newbuf + (src->pos - src->buffer); - src->end = newbuf + newmax; - src->buffer = newbuf; - src->maxlength = newmax; - } - - strcpy(src->pos, str); - src->pos += len; - return 0; -} - -void *pc_getpossrc(void *handle,void *position) -{ - src_file_t *src = (src_file_t *)handle; - - assert(!src->fp); - return (void *)(ptrdiff_t)(src->pos - src->buffer); -} - -/* pc_resetsrc() - * "position" may only hold a pointer that was previously obtained from - * pc_getpossrc() - */ -void pc_resetsrc(void *handle,void *position) -{ - src_file_t *src = (src_file_t *)handle; - ptrdiff_t pos = (ptrdiff_t)position; - - assert(!src->fp); - assert(pos >= 0 && src->buffer + pos <= src->end); - src->pos = src->buffer + pos; -} - -int pc_eofsrc(void *handle) -{ - src_file_t *src = (src_file_t *)handle; - - assert(!src->fp); - return src->pos == src->end; -} - -/* should return a pointer, which is used as a "magic cookie" to all I/O - * functions; return NULL for failure - */ -void *pc_openasm(char *filename) -{ - #if defined __MSDOS__ || defined SC_LIGHT - return fopen(filename,"w+t"); - #else - return mfcreate(filename); - #endif -} - -void pc_closeasm(void *handle, int deletefile) -{ - #if defined __MSDOS__ || defined SC_LIGHT - if (handle!=NULL) - fclose((FILE*)handle); - if (deletefile) - remove(outfname); - #else - if (handle!=NULL) { - if (!deletefile) - mfdump((MEMFILE*)handle); - mfclose((MEMFILE*)handle); - } /* if */ - #endif -} - -void pc_resetasm(void *handle) -{ - assert(handle!=NULL); - #if defined __MSDOS__ || defined SC_LIGHT - fflush((FILE*)handle); - fseek((FILE*)handle,0,SEEK_SET); - #else - mfseek((MEMFILE*)handle,0,SEEK_SET); - #endif -} - -int pc_writeasm(void *handle,char *string) -{ - #if defined __MSDOS__ || defined SC_LIGHT - return fputs(string,(FILE*)handle) >= 0; - #else - return mfputs((MEMFILE*)handle,string); - #endif -} - -char *pc_readasm(void *handle, char *string, int maxchars) -{ - #if defined __MSDOS__ || defined SC_LIGHT - return fgets(string,maxchars,(FILE*)handle); - #else - return mfgets((MEMFILE*)handle,string,maxchars); - #endif -} - -extern memfile_t *bin_file; - -/* Should return a pointer, which is used as a "magic cookie" to all I/O - * functions; return NULL for failure. - */ -void *pc_openbin(char *filename) -{ - return memfile_creat(filename, 1); -} - -void pc_closebin(void *handle,int deletefile) -{ - if (deletefile) - { - memfile_destroy((memfile_t *)handle); - bin_file = NULL; - } else { - bin_file = (memfile_t *)handle; - } -} - -/* pc_resetbin() - * Can seek to any location in the file. - * The offset is always from the start of the file. - */ -void pc_resetbin(void *handle,long offset) -{ - memfile_seek((memfile_t *)handle, offset); -} - -int pc_writebin(void *handle,void *buffer,int size) -{ - return memfile_write((memfile_t *)handle, buffer, size); -} - -long pc_lengthbin(void *handle) -{ - return memfile_tell((memfile_t *)handle); -} diff --git a/sourcepawn/compiler/libpawnc.cpp b/sourcepawn/compiler/libpawnc.cpp new file mode 100644 index 00000000..f99086d9 --- /dev/null +++ b/sourcepawn/compiler/libpawnc.cpp @@ -0,0 +1,382 @@ +// vim: set sts=8 ts=4 sw=4 tw=99 noet: +/* LIBPAWNC.C + * + * A "glue file" for building the Pawn compiler as a DLL or shared library. + * + * Copyright (c) ITB CompuPhase, 2000-2006 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Version: $Id$ + */ +#include +#include +#include +#include +#include +#include "sc.h" +#include "memfile.h" + +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN +#include +#include +#endif + +/* pc_printf() + * Called for general purpose "console" output. This function prints general + * purpose messages; errors go through pc_error(). The function is modelled + * after printf(). + */ +int pc_printf(const char *message,...) +{ + int ret; + va_list argptr; + + va_start(argptr,message); + ret=vprintf(message,argptr); + va_end(argptr); + + return ret; +} + +/* pc_error() + * Called for producing error output. + * number the error number (as documented in the manual) + * message a string describing the error with embedded %d and %s tokens + * filename the name of the file currently being parsed + * firstline the line number at which the expression started on which + * the error was found, or -1 if there is no "starting line" + * lastline the line number at which the error was detected + * argptr a pointer to the first of a series of arguments (for macro + * "va_arg") + * Return: + * If the function returns 0, the parser attempts to continue compilation. + * On a non-zero return value, the parser aborts. + */ +int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr) +{ +static const char *prefix[3]={ "error", "fatal error", "warning" }; + + if (number!=0) { + int idx; + + if (number < 160) + idx = 0; + else if (number < 200) + idx = 1; + else + idx = 2; + + const char *pre=prefix[idx]; + if (firstline>=0) + fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number); + else + fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number); + } /* if */ + vfprintf(stdout,message,argptr); + fflush(stdout); + return 0; +} + +typedef struct src_file_s { + FILE *fp; // Set if writing. + char *buffer; // IO buffer. + char *pos; // IO position. + char *end; // End of buffer. + size_t maxlength; // Maximum length of the writable buffer. +} src_file_t; + +/* pc_opensrc() + * Opens a source file (or include file) for reading. The "file" does not have + * to be a physical file, one might compile from memory. + * filename the name of the "file" to read from + * Return: + * The function must return a pointer, which is used as a "magic cookie" to + * all I/O functions. When failing to open the file for reading, the + * function must return NULL. + * Note: + * Several "source files" may be open at the same time. Specifically, one + * file can be open for reading and another for writing. + */ +void *pc_opensrc(char *filename) +{ + FILE *fp = NULL; + long length; + src_file_t *src = NULL; + +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN + struct stat fileInfo; + if (stat(filename, &fileInfo) != 0) { + return NULL; + } + + if (S_ISDIR(fileInfo.st_mode)) { + return NULL; + } +#endif + + if ((fp = fopen(filename, "rb")) == NULL) + return NULL; + if (fseek(fp, 0, SEEK_END) == -1) + goto err; + if ((length = ftell(fp)) == -1) + goto err; + if (fseek(fp, 0, SEEK_SET) == -1) + goto err; + + if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL) + goto err; + if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL) + goto err; + if (fread(src->buffer, length, 1, fp) != 1) + goto err; + + src->pos = src->buffer; + src->end = src->buffer + length; + fclose(fp); + return src; + +err: + pc_closesrc(src); + fclose(fp); + return NULL; +} + +/* pc_createsrc() + * Creates/overwrites a source file for writing. The "file" does not have + * to be a physical file, one might compile from memory. + * filename the name of the "file" to create + * Return: + * The function must return a pointer which is used as a "magic cookie" to + * all I/O functions. When failing to open the file for reading, the + * function must return NULL. + * Note: + * Several "source files" may be open at the same time. Specifically, one + * file can be open for reading and another for writing. + */ +void *pc_createsrc(char *filename) +{ + src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t)); + if (!src) + return NULL; + if ((src->fp = fopen(filename, "wt")) == NULL) { + pc_closesrc(src); + return NULL; + } + + src->maxlength = 1024; + if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) { + pc_closesrc(src); + return NULL; + } + + src->pos = src->buffer; + src->end = src->buffer + src->maxlength; + return src; +} + +/* pc_closesrc() + * Closes a source file (or include file). The "handle" parameter has the + * value that pc_opensrc() returned in an earlier call. + */ +void pc_closesrc(void *handle) +{ + src_file_t *src = (src_file_t *)handle; + if (!src) + return; + if (src->fp) { + fwrite(src->buffer, src->pos - src->buffer, 1, src->fp); + fclose(src->fp); + } + free(src->buffer); + free(src); +} + +/* pc_readsrc() + * Reads a single line from the source file (or up to a maximum number of + * characters if the line in the input file is too long). + */ +char *pc_readsrc(void *handle,unsigned char *target,int maxchars) +{ + src_file_t *src = (src_file_t *)handle; + char *outptr = (char *)target; + char *outend = outptr + maxchars; + + assert(!src->fp); + + if (src->pos == src->end) + return NULL; + + while (outptr < outend && src->pos < src->end) { + char c = *src->pos++; + *outptr++ = c; + + if (c == '\n') + break; + if (c == '\r') { + // Handle CRLF. + if (src->pos < src->end && *src->pos == '\n') { + src->pos++; + if (outptr < outend) + *outptr++ = '\n'; + } + break; + } + } + + // Caller passes in a buffer of size >= maxchars+1. + *outptr = '\0'; + return (char *)target; +} + +/* pc_writesrc() + * Writes to to the source file. There is no automatic line ending; to end a + * line, write a "\n". + */ +int pc_writesrc(void *handle,unsigned char *source) +{ + char *str = (char *)source; + size_t len = strlen(str); + src_file_t *src = (src_file_t *)handle; + + assert(src->fp && src->maxlength); + + if (src->pos + len > src->end) { + char *newbuf; + size_t newmax = src->maxlength; + size_t newlen = (src->pos - src->buffer) + len; + while (newmax < newlen) { + // Grow by 1.5X + newmax += newmax + newmax / 2; + if (newmax < src->maxlength) + abort(); + } + + newbuf = (char *)realloc(src->buffer, newmax); + if (!newbuf) + abort(); + src->pos = newbuf + (src->pos - src->buffer); + src->end = newbuf + newmax; + src->buffer = newbuf; + src->maxlength = newmax; + } + + strcpy(src->pos, str); + src->pos += len; + return 0; +} + +void *pc_getpossrc(void *handle,void *position) +{ + src_file_t *src = (src_file_t *)handle; + + assert(!src->fp); + return (void *)(ptrdiff_t)(src->pos - src->buffer); +} + +/* pc_resetsrc() + * "position" may only hold a pointer that was previously obtained from + * pc_getpossrc() + */ +void pc_resetsrc(void *handle,void *position) +{ + src_file_t *src = (src_file_t *)handle; + ptrdiff_t pos = (ptrdiff_t)position; + + assert(!src->fp); + assert(pos >= 0 && src->buffer + pos <= src->end); + src->pos = src->buffer + pos; +} + +int pc_eofsrc(void *handle) +{ + src_file_t *src = (src_file_t *)handle; + + assert(!src->fp); + return src->pos == src->end; +} + +/* should return a pointer, which is used as a "magic cookie" to all I/O + * functions; return NULL for failure + */ +void *pc_openasm(char *filename) +{ + return mfcreate(filename); +} + +void pc_closeasm(void *handle, int deletefile) +{ + if (handle!=NULL) { + if (!deletefile) + mfdump((MEMFILE*)handle); + mfclose((MEMFILE*)handle); + } /* if */ +} + +void pc_resetasm(void *handle) +{ + mfseek((MEMFILE*)handle,0,SEEK_SET); +} + +int pc_writeasm(void *handle,const char *string) +{ + return mfputs((MEMFILE*)handle,string); +} + +char *pc_readasm(void *handle, char *string, int maxchars) +{ + return mfgets((MEMFILE*)handle,string,maxchars); +} + +extern memfile_t *bin_file; + +/* Should return a pointer, which is used as a "magic cookie" to all I/O + * functions; return NULL for failure. + */ +void *pc_openbin(char *filename) +{ + return memfile_creat(filename, 1); +} + +void pc_closebin(void *handle,int deletefile) +{ + if (deletefile) { + memfile_destroy((memfile_t *)handle); + bin_file = NULL; + } else { + bin_file = (memfile_t *)handle; + } +} + +/* pc_resetbin() + * Can seek to any location in the file. + * The offset is always from the start of the file. + */ +void pc_resetbin(void *handle,long offset) +{ + memfile_seek((memfile_t *)handle, offset); +} + +int pc_writebin(void *handle,void *buffer,int size) +{ + return memfile_write((memfile_t *)handle, buffer, size); +} + +long pc_lengthbin(void *handle) +{ + return memfile_tell((memfile_t *)handle); +} diff --git a/sourcepawn/compiler/lstring.c b/sourcepawn/compiler/lstring.cpp similarity index 95% rename from sourcepawn/compiler/lstring.c rename to sourcepawn/compiler/lstring.cpp index f5156b32..102a956e 100644 --- a/sourcepawn/compiler/lstring.c +++ b/sourcepawn/compiler/lstring.cpp @@ -37,7 +37,7 @@ * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ -size_t +extern "C" size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; @@ -93,7 +93,7 @@ strlcpy(char *dst, const char *src, size_t siz) * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ -size_t +extern "C" size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; diff --git a/sourcepawn/compiler/lstring.h b/sourcepawn/compiler/lstring.h index ca62cb9a..f8206e11 100644 --- a/sourcepawn/compiler/lstring.h +++ b/sourcepawn/compiler/lstring.h @@ -9,10 +9,18 @@ #if !defined HAVE_SAFESTR -size_t +#if defined(__cplusplus) +# define EXPORT extern "C" +#else +# define EXPORT +#endif + +EXPORT size_t strlcpy(char *dst, const char *src, size_t siz); -size_t +EXPORT size_t strlcat(char *dst, const char *src, size_t siz); +#undef EXPORT + #endif diff --git a/sourcepawn/compiler/memfile.c b/sourcepawn/compiler/memfile.cpp similarity index 100% rename from sourcepawn/compiler/memfile.c rename to sourcepawn/compiler/memfile.cpp diff --git a/sourcepawn/compiler/memfile.h b/sourcepawn/compiler/memfile.h index 8fbf38a7..225e4d87 100644 --- a/sourcepawn/compiler/memfile.h +++ b/sourcepawn/compiler/memfile.h @@ -52,4 +52,15 @@ long memfile_tell(memfile_t *mf); */ void memfile_reset(memfile_t *mf); +typedef memfile_t MEMFILE; +MEMFILE *mfcreate(const char *filename); +void mfclose(MEMFILE *mf); +int mfdump(MEMFILE *mf); +long mflength(const MEMFILE *mf); +long mfseek(MEMFILE *mf,long offset,int whence); +unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size); +unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size); +char *mfgets(MEMFILE *mf,char *string,unsigned int size); +int mfputs(MEMFILE *mf,const char *string); + #endif //_INCLUDE_MEMFILE_H diff --git a/sourcepawn/compiler/pawncc.c b/sourcepawn/compiler/pawncc.c deleted file mode 100644 index af1d9842..00000000 --- a/sourcepawn/compiler/pawncc.c +++ /dev/null @@ -1,615 +0,0 @@ -#include -#include -#include -#include -#include "memfile.h" -#include "sp_file.h" -#include "amx.h" -#include "amxdbg.h" -#include "osdefs.h" -#include "zlib/zlib.h" -#if defined LINUX || defined DARWIN -#include -#elif defined WIN32 -#include -#endif - -enum FileSections -{ - FS_Code, /* required */ - FS_Data, /* required */ - FS_Publics, - FS_Pubvars, - FS_Natives, - FS_Nametable, /* required */ - FS_DbgFile, - FS_DbgSymbol, - FS_DbgLine, - FS_DbgTags, - FS_DbgNatives, - FS_DbgAutomaton, - FS_DbgState, - FS_DbgStrings, - FS_DbgInfo, - FS_Tags, - /* --- */ - FS_Number, -}; - -int pc_printf(const char *message,...); -int pc_compile(int argc, char **argv); -void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf); - -memfile_t *bin_file = NULL; -jmp_buf brkout; - -#define sARGS_MAX 32 /* number of arguments a function can have, max */ -#define sDIMEN_MAX 4 /* maximum number of array dimensions */ - -typedef struct t_arg_s -{ - uint8_t ident; - int16_t tag; - char *name; - uint16_t dimcount; - sp_fdbg_arraydim_t dims[sDIMEN_MAX]; -} t_arg; - -typedef struct t_native_s -{ - char *name; - int16_t ret_tag; - uint16_t num_args; - t_arg args[sARGS_MAX]; -} t_native; - -t_native *native_list = NULL; - -int main(int argc, char *argv[]) -{ - if (pc_compile(argc,argv) == 0) - { - AMX_HEADER *hdr; - AMX_DBG_HDR *dbg = NULL; - int err; - uint32_t i; - sp_file_t *spf; - memfile_t *dbgtab = NULL; //dbgcrab - unsigned char *dbgptr = NULL; - uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0}; - FILE *fp; - - if (bin_file == NULL) - { - return 0; - } - - hdr = (AMX_HEADER *)bin_file->base; - - if ((spf=spfw_create(bin_file->name, NULL)) == NULL) - { - pc_printf("Error creating binary file!\n"); - memfile_destroy(bin_file); - return 0; - } - - if ((err=setjmp(brkout))!=0) - { - goto write_error; - } - - spfw_add_section(spf, ".code"); - spfw_add_section(spf, ".data"); - - sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize; - if (sections[FS_Publics]) - { - spfw_add_section(spf, ".publics"); - } - sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize; - if (sections[FS_Pubvars]) - { - spfw_add_section(spf, ".pubvars"); - } - sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize; - if (sections[FS_Natives]) - { - spfw_add_section(spf, ".natives"); - } - sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize; - if (sections[FS_Tags]) - { - spfw_add_section(spf, ".tags"); - } - - spfw_add_section(spf, ".names"); - - if (hdr->flags & AMX_FLAG_DEBUG) - { - dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size); - if (dbg->magic != AMX_DBG_MAGIC) - { - pc_printf("Error reading AMX_DBG_HDR, debug data will not be written."); - } else { - dbgtab = memfile_creat("", 512); - dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR); - if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0) - { - spfw_add_section(spf, ".dbg.natives"); - } - if (dbg->files) - { - spfw_add_section(spf, ".dbg.files"); - sections[FS_DbgFile] = dbg->files; - } - if (dbg->lines) - { - spfw_add_section(spf, ".dbg.lines"); - sections[FS_DbgLine] = dbg->lines; - } - if (dbg->symbols) - { - spfw_add_section(spf, ".dbg.symbols"); - sections[FS_DbgSymbol] = dbg->symbols; - } - sections[FS_DbgInfo] = 1; - sections[FS_DbgStrings] = 1; - spfw_add_section(spf, ".dbg.info"); - spfw_add_section(spf, ".dbg.strings"); - } - } - - spfw_finalize_header(spf); - - /** - * Begin writing each of our known tables out - */ - - if (sections[FS_Code]) - { - sp_file_code_t cod; - unsigned char *cbase; - - cod.cellsize = sizeof(cell); - - cod.codesize = hdr->dat - hdr->cod; - cod.codeversion = hdr->amx_version; - cod.flags = 0; - if (hdr->flags & AMX_FLAG_DEBUG) - { - cod.flags |= SP_FLAG_DEBUG; - } - cod.code = sizeof(cod); - cod.main = hdr->cip; - - /* write the code */ - cbase = (unsigned char *)hdr + hdr->cod; - sfwrite(&cod, sizeof(cod), 1, spf); - sfwrite(cbase, cod.codesize, 1, spf); - - spfw_next_section(spf); - } - - if (sections[FS_Data]) - { - sp_file_data_t dat; - unsigned char *dbase = (unsigned char *)hdr + hdr->dat; - - dat.datasize = hdr->hea - hdr->dat; - dat.memsize = hdr->stp; - dat.data = sizeof(dat); - - /* write header */ - sfwrite(&dat, sizeof(dat), 1, spf); - - if (dat.datasize) - { - /* write data */ - sfwrite(dbase, dat.datasize, 1, spf); - } - - spfw_next_section(spf); - } - - if (sections[FS_Publics]) - { - sp_file_publics_t *pbtbl; - AMX_FUNCSTUBNT *stub; - unsigned char *stubptr; - uint32_t publics = sections[FS_Publics]; - - pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics); - stubptr = (unsigned char *)hdr + hdr->publics; - - for (i=0; iaddress; - pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); - - stubptr += hdr->defsize; - } - if (publics) - { - sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf); - } - free(pbtbl); - - spfw_next_section(spf); - } - - if (sections[FS_Pubvars]) - { - sp_file_pubvars_t *pbvars; - AMX_FUNCSTUBNT *stub; - unsigned char *stubptr; - uint32_t pubvars = sections[FS_Pubvars]; - - pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars); - stubptr = (unsigned char *)hdr + hdr->pubvars; - - for (i=0; iaddress; - pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); - - stubptr += hdr->defsize; - } - if (pubvars) - { - sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf); - } - free(pbvars); - spfw_next_section(spf); - } - - if (sections[FS_Natives]) - { - sp_file_natives_t *nvtbl; - AMX_FUNCSTUBNT *stub; - unsigned char *stubptr; - uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize; - - nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives); - stubptr = (unsigned char *)hdr + hdr->natives; - - for (i=0; inameofs - (hdr->nametable + sizeof(uint16_t)); - - stubptr += hdr->defsize; - } - if (natives) - { - sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf); - } - free(nvtbl); - spfw_next_section(spf); - } - - if (sections[FS_Tags]) - { - uint32_t numTags = (uint32_t)sections[FS_Tags]; - AMX_FUNCSTUBNT *stub; - sp_file_tag_t tag; - - for (i=0; itags + (i * hdr->defsize)); - tag.tag_id = stub->address; - tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); - sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf); - } - spfw_next_section(spf); - } - - if (sections[FS_Nametable]) - { - unsigned char *base; - uint32_t namelen; - - /* write the entire block */ - base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t); - /** - * note - the name table will be padded to sizeof(cell) bytes. - * this may clip at most an extra three bytes in! - */ - namelen = hdr->cod - hdr->nametable; - sfwrite(base, namelen, 1, spf); - spfw_next_section(spf); - } - - if (hdr->flags & AMX_FLAG_DEBUG) - { - sp_fdbg_info_t info; - - memset(&info, 0, sizeof(sp_fdbg_info_t)); - - if (sections[FS_Natives]) - { - uint16_t j; - uint32_t idx; - uint32_t name; - uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize; - - sfwrite(&natives, sizeof(uint32_t), 1, spf); - for (idx=0; idxname); - /* store */ - dbgfile.addr = _ptr->address; - dbgfile.name = (uint32_t)memfile_tell(dbgtab); - sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf); - /* write to tab, then move to next */ - memfile_write(dbgtab, _ptr->name, len + 1); - dbgptr += sizeof(AMX_DBG_FILE) + len; - info.num_files++; - } - spfw_next_section(spf); - } - - if (sections[FS_DbgLine]) - { - uint32_t idx; - AMX_DBG_LINE *line; - sp_fdbg_line_t dbgline; - for (idx=0; idxaddress; - dbgline.line = (uint32_t)line->line; - sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf); - /* move to next */ - dbgptr += sizeof(AMX_DBG_LINE); - info.num_lines++; - } - spfw_next_section(spf); - } - - if (sections[FS_DbgSymbol]) - { - uint32_t idx; - uint32_t dnum; - AMX_DBG_SYMBOL *sym; - AMX_DBG_SYMDIM *dim; - sp_fdbg_symbol_t dbgsym; - sp_fdbg_arraydim_t dbgdim; - uint32_t len; - - for (idx=0; idxaddress; - dbgsym.tagid = sym->tag; - dbgsym.codestart = (uint32_t)sym->codestart; - dbgsym.codeend = (uint32_t)sym->codeend; - dbgsym.dimcount = (uint16_t)sym->dim; - dbgsym.vclass = (uint8_t)sym->vclass; - dbgsym.ident = (uint8_t)sym->ident; - dbgsym.name = (uint32_t)memfile_tell(dbgtab); - sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf); - /* write to tab */ - len = strlen(sym->name); - memfile_write(dbgtab, sym->name, len + 1); - /* move to next */ - dbgptr += sizeof(AMX_DBG_SYMBOL) + len; - /* look for any dimensions */ - info.num_syms++; - for (dnum=0; dnumsize; - dbgdim.tagid = dim->tag; - sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf); - /* move to next */ - dbgptr += sizeof(AMX_DBG_SYMDIM); - info.num_arrays++; - } - } - spfw_next_section(spf); - } - - sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf); - spfw_next_section(spf); - - if (sections[FS_DbgStrings]) - { - sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf); - spfw_next_section(spf); - } - } - - spfw_finalize_all(spf); - - /** - * do compression - * new block for scoping only - */ - { - memfile_t *pOrig = (memfile_t *)spf->handle; - sp_file_hdr_t *pHdr; - unsigned char *proper; - size_t size; - Bytef *zcmp; - uLong disksize; - size_t header_size; - int err = Z_OK; - - /* reuse this memory block! */ - memfile_reset(bin_file); - - /* copy tip of header */ - memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t)); - - /* get pointer to header */ - pHdr = (sp_file_hdr_t *)bin_file->base; - - /* copy the rest of the header */ - memfile_write(bin_file, - (unsigned char *)pOrig->base + sizeof(sp_file_hdr_t), - pHdr->dataoffs - sizeof(sp_file_hdr_t)); - - header_size = pHdr->dataoffs; - size = pHdr->imagesize - header_size; - proper = (unsigned char *)pOrig->base + header_size; - - /* get initial size estimate */ - disksize = compressBound(pHdr->imagesize); - pHdr->disksize = (uint32_t)disksize; - zcmp = (Bytef *)malloc(pHdr->disksize); - - if ((err=compress2(zcmp, - &disksize, - (Bytef *)proper, - (uLong)size, - Z_BEST_COMPRESSION)) - != Z_OK) - { - free(zcmp); - pc_printf("Unable to compress (Z): error %d\n", err); - pc_printf("Falling back to no compression."); - memfile_write(bin_file, - proper, - size); - } else { - pHdr->disksize = (uint32_t)disksize + header_size; - pHdr->compression = SPFILE_COMPRESSION_GZ; - memfile_write(bin_file, - (unsigned char *)zcmp, - disksize); - free(zcmp); - } - } - - spfw_destroy(spf); - memfile_destroy(dbgtab); - - /** - * write file - */ - if ((fp=fopen(bin_file->name, "wb")) != NULL) - { - fwrite(bin_file->base, bin_file->usedoffs, 1, fp); - fclose(fp); - } else { - pc_printf("Unable to open %s for writing!", bin_file->name); - } - - memfile_destroy(bin_file); - - return 0; - -write_error: - pc_printf("Error writing to file: %s", bin_file->name); - - spfw_destroy(spf); - unlink(bin_file->name); - memfile_destroy(bin_file); - memfile_destroy(dbgtab); - - return 1; - } - - return 1; -} - -void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf) -{ - if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count) - { - longjmp(brkout, 1); - } -} - -void sp_fdbg_ntv_start(int num_natives) -{ - if (num_natives == 0) - { - return; - } - - native_list = (t_native *)malloc(sizeof(t_native) * num_natives); - memset(native_list, 0, sizeof(t_native) * num_natives); -} - -#include "sc.h" - -void sp_fdbg_ntv_hook(int index, symbol *sym) -{ - int i, j; - t_native *native; - - native = &native_list[index]; - native->name = strdup(sym->name); - - for (i = 0; i < sMAXARGS; i++) - { - if (sym->dim.arglist[i].ident == 0) - { - break; - } - native->num_args++; - native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0]; - native->args[i].name = strdup(sym->dim.arglist[i].name); - native->args[i].ident = sym->dim.arglist[i].ident; - native->args[i].dimcount = sym->dim.arglist[i].numdim; - for (j = 0; j < native->args[i].dimcount; j++) - { - native->args[i].dims[j].size = sym->dim.arglist[i].dim[j]; - native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j]; - } - } - - native->ret_tag = sym->tag; -} diff --git a/sourcepawn/compiler/pawncc.cpp b/sourcepawn/compiler/pawncc.cpp new file mode 100644 index 00000000..10ceaa96 --- /dev/null +++ b/sourcepawn/compiler/pawncc.cpp @@ -0,0 +1,581 @@ +#include +#include +#include +#include +#include "memfile.h" +#include "sp_file.h" +#include "amx.h" +#include "amxdbg.h" +#include "osdefs.h" +#include "zlib/zlib.h" +#if defined LINUX || defined DARWIN +#include +#elif defined WIN32 +#include +#endif + +enum FileSections +{ + FS_Code, /* required */ + FS_Data, /* required */ + FS_Publics, + FS_Pubvars, + FS_Natives, + FS_Nametable, /* required */ + FS_DbgFile, + FS_DbgSymbol, + FS_DbgLine, + FS_DbgTags, + FS_DbgNatives, + FS_DbgAutomaton, + FS_DbgState, + FS_DbgStrings, + FS_DbgInfo, + FS_Tags, + /* --- */ + FS_Number, +}; + +int pc_printf(const char *message,...); +int pc_compile(int argc, char **argv); +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf); + +memfile_t *bin_file = NULL; +jmp_buf brkout; + +#define sARGS_MAX 32 /* number of arguments a function can have, max */ +#define sDIMEN_MAX 4 /* maximum number of array dimensions */ + +typedef struct t_arg_s +{ + uint8_t ident; + int16_t tag; + char *name; + uint16_t dimcount; + sp_fdbg_arraydim_t dims[sDIMEN_MAX]; +} t_arg; + +typedef struct t_native_s +{ + char *name; + int16_t ret_tag; + uint16_t num_args; + t_arg args[sARGS_MAX]; +} t_native; + +t_native *native_list = NULL; + +int main(int argc, char *argv[]) +{ + if (pc_compile(argc,argv) != 0) + return 1; + + AMX_HEADER *hdr; + AMX_DBG_HDR *dbg = NULL; + int err; + uint32_t i; + sp_file_t *spf; + memfile_t *dbgtab = NULL; //dbgcrab + unsigned char *dbgptr = NULL; + uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0}; + FILE *fp; + + if (bin_file == NULL) + return 0; + + hdr = (AMX_HEADER *)bin_file->base; + + if ((spf=spfw_create(bin_file->name, NULL)) == NULL) { + pc_printf("Error creating binary file!\n"); + memfile_destroy(bin_file); + return 0; + } + + if ((err=setjmp(brkout))!=0) + goto write_error; + + spfw_add_section(spf, ".code"); + spfw_add_section(spf, ".data"); + + sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize; + if (sections[FS_Publics]) + spfw_add_section(spf, ".publics"); + sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize; + if (sections[FS_Pubvars]) + spfw_add_section(spf, ".pubvars"); + sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize; + if (sections[FS_Natives]) + spfw_add_section(spf, ".natives"); + sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize; + if (sections[FS_Tags]) + spfw_add_section(spf, ".tags"); + + spfw_add_section(spf, ".names"); + + if (hdr->flags & AMX_FLAG_DEBUG) { + dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size); + if (dbg->magic != AMX_DBG_MAGIC) { + pc_printf("Error reading AMX_DBG_HDR, debug data will not be written."); + } else { + dbgtab = memfile_creat("", 512); + dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR); + if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0) + spfw_add_section(spf, ".dbg.natives"); + if (dbg->files) { + spfw_add_section(spf, ".dbg.files"); + sections[FS_DbgFile] = dbg->files; + } + if (dbg->lines) { + spfw_add_section(spf, ".dbg.lines"); + sections[FS_DbgLine] = dbg->lines; + } + if (dbg->symbols) { + spfw_add_section(spf, ".dbg.symbols"); + sections[FS_DbgSymbol] = dbg->symbols; + } + sections[FS_DbgInfo] = 1; + sections[FS_DbgStrings] = 1; + spfw_add_section(spf, ".dbg.info"); + spfw_add_section(spf, ".dbg.strings"); + } + } + + spfw_finalize_header(spf); + + /** + * Begin writing each of our known tables out + */ + + if (sections[FS_Code]) { + sp_file_code_t cod; + unsigned char *cbase; + + cod.cellsize = sizeof(cell); + + cod.codesize = hdr->dat - hdr->cod; + cod.codeversion = hdr->amx_version; + cod.flags = 0; + if (hdr->flags & AMX_FLAG_DEBUG) + { + cod.flags |= SP_FLAG_DEBUG; + } + cod.code = sizeof(cod); + cod.main = hdr->cip; + + /* write the code */ + cbase = (unsigned char *)hdr + hdr->cod; + sfwrite(&cod, sizeof(cod), 1, spf); + sfwrite(cbase, cod.codesize, 1, spf); + + spfw_next_section(spf); + } + + if (sections[FS_Data]) { + sp_file_data_t dat; + unsigned char *dbase = (unsigned char *)hdr + hdr->dat; + + dat.datasize = hdr->hea - hdr->dat; + dat.memsize = hdr->stp; + dat.data = sizeof(dat); + + /* write header */ + sfwrite(&dat, sizeof(dat), 1, spf); + + if (dat.datasize) { + /* write data */ + sfwrite(dbase, dat.datasize, 1, spf); + } + + spfw_next_section(spf); + } + + if (sections[FS_Publics]) { + sp_file_publics_t *pbtbl; + AMX_FUNCSTUBNT *stub; + unsigned char *stubptr; + uint32_t publics = sections[FS_Publics]; + + pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics); + stubptr = (unsigned char *)hdr + hdr->publics; + + for (i=0; iaddress; + pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); + + stubptr += hdr->defsize; + } + if (publics) + sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf); + free(pbtbl); + + spfw_next_section(spf); + } + + if (sections[FS_Pubvars]) { + sp_file_pubvars_t *pbvars; + AMX_FUNCSTUBNT *stub; + unsigned char *stubptr; + uint32_t pubvars = sections[FS_Pubvars]; + + pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars); + stubptr = (unsigned char *)hdr + hdr->pubvars; + + for (i=0; iaddress; + pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); + + stubptr += hdr->defsize; + } + if (pubvars) + sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf); + free(pbvars); + spfw_next_section(spf); + } + + if (sections[FS_Natives]) { + sp_file_natives_t *nvtbl; + AMX_FUNCSTUBNT *stub; + unsigned char *stubptr; + uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize; + + nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives); + stubptr = (unsigned char *)hdr + hdr->natives; + + for (i=0; inameofs - (hdr->nametable + sizeof(uint16_t)); + + stubptr += hdr->defsize; + } + if (natives) { + sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf); + } + free(nvtbl); + spfw_next_section(spf); + } + + if (sections[FS_Tags]) { + uint32_t numTags = (uint32_t)sections[FS_Tags]; + AMX_FUNCSTUBNT *stub; + sp_file_tag_t tag; + + for (i=0; itags + (i * hdr->defsize)); + tag.tag_id = stub->address; + tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t)); + sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf); + } + spfw_next_section(spf); + } + + if (sections[FS_Nametable]) { + unsigned char *base; + uint32_t namelen; + + /* write the entire block */ + base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t); + /** + * note - the name table will be padded to sizeof(cell) bytes. + * this may clip at most an extra three bytes in! + */ + namelen = hdr->cod - hdr->nametable; + sfwrite(base, namelen, 1, spf); + spfw_next_section(spf); + } + + if (hdr->flags & AMX_FLAG_DEBUG) { + sp_fdbg_info_t info; + + memset(&info, 0, sizeof(sp_fdbg_info_t)); + + if (sections[FS_Natives]) { + uint16_t j; + uint32_t idx; + uint32_t name; + uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize; + + sfwrite(&natives, sizeof(uint32_t), 1, spf); + for (idx=0; idxname); + /* store */ + dbgfile.addr = _ptr->address; + dbgfile.name = (uint32_t)memfile_tell(dbgtab); + sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf); + /* write to tab, then move to next */ + memfile_write(dbgtab, _ptr->name, len + 1); + dbgptr += sizeof(AMX_DBG_FILE) + len; + info.num_files++; + } + spfw_next_section(spf); + } + + if (sections[FS_DbgLine]) { + uint32_t idx; + AMX_DBG_LINE *line; + sp_fdbg_line_t dbgline; + for (idx=0; idxaddress; + dbgline.line = (uint32_t)line->line; + sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf); + /* move to next */ + dbgptr += sizeof(AMX_DBG_LINE); + info.num_lines++; + } + spfw_next_section(spf); + } + + if (sections[FS_DbgSymbol]) { + uint32_t idx; + uint32_t dnum; + AMX_DBG_SYMBOL *sym; + AMX_DBG_SYMDIM *dim; + sp_fdbg_symbol_t dbgsym; + sp_fdbg_arraydim_t dbgdim; + uint32_t len; + + for (idx=0; idxaddress; + dbgsym.tagid = sym->tag; + dbgsym.codestart = (uint32_t)sym->codestart; + dbgsym.codeend = (uint32_t)sym->codeend; + dbgsym.dimcount = (uint16_t)sym->dim; + dbgsym.vclass = (uint8_t)sym->vclass; + dbgsym.ident = (uint8_t)sym->ident; + dbgsym.name = (uint32_t)memfile_tell(dbgtab); + sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf); + /* write to tab */ + len = strlen(sym->name); + memfile_write(dbgtab, sym->name, len + 1); + /* move to next */ + dbgptr += sizeof(AMX_DBG_SYMBOL) + len; + /* look for any dimensions */ + info.num_syms++; + for (dnum=0; dnumsize; + dbgdim.tagid = dim->tag; + sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf); + /* move to next */ + dbgptr += sizeof(AMX_DBG_SYMDIM); + info.num_arrays++; + } + } + spfw_next_section(spf); + } + + sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf); + spfw_next_section(spf); + + if (sections[FS_DbgStrings]) { + sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf); + spfw_next_section(spf); + } + } + + spfw_finalize_all(spf); + + /** + * do compression + * new block for scoping only + */ + { + memfile_t *pOrig = (memfile_t *)spf->handle; + sp_file_hdr_t *pHdr; + unsigned char *proper; + size_t size; + Bytef *zcmp; + uLong disksize; + size_t header_size; + int err = Z_OK; + + /* reuse this memory block! */ + memfile_reset(bin_file); + + /* copy tip of header */ + memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t)); + + /* get pointer to header */ + pHdr = (sp_file_hdr_t *)bin_file->base; + + /* copy the rest of the header */ + memfile_write(bin_file, + (unsigned char *)pOrig->base + sizeof(sp_file_hdr_t), + pHdr->dataoffs - sizeof(sp_file_hdr_t)); + + header_size = pHdr->dataoffs; + size = pHdr->imagesize - header_size; + proper = (unsigned char *)pOrig->base + header_size; + + /* get initial size estimate */ + disksize = compressBound(pHdr->imagesize); + pHdr->disksize = (uint32_t)disksize; + zcmp = (Bytef *)malloc(pHdr->disksize); + + if ((err=compress2(zcmp, + &disksize, + (Bytef *)proper, + (uLong)size, + Z_BEST_COMPRESSION)) + != Z_OK) + { + free(zcmp); + pc_printf("Unable to compress (Z): error %d\n", err); + pc_printf("Falling back to no compression."); + memfile_write(bin_file, + proper, + size); + } else { + pHdr->disksize = (uint32_t)disksize + header_size; + pHdr->compression = SPFILE_COMPRESSION_GZ; + memfile_write(bin_file, + (unsigned char *)zcmp, + disksize); + free(zcmp); + } + } + + spfw_destroy(spf); + memfile_destroy(dbgtab); + + /** + * write file + */ + if ((fp=fopen(bin_file->name, "wb")) != NULL) { + fwrite(bin_file->base, bin_file->usedoffs, 1, fp); + fclose(fp); + } else { + pc_printf("Unable to open %s for writing!", bin_file->name); + } + + memfile_destroy(bin_file); + + return 0; + +write_error: + pc_printf("Error writing to file: %s", bin_file->name); + + spfw_destroy(spf); + unlink(bin_file->name); + memfile_destroy(bin_file); + memfile_destroy(dbgtab); + + return 1; +} + +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf) +{ + if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count) + longjmp(brkout, 1); +} + +void sp_fdbg_ntv_start(int num_natives) +{ + if (num_natives == 0) + return; + + native_list = (t_native *)malloc(sizeof(t_native) * num_natives); + memset(native_list, 0, sizeof(t_native) * num_natives); +} + +#include "sc.h" +void sp_fdbg_ntv_hook(int index, symbol *sym) +{ + int i, j; + t_native *native; + + native = &native_list[index]; + native->name = strdup(sym->name); + + for (i = 0; i < sMAXARGS; i++) { + if (sym->dim.arglist[i].ident == 0) + break; + native->num_args++; + native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0]; + native->args[i].name = strdup(sym->dim.arglist[i].name); + native->args[i].ident = sym->dim.arglist[i].ident; + native->args[i].dimcount = sym->dim.arglist[i].numdim; + for (j = 0; j < native->args[i].dimcount; j++) { + native->args[i].dims[j].size = sym->dim.arglist[i].dim[j]; + native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j]; + } + } + + native->ret_tag = sym->tag; +} + + +#if defined __linux__ || defined __APPLE__ +extern "C" void __cxa_pure_virtual(void) +{ +} + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void *ptr) +{ + free(ptr); +} + +void operator delete[](void * ptr) +{ + free(ptr); +} +#endif diff --git a/sourcepawn/compiler/sc.h b/sourcepawn/compiler/sc.h index 0e9fa60c..aaab83c3 100644 --- a/sourcepawn/compiler/sc.h +++ b/sourcepawn/compiler/sc.h @@ -537,18 +537,13 @@ typedef enum s_optmark { #define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1) -/* interface functions */ -#if defined __cplusplus - extern "C" { -#endif - /* * Functions you call from the "driver" program */ int pc_compile(int argc, char **argv); -int pc_addconstant(char *name,cell value,int tag); -int pc_addtag(char *name); -int pc_addtag_flags(char *name, int flags); +int pc_addconstant(const char *name,cell value,int tag); +int pc_addtag(const char *name); +int pc_addtag_flags(const char *name, int flags); int pc_findtag(const char *name); constvalue *pc_tagptr(const char *name); int pc_enablewarning(int number,int enable); @@ -564,7 +559,7 @@ const char *type_to_name(int tag); int pc_printf(const char *message,...); /* error report function */ -int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr); +int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr); /* input from source file */ void *pc_opensrc(char *filename); /* reading only */ @@ -580,7 +575,7 @@ int pc_eofsrc(void *handle); void *pc_openasm(char *filename); /* read/write */ void pc_closeasm(void *handle,int deletefile); void pc_resetasm(void *handle); -int pc_writeasm(void *handle,char *str); +int pc_writeasm(void *handle,const char *str); char *pc_readasm(void *handle,char *target,int maxchars); /* output to binary (.AMX) file */ @@ -590,161 +585,144 @@ void pc_resetbin(void *handle,long offset); int pc_writebin(void *handle,void *buffer,int size); long pc_lengthbin(void *handle); /* return the length of the file */ -#if defined __cplusplus - } -#endif - - -/* by default, functions and variables used in throughout the compiler - * files are "external" - */ -#if !defined SC_FUNC - #define SC_FUNC -#endif -#if !defined SC_VDECL - #define SC_VDECL extern -#endif -#if !defined SC_VDEFINE - #define SC_VDEFINE -#endif - void sp_fdbg_ntv_start(int num_natives); void sp_fdbg_ntv_hook(int index, symbol *sym); /* function prototypes in SC1.C */ -SC_FUNC void set_extension(char *filename,char *extension,int force); -SC_FUNC symbol *fetchfunc(char *name); -SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag); -SC_FUNC char *funcdisplayname(char *dest,char *funcname); -SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr); -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index); -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index); -SC_FUNC void delete_consttable(constvalue *table); -SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag); -SC_FUNC void exporttag(int tag); -SC_FUNC void sc_attachdocumentation(symbol *sym); -SC_FUNC constvalue *find_tag_byval(int tag); -SC_FUNC int get_actual_compound(symbol *sym); +void set_extension(char *filename,const char *extension,int force); +symbol *fetchfunc(char *name); +char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag); +char *funcdisplayname(char *dest,char *funcname); +int exprconst(cell *val,int *tag,symbol **symptr); +constvalue *append_constval(constvalue *table,const char *name,cell val,int index); +constvalue *find_constval(constvalue *table,char *name,int index); +void delete_consttable(constvalue *table); +symbol *add_constant(const char *name,cell val,int vclass,int tag); +void exporttag(int tag); +void sc_attachdocumentation(symbol *sym); +constvalue *find_tag_byval(int tag); +int get_actual_compound(symbol *sym); /* function prototypes in SC2.C */ #define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); } #define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); } #define POPSTK_P() (popstk().pv) #define POPSTK_I() (popstk().i) -SC_FUNC void pushstk(stkitem val); -SC_FUNC stkitem popstk(void); -SC_FUNC void clearstk(void); -SC_FUNC int plungequalifiedfile(char *name); /* explicit path included */ -SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */ -SC_FUNC void preprocess(void); -SC_FUNC void lexinit(void); -SC_FUNC int lex(cell *lexvalue,char **lexsym); -SC_FUNC int lextok(token_t *tok); -SC_FUNC int lexpeek(int id); -SC_FUNC void lexpush(void); -SC_FUNC void lexclr(int clreol); -SC_FUNC int matchtoken(int token); -SC_FUNC int tokeninfo(cell *val,char **str); -SC_FUNC int needtoken(int token); -SC_FUNC int matchtoken2(int id, token_t *tok); -SC_FUNC int expecttoken(int id, token_t *tok); -SC_FUNC int matchsymbol(token_ident_t *ident); -SC_FUNC int needsymbol(token_ident_t *ident); -SC_FUNC int peek_same_line(); -SC_FUNC int require_newline(int allow_semi); -SC_FUNC void litadd(cell value); -SC_FUNC void litinsert(cell value,int pos); -SC_FUNC int alphanum(char c); -SC_FUNC int ishex(char c); -SC_FUNC void delete_symbol(symbol *root,symbol *sym); -SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions); -SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom); -SC_FUNC void markusage(symbol *sym,int usage); -SC_FUNC symbol *findglb(const char *name,int filter); -SC_FUNC symbol *findloc(const char *name); -SC_FUNC symbol *findconst(const char *name,int *matchtag); -SC_FUNC symbol *finddepend(const symbol *parent); -SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage); -SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, +void pushstk(stkitem val); +stkitem popstk(void); +void clearstk(void); +int plungequalifiedfile(char *name); /* explicit path included */ +int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */ +void preprocess(void); +void lexinit(void); +int lex(cell *lexvalue,char **lexsym); +int lextok(token_t *tok); +int lexpeek(int id); +void lexpush(void); +void lexclr(int clreol); +int matchtoken(int token); +int tokeninfo(cell *val,char **str); +int needtoken(int token); +int matchtoken2(int id, token_t *tok); +int expecttoken(int id, token_t *tok); +int matchsymbol(token_ident_t *ident); +int needsymbol(token_ident_t *ident); +int peek_same_line(); +int require_newline(int allow_semi); +void litadd(cell value); +void litinsert(cell value,int pos); +int alphanum(char c); +int ishex(char c); +void delete_symbol(symbol *root,symbol *sym); +void delete_symbols(symbol *root,int level,int del_labels,int delete_functions); +int refer_symbol(symbol *entry,symbol *bywhom); +void markusage(symbol *sym,int usage); +symbol *findglb(const char *name,int filter); +symbol *findloc(const char *name); +symbol *findconst(const char *name,int *matchtag); +symbol *finddepend(const symbol *parent); +symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage); +symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[]); -SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, +symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[],int slength); -SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength); -SC_FUNC int getlabel(void); -SC_FUNC char *itoh(ucell val); +symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength); +int getlabel(void); +char *itoh(ucell val); #define MATCHTAG_COERCE 0x1 // allow coercion #define MATCHTAG_SILENT 0x2 // silence the error(213) warning #define MATCHTAG_COMMUTATIVE 0x4 // order does not matter /* function prototypes in SC3.C */ -SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam, +int check_userop(void (*oper)(void),int tag1,int tag2,int numparam, value *lval,int *resulttag); -SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce); -SC_FUNC int checktag(int tags[],int numtags,int exprtag); -SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval); -SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state); -SC_FUNC cell array_totalsize(symbol *sym); -SC_FUNC int matchtag_string(int ident, int tag); -SC_FUNC int checktag_string(value *sym1, value *sym2); -SC_FUNC int checktags_string(int tags[], int numtags, value *sym1); -SC_FUNC int lvalexpr(svalue *sval); +int matchtag(int formaltag,int actualtag,int allowcoerce); +int checktag(int tags[],int numtags,int exprtag); +int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval); +int sc_getstateid(constvalue **automaton,constvalue **state); +cell array_totalsize(symbol *sym); +int matchtag_string(int ident, int tag); +int checktag_string(value *sym1, value *sym2); +int checktags_string(int tags[], int numtags, value *sym1); +int lvalexpr(svalue *sval); /* function prototypes in SC4.C */ -SC_FUNC void writeleader(symbol *root); -SC_FUNC void writetrailer(void); -SC_FUNC void begcseg(void); -SC_FUNC void begdseg(void); -SC_FUNC void setline(int chkbounds); -SC_FUNC void setfiledirect(char *name); -SC_FUNC void setlinedirect(int line); -SC_FUNC void setlabel(int index); -SC_FUNC void markexpr(optmark type,const char *name,cell offset); -SC_FUNC void startfunc(char *fname); -SC_FUNC void endfunc(void); -SC_FUNC void alignframe(int numbytes); -SC_FUNC void rvalue(value *lval); -SC_FUNC void address(symbol *ptr,regid reg); -SC_FUNC void store(value *lval); -SC_FUNC void loadreg(cell address,regid reg); -SC_FUNC void storereg(cell address,regid reg); -SC_FUNC void memcopy(cell size); -SC_FUNC void copyarray(symbol *sym,cell size); -SC_FUNC void fillarray(symbol *sym,cell size,cell value); -SC_FUNC void ldconst(cell val,regid reg); -SC_FUNC void moveto1(void); -SC_FUNC void move_alt(void); -SC_FUNC void pushreg(regid reg); -SC_FUNC void pushval(cell val); -SC_FUNC void popreg(regid reg); -SC_FUNC void genarray(int dims, int _autozero); -SC_FUNC void swap1(void); -SC_FUNC void ffswitch(int label); -SC_FUNC void ffcase(cell value,char *labelname,int newtable); -SC_FUNC void ffcall(symbol *sym,const char *label,int numargs); -SC_FUNC void ffret(int remparams); -SC_FUNC void ffabort(int reason); -SC_FUNC void ffbounds(cell size); -SC_FUNC void jumplabel(int number); -SC_FUNC void defstorage(void); -SC_FUNC void modstk(int delta); -SC_FUNC void setstk(cell value); -SC_FUNC void modheap(int delta); -SC_FUNC void modheap_i(); -SC_FUNC void setheap_pri(void); -SC_FUNC void setheap(cell value); -SC_FUNC void cell2addr(void); -SC_FUNC void cell2addr_alt(void); -SC_FUNC void addr2cell(void); -SC_FUNC void char2addr(void); -SC_FUNC void charalign(void); -SC_FUNC void addconst(cell value); -SC_FUNC void setheap_save(cell value); -SC_FUNC void stradjust(regid reg); -SC_FUNC void invoke_getter(struct methodmap_method_s *method); -SC_FUNC void invoke_setter(struct methodmap_method_s *method, int save); -SC_FUNC void inc_pri(); -SC_FUNC void dec_pri(); +void writeleader(symbol *root); +void writetrailer(void); +void begcseg(void); +void begdseg(void); +void setline(int chkbounds); +void setfiledirect(char *name); +void setlinedirect(int line); +void setlabel(int index); +void markexpr(optmark type,const char *name,cell offset); +void startfunc(char *fname); +void endfunc(void); +void alignframe(int numbytes); +void rvalue(value *lval); +void address(symbol *ptr,regid reg); +void store(value *lval); +void loadreg(cell address,regid reg); +void storereg(cell address,regid reg); +void memcopy(cell size); +void copyarray(symbol *sym,cell size); +void fillarray(symbol *sym,cell size,cell value); +void ldconst(cell val,regid reg); +void moveto1(void); +void move_alt(void); +void pushreg(regid reg); +void pushval(cell val); +void popreg(regid reg); +void genarray(int dims, int _autozero); +void swap1(void); +void ffswitch(int label); +void ffcase(cell value,char *labelname,int newtable); +void ffcall(symbol *sym,const char *label,int numargs); +void ffret(int remparams); +void ffabort(int reason); +void ffbounds(cell size); +void jumplabel(int number); +void defstorage(void); +void modstk(int delta); +void setstk(cell value); +void modheap(int delta); +void modheap_i(); +void setheap_pri(void); +void setheap(cell value); +void cell2addr(void); +void cell2addr_alt(void); +void addr2cell(void); +void char2addr(void); +void charalign(void); +void addconst(cell value); +void setheap_save(cell value); +void stradjust(regid reg); +void invoke_getter(struct methodmap_method_s *method); +void invoke_setter(struct methodmap_method_s *method, int save); +void inc_pri(); +void dec_pri(); +void load_hidden_arg(); /* Code generation functions for arithmetic operators. * @@ -754,218 +732,204 @@ SC_FUNC void dec_pri(); * | +--------- "u"nsigned operator, "s"igned operator or "b"oth * +------------- "o"perator */ -SC_FUNC void os_mult(void); /* multiplication (signed) */ -SC_FUNC void os_div(void); /* division (signed) */ -SC_FUNC void os_mod(void); /* modulus (signed) */ -SC_FUNC void ob_add(void); /* addition */ -SC_FUNC void ob_sub(void); /* subtraction */ -SC_FUNC void ob_sal(void); /* shift left (arithmetic) */ -SC_FUNC void os_sar(void); /* shift right (arithmetic, signed) */ -SC_FUNC void ou_sar(void); /* shift right (logical, unsigned) */ -SC_FUNC void ob_or(void); /* bitwise or */ -SC_FUNC void ob_xor(void); /* bitwise xor */ -SC_FUNC void ob_and(void); /* bitwise and */ -SC_FUNC void ob_eq(void); /* equality */ -SC_FUNC void ob_ne(void); /* inequality */ -SC_FUNC void relop_prefix(void); -SC_FUNC void relop_suffix(void); -SC_FUNC void os_le(void); /* less or equal (signed) */ -SC_FUNC void os_ge(void); /* greater or equal (signed) */ -SC_FUNC void os_lt(void); /* less (signed) */ -SC_FUNC void os_gt(void); /* greater (signed) */ +void os_mult(void); /* multiplication (signed) */ +void os_div(void); /* division (signed) */ +void os_mod(void); /* modulus (signed) */ +void ob_add(void); /* addition */ +void ob_sub(void); /* subtraction */ +void ob_sal(void); /* shift left (arithmetic) */ +void os_sar(void); /* shift right (arithmetic, signed) */ +void ou_sar(void); /* shift right (logical, unsigned) */ +void ob_or(void); /* bitwise or */ +void ob_xor(void); /* bitwise xor */ +void ob_and(void); /* bitwise and */ +void ob_eq(void); /* equality */ +void ob_ne(void); /* inequality */ +void relop_prefix(void); +void relop_suffix(void); +void os_le(void); /* less or equal (signed) */ +void os_ge(void); /* greater or equal (signed) */ +void os_lt(void); /* less (signed) */ +void os_gt(void); /* greater (signed) */ -SC_FUNC void lneg(void); -SC_FUNC void neg(void); -SC_FUNC void invert(void); -SC_FUNC void nooperation(void); -SC_FUNC void inc(value *lval); -SC_FUNC void dec(value *lval); -SC_FUNC void jmp_ne0(int number); -SC_FUNC void jmp_eq0(int number); -SC_FUNC void outval(cell val,int newline); +void lneg(void); +void neg(void); +void invert(void); +void nooperation(void); +void inc(value *lval); +void dec(value *lval); +void jmp_ne0(int number); +void jmp_eq0(int number); +void outval(cell val,int newline); /* function prototypes in SC5.C */ -SC_FUNC int error(int number,...); -SC_FUNC void errorset(int code,int line); +int error(int number,...); +void errorset(int code,int line); /* function prototypes in SC6.C */ -SC_FUNC int assemble(FILE *fout,FILE *fin); +int assemble(void *fout,void *fin); /* function prototypes in SC7.C */ -SC_FUNC void stgbuffer_cleanup(void); -SC_FUNC void stgmark(char mark); -SC_FUNC void stgwrite(const char *st); -SC_FUNC void stgout(int index); -SC_FUNC void stgdel(int index,cell code_index); -SC_FUNC int stgget(int *index,cell *code_index); -SC_FUNC void stgset(int onoff); -SC_FUNC int phopt_init(void); -SC_FUNC int phopt_cleanup(void); +void stgbuffer_cleanup(void); +void stgmark(char mark); +void stgwrite(const char *st); +void stgout(int index); +void stgdel(int index,cell code_index); +int stgget(int *index,cell *code_index); +void stgset(int onoff); +int phopt_init(void); +int phopt_cleanup(void); /* function prototypes in SCLIST.C */ -SC_FUNC char* duplicatestring(const char* sourcestring); -SC_FUNC stringpair *insert_alias(char *name,char *alias); -SC_FUNC stringpair *find_alias(char *name); -SC_FUNC int lookup_alias(char *target,char *name); -SC_FUNC void delete_aliastable(void); -SC_FUNC stringlist *insert_path(char *path); -SC_FUNC char *get_path(int index); -SC_FUNC void delete_pathtable(void); -SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen); -SC_FUNC int get_subst(int index,char **pattern,char **substitution); -SC_FUNC stringpair *find_subst(char *name,int length); -SC_FUNC int delete_subst(char *name,int length); -SC_FUNC void delete_substtable(void); -SC_FUNC stringlist *insert_sourcefile(char *string); -SC_FUNC char *get_sourcefile(int index); -SC_FUNC void delete_sourcefiletable(void); -SC_FUNC stringlist *insert_docstring(char *string); -SC_FUNC char *get_docstring(int index); -SC_FUNC void delete_docstring(int index); -SC_FUNC void delete_docstringtable(void); -SC_FUNC stringlist *insert_autolist(char *string); -SC_FUNC char *get_autolist(int index); -SC_FUNC void delete_autolisttable(void); -SC_FUNC stringlist *insert_dbgfile(const char *filename); -SC_FUNC stringlist *insert_dbgline(int linenr); -SC_FUNC stringlist *insert_dbgsymbol(symbol *sym); -SC_FUNC char *get_dbgstring(int index); -SC_FUNC void delete_dbgstringtable(void); -SC_FUNC stringlist *get_dbgstrings(); - -/* function prototypes in SCMEMFILE.C */ -#if !defined tMEMFILE - typedef unsigned char MEMFILE; - #define tMEMFILE 1 -#endif -MEMFILE *mfcreate(const char *filename); -void mfclose(MEMFILE *mf); -int mfdump(MEMFILE *mf); -long mflength(const MEMFILE *mf); -long mfseek(MEMFILE *mf,long offset,int whence); -unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size); -unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size); -char *mfgets(MEMFILE *mf,char *string,unsigned int size); -int mfputs(MEMFILE *mf,const char *string); +char* duplicatestring(const char* sourcestring); +stringpair *insert_alias(char *name,char *alias); +stringpair *find_alias(char *name); +int lookup_alias(char *target,char *name); +void delete_aliastable(void); +stringlist *insert_path(char *path); +char *get_path(int index); +void delete_pathtable(void); +stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen); +int get_subst(int index,char **pattern,char **substitution); +stringpair *find_subst(char *name,int length); +int delete_subst(char *name,int length); +void delete_substtable(void); +stringlist *insert_sourcefile(char *string); +char *get_sourcefile(int index); +void delete_sourcefiletable(void); +stringlist *insert_docstring(char *string); +char *get_docstring(int index); +void delete_docstring(int index); +void delete_docstringtable(void); +stringlist *insert_autolist(const char *string); +char *get_autolist(int index); +void delete_autolisttable(void); +stringlist *insert_dbgfile(const char *filename); +stringlist *insert_dbgline(int linenr); +stringlist *insert_dbgsymbol(symbol *sym); +char *get_dbgstring(int index); +void delete_dbgstringtable(void); +stringlist *get_dbgstrings(); /* function prototypes in SCI18N.C */ #define MAXCODEPAGE 12 -SC_FUNC int cp_path(const char *root,const char *directory); -SC_FUNC int cp_set(const char *name); -SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr); -SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr); -SC_FUNC int scan_utf8(FILE *fp,const char *filename); +int cp_path(const char *root,const char *directory); +int cp_set(const char *name); +cell cp_translate(const unsigned char *string,const unsigned char **endptr); +cell get_utf8_char(const unsigned char *string,const unsigned char **endptr); +int scan_utf8(void *fp,const char *filename); /* function prototypes in SCSTATE.C */ -SC_FUNC constvalue *automaton_add(const char *name); -SC_FUNC constvalue *automaton_find(const char *name); -SC_FUNC constvalue *automaton_findid(int id); -SC_FUNC constvalue *state_add(const char *name,int fsa_id); -SC_FUNC constvalue *state_find(const char *name,int fsa_id); -SC_FUNC constvalue *state_findid(int id); -SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid); -SC_FUNC int state_addlist(int *list,int count,int fsa_id); -SC_FUNC void state_deletetable(void); -SC_FUNC int state_getfsa(int listid); -SC_FUNC int state_count(int listid); -SC_FUNC int state_inlist(int listid,int state); -SC_FUNC int state_listitem(int listid,int index); -SC_FUNC void state_conflict(symbol *root); -SC_FUNC int state_conflict_id(int listid1,int listid2); +constvalue *automaton_add(const char *name); +constvalue *automaton_find(const char *name); +constvalue *automaton_findid(int id); +constvalue *state_add(const char *name,int fsa_id); +constvalue *state_find(const char *name,int fsa_id); +constvalue *state_findid(int id); +void state_buildlist(int **list,int *listsize,int *count,int stateid); +int state_addlist(int *list,int count,int fsa_id); +void state_deletetable(void); +int state_getfsa(int listid); +int state_count(int listid); +int state_inlist(int listid,int state); +int state_listitem(int listid,int index); +void state_conflict(symbol *root); +int state_conflict_id(int listid1,int listid2); /* external variables (defined in scvars.c) */ #if !defined SC_SKIP_VDECL typedef struct HashTable HashTable; -SC_VDECL struct HashTable *sp_Globals; -SC_VDECL symbol loctab; /* local symbol table */ -SC_VDECL symbol glbtab; /* global symbol table */ -SC_VDECL cell *litq; /* the literal queue */ -SC_VDECL unsigned char pline[]; /* the line read from the input file */ -SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */ -SC_VDECL constvalue tagname_tab;/* tagname table */ -SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */ -SC_VDECL constvalue *curlibrary;/* current library */ -SC_VDECL int pc_addlibtable; /* is the library table added to the AMX file? */ -SC_VDECL symbol *curfunc; /* pointer to current function */ -SC_VDECL char *inpfname; /* name of the file currently read from */ -SC_VDECL char outfname[]; /* intermediate (assembler) file name */ -SC_VDECL char binfname[]; /* binary file name */ -SC_VDECL char errfname[]; /* error file name */ -SC_VDECL char sc_ctrlchar; /* the control character (or escape character) */ -SC_VDECL char sc_ctrlchar_org;/* the default control character */ -SC_VDECL int litidx; /* index to literal table */ -SC_VDECL int litmax; /* current size of the literal table */ -SC_VDECL int stgidx; /* index to the staging buffer */ -SC_VDECL int sc_labnum; /* number of (internal) labels */ -SC_VDECL int staging; /* true if staging output */ -SC_VDECL cell declared; /* number of local cells declared */ -SC_VDECL cell glb_declared; /* number of global cells declared */ -SC_VDECL cell code_idx; /* number of bytes with generated code */ -SC_VDECL int ntv_funcid; /* incremental number of native function */ -SC_VDECL int errnum; /* number of errors */ -SC_VDECL int warnnum; /* number of warnings */ -SC_VDECL int sc_debug; /* debug/optimization options (bit field) */ -SC_VDECL int sc_packstr; /* strings are packed by default? */ -SC_VDECL int sc_asmfile; /* create .ASM file? */ -SC_VDECL int sc_listing; /* create .LST file? */ -SC_VDECL int sc_compress; /* compress bytecode? */ -SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */ -SC_VDECL int sc_dataalign; /* data alignment value */ -SC_VDECL int sc_alignnext; /* must frame of the next function be aligned? */ -SC_VDECL int pc_docexpr; /* must expression be attached to documentation comment? */ -SC_VDECL int sc_showincludes; /* show include files? */ -SC_VDECL int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */ -SC_VDECL cell pc_stksize; /* stack size */ -SC_VDECL cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */ -SC_VDECL cell pc_amxram; /* abstract machine data size limit */ -SC_VDECL int freading; /* is there an input file ready for reading? */ -SC_VDECL int fline; /* the line number in the current file */ -SC_VDECL short fnumber; /* number of files in the file table (debugging) */ -SC_VDECL short fcurrent; /* current file being processed (debugging) */ -SC_VDECL short sc_intest; /* true if inside a test */ -SC_VDECL int sideeffect; /* true if an expression causes a side-effect */ -SC_VDECL int stmtindent; /* current indent of the statement */ -SC_VDECL int indent_nowarn; /* skip warning "217 loose indentation" */ -SC_VDECL int sc_tabsize; /* number of spaces that a TAB represents */ -SC_VDECL short sc_allowtags; /* allow/detect tagnames in lex() */ -SC_VDECL int sc_status; /* read/write status */ -SC_VDECL int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */ -SC_VDECL int sc_rationaltag; /* tag for rational numbers */ -SC_VDECL int rational_digits; /* number of fractional digits */ -SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */ -SC_VDECL short sc_is_utf8; /* is this source file in UTF-8 encoding */ -SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */ -SC_VDECL int sc_curstates; /* ID of the current state list */ -SC_VDECL int pc_optimize; /* (peephole) optimization level */ -SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */ -SC_VDECL int pc_functag; /* global function tag */ -SC_VDECL int pc_tag_string; /* global String tag */ -SC_VDECL int pc_tag_void; /* global void tag */ -SC_VDECL int pc_tag_object; /* root object tag */ -SC_VDECL int pc_tag_bool; /* global bool tag */ -SC_VDECL int pc_tag_null_t; /* the null type */ -SC_VDECL int pc_tag_nullfunc_t; /* the null function type */ -SC_VDECL int pc_anytag; /* global any tag */ -SC_VDECL int glbstringread; /* last global string read */ -SC_VDECL int sc_require_newdecls; /* only newdecls are allowed */ +extern struct HashTable *sp_Globals; +extern symbol loctab; /* local symbol table */ +extern symbol glbtab; /* global symbol table */ +extern cell *litq; /* the literal queue */ +extern unsigned char pline[]; /* the line read from the input file */ +extern const unsigned char *lptr;/* points to the current position in "pline" */ +extern constvalue tagname_tab;/* tagname table */ +extern constvalue libname_tab;/* library table (#pragma library "..." syntax) */ +extern constvalue *curlibrary;/* current library */ +extern int pc_addlibtable; /* is the library table added to the AMX file? */ +extern symbol *curfunc; /* pointer to current function */ +extern char *inpfname; /* name of the file currently read from */ +extern char outfname[]; /* intermediate (assembler) file name */ +extern char binfname[]; /* binary file name */ +extern char errfname[]; /* error file name */ +extern char sc_ctrlchar; /* the control character (or escape character) */ +extern char sc_ctrlchar_org;/* the default control character */ +extern int litidx; /* index to literal table */ +extern int litmax; /* current size of the literal table */ +extern int stgidx; /* index to the staging buffer */ +extern int sc_labnum; /* number of (internal) labels */ +extern int staging; /* true if staging output */ +extern cell declared; /* number of local cells declared */ +extern cell glb_declared; /* number of global cells declared */ +extern cell code_idx; /* number of bytes with generated code */ +extern int ntv_funcid; /* incremental number of native function */ +extern int errnum; /* number of errors */ +extern int warnnum; /* number of warnings */ +extern int sc_debug; /* debug/optimization options (bit field) */ +extern int sc_packstr; /* strings are packed by default? */ +extern int sc_asmfile; /* create .ASM file? */ +extern int sc_listing; /* create .LST file? */ +extern int sc_compress; /* compress bytecode? */ +extern int sc_needsemicolon;/* semicolon required to terminate expressions? */ +extern int sc_dataalign; /* data alignment value */ +extern int sc_alignnext; /* must frame of the next function be aligned? */ +extern int pc_docexpr; /* must expression be attached to documentation comment? */ +extern int sc_showincludes; /* show include files? */ +extern int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */ +extern cell pc_stksize; /* stack size */ +extern cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */ +extern cell pc_amxram; /* abstract machine data size limit */ +extern int freading; /* is there an input file ready for reading? */ +extern int fline; /* the line number in the current file */ +extern short fnumber; /* number of files in the file table (debugging) */ +extern short fcurrent; /* current file being processed (debugging) */ +extern short sc_intest; /* true if inside a test */ +extern int sideeffect; /* true if an expression causes a side-effect */ +extern int stmtindent; /* current indent of the statement */ +extern int indent_nowarn; /* skip warning "217 loose indentation" */ +extern int sc_tabsize; /* number of spaces that a TAB represents */ +extern short sc_allowtags; /* allow/detect tagnames in lex() */ +extern int sc_status; /* read/write status */ +extern int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */ +extern int sc_rationaltag; /* tag for rational numbers */ +extern int rational_digits; /* number of fractional digits */ +extern int sc_allowproccall;/* allow/detect tagnames in lex() */ +extern short sc_is_utf8; /* is this source file in UTF-8 encoding */ +extern char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */ +extern int sc_curstates; /* ID of the current state list */ +extern int pc_optimize; /* (peephole) optimization level */ +extern int pc_memflags; /* special flags for the stack/heap usage */ +extern int pc_functag; /* global function tag */ +extern int pc_tag_string; /* global String tag */ +extern int pc_tag_void; /* global void tag */ +extern int pc_tag_object; /* root object tag */ +extern int pc_tag_bool; /* global bool tag */ +extern int pc_tag_null_t; /* the null type */ +extern int pc_tag_nullfunc_t; /* the null function type */ +extern int pc_anytag; /* global any tag */ +extern int glbstringread; /* last global string read */ +extern int sc_require_newdecls; /* only newdecls are allowed */ -SC_VDECL constvalue sc_automaton_tab; /* automaton table */ -SC_VDECL constvalue sc_state_tab; /* state table */ +extern constvalue sc_automaton_tab; /* automaton table */ +extern constvalue sc_state_tab; /* state table */ -SC_VDECL FILE *inpf; /* file read from (source or include) */ -SC_VDECL FILE *inpf_org; /* main source file */ -SC_VDECL FILE *outf; /* file written to */ +extern void *inpf; /* file read from (source or include) */ +extern void *inpf_org; /* main source file */ +extern void *outf; /* file written to */ -SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */ +extern jmp_buf errbuf; /* target of longjmp() on a fatal error */ #if !defined SC_LIGHT - SC_VDECL int sc_makereport; /* generate a cross-reference report */ + extern int sc_makereport; /* generate a cross-reference report */ #endif #if defined WIN32 -#if !defined snprintf -#define snprintf _snprintf -#endif +# if !defined snprintf +# define snprintf _snprintf +# define vsnprintf _vsnprintf +# endif #endif #endif /* SC_SKIP_VDECL */ diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.cpp similarity index 95% rename from sourcepawn/compiler/sc1.c rename to sourcepawn/compiler/sc1.cpp index 6f07e61d..80fdad7b 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.cpp @@ -193,9 +193,6 @@ char g_tmpfile[_MAX_PATH] = {0}; /* "main" of the compiler */ -#if defined __cplusplus - extern "C" -#endif int pc_compile(int argc, char *argv[]) { int entry,i,jmpcode; @@ -582,10 +579,7 @@ cleanup: return retcode; } -#if defined __cplusplus - extern "C" -#endif -int pc_addconstant(char *name,cell value,int tag) +int pc_addconstant(const char *name,cell value,int tag) { errorset(sFORCESET,0); /* make sure error engine is silenced */ sc_status=statIDLE; @@ -678,20 +672,19 @@ int pc_findtag(const char *name) return -1; } -#if defined __cplusplus - extern "C" -#endif -int pc_addtag(char *name) +int pc_addtag(const char *name) { int val; int flags = 0; if (name==NULL) { /* no tagname was given, check for one */ - if (lex(&val,&name)!=tLABEL) { + char *nameptr; + if (lex(&val,&nameptr)!=tLABEL) { lexpush(); return 0; /* untagged */ } /* if */ + name = nameptr; } /* if */ if (isupper(*name)) @@ -700,12 +693,12 @@ int pc_addtag(char *name) return pc_addtag_flags(name, flags); } -int pc_addtag_flags(char *name, int flags) +int pc_addtag_flags(const char *name, int flags) { constvalue *ptr; int last,tag; - assert(strchr(name,':')==NULL); /* colon should already have been stripped */ + assert((flags & FUNCTAG) || strchr(name,':')==NULL); /* colon should already have been stripped */ last=0; ptr=tagname_tab.next; while (ptr!=NULL) { @@ -831,7 +824,7 @@ static char *get_extension(char *filename) * Set the default extension, or force an extension. To erase the * extension of a filename, set "extension" to an empty string. */ -SC_FUNC void set_extension(char *filename,char *extension,int force) +void set_extension(char *filename,const char *extension,int force) { char *ptr; @@ -1362,35 +1355,14 @@ static void setconstants(void) add_constant("false",0,sGLOBAL,1); add_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */ add_constant("INVALID_FUNCTION", -1, sGLOBAL, pc_tag_nullfunc_t); - #if PAWN_CELL_SIZE==16 - add_constant("cellbits",16,sGLOBAL,0); - #if defined _I16_MAX - add_constant("cellmax",_I16_MAX,sGLOBAL,0); - add_constant("cellmin",_I16_MIN,sGLOBAL,0); - #else - add_constant("cellmax",SHRT_MAX,sGLOBAL,0); - add_constant("cellmin",SHRT_MIN,sGLOBAL,0); - #endif - #elif PAWN_CELL_SIZE==32 - add_constant("cellbits",32,sGLOBAL,0); - #if defined _I32_MAX - add_constant("cellmax",_I32_MAX,sGLOBAL,0); - add_constant("cellmin",_I32_MIN,sGLOBAL,0); - #else - add_constant("cellmax",LONG_MAX,sGLOBAL,0); - add_constant("cellmin",LONG_MIN,sGLOBAL,0); - #endif - #elif PAWN_CELL_SIZE==64 - #if !defined _I64_MIN - #define _I64_MIN (-9223372036854775807ULL - 1) - #define _I64_MAX 9223372036854775807ULL - #endif - add_constant("cellbits",64,sGLOBAL,0); - add_constant("cellmax",_I64_MAX,sGLOBAL,0); - add_constant("cellmin",_I64_MIN,sGLOBAL,0); - #else - #error Unsupported cell size - #endif + add_constant("cellbits",32,sGLOBAL,0); +#if defined _I32_MAX + add_constant("cellmax",_I32_MAX,sGLOBAL,0); + add_constant("cellmin",_I32_MIN,sGLOBAL,0); +#else + add_constant("cellmax",LONG_MAX,sGLOBAL,0); + add_constant("cellmin",LONG_MIN,sGLOBAL,0); +#endif add_constant("charbits",sCHARBITS,sGLOBAL,0); add_constant("charmin",0,sGLOBAL,0); add_constant("charmax",~(-1 << sCHARBITS) - 1,sGLOBAL,0); @@ -1948,14 +1920,12 @@ static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct) static void declglb(declinfo_t *decl,int fpublic,int fstatic,int fstock) { int ispublic; - cell val,cidx; + cell cidx; ucell address; int glb_incr; - char *str; int slength=0; short filenum; symbol *sym; - constvalue *enumroot; #if !defined NDEBUG cell glbdecl=0; #endif @@ -2750,8 +2720,11 @@ static cell initvector(int ident,int tag,cell size,int fillzero, } while (matchtoken(',')); /* do */ needtoken('}'); } else { - init(ident,&ctag,errorfound); - matchtag(tag,ctag,TRUE); + if (!lexpeek('}')) + { + init(ident,&ctag,errorfound); + matchtag(tag,ctag,TRUE); + } } /* if */ /* fill up the literal queue with a series */ if (ellips) { @@ -2794,7 +2767,7 @@ static cell init(int ident,int *tag,int *errorfound) litidx=1; /* reset literal queue */ } /* if */ *tag=pc_tag_string; - } else if (constexpr(&i,tag,NULL)){ + } else if (exprconst(&i,tag,NULL)){ litadd(i); /* store expression result in literal table */ } else { if (errorfound!=NULL) @@ -2819,7 +2792,7 @@ static cell needsub(int *tag,constvalue **enumroot) if (matchtoken(']')) /* we have already seen "[" */ return 0; /* zero size (like "char msg[]") */ - constexpr(&val,tag,&sym); /* get value (must be constant expression) */ + exprconst(&val,tag,&sym); /* get value (must be constant expression) */ if (val<0) { error(9); /* negative array size is invalid; assumed zero */ val=0; @@ -2891,7 +2864,7 @@ static void decl_const(int vclass) symbolline=fline; /* save line where symbol was found */ needtoken('='); - constexpr(&val,&exprtag,NULL); /* get value */ + exprconst(&val,&exprtag,NULL); /* get value */ /* add_constant() checks for duplicate definitions */ /* temporarily reset the line number to where the symbol was defined */ @@ -3202,8 +3175,6 @@ static void parse_old_array_dims(declinfo_t *decl, int flags) stgset(FALSE); } else { do { - cell size; - if (type->numdim == sDIMEN_MAX) { error(53); return; @@ -3281,7 +3252,7 @@ static int parse_old_decl(declinfo_t *decl, int flags) strcpy(decl->name, "__unknown__"); } else { if (!lexpeek(tSYMBOL)) { - extern char *sc_tokens[]; + extern const char *sc_tokens[]; switch (lextok(&tok)) { case tOBJECT: case tCHAR: @@ -3404,7 +3375,6 @@ static int reparse_new_decl(declinfo_t *decl, int flags) // int parse_decl(declinfo_t *decl, int flags) { - token_t tok; token_ident_t ident; memset(decl, 0, sizeof(*decl)); @@ -4059,19 +4029,36 @@ static void domethodmap(LayoutSpec spec) require_newline(TRUE); } +class AutoStage +{ + public: + AutoStage() : lcl_staging_(FALSE) + { + if (!staging) { + stgset(TRUE); + lcl_staging_ = TRUE; + lcl_stgidx_ = stgidx; + assert(stgidx == 0); + } + } + ~AutoStage() { + if (lcl_staging_) { + stgout(lcl_stgidx_); + stgset(FALSE); + } + } + + private: + int lcl_staging_; + int lcl_stgidx_; +}; + // delete ::= "delete" expr static void dodelete() { + AutoStage staging_on; + svalue sval; - - int lcl_staging = FALSE; - if (!staging) { - stgset(TRUE); - lcl_staging = TRUE; - assert(stgidx == 0); - } - int lcl_stgidx = stgidx; - int ident = lvalexpr(&sval); needtoken(tTERM); @@ -4079,7 +4066,7 @@ static void dodelete() case iFUNCTN: case iREFFUNC: error(115, "functions"); - goto cleanup; + return; case iARRAY: case iREFARRAY: @@ -4089,7 +4076,7 @@ static void dodelete() symbol *sym = sval.val.sym; if (!sym || sym->dim.array.level > 0) { error(115, "arrays"); - goto cleanup; + return; } break; } @@ -4097,13 +4084,13 @@ static void dodelete() if (sval.val.tag == 0) { error(115, "primitive types or enums"); - goto cleanup; + return; } methodmap_t *map = methodmap_find_by_tag(sval.val.tag); if (!map) { error(115, pc_tagname(sval.val.tag)); - goto cleanup; + return; } { @@ -4119,7 +4106,7 @@ static void dodelete() if (!map || !map->dtor) { error(115, layout_spec_name(map->spec), map->name); - goto cleanup; + return; } // Only zap non-const lvalues. @@ -4180,12 +4167,6 @@ static void dodelete() } markexpr(sEXPR, NULL, 0); - -cleanup: - if (lcl_staging) { - stgout(lcl_stgidx); - stgset(FALSE); - } } /** @@ -4201,7 +4182,7 @@ static void parse_function_type(functag_t *type) needtoken(tFUNCTION); type->ret_tag = parse_new_typename(NULL); - type->type = uPUBLIC; + type->usage = uPUBLIC; needtoken('('); @@ -4223,6 +4204,9 @@ static void parse_function_type(functag_t *type) continue; } + // Account for strings. + fix_char_size(&decl); + funcarg_t *arg = &type->args[type->argcount++]; arg->tagcount = 1; arg->tags[0] = decl.type.tag; @@ -4367,13 +4351,13 @@ static void dofuncenum(int listmode) * rather than the constant value. And even if we could, we'd have to change the assembler recognize that. */ if (l == tPUBLIC) { - func.type = uPUBLIC; + func.usage = uPUBLIC; } else { error(1, "-public-", str); } } else { func.ret_tag = newStyleTag; - func.type = uPUBLIC; + func.usage = uPUBLIC; } needtoken('('); do { @@ -4523,11 +4507,11 @@ static void decl_enum(int vclass) multiplier=1; if (matchtoken('(')) { if (matchtoken(taADD)) { - constexpr(&increment,NULL,NULL); + exprconst(&increment,NULL,NULL); } else if (matchtoken(taMULT)) { - constexpr(&multiplier,NULL,NULL); + exprconst(&multiplier,NULL,NULL); } else if (matchtoken(taSHL)) { - constexpr(&val,NULL,NULL); + exprconst(&val,NULL,NULL); while (val-->0) multiplier*=2; } /* if */ @@ -4568,12 +4552,12 @@ static void decl_enum(int vclass) size=increment; /* default increment of 'val' */ fieldtag=0; /* default field tag */ if (matchtoken('[')) { - constexpr(&size,&fieldtag,NULL); /* get size */ + exprconst(&size,&fieldtag,NULL); /* get size */ needtoken(']'); } /* if */ /* :TODO: do we need a size modifier here for pc_tag_string? */ if (matchtoken('=')) - constexpr(&value,NULL,NULL); /* get value */ + exprconst(&value,NULL,NULL); /* get value */ /* add_constant() checks whether a variable (global or local) or * a constant with the same name already exists */ @@ -4734,7 +4718,7 @@ static int compare_tag(int tag1, int tag2) * Finds a function in the global symbol table or creates a new entry. * It does some basic processing and error checking. */ -SC_FUNC symbol *fetchfunc(char *name) +symbol *fetchfunc(char *name) { symbol *sym; @@ -4963,7 +4947,7 @@ static char *tag2str(char *dest,int tag) return isdigit(dest[1]) ? &dest[1] : dest; } -SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag) +char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag) { char tagstr1[10], tagstr2[10]; int opertok; @@ -5013,7 +4997,7 @@ constvalue *find_tag_byval(int tag) return tagsym; } -SC_FUNC char *funcdisplayname(char *dest,char *funcname) +char *funcdisplayname(char *dest,char *funcname) { int tags[2]; char opname[10]; @@ -5064,7 +5048,7 @@ static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag) int tok; char *str; cell val,size; - symbol *sym,*sub; + symbol *sym; int fnative = (tokid == tNATIVE || tokid == tMETHODMAP); int fpublic = (tokid == tPUBLIC); @@ -5125,7 +5109,7 @@ static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag) tokeninfo(&val,&str); insert_alias(sym->name,str); } else { - constexpr(&val,NULL,NULL); + exprconst(&val,NULL,NULL); sym->addr=val; /* At the moment, I have assumed that this syntax is only valid if * val < 0. To properly mix "normal" native functions and indexed @@ -5172,7 +5156,6 @@ static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstati char *str; cell val,cidx,glbdecl; short filenum; - int state_id; assert(litidx==0); /* literal queue should be empty */ litidx=0; /* clear the literal pool (should already be empty) */ @@ -5279,7 +5262,7 @@ static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstati } /* if */ if ((sym->flags & flgDEPRECATED) != 0 && (sym->usage & uSTOCK) == 0) { - char *ptr= (sym->documentation!=NULL) ? sym->documentation : ""; + const char *ptr= (sym->documentation!=NULL) ? sym->documentation : ""; error(234, decl->name, ptr); /* deprecated (probably a public function) */ } /* if */ begcseg(); @@ -5443,10 +5426,9 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag) { char *ptr; int argcnt,oldargcnt,tok; - cell val; arginfo arg, *arglist; char name[sNAMEMAX+1]; - int ident,fpublic; + int fpublic; int idx; /* if the function is already defined earlier, get the number of arguments @@ -5470,7 +5452,7 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag) memset(argptr, 0, sizeof(*argptr)); strcpy(argptr->name, "this"); argptr->ident = iVARIABLE; - argptr->tags = malloc(sizeof(int)); + argptr->tags = (int *)malloc(sizeof(int)); argptr->tags[0] = *thistag; argptr->numtags = 1; } else { @@ -5632,7 +5614,6 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag) static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, arginfo *arg) { symbol *argsym; - constvalue *enumroot; int slength=0; typeinfo_t *type = &decl->type; @@ -5728,7 +5709,7 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi while (paranthese--) needtoken(')'); } else { - constexpr(&arg->defvalue.val,&arg->defvalue_tag,NULL); + exprconst(&arg->defvalue.val,&arg->defvalue_tag,NULL); assert(type->numtags > 0); matchtag(type->tags[0], arg->defvalue_tag, TRUE); } /* if */ @@ -5773,11 +5754,12 @@ static int count_referrers(symbol *entry) } #if !defined SC_LIGHT -static int find_xmltag(char *source,char *xmltag,char *xmlparam,char *xmlvalue, +static int find_xmltag(char *source, const char *xmltag, const char *xmlparam, const char *xmlvalue, char **outer_start,int *outer_length, - char **inner_start,int *inner_length) + const char **inner_start,int *inner_length) { - char *ptr,*inner_end; + char *ptr; + const char *inner_end; int xmltag_len,xmlparam_len,xmlvalue_len; int match; @@ -6120,7 +6102,8 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) assert(sym->dim.arglist!=NULL); for (arg=0; sym->dim.arglist[arg].ident!=0; arg++) { int dim,paraminfo; - char *outer_start,*inner_start; + char *outer_start; + const char *inner_start; int outer_length,inner_length; if (sym->dim.arglist[arg].ident==iVARARGS) fprintf(log,"\t\t\t\n"); @@ -6173,10 +6156,9 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) && find_xmltag(sym->documentation, "param", "name", sym->dim.arglist[arg].name, &outer_start, &outer_length, &inner_start, &inner_length)) { - char *tail; fprintf(log,"\t\t\t\t%.*s\n",inner_length,inner_start); /* delete from documentation string */ - tail=outer_start+outer_length; + char *tail=outer_start+outer_length; memmove(outer_start,tail,strlen(tail)+1); } /* if */ fprintf(log,"\t\t\t\n"); @@ -6500,7 +6482,7 @@ static constvalue *insert_constval(constvalue *prev,constvalue *next,const char return cur; } -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index) +constvalue *append_constval(constvalue *table,const char *name,cell val,int index) { constvalue *cur,*prev; @@ -6510,7 +6492,7 @@ SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val, return insert_constval(prev,NULL,name,val,index); } -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index) +constvalue *find_constval(constvalue *table,char *name,int index) { constvalue *ptr = table->next; @@ -6553,7 +6535,7 @@ static int delete_constval(constvalue *table,char *name) } #endif -SC_FUNC void delete_consttable(constvalue *table) +void delete_consttable(constvalue *table) { constvalue *cur=table->next, *next; @@ -6569,7 +6551,7 @@ SC_FUNC void delete_consttable(constvalue *table) * * Adds a symbol to the symbol table. Returns NULL on failure. */ -SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag) +symbol *add_constant(const char *name,cell val,int vclass,int tag) { symbol *sym; @@ -6901,9 +6883,9 @@ static int doexpr2(int comma,int chkeffect,int allowarray,int mark_endexpr, return ident; } -/* constexpr +/* exprconst */ -SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr) +int exprconst(cell *val,int *tag,symbol **symptr) { int ident,index; cell cidx; @@ -6978,7 +6960,7 @@ static int test(int label,int parens,int invert) if (endtok!=0) needtoken(endtok); if (ident==iARRAY || ident==iREFARRAY) { - char *ptr=(sym->name!=NULL) ? sym->name : "-unknown-"; + const char *ptr=(sym->name!=NULL) ? sym->name : "-unknown-"; error(33,ptr); /* array must be indexed */ } /* if */ if (ident==iCONSTEXPR) { /* constant expression */ @@ -7294,7 +7276,7 @@ static void doswitch(void) * parse all expressions until that special token. */ - constexpr(&val,NULL,NULL); + exprconst(&val,NULL,NULL); /* Search the insertion point (the table is kept in sorted order, so * that advanced abstract machines can sift the case table with a * binary search). Check for duplicate case values at the same time. @@ -7466,6 +7448,18 @@ static symbol *fetchlab(char *name) return sym; } +static int is_variadic(symbol *sym) +{ + assert(sym->ident==iFUNCTN); + arginfo *arg = sym->dim.arglist; + while (arg->ident) { + if (arg->ident == iVARARGS) + return TRUE; + arg++; + } + return FALSE; +} + /* doreturn * * Global references: rettype (altered) @@ -7574,7 +7568,11 @@ static void doreturn(void) * it stays on the heap for the moment, and it is removed -usually- at * the end of the expression/statement, see expression() in SC3.C) */ - address(sub,sALT); /* ALT = destination */ + if (is_variadic(curfunc)) { + load_hidden_arg(); + } else { + address(sub,sALT); /* ALT = destination */ + } arraysize=calc_arraysize(dim,numdim,0); memcopy(arraysize*sizeof(cell)); /* source already in PRI */ /* moveto1(); is not necessary, callfunction() does a popreg() */ @@ -7624,7 +7622,7 @@ static void docont(void) jumplabel(ptr[wqLOOP]); } -SC_FUNC void exporttag(int tag) +void exporttag(int tag) { /* find the tag by value in the table, then set the top bit to mark it * "public" diff --git a/sourcepawn/compiler/sc2.c b/sourcepawn/compiler/sc2.cpp similarity index 94% rename from sourcepawn/compiler/sc2.c rename to sourcepawn/compiler/sc2.cpp index f1b6505d..b03d6929 100644 --- a/sourcepawn/compiler/sc2.c +++ b/sourcepawn/compiler/sc2.cpp @@ -47,7 +47,7 @@ static cell litchar(const unsigned char **lptr,int flags); static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int automaton,int *cmptag); static void substallpatterns(unsigned char *line,int buffersize); -static int match(char *st,int end); +static int match(const char *st,int end); static int alpha(char c); #define SKIPMODE 1 /* bit field in "#if" stack */ @@ -86,7 +86,7 @@ static double pow10(double d) static stkitem *stack=NULL; static int stkidx=0,stktop=0; -SC_FUNC void pushstk(stkitem val) +void pushstk(stkitem val) { assert(stkidx<=stktop); if (stkidx==stktop) { @@ -109,7 +109,7 @@ SC_FUNC void pushstk(stkitem val) stkidx+=1; } -SC_FUNC stkitem popstk(void) +stkitem popstk(void) { if (stkidx==0) { stkitem s; @@ -121,7 +121,7 @@ SC_FUNC stkitem popstk(void) return stack[stkidx]; } -SC_FUNC void clearstk(void) +void clearstk(void) { assert(stack!=NULL || stktop==0); if (stack!=NULL) { @@ -132,9 +132,10 @@ SC_FUNC void clearstk(void) assert(stktop==0); } -SC_FUNC int plungequalifiedfile(char *name) +int plungequalifiedfile(char *name) { -static char *extensions[] = { ".inc", ".p", ".pawn" }; + static const char *extensions[] = { ".inc", ".p", ".pawn" }; + void *fp; char *ext; int ext_idx; @@ -184,7 +185,7 @@ static char *extensions[] = { ".inc", ".p", ".pawn" }; return TRUE; } -SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths) +int plungefile(char *name,int try_currentpath,int try_includepaths) { int result=FALSE; @@ -671,11 +672,11 @@ static int ftoi(cell *val,const unsigned char *curptr) exp=(exp*10)+(*ptr-'0'); ptr++; } /* while */ - #if defined __GNUC__ - fmult=pow10(exp*sign); - #else - fmult=pow(10,exp*sign); - #endif +#if defined __GNUC__ + fmult=pow10(exp*sign); +#else + fmult=pow(10.0,exp*sign); +#endif fnum *= fmult; dnum *= (unsigned long)(fmult+0.5); } /* if */ @@ -796,7 +797,7 @@ static int preproc_expr(cell *val,int *tag) term=strchr((char*)pline,'\0'); assert(term!=NULL); chrcat((char*)pline,PREPROC_TERM); /* the "DEL" code (see SC.H) */ - result=constexpr(val,tag,NULL); /* get value (or 0 on error) */ + result=exprconst(val,tag,NULL); /* get value (or 0 on error) */ *term='\0'; /* erase the token (if still present) */ lexclr(FALSE); /* clear any "pushed" tokens */ return result; @@ -1251,7 +1252,7 @@ static int command(void) break; default: { char s2[20]; - extern char *sc_tokens[];/* forward declaration */ + extern const char *sc_tokens[];/* forward declaration */ if (tok<256) sprintf(s2,"%c",(char)tok); else @@ -1482,7 +1483,7 @@ static char *strdel(char *str,size_t len) return str; } -static char *strins(char *dest,char *src,size_t srclen) +static char *strins(char *dest,const char *src,size_t srclen) { size_t destlen=strlen(dest); assert(srclen<=strlen(src)); @@ -1792,7 +1793,7 @@ static int scanellipsis(const unsigned char *lptr) * pline (altered) * freading (referred to only) */ -SC_FUNC void preprocess(void) +void preprocess(void) { int iscommand; @@ -1931,7 +1932,7 @@ static full_token_t *next_token() return &sTokenBuffer->tokens[cursor]; } -SC_FUNC void lexinit(void) +void lexinit(void) { stkidx=0; /* index for pushstk() and popstk() */ iflevel=0; /* preprocessor: nesting of "#if" is currently 0 */ @@ -1943,7 +1944,7 @@ SC_FUNC void lexinit(void) sTokenBuffer = &sNormalBuffer; } -char *sc_tokens[] = { +const char *sc_tokens[] = { "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=", "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--", "...", "..", "::", @@ -2000,10 +2001,9 @@ static void lexpop() sTokenBuffer->cursor = 0; } -SC_FUNC int lex(cell *lexvalue,char **lexsym) +int lex(cell *lexvalue,char **lexsym) { int i,toolong,newline; - char **tokptr; const unsigned char *starttoken; if (sTokenBuffer->depth > 0) { @@ -2054,7 +2054,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym) tok->start.col = (int)(lptr - pline); i=tFIRST; - tokptr=sc_tokens; + const char **tokptr=sc_tokens; while (i<=tMIDDLE) { /* match multi-character operators */ if (*lptr==**tokptr && match(*tokptr,FALSE)) { tok->id = i; @@ -2259,7 +2259,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym) * to read and return the information from these variables, rather than * to read in a new token from the input file. */ -SC_FUNC void lexpush(void) +void lexpush(void) { assert(sTokenBuffer->depth < MAX_TOKEN_DEPTH); sTokenBuffer->depth++; @@ -2276,7 +2276,7 @@ SC_FUNC void lexpush(void) * symbol (a not continue with some old one). This is required upon return * from Assembler mode, and in a few cases after detecting an syntax error. */ -SC_FUNC void lexclr(int clreol) +void lexclr(int clreol) { sTokenBuffer->depth = 0; if (clreol) { @@ -2286,7 +2286,7 @@ SC_FUNC void lexclr(int clreol) } // Return true if the symbol is ahead, false otherwise. -SC_FUNC int lexpeek(int id) +int lexpeek(int id) { if (matchtoken(id)) { lexpush(); @@ -2305,7 +2305,7 @@ SC_FUNC int lexpeek(int id) * (i.e. not present in the source code) should not be pushed back, which is * why it is sometimes important to distinguish the two. */ -SC_FUNC int matchtoken(int token) +int matchtoken(int token) { cell val; char *str; @@ -2338,7 +2338,7 @@ SC_FUNC int matchtoken(int token) * * The token itself is the return value. Normally, this one is already known. */ -SC_FUNC int tokeninfo(cell *val,char **str) +int tokeninfo(cell *val,char **str) { *val = current_token()->value; *str = current_token()->str; @@ -2352,7 +2352,7 @@ SC_FUNC int tokeninfo(cell *val,char **str) * this function returns 1 for "token found" and 2 for "statement termination * token" found; see function matchtoken() for details. */ -SC_FUNC int needtoken(int token) +int needtoken(int token) { char s1[20],s2[20]; int t; @@ -2379,7 +2379,7 @@ SC_FUNC int needtoken(int token) // If the next token is on the current line, return that token. Otherwise, // return tNEWLINE. -SC_FUNC int peek_same_line() +int peek_same_line() { // We should not call this without having parsed at least one token. assert(sTokenBuffer->num_tokens > 0); @@ -2407,7 +2407,7 @@ SC_FUNC int peek_same_line() return tEOL; } -SC_FUNC int require_newline(int allow_semi) +int require_newline(int allow_semi) { if (allow_semi) { // Semicolon must be on the same line. @@ -2440,7 +2440,7 @@ SC_FUNC int require_newline(int allow_semi) * * Global references: lptr (altered) */ -static int match(char *st,int end) +static int match(const char *st,int end) { int k; const unsigned char *ptr; @@ -2482,7 +2482,7 @@ static void chk_grow_litq(void) * Global references: litidx (altered) * litq (altered) */ -SC_FUNC void litadd(cell value) +void litadd(cell value) { chk_grow_litq(); assert(litidx='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'); } @@ -2717,7 +2717,7 @@ static void free_symbol(symbol *sym) free(sym); } -SC_FUNC void delete_symbol(symbol *root,symbol *sym) +void delete_symbol(symbol *root,symbol *sym) { symbol *origRoot=root; /* find the symbol and its predecessor @@ -2738,7 +2738,7 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym) free_symbol(sym); } -SC_FUNC int get_actual_compound(symbol *sym) +int get_actual_compound(symbol *sym) { if (sym->ident == iARRAY || sym->ident == iREFARRAY) { while (sym->parent) @@ -2748,7 +2748,7 @@ SC_FUNC int get_actual_compound(symbol *sym) return sym->compound; } -SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions) +void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions) { symbol *origRoot=root; symbol *sym,*parent_sym; @@ -2908,7 +2908,7 @@ static symbol *find_symbol_child(const symbol *root,const symbol *sym) * bywhom will be the function that uses a variable or that calls * the function. */ -SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom) +int refer_symbol(symbol *entry,symbol *bywhom) { int count; @@ -2950,7 +2950,7 @@ SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom) return TRUE; } -SC_FUNC void markusage(symbol *sym,int usage) +void markusage(symbol *sym,int usage) { assert(sym!=NULL); sym->usage |= (char)usage; @@ -2974,7 +2974,7 @@ SC_FUNC void markusage(symbol *sym,int usage) * * Returns a pointer to the global symbol (if found) or NULL (if not found) */ -SC_FUNC symbol *findglb(const char *name,int filter) +symbol *findglb(const char *name,int filter) { /* find a symbol with a matching automaton first */ symbol *sym=NULL; @@ -3010,12 +3010,12 @@ SC_FUNC symbol *findglb(const char *name,int filter) * Returns a pointer to the local symbol (if found) or NULL (if not found). * See add_symbol() how the deepest nesting level is searched first. */ -SC_FUNC symbol *findloc(const char *name) +symbol *findloc(const char *name) { return find_symbol(&loctab,name,-1,-1,NULL); } -SC_FUNC symbol *findconst(const char *name,int *cmptag) +symbol *findconst(const char *name,int *cmptag) { symbol *sym; @@ -3033,7 +3033,7 @@ SC_FUNC symbol *findconst(const char *name,int *cmptag) return sym; } -SC_FUNC symbol *finddepend(const symbol *parent) +symbol *finddepend(const symbol *parent) { symbol *sym; @@ -3048,7 +3048,7 @@ SC_FUNC symbol *finddepend(const symbol *parent) * Adds a symbol to the symbol table (either global or local variables, * or global and local constants). */ -SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,int usage) +symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,int usage) { symbol entry, **refer; @@ -3083,13 +3083,13 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i return add_symbol(&loctab,&entry,FALSE); } -SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, +symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[]) { return addvariable2(name,addr,ident,vclass,tag,dim,numdim,idxtag,0); } -SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength) +symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength) { typeinfo_t *type = &decl->type; return addvariable2( @@ -3105,7 +3105,7 @@ SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength) ); } -SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, +symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[],int slength) { symbol *sym; @@ -3154,7 +3154,7 @@ SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int * Returns te next internal label number. The global variable sc_labnum is * initialized to zero. */ -SC_FUNC int getlabel(void) +int getlabel(void) { return sc_labnum++; } @@ -3164,7 +3164,7 @@ SC_FUNC int getlabel(void) * Converts a number to a hexadecimal string and returns a pointer to that * string. This function is NOT re-entrant. */ -SC_FUNC char *itoh(ucell val) +char *itoh(ucell val) { static char itohstr[30]; char *ptr; @@ -3199,13 +3199,13 @@ static char itohstr[30]; return itohstr; } -SC_FUNC int lextok(token_t *tok) +int lextok(token_t *tok) { tok->id = lex(&tok->val, &tok->str); return tok->id; } -SC_FUNC int expecttoken(int id, token_t *tok) +int expecttoken(int id, token_t *tok) { int rval = needtoken(id); if (rval) { @@ -3217,7 +3217,7 @@ SC_FUNC int expecttoken(int id, token_t *tok) return FALSE; } -SC_FUNC int matchtoken2(int id, token_t *tok) +int matchtoken2(int id, token_t *tok) { if (matchtoken(id)) { tok->id = tokeninfo(&tok->val, &tok->str); @@ -3226,7 +3226,7 @@ SC_FUNC int matchtoken2(int id, token_t *tok) return FALSE; } -SC_FUNC int matchsymbol(token_ident_t *ident) +int matchsymbol(token_ident_t *ident) { if (lextok(&ident->tok) != tSYMBOL) { lexpush(); @@ -3237,7 +3237,7 @@ SC_FUNC int matchsymbol(token_ident_t *ident) return TRUE; } -SC_FUNC int needsymbol(token_ident_t *ident) +int needsymbol(token_ident_t *ident) { if (!expecttoken(tSYMBOL, &ident->tok)) return FALSE; diff --git a/sourcepawn/compiler/sc3.c b/sourcepawn/compiler/sc3.cpp similarity index 91% rename from sourcepawn/compiler/sc3.c rename to sourcepawn/compiler/sc3.cpp index 44d20d4f..42c49636 100644 --- a/sourcepawn/compiler/sc3.c +++ b/sourcepawn/compiler/sc3.cpp @@ -35,7 +35,7 @@ static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval, int (*hier)(value*),value *lval); static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval); static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval, - char *forcetag,int chkbitwise); + const char *forcetag,int chkbitwise); static int plnge1(int (*hier)(value *lval),value *lval); static void plnge2(void (*oper)(void), int (*hier)(value *lval), @@ -113,16 +113,20 @@ static int nextop(int *opidx,int *list) return FALSE; /* entire list scanned, nothing found */ } -SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam, +int check_userop(void (*oper)(void),int tag1,int tag2,int numparam, value *lval,int *resulttag) { -static char *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "", - "", "", "", "<=", ">=", "<", ">", "==", "!=" }; -static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, - FALSE, FALSE, FALSE, FALSE, FALSE, - TRUE, TRUE, TRUE, TRUE, FALSE, FALSE }; -static char *unoperstr[] = { "!", "-", "++", "--" }; -static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec }; + static const char *binoperstr[] = { + "*", "/", "%", "+", "-", "", "", "", + "", "", "", "<=", ">=", "<", ">", "==", "!=" + }; + static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, + TRUE, TRUE, TRUE, TRUE, FALSE, FALSE + }; + static const char *unoperstr[] = { "!", "-", "++", "--" }; + static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec }; + char opername[4] = "", symbolname[sNAMEMAX+1]; int i,swapparams,savepri,savealt; int paramspassed; @@ -286,7 +290,7 @@ static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec }; return TRUE; } -SC_FUNC int checktags_string(int tags[], int numtags, value *sym1) +int checktags_string(int tags[], int numtags, value *sym1) { int i; if (sym1->ident == iARRAY || sym1->ident == iREFARRAY) @@ -301,7 +305,7 @@ SC_FUNC int checktags_string(int tags[], int numtags, value *sym1) return FALSE; } -SC_FUNC int checktag_string(value *sym1, value *sym2) +int checktag_string(value *sym1, value *sym2) { if (sym1->ident == iARRAY || sym2->ident == iARRAY || sym1->ident == iREFARRAY || sym2->ident == iREFARRAY) @@ -317,7 +321,7 @@ SC_FUNC int checktag_string(value *sym1, value *sym2) return FALSE; } -SC_FUNC const char *type_to_name(int tag) +const char *type_to_name(int tag) { if (tag == 0) return "int"; @@ -335,7 +339,7 @@ SC_FUNC const char *type_to_name(int tag) return "unknown"; } -SC_FUNC int matchtag_string(int ident, int tag) +int matchtag_string(int ident, int tag) { if (ident == iARRAY || ident == iREFARRAY) return FALSE; @@ -413,15 +417,81 @@ static int matchobjecttags(int formaltag, int actualtag, int flags) return obj_typeerror(133, formaltag, actualtag); } -static int matchreturntag(functag_t *t, symbol *sym) +static int matchreturntag(const functag_t *formal, const functag_t *actual) { - if (t->ret_tag == sym->tag) - return TRUE; - if (t->ret_tag == pc_tag_void && (sym->tag == 0 && !(sym->usage & uRETVALUE))) + if (formal->ret_tag == actual->ret_tag) return TRUE; + if (formal->ret_tag == pc_tag_void) { + if (actual->ret_tag == 0 && !(actual->usage & uRETVALUE)) + return TRUE; + } return FALSE; } +static int funcarg_compare(const funcarg_t *formal, const funcarg_t *actual) +{ + // Check type. + if (actual->ident != formal->ident) + return FALSE; + + // Check rank. + if (actual->dimcount != formal->dimcount) + return FALSE; + + // Check arity. + for (int i = 0; i < formal->dimcount; i++) { + if (actual->dims[i] != formal->dims[i]) + return FALSE; + } + + // Check tags. + if (actual->tagcount != formal->tagcount) + return FALSE; + for (int i = 0; i < formal->tagcount; i++) { + // Note we invert the order we pass things to matchtag() here. If the + // typedef specifies base type X, and the function specifies derived + // type Y, we want this to type since such an assignment is valid. + // + // Most programming languages do not subtype arguments like this. We do + // it in SourcePawn to preserve compatibility during the Transitional + // Syntax effort. + int actual_tag = actual->tags[i]; + int formal_tag = formal->tags[i]; + if (!matchtag(actual_tag, formal_tag, MATCHTAG_SILENT|MATCHTAG_COERCE)) + return FALSE; + } + + return TRUE; +} + +static int functag_compare(const functag_t *formal, const functag_t *actual) +{ + // Check return types. + if (!matchreturntag(formal, actual)) + return FALSE; + + // Make sure there are no trailing arguments. + if (actual->argcount > formal->argcount) + return FALSE; + + // Check arguments. + for (int i = 0; i < formal->argcount; i++) { + const funcarg_t *formal_arg = &formal->args[i]; + + if (i >= actual->argcount) { + if (formal_arg->ommittable) + return TRUE; + return FALSE; + } + + const funcarg_t *actual_arg = &actual->args[i]; + if (!funcarg_compare(formal_arg, actual_arg)) + return FALSE; + } + + return TRUE; +} + static int matchfunctags(int formaltag, int actualtag) { if (formaltag == pc_functag && (actualtag & FUNCTAG)) @@ -433,141 +503,23 @@ static int matchfunctags(int formaltag, int actualtag) if (!(actualtag & FUNCTAG)) return FALSE; - constvalue *v = find_tag_byval(actualtag); - int index; - short usage = uPUBLIC; - symbol *sym, *found = NULL; - funcenum_t *e; - functag_t *t; - - if (strncmp(v->name, "$Func", 5) != 0) + functag_t *actual = functag_find_intrinsic(actualtag); + if (!actual) return FALSE; - /* Now we have to go about looking up each function in this enum. WHICH IS IT. */ - e = funcenums_find_byval(formaltag); + funcenum_t *e = funcenums_find_by_tag(formaltag); if (!e) return FALSE; - assert(v->name[5] == '@' || v->name[5] == '!'); - - /* Deduce which function type this is */ - if (v->name[5] == '@') - { - usage = uPUBLIC; - } else if (v->name[5] == '!') { - usage = uSTOCK; - } - - index = atoi(&v->name[6]); - - assert(index >= 0); - - /* Find the function, either by public idx or code addr */ - if (usage == uPUBLIC) { - for (sym=glbtab.next; sym!=NULL; sym=sym->next) { - if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL)) { - if (index-- == 0) { - found = sym; - break; - } - } - } - } else if (usage == uSTOCK) { - for (sym=glbtab.next; sym!=NULL; sym=sym->next) { - if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL)) { - if (sym->codeaddr == index) { - found = sym; - break; - } - } - } - } - - if (!found) { - assert(found); - return FALSE; - } - - /* Wow, we now have: - * 1) The functional enum deduced from formaltag - * 2) The function trying to be shoved in deduced from actualtag - * Now we have to check if it matches any one of the functags inside the enum. - */ - t = e->first; - while (t) { - int curarg,skip=0,i; - arginfo *func_arg; - funcarg_t *enum_arg; - /* Check return type first. */ - if (!matchreturntag(t, sym)) { - t = t->next; - continue; - } - /* Check usage */ - if (t->type != usage) { - t = t->next; - continue; - } - /* Begin iterating arguments */ - for (curarg=0; curargargcount; curarg++) { - enum_arg = &t->args[curarg]; - /* Check whether we've exhausted our arguments */ - if (sym->dim.arglist[curarg].ident == 0) { - /* Can we bail out early? */ - if (!enum_arg->ommittable) { - /* No! */ - skip = 1; - } - break; - } - func_arg = &sym->dim.arglist[curarg]; - /* First check the ident type */ - if (enum_arg->ident != func_arg->ident) { - skip = 1; - break; - } - /* Next check arrayness */ - if (enum_arg->dimcount != func_arg->numdim) { - skip = 1; - break; - } - if (enum_arg->dimcount > 0) { - for (i=0; idimcount; i++) { - if (enum_arg->dims[i] != func_arg->dim[i]) { - skip = 1; - break; - } - } - if (skip) - break; - } - /* Lastly, check the tags */ - if (enum_arg->tagcount != func_arg->numtags) { - skip = 1; - break; - } - /* They should all be in the same order just for clarity... */ - for (i=0; itagcount; i++) { - if (!matchtag(func_arg->tags[i], enum_arg->tags[i], MATCHTAG_SILENT|MATCHTAG_COERCE)) { - skip = 1; - break; - } - } - if (skip) - break; - } - if (!skip) { - /* Make sure there are no trailing arguments */ - if (sym->dim.arglist[curarg].ident == 0) - return TRUE; - } - t = t->next; + for (functag_t *formal = e->first; formal; formal = formal->next) { + if (functag_compare(formal, actual)) + return TRUE; } return FALSE; } -SC_FUNC int matchtag(int formaltag, int actualtag, int flags) +int matchtag(int formaltag, int actualtag, int flags) { if (formaltag == actualtag) return TRUE; @@ -771,7 +723,7 @@ static void checkfunction(value *lval) * Plunge to a lower level */ static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval, - char *forcetag,int chkbitwise) + const char *forcetag,int chkbitwise) { int lvalue,opidx; int count; @@ -914,10 +866,10 @@ static void plnge2(void (*oper)(void), checkfunction(lval1); checkfunction(lval2); if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) { - char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-"; + const char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-"; error(33,ptr); /* array must be indexed */ } else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) { - char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-"; + const char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-"; error(33,ptr); /* array must be indexed */ } /* if */ /* ??? ^^^ should do same kind of error checking with functions */ @@ -1006,7 +958,7 @@ static cell calc(cell left,void (*oper)(),cell right,char *boolresult) return 0; } -SC_FUNC int lvalexpr(svalue *sval) +int lvalexpr(svalue *sval) { memset(sval, 0, sizeof(*sval)); @@ -1019,7 +971,7 @@ SC_FUNC int lvalexpr(svalue *sval) return sval->val.ident; } -SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval) +int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval) { value lval={0}; pushheaplist(); @@ -1042,7 +994,7 @@ SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,valu return lval.ident; } -SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state) +int sc_getstateid(constvalue **automaton,constvalue **state) { char name[sNAMEMAX+1]; cell val; @@ -1085,7 +1037,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state) assert(*automaton!=NULL); *state=state_find(name,fsa); if (*state==NULL) { - char *fsaname=(*automaton)->name; + const char *fsaname=(*automaton)->name; if (*fsaname=='\0') fsaname="
"; error(87,name,fsaname); /* unknown state for automaton */ @@ -1095,7 +1047,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state) return 1; } -SC_FUNC cell array_totalsize(symbol *sym) +cell array_totalsize(symbol *sym) { cell length; @@ -2281,48 +2233,36 @@ restart: } /* if */ if (sym!=NULL && lval1->ident==iFUNCTN) { assert(sym->ident==iFUNCTN); - if (sc_allowproccall) { - // Note: this is unreachable in SourceMod, we don't support paren-less calls. - callfunction(sym,NULL,lval1,FALSE); - } else if ((sym->usage & uNATIVE) != uNATIVE) { - symbol *oldsym=sym; - int n=-1,iter=0; - int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0; - cell code_addr=0; - for (sym=glbtab.next; sym!=NULL; sym=sym->next) { - if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage))) - { - if (strcmp(sym->name, lval1->sym->name)==0) { - n = iter; - code_addr = sym->codeaddr; - break; - } - iter++; - } - } - if (n!=-1) { - char faketag[sNAMEMAX+1]; - lval1->sym=NULL; - lval1->ident=iCONSTEXPR; - /* Generate a quick pseudo-tag! */ - if (usage == uPUBLIC) { - lval1->constval=(n<<1)|1; - snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n); - } else { - lval1->constval=(code_addr<<1)|0; - snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr); - error(153); - } - lval1->tag=pc_addtag_flags(faketag, FIXEDTAG|FUNCTAG); - oldsym->usage |= uREAD; - sym->usage |= uREAD; - } else { - error(76); /* invalid function call, or syntax error */ - } /* if */ + + if (sym->usage & uNATIVE) { + error(76); return FALSE; - } else { - error(76); /* invalid function call, or syntax error */ } + + int public_index = 0; + symbol *target = NULL; + for (symbol *iter = glbtab.next; iter; iter = iter->next) { + if (iter->ident != iFUNCTN || iter->vclass != sGLOBAL) + continue; + if (strcmp(iter->name, lval1->sym->name) == 0) { + target = iter; + break; + } + if (iter->usage & uPUBLIC) + public_index++; + } + + if (!target || !(target->usage & uPUBLIC)) { + error(76); + return FALSE; + } + + funcenum_t *fe = funcenum_for_symbol(target); + lval1->sym = NULL; + lval1->ident = iCONSTEXPR; + lval1->constval = (public_index << 1) | 1; + lval1->tag = fe->tag; + target->usage |= uREAD; } /* if */ return lvalue; } @@ -2590,7 +2530,7 @@ static int nesting=0; sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */ if ((sym->flags & flgDEPRECATED)!=0) { - char *ptr= (sym->documentation!=NULL) ? sym->documentation : ""; + const char *ptr= (sym->documentation!=NULL) ? sym->documentation : ""; error(234,sym->name,ptr); /* deprecated (probably a native function) */ } /* if */ @@ -2621,10 +2561,9 @@ static int nesting=0; do { if (!pending_this && matchtoken('.')) { namedparams=TRUE; - if (needtoken(tSYMBOL)) - tokeninfo(&lexval,&lexstr); - else - lexstr=""; + if (!needtoken(tSYMBOL)) + break; + tokeninfo(&lexval,&lexstr); argpos=findnamedarg(arg,lexstr); if (argpos<0) { error(17,lexstr); /* undefined symbol */ diff --git a/sourcepawn/compiler/sc4.c b/sourcepawn/compiler/sc4.cpp similarity index 87% rename from sourcepawn/compiler/sc4.c rename to sourcepawn/compiler/sc4.cpp index 70c6f06f..b9c9fb5c 100644 --- a/sourcepawn/compiler/sc4.c +++ b/sourcepawn/compiler/sc4.cpp @@ -34,13 +34,14 @@ static int fcurseg; /* the file number (fcurrent) for the active segment */ +void load_i(); /* When a subroutine returns to address 0, the AMX must halt. In earlier * releases, the RET and RETN opcodes checked for the special case 0 address. * Today, the compiler simply generates a HALT instruction at address 0. So * a subroutine can savely return to 0, and then encounter a HALT. */ -SC_FUNC void writeleader(symbol *root) +void writeleader(symbol *root) { int lbl_nostate,lbl_table; int statecount; @@ -174,7 +175,7 @@ SC_FUNC void writeleader(symbol *root) * code_idx (altered) * glb_declared (altered) */ -SC_FUNC void writetrailer(void) +void writetrailer(void) { assert(sc_dataalign % opcodes(1) == 0); /* alignment must be a multiple of * the opcode size */ @@ -214,7 +215,7 @@ SC_FUNC void writetrailer(void) * Global references: curseg * fcurrent */ -SC_FUNC void begcseg(void) +void begcseg(void) { if (sc_status!=statSKIP && (curseg!=sIN_CSEG || fcurrent!=fcurseg)) { stgwrite("\n"); @@ -232,7 +233,7 @@ SC_FUNC void begcseg(void) * * Global references: curseg */ -SC_FUNC void begdseg(void) +void begdseg(void) { if (sc_status!=statSKIP && (curseg!=sIN_DSEG || fcurrent!=fcurseg)) { stgwrite("\n"); @@ -245,7 +246,7 @@ SC_FUNC void begdseg(void) } /* if */ } -SC_FUNC void setline(int chkbounds) +void setline(int chkbounds) { if (sc_asmfile) { stgwrite("\t; line "); @@ -262,7 +263,7 @@ SC_FUNC void setline(int chkbounds) } /* if */ } -SC_FUNC void setfiledirect(char *name) +void setfiledirect(char *name) { if (sc_status==statFIRST && sc_listing) { assert(name!=NULL); @@ -272,7 +273,7 @@ SC_FUNC void setfiledirect(char *name) } /* if */ } -SC_FUNC void setlinedirect(int line) +void setlinedirect(int line) { if (sc_status==statFIRST && sc_listing) { char string[40]; @@ -285,7 +286,7 @@ SC_FUNC void setlinedirect(int line) * * Post a code label (specified as a number), on a new line. */ -SC_FUNC void setlabel(int number) +void setlabel(int number) { assert(number>=0); stgwrite("l."); @@ -306,7 +307,7 @@ SC_FUNC void setlabel(int number) * statement. This allows several simple optimizations by the peephole * optimizer. */ -SC_FUNC void markexpr(optmark type,const char *name,cell offset) +void markexpr(optmark type,const char *name,cell offset) { switch (type) { case sEXPR: @@ -331,7 +332,7 @@ SC_FUNC void markexpr(optmark type,const char *name,cell offset) * * Global references: funcstatus (referred to only) */ -SC_FUNC void startfunc(char *fname) +void startfunc(char *fname) { stgwrite("\tproc"); if (sc_asmfile) { @@ -348,7 +349,7 @@ SC_FUNC void startfunc(char *fname) * * Declare a CODE ending point (function end) */ -SC_FUNC void endfunc(void) +void endfunc(void) { stgwrite("\n"); /* skip a line */ } @@ -360,7 +361,7 @@ SC_FUNC void endfunc(void) * be a power of 2, and this alignment must be done right after the frame * is set up (before the first variable is declared) */ -SC_FUNC void alignframe(int numbytes) +void alignframe(int numbytes) { #if !defined NDEBUG /* "numbytes" should be a power of 2 for this code to work */ @@ -384,15 +385,14 @@ SC_FUNC void alignframe(int numbytes) * * Generate code to get the value of a symbol into "primary". */ -SC_FUNC void rvalue(value *lval) +void rvalue(value *lval) { symbol *sym; sym=lval->sym; if (lval->ident==iARRAYCELL) { /* indirect fetch, address already in PRI */ - stgwrite("\tload.i\n"); - code_idx+=opcodes(1); + load_i(); } else if (lval->ident==iARRAYCHAR) { /* indirect fetch of a character from a pack, address already in PRI */ stgwrite("\tlodb.i "); @@ -429,7 +429,7 @@ SC_FUNC void rvalue(value *lval) /* Get the address of a symbol into the primary or alternate register (used * for arrays, and for passing arguments by reference). */ -SC_FUNC void address(symbol *sym,regid reg) +void address(symbol *sym,regid reg) { assert(sym!=NULL); assert(reg==sPRI || reg==sALT); @@ -469,12 +469,71 @@ SC_FUNC void address(symbol *sym,regid reg) code_idx+=opcodes(1)+opargs(1); } +static void addr_reg(int val, regid reg) +{ + if (reg == sPRI) + stgwrite("\taddr.pri "); + else + stgwrite("\taddr.alt "); + outval(val, TRUE); + code_idx += opcodes(1) + opargs(1); +} + +// Load the number of arguments into PRI. Frame layout: +// base + 0*sizeof(cell) == previous "base" +// base + 1*sizeof(cell) == function return address +// base + 2*sizeof(cell) == number of arguments +// base + 3*sizeof(cell) == first argument of the function +static void load_argcount(regid reg) +{ + if (reg == sPRI) + stgwrite("\tload.s.pri "); + else + stgwrite("\tload.s.alt "); + outval(2 * sizeof(cell), TRUE); + code_idx += opcodes(1) + opargs(1); +} + +// PRI = ALT + (PRI * cellsize) +void idxaddr() +{ + stgwrite("\tidxaddr\n"); + code_idx += opcodes(1); +} + +void load_i() +{ + stgwrite("\tload.i\n"); + code_idx+=opcodes(1); +} + +// Load the hidden array argument into ALT. +void load_hidden_arg() +{ + pushreg(sPRI); + + // Compute an address to the first argument, then add the argument count + // to find the address after the final argument: + // addr.alt 0xc ; Compute &first_arg + // load.s.alt 0x8 ; Load arg count + // idxaddr ; Compute (&first_arg) + argcount + // load.i ; Load *(&first_arg + argcount) + // move.alt ; Move result into ALT. + addr_reg(0xc, sALT); + load_argcount(sPRI); + idxaddr(); + load_i(); + move_alt(); + + popreg(sPRI); +} + /* store * * Saves the contents of "primary" into a memory cell, either directly * or indirectly (at the address given in the alternate register). */ -SC_FUNC void store(value *lval) +void store(value *lval) { symbol *sym; @@ -511,7 +570,7 @@ SC_FUNC void store(value *lval) } /* Get a cell from a fixed address in memory */ -SC_FUNC void loadreg(cell address,regid reg) +void loadreg(cell address,regid reg) { assert(reg==sPRI || reg==sALT); if (reg==sPRI) @@ -523,7 +582,7 @@ SC_FUNC void loadreg(cell address,regid reg) } /* Store a cell into a fixed address in memory */ -SC_FUNC void storereg(cell address,regid reg) +void storereg(cell address,regid reg) { assert(reg==sPRI || reg==sALT); if (reg==sPRI) @@ -537,7 +596,7 @@ SC_FUNC void storereg(cell address,regid reg) /* source must in PRI, destination address in ALT. The "size" * parameter is in bytes, not cells. */ -SC_FUNC void memcopy(cell size) +void memcopy(cell size) { stgwrite("\tmovs "); outval(size,TRUE); @@ -548,7 +607,7 @@ SC_FUNC void memcopy(cell size) /* Address of the source must already have been loaded in PRI * "size" is the size in bytes (not cells). */ -SC_FUNC void copyarray(symbol *sym,cell size) +void copyarray(symbol *sym,cell size) { assert(sym!=NULL); /* the symbol can be a local array, a global array, or an array @@ -572,7 +631,7 @@ SC_FUNC void copyarray(symbol *sym,cell size) memcopy(size); } -SC_FUNC void fillarray(symbol *sym,cell size,cell value) +void fillarray(symbol *sym,cell size,cell value) { ldconst(value,sPRI); /* load value in PRI */ @@ -601,7 +660,7 @@ SC_FUNC void fillarray(symbol *sym,cell size,cell value) code_idx+=opcodes(2)+opargs(2); } -SC_FUNC void stradjust(regid reg) +void stradjust(regid reg) { assert(reg==sPRI); stgwrite("\tstradjust.pri\n"); @@ -611,7 +670,7 @@ SC_FUNC void stradjust(regid reg) /* Instruction to get an immediate value into the primary or the alternate * register */ -SC_FUNC void ldconst(cell val,regid reg) +void ldconst(cell val,regid reg) { assert(reg==sPRI || reg==sALT); switch (reg) { @@ -639,13 +698,13 @@ SC_FUNC void ldconst(cell val,regid reg) } /* Copy value in alternate register to the primary register */ -SC_FUNC void moveto1(void) +void moveto1(void) { stgwrite("\tmove.pri\n"); code_idx+=opcodes(1)+opargs(0); } -SC_FUNC void move_alt(void) +void move_alt(void) { stgwrite("\tmove.alt\n"); code_idx+=opcodes(1)+opargs(0); @@ -653,7 +712,7 @@ SC_FUNC void move_alt(void) /* Push primary or the alternate register onto the stack */ -SC_FUNC void pushreg(regid reg) +void pushreg(regid reg) { assert(reg==sPRI || reg==sALT); switch (reg) { @@ -670,7 +729,7 @@ SC_FUNC void pushreg(regid reg) /* * Push a constant value onto the stack */ -SC_FUNC void pushval(cell val) +void pushval(cell val) { stgwrite("\tpush.c "); outval(val, TRUE); @@ -679,7 +738,7 @@ SC_FUNC void pushval(cell val) /* Pop stack into the primary or the alternate register */ -SC_FUNC void popreg(regid reg) +void popreg(regid reg) { assert(reg==sPRI || reg==sALT); switch (reg) { @@ -696,7 +755,7 @@ SC_FUNC void popreg(regid reg) /* * Generate an array */ -SC_FUNC void genarray(int dims, int _autozero) +void genarray(int dims, int _autozero) { if (_autozero) { stgwrite("\tgenarray.z "); @@ -710,7 +769,7 @@ SC_FUNC void genarray(int dims, int _autozero) /* * swap the top-of-stack with the value in primary register */ -SC_FUNC void swap1(void) +void swap1(void) { stgwrite("\tswap.pri\n"); code_idx+=opcodes(1); @@ -725,14 +784,14 @@ SC_FUNC void swap1(void) * The case table is sorted on the comparison value. This allows more advanced * abstract machines to sift the case table with a binary search. */ -SC_FUNC void ffswitch(int label) +void ffswitch(int label) { stgwrite("\tswitch "); outval(label,TRUE); /* the label is the address of the case table */ code_idx+=opcodes(1)+opargs(1); } -SC_FUNC void ffcase(cell value,char *labelname,int newtable) +void ffcase(cell value,char *labelname,int newtable) { if (newtable) { stgwrite("\tcasetbl\n"); @@ -749,7 +808,7 @@ SC_FUNC void ffcase(cell value,char *labelname,int newtable) /* * Call specified function */ -SC_FUNC void ffcall(symbol *sym,const char *label,int numargs) +void ffcall(symbol *sym,const char *label,int numargs) { char symname[2*sNAMEMAX+16]; char aliasname[sNAMEMAX+1]; @@ -809,7 +868,7 @@ SC_FUNC void ffcall(symbol *sym,const char *label,int numargs) * * Global references: funcstatus (referred to only) */ -SC_FUNC void ffret(int remparams) +void ffret(int remparams) { if (remparams) stgwrite("\tretn\n"); @@ -818,14 +877,14 @@ SC_FUNC void ffret(int remparams) code_idx+=opcodes(1); } -SC_FUNC void ffabort(int reason) +void ffabort(int reason) { stgwrite("\thalt "); outval(reason,TRUE); code_idx+=opcodes(1)+opargs(1); } -SC_FUNC void ffbounds(cell size) +void ffbounds(cell size) { if ((sc_debug & sCHKBOUNDS)!=0) { stgwrite("\tbounds "); @@ -837,7 +896,7 @@ SC_FUNC void ffbounds(cell size) /* * Jump to local label number (the number is converted to a name) */ -SC_FUNC void jumplabel(int number) +void jumplabel(int number) { stgwrite("\tjump "); outval(number,TRUE); @@ -847,7 +906,7 @@ SC_FUNC void jumplabel(int number) /* * Define storage (global and static variables) */ -SC_FUNC void defstorage(void) +void defstorage(void) { stgwrite("dump "); } @@ -856,7 +915,7 @@ SC_FUNC void defstorage(void) * Inclrement/decrement stack pointer. Note that this routine does * nothing if the delta is zero. */ -SC_FUNC void modstk(int delta) +void modstk(int delta) { if (delta) { stgwrite("\tstack "); @@ -866,7 +925,7 @@ SC_FUNC void modstk(int delta) } /* set the stack to a hard offset from the frame */ -SC_FUNC void setstk(cell value) +void setstk(cell value) { stgwrite("\tstackadjust "); assert(value<=0); /* STK should always become <= FRM */ @@ -874,7 +933,7 @@ SC_FUNC void setstk(cell value) code_idx+=opcodes(1)+opargs(1); } -SC_FUNC void modheap(int delta) +void modheap(int delta) { if (delta) { stgwrite("\theap "); @@ -883,13 +942,13 @@ SC_FUNC void modheap(int delta) } /* if */ } -SC_FUNC void modheap_i() +void modheap_i() { stgwrite("\ttracker.pop.setheap\n"); code_idx+=opcodes(1); } -SC_FUNC void setheap_save(cell value) +void setheap_save(cell value) { assert(value); stgwrite("\ttracker.push.c "); @@ -897,7 +956,7 @@ SC_FUNC void setheap_save(cell value) code_idx+=opcodes(1)+opargs(1); } -SC_FUNC void setheap_pri(void) +void setheap_pri(void) { stgwrite("\theap "); /* ALT = HEA++ */ outval(sizeof(cell), TRUE); @@ -906,7 +965,7 @@ SC_FUNC void setheap_pri(void) code_idx+=opcodes(3)+opargs(1); } -SC_FUNC void setheap(cell value) +void setheap(cell value) { stgwrite("\tconst.pri "); /* load default value in PRI */ outval(value, TRUE); @@ -918,7 +977,7 @@ SC_FUNC void setheap(cell value) * Convert a cell number to a "byte" address; i.e. double or quadruple * the primary register. */ -SC_FUNC void cell2addr(void) +void cell2addr(void) { #if PAWN_CELL_SIZE==16 stgwrite("\tshl.c.pri 1\n"); @@ -935,7 +994,7 @@ SC_FUNC void cell2addr(void) /* * Double or quadruple the alternate register. */ -SC_FUNC void cell2addr_alt(void) +void cell2addr_alt(void) { #if PAWN_CELL_SIZE==16 stgwrite("\tshl.c.alt 1\n"); @@ -954,7 +1013,7 @@ SC_FUNC void cell2addr_alt(void) * Or convert a number of packed characters to the number of cells (with * truncation). */ -SC_FUNC void addr2cell(void) +void addr2cell(void) { #if PAWN_CELL_SIZE==16 stgwrite("\tshr.c.pri 1\n"); @@ -971,7 +1030,7 @@ SC_FUNC void addr2cell(void) /* Convert from character index to byte address. This routine does * nothing if a character has the size of a byte. */ -SC_FUNC void char2addr(void) +void char2addr(void) { #if sCHARBITS==16 stgwrite("\tshl.c.pri 1\n"); @@ -989,7 +1048,7 @@ SC_FUNC void char2addr(void) * * NOTE: For Source Pawn, this is fliped. It will do nothing on Little-Endian. */ -SC_FUNC void charalign(void) +void charalign(void) { #if 0 /* TEMPORARILY DISABLED BECAUSE WE DON'T USE BIG ENDIAN */ stgwrite("\talign.pri "); @@ -1001,7 +1060,7 @@ SC_FUNC void charalign(void) /* * Add a constant to the primary register. */ -SC_FUNC void addconst(cell value) +void addconst(cell value) { if (value!=0) { stgwrite("\tadd.c "); @@ -1013,7 +1072,7 @@ SC_FUNC void addconst(cell value) /* * signed multiply of primary and secundairy registers (result in primary) */ -SC_FUNC void os_mult(void) +void os_mult(void) { stgwrite("\tsmul\n"); code_idx+=opcodes(1); @@ -1023,7 +1082,7 @@ SC_FUNC void os_mult(void) * signed divide of alternate register by primary register (quotient in * primary; remainder in alternate) */ -SC_FUNC void os_div(void) +void os_div(void) { stgwrite("\tsdiv.alt\n"); code_idx+=opcodes(1); @@ -1032,7 +1091,7 @@ SC_FUNC void os_div(void) /* * modulus of (alternate % primary), result in primary (signed) */ -SC_FUNC void os_mod(void) +void os_mod(void) { stgwrite("\tsdiv.alt\n"); stgwrite("\tmove.pri\n"); /* move ALT to PRI */ @@ -1042,7 +1101,7 @@ SC_FUNC void os_mod(void) /* * Add primary and alternate registers (result in primary). */ -SC_FUNC void ob_add(void) +void ob_add(void) { stgwrite("\tadd\n"); code_idx+=opcodes(1); @@ -1051,7 +1110,7 @@ SC_FUNC void ob_add(void) /* * subtract primary register from alternate register (result in primary) */ -SC_FUNC void ob_sub(void) +void ob_sub(void) { stgwrite("\tsub.alt\n"); code_idx+=opcodes(1); @@ -1063,7 +1122,7 @@ SC_FUNC void ob_sub(void) * There is no need for a "logical shift left" routine, since * logical shift left is identical to arithmic shift left. */ -SC_FUNC void ob_sal(void) +void ob_sal(void) { stgwrite("\txchg\n"); stgwrite("\tshl\n"); @@ -1074,7 +1133,7 @@ SC_FUNC void ob_sal(void) * arithmic shift right alternate register the number of bits * given in the primary register (result in primary). */ -SC_FUNC void os_sar(void) +void os_sar(void) { stgwrite("\txchg\n"); stgwrite("\tsshr\n"); @@ -1085,7 +1144,7 @@ SC_FUNC void os_sar(void) * logical (unsigned) shift right of the alternate register by the * number of bits given in the primary register (result in primary). */ -SC_FUNC void ou_sar(void) +void ou_sar(void) { stgwrite("\txchg\n"); stgwrite("\tshr\n"); @@ -1095,7 +1154,7 @@ SC_FUNC void ou_sar(void) /* * inclusive "or" of primary and alternate registers (result in primary) */ -SC_FUNC void ob_or(void) +void ob_or(void) { stgwrite("\tor\n"); code_idx+=opcodes(1); @@ -1104,7 +1163,7 @@ SC_FUNC void ob_or(void) /* * "exclusive or" of primary and alternate registers (result in primary) */ -SC_FUNC void ob_xor(void) +void ob_xor(void) { stgwrite("\txor\n"); code_idx+=opcodes(1); @@ -1113,7 +1172,7 @@ SC_FUNC void ob_xor(void) /* * "and" of primary and secundairy registers (result in primary) */ -SC_FUNC void ob_and(void) +void ob_and(void) { stgwrite("\tand\n"); code_idx+=opcodes(1); @@ -1122,7 +1181,7 @@ SC_FUNC void ob_and(void) /* * test ALT==PRI; result in primary register (1 or 0). */ -SC_FUNC void ob_eq(void) +void ob_eq(void) { stgwrite("\teq\n"); code_idx+=opcodes(1); @@ -1131,7 +1190,7 @@ SC_FUNC void ob_eq(void) /* * test ALT!=PRI */ -SC_FUNC void ob_ne(void) +void ob_ne(void) { stgwrite("\tneq\n"); code_idx+=opcodes(1); @@ -1157,14 +1216,14 @@ SC_FUNC void ob_ne(void) * stack and moves the value of ALT into PRI. If there is a next comparison, * PRI can now serve as the "left" operand of the relational operator. */ -SC_FUNC void relop_prefix(void) +void relop_prefix(void) { stgwrite("\tpush.pri\n"); stgwrite("\tmove.pri\n"); code_idx+=opcodes(2); } -SC_FUNC void relop_suffix(void) +void relop_suffix(void) { stgwrite("\tswap.alt\n"); stgwrite("\tand\n"); @@ -1175,7 +1234,7 @@ SC_FUNC void relop_suffix(void) /* * test ALTPRI (signed) */ -SC_FUNC void os_gt(void) +void os_gt(void) { stgwrite("\txchg\n"); stgwrite("\tsgrtr\n"); @@ -1205,7 +1264,7 @@ SC_FUNC void os_gt(void) /* * test ALT>=PRI (signed) */ -SC_FUNC void os_ge(void) +void os_ge(void) { stgwrite("\txchg\n"); stgwrite("\tsgeq\n"); @@ -1215,7 +1274,7 @@ SC_FUNC void os_ge(void) /* * logical negation of primary register */ -SC_FUNC void lneg(void) +void lneg(void) { stgwrite("\tnot\n"); code_idx+=opcodes(1); @@ -1224,7 +1283,7 @@ SC_FUNC void lneg(void) /* * two's complement primary register */ -SC_FUNC void neg(void) +void neg(void) { stgwrite("\tneg\n"); code_idx+=opcodes(1); @@ -1233,7 +1292,7 @@ SC_FUNC void neg(void) /* * one's complement of primary register */ -SC_FUNC void invert(void) +void invert(void) { stgwrite("\tinvert\n"); code_idx+=opcodes(1); @@ -1242,19 +1301,19 @@ SC_FUNC void invert(void) /* * nop */ -SC_FUNC void nooperation(void) +void nooperation(void) { stgwrite("\tnop\n"); code_idx+=opcodes(1); } -SC_FUNC void inc_pri() +void inc_pri() { stgwrite("\tinc.pri\n"); code_idx+=opcodes(1); } -SC_FUNC void dec_pri() +void dec_pri() { stgwrite("\tdec.pri\n"); code_idx+=opcodes(1); @@ -1262,7 +1321,7 @@ SC_FUNC void dec_pri() /* increment symbol */ -SC_FUNC void inc(value *lval) +void inc(value *lval) { symbol *sym; @@ -1320,7 +1379,7 @@ SC_FUNC void inc(value *lval) * * in case of an integer pointer, the symbol must be incremented by 2. */ -SC_FUNC void dec(value *lval) +void dec(value *lval) { symbol *sym; @@ -1377,7 +1436,7 @@ SC_FUNC void dec(value *lval) /* * Jumps to "label" if PRI != 0 */ -SC_FUNC void jmp_ne0(int number) +void jmp_ne0(int number) { stgwrite("\tjnz "); outval(number,TRUE); @@ -1387,7 +1446,7 @@ SC_FUNC void jmp_ne0(int number) /* * Jumps to "label" if PRI == 0 */ -SC_FUNC void jmp_eq0(int number) +void jmp_eq0(int number) { stgwrite("\tjzer "); outval(number,TRUE); @@ -1395,14 +1454,14 @@ SC_FUNC void jmp_eq0(int number) } /* write a value in hexadecimal; optionally adds a newline */ -SC_FUNC void outval(cell val,int newline) +void outval(cell val,int newline) { stgwrite(itoh(val)); if (newline) stgwrite("\n"); } -SC_FUNC void invoke_getter(methodmap_method_t *method) +void invoke_getter(methodmap_method_t *method) { if (!method->getter) { error(149, method->name); @@ -1420,7 +1479,7 @@ SC_FUNC void invoke_getter(methodmap_method_t *method) markusage(method->getter, uREAD); } -SC_FUNC void invoke_setter(methodmap_method_t *method, int save) +void invoke_setter(methodmap_method_t *method, int save) { if (!method->setter) { error(152, method->name); diff --git a/sourcepawn/compiler/sc5-in.scp b/sourcepawn/compiler/sc5-in.scp index 57d289b2..0478abb2 100644 --- a/sourcepawn/compiler/sc5-in.scp +++ b/sourcepawn/compiler/sc5-in.scp @@ -21,7 +21,7 @@ * Version: $Id$ */ -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]); +int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]); #ifndef SCPACK # define SCPACK @@ -42,7 +42,7 @@ unsigned char errstr_table [][2] = { }; /*-*SCPACK end of pair table, do not change or remove this line */ -static char *errmsg[] = { +static const char *errmsg[] = { #ifdef SCPACK /*001*/ "expected token: \"%s\", but found \"%s\"\n", /*002*/ "only a single statement (or expression) can follow each \"case\"\n", @@ -362,7 +362,7 @@ static char *errmsg[] = { #endif }; -static char *fatalmsg[] = { +static const char *fatalmsg[] = { #ifdef SCPACK /*160*/ "cannot read from file: \"%s\"\n", /*161*/ "cannot write to file: \"%s\"\n", @@ -398,7 +398,7 @@ static char *fatalmsg[] = { #endif }; -static char *warnmsg[] = { +static const char *warnmsg[] = { #ifdef SCPACK /*200*/ "symbol \"%s\" is truncated to %d characters\n", /*201*/ "redefinition of constant/macro (symbol \"%s\")\n", diff --git a/sourcepawn/compiler/sc5.c b/sourcepawn/compiler/sc5.cpp similarity index 94% rename from sourcepawn/compiler/sc5.c rename to sourcepawn/compiler/sc5.cpp index 96d5740b..64d2a649 100644 --- a/sourcepawn/compiler/sc5.c +++ b/sourcepawn/compiler/sc5.cpp @@ -67,12 +67,12 @@ static int sErrLine; /* forced line number for the error message */ * fcurrent (reffered to only) * errflag (altered) */ -SC_FUNC int error(int number,...) +int error(int number,...) { -static char *prefix[3]={ "error", "fatal error", "warning" }; +static const char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; - char *msg,*pre; + const char *msg,*pre; va_list argptr; // sErrLine is used to temporarily change the line number of reported errors. @@ -172,7 +172,7 @@ static short lastfile; return 0; } -SC_FUNC void errorset(int code,int line) +void errorset(int code,int line) { switch (code) { case sRESET: diff --git a/sourcepawn/compiler/sc6.c b/sourcepawn/compiler/sc6.cpp similarity index 94% rename from sourcepawn/compiler/sc6.c rename to sourcepawn/compiler/sc6.cpp index 926c454c..8e677f0e 100644 --- a/sourcepawn/compiler/sc6.c +++ b/sourcepawn/compiler/sc6.cpp @@ -37,14 +37,14 @@ #endif -static void append_dbginfo(FILE *fout); +static void append_dbginfo(void *fout); -typedef cell (*OPCODE_PROC)(FILE *fbin,char *params,cell opcode); +typedef cell (*OPCODE_PROC)(void *fbin,char *params,cell opcode); typedef struct { cell opcode; - char *name; + const char *name; int segment; /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */ OPCODE_PROC func; } OPCODEC; @@ -192,7 +192,7 @@ static char *stripcomment(char *str) return str; } -static void write_encoded(FILE *fbin,ucell *c,int num) +static void write_encoded(void *fbin,ucell *c,int num) { #if PAWN_CELL_SIZE == 16 #define ENC_MAX 3 /* a 16-bit cell is encoded in max. 3 bytes */ @@ -246,7 +246,7 @@ static void write_encoded(FILE *fbin,ucell *c,int num) #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif -static cell noop(FILE *fbin,char *params,cell opcode) +static cell noop(void *fbin,char *params,cell opcode) { return 0; } @@ -254,7 +254,7 @@ static cell noop(FILE *fbin,char *params,cell opcode) #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif -static cell set_currentfile(FILE *fbin,char *params,cell opcode) +static cell set_currentfile(void *fbin,char *params,cell opcode) { fcurrent=(short)getparam(params,NULL); return 0; @@ -263,14 +263,14 @@ static cell set_currentfile(FILE *fbin,char *params,cell opcode) #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif -static cell parm0(FILE *fbin,char *params,cell opcode) +static cell parm0(void *fbin,char *params,cell opcode) { if (fbin!=NULL) write_encoded(fbin,(ucell*)&opcode,1); return opcodes(1); } -static cell parm1(FILE *fbin,char *params,cell opcode) +static cell parm1(void *fbin,char *params,cell opcode) { ucell p=getparam(params,NULL); if (fbin!=NULL) { @@ -280,7 +280,7 @@ static cell parm1(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(1); } -static cell parm2(FILE *fbin,char *params,cell opcode) +static cell parm2(void *fbin,char *params,cell opcode) { ucell p1=getparam(params,¶ms); ucell p2=getparam(params,NULL); @@ -292,7 +292,7 @@ static cell parm2(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(2); } -static cell parm3(FILE *fbin,char *params,cell opcode) +static cell parm3(void *fbin,char *params,cell opcode) { ucell p1=getparam(params,¶ms); ucell p2=getparam(params,¶ms); @@ -306,7 +306,7 @@ static cell parm3(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(3); } -static cell parm4(FILE *fbin,char *params,cell opcode) +static cell parm4(void *fbin,char *params,cell opcode) { ucell p1=getparam(params,¶ms); ucell p2=getparam(params,¶ms); @@ -322,7 +322,7 @@ static cell parm4(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(4); } -static cell parm5(FILE *fbin,char *params,cell opcode) +static cell parm5(void *fbin,char *params,cell opcode) { ucell p1=getparam(params,¶ms); ucell p2=getparam(params,¶ms); @@ -343,7 +343,7 @@ static cell parm5(FILE *fbin,char *params,cell opcode) #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif -static cell do_dump(FILE *fbin,char *params,cell opcode) +static cell do_dump(void *fbin,char *params,cell opcode) { ucell p; int num = 0; @@ -359,7 +359,7 @@ static cell do_dump(FILE *fbin,char *params,cell opcode) return num*sizeof(cell); } -static cell do_call(FILE *fbin,char *params,cell opcode) +static cell do_call(void *fbin,char *params,cell opcode) { char name[sNAMEMAX+1]; int i; @@ -399,7 +399,7 @@ static cell do_call(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(1); } -static cell do_jump(FILE *fbin,char *params,cell opcode) +static cell do_jump(void *fbin,char *params,cell opcode) { int i; ucell p; @@ -416,7 +416,7 @@ static cell do_jump(FILE *fbin,char *params,cell opcode) return opcodes(1)+opargs(1); } -static cell do_switch(FILE *fbin,char *params,cell opcode) +static cell do_switch(void *fbin,char *params,cell opcode) { int i; ucell p; @@ -436,7 +436,7 @@ static cell do_switch(FILE *fbin,char *params,cell opcode) #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif -static cell do_case(FILE *fbin,char *params,cell opcode) +static cell do_case(void *fbin,char *params,cell opcode) { int i; ucell p,v; @@ -659,7 +659,7 @@ static int findopcode(char *instr,int maxlen) return 0; /* not found, return special index */ } -SC_FUNC int assemble(FILE *fout,FILE *fin) +int assemble(void *fout, void *fin) { AMX_HEADER hdr; AMX_FUNCSTUBNT func; @@ -1058,7 +1058,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) return size; } -static void append_dbginfo(FILE *fout) +static void append_dbginfo(void *fout) { AMX_DBG_HDR dbghdr; AMX_DBG_LINE dbgline; diff --git a/sourcepawn/compiler/sc7-in.scp b/sourcepawn/compiler/sc7-in.scp index 856994ca..ddbfb9b8 100644 --- a/sourcepawn/compiler/sc7-in.scp +++ b/sourcepawn/compiler/sc7-in.scp @@ -22,7 +22,7 @@ * Version: $Id$ */ -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]); +int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]); #define SCPACK_TERMINATOR , /* end each section with a comma */ @@ -41,12 +41,17 @@ unsigned char sequences_table[][2] = { /*-*SCPACK end of pair table, do not change or remove this line */ #define seqsize(o,p) (opcodes(o)+opargs(p)) +typedef struct { + const char *find; + const char *replace; + int savesize; /* number of bytes saved (in bytecode) */ +} SETUP_SEQUENCE; typedef struct { char *find; char *replace; int savesize; /* number of bytes saved (in bytecode) */ } SEQUENCE; -static SEQUENCE sequences_cmp[] = { +static SETUP_SEQUENCE sequences_cmp[] = { /* A very common sequence in four varieties * load.s.pri n1 load.s.pri n2 * push.pri load.s.alt n1 diff --git a/sourcepawn/compiler/sc7.c b/sourcepawn/compiler/sc7.cpp similarity index 95% rename from sourcepawn/compiler/sc7.c rename to sourcepawn/compiler/sc7.cpp index 61f095d8..754a0ed1 100644 --- a/sourcepawn/compiler/sc7.c +++ b/sourcepawn/compiler/sc7.cpp @@ -108,7 +108,7 @@ static void grow_stgbuffer(char **buffer, int *curmax, int requiredsize) **buffer='\0'; } -SC_FUNC void stgbuffer_cleanup(void) +void stgbuffer_cleanup(void) { if (stgbuf!=NULL) { free(stgbuf); @@ -141,7 +141,7 @@ SC_FUNC void stgbuffer_cleanup(void) * stgbuf (altered) * staging (referred to only) */ -SC_FUNC void stgmark(char mark) +void stgmark(char mark) { if (staging) { CHECK_STGBUFFER(stgidx); @@ -188,7 +188,7 @@ static int filewrite(char *str) * stgbuf (altered) * staging (referred to only) */ -SC_FUNC void stgwrite(const char *st) +void stgwrite(const char *st) { int len; @@ -224,7 +224,7 @@ SC_FUNC void stgwrite(const char *st) * stgbuf (referred to only) * staging (referred to only) */ -SC_FUNC void stgout(int index) +void stgout(int index) { int reordered=0; int idx; @@ -348,7 +348,7 @@ static int stgstring(char *start,char *end) * Global references: stgidx (altered) * staging (reffered to only) */ -SC_FUNC void stgdel(int index,cell code_index) +void stgdel(int index,cell code_index) { if (staging) { stgidx=index; @@ -356,7 +356,7 @@ SC_FUNC void stgdel(int index,cell code_index) } /* if */ } -SC_FUNC int stgget(int *index,cell *code_index) +int stgget(int *index,cell *code_index) { if (staging) { *index=stgidx; @@ -375,7 +375,7 @@ SC_FUNC int stgget(int *index,cell *code_index) * stgidx (altered) * stgbuf (contents altered) */ -SC_FUNC void stgset(int onoff) +void stgset(int onoff) { staging=onoff; if (staging){ @@ -398,7 +398,7 @@ SC_FUNC void stgset(int onoff) */ static SEQUENCE *sequences; -SC_FUNC int phopt_init(void) +int phopt_init(void) { int number, i, len; char str[160]; @@ -440,7 +440,7 @@ SC_FUNC int phopt_init(void) return TRUE; } -SC_FUNC int phopt_cleanup(void) +int phopt_cleanup(void) { int i; if (sequences!=NULL) { diff --git a/sourcepawn/compiler/scexpand.c b/sourcepawn/compiler/scexpand.cpp similarity index 89% rename from sourcepawn/compiler/scexpand.c rename to sourcepawn/compiler/scexpand.cpp index 977c0121..09182ad6 100644 --- a/sourcepawn/compiler/scexpand.c +++ b/sourcepawn/compiler/scexpand.cpp @@ -16,7 +16,7 @@ #define STACKSIZE 16 -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]) +int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]) { unsigned char stack[STACKSIZE]; short c, top = 0; diff --git a/sourcepawn/compiler/sci18n.c b/sourcepawn/compiler/sci18n.cpp similarity index 94% rename from sourcepawn/compiler/sci18n.c rename to sourcepawn/compiler/sci18n.cpp index 8730e4ec..980dcbdc 100644 --- a/sourcepawn/compiler/sci18n.c +++ b/sourcepawn/compiler/sci18n.cpp @@ -113,7 +113,7 @@ static int cp_readline(FILE *fp,char *string,size_t size) * codepages are most conveniently stored in a subdirectory of this home * directory. */ -SC_FUNC int cp_path(const char *root, const char *directory) +int cp_path(const char *root, const char *directory) { size_t len1,len2; int add_slash1,add_slash2; @@ -154,7 +154,7 @@ SC_FUNC int cp_path(const char *root, const char *directory) * /cp * /cp.txt */ -SC_FUNC int cp_set(const char *name) +int cp_set(const char *name) { char filename[_MAX_PATH]; FILE *fp=NULL; @@ -277,7 +277,7 @@ SC_FUNC int cp_set(const char *name) return TRUE; } -SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr) +cell cp_translate(const unsigned char *string,const unsigned char **endptr) { wchar_t result; @@ -312,7 +312,7 @@ SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endp #endif /* NO_CODEPAGE */ #if !defined NO_UTF8 -SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr) +cell get_utf8_char(const unsigned char *string,const unsigned char **endptr) { int follow=0; long lowmark=0; @@ -391,7 +391,7 @@ SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **end } #endif -SC_FUNC int scan_utf8(FILE *fp,const char *filename) +int scan_utf8(void *fp,const char *filename) { #if defined NO_UTF8 return 0; diff --git a/sourcepawn/compiler/sclist.c b/sourcepawn/compiler/sclist.cpp similarity index 85% rename from sourcepawn/compiler/sclist.c rename to sourcepawn/compiler/sclist.cpp index 8ffd9c73..bcf7192b 100644 --- a/sourcepawn/compiler/sclist.c +++ b/sourcepawn/compiler/sclist.cpp @@ -41,7 +41,7 @@ * to other memory allocators becomes easier. * By Søren Hannibal. */ -SC_FUNC char* duplicatestring(const char* sourcestring) +char* duplicatestring(const char* sourcestring) { char* result=(char*)malloc(strlen(sourcestring)+1); strcpy(result,sourcestring); @@ -49,7 +49,7 @@ SC_FUNC char* duplicatestring(const char* sourcestring) } -static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength) +static stringpair *insert_stringpair(stringpair *root,const char *first,const char *second,int matchlength) { stringpair *cur,*pred; @@ -137,7 +137,7 @@ static int delete_stringpair(stringpair *root,stringpair *item) } /* ----- string list functions ----------------------------------- */ -static stringlist *insert_string(stringlist *root,char *string) +static stringlist *insert_string(stringlist *root,const char *string) { stringlist *cur; @@ -190,7 +190,7 @@ static int delete_string(stringlist *root,int index) return FALSE; } -SC_FUNC void delete_stringtable(stringlist *root) +void delete_stringtable(stringlist *root) { stringlist *cur,*next; @@ -210,7 +210,7 @@ SC_FUNC void delete_stringtable(stringlist *root) /* ----- alias table --------------------------------------------- */ static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */ -SC_FUNC stringpair *insert_alias(char *name,char *alias) +stringpair *insert_alias(char *name,char *alias) { stringpair *cur; @@ -223,7 +223,7 @@ SC_FUNC stringpair *insert_alias(char *name,char *alias) return cur; } -SC_FUNC int lookup_alias(char *target,char *name) +int lookup_alias(char *target,char *name) { stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name)); if (cur!=NULL) { @@ -233,7 +233,7 @@ SC_FUNC int lookup_alias(char *target,char *name) return cur!=NULL; } -SC_FUNC void delete_aliastable(void) +void delete_aliastable(void) { delete_stringpairtable(&alias_tab); } @@ -241,17 +241,17 @@ SC_FUNC void delete_aliastable(void) /* ----- include paths list -------------------------------------- */ static stringlist includepaths; /* directory list for include files */ -SC_FUNC stringlist *insert_path(char *path) +stringlist *insert_path(char *path) { return insert_string(&includepaths,path); } -SC_FUNC char *get_path(int index) +char *get_path(int index) { return get_string(&includepaths,index); } -SC_FUNC void delete_pathtable(void) +void delete_pathtable(void) { delete_stringtable(&includepaths); assert(includepaths.next==NULL); @@ -275,7 +275,7 @@ static void adjustindex(char c) substindex[(int)c-PUBLIC_CHAR]=cur; } -SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen) +stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen) { stringpair *cur; @@ -306,7 +306,7 @@ SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen) return cur; } -SC_FUNC stringpair *find_subst(char *name,int length) +stringpair *find_subst(char *name,int length) { stringpair *item; assert(name!=NULL); @@ -319,12 +319,13 @@ SC_FUNC stringpair *find_subst(char *name,int length) if (item && (item->flags & flgDEPRECATED) != 0) { static char macro[128]; - char *rem, *msg = (item->documentation != NULL) ? item->documentation : ""; + const char *msg = (item->documentation != NULL) ? item->documentation : ""; strlcpy(macro, item->first, sizeof(macro)); /* If macro contains an opening parentheses and a percent sign, then assume that * it takes arguments and remove them from the warning message. */ + char *rem; if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem) { *rem = '\0'; @@ -335,7 +336,7 @@ SC_FUNC stringpair *find_subst(char *name,int length) return item; } -SC_FUNC int delete_subst(char *name,int length) +int delete_subst(char *name,int length) { stringpair *item; assert(name!=NULL); @@ -356,7 +357,7 @@ SC_FUNC int delete_subst(char *name,int length) return TRUE; } -SC_FUNC void delete_substtable(void) +void delete_substtable(void) { int i; delete_stringpairtable(&substpair); @@ -370,17 +371,17 @@ SC_FUNC void delete_substtable(void) /* ----- input file list ----------------------------------------- */ static stringlist sourcefiles; -SC_FUNC stringlist *insert_sourcefile(char *string) +stringlist *insert_sourcefile(char *string) { return insert_string(&sourcefiles,string); } -SC_FUNC char *get_sourcefile(int index) +char *get_sourcefile(int index) { return get_string(&sourcefiles,index); } -SC_FUNC void delete_sourcefiletable(void) +void delete_sourcefiletable(void) { delete_stringtable(&sourcefiles); assert(sourcefiles.next==NULL); @@ -391,22 +392,22 @@ SC_FUNC void delete_sourcefiletable(void) #if !defined SC_LIGHT static stringlist docstrings; -SC_FUNC stringlist *insert_docstring(char *string) +stringlist *insert_docstring(char *string) { return insert_string(&docstrings,string); } -SC_FUNC char *get_docstring(int index) +char *get_docstring(int index) { return get_string(&docstrings,index); } -SC_FUNC void delete_docstring(int index) +void delete_docstring(int index) { delete_string(&docstrings,index); } -SC_FUNC void delete_docstringtable(void) +void delete_docstringtable(void) { delete_stringtable(&docstrings); assert(docstrings.next==NULL); @@ -417,17 +418,17 @@ SC_FUNC void delete_docstringtable(void) /* ----- autolisting --------------------------------------------- */ static stringlist autolist; -SC_FUNC stringlist *insert_autolist(char *string) +stringlist *insert_autolist(const char *string) { return insert_string(&autolist,string); } -SC_FUNC char *get_autolist(int index) +char *get_autolist(int index) { return get_string(&autolist,index); } -SC_FUNC void delete_autolisttable(void) +void delete_autolisttable(void) { delete_stringtable(&autolist); assert(autolist.next==NULL); @@ -463,7 +464,7 @@ SC_FUNC void delete_autolisttable(void) static stringlist dbgstrings; -SC_FUNC stringlist *insert_dbgfile(const char *filename) +stringlist *insert_dbgfile(const char *filename) { if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) { @@ -476,7 +477,7 @@ SC_FUNC stringlist *insert_dbgfile(const char *filename) return NULL; } -SC_FUNC stringlist *insert_dbgline(int linenr) +stringlist *insert_dbgline(int linenr) { if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) { char string[40]; @@ -488,7 +489,7 @@ SC_FUNC stringlist *insert_dbgline(int linenr) return NULL; } -SC_FUNC stringlist *insert_dbgsymbol(symbol *sym) +stringlist *insert_dbgsymbol(symbol *sym) { if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) { char string[2*sNAMEMAX+128]; @@ -521,17 +522,17 @@ SC_FUNC stringlist *insert_dbgsymbol(symbol *sym) return NULL; } -SC_FUNC stringlist *get_dbgstrings() +stringlist *get_dbgstrings() { return &dbgstrings; } -SC_FUNC char *get_dbgstring(int index) +char *get_dbgstring(int index) { return get_string(&dbgstrings,index); } -SC_FUNC void delete_dbgstringtable(void) +void delete_dbgstringtable(void) { delete_stringtable(&dbgstrings); assert(dbgstrings.next==NULL); diff --git a/sourcepawn/compiler/scmemfil.c b/sourcepawn/compiler/scmemfil.cpp similarity index 94% rename from sourcepawn/compiler/scmemfil.c rename to sourcepawn/compiler/scmemfil.cpp index a8dd0aae..59eb3875 100644 --- a/sourcepawn/compiler/scmemfil.c +++ b/sourcepawn/compiler/scmemfil.cpp @@ -34,8 +34,6 @@ #if defined FORTIFY #include #endif -typedef memfile_t MEMFILE; -#define tMEMFILE 1 #include "sc.h" diff --git a/sourcepawn/compiler/scstate.c b/sourcepawn/compiler/scstate.cpp similarity index 89% rename from sourcepawn/compiler/scstate.c rename to sourcepawn/compiler/scstate.cpp index 1d383e2b..8c772804 100644 --- a/sourcepawn/compiler/scstate.c +++ b/sourcepawn/compiler/scstate.cpp @@ -87,7 +87,7 @@ static constvalue *find_automaton(const char *name,int *last) return NULL; } -SC_FUNC constvalue *automaton_add(const char *name) +constvalue *automaton_add(const char *name) { constvalue *ptr; int last; @@ -101,13 +101,13 @@ SC_FUNC constvalue *automaton_add(const char *name) return ptr; } -SC_FUNC constvalue *automaton_find(const char *name) +constvalue *automaton_find(const char *name) { int last; return find_automaton(name,&last); } -SC_FUNC constvalue *automaton_findid(int id) +constvalue *automaton_findid(int id) { constvalue *ptr; for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next) @@ -135,7 +135,7 @@ static constvalue *find_state(const char *name,int fsa,int *last) return NULL; } -SC_FUNC constvalue *state_add(const char *name,int fsa) +constvalue *state_add(const char *name,int fsa) { constvalue *ptr; int last; @@ -149,13 +149,13 @@ SC_FUNC constvalue *state_add(const char *name,int fsa) return ptr; } -SC_FUNC constvalue *state_find(const char *name,int fsa_id) +constvalue *state_find(const char *name,int fsa_id) { int last; /* dummy */ return find_state(name,fsa_id,&last); } -SC_FUNC constvalue *state_findid(int id) +constvalue *state_findid(int id) { constvalue *ptr; for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next) @@ -163,7 +163,7 @@ SC_FUNC constvalue *state_findid(int id) return ptr; } -SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid) +void state_buildlist(int **list,int *listsize,int *count,int stateid) { int idx; @@ -227,7 +227,7 @@ static statelist *state_getlist_ptr(int listid) return ptr; } -SC_FUNC int state_addlist(int *list,int count,int fsa) +int state_addlist(int *list,int count,int fsa) { statelist *ptr; int last; @@ -253,7 +253,7 @@ SC_FUNC int state_addlist(int *list,int count,int fsa) return ptr->listid; } -SC_FUNC void state_deletetable(void) +void state_deletetable(void) { statelist *ptr; @@ -268,7 +268,7 @@ SC_FUNC void state_deletetable(void) } /* while */ } -SC_FUNC int state_getfsa(int listid) +int state_getfsa(int listid) { statelist *ptr; @@ -280,7 +280,7 @@ SC_FUNC int state_getfsa(int listid) return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */ } -SC_FUNC int state_count(int listid) +int state_count(int listid) { statelist *ptr=state_getlist_ptr(listid); if (ptr==NULL) @@ -288,7 +288,7 @@ SC_FUNC int state_count(int listid) return ptr->numstates; } -SC_FUNC int state_inlist(int listid,int state) +int state_inlist(int listid,int state) { statelist *ptr; int i; @@ -302,7 +302,7 @@ SC_FUNC int state_inlist(int listid,int state) return FALSE; } -SC_FUNC int state_listitem(int listid,int index) +int state_listitem(int listid,int index) { statelist *ptr; @@ -329,7 +329,7 @@ static int checkconflict(statelist *psrc,statelist *ptgt) * of a symbol exists in any other statelist id's of the same function; it also * verifies that all definitions of the symbol are in the same automaton. */ -SC_FUNC void state_conflict(symbol *root) +void state_conflict(symbol *root) { statelist *psrc,*ptgt; constvalue *srcptr,*tgtptr; @@ -363,7 +363,7 @@ SC_FUNC void state_conflict(symbol *root) /* check whether the two state lists (whose ids are passed in) share any * states */ -SC_FUNC int state_conflict_id(int listid1,int listid2) +int state_conflict_id(int listid1,int listid2) { statelist *psrc,*ptgt; diff --git a/sourcepawn/compiler/sctracker.c b/sourcepawn/compiler/sctracker.cpp similarity index 62% rename from sourcepawn/compiler/sctracker.c rename to sourcepawn/compiler/sctracker.cpp index 2a2025f1..b575adcf 100644 --- a/sourcepawn/compiler/sctracker.c +++ b/sourcepawn/compiler/sctracker.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "sc.h" #include "sctracker.h" @@ -16,187 +17,213 @@ methodmap_t *methodmap_last = NULL; structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member) { - int i; + int i; - for (i=0; iargcount; i++) - { - if (strcmp(pstruct->args[i]->name, member) == 0) - { - return pstruct->args[i]; - } - } + for (i=0; iargcount; i++) { + if (strcmp(pstruct->args[i]->name, member) == 0) + return pstruct->args[i]; + } - return NULL; + return NULL; } pstruct_t *pstructs_add(const char *name) { - pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t)); - - memset(p, 0, sizeof(pstruct_t)); - strcpy(p->name, name); - - if (!firststruct) - { - firststruct = p; - laststruct = p; - } else { - laststruct->next = p; - laststruct = p; - } + pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t)); + + memset(p, 0, sizeof(pstruct_t)); + strcpy(p->name, name); + + if (!firststruct) { + firststruct = p; + laststruct = p; + } else { + laststruct->next = p; + laststruct = p; + } - return p; + return p; } void pstructs_free() { - pstruct_t *p, *next; + pstruct_t *p, *next; - p = firststruct; - while (p) - { - while (p->argcount--) - { - free(p->args[p->argcount]); - } - free(p->args); - next = p->next; - free(p); - p = next; - } - firststruct = NULL; - laststruct = NULL; + p = firststruct; + while (p) { + while (p->argcount--) + free(p->args[p->argcount]); + free(p->args); + next = p->next; + free(p); + p = next; + } + firststruct = NULL; + laststruct = NULL; } pstruct_t *pstructs_find(const char *name) { - pstruct_t *p = firststruct; + pstruct_t *p = firststruct; - while (p) - { - if (strcmp(p->name, name) == 0) - { - return p; - } - p = p->next; - } + while (p) { + if (strcmp(p->name, name) == 0) + return p; + p = p->next; + } - return NULL; + return NULL; } structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg) { - structarg_t *newarg; - int i; + structarg_t *newarg; + int i; - for (i=0; iargcount; i++) - { - if (strcmp(pstruct->args[i]->name, arg->name) == 0) - { - /* Don't allow dup names */ - return NULL; - } - } - - newarg = (structarg_t *)malloc(sizeof(structarg_t)); + for (i=0; iargcount; i++) { + if (strcmp(pstruct->args[i]->name, arg->name) == 0) { + /* Don't allow dup names */ + return NULL; + } + } + + newarg = (structarg_t *)malloc(sizeof(structarg_t)); - memcpy(newarg, arg, sizeof(structarg_t)); + memcpy(newarg, arg, sizeof(structarg_t)); - if (pstruct->argcount == 0) - { - pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1); - } else { - pstruct->args = (structarg_t **)realloc( - pstruct->args, - sizeof(structarg_t *) * (pstruct->argcount + 1)); - } + if (pstruct->argcount == 0) { + pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1); + } else { + pstruct->args = (structarg_t **)realloc( + pstruct->args, + sizeof(structarg_t *) * (pstruct->argcount + 1)); + } - newarg->offs = pstruct->argcount * sizeof(cell); - newarg->index = pstruct->argcount; - pstruct->args[pstruct->argcount++] = newarg; + newarg->offs = pstruct->argcount * sizeof(cell); + newarg->index = pstruct->argcount; + pstruct->args[pstruct->argcount++] = newarg; - return newarg; + return newarg; } void funcenums_free() { - funcenum_t *e, *next; + funcenum_t *e, *next; - e = firstenum; - while (e) - { - functag_t *tag, *nexttag; - tag = e->first; - while (tag) - { - nexttag = tag->next; - free(tag); - tag = nexttag; - } - next = e->next; - free(e); - e = next; - } + e = firstenum; + while (e) { + functag_t *tag, *nexttag; + tag = e->first; + while (tag) { + nexttag = tag->next; + free(tag); + tag = nexttag; + } + next = e->next; + free(e); + e = next; + } - firstenum = NULL; - lastenum = NULL; + firstenum = NULL; + lastenum = NULL; } -funcenum_t *funcenums_find_byval(int value) +funcenum_t *funcenums_find_by_tag(int tag) { - funcenum_t *e = firstenum; + funcenum_t *e = firstenum; - while (e) - { - if (e->value == value) - { - return e; - } - e = e->next; - } + while (e) { + if (e->tag == tag) + return e; + e = e->next; + } - return NULL; + return NULL; } funcenum_t *funcenums_add(const char *name) { - funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t)); + funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t)); - memset(e, 0, sizeof(funcenum_t)); + memset(e, 0, sizeof(funcenum_t)); - if (firstenum == NULL) - { - firstenum = e; - lastenum = e; - } else { - lastenum->next = e; - lastenum = e; - } + if (!firstenum) { + firstenum = e; + lastenum = e; + } else { + lastenum->next = e; + lastenum = e; + } - strcpy(e->name, name); - e->value = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG); + strcpy(e->name, name); + e->tag = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG); - return e; + return e; +} + +funcenum_t *funcenum_for_symbol(symbol *sym) +{ + functag_t ft; + memset(&ft, 0, sizeof(ft)); + + ft.ret_tag = sym->tag; + ft.usage = uPUBLIC & (sym->usage & uRETVALUE); + ft.argcount = 0; + ft.ommittable = FALSE; + for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) { + funcarg_t *dest = &ft.args[ft.argcount++]; + + dest->tagcount = arg->numtags; + memcpy(dest->tags, arg->tags, arg->numtags * sizeof(int)); + + dest->dimcount = arg->numdim; + memcpy(dest->dims, arg->dim, arg->numdim * sizeof(int)); + + dest->ident = arg->ident; + dest->fconst = !!(arg->usage & uCONST); + dest->ommittable = FALSE; + } + + char name[METHOD_NAMEMAX+1]; + UTIL_Format(name, sizeof(name), "::ft:%s:%d:%d", sym->name, sym->addr, sym->codeaddr); + + funcenum_t *fe = funcenums_add(name); + functags_add(fe, &ft); + + return fe; +} + +// Finds a functag that was created intrinsically. +functag_t *functag_find_intrinsic(int tag) +{ + funcenum_t *fe = funcenums_find_by_tag(tag); + if (!fe) + return NULL; + + if (strncmp(fe->name, "::ft:", 5) != 0) + return NULL; + + assert(fe->first && fe->first == fe->last); + return fe->first; } functag_t *functags_add(funcenum_t *en, functag_t *src) { - functag_t *t = (functag_t *)malloc(sizeof(functag_t)); - - memcpy(t, src, sizeof(functag_t)); + functag_t *t = (functag_t *)malloc(sizeof(functag_t)); + + memcpy(t, src, sizeof(functag_t)); - t->next = NULL; + t->next = NULL; - if (en->first == NULL) - { - en->first = t; - en->last = t; - } else { - en->last->next = t; - en->last = t; - } + if (en->first == NULL) { + en->first = t; + en->last = t; + } else { + en->last->next = t; + en->last = t; + } - return t; + return t; } /** @@ -318,16 +345,13 @@ void _heap_freeusage(memuse_list_t *heap, int dofree) { memuse_t *cur=heap->head; memuse_t *tmp; - while (cur) - { - if (cur->type == MEMUSE_STATIC) - { + while (cur) { + if (cur->type == MEMUSE_STATIC) { modheap((-1)*cur->size*sizeof(cell)); } else { modheap_i(); } - if (dofree) - { + if (dofree) { tmp=cur->prev; free(cur); cur=tmp; @@ -336,9 +360,7 @@ void _heap_freeusage(memuse_list_t *heap, int dofree) } } if (dofree) - { heap->head=NULL; - } } void _stack_genusage(memuse_list_t *stack, int dofree) @@ -575,3 +597,18 @@ int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2) } return FALSE; } + +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + size_t len = vsnprintf(buffer, maxlength, fmt, ap); + va_end(ap); + + if (len >= maxlength) { + buffer[maxlength - 1] = '\0'; + return maxlength - 1; + } + return len; +} diff --git a/sourcepawn/compiler/sctracker.h b/sourcepawn/compiler/sctracker.h index 439d97b4..a9ff552c 100644 --- a/sourcepawn/compiler/sctracker.h +++ b/sourcepawn/compiler/sctracker.h @@ -31,7 +31,7 @@ typedef struct funcarg_s typedef struct functag_s { int ret_tag; - int type; + int usage; int argcount; int ommittable; funcarg_t args[sARGS_MAX]; @@ -40,8 +40,8 @@ typedef struct functag_s typedef struct funcenum_s { - int value; - char name[sNAMEMAX+1]; + int tag; + char name[METHOD_NAMEMAX+1]; functag_t *first; functag_t *last; struct funcenum_s *next; @@ -116,8 +116,10 @@ structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member); */ void funcenums_free(); funcenum_t *funcenums_add(const char *name); -funcenum_t *funcenums_find_byval(int value); +funcenum_t *funcenums_find_by_tag(int tag); functag_t *functags_add(funcenum_t *en, functag_t *src); +funcenum_t *funcenum_for_symbol(symbol *sym); +functag_t *functag_find_intrinsic(int tag); /** * Given a name or tag, find any extra weirdness it has associated with it. @@ -167,4 +169,6 @@ void methodmaps_free(); extern memuse_list_t *heapusage; extern memuse_list_t *stackusage; +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); + #endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_ diff --git a/sourcepawn/compiler/scvars.c b/sourcepawn/compiler/scvars.c deleted file mode 100644 index a7b5b5f9..00000000 --- a/sourcepawn/compiler/scvars.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Pawn compiler - * - * Global (cross-module) variables. - * - * Copyright (c) ITB CompuPhase, 1997-2006 - * - * This software is provided "as-is", without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ -#include -#include /* for _MAX_PATH */ -#include "sc.h" -#include "sp_symhash.h" - -/* global variables - * - * All global variables that are shared amongst the compiler files are - * declared here. - */ -SC_VDEFINE symbol loctab; /* local symbol table */ -SC_VDEFINE symbol glbtab; /* global symbol table */ -SC_VDEFINE cell *litq; /* the literal queue */ -SC_VDEFINE unsigned char pline[sLINEMAX+1]; /* the line read from the input file */ -SC_VDEFINE const unsigned char *lptr; /* points to the current position in "pline" */ -SC_VDEFINE constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */ -SC_VDEFINE constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */ -SC_VDEFINE constvalue *curlibrary = NULL; /* current library */ -SC_VDEFINE int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */ -SC_VDEFINE symbol *curfunc; /* pointer to current function */ -SC_VDEFINE char *inpfname; /* pointer to name of the file currently read from */ -SC_VDEFINE char outfname[_MAX_PATH]; /* intermediate (assembler) file name */ -SC_VDEFINE char binfname[_MAX_PATH]; /* binary file name */ -SC_VDEFINE char errfname[_MAX_PATH]; /* error file name */ -SC_VDEFINE char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/ -SC_VDEFINE char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */ -SC_VDEFINE int litidx = 0; /* index to literal table */ -SC_VDEFINE int litmax = sDEF_LITMAX; /* current size of the literal table */ -SC_VDEFINE int stgidx = 0; /* index to the staging buffer */ -SC_VDEFINE int sc_labnum = 0; /* number of (internal) labels */ -SC_VDEFINE int staging = 0; /* true if staging output */ -SC_VDEFINE cell declared = 0; /* number of local cells declared */ -SC_VDEFINE cell glb_declared=0; /* number of global cells declared */ -SC_VDEFINE cell code_idx = 0; /* number of bytes with generated code */ -SC_VDEFINE int ntv_funcid= 0; /* incremental number of native function */ -SC_VDEFINE int errnum = 0; /* number of errors */ -SC_VDEFINE int warnnum = 0; /* number of warnings */ -SC_VDEFINE int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */ -SC_VDEFINE int sc_packstr= FALSE; /* strings are packed by default? */ -SC_VDEFINE int sc_asmfile= FALSE; /* create .ASM file? */ -SC_VDEFINE int sc_listing= FALSE; /* create .LST file? */ -SC_VDEFINE int sc_compress=TRUE; /* compress bytecode? */ -SC_VDEFINE int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */ -SC_VDEFINE int sc_dataalign=sizeof(cell);/* data alignment value */ -SC_VDEFINE int sc_alignnext=FALSE; /* must frame of the next function be aligned? */ -SC_VDEFINE int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */ -SC_VDEFINE int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */ -SC_VDEFINE cell pc_stksize=sDEF_AMXSTACK;/* default stack size */ -SC_VDEFINE cell pc_amxlimit=0; /* default abstract machine size limit = none */ -SC_VDEFINE cell pc_amxram=0; /* default abstract machine data size limit = none */ -SC_VDEFINE int freading = FALSE; /* Is there an input file ready for reading? */ -SC_VDEFINE int fline = 0; /* the line number in the current file */ -SC_VDEFINE short fnumber = 0; /* the file number in the file table (debugging) */ -SC_VDEFINE short fcurrent= 0; /* current file being processed (debugging) */ -SC_VDEFINE short sc_intest=FALSE; /* true if inside a test */ -SC_VDEFINE int sideeffect= 0; /* true if an expression causes a side-effect */ -SC_VDEFINE int stmtindent= 0; /* current indent of the statement */ -SC_VDEFINE int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */ -SC_VDEFINE int sc_tabsize=8; /* number of spaces that a TAB represents */ -SC_VDEFINE short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */ -SC_VDEFINE int sc_status; /* read/write status */ -SC_VDEFINE int sc_err_status; -SC_VDEFINE int sc_rationaltag=0; /* tag for rational numbers */ -SC_VDEFINE int rational_digits=0; /* number of fractional digits */ -SC_VDEFINE int sc_allowproccall=0; /* allow/detect tagnames in lex() */ -SC_VDEFINE short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */ -SC_VDEFINE char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */ -SC_VDEFINE int sc_curstates=0; /* ID of the current state list */ -SC_VDEFINE int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */ -SC_VDEFINE int pc_memflags=0; /* special flags for the stack/heap usage */ -SC_VDEFINE int sc_showincludes=0; /* show include files */ -SC_VDEFINE int sc_require_newdecls=0; /* Require new-style declarations */ - -SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */ -SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */ - -SC_VDEFINE FILE *inpf = NULL; /* file read from (source or include) */ -SC_VDEFINE FILE *inpf_org= NULL; /* main source file */ -SC_VDEFINE FILE *outf = NULL; /* (intermediate) text file written to */ - -SC_VDEFINE jmp_buf errbuf; - -SC_VDEFINE HashTable *sp_Globals = NULL; - -#if !defined SC_LIGHT - SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */ -#endif - -#if defined __WATCOMC__ && !defined NDEBUG - /* Watcom's CVPACK dislikes .OBJ files without functions */ - static int dummyfunc(void) - { - return 0; - } -#endif diff --git a/sourcepawn/compiler/scvars.cpp b/sourcepawn/compiler/scvars.cpp new file mode 100644 index 00000000..0f030923 --- /dev/null +++ b/sourcepawn/compiler/scvars.cpp @@ -0,0 +1,119 @@ +/* Pawn compiler + * + * Global (cross-module) variables. + * + * Copyright (c) ITB CompuPhase, 1997-2006 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Version: $Id$ + */ +#include +#include /* for _MAX_PATH */ +#include "sc.h" +#include "sp_symhash.h" + +/* global variables + * + * All global variables that are shared amongst the compiler files are + * declared here. + */ +symbol loctab; /* local symbol table */ +symbol glbtab; /* global symbol table */ +cell *litq; /* the literal queue */ +unsigned char pline[sLINEMAX+1]; /* the line read from the input file */ +const unsigned char *lptr; /* points to the current position in "pline" */ +constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */ +constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */ +constvalue *curlibrary = NULL; /* current library */ +int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */ +symbol *curfunc; /* pointer to current function */ +char *inpfname; /* pointer to name of the file currently read from */ +char outfname[_MAX_PATH]; /* intermediate (assembler) file name */ +char binfname[_MAX_PATH]; /* binary file name */ +char errfname[_MAX_PATH]; /* error file name */ +char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/ +char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */ +int litidx = 0; /* index to literal table */ +int litmax = sDEF_LITMAX; /* current size of the literal table */ +int stgidx = 0; /* index to the staging buffer */ +int sc_labnum = 0; /* number of (internal) labels */ +int staging = 0; /* true if staging output */ +cell declared = 0; /* number of local cells declared */ +cell glb_declared=0; /* number of global cells declared */ +cell code_idx = 0; /* number of bytes with generated code */ +int ntv_funcid= 0; /* incremental number of native function */ +int errnum = 0; /* number of errors */ +int warnnum = 0; /* number of warnings */ +int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */ +int sc_packstr= FALSE; /* strings are packed by default? */ +int sc_asmfile= FALSE; /* create .ASM file? */ +int sc_listing= FALSE; /* create .LST file? */ +int sc_compress=TRUE; /* compress bytecode? */ +int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */ +int sc_dataalign=sizeof(cell);/* data alignment value */ +int sc_alignnext=FALSE; /* must frame of the next function be aligned? */ +int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */ +int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */ +cell pc_stksize=sDEF_AMXSTACK;/* default stack size */ +cell pc_amxlimit=0; /* default abstract machine size limit = none */ +cell pc_amxram=0; /* default abstract machine data size limit = none */ +int freading = FALSE; /* Is there an input file ready for reading? */ +int fline = 0; /* the line number in the current file */ +short fnumber = 0; /* the file number in the file table (debugging) */ +short fcurrent= 0; /* current file being processed (debugging) */ +short sc_intest=FALSE; /* true if inside a test */ +int sideeffect= 0; /* true if an expression causes a side-effect */ +int stmtindent= 0; /* current indent of the statement */ +int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */ +int sc_tabsize=8; /* number of spaces that a TAB represents */ +short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */ +int sc_status; /* read/write status */ +int sc_err_status; +int sc_rationaltag=0; /* tag for rational numbers */ +int rational_digits=0; /* number of fractional digits */ +int sc_allowproccall=0; /* allow/detect tagnames in lex() */ +short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */ +char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */ +int sc_curstates=0; /* ID of the current state list */ +int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */ +int pc_memflags=0; /* special flags for the stack/heap usage */ +int sc_showincludes=0; /* show include files */ +int sc_require_newdecls=0; /* Require new-style declarations */ + +constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */ +constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */ + +void *inpf = NULL; /* file read from (source or include) */ +void *inpf_org= NULL; /* main source file */ +void *outf = NULL; /* (intermediate) text file written to */ + +jmp_buf errbuf; + +HashTable *sp_Globals = NULL; + +#if !defined SC_LIGHT + int sc_makereport=FALSE; /* generate a cross-reference report */ +#endif + +#if defined __WATCOMC__ && !defined NDEBUG + /* Watcom's CVPACK dislikes .OBJ files without functions */ + static int dummyfunc(void) + { + return 0; + } +#endif diff --git a/sourcepawn/compiler/sp_file.c b/sourcepawn/compiler/sp_file.c deleted file mode 100644 index e5d6addb..00000000 --- a/sourcepawn/compiler/sp_file.c +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include -#include "sp_file.h" -#include "memfile.h" - -void *mf_open(const char *name); -void mf_close(void *handle); -size_t mf_write(const void *buf, size_t size, size_t count, void *handle); -size_t mf_read(void *buf, size_t size, size_t count, void *handle); -size_t mf_getpos(void *handle); -int mf_setpos(void *handle, size_t pos); - -sp_writefuncs_t cstd_funcs = -{ - mf_open, - mf_close, - mf_write, - mf_read, - mf_getpos, - mf_setpos -}; - -sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) -{ - sp_file_t file; - sp_file_t *pFile; - - if (!optfuncs) - { - optfuncs = &cstd_funcs; - } - - file.handle = optfuncs->fnOpen(name); - if (!file.handle) - { - return NULL; - } - - pFile = (sp_file_t *)malloc(sizeof(sp_file_t)); - - pFile->handle = file.handle; - memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t)); - pFile->curoffs = 0; - pFile->header.magic = SPFILE_MAGIC; - pFile->header.sections = 0; - pFile->header.stringtab = 0; - pFile->header.version = SPFILE_VERSION; - pFile->header.imagesize = 0; - pFile->header.disksize = 0; - pFile->header.compression = SPFILE_COMPRESSION_NONE; - pFile->header.dataoffs = 0; - pFile->lastsection = 0; - pFile->offsets = NULL; - pFile->sections = NULL; - pFile->state = -1; - pFile->nametab = NULL; - pFile->nametab_idx = 0; - - return pFile; -} - -void spfw_destroy(sp_file_t *spf) -{ - free(spf->sections); - free(spf->nametab); - free(spf->offsets); - spf->funcs.fnClose(spf->handle); - free(spf); -} - -uint8_t spfw_add_section(sp_file_t *spf, const char *name) -{ - size_t namelen; - uint8_t s; - if (spf->state != -1) - { - return 0; - } - - namelen = strlen(name) + 1; - - if (spf->header.sections == 0) - { - /** allocate for first section */ - spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t)); - spf->offsets = (size_t *)malloc(sizeof(size_t)); - spf->nametab = (char *)malloc(namelen); - } else { - uint16_t num = spf->header.sections + 1; - spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num); - spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num); - spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen); - } - - s = spf->header.sections; - - spf->sections[s].nameoffs = spf->nametab_idx; - /** - * "fix" offset will be the second uint2 slot, which is after the previous sections after the header. - */ - spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t); - strcpy(&spf->nametab[spf->nametab_idx], name); - spf->nametab_idx += namelen; - - return ++spf->header.sections; -} - -int spfw_finalize_header(sp_file_t *spf) -{ - uint32_t size; - if (spf->state != -1) - { - return -1; - } - - size = sizeof(sp_file_section_t) * spf->header.sections; - - spf->header.stringtab = sizeof(spf->header) + size; - spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx; - if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1) - { - return -1; - } - if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) != - spf->header.sections) - { - return -1; - } - if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx) - { - return -1; - } - spf->curoffs = spf->funcs.fnGetPos(spf->handle); - spf->lastsection = spf->curoffs; - spf->state++; - - return 0; -} - -int spfw_next_section(sp_file_t *spf) -{ - uint8_t s; - uint32_t rest[2]; - - if (spf->state < 0 || spf->state > spf->header.sections) - { - return -1; - } - - if (spf->state == (int)spf->header.sections) - { - return 0; - } - - s = (uint8_t)spf->state; - - spf->curoffs = spf->funcs.fnGetPos(spf->handle); - spf->funcs.fnSetPos(spf->handle, spf->offsets[s]); - - rest[0] = spf->lastsection; - rest[1] = spf->curoffs - spf->lastsection; - if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2) - { - return -1; - } - - spf->funcs.fnSetPos(spf->handle, spf->curoffs); - spf->lastsection = spf->curoffs; - - spf->state++; - - return 1; -} - -int spfw_finalize_all(sp_file_t *spf) -{ - uint8_t offs; - - if (spf->state < spf->header.sections) - { - return -1; - } - - offs = offsetof(sp_file_hdr_t, imagesize); - spf->header.disksize = spf->funcs.fnGetPos(spf->handle); - spf->header.imagesize = spf->funcs.fnGetPos(spf->handle); - spf->funcs.fnSetPos(spf->handle, offs); - spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle); - spf->funcs.fnSetPos(spf->handle, spf->header.imagesize); - - return 1; -} - -/** - * More memory file operations - */ - -void *mf_open(const char *name) -{ - return memfile_creat(name, 1024); -} - -void mf_close(void *handle) -{ - memfile_destroy((memfile_t *)handle); -} - -size_t mf_write(const void *buf, size_t size, size_t count, void *handle) -{ - if (!count) - { - return 0; - } - - if (memfile_write((memfile_t *)handle, buf, size*count)) - { - return count; - } - - return 0; -} - -size_t mf_read(void *buf, size_t size, size_t count, void *handle) -{ - return memfile_read((memfile_t *)handle, buf, size*count) / count; -} - -size_t mf_getpos(void *handle) -{ - return (long)memfile_tell((memfile_t *)handle); -} - -int mf_setpos(void *handle, size_t pos) -{ - memfile_seek((memfile_t *)handle, (long)pos); - return 1; -} - - -#if UNUSED_FOR_NOW -/** - * Default file operations... - * Based on C standard library calls. - */ - -void *fp_open(const char *name) -{ - return fopen(name, "wb"); -} - -void fp_close(void *handle) -{ - fclose((FILE *)handle); -} - -size_t fp_write(const void *buf, size_t size, size_t count, void *handle) -{ - return fwrite(buf, size, count, (FILE *)handle); -} - -size_t fp_read(void *buf, size_t size, size_t count, void *handle) -{ - return fread(buf, size, count, (FILE *)handle); -} - -size_t fp_getpos(void *handle) -{ - return (size_t)ftell((FILE *)handle); -} - -int fp_setpos(void *handle, size_t pos) -{ - return fseek((FILE *)handle, (long)pos, SEEK_SET); -} -#endif diff --git a/sourcepawn/compiler/sp_file.cpp b/sourcepawn/compiler/sp_file.cpp new file mode 100644 index 00000000..b849c311 --- /dev/null +++ b/sourcepawn/compiler/sp_file.cpp @@ -0,0 +1,213 @@ +#include +#include +#include +#include "sp_file.h" +#include "memfile.h" + +void *mf_open(const char *name); +void mf_close(void *handle); +size_t mf_write(const void *buf, size_t size, size_t count, void *handle); +size_t mf_read(void *buf, size_t size, size_t count, void *handle); +size_t mf_getpos(void *handle); +int mf_setpos(void *handle, size_t pos); + +sp_writefuncs_t cstd_funcs = +{ + mf_open, + mf_close, + mf_write, + mf_read, + mf_getpos, + mf_setpos +}; + +sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) +{ + sp_file_t file; + sp_file_t *pFile; + + if (!optfuncs) + optfuncs = &cstd_funcs; + + file.handle = optfuncs->fnOpen(name); + if (!file.handle) + return NULL; + + pFile = (sp_file_t *)malloc(sizeof(sp_file_t)); + + pFile->handle = file.handle; + memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t)); + pFile->curoffs = 0; + pFile->header.magic = SPFILE_MAGIC; + pFile->header.sections = 0; + pFile->header.stringtab = 0; + pFile->header.version = SPFILE_VERSION; + pFile->header.imagesize = 0; + pFile->header.disksize = 0; + pFile->header.compression = SPFILE_COMPRESSION_NONE; + pFile->header.dataoffs = 0; + pFile->lastsection = 0; + pFile->offsets = NULL; + pFile->sections = NULL; + pFile->state = -1; + pFile->nametab = NULL; + pFile->nametab_idx = 0; + + return pFile; +} + +void spfw_destroy(sp_file_t *spf) +{ + free(spf->sections); + free(spf->nametab); + free(spf->offsets); + spf->funcs.fnClose(spf->handle); + free(spf); +} + +uint8_t spfw_add_section(sp_file_t *spf, const char *name) +{ + size_t namelen; + uint8_t s; + if (spf->state != -1) + return 0; + + namelen = strlen(name) + 1; + + if (spf->header.sections == 0) + { + /** allocate for first section */ + spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t)); + spf->offsets = (size_t *)malloc(sizeof(size_t)); + spf->nametab = (char *)malloc(namelen); + } else { + uint16_t num = spf->header.sections + 1; + spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num); + spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num); + spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen); + } + + s = spf->header.sections; + + spf->sections[s].nameoffs = spf->nametab_idx; + /** + * "fix" offset will be the second uint2 slot, which is after the previous sections after the header. + */ + spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t); + strcpy(&spf->nametab[spf->nametab_idx], name); + spf->nametab_idx += namelen; + + return ++spf->header.sections; +} + +int spfw_finalize_header(sp_file_t *spf) +{ + uint32_t size; + if (spf->state != -1) + return -1; + + size = sizeof(sp_file_section_t) * spf->header.sections; + + spf->header.stringtab = sizeof(spf->header) + size; + spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx; + if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1) + return -1; + if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) != + spf->header.sections) + return -1; + if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx) + return -1; + spf->curoffs = spf->funcs.fnGetPos(spf->handle); + spf->lastsection = spf->curoffs; + spf->state++; + + return 0; +} + +int spfw_next_section(sp_file_t *spf) +{ + uint8_t s; + uint32_t rest[2]; + + if (spf->state < 0 || spf->state > spf->header.sections) + return -1; + + if (spf->state == (int)spf->header.sections) + return 0; + + s = (uint8_t)spf->state; + + spf->curoffs = spf->funcs.fnGetPos(spf->handle); + spf->funcs.fnSetPos(spf->handle, spf->offsets[s]); + + rest[0] = spf->lastsection; + rest[1] = spf->curoffs - spf->lastsection; + if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2) + return -1; + + spf->funcs.fnSetPos(spf->handle, spf->curoffs); + spf->lastsection = spf->curoffs; + + spf->state++; + + return 1; +} + +int spfw_finalize_all(sp_file_t *spf) +{ + uint8_t offs; + + if (spf->state < spf->header.sections) + return -1; + + offs = offsetof(sp_file_hdr_t, imagesize); + spf->header.disksize = spf->funcs.fnGetPos(spf->handle); + spf->header.imagesize = spf->funcs.fnGetPos(spf->handle); + spf->funcs.fnSetPos(spf->handle, offs); + spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle); + spf->funcs.fnSetPos(spf->handle, spf->header.imagesize); + + return 1; +} + +/** + * More memory file operations + */ + +void *mf_open(const char *name) +{ + return memfile_creat(name, 1024); +} + +void mf_close(void *handle) +{ + memfile_destroy((memfile_t *)handle); +} + +size_t mf_write(const void *buf, size_t size, size_t count, void *handle) +{ + if (!count) + return 0; + + if (memfile_write((memfile_t *)handle, buf, size*count)) + return count; + + return 0; +} + +size_t mf_read(void *buf, size_t size, size_t count, void *handle) +{ + return memfile_read((memfile_t *)handle, buf, size*count) / count; +} + +size_t mf_getpos(void *handle) +{ + return (long)memfile_tell((memfile_t *)handle); +} + +int mf_setpos(void *handle, size_t pos) +{ + memfile_seek((memfile_t *)handle, (long)pos); + return 1; +} + diff --git a/sourcepawn/compiler/sp_file.h b/sourcepawn/compiler/sp_file.h index f2d39786..2a9edcbe 100644 --- a/sourcepawn/compiler/sp_file.h +++ b/sourcepawn/compiler/sp_file.h @@ -8,30 +8,30 @@ */ typedef struct sp_writefuncs_s { - void *(*fnOpen)(const char *); /* filename, returns handle */ - void (*fnClose)(void *); /* handle */ - /* buffer, size, count, handle, returns count written */ - size_t (*fnWrite)(const void *, size_t, size_t, void *); - /* buffer, size, count, handle, returns count read */ - size_t (*fnRead)(void *, size_t, size_t, void *); - /* returns current position from start */ - size_t (*fnGetPos)(void *); - /* sets current position from start, return 0 for success, nonzero for error */ - int (*fnSetPos)(void *, size_t); + void *(*fnOpen)(const char *); /* filename, returns handle */ + void (*fnClose)(void *); /* handle */ + /* buffer, size, count, handle, returns count written */ + size_t (*fnWrite)(const void *, size_t, size_t, void *); + /* buffer, size, count, handle, returns count read */ + size_t (*fnRead)(void *, size_t, size_t, void *); + /* returns current position from start */ + size_t (*fnGetPos)(void *); + /* sets current position from start, return 0 for success, nonzero for error */ + int (*fnSetPos)(void *, size_t); } sp_writefuncs_t; typedef struct sp_file_s { - sp_file_hdr_t header; - sp_file_section_t *sections; - size_t *offsets; - sp_writefuncs_t funcs; - size_t lastsection; - size_t curoffs; - void *handle; - int state; - char *nametab; - size_t nametab_idx; + sp_file_hdr_t header; + sp_file_section_t *sections; + size_t *offsets; + sp_writefuncs_t funcs; + size_t lastsection; + size_t curoffs; + void *handle; + int state; + char *nametab; + size_t nametab_idx; } sp_file_t; /** diff --git a/public/sourcepawn/sp_file_headers.h b/sourcepawn/compiler/sp_file_headers.h similarity index 100% rename from public/sourcepawn/sp_file_headers.h rename to sourcepawn/compiler/sp_file_headers.h diff --git a/sourcepawn/compiler/sp_symhash.c b/sourcepawn/compiler/sp_symhash.c deleted file mode 100644 index bb35a5ac..00000000 --- a/sourcepawn/compiler/sp_symhash.c +++ /dev/null @@ -1,230 +0,0 @@ -/* vim: set ts=4 sw=4 tw=99 et: */ -#include -#include -#include -#include "sp_file_headers.h" -#include "sc.h" -#include "sp_symhash.h" - -SC_FUNC uint32_t -NameHash(const char *str) -{ - size_t len = strlen(str); - const uint8_t *data = (uint8_t *)str; - #undef get16bits - #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) - #define get16bits(d) (*((const uint16_t *) (d))) - #endif - #if !defined (get16bits) - #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ - +(uint32_t)(((const uint8_t *)(d))[0]) ) - #endif - uint32_t hash = len, tmp; - int rem; - - if (len <= 0 || data == NULL) return 0; - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (uint16_t); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= data[sizeof (uint16_t)] << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += *data; - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; - - #undef get16bits -} - -SC_FUNC HashTable *NewHashTable() -{ - HashTable *ht = (HashTable*)malloc(sizeof(HashTable)); - if (!ht) - return ht; - ht->buckets = (HashEntry **)calloc(32, sizeof(HashEntry *)); - if (!ht->buckets) { - free(ht); - return NULL; - } - ht->nbuckets = 32; - ht->nused = 0; - ht->bucketmask = 32 - 1; - return ht; -} - -SC_FUNC void -DestroyHashTable(HashTable *ht) -{ - uint32_t i; - if (!ht) - return; - for (i = 0; i < ht->nbuckets; i++) { - HashEntry *he = ht->buckets[i]; - while (he != NULL) { - HashEntry *next = he->next; - free(he); - he = next; - } - } - free(ht->buckets); - free(ht); -} - -SC_FUNC symbol * -FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, - int *cmptag) -{ - int count=0; - symbol *firstmatch=NULL; - uint32_t hash = NameHash(name); - uint32_t bucket = hash & ht->bucketmask; - HashEntry *he = ht->buckets[bucket]; - - assert(cmptag!=NULL); - - while (he != NULL) { - symbol *sym = he->sym; - if ((sym->parent==NULL || sym->ident==iCONSTEXPR) && - (sym->fnumber<0 || sym->fnumber==fnumber) && - (strcmp(sym->name, name) == 0)) - { - /* return closest match or first match; count number of matches */ - if (firstmatch==NULL) - firstmatch=sym; - if (*cmptag==0) - count++; - if (*cmptag==sym->tag) { - *cmptag=1; /* good match found, set number of matches to 1 */ - return sym; - } - } - he = he->next; - } - - if (firstmatch!=NULL) - *cmptag=count; - return firstmatch; -} - -SC_FUNC symbol * -FindInHashTable(HashTable *ht, const char *name, int fnumber) -{ - uint32_t hash = NameHash(name); - uint32_t bucket = hash & ht->bucketmask; - HashEntry *he = ht->buckets[bucket]; - - while (he != NULL) { - symbol *sym = he->sym; - if ((sym->parent==NULL || sym->ident==iCONSTEXPR) && - (sym->fnumber<0 || sym->fnumber==fnumber) && - (strcmp(sym->name, name) == 0)) - { - return sym; - } - he = he->next; - } - - return NULL; -} - -static void -ResizeHashTable(HashTable *ht) -{ - uint32_t i; - uint32_t xnbuckets = ht->nbuckets * 2; - uint32_t xbucketmask = xnbuckets - 1; - HashEntry **xbuckets = (HashEntry **)calloc(xnbuckets, sizeof(HashEntry*)); - if (!xbuckets) - return; - - for (i = 0; i < ht->nbuckets; i++) { - HashEntry *he = ht->buckets[i]; - while (he != NULL) { - HashEntry *next = he->next; - uint32_t bucket = he->sym->hash & xbucketmask; - he->next = xbuckets[bucket]; - xbuckets[bucket] = he; - he = next; - } - } - free(ht->buckets); - ht->buckets = xbuckets; - ht->nbuckets = xnbuckets; - ht->bucketmask = xbucketmask; -} - -SC_FUNC void -AddToHashTable(HashTable *ht, symbol *sym) -{ - uint32_t bucket = sym->hash & ht->bucketmask; - HashEntry **hep, *he; - - hep = &ht->buckets[bucket]; - while (*hep) { - assert((*hep)->sym != sym); - hep = &(*hep)->next; - } - - he = (HashEntry *)malloc(sizeof(HashEntry)); - if (!he) - error(163); - he->sym = sym; - he->next = NULL; - *hep = he; - ht->nused++; - - if (ht->nused > ht->nbuckets && ht->nbuckets <= INT_MAX / 2) - ResizeHashTable(ht); -} - -SC_FUNC void -RemoveFromHashTable(HashTable *ht, symbol *sym) -{ - uint32_t bucket = sym->hash & ht->bucketmask; - HashEntry **hep = &ht->buckets[bucket]; - HashEntry *he = *hep; - - while (he != NULL) { - if (he->sym == sym) { - *hep = he->next; - free(he); - ht->nused--; - return; - } - hep = &he->next; - he = *hep; - } - - assert(0); -} - diff --git a/sourcepawn/compiler/sp_symhash.cpp b/sourcepawn/compiler/sp_symhash.cpp new file mode 100644 index 00000000..b843698c --- /dev/null +++ b/sourcepawn/compiler/sp_symhash.cpp @@ -0,0 +1,130 @@ +// vim: set ts=8 sts=2 sw=2 tw=99 et: +#include +#include +#include +#include "sp_file_headers.h" +#include "sc.h" +#include "sp_symhash.h" +#include + +struct NameAndScope +{ + const char *name; + int fnumber; + int *cmptag; + mutable symbol *matched; + mutable int count; + + NameAndScope(const char *name, int fnumber, int *cmptag) + : name(name), + fnumber(fnumber), + cmptag(cmptag), + matched(nullptr), + count(0) + { + } +}; + +struct SymbolHashPolicy +{ + typedef symbol *Payload; + + // Everything with the same name has the same hash, because the compiler + // wants to know two names that have the same tag for some reason. Even + // so, we can't be that accurate, since we might match the right symbol + // very early. + static uint32_t hash(const NameAndScope &key) { + return ke::HashCharSequence(key.name, strlen(key.name)); + } + static uint32_t hash(const symbol *s) { + return ke::HashCharSequence(s->name, strlen(s->name)); + } + + static bool matches(const NameAndScope &key, symbol *sym) { + if (sym->parent && sym->ident != iCONSTEXPR) + return false; + if (sym->fnumber >= 0 && sym->fnumber != key.fnumber) + return false; + if (strcmp(key.name, sym->name) != 0) + return false; + if (key.cmptag) { + key.count++; + key.matched = sym; + if (*key.cmptag != sym->tag) + return false; + } + return true; + } + static bool matches(const symbol *key, symbol *sym) { + return key == sym; + } +}; + +struct HashTable : public ke::HashTable +{ +}; + +uint32_t +NameHash(const char *str) +{ + return ke::HashCharSequence(str, strlen(str)); +} + +HashTable *NewHashTable() +{ + HashTable *ht = new HashTable(); + if (!ht->init()) { + delete ht; + return nullptr; + } + return ht; +} + +void +DestroyHashTable(HashTable *ht) +{ + delete ht; +} + +symbol * +FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, int *cmptag) +{ + NameAndScope nas(name, fnumber, cmptag); + HashTable::Result r = ht->find(nas); + if (!r.found()) { + if (nas.matched) { + *cmptag = nas.count; + return nas.matched; + } + return nullptr; + } + + *cmptag = 1; + return *r; +} + +symbol * +FindInHashTable(HashTable *ht, const char *name, int fnumber) +{ + NameAndScope nas(name, fnumber, nullptr); + HashTable::Result r = ht->find(nas); + if (!r.found()) + return nullptr; + return *r; +} + +void +AddToHashTable(HashTable *ht, symbol *sym) +{ + HashTable::Insert i = ht->findForAdd(sym); + assert(!i.found()); + ht->add(i, sym); +} + +void +RemoveFromHashTable(HashTable *ht, symbol *sym) +{ + HashTable::Result r = ht->find(sym); + assert(r.found()); + ht->remove(r); +} diff --git a/sourcepawn/compiler/sp_symhash.h b/sourcepawn/compiler/sp_symhash.h index beb0f1e5..3617368f 100644 --- a/sourcepawn/compiler/sp_symhash.h +++ b/sourcepawn/compiler/sp_symhash.h @@ -1,28 +1,18 @@ -/* vim: set ts=4 sw=4 tw=99 et: */ -#ifndef _INCLUDE_SPCOMP_SYMHASH_H_ -#define _INCLUDE_SPCOMP_SYMHASH_H_ - -SC_FUNC uint32_t NameHash(const char *str); - -typedef struct HashEntry { - symbol *sym; - struct HashEntry *next; -} HashEntry; - -struct HashTable { - uint32_t nbuckets; - uint32_t nused; - uint32_t bucketmask; - HashEntry **buckets; -}; - -SC_FUNC HashTable *NewHashTable(); -SC_FUNC void DestroyHashTable(HashTable *ht); -SC_FUNC void AddToHashTable(HashTable *ht, symbol *sym); -SC_FUNC void RemoveFromHashTable(HashTable *ht, symbol *sym); -SC_FUNC symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber); -SC_FUNC symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, - int *cmptag); - -#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */ - +/* vim: set ts=4 sw=4 tw=99 et: */ +#ifndef _INCLUDE_SPCOMP_SYMHASH_H_ +#define _INCLUDE_SPCOMP_SYMHASH_H_ + +uint32_t NameHash(const char *str); + +struct HashTable; + +HashTable *NewHashTable(); +void DestroyHashTable(HashTable *ht); +void AddToHashTable(HashTable *ht, symbol *sym); +void RemoveFromHashTable(HashTable *ht, symbol *sym); +symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber); +symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, + int *cmptag); + +#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */ + diff --git a/sourcepawn/compiler/tests/ok-trailing-comma-in-literal.sp b/sourcepawn/compiler/tests/ok-trailing-comma-in-literal.sp new file mode 100644 index 00000000..e1876f6d --- /dev/null +++ b/sourcepawn/compiler/tests/ok-trailing-comma-in-literal.sp @@ -0,0 +1,20 @@ + +new String:oldArray[][] = +{ + "string", + "string2", +}; + +char newArray[][] = +{ + "another string", + "more strings", +}; + +native Print( const String:string[] ); + +public OnPluginStart() +{ + Print( oldArray[ 0 ] ); + Print( newArray[ 0 ] ); +} diff --git a/sourcepawn/compiler/tests/ok-typedef-func-chars.sp b/sourcepawn/compiler/tests/ok-typedef-func-chars.sp new file mode 100644 index 00000000..36f8753c --- /dev/null +++ b/sourcepawn/compiler/tests/ok-typedef-func-chars.sp @@ -0,0 +1,26 @@ +enum Action: {} +functag public Action:OldFuncTag( String:someString[128] ); +typedef NewFuncTag = function Action ( char someString[128] ); + +native UseOldFuncTag( OldFuncTag func ); +native UseNewFuncTag( NewFuncTag func ); + +public OnPluginStart() +{ + // fine + UseOldFuncTag( MyOldFunc ); + // also fine + UseOldFuncTag( MyNewFunc ); + + // error 100: function prototypes do not match + UseNewFuncTag( MyOldFunc ); + // error 100: function prototypes do not match + UseNewFuncTag( MyNewFunc ); +} + +public Action:MyOldFunc( String:someString[128] ) +{ +} +public Action MyNewFunc( char someString[128] ) +{ +} diff --git a/sourcepawn/include/smx/smx-headers.h b/sourcepawn/include/smx/smx-headers.h new file mode 100644 index 00000000..dc9d7dcf --- /dev/null +++ b/sourcepawn/include/smx/smx-headers.h @@ -0,0 +1,164 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. +// ============================================================================= +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License, version 3.0, as published by the +// Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// +// As a special exception, AlliedModders LLC gives you permission to link the +// code of this program (as well as its derivative works) to "Half-Life 2," the +// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +// by the Valve Corporation. You must obey the GNU General Public License in +// all respects for all other code used. Additionally, AlliedModders LLC grants +// this exception to all derivative works. AlliedModders LLC defines further +// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +// or . + +#ifndef _INCLUDE_SPFILE_HEADERS_H +#define _INCLUDE_SPFILE_HEADERS_H + +#include +#include + +namespace sp { + +struct SmxConsts +{ + // SourcePawn File Format (SPFF) magic number. + static const uint32_t FILE_MAGIC = 0x53504646; + + // File format verison number. + // 0x0101 - Initial version used by spcomp1 and SourceMod 1.0. + // 0x0102 - Used by spcomp1 and SourceMod 1.1+. + // 0x0103 - Used by SourceMod 1.7+. + // 0x0200 - Used by spcomp2. + // + // The major version bits (8-15) indicate a product number. Consumers should + // reject any version for a different product. + // + // The minor version bits (0-7) indicate a compatibility revision. Any minor + // version higher than the current version should be rejected. + static const uint16_t SP1_VERSION_MIN = 0x0101; + static const uint16_t SP1_VERSION_MAX = 0x0103; + static const uint16_t SP2_VERSION_MIN = 0x0200; + static const uint16_t SP2_VERSION_MAX = 0x0200; + + // Compression types. + static const uint8_t FILE_COMPRESSION_NONE = 0; + static const uint8_t FILE_COMPRESSION_GZ = 1; + + // SourcePawn 1.0. + static const uint8_t CODE_VERSION_JIT1 = 9; + + // SourcePawn 1.1. + static const uint8_t CODE_VERSION_JIT2 = 10; + + // For SP1 consumers, the container version may not be checked, but usually + // the code version is. This constant allows newer containers to be rejected + // in those applications. + static const uint8_t CODE_VERSION_REJECT = 0x7F; +}; + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// The very first bytes in a .smx file. The .smx file format is a container for +// arbitrary sections, though to actually load a .smx file certain sections +// must be present. The on-disk format has four major regions, in order: +// 1. The header (sp_file_hdr_t). +// 2. The section list (sp_file_section_t). +// 3. The string table. +// 4. The section contents. +// +// Although any part of the file after the header can be compressed, by default +// only the section contents are, and the section list and string table are not. +typedef struct sp_file_hdr_s +{ + // Magic number and version number. + uint32_t magic; + uint16_t version; + + // Compression algorithm. If the file is not compressed, then imagesize and + // disksize are the same value, and dataoffs is 0. + // + // The start of the compressed region is indicated by dataoffs. The length + // of the compressed region is (disksize - dataoffs). The amount of memory + // required to hold the decompressed bytes is (imagesize - dataoffs). The + // compressed region should be expanded in-place. That is, bytes before + // "dataoffs" should be retained, and the decompressed region should be + // appended. + // + // |imagesize| is the amount of memory required to hold the entire container + // in memory. + // + // Note: This scheme may seem odd. It's a combination of historical debt and + // previously unspecified behavior. The original .amx file format contained + // an on-disk structure that supported an endian-agnostic variable-length + // encoding of its data section, and this structure was loaded directly into + // memory and used as the VM context. AMX Mod X later developed a container + // format called ".amxx" as a "universal binary" for 32-bit and 64-bit + // plugins. This format dropped compact encoding, but supported gzip. The + // disksize/imagesize oddness made its way to this file format. When .smx + // was created for SourceMod, it persisted even though AMX was dropped + // entirely. So it goes. + uint8_t compression; + uint32_t disksize; + uint32_t imagesize; + + // Number of named file sections. + uint8_t sections; + + // Offset to the string table. Each string is null-terminated. The string + // table is only used for strings related to parsing the container itself. + // For SourcePawn, a separate ".names" section exists for Pawn-specific data. + uint32_t stringtab; + + // Offset to where compression begins. + uint32_t dataoffs; +} sp_file_hdr_t; + +// Each section is written immediately after the header. +typedef struct sp_file_section_s +{ + uint32_t nameoffs; /**< Offset into the string table. */ + uint32_t dataoffs; /**< Offset into the file for the section contents. */ + uint32_t size; /**< Size of this section's contents. */ +} sp_file_section_t; + +// Code section. This is used only in SP1, but is emitted by default for legacy +// systems which check |codeversion| but not the SMX file version. +typedef struct sp_file_code_s +{ + uint32_t codesize; /**< Size of the code section. */ + uint8_t cellsize; /**< Cellsize in bytes. */ + uint8_t codeversion; /**< Version of opcodes supported. */ + uint16_t flags; /**< Flags. */ + uint32_t main; /**< Address to "main". */ + uint32_t code; /**< Offset to bytecode, relative to the start of this section. */ +} sp_file_code_t; + +#if defined __GNUC__ +# pragma pack() +#else +# pragma pack(pop) +#endif + +} // namespace sp + +#endif //_INCLUDE_SPFILE_HEADERS_H diff --git a/sourcepawn/include/smx/smx-v1-opcodes.h b/sourcepawn/include/smx/smx-v1-opcodes.h new file mode 100644 index 00000000..9ed2601d --- /dev/null +++ b/sourcepawn/include/smx/smx-v1-opcodes.h @@ -0,0 +1,266 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved. +// ============================================================================= +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License, version 3.0, as published by the +// Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// +// As a special exception, AlliedModders LLC gives you permission to link the +// code of this program (as well as its derivative works) to "Half-Life 2," the +// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +// by the Valve Corporation. You must obey the GNU General Public License in +// all respects for all other code used. Additionally, AlliedModders LLC grants +// this exception to all derivative works. AlliedModders LLC defines further +// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +// or . + +#ifndef _INCLUDE_SPFILE_HEADERS_v1_opcodes_H +#define _INCLUDE_SPFILE_HEADERS_v1_opcodes_H + +#include +#include + +namespace sp { + +// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few, +// if they could, make little sense in the context of a JIT and could not +// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively, +// the code emitter and peephole optimizer) are not necessarily ever generated. +// For example, lref.pri and lref.alt would be used if a reference could be +// stored in the global scope; but they can't, so they are unreachable. +// +// Most opcodes have been manually verified. A few have not, as they are only +// produced by the peephole optimizer, or not produced at all, or eliminated +// during optimization. We generate them anyway, just in case, but they have +// not been tested. +// lref.s.alt (phopt only) +// stor.alt (never) +// stor.s.alt (never) +// sref.s.alt (never) +// lidx.b (phopt only, probably impossible) +// idxaddr.b (phopt only, looks difficult) +// move.pri (eliminated in phopt) +// shl.c.pri (eliminated in phopt) +// shl.c.alt (eliminated in phopt) +// shr.c.pri (eliminated in phopt) +// shr.c.alt (eliminated in phopt) +// eq.c.alt (never) +// inc.alt (never) +// dec.alt (never) +// sdiv (never) +// nop (never in function bodies) +// +// Additionally, some opcodes which were supported in the earlier JIT are no +// longer supported because of the above: +// lref.pri/alt +// sref.pri/alt +// sign.pri/alt + +#define OPCODE_LIST(_) \ + _(NONE, "none") \ + _(LOAD_PRI, "load.pri") \ + _(LOAD_ALT, "load.alt") \ + _(LOAD_S_PRI, "load.s.pri") \ + _(LOAD_S_ALT, "load.s.alt") \ + _(UNGEN_LREF_PRI, "lref.pri") \ + _(UNGEN_LREF_ALT, "lref.alt") \ + _(LREF_S_PRI, "lref.s.pri") \ + _(LREF_S_ALT, "lref.s.alt") \ + _(LOAD_I, "load.i") \ + _(LODB_I, "lodb.i") \ + _(CONST_PRI, "const.pri") \ + _(CONST_ALT, "const.alt") \ + _(ADDR_PRI, "addr.pri") \ + _(ADDR_ALT, "addr.alt") \ + _(STOR_PRI, "stor.pri") \ + _(STOR_ALT, "stor.alt") \ + _(STOR_S_PRI, "stor.s.pri") \ + _(STOR_S_ALT, "stor.s.alt") \ + _(UNGEN_SREF_PRI, "sref.pri") \ + _(UNGEN_SREF_ALT, "sref.alt") \ + _(SREF_S_PRI, "sref.s.pri") \ + _(SREF_S_ALT, "sref.s.alt") \ + _(STOR_I, "stor.i") \ + _(STRB_I, "strb.i") \ + _(LIDX, "lidx") \ + _(LIDX_B, "lidx.b") \ + _(IDXADDR, "idxaddr") \ + _(IDXADDR_B, "idxaddr.b") \ + _(UNGEN_ALIGN_PRI,"align.pri") \ + _(UNGEN_ALIGN_ALT,"align.alt") \ + _(UNGEN_LCTRL, "lctrl") \ + _(UNGEN_SCTRL, "sctrl") \ + _(MOVE_PRI, "move.pri") \ + _(MOVE_ALT, "move.alt") \ + _(XCHG, "xchg") \ + _(PUSH_PRI, "push.pri") \ + _(PUSH_ALT, "push.alt") \ + _(UNGEN_PUSH_R, "push.r") \ + _(PUSH_C, "push.c") \ + _(PUSH, "push") \ + _(PUSH_S, "push.s") \ + _(POP_PRI, "pop.pri") \ + _(POP_ALT, "pop.alt") \ + _(STACK, "stack") \ + _(HEAP, "heap") \ + _(PROC, "proc") \ + _(UNGEN_RET, "ret") \ + _(RETN, "retn") \ + _(CALL, "call") \ + _(UNGEN_CALL_PRI, "call.pri") \ + _(JUMP, "jump") \ + _(UNGEN_JREL, "jrel") \ + _(JZER, "jzer") \ + _(JNZ, "jnz") \ + _(JEQ, "jeq") \ + _(JNEQ, "jneq") \ + _(UNGEN_JLESS, "jsless") \ + _(UNGEN_JLEQ, "jleq") \ + _(UNGEN_JGRTR, "jgrtr") \ + _(UNGEN_JGEQ, "jgeq") \ + _(JSLESS, "jsless") \ + _(JSLEQ, "jsleq") \ + _(JSGRTR, "jsgrtr") \ + _(JSGEQ, "jsgeq") \ + _(SHL, "shl") \ + _(SHR, "shr") \ + _(SSHR, "sshr") \ + _(SHL_C_PRI, "shl.c.pri") \ + _(SHL_C_ALT, "shl.c.alt") \ + _(SHR_C_PRI, "shr.c.pri") \ + _(SHR_C_ALT, "shr.c.alt") \ + _(SMUL, "smul") \ + _(SDIV, "sdiv") \ + _(SDIV_ALT, "sdiv.alt") \ + _(UNGEN_UMUL, "umul") \ + _(UNGEN_UDIV, "udiv") \ + _(UNGEN_UDIV_ALT, "udiv.alt") \ + _(ADD, "add") \ + _(SUB, "sub") \ + _(SUB_ALT, "sub.alt") \ + _(AND, "and") \ + _(OR, "or") \ + _(XOR, "xor") \ + _(NOT, "not") \ + _(NEG, "neg") \ + _(INVERT, "invert") \ + _(ADD_C, "add.c") \ + _(SMUL_C, "smul.c") \ + _(ZERO_PRI, "zero.pri") \ + _(ZERO_ALT, "zero.alt") \ + _(ZERO, "zero") \ + _(ZERO_S, "zero.s") \ + _(UNGEN_SIGN_PRI, "sign.pri") \ + _(UNGEN_SIGN_ALT, "sign.alt") \ + _(EQ, "eq") \ + _(NEQ, "neq") \ + _(UNGEN_LESS, "less") \ + _(UNGEN_LEQ, "leq") \ + _(UNGEN_GRTR, "grtr") \ + _(UNGEN_GEQ, "geq") \ + _(SLESS, "sless") \ + _(SLEQ, "sleq") \ + _(SGRTR, "sgrtr") \ + _(SGEQ, "sgeq") \ + _(EQ_C_PRI, "eq.c.pri") \ + _(EQ_C_ALT, "eq.c.alt") \ + _(INC_PRI, "inc.pri") \ + _(INC_ALT, "inc.alt") \ + _(INC, "inc") \ + _(INC_S, "inc.s") \ + _(INC_I, "inc.i") \ + _(DEC_PRI, "dec.pri") \ + _(DEC_ALT, "dec.alt") \ + _(DEC, "dec") \ + _(DEC_S, "dec.s") \ + _(DEC_I, "dec.i") \ + _(MOVS, "movs") \ + _(UNGEN_CMPS, "cmps") \ + _(FILL, "fill") \ + _(HALT, "halt") \ + _(BOUNDS, "bounds") \ + _(UNGEN_SYSREQ_PRI,"sysreq.pri") \ + _(SYSREQ_C, "sysreq.c") \ + _(UNGEN_FILE, "file") \ + _(UNGEN_LINE, "line") \ + _(UNGEN_SYMBOL, "symbol") \ + _(UNGEN_SRANGE, "srange") \ + _(UNGEN_JUMP_PRI, "jump.pri") \ + _(SWITCH, "switch") \ + _(CASETBL, "casetbl") \ + _(SWAP_PRI, "swap.pri") \ + _(SWAP_ALT, "swap.alt") \ + _(PUSH_ADR, "push.adr") \ + _(NOP, "nop") \ + _(SYSREQ_N, "sysreq.n") \ + _(UNGEN_SYMTAG, "symtag") \ + _(BREAK, "break") \ + _(PUSH2_C, "push2.c") \ + _(PUSH2, "push2") \ + _(PUSH2_S, "push2.s") \ + _(PUSH2_ADR, "push2.adr") \ + _(PUSH3_C, "push3.c") \ + _(PUSH3, "push3") \ + _(PUSH3_S, "push3.s") \ + _(PUSH3_ADR, "push3.adr") \ + _(PUSH4_C, "push4.c") \ + _(PUSH4, "push4") \ + _(PUSH4_S, "push4.s") \ + _(PUSH4_ADR, "push4.adr") \ + _(PUSH5_C, "push5.c") \ + _(PUSH5, "push5") \ + _(PUSH5_S, "push5.s") \ + _(PUSH5_ADR, "push5.adr") \ + _(LOAD_BOTH, "load.both") \ + _(LOAD_S_BOTH, "load.s.both") \ + _(CONST, "const") \ + _(CONST_S, "const.s") \ + _(UNGEN_SYSREQ_D, "sysreq.d") \ + _(UNGEB_SYSREQ_ND,"sysreq.nd") \ + _(TRACKER_PUSH_C, "trk.push.c") \ + _(TRACKER_POP_SETHEAP,"trk.pop") \ + _(GENARRAY, "genarray") \ + _(GENARRAY_Z, "genarray.z") \ + _(STRADJUST_PRI, "stradjust.pri") \ + _(UNGEN_STKADJUST,"stackadjust") \ + _(ENDPROC, "endproc") \ + _(FABS, "fabs") \ + _(FLOAT, "float") \ + _(FLOATADD, "float.add") \ + _(FLOATSUB, "float.sub") \ + _(FLOATMUL, "float.mul") \ + _(FLOATDIV, "float.div") \ + _(RND_TO_NEAREST, "round") \ + _(RND_TO_FLOOR, "floor") \ + _(RND_TO_CEIL, "ceil") \ + _(RND_TO_ZERO, "rndtozero") \ + _(FLOATCMP, "float.cmp") \ + _(FLOAT_GT, "float.gt") \ + _(FLOAT_GE, "float.ge") \ + _(FLOAT_LT, "float.lt") \ + _(FLOAT_LE, "float.le") \ + _(FLOAT_NE, "float.ne") \ + _(FLOAT_EQ, "float.eq") \ + _(FLOAT_NOT, "float.not") + +enum OPCODE { +#define _(op, text) OP_##op, + OPCODE_LIST(_) +#undef _ + OPCODES_TOTAL +}; + +} // namespace sp + +#endif // _INCLUDE_SPFILE_HEADERS_v1_opcodes_H diff --git a/sourcepawn/include/smx/smx-v1.h b/sourcepawn/include/smx/smx-v1.h new file mode 100644 index 00000000..3ae95029 --- /dev/null +++ b/sourcepawn/include/smx/smx-v1.h @@ -0,0 +1,205 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved. +// ============================================================================= +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License, version 3.0, as published by the +// Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// +// As a special exception, AlliedModders LLC gives you permission to link the +// code of this program (as well as its derivative works) to "Half-Life 2," the +// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +// by the Valve Corporation. You must obey the GNU General Public License in +// all respects for all other code used. Additionally, AlliedModders LLC grants +// this exception to all derivative works. AlliedModders LLC defines further +// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +// or . + +#ifndef _INCLUDE_SPFILE_HEADERS_v1_H +#define _INCLUDE_SPFILE_HEADERS_v1_H + +#include +#include +#include + +namespace sp { + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// (Obsolete) debug-information is present. +static const uint16_t CODEFLAG_DEBUG = 0x1; + +// The ".data" section. +typedef struct sp_file_data_s +{ + uint32_t datasize; /**< Size of data section in memory */ + uint32_t memsize; /**< Total mem required (includes data) */ + uint32_t data; /**< File offset to data (helper) */ +} sp_file_data_t; + +// The ".publics" section. +typedef struct sp_file_publics_s +{ + uint32_t address; /**< Address relative to code section */ + uint32_t name; /**< Index into nametable */ +} sp_file_publics_t; + +// The ".natives" section. +typedef struct sp_file_natives_s +{ + uint32_t name; /**< Index into nametable */ +} sp_file_natives_t; + +// The ".pubvars" section. +typedef struct sp_file_pubvars_s +{ + uint32_t address; /**< Address relative to the DAT section */ + uint32_t name; /**< Index into nametable */ +} sp_file_pubvars_t; + +// The ".tags" section. +typedef struct sp_file_tag_s +{ + uint32_t tag_id; /**< Tag ID from compiler */ + uint32_t name; /**< Index into nametable */ +} sp_file_tag_t; + +// The ".dbg.info" section. +typedef struct sp_fdbg_info_s +{ + uint32_t num_files; /**< number of files */ + uint32_t num_lines; /**< number of lines */ + uint32_t num_syms; /**< number of symbols */ + uint32_t num_arrays; /**< number of symbols which are arrays */ +} sp_fdbg_info_t; + +// The ".dbg.files" section. +typedef struct sp_fdbg_file_s +{ + uint32_t addr; /**< Address into code */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_file_t; + +// The ".dbg.lines" section. +typedef struct sp_fdbg_line_s +{ + uint32_t addr; /**< Address into code */ + uint32_t line; /**< Line number */ +} sp_fdbg_line_t; + +static const uint8_t IDENT_VARIABLE = 1; // Scalar local variable. +static const uint8_t IDENT_REFERENCE = 2; // Reference to a scalar argument. +static const uint8_t IDENT_ARRAY = 3; // Array with known dimensions. +static const uint8_t IDENT_REFARRAY = 4; // Array with unknown dimensions. +static const uint8_t IDENT_FUNCTION = 9; // Symbolic function. +static const uint8_t IDENT_VARARGS = 11; // Variadic argument (...). + +// The ".dbg.symbols" table. +typedef struct sp_fdbg_symbol_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_symbol_t; + +// Occurs after an fdbg_symbol entry, for each dimension. +typedef struct sp_fdbg_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_fdbg_arraydim_t; + +// Typedef for the ".names" section. +typedef char * sp_file_nametab_t; + +// Header for the ".dbg.natives" section. It is followed by a number of +// sp_fdbg_native_t entries. +typedef struct sp_fdbg_ntvtab_s +{ + uint32_t num_entries; /**< Number of entries. */ +} sp_fdbg_ntvtab_t; + +// An entry in the .dbg.natives section. Each is followed by an +// sp_fdbg_ntvarg_t for each argument. +typedef struct sp_fdbg_native_s +{ + uint32_t index; /**< Native index in the plugin. */ + uint32_t name; /**< Offset into debug nametable. */ + int16_t tagid; /**< Return tag. */ + uint16_t nargs; /**< Number of formal arguments. */ +} sp_fdbg_native_t; + +static const uint8_t IDENT_NATIVE_VARARGS = 1; + +// Each entry is followed by an sp_fdbg_arraydim_t for each dimcount. +typedef struct sp_fdbg_ntvarg_s +{ + uint8_t ident; /**< Variable type */ + int16_t tagid; /**< Tag id */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_ntvarg_t; + +#if defined __GNUC__ +# pragma pack() /* reset default packing */ +#else +# pragma pack(pop) /* reset previous packing */ +#endif + +// The packing for files changed by accident for a small window of time, and +// some files may have unparsable debug information using sp_fdbg_arraydim_t or +// sp_fdbg_symbol_t. +// +// If the file version is >= 0x0102, all structures will be packed. If the +// file version is < 0x0101, and the ".dbg.natives" table is present, +// all structures will be packed. +// +// If the version is 0x0101 and ".dbg.natives" is not present, then you must +// use the unpacked versions of those structures below. There is an extremely +// small chance, if the plugin used no natives, that the packing is +// indeterminate. This case is unlikely to be interesting, but if such a file +// exists, the only solution is to re-parse if the data looks corrupt. + +typedef struct sp_u_fdbg_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_u_fdbg_arraydim_t; + +typedef struct sp_u_fdbg_symbol_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_u_fdbg_symbol_t; + +} // namespace sp + +#endif //_INCLUDE_SPFILE_HEADERS_v1_H + diff --git a/sourcepawn/include/smx/smx-v2.h b/sourcepawn/include/smx/smx-v2.h new file mode 100644 index 00000000..9b8dec22 --- /dev/null +++ b/sourcepawn/include/smx/smx-v2.h @@ -0,0 +1,218 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 AlliedModders LLC. All rights RESERVED. +// ============================================================================= +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License, version 3.0, as published by the +// Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// +// As a special exception, AlliedModders LLC gives you permission to link the +// code of this program (as well as its derivative works) to "Half-Life 2," the +// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +// by the Valve Corporation. You must obey the GNU General Public License in +// all respects for all other code used. Additionally, AlliedModders LLC grants +// this exception to all derivative works. AlliedModders LLC defines further +// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +// or . + +#ifndef _INCLUDE_SPFILE_HEADERS_v2_H +#define _INCLUDE_SPFILE_HEADERS_v2_H + +#include + +namespace sp { + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// Tables present in smx v2: +// .names Blob of null-terminated strings. +// .methods Table of smx_method_t entries. +// .pcode Blob of smx_pcode_header_t entries. +// .globals Table of smx_global_var_t entries. +// .types Blob of type information. + +// TypeSpec is a variable-length encoding referenced anywhere that "typespec" +// is specified. +// +// Whenever a TypeSpec is referenced from outside the .types table, specifically +// as a "typeid", it has an encoding to save space: If the id is < 0x20, then +// the id is a single-byte TypeSpec. Otherwise, the |id - 0x20| is an offset +// into the .types section. +enum class TypeSpec : uint8_t +{ + // The void type is special in that it is not a storable type. + void_t = 0x0, + + // Standard C++ datatypes. + boolean = 0x1, + RESERVED_int8 = 0x2, + RESERVED_uint8 = 0x3, + RESERVED_int16 = 0x4, + RESERVED_uint16 = 0x5, + int32 = 0x6, + RESERVED_uint32 = 0x7, + RESERVED_int64 = 0x8, + RESERVED_uint64 = 0x9, + + // platform-width int and uint. + RESERVED_intptr = 0xA, + RESERVED_uintptr = 0xB, + + float32 = 0xC, + RESERVED_float64 = 0xD, + + // char8 is semantically an alias for int8. + char8 = 0xE, + + RESERVED_char32 = 0xF, // Full unicode point. + + RESERVED_string = 0x16, // String reference. + RESERVED_object = 0x17, // Opaque object reference. + + // Followed by an int32 index into the .classes table. + RESERVED_classdef = 0x40, + + // Followed by an int32 index into the .structs table. + RESERVED_structdef = 0x41, + + // Followed by: + // [int8 formalCount] ; Number of formal parameters, counting varargs. + // [typespec *formals] ; Sequence of formal parameter specifications. + // + // When the type spec is for a method definition (for example, the .method + // table), then each type in |formals| must begin with "named" (0x7e) or, + // if it is the last formal, may be "variadic" (0x7a). + method = 0x50, + + // Fixed arrays have their size as part of their type, are copied by-value, + // and passed by-reference. + // + // Followed by: + // typespec type ; Type specification of innermost elements. + // uint8 rank ; Number of dimensions + // int32* dims ; One dimension for each rank. + fixedarray = 0x60, + + // Arrays are true arrays. They are copied by-reference and passed by- + // reference. + // + // Followed by: + // typesec type ; Type specification of innermost elements. + // uint8 rank ; Number of dimensions. + RESERVED_array = 0x61, + + // Only legal as the initial byte or byte following "named" (0x7e) in a + // parameter for a method signature. + // + // Followed by a typespec. Only typespecs < 0x60 ar elegal. + byref = 0x70, + + // Only legal as the initial byte or byte following "named" (0x7e) in a + // parameter for a method signature. + // + // Followed by a typespec. + variadic = 0x7A, + + // Only legal as the initial byte in a parameter or local variable signature. + // + // Followed by: + // uint32 name ; Index into the .names section. + // typespec type ; Type. + named = 0x7E, + + // For readability, this may be emitted at the end of typespec lists. It must + // not be emitted at the end of nested typespecs. + terminator = 0x7F +}; + +// Flags for method definitions. +enum class MethodFlags : uint32_t +{ + STATIC = 0x1, + VARIADIC = 0x2, + PUBLIC = 0x4, + NATIVE = 0x8, + OPTIONAL = 0x10 +}; + +// Specifies an entry in the .methods table. +struct smx_method_t +{ + // Offset into the .names section. + uint32_t name; + + MethodFlags flags; + + // Offset into .types, which must point at a TypeSpec::method. + uint32_t typespec; + + // Offset into .pcode. If flags contains NATIVE, this must be 0. + uint32_t address; +}; + +enum class GlobalVarFlags : uint32_t +{ + PUBLIC = 0x04, + CONST = 0x08 +}; + +// Specifies an entry in the .globals table. +struct smx_global_var_t +{ + // Offset into the .names section. + uint32_t name; + + GlobalVarFlags flags; + + // TypeId of the global. + uint32_t type_id; +}; + +// Specifies the layout we expect at a valid pcode starting position. +struct smx_pcode_header_t +{ + // Must be 0. + uint32_t reserved; + + // Number of local variables. + uint16_t nlocals; + + // Maximum depth of the operand stack. + uint16_t max_depth; + + // Pointer to .types section where local information begins. + uint32_t local_specs; + + // Number of bytes of pcode in the method. + uint32_t length; +}; + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// DO NOT DEFINE NEW STRUCTURES BELOW. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +#if defined __GNUC__ +# pragma pack() +#else +# pragma pack(pop) +#endif + +} // namespace sp + +#endif // _INCLUDE_SPFILE_HEADERS_v2_H diff --git a/sourcepawn/jit/AMBuilder b/sourcepawn/jit/AMBuilder index 77c3cdfd..a09b49c0 100644 --- a/sourcepawn/jit/AMBuilder +++ b/sourcepawn/jit/AMBuilder @@ -12,6 +12,9 @@ binary.compiler.includes += [ os.path.join(builder.sourcePath, 'public', 'jit'), os.path.join(builder.sourcePath, 'public', 'jit', 'x86'), os.path.join(builder.sourcePath, 'knight', 'shared'), + + # The include path for SP v2 stuff. + os.path.join(builder.sourcePath, 'sourcepawn', 'include'), ] if builder.target_platform == 'linux': diff --git a/sourcepawn/jit/BaseRuntime.cpp b/sourcepawn/jit/BaseRuntime.cpp index c7d5ec02..fcf7fbf7 100644 --- a/sourcepawn/jit/BaseRuntime.cpp +++ b/sourcepawn/jit/BaseRuntime.cpp @@ -11,6 +11,7 @@ #include "md5/md5.h" +using namespace sp; using namespace SourcePawn; static inline bool @@ -171,9 +172,9 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base) if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) { sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs); - if (cod->codeversion < SP_CODEVERS_JIT1) + if (cod->codeversion < SmxConsts::CODE_VERSION_JIT1) return SP_ERROR_CODE_TOO_OLD; - if (cod->codeversion > SP_CODEVERS_JIT2) + if (cod->codeversion > SmxConsts::CODE_VERSION_JIT2) return SP_ERROR_CODE_TOO_NEW; m_plugin.pcode = base + secptr->dataoffs + cod->code; @@ -266,7 +267,7 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base) if (m_plugin.pcode == NULL || m_plugin.data == NULL) return SP_ERROR_FILE_FORMAT; - if ((m_plugin.flags & SP_FLAG_DEBUG) && ( + if ((m_plugin.flags & sp::CODEFLAG_DEBUG) && ( !(m_plugin.debug.files) || !(m_plugin.debug.lines) || !(m_plugin.debug.symbols) || diff --git a/sourcepawn/jit/engine2.cpp b/sourcepawn/jit/engine2.cpp index 9ce845cb..e5a8b8c2 100644 --- a/sourcepawn/jit/engine2.cpp +++ b/sourcepawn/jit/engine2.cpp @@ -37,7 +37,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file /* Rewind for safety */ fread(&hdr, sizeof(sp_file_hdr_t), 1, fp); - if (hdr.magic != SPFILE_MAGIC) + if (hdr.magic != SmxConsts::FILE_MAGIC) { error = SP_ERROR_FILE_FORMAT; goto return_error; @@ -45,7 +45,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file switch (hdr.compression) { - case SPFILE_COMPRESSION_GZ: + case SmxConsts::FILE_COMPRESSION_GZ: { uint32_t uncompsize = hdr.imagesize - hdr.dataoffs; uint32_t compsize = hdr.disksize - hdr.dataoffs; @@ -77,7 +77,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file free(uncompdata); break; } - case SPFILE_COMPRESSION_NONE: + case SmxConsts::FILE_COMPRESSION_NONE: { base = (uint8_t *)malloc(hdr.imagesize); rewind(fp); diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 257e9414..fcaafe61 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -22,6 +22,7 @@ #define STACK_MARGIN 64 +using namespace sp; using namespace SourcePawn; static inline bool diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 4642e5dd..4e06b61e 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -3,7 +3,9 @@ #define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_ #include +#include +using namespace sp; using namespace SourcePawn; #define SP_MAX_RETURN_STACK 1024 diff --git a/sourcepawn/jit/opcodes.cpp b/sourcepawn/jit/opcodes.cpp index ef50eacf..c2cf3eb9 100644 --- a/sourcepawn/jit/opcodes.cpp +++ b/sourcepawn/jit/opcodes.cpp @@ -31,6 +31,7 @@ #include "opcodes.h" #include "jit_shared.h" +using namespace sp; using namespace SourcePawn; const char *OpcodeNames[] = { diff --git a/sourcepawn/jit/opcodes.h b/sourcepawn/jit/opcodes.h index 599b0353..963535ec 100644 --- a/sourcepawn/jit/opcodes.h +++ b/sourcepawn/jit/opcodes.h @@ -32,235 +32,8 @@ #ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_ #define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_ -#include - -// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few, -// if they could, make little sense in the context of a JIT and could not -// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively, -// the code emitter and peephole optimizer) are not necessarily ever generated. -// For example, lref.pri and lref.alt would be used if a reference could be -// stored in the global scope; but they can't, so they are unreachable. -// -// Most opcodes have been manually verified. A few have not, as they are only -// produced by the peephole optimizer, or not produced at all, or eliminated -// during optimization. We generate them anyway, just in case, but they have -// not been tested. -// lref.s.alt (phopt only) -// stor.alt (never) -// stor.s.alt (never) -// sref.s.alt (never) -// lidx.b (phopt only, probably impossible) -// idxaddr.b (phopt only, looks difficult) -// move.pri (eliminated in phopt) -// shl.c.pri (eliminated in phopt) -// shl.c.alt (eliminated in phopt) -// shr.c.pri (eliminated in phopt) -// shr.c.alt (eliminated in phopt) -// eq.c.alt (never) -// inc.alt (never) -// dec.alt (never) -// sdiv (never) -// nop (never in function bodies) -// -// Additionally, some opcodes which were supported in the earlier JIT are no -// longer supported because of the above: -// lref.pri/alt -// sref.pri/alt -// sign.pri/alt - -#define OPCODE_LIST(_) \ - _(NONE, "none") \ - _(LOAD_PRI, "load.pri") \ - _(LOAD_ALT, "load.alt") \ - _(LOAD_S_PRI, "load.s.pri") \ - _(LOAD_S_ALT, "load.s.alt") \ - _(UNGEN_LREF_PRI, "lref.pri") \ - _(UNGEN_LREF_ALT, "lref.alt") \ - _(LREF_S_PRI, "lref.s.pri") \ - _(LREF_S_ALT, "lref.s.alt") \ - _(LOAD_I, "load.i") \ - _(LODB_I, "lodb.i") \ - _(CONST_PRI, "const.pri") \ - _(CONST_ALT, "const.alt") \ - _(ADDR_PRI, "addr.pri") \ - _(ADDR_ALT, "addr.alt") \ - _(STOR_PRI, "stor.pri") \ - _(STOR_ALT, "stor.alt") \ - _(STOR_S_PRI, "stor.s.pri") \ - _(STOR_S_ALT, "stor.s.alt") \ - _(UNGEN_SREF_PRI, "sref.pri") \ - _(UNGEN_SREF_ALT, "sref.alt") \ - _(SREF_S_PRI, "sref.s.pri") \ - _(SREF_S_ALT, "sref.s.alt") \ - _(STOR_I, "stor.i") \ - _(STRB_I, "strb.i") \ - _(LIDX, "lidx") \ - _(LIDX_B, "lidx.b") \ - _(IDXADDR, "idxaddr") \ - _(IDXADDR_B, "idxaddr.b") \ - _(UNGEN_ALIGN_PRI,"align.pri") \ - _(UNGEN_ALIGN_ALT,"align.alt") \ - _(UNGEN_LCTRL, "lctrl") \ - _(UNGEN_SCTRL, "sctrl") \ - _(MOVE_PRI, "move.pri") \ - _(MOVE_ALT, "move.alt") \ - _(XCHG, "xchg") \ - _(PUSH_PRI, "push.pri") \ - _(PUSH_ALT, "push.alt") \ - _(UNGEN_PUSH_R, "push.r") \ - _(PUSH_C, "push.c") \ - _(PUSH, "push") \ - _(PUSH_S, "push.s") \ - _(POP_PRI, "pop.pri") \ - _(POP_ALT, "pop.alt") \ - _(STACK, "stack") \ - _(HEAP, "heap") \ - _(PROC, "proc") \ - _(UNGEN_RET, "ret") \ - _(RETN, "retn") \ - _(CALL, "call") \ - _(UNGEN_CALL_PRI, "call.pri") \ - _(JUMP, "jump") \ - _(UNGEN_JREL, "jrel") \ - _(JZER, "jzer") \ - _(JNZ, "jnz") \ - _(JEQ, "jeq") \ - _(JNEQ, "jneq") \ - _(UNGEN_JLESS, "jsless") \ - _(UNGEN_JLEQ, "jleq") \ - _(UNGEN_JGRTR, "jgrtr") \ - _(UNGEN_JGEQ, "jgeq") \ - _(JSLESS, "jsless") \ - _(JSLEQ, "jsleq") \ - _(JSGRTR, "jsgrtr") \ - _(JSGEQ, "jsgeq") \ - _(SHL, "shl") \ - _(SHR, "shr") \ - _(SSHR, "sshr") \ - _(SHL_C_PRI, "shl.c.pri") \ - _(SHL_C_ALT, "shl.c.alt") \ - _(SHR_C_PRI, "shr.c.pri") \ - _(SHR_C_ALT, "shr.c.alt") \ - _(SMUL, "smul") \ - _(SDIV, "sdiv") \ - _(SDIV_ALT, "sdiv.alt") \ - _(UNGEN_UMUL, "umul") \ - _(UNGEN_UDIV, "udiv") \ - _(UNGEN_UDIV_ALT, "udiv.alt") \ - _(ADD, "add") \ - _(SUB, "sub") \ - _(SUB_ALT, "sub.alt") \ - _(AND, "and") \ - _(OR, "or") \ - _(XOR, "xor") \ - _(NOT, "not") \ - _(NEG, "neg") \ - _(INVERT, "invert") \ - _(ADD_C, "add.c") \ - _(SMUL_C, "smul.c") \ - _(ZERO_PRI, "zero.pri") \ - _(ZERO_ALT, "zero.alt") \ - _(ZERO, "zero") \ - _(ZERO_S, "zero.s") \ - _(UNGEN_SIGN_PRI, "sign.pri") \ - _(UNGEN_SIGN_ALT, "sign.alt") \ - _(EQ, "eq") \ - _(NEQ, "neq") \ - _(UNGEN_LESS, "less") \ - _(UNGEN_LEQ, "leq") \ - _(UNGEN_GRTR, "grtr") \ - _(UNGEN_GEQ, "geq") \ - _(SLESS, "sless") \ - _(SLEQ, "sleq") \ - _(SGRTR, "sgrtr") \ - _(SGEQ, "sgeq") \ - _(EQ_C_PRI, "eq.c.pri") \ - _(EQ_C_ALT, "eq.c.alt") \ - _(INC_PRI, "inc.pri") \ - _(INC_ALT, "inc.alt") \ - _(INC, "inc") \ - _(INC_S, "inc.s") \ - _(INC_I, "inc.i") \ - _(DEC_PRI, "dec.pri") \ - _(DEC_ALT, "dec.alt") \ - _(DEC, "dec") \ - _(DEC_S, "dec.s") \ - _(DEC_I, "dec.i") \ - _(MOVS, "movs") \ - _(UNGEN_CMPS, "cmps") \ - _(FILL, "fill") \ - _(HALT, "halt") \ - _(BOUNDS, "bounds") \ - _(UNGEN_SYSREQ_PRI,"sysreq.pri") \ - _(SYSREQ_C, "sysreq.c") \ - _(UNGEN_FILE, "file") \ - _(UNGEN_LINE, "line") \ - _(UNGEN_SYMBOL, "symbol") \ - _(UNGEN_SRANGE, "srange") \ - _(UNGEN_JUMP_PRI, "jump.pri") \ - _(SWITCH, "switch") \ - _(CASETBL, "casetbl") \ - _(SWAP_PRI, "swap.pri") \ - _(SWAP_ALT, "swap.alt") \ - _(PUSH_ADR, "push.adr") \ - _(NOP, "nop") \ - _(SYSREQ_N, "sysreq.n") \ - _(UNGEN_SYMTAG, "symtag") \ - _(BREAK, "break") \ - _(PUSH2_C, "push2.c") \ - _(PUSH2, "push2") \ - _(PUSH2_S, "push2.s") \ - _(PUSH2_ADR, "push2.adr") \ - _(PUSH3_C, "push3.c") \ - _(PUSH3, "push3") \ - _(PUSH3_S, "push3.s") \ - _(PUSH3_ADR, "push3.adr") \ - _(PUSH4_C, "push4.c") \ - _(PUSH4, "push4") \ - _(PUSH4_S, "push4.s") \ - _(PUSH4_ADR, "push4.adr") \ - _(PUSH5_C, "push5.c") \ - _(PUSH5, "push5") \ - _(PUSH5_S, "push5.s") \ - _(PUSH5_ADR, "push5.adr") \ - _(LOAD_BOTH, "load.both") \ - _(LOAD_S_BOTH, "load.s.both") \ - _(CONST, "const") \ - _(CONST_S, "const.s") \ - _(UNGEN_SYSREQ_D, "sysreq.d") \ - _(UNGEB_SYSREQ_ND,"sysreq.nd") \ - _(TRACKER_PUSH_C, "trk.push.c") \ - _(TRACKER_POP_SETHEAP,"trk.pop") \ - _(GENARRAY, "genarray") \ - _(GENARRAY_Z, "genarray.z") \ - _(STRADJUST_PRI, "stradjust.pri") \ - _(UNGEN_STKADJUST,"stackadjust") \ - _(ENDPROC, "endproc") \ - _(FABS, "fabs") \ - _(FLOAT, "float") \ - _(FLOATADD, "float.add") \ - _(FLOATSUB, "float.sub") \ - _(FLOATMUL, "float.mul") \ - _(FLOATDIV, "float.div") \ - _(RND_TO_NEAREST, "round") \ - _(RND_TO_FLOOR, "floor") \ - _(RND_TO_CEIL, "ceil") \ - _(RND_TO_ZERO, "rndtozero") \ - _(FLOATCMP, "float.cmp") \ - _(FLOAT_GT, "float.gt") \ - _(FLOAT_GE, "float.ge") \ - _(FLOAT_LT, "float.lt") \ - _(FLOAT_LE, "float.le") \ - _(FLOAT_NE, "float.ne") \ - _(FLOAT_EQ, "float.eq") \ - _(FLOAT_NOT, "float.not") - -enum OPCODE { -#define _(op, text) OP_##op, - OPCODE_LIST(_) -#undef _ - OPCODES_TOTAL -}; +#include +#include "jit_shared.h" namespace SourcePawn { void SpewOpcode(const sp_plugin_t *plugin, cell_t *start, cell_t *cip); diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp index b2e841ad..dbd4c1dd 100644 --- a/sourcepawn/jit/sp_vm_basecontext.cpp +++ b/sourcepawn/jit/sp_vm_basecontext.cpp @@ -738,7 +738,7 @@ int DebugInfo::LookupFunction(ucell_t addr, const char **name) { sym = (sp_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= addr && sym->codeend > addr) { @@ -769,7 +769,7 @@ int DebugInfo::LookupFunction(ucell_t addr, const char **name) { sym = (sp_u_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= addr && sym->codeend > addr) { diff --git a/sourcepawn/jit/sp_vm_engine.cpp b/sourcepawn/jit/sp_vm_engine.cpp index 05e5be15..4c314b20 100644 --- a/sourcepawn/jit/sp_vm_engine.cpp +++ b/sourcepawn/jit/sp_vm_engine.cpp @@ -34,7 +34,6 @@ #include #include "sp_vm_types.h" #include -#include "sp_file_headers.h" #include "sp_vm_engine.h" #include "zlib/zlib.h" #include "sp_vm_basecontext.h" diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index a0930ba9..26e4098f 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -40,6 +40,7 @@ #include "watchdog_timer.h" #include "interpreter.h" +using namespace sp; using namespace Knight; #if defined USE_UNGEN_OPCODES @@ -230,7 +231,7 @@ GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) for (iter = 0; iter < max; iter++) { sym = (sp_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs) + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= offs && sym->codeend > offs) return plugin->debug.stringbase + sym->name; if (sym->dimcount > 0) { @@ -252,7 +253,7 @@ GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) for (iter = 0; iter < max; iter++) { sym = (sp_u_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs) + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= offs && sym->codeend > offs) return plugin->debug.stringbase + sym->name; if (sym->dimcount > 0) {