Merge remote-tracking branch 'upstream/master' into sdkhooks-blocked
This commit is contained in:
commit
88c6d3d9a7
@ -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']
|
||||
|
@ -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.
|
@ -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',
|
||||
@ -53,17 +52,14 @@ for sdk_name in SM.sdks:
|
||||
compiler = binary.compiler
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
# Protobuf 2.3 headers have some signed/unsigned compares. I believe that it's fixed in later versions, but Valve.
|
||||
if compiler.cxx.behavior == 'gcc':
|
||||
compiler.cflags += ['-Wno-sign-compare']
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.3.0', 'src'),
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
elif sdk.name == 'dota':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.4.1', 'src'),
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
||||
@ -110,6 +106,7 @@ for sdk_name in SM.sdks:
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'network_connection.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
|
||||
|
@ -76,9 +76,12 @@ void CDataPack::ResetSize()
|
||||
|
||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + size);
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + size);
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
|
||||
*(char *)m_curptr = Raw;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = size;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
@ -88,14 +91,17 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
}
|
||||
|
||||
m_curptr += size;
|
||||
m_size += sizeof(size_t) + size;
|
||||
m_size += sizeof(char) + sizeof(size_t) + size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void CDataPack::PackCell(cell_t cell)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + sizeof(cell_t));
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
*(char *)m_curptr = Cell;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
@ -103,12 +109,15 @@ void CDataPack::PackCell(cell_t cell)
|
||||
*(cell_t *)m_curptr = cell;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
m_size += sizeof(size_t) + sizeof(cell_t);
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
void CDataPack::PackFloat(float val)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + sizeof(float));
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
|
||||
|
||||
*(char *)m_curptr = Float;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(float);
|
||||
m_curptr += sizeof(size_t);
|
||||
@ -116,15 +125,18 @@ void CDataPack::PackFloat(float val)
|
||||
*(float *)m_curptr = val;
|
||||
m_curptr += sizeof(float);
|
||||
|
||||
m_size += sizeof(size_t) + sizeof(float);
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
|
||||
}
|
||||
|
||||
void CDataPack::PackString(const char *string)
|
||||
{
|
||||
size_t len = strlen(string);
|
||||
size_t maxsize = sizeof(size_t) + len + 1;
|
||||
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
|
||||
CheckSize(maxsize);
|
||||
|
||||
*(char *)m_curptr = String;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
// Pack the string length first for buffer overrun checking.
|
||||
*(size_t *)m_curptr = len;
|
||||
m_curptr += sizeof(size_t);
|
||||
@ -160,10 +172,16 @@ bool CDataPack::SetPosition(size_t pos) const
|
||||
|
||||
cell_t CDataPack::ReadCell() const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Cell)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
@ -178,10 +196,16 @@ cell_t CDataPack::ReadCell() const
|
||||
|
||||
float CDataPack::ReadFloat() const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t) + sizeof(float)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Float)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
||||
{
|
||||
return 0;
|
||||
@ -201,10 +225,15 @@ bool CDataPack::IsReadable(size_t bytes) const
|
||||
|
||||
const char *CDataPack::ReadString(size_t *len) const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != String)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
size_t real_len = *(size_t *)m_curptr;
|
||||
|
||||
@ -237,6 +266,11 @@ void *CDataPack::ReadMemory(size_t *size) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Raw)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
size_t bytecount = *(size_t *)m_curptr;
|
||||
m_curptr += sizeof(size_t);
|
||||
@ -257,3 +291,43 @@ void *CDataPack::ReadMemory(size_t *size) const
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void CDataPack::PackFunction(cell_t function)
|
||||
{
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
*(char *)m_curptr = Function;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(cell_t *)m_curptr = function;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
cell_t CDataPack::ReadFunction() const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Function)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
||||
m_curptr += sizeof(cell_t);
|
||||
return val;
|
||||
}
|
@ -51,12 +51,14 @@ public: //IDataReader
|
||||
const char *ReadString(size_t *len) const;
|
||||
void *GetMemory() const;
|
||||
void *ReadMemory(size_t *size) const;
|
||||
cell_t ReadFunction() const;
|
||||
public: //IDataPack
|
||||
void ResetSize();
|
||||
void PackCell(cell_t cell);
|
||||
void PackFloat(float val);
|
||||
void PackString(const char *string);
|
||||
size_t CreateMemory(size_t size, void **addr);
|
||||
void PackFunction(cell_t function);
|
||||
public:
|
||||
void Initialize();
|
||||
private:
|
||||
@ -66,6 +68,14 @@ private:
|
||||
mutable char *m_curptr;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
|
||||
enum DataPackType {
|
||||
Raw,
|
||||
Cell,
|
||||
Float,
|
||||
String,
|
||||
Function
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
|
@ -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<CommandGroup> cmdgroup = i->value;
|
||||
|
||||
|
@ -648,8 +648,11 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
|
||||
return InvalidQueryCvarCookie;
|
||||
}
|
||||
|
||||
ConVarQuery query = {cookie, pCallback, (cell_t)hndl, IndexOfEdict(pPlayer)};
|
||||
m_ConVarQueries.push_back(query);
|
||||
if (pCallback != NULL)
|
||||
{
|
||||
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||
m_ConVarQueries.push_back(query);
|
||||
}
|
||||
#endif
|
||||
|
||||
return cookie;
|
||||
@ -753,6 +756,13 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIn
|
||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
#endif // SE_DOTA
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
IPluginFunction *pCallback = NULL;
|
||||
cell_t value = 0;
|
||||
List<ConVarQuery>::iterator iter;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||
int EventManager::GetEventDebugID()
|
||||
{
|
||||
return EVENT_DEBUG_ID_INIT;
|
||||
|
@ -110,7 +110,7 @@ public: // IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public: // IGameEventListener2
|
||||
void FireGameEvent(IGameEvent *pEvent);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||
int GetEventDebugID();
|
||||
#endif
|
||||
public:
|
||||
|
@ -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<ILibrary> 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<ILibrary> 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
520
core/Logger.cpp
520
core/Logger.cpp
@ -39,61 +39,12 @@
|
||||
#include "logic_bridge.h"
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
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)
|
||||
|
@ -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_
|
||||
|
@ -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");
|
||||
|
@ -502,6 +502,9 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
/* Get the client's language */
|
||||
if (m_QueryLang)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
#else
|
||||
const char *name;
|
||||
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
||||
{
|
||||
@ -510,6 +513,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
} else {
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
List<IClientListener *>::iterator iter;
|
||||
@ -727,6 +731,13 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
}
|
||||
pPlayer->Authorize_Post();
|
||||
}
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
else
|
||||
{
|
||||
// Not a bot
|
||||
pPlayer->m_LanguageCookie = g_ConVarManager.QueryClientConVar(pEntity, "cl_language", NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (playerinfo)
|
||||
{
|
||||
@ -1227,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><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
logger->LogMessage("\"%s<%d><STEAM_1:%d:%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.");
|
||||
@ -1862,6 +1873,24 @@ void CmdMaxplayersCallback()
|
||||
g_Players.MaxPlayersChanged();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
{
|
||||
for (int i = 1; i <= m_maxClients; i++)
|
||||
{
|
||||
if (m_Players[i].m_LanguageCookie == cookie)
|
||||
{
|
||||
unsigned int langid;
|
||||
m_Players[i].m_LangId = (translator->GetLanguageByName(cvarValue, &langid)) ? langid : translator->GetServerLanguage();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*******************
|
||||
*** PLAYER CODE ***
|
||||
@ -1886,6 +1915,9 @@ CPlayer::CPlayer()
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
@ -1966,6 +1998,9 @@ void CPlayer::Disconnect()
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPlayer::SetName(const char *name)
|
||||
|
@ -131,6 +131,9 @@ private:
|
||||
bool m_bIsReplay;
|
||||
serial_t m_Serial;
|
||||
unsigned int m_SteamAccountID;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
QueryCvarCookie_t m_LanguageCookie;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
@ -211,6 +214,9 @@ public:
|
||||
unsigned int GetReplyTo();
|
||||
unsigned int SetReplyTo(unsigned int reply);
|
||||
void MaxPlayersChanged(int newvalue = -1);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||
#endif
|
||||
private:
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
void OnServerActivate();
|
||||
|
@ -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']
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <IPluginSys.h>
|
||||
#include <stdarg.h>
|
||||
#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,
|
||||
|
@ -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<CExtension *>::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<IExtension *> *CExtensionManager::ListExtensions()
|
||||
{
|
||||
CVector<IExtension *> *list = new CVector<IExtension *>();
|
||||
|
@ -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<IExtension *> *ListExtensions();
|
||||
void FreeExtensionList(const CVector<IExtension *> *list);
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
551
core/logic/Logger.cpp
Normal file
551
core/logic/Logger.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <cstdarg>
|
||||
#include "Logger.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
111
core/logic/Logger.h
Normal file
111
core/logic/Logger.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sh_string.h>
|
||||
|
||||
#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_
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,13 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
||||
active_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "dump") == 0) {
|
||||
if (active_) {
|
||||
// if we have an active profiler, dump it
|
||||
active_->Dump();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->ArgC() < 4) {
|
||||
if (strcmp(cmdname, "start") == 0) {
|
||||
@ -154,6 +161,15 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
||||
StartFromConsole(tool);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "dump") == 0) {
|
||||
IProfilingTool *tool = FindToolByName(toolname);
|
||||
if (!tool) {
|
||||
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
|
||||
return;
|
||||
}
|
||||
tool->Dump();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "help") == 0) {
|
||||
IProfilingTool *tool = FindToolByName(toolname);
|
||||
if (!tool) {
|
||||
@ -169,5 +185,6 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
||||
rootmenu->DrawGenericOption("list", "List all available profiling tools.");
|
||||
rootmenu->DrawGenericOption("start", "Start a profile with a given tool.");
|
||||
rootmenu->DrawGenericOption("stop", "Stop the current profile session.");
|
||||
rootmenu->DrawGenericOption("dump", "Dumps output from the current profile session.");
|
||||
rootmenu->DrawGenericOption("help", "Display help text for a profiler.");
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nat
|
||||
if (i.found())
|
||||
return NULL;
|
||||
|
||||
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv));
|
||||
Ref<Native> entry = new Native(pOwner, ntv);
|
||||
m_NtvCache.insert(ntv->name, entry);
|
||||
return entry;
|
||||
}
|
||||
@ -415,7 +415,7 @@ PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n
|
||||
|
||||
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
|
||||
|
||||
entry = Newborn<Native>(new Native(owner, fake.take()));
|
||||
entry = new Native(owner, fake.take());
|
||||
m_NtvCache.insert(name, entry);
|
||||
|
||||
return entry;
|
||||
|
@ -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; i<m_Files.size(); i++)
|
||||
@ -872,7 +872,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
|
||||
|
||||
if (!m_InLanguageSection)
|
||||
{
|
||||
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
logger->LogError("[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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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_ */
|
||||
|
||||
|
@ -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
|
||||
@ -83,6 +83,7 @@ class IFileSystem_Logic
|
||||
public:
|
||||
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
|
||||
virtual const char *FindNext(FileFindHandle_t handle) = 0;
|
||||
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
|
||||
virtual void FindClose(FileFindHandle_t handle) = 0;
|
||||
virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0;
|
||||
virtual void Close(FileHandle_t file) = 0;
|
||||
@ -90,6 +91,17 @@ public:
|
||||
virtual bool EndOfFile(FileHandle_t file) = 0;
|
||||
virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0;
|
||||
virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0;
|
||||
virtual int Read(void* pOutput, int size, FileHandle_t file) = 0;
|
||||
virtual int Write(void const* pInput, int size, FileHandle_t file) = 0;
|
||||
virtual void Seek(FileHandle_t file, int post, int seekType) = 0;
|
||||
virtual unsigned int Tell(FileHandle_t file) = 0;
|
||||
virtual int FPrint(FileHandle_t file, const char *pData) = 0;
|
||||
virtual void Flush(FileHandle_t file) = 0;
|
||||
virtual bool IsOk(FileHandle_t file) = 0;
|
||||
virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0;
|
||||
virtual void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID = 0) = 0;
|
||||
virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0;
|
||||
virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0;
|
||||
};
|
||||
|
||||
namespace SourceMod
|
||||
@ -211,6 +223,15 @@ public:
|
||||
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
|
||||
virtual const CVector<IExtension *> *ListExtensions() = 0;
|
||||
virtual void FreeExtensionList(const CVector<IExtension *> *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 +294,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 +343,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 +357,7 @@ struct sm_logic_t
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
IdentityToken_t *core_ident;
|
||||
ILogger *logger;
|
||||
float sentinel;
|
||||
};
|
||||
|
||||
|
@ -163,7 +163,7 @@ private:
|
||||
cell_t data_;
|
||||
};
|
||||
|
||||
struct CellTrie : public ke::Refcounted<CellTrie>
|
||||
struct CellTrie
|
||||
{
|
||||
StringHashMap<Entry> 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;
|
||||
|
@ -32,14 +32,14 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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 <ISourceMod.h>
|
||||
#include <ITranslator.h>
|
||||
|
||||
#include <sourcehook.h>
|
||||
#include <sh_memory.h>
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
@ -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<char *>(sm_datetime_format.GetString());
|
||||
format = const_cast<char *>(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},
|
||||
};
|
||||
|
||||
};
|
@ -148,6 +148,27 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError herr;
|
||||
HandleSecurity sec;
|
||||
IDataPack *pDataPack;
|
||||
|
||||
sec.pOwner = pContext->GetIdentity();
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
pDataPack->PackFunction(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@ -164,7 +185,7 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(cell_t)))
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
@ -188,7 +209,7 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(float)))
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
@ -223,6 +244,30 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError herr;
|
||||
HandleSecurity sec;
|
||||
IDataPack *pDataPack;
|
||||
|
||||
sec.pOwner = pContext->GetIdentity();
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
|
||||
return pDataPack->ReadFunction();
|
||||
}
|
||||
|
||||
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@ -318,9 +363,11 @@ REGISTER_NATIVES(datapacknatives)
|
||||
{"WritePackCell", smn_WritePackCell},
|
||||
{"WritePackFloat", smn_WritePackFloat},
|
||||
{"WritePackString", smn_WritePackString},
|
||||
{"WritePackFunction", smn_WritePackFunction},
|
||||
{"ReadPackCell", smn_ReadPackCell},
|
||||
{"ReadPackFloat", smn_ReadPackFloat},
|
||||
{"ReadPackString", smn_ReadPackString},
|
||||
{"ReadPackFunction", smn_ReadPackFunction},
|
||||
{"ResetPack", smn_ResetPack},
|
||||
{"GetPackPosition", smn_GetPackPosition},
|
||||
{"SetPackPosition", smn_SetPackPosition},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ IExtensionSys *extsys;
|
||||
IHandleSys *handlesys;
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
ILogger *logger;
|
||||
|
||||
class VEngineServer_Logic : public IVEngineServer_Logic
|
||||
{
|
||||
@ -146,6 +147,10 @@ public:
|
||||
{
|
||||
return filesystem->FindNext(handle);
|
||||
}
|
||||
bool FindIsDirectory(FileFindHandle_t handle)
|
||||
{
|
||||
return filesystem->FindIsDirectory(handle);
|
||||
}
|
||||
void FindClose(FileFindHandle_t handle)
|
||||
{
|
||||
filesystem->FindClose(handle);
|
||||
@ -174,6 +179,50 @@ public:
|
||||
{
|
||||
return filesystem->Size(pFileName, pPathID);
|
||||
}
|
||||
int Read(void* pOutput, int size, FileHandle_t file)
|
||||
{
|
||||
return filesystem->Read(pOutput, size, file);
|
||||
}
|
||||
int Write(void const* pInput, int size, FileHandle_t file)
|
||||
{
|
||||
return filesystem->Write(pInput, size, file);
|
||||
}
|
||||
void Seek(FileHandle_t file, int pos, int seekType)
|
||||
{
|
||||
filesystem->Seek(file, pos, (FileSystemSeek_t) seekType);
|
||||
}
|
||||
unsigned int Tell(FileHandle_t file)
|
||||
{
|
||||
return filesystem->Tell(file);
|
||||
}
|
||||
int FPrint(FileHandle_t file, const char *pData)
|
||||
{
|
||||
return filesystem->FPrintf(file, "%s", pData);
|
||||
}
|
||||
void Flush(FileHandle_t file)
|
||||
{
|
||||
filesystem->Flush(file);
|
||||
}
|
||||
bool IsOk(FileHandle_t file)
|
||||
{
|
||||
return filesystem->IsOk(file);
|
||||
}
|
||||
void RemoveFile(const char *pRelativePath, const char *pathID)
|
||||
{
|
||||
filesystem->RemoveFile(pRelativePath, pathID);
|
||||
}
|
||||
void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID)
|
||||
{
|
||||
filesystem->RenameFile(pOldPath, pNewPath, pathID);
|
||||
}
|
||||
bool IsDirectory(const char *pFileName, const char *pathID)
|
||||
{
|
||||
return filesystem->IsDirectory(pFileName, pathID);
|
||||
}
|
||||
void CreateDirHierarchy(const char *path, const char *pathID)
|
||||
{
|
||||
filesystem->CreateDirHierarchy(path, pathID);
|
||||
}
|
||||
};
|
||||
|
||||
static VFileSystem_Logic logic_filesystem;
|
||||
@ -251,46 +300,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 +322,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 +582,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 +654,7 @@ void InitLogicBridge()
|
||||
handlesys = logicore.handlesys;
|
||||
forwardsys = logicore.forwardsys;
|
||||
adminsys = logicore.adminsys;
|
||||
logger = logicore.logger;
|
||||
}
|
||||
|
||||
bool StartLogicBridge(char *error, size_t maxlength)
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,14 @@ VProfTool::Stop(void (*render)(const char *fmt, ...))
|
||||
RenderHelp(render);
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::Dump()
|
||||
{
|
||||
g_VProfCurrentProfile.Pause();
|
||||
g_VProfCurrentProfile.OutputReport(VPRT_FULL);
|
||||
g_VProfCurrentProfile.Resume();
|
||||
}
|
||||
|
||||
bool
|
||||
VProfTool::IsActive()
|
||||
{
|
||||
@ -105,5 +113,5 @@ VProfTool::LeaveScope()
|
||||
void
|
||||
VProfTool::RenderHelp(void (*render)(const char *fmt, ...))
|
||||
{
|
||||
render("Use vprof_generate_report in your console to analyze a profile session.");
|
||||
render("Use 'sm prof dump vprof' or one of the vprof_generate_report commands in your console to analyze a profile session.");
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
const char *Description() KE_OVERRIDE;
|
||||
bool Start() KE_OVERRIDE;
|
||||
void Stop(void (*render)(const char *fmt, ...)) KE_OVERRIDE;
|
||||
void Dump() KE_OVERRIDE;
|
||||
bool IsActive() KE_OVERRIDE;
|
||||
bool IsAttached() KE_OVERRIDE;
|
||||
void EnterScope(const char *group, const char *name) KE_OVERRIDE;
|
||||
|
@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect()
|
||||
char error[256];
|
||||
int errCode = 0;
|
||||
|
||||
Database = Newborn<IDatabase>(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
|
||||
if (!Database)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,9 @@
|
||||
}
|
||||
"PreThink"
|
||||
{
|
||||
"windows" "344"
|
||||
"linux" "345"
|
||||
"mac" "345"
|
||||
"windows" "345"
|
||||
"linux" "346"
|
||||
"mac" "346"
|
||||
}
|
||||
"PostThink"
|
||||
{
|
||||
|
@ -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"
|
||||
{
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
{
|
||||
|
@ -118,18 +118,21 @@ LoadBanReasons()
|
||||
decl String:sectionName[255];
|
||||
if(!KvGetSectionName(g_hKvBanReasons, sectionName, sizeof(sectionName)))
|
||||
{
|
||||
return SetFailState("Error in %s: File corrupt or in the wrong format", g_BanReasonsPath);
|
||||
SetFailState("Error in %s: File corrupt or in the wrong format", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if(strcmp(sectionName, "banreasons") != 0)
|
||||
{
|
||||
return SetFailState("Error in %s: Couldn't find 'banreasons'", g_BanReasonsPath);
|
||||
SetFailState("Error in %s: Couldn't find 'banreasons'", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset kvHandle
|
||||
KvRewind(g_hKvBanReasons);
|
||||
} else {
|
||||
return SetFailState("Error in %s: File not found, corrupt or in the wrong format", g_BanReasonsPath);
|
||||
SetFailState("Error in %s: File not found, corrupt or in the wrong format", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,13 @@ forward OnClientCookiesCached(client);
|
||||
* @param maxlen Max length of the output buffer.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void CookieMenuHandler(client, CookieMenuAction:action, any:info, String:buffer[], maxlen);
|
||||
typedef CookieMenuHandler = function void (
|
||||
int client,
|
||||
CookieMenuAction action,
|
||||
any info,
|
||||
char[] buffer,
|
||||
int maxlen
|
||||
);
|
||||
|
||||
/**
|
||||
* Add a new prefab item to the client cookie settings menu.
|
||||
|
@ -140,7 +140,7 @@ stock ReplyToTargetError(client, reason)
|
||||
* @param clients Array to fill with unique, valid client indexes.
|
||||
* @return True if pattern was recognized, false otherwise.
|
||||
*/
|
||||
functag public bool:MultiTargetFilter(const String:pattern[], Handle:clients);
|
||||
typedef MultiTargetFilter = function bool (const char[] pattern, Handle clients);
|
||||
|
||||
/**
|
||||
* Adds a multi-target filter function for ProcessTargetString().
|
||||
|
@ -328,7 +328,7 @@ native FormatActivitySource(client, target, const String:namebuf[], maxlength);
|
||||
* @return An Action value. Not handling the command
|
||||
* means that Source will report it as "not found."
|
||||
*/
|
||||
functag public Action:SrvCmd(args);
|
||||
typedef SrvCmd = function Action (int args);
|
||||
|
||||
/**
|
||||
* Creates a server-only console command, or hooks an already existing one.
|
||||
@ -352,7 +352,7 @@ native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:descriptio
|
||||
* @return An Action value. Not handling the command
|
||||
* means that Source will report it as "not found."
|
||||
*/
|
||||
functag public Action:ConCmd(client, args);
|
||||
typedef ConCmd = function Action (int client, int args);
|
||||
|
||||
/**
|
||||
* Creates a console command, or hooks an already existing one.
|
||||
@ -456,7 +456,7 @@ native Handle:FindConVar(const String:name[]);
|
||||
* @param newValue String containing the new value of the convar.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void ConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]);
|
||||
typedef ConVarChanged = function void (Handle convar, const char[] oldValue, const char[] newValue);
|
||||
|
||||
/**
|
||||
* Creates a hook for when a console variable's value is changed.
|
||||
@ -669,7 +669,7 @@ native SetConVarBounds(Handle:convar, ConVarBounds:type, bool:set, Float:value=0
|
||||
*/
|
||||
native GetConVarName(Handle:convar, String:name[], maxlength);
|
||||
|
||||
funcenum ConVarQueryFinished
|
||||
union ConVarQueryFinished
|
||||
{
|
||||
/**
|
||||
* Called when a query to retrieve a client's console variable has finished.
|
||||
@ -683,7 +683,7 @@ funcenum ConVarQueryFinished
|
||||
* @param value Value that was passed when query was started.
|
||||
* @noreturn
|
||||
*/
|
||||
public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[], any:value),
|
||||
function void (QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, any value);
|
||||
|
||||
/**
|
||||
* Called when a query to retrieve a client's console variable has finished.
|
||||
@ -696,7 +696,7 @@ funcenum ConVarQueryFinished
|
||||
* @param convarValue Value of client convar that was queried if successful. This will be "" if it was not.
|
||||
* @noreturn
|
||||
*/
|
||||
public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[])
|
||||
function void (QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -905,7 +905,7 @@ native RemoveServerTag(const String:tag[]);
|
||||
* @param argc Argument count.
|
||||
* @return Action to take (see extended notes above).
|
||||
*/
|
||||
functag public Action:CommandListener(client, const String:command[], argc);
|
||||
typedef CommandListener = function Action (int client, const char[] command, int argc);
|
||||
|
||||
#define FEATURECAP_COMMANDLISTENER "command listener"
|
||||
|
||||
|
@ -72,6 +72,16 @@ native WritePackFloat(Handle:pack, Float:val);
|
||||
*/
|
||||
native WritePackString(Handle:pack, const String:str[]);
|
||||
|
||||
/**
|
||||
* Packs a function pointer into a data pack.
|
||||
*
|
||||
* @param pack Handle to the data pack.
|
||||
* @param fktptr Function pointer to add.
|
||||
* @noreturn
|
||||
* @error Invalid handle.
|
||||
*/
|
||||
native WritePackFunction(Handle:pack, Function:fktptr);
|
||||
|
||||
/**
|
||||
* Reads a cell from a data pack.
|
||||
*
|
||||
@ -101,6 +111,15 @@ native Float:ReadPackFloat(Handle:pack);
|
||||
*/
|
||||
native ReadPackString(Handle:pack, String:buffer[], maxlen);
|
||||
|
||||
/**
|
||||
* Reads a function pointer from a data pack.
|
||||
*
|
||||
* @param pack Handle to the data pack.
|
||||
* @return Function pointer.
|
||||
* @error Invalid handle, or bounds error.
|
||||
*/
|
||||
native Function ReadPackFunction(Handle:pack);
|
||||
|
||||
/**
|
||||
* Resets the position in a data pack.
|
||||
*
|
||||
|
@ -643,7 +643,7 @@ native SQL_UnlockDatabase(Handle:database);
|
||||
* @param data Data passed in via the original threaded invocation.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void SQLTCallback(Handle:owner, Handle:hndl, const String:error[], any:data);
|
||||
typedef SQLTCallback = function void (Handle owner, Handle hndl, const char[] error, any data);
|
||||
|
||||
/**
|
||||
* Tells whether two database handles both point to the same database
|
||||
@ -713,7 +713,7 @@ native Transaction:SQL_CreateTransaction();
|
||||
* @param queryData An array of each data value passed to SQL_AddQuery().
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void SQLTxnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[]);
|
||||
typedef SQLTxnSuccess = function void (Handle db, any data, int numQueries, Handle[] results, any[] queryData);
|
||||
|
||||
/**
|
||||
* Callback for a failed transaction.
|
||||
@ -726,7 +726,7 @@ functag public void SQLTxnSuccess(Handle:db, any:data, numQueries, Handle:result
|
||||
* @param queryData An array of each data value passed to SQL_AddQuery().
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void SQLTxnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[]);
|
||||
typedef SQLTxnFailure = function void (Handle db, any data, int numQueries, const char[] error, int failIndex, any[] queryData);
|
||||
|
||||
/**
|
||||
* Adds a query to a transaction object.
|
||||
|
@ -48,7 +48,7 @@ enum EventHookMode
|
||||
/**
|
||||
* Hook function types for events.
|
||||
*/
|
||||
funcenum EventHook
|
||||
union EventHook
|
||||
{
|
||||
/**
|
||||
* Called when a game event is fired.
|
||||
@ -59,7 +59,7 @@ funcenum EventHook
|
||||
* @param dontBroadcast True if event was not broadcast to clients, false otherwise.
|
||||
* @return Ignored for post hooks. Plugin_Handled will block event if hooked as pre.
|
||||
*/
|
||||
Action:public(Handle:event, const String:name[], bool:dontBroadcast),
|
||||
function Action (Handle event, const char[] name, bool dontBroadcast);
|
||||
/**
|
||||
* Called when a game event is fired.
|
||||
*
|
||||
@ -69,7 +69,7 @@ funcenum EventHook
|
||||
* @param dontBroadcast True if event was not broadcast to clients, false otherwise.
|
||||
* @noreturn
|
||||
*/
|
||||
public(Handle:event, const String:name[], bool:dontBroadcast),
|
||||
function void (Handle event, const char[] name, bool dontBroadcast);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -108,9 +108,14 @@ native BuildPath(PathType:type, String:buffer[], maxlength, const String:fmt[],
|
||||
* @note OpenDirectory() supports the "file://" notation.
|
||||
*
|
||||
* @param path Path to open.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to find files existing in any of
|
||||
* the Valve search paths, rather than solely files
|
||||
* existing directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return A Handle to the directory, INVALID_HANDLE on open error.
|
||||
*/
|
||||
native Handle:OpenDirectory(const String:path[]);
|
||||
native Handle:OpenDirectory(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME");
|
||||
|
||||
/**
|
||||
* Reads the current directory entry as a local filename, then moves to the next file.
|
||||
@ -136,17 +141,27 @@ native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type=
|
||||
*
|
||||
* @param file File to open.
|
||||
* @param mode Open mode.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to find files existing in valve
|
||||
* search paths, rather than solely files existing directly
|
||||
* in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return A Handle to the file, INVALID_HANDLE on open error.
|
||||
*/
|
||||
native Handle:OpenFile(const String:file[], const String:mode[]);
|
||||
native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME");
|
||||
|
||||
/**
|
||||
* Deletes a file.
|
||||
*
|
||||
* @param path Path of the file to delete.
|
||||
* @return True on success, false otherwise.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to delete files existing in the Valve
|
||||
* search path, rather than solely files existing directly
|
||||
* in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return True on success, false on failure or if file not immediately removed.
|
||||
*/
|
||||
native bool:DeleteFile(const String:path[]);
|
||||
native bool:DeleteFile(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH");
|
||||
|
||||
/**
|
||||
* Reads a line from a text file.
|
||||
@ -304,28 +319,38 @@ native FilePosition(Handle:file);
|
||||
* @param path Path to the file.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to find files existing in any of
|
||||
* the GAME search paths, rather than solely files
|
||||
* the Valve search paths, rather than solely files
|
||||
* existing directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return True if the file exists, false otherwise.
|
||||
*/
|
||||
native bool:FileExists(const String:path[], bool:use_valve_fs=false);
|
||||
native bool:FileExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME");
|
||||
|
||||
/**
|
||||
* Renames a file.
|
||||
*
|
||||
* @param newpath New path to the file.
|
||||
* @param oldpath Path to the existing file.
|
||||
* @return True on success, false otherwise.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to rename files in the game's
|
||||
* Valve search paths, rather than directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return True on success or use_valve_fs specified, false otherwise.
|
||||
*/
|
||||
native bool:RenameFile(const String:newpath[], const String:oldpath[]);
|
||||
native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH");
|
||||
|
||||
/**
|
||||
* Checks if a directory exists.
|
||||
*
|
||||
* @param path Path to the directory.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to find files existing in any of
|
||||
* the Valve search paths, rather than solely files
|
||||
* existing directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return True if the directory exists, false otherwise.
|
||||
*/
|
||||
native bool:DirExists(const String:path[]);
|
||||
native bool:DirExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME");
|
||||
|
||||
/**
|
||||
* Get the file size in bytes.
|
||||
@ -333,18 +358,20 @@ native bool:DirExists(const String:path[]);
|
||||
* @param path Path to the file.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to find files existing in any of
|
||||
* the GAME search paths, rather than solely files
|
||||
* the Valve search paths, rather than solely files
|
||||
* existing directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.
|
||||
* @return File size in bytes, -1 if file not found.
|
||||
*/
|
||||
native FileSize(const String:path[], bool:use_valve_fs=false);
|
||||
native FileSize(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME");
|
||||
|
||||
/**
|
||||
* Flushes a file's buffered output; any buffered output
|
||||
* is immediately written to the file.
|
||||
*
|
||||
* @param file Handle to the file.
|
||||
* @return True on success, false on failure.
|
||||
* @return True on success or use_valve_fs specified with OpenFile,
|
||||
* otherwise false on failure.
|
||||
*/
|
||||
native FlushFile(Handle:file);
|
||||
|
||||
@ -373,8 +400,22 @@ native bool:RemoveDir(const String:path[]);
|
||||
* @param path Path to create.
|
||||
* @param mode Permissions (default is o=rx,g=rx,u=rwx). Note that folders must have
|
||||
* the execute bit set on Linux. On Windows, the mode is ignored.
|
||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
||||
* This can be used to create folders in the game's
|
||||
* Valve search paths, rather than directly in the gamedir.
|
||||
* @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default.
|
||||
* In this case, mode is ignored.
|
||||
*/
|
||||
native bool:CreateDirectory(const String:path[], mode);
|
||||
native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH");
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -35,6 +35,7 @@
|
||||
#endif
|
||||
#define _float_included
|
||||
|
||||
#if !defined __sourcepawn2__
|
||||
/**
|
||||
* Converts an integer into a floating point value.
|
||||
*
|
||||
@ -42,6 +43,7 @@
|
||||
* @return Floating point value.
|
||||
*/
|
||||
native Float:float(value);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Multiplies two floats together.
|
||||
|
@ -357,7 +357,7 @@ native Call_Cancel();
|
||||
* @param numParams Number of parameters passed to the native.
|
||||
* @return Value for the native call to return.
|
||||
*/
|
||||
functag public int NativeCall(Handle:plugin, numParams);
|
||||
typedef NativeCall = function int (Handle plugin, int numParams);
|
||||
|
||||
/**
|
||||
* Creates a dynamic native. This should only be called in AskPluginLoad(), or
|
||||
@ -508,7 +508,7 @@ native FormatNativeString(out_param,
|
||||
* @param data Data passed to the RequestFrame native.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void RequestFrameCallback(any:data);
|
||||
typedef RequestFrameCallback = function void (any data);
|
||||
|
||||
/**
|
||||
* Creates a single use Next Frame hook.
|
||||
|
@ -59,7 +59,6 @@ native SetGlobalTransTarget(client);
|
||||
|
||||
/**
|
||||
* Retrieves the language number of a client.
|
||||
* Currently this simply returns the server language index.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Language number client is using.
|
||||
|
@ -123,7 +123,7 @@ forward Action:OnLogAction(Handle:source,
|
||||
* @return Plugin_Handled or Plugin_Stop will prevent the message
|
||||
* from being written to the log file.
|
||||
*/
|
||||
functag public Action:GameLogHook(const String:message[]);
|
||||
typedef GameLogHook = function Action (const char[] message);
|
||||
|
||||
/**
|
||||
* Adds a game log hook.
|
||||
|
@ -151,7 +151,7 @@ enum MenuSource
|
||||
* @param param1 First action parameter (usually the client).
|
||||
* @param param2 Second action parameter (usually the item).
|
||||
*/
|
||||
functag public int MenuHandler(Menu:menu, MenuAction:action, param1, param2);
|
||||
typedef MenuHandler = function int (Menu menu, MenuAction action, int param1, int param2);
|
||||
|
||||
/**
|
||||
* Creates a new, empty menu using the default style.
|
||||
@ -527,12 +527,14 @@ stock bool:VoteMenuToAll(Handle:menu, time, flags=0)
|
||||
* defines.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void VoteHandler(Menu:menu,
|
||||
num_votes,
|
||||
num_clients,
|
||||
const client_info[][2],
|
||||
num_items,
|
||||
const item_info[][2]);
|
||||
typedef VoteHandler = function void (
|
||||
Menu menu,
|
||||
int num_votes,
|
||||
int num_clients,
|
||||
const int client_info[][2],
|
||||
int num_items,
|
||||
const int item_info[][2]
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets an advanced vote handling callback. If this callback is set,
|
||||
|
@ -197,91 +197,91 @@ enum UseType
|
||||
Use_Toggle
|
||||
};
|
||||
|
||||
funcenum SDKHookCB
|
||||
union SDKHookCB
|
||||
{
|
||||
// PreThink/Post
|
||||
// PostThink/Post
|
||||
public(client),
|
||||
function void (int client);
|
||||
|
||||
// Spawn
|
||||
Action:public(entity),
|
||||
function Action (int entity);
|
||||
|
||||
// GroundEntChanged
|
||||
// SpawnPost
|
||||
// Think/Post
|
||||
// VPhysicsUpdate/Post
|
||||
public(entity),
|
||||
function void (int entity);
|
||||
|
||||
// EndTouch
|
||||
// StartTouch
|
||||
// Touch
|
||||
// Blocked
|
||||
Action:public(entity, other),
|
||||
function Action (int entity, int other);
|
||||
|
||||
// EndTouchPost
|
||||
// StartTouchPost
|
||||
// TouchPost
|
||||
public(entity, other),
|
||||
function void (int entity, int other);
|
||||
|
||||
// SetTransmit
|
||||
Action:public(entity, client),
|
||||
function Action (int entity, int client);
|
||||
|
||||
// WeaponCanSwitchTo
|
||||
// WeaponCanUse
|
||||
// WeaponDrop
|
||||
// WeaponEquip
|
||||
// WeaponSwitch
|
||||
Action:public(client, weapon),
|
||||
function Action (int client, int weapon);
|
||||
|
||||
// WeaponCanSwitchToPost
|
||||
// WeaponCanUsePost
|
||||
// WeaponDropPost
|
||||
// WeaponEquipPost
|
||||
// WeaponSwitchPost
|
||||
public(client, weapon),
|
||||
function void (int client, int weapon);
|
||||
|
||||
// GetMaxHealth (ep2v and later)
|
||||
Action:public(entity, &maxhealth),
|
||||
function Action (int entity, int &maxhealth);
|
||||
|
||||
// OnTakeDamage
|
||||
// Note: The weapon parameter is not used by all games and damage sources.
|
||||
// Note: Force application is dependent on game and damage type(s)
|
||||
// SDKHooks 1.0+
|
||||
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype),
|
||||
function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype),
|
||||
// SDKHooks 2.0+
|
||||
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3]),
|
||||
function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float[3] damageForce, float[3] damagePosition);
|
||||
// SDKHooks 2.1+ (can check for support at runtime using GetFeatureStatus on SDKHook_DmgCustomInOTD capability.
|
||||
// DON'T attempt to access 'damagecustom' var if feature status != available
|
||||
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon,
|
||||
Float:damageForce[3], Float:damagePosition[3], damagecustom),
|
||||
function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon,
|
||||
float[3] damageForce, float[3] damagePosition, int damagecustom);
|
||||
|
||||
// OnTakeDamagePost
|
||||
public(victim, attacker, inflictor, Float:damage, damagetype),
|
||||
public(victim, attacker, inflictor, Float:damage, damagetype, weapon, const Float:damageForce[3], const Float:damagePosition[3]),
|
||||
function void (int victim, int attacker, int inflictor, float damage, int damagetype);
|
||||
function void (int victim, int attacker, int inflictor, float damage, int damagetype, const float[3] damageForce, const float[3] damagePosition);
|
||||
|
||||
// FireBulletsPost
|
||||
public(client, shots, const String:weaponname[]),
|
||||
function void (int client, int shots, const char[] weaponname);
|
||||
|
||||
// TraceAttack
|
||||
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup),
|
||||
function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &ammotype, int hitbox, int hitgroup);
|
||||
|
||||
// TraceAttackPost
|
||||
public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup),
|
||||
function void (int victim, int attacker, int inflictor, float damage, int damagetype, int ammotype, int hitbox, int hitgroup);
|
||||
|
||||
// ShouldCollide
|
||||
bool:public(entity, collisiongroup, contentsmask, bool:originalResult),
|
||||
function bool (int entity, int collisiongroup, int contentsmask, bool originalResult);
|
||||
|
||||
// Use
|
||||
Action:public(entity, activator, caller, UseType:type, Float:value),
|
||||
function Action (int entity, int activator, int caller, UseType type, float value);
|
||||
|
||||
// UsePost
|
||||
public(entity, activator, caller, UseType:type, Float:value),
|
||||
function void (int entity, int activator, int caller, UseType type, float value);
|
||||
|
||||
// Reload
|
||||
Action:public(weapon),
|
||||
function Action (int weapon);
|
||||
|
||||
// Reload post
|
||||
public(weapon, bool:bSuccessful)
|
||||
function void (int weapon, bool bSuccessful);
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
||||
* @param delay Delay in seconds? before the event gets fired.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void EntityOutput(const String:output[], caller, activator, Float:delay);
|
||||
typedef EntityOutput = function void (const char[] output, int caller, int activator, float delay);
|
||||
|
||||
/**
|
||||
* Add an entity output hook on a entity classname
|
||||
|
@ -283,7 +283,16 @@ native Float:GetDistGainFromSoundLevel(soundlevel, Float:distance);
|
||||
* @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
|
||||
* Plugin_Changed when any parameter has been modified.
|
||||
*/
|
||||
functag public Action:AmbientSHook(String:sample[PLATFORM_MAX_PATH], &entity, &Float:volume, &level, &pitch, Float:pos[3], &flags, &Float:delay);
|
||||
typedef AmbientSHook = function Action (
|
||||
char sample[PLATFORM_MAX_PATH],
|
||||
int &entity,
|
||||
float &volume,
|
||||
int &level,
|
||||
int &pitch,
|
||||
float pos[3],
|
||||
int &flags,
|
||||
float &delay
|
||||
);
|
||||
|
||||
/**
|
||||
* Called when a sound is going to be emitted to one or more clients.
|
||||
@ -301,7 +310,17 @@ functag public Action:AmbientSHook(String:sample[PLATFORM_MAX_PATH], &entity, &F
|
||||
* @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
|
||||
* Plugin_Changed when any parameter has been modified.
|
||||
*/
|
||||
functag public Action:NormalSHook(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags);
|
||||
typedef NormalSHook = function Action (
|
||||
int clients[64],
|
||||
int &numClients,
|
||||
char sample[PLATFORM_MAX_PATH],
|
||||
int &entity,
|
||||
int &channel,
|
||||
float &volume,
|
||||
int &level,
|
||||
int &pitch,
|
||||
int &flags
|
||||
);
|
||||
|
||||
/**
|
||||
* Hooks all played ambient sounds.
|
||||
|
@ -44,7 +44,7 @@
|
||||
* @param delay Delay in seconds to send the TE.
|
||||
* @return Plugin_Continue to allow the transmission of the TE, Plugin_Stop to block it.
|
||||
*/
|
||||
functag public Action:TEHook(const String:te_name[], const Players[], numClients, Float:delay);
|
||||
typedef TEHook = function Action (const char[] te_name, const int[] Players, int numClients, float delay);
|
||||
|
||||
/**
|
||||
* Hooks a temp entity.
|
||||
|
@ -110,7 +110,7 @@ enum RayType
|
||||
RayType_Infinite /**< The trace ray will go from the start position to infinity using a direction vector. */
|
||||
};
|
||||
|
||||
funcenum TraceEntityFilter
|
||||
union TraceEntityFilter
|
||||
{
|
||||
/**
|
||||
* Called on entity filtering.
|
||||
@ -119,7 +119,7 @@ funcenum TraceEntityFilter
|
||||
* @param contentsMask Contents Mask.
|
||||
* @return True to allow the current entity to be hit, otherwise false.
|
||||
*/
|
||||
bool:public(entity, contentsMask),
|
||||
function bool (int entity, int contentsMask);
|
||||
|
||||
/**
|
||||
* Called on entity filtering.
|
||||
@ -129,7 +129,7 @@ funcenum TraceEntityFilter
|
||||
* @param data Data value, if used.
|
||||
* @return True to allow the current entity to be hit, otherwise false.
|
||||
*/
|
||||
bool:public(entity, contentsMask, any:data),
|
||||
function bool (int entity, int contentsMask, any data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -371,4 +371,4 @@ native TR_GetPlaneNormal(Handle:hndl, Float:normal[3]);
|
||||
* @param pos Vector buffer to store data in.
|
||||
* @return True if outside world, otherwise false.
|
||||
*/
|
||||
native TR_PointOutsideWorld(Float:pos[3]);
|
||||
native TR_PointOutsideWorld(Float:pos[3]);
|
||||
|
@ -98,7 +98,7 @@ native SortStrings(String:array[][], array_size, SortOrder:order = Sort_Ascendin
|
||||
* 0 if first is equal to second
|
||||
* 1 if first should go after second
|
||||
*/
|
||||
functag public int SortFunc1D(elem1, elem2, const array[], Handle:hndl);
|
||||
typedef SortFunc1D = function int (int elem1, int elem2, const int[] array, Handle hndl);
|
||||
|
||||
/**
|
||||
* Sorts a custom 1D array. You must pass in a comparison function.
|
||||
@ -123,10 +123,10 @@ native SortCustom1D(array[], array_size, SortFunc1D:sortfunc, Handle:hndl=INVALI
|
||||
* 0 if first is equal to second
|
||||
* 1 if first should go after second
|
||||
*/
|
||||
funcenum SortFunc2D
|
||||
union SortFunc2D
|
||||
{
|
||||
public(elem1[], elem2[], const array[][], Handle:hndl),
|
||||
public(String:elem1[], String:elem2[], const String:array[][], Handle:hndl),
|
||||
function int (int[] elem1, int[] elem2, const int[][] array, Handle hndl);
|
||||
function int (char[] elem1, char[] elem2, const char[][] array, Handle hndl);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -163,7 +163,7 @@ native SortADTArray(Handle:array, SortOrder:order, SortType:type);
|
||||
* 0 if first is equal to second
|
||||
* 1 if first should go after second
|
||||
*/
|
||||
functag public int SortFuncADTArray(index1, index2, Handle:array, Handle:hndl);
|
||||
typedef SortFuncADTArray = function int (int index1, int index2, Handle array, Handle hndl);
|
||||
|
||||
/**
|
||||
* Custom sorts an ADT Array. You must pass in a comparison function.
|
||||
@ -173,4 +173,4 @@ functag public int SortFuncADTArray(index1, index2, Handle:array, Handle:hndl);
|
||||
* @param hndl Optional Handle to pass through the comparison calls.
|
||||
* @noreturn
|
||||
*/
|
||||
native SortADTArrayCustom(Handle:array, SortFuncADTArray:sortfunc, Handle:hndl=INVALID_HANDLE);
|
||||
native SortADTArrayCustom(Handle:array, SortFuncADTArray:sortfunc, Handle:hndl=INVALID_HANDLE);
|
||||
|
@ -108,7 +108,7 @@ native bool:SMC_GetErrorString(SMCError:error, String:buffer[], buf_max);
|
||||
* @param smc The SMC Parse Handle.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void SMC_ParseStart(Handle:smc);
|
||||
typedef SMC_ParseStart = function void (Handle smc);
|
||||
|
||||
/**
|
||||
* Sets the SMC_ParseStart function of a parse Handle.
|
||||
@ -128,7 +128,7 @@ native SMC_SetParseStart(Handle:smc, SMC_ParseStart:func);
|
||||
* @param failed True if parsing failed, false otherwise.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void SMC_ParseEnd(Handle:smc, bool:halted, bool:failed);
|
||||
typedef SMC_ParseEnd = function void (Handle smc, bool halted, bool failed);
|
||||
|
||||
/**
|
||||
* Sets the SMC_ParseEnd of a parse handle.
|
||||
@ -149,7 +149,7 @@ native SMC_SetParseEnd(Handle:smc, SMC_ParseEnd:func);
|
||||
* @param opt_quotes True if the section name was quote-enclosed in the file.
|
||||
* @return An SMCResult action to take.
|
||||
*/
|
||||
functag public SMCResult:SMC_NewSection(Handle:smc, const String:name[], bool:opt_quotes);
|
||||
typedef SMC_NewSection = function SMCResult (Handle smc, const char[] name, bool opt_quotes);
|
||||
|
||||
/**
|
||||
* Called when the parser finds a new key/value pair.
|
||||
@ -162,7 +162,7 @@ functag public SMCResult:SMC_NewSection(Handle:smc, const String:name[], bool:op
|
||||
* @param value_quotes Whether or not the value was enclosed in quotes.
|
||||
* @return An SMCResult action to take.
|
||||
*/
|
||||
functag public SMCResult:SMC_KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes);
|
||||
typedef SMC_KeyValue = function SMCResult (Handle smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes);
|
||||
|
||||
/**
|
||||
* Called when the parser finds the end of the current section.
|
||||
@ -170,7 +170,7 @@ functag public SMCResult:SMC_KeyValue(Handle:smc, const String:key[], const Stri
|
||||
* @param smc The SMC Parse Handle.
|
||||
* @return An SMCResult action to take.
|
||||
*/
|
||||
functag public SMCResult:SMC_EndSection(Handle:smc);
|
||||
typedef SMC_EndSection = function SMCResult (Handle smc);
|
||||
|
||||
/**
|
||||
* Sets the three main reader functions.
|
||||
@ -191,7 +191,7 @@ native SMC_SetReaders(Handle:smc, SMC_NewSection:ns, SMC_KeyValue:kv, SMC_EndSec
|
||||
* @param lineno The line number it occurs on.
|
||||
* @return An SMCResult action to take.
|
||||
*/
|
||||
functag public SMCResult:SMC_RawLine(Handle:smc, const String:line[], lineno);
|
||||
typedef SMC_RawLine = function SMCResult (Handle smc, const char[] line, int lineno);
|
||||
|
||||
/**
|
||||
* Sets a raw line reader on an SMC parser Handle.
|
||||
|
@ -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
|
||||
|
@ -249,6 +249,7 @@ enum {
|
||||
TF_WEAPON_SPELLBOOK,
|
||||
TF_WEAPON_SPELLBOOK_PROJECTILE,
|
||||
TF_WEAPON_SNIPERRIFLE_CLASSIC,
|
||||
TF_WEAPON_PARACHUTE,
|
||||
};
|
||||
|
||||
// TF2 Weapon Loadout Slots
|
||||
@ -435,6 +436,20 @@ stock TF2_RemoveWeaponSlot(client, slot)
|
||||
new weaponIndex;
|
||||
while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1)
|
||||
{
|
||||
// bug #6206
|
||||
// papering over a valve bug where a weapon's extra wearables aren't properly removed from the weapon's owner
|
||||
new extraWearable = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearable");
|
||||
if (extraWearable != -1)
|
||||
{
|
||||
TF2_RemoveWearable(client, extraWearable);
|
||||
}
|
||||
|
||||
extraWearable = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearableViewModel");
|
||||
if (extraWearable != -1)
|
||||
{
|
||||
TF2_RemoveWearable(client, extraWearable);
|
||||
}
|
||||
|
||||
RemovePlayerItem(client, weaponIndex);
|
||||
AcceptEntityInput(weaponIndex, "Kill");
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
/**
|
||||
* Any of the following prototypes will work for a timed function.
|
||||
*/
|
||||
funcenum Timer
|
||||
union Timer
|
||||
{
|
||||
/**
|
||||
* Called when the timer interval has elapsed.
|
||||
@ -55,7 +55,7 @@ funcenum Timer
|
||||
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||
* default behavior.
|
||||
*/
|
||||
Action:public(Handle:timer, Handle:hndl),
|
||||
function Action(Handle timer, Handle hndl);
|
||||
|
||||
/**
|
||||
* Called when the timer interval has elapsed.
|
||||
@ -65,7 +65,7 @@ funcenum Timer
|
||||
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||
* default behavior.
|
||||
*/
|
||||
Action:public(Handle:timer, any:data),
|
||||
function Action(Handle timer, any data);
|
||||
|
||||
/**
|
||||
* Called when the timer interval has elapsed.
|
||||
@ -74,7 +74,7 @@ funcenum Timer
|
||||
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||
* default behavior.
|
||||
*/
|
||||
Action:public(Handle:timer),
|
||||
function Action(Handle timer);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -127,12 +127,14 @@ enum TopMenuObject
|
||||
* @param maxlength Output buffer (if used).
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void TopMenuHandler(Handle:topmenu,
|
||||
TopMenuAction:action,
|
||||
TopMenuObject:topobj_id,
|
||||
param,
|
||||
String:buffer[],
|
||||
maxlength);
|
||||
typedef TopMenuHandler = function void (
|
||||
Handle topmenu,
|
||||
TopMenuAction action,
|
||||
TopMenuObject topobj_id,
|
||||
int param,
|
||||
char[] buffer,
|
||||
int maxlength
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a TopMenu.
|
||||
|
@ -140,7 +140,7 @@ native EndMessage();
|
||||
* blocks the message from being sent, and Plugin_Continue
|
||||
* resumes normal functionality.
|
||||
*/
|
||||
functag public Action:MsgHook(UserMsg:msg_id, Handle:msg, const players[], playersNum, bool:reliable, bool:init);
|
||||
typedef MsgHook = function Action (UserMsg msg_id, Handle msg, const int[] players, int playersNum, bool reliable, bool init);
|
||||
|
||||
/**
|
||||
* Called when a message hook has completed.
|
||||
@ -149,7 +149,7 @@ functag public Action:MsgHook(UserMsg:msg_id, Handle:msg, const players[], playe
|
||||
* @param sent True if message was sent, false if blocked.
|
||||
* @noreturn
|
||||
*/
|
||||
functag public void MsgPostHook(UserMsg:msg_id, bool:sent);
|
||||
typedef MsgPostHook = function void (UserMsg msg_id, bool sent);
|
||||
|
||||
/**
|
||||
* Hooks a user message.
|
||||
|
@ -113,6 +113,13 @@ namespace SourceMod
|
||||
* @return Pointer to the data, or NULL if out of bounds.
|
||||
*/
|
||||
virtual void *ReadMemory(size_t *size) const =0;
|
||||
|
||||
/**
|
||||
* @brief Reads a function pointer from the data stream.
|
||||
*
|
||||
* @return A function pointer read from the current position.
|
||||
*/
|
||||
virtual cell_t ReadFunction() const =0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -160,6 +167,13 @@ namespace SourceMod
|
||||
* @return Current position of the stream beforehand.
|
||||
*/
|
||||
virtual size_t CreateMemory(size_t size, void **addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Packs one function pointer into the data stream.
|
||||
*
|
||||
* @param function The function pointer to write.
|
||||
*/
|
||||
virtual void PackFunction(cell_t function) =0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -35,12 +35,15 @@
|
||||
|
||||
namespace ke {
|
||||
|
||||
// See the comment above Refcounted<T> 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 <typename T>
|
||||
class RefcountedThreadsafe
|
||||
{
|
||||
public:
|
||||
RefcountedThreadsafe()
|
||||
: refcount_(1)
|
||||
: refcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,18 +37,28 @@ namespace ke {
|
||||
|
||||
template <typename T> 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 <typename T>
|
||||
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 <typename T>
|
||||
static inline Newborn<T>
|
||||
NoAddRef(T *t)
|
||||
static inline AlreadyRefed<T>
|
||||
AdoptRef(T *t)
|
||||
{
|
||||
return Newborn<T>(t);
|
||||
return AlreadyRefed<T>(t);
|
||||
}
|
||||
|
||||
// When returning a value, we'd rather not be needlessly changing the refcount,
|
||||
@ -81,7 +91,14 @@ class PassRef
|
||||
{
|
||||
}
|
||||
|
||||
PassRef(const Newborn<T *> &other)
|
||||
PassRef(const AlreadyRefed<T *> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
// Don't addref, newborn means already addref'd.
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
PassRef(const AlreadyRefed<S *> &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<T> &other);
|
||||
PassRef &operator =(AlreadyRefed<T> &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 <typename T>
|
||||
class Refcounted
|
||||
{
|
||||
public:
|
||||
Refcounted()
|
||||
: refcount_(1)
|
||||
: refcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -217,7 +239,12 @@ class Ref
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
Ref(const Newborn<T> &other)
|
||||
Ref(const AlreadyRefed<T> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
template <typename S>
|
||||
Ref(const AlreadyRefed<S> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
@ -255,7 +282,7 @@ class Ref
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
Ref &operator =(const Newborn<S> &other) {
|
||||
Ref &operator =(const AlreadyRefed<S> &other) {
|
||||
Release();
|
||||
thing_ = other.release();
|
||||
return *this;
|
||||
|
@ -1044,6 +1044,15 @@ namespace SourcePawn
|
||||
* @param render Function to render any help messages.
|
||||
*/
|
||||
virtual void Stop(void (*render)(const char *fmt, ...)) = 0;
|
||||
|
||||
/**
|
||||
* @brief Dump profiling information.
|
||||
*
|
||||
* Informs the profiling tool to dump any current profiling information
|
||||
* it has accumulated. The format and location of the output is profiling
|
||||
* tool specific.
|
||||
*/
|
||||
virtual void Dump() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns whether or not the profiler is currently profiling.
|
||||
|
@ -36,8 +36,8 @@
|
||||
* @file sp_vm_types.h
|
||||
* @brief Contains all run-time SourcePawn structures.
|
||||
*/
|
||||
|
||||
#include "sp_file_headers.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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 <smx/smx-v1-headers.h>.
|
||||
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
|
||||
|
@ -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')
|
||||
|
@ -34,8 +34,12 @@
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_STDINT_H
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#include <stdint.h>
|
||||
#if !defined HAVE_STDINT_H
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#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);
|
||||
}
|
382
sourcepawn/compiler/libpawnc.cpp
Normal file
382
sourcepawn/compiler/libpawnc.cpp
Normal file
@ -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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#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);
|
||||
}
|
@ -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;
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,615 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#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 <unistd.h>
|
||||
#elif defined WIN32
|
||||
#include <io.h>
|
||||
#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; i<publics; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbtbl[i].address = stub->address;
|
||||
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; i<pubvars; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbvars[i].address = stub->address;
|
||||
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; i<natives; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
nvtbl[i].name = stub->nameofs - (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; i<numTags; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (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; idx<natives; idx++)
|
||||
{
|
||||
sfwrite(&idx, sizeof(uint32_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
|
||||
|
||||
/* Go through arguments */
|
||||
for (j = 0; j < native_list[idx].num_args; j++)
|
||||
{
|
||||
sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
memfile_write(dbgtab,
|
||||
native_list[idx].args[j].name,
|
||||
strlen(native_list[idx].args[j].name) + 1);
|
||||
if (native_list[idx].args[j].dimcount)
|
||||
{
|
||||
sfwrite(native_list[idx].args[j].dims,
|
||||
sizeof(sp_fdbg_arraydim_t),
|
||||
native_list[idx].args[j].dimcount,
|
||||
spf);
|
||||
}
|
||||
free(native_list[idx].args[j].name);
|
||||
}
|
||||
free(native_list[idx].name);
|
||||
}
|
||||
free(native_list);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgFile])
|
||||
{
|
||||
uint32_t idx;
|
||||
sp_fdbg_file_t dbgfile;
|
||||
AMX_DBG_FILE *_ptr;
|
||||
uint32_t len;
|
||||
for (idx=0; idx<sections[FS_DbgFile]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
||||
len = strlen(_ptr->name);
|
||||
/* 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; idx<sections[FS_DbgLine]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
line = (AMX_DBG_LINE *)dbgptr;
|
||||
/* store */
|
||||
dbgline.addr = (uint32_t)line->address;
|
||||
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; idx<sections[FS_DbgSymbol]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
||||
/* store */
|
||||
dbgsym.addr = (int32_t)sym->address;
|
||||
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; dnum<dbgsym.dimcount; dnum++)
|
||||
{
|
||||
/* get entry info */
|
||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
||||
/* store */
|
||||
dbgdim.size = (uint32_t)dim->size;
|
||||
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;
|
||||
}
|
581
sourcepawn/compiler/pawncc.cpp
Normal file
581
sourcepawn/compiler/pawncc.cpp
Normal file
@ -0,0 +1,581 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#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 <unistd.h>
|
||||
#elif defined WIN32
|
||||
#include <io.h>
|
||||
#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; i<publics; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbtbl[i].address = stub->address;
|
||||
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; i<pubvars; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbvars[i].address = stub->address;
|
||||
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; i<natives; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
nvtbl[i].name = stub->nameofs - (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; i<numTags; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (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; idx<natives; idx++) {
|
||||
sfwrite(&idx, sizeof(uint32_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
|
||||
|
||||
/* Go through arguments */
|
||||
for (j = 0; j < native_list[idx].num_args; j++) {
|
||||
sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
memfile_write(dbgtab,
|
||||
native_list[idx].args[j].name,
|
||||
strlen(native_list[idx].args[j].name) + 1);
|
||||
if (native_list[idx].args[j].dimcount) {
|
||||
sfwrite(native_list[idx].args[j].dims,
|
||||
sizeof(sp_fdbg_arraydim_t),
|
||||
native_list[idx].args[j].dimcount,
|
||||
spf);
|
||||
}
|
||||
free(native_list[idx].args[j].name);
|
||||
}
|
||||
free(native_list[idx].name);
|
||||
}
|
||||
free(native_list);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgFile]) {
|
||||
uint32_t idx;
|
||||
sp_fdbg_file_t dbgfile;
|
||||
AMX_DBG_FILE *_ptr;
|
||||
uint32_t len;
|
||||
for (idx=0; idx<sections[FS_DbgFile]; idx++) {
|
||||
/* get entry info */
|
||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
||||
len = strlen(_ptr->name);
|
||||
/* 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; idx<sections[FS_DbgLine]; idx++) {
|
||||
/* get entry info */
|
||||
line = (AMX_DBG_LINE *)dbgptr;
|
||||
/* store */
|
||||
dbgline.addr = (uint32_t)line->address;
|
||||
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; idx<sections[FS_DbgSymbol]; idx++) {
|
||||
/* get entry info */
|
||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
||||
/* store */
|
||||
dbgsym.addr = (int32_t)sym->address;
|
||||
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; dnum<dbgsym.dimcount; dnum++)
|
||||
{
|
||||
/* get entry info */
|
||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
||||
/* store */
|
||||
dbgdim.size = (uint32_t)dim->size;
|
||||
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
|
@ -357,7 +357,7 @@ typedef struct {
|
||||
/* Tokens recognized by lex()
|
||||
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
|
||||
*/
|
||||
enum {
|
||||
enum TokenKind {
|
||||
/* value of first multi-character operator */
|
||||
tFIRST = 256,
|
||||
/* multi-character operators */
|
||||
@ -431,6 +431,8 @@ enum {
|
||||
tSWITCH,
|
||||
tTAGOF,
|
||||
tTHEN,
|
||||
tTYPEDEF,
|
||||
tUNION,
|
||||
tVOID,
|
||||
tWHILE,
|
||||
/* compiler directives */
|
||||
@ -536,18 +538,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);
|
||||
@ -563,7 +560,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 */
|
||||
@ -579,7 +576,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 */
|
||||
@ -589,161 +586,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.
|
||||
*
|
||||
@ -753,218 +733,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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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[] = {
|
||||
"*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
|
||||
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
||||
"...", "..", "::",
|
||||
@ -1961,7 +1962,8 @@ char *sc_tokens[] = {
|
||||
"public",
|
||||
"return",
|
||||
"sizeof", "sleep", "static", "stock", "struct", "switch",
|
||||
"tagof", "*then",
|
||||
"tagof", "*then", "typedef",
|
||||
"union",
|
||||
"void",
|
||||
"while",
|
||||
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
||||
@ -1969,7 +1971,7 @@ char *sc_tokens[] = {
|
||||
"#tryinclude", "#undef",
|
||||
";", ";", "-integer value-", "-rational value-", "-identifier-",
|
||||
"-label-", "-string-"
|
||||
};
|
||||
};
|
||||
|
||||
static full_token_t *advance_token_ptr()
|
||||
{
|
||||
@ -2000,10 +2002,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 +2055,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 +2260,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 +2277,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 +2287,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 +2306,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 +2339,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 +2353,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 +2380,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 +2408,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 +2441,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 +2483,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<litmax);
|
||||
@ -2497,7 +2498,7 @@ SC_FUNC void litadd(cell value)
|
||||
* Global references: litidx (altered)
|
||||
* litq (altered)
|
||||
*/
|
||||
SC_FUNC void litinsert(cell value,int pos)
|
||||
void litinsert(cell value,int pos)
|
||||
{
|
||||
chk_grow_litq();
|
||||
assert(litidx<litmax);
|
||||
@ -2632,7 +2633,7 @@ static int alpha(char c)
|
||||
*
|
||||
* Test if character "c" is alphanumeric ("a".."z", "0".."9", "_" or "@")
|
||||
*/
|
||||
SC_FUNC int alphanum(char c)
|
||||
int alphanum(char c)
|
||||
{
|
||||
return (alpha(c) || isdigit(c));
|
||||
}
|
||||
@ -2641,7 +2642,7 @@ SC_FUNC int alphanum(char c)
|
||||
*
|
||||
* Test if character "c" is a hexadecimal digit ("0".."9" or "a".."f").
|
||||
*/
|
||||
SC_FUNC int ishex(char c)
|
||||
int ishex(char c)
|
||||
{
|
||||
return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F');
|
||||
}
|
||||
@ -2717,7 +2718,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 +2739,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 +2749,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 +2909,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 +2951,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 +2975,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 +3011,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 +3034,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 +3049,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 +3084,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 +3106,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 +3155,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 +3165,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 +3200,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 +3218,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 +3227,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 +3238,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;
|
@ -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; curarg<t->argcount; 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; i<enum_arg->dimcount; 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; i<enum_arg->tagcount; 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="<main>";
|
||||
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 */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user