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']
|
cxx.cflags += ['-Wno-unused-result']
|
||||||
if have_clang:
|
if have_clang:
|
||||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
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']
|
cxx.cxxflags += ['-Wno-deprecated-register']
|
||||||
else:
|
else:
|
||||||
cxx.cxxflags += ['-Wno-deprecated']
|
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',
|
'smn_console.cpp',
|
||||||
'UserMessages.cpp',
|
'UserMessages.cpp',
|
||||||
'MenuManager.cpp',
|
'MenuManager.cpp',
|
||||||
'smn_core.cpp',
|
|
||||||
'smn_hudtext.cpp',
|
'smn_hudtext.cpp',
|
||||||
'smn_usermsgs.cpp',
|
'smn_usermsgs.cpp',
|
||||||
'MenuStyle_Base.cpp',
|
'MenuStyle_Base.cpp',
|
||||||
@ -53,17 +52,14 @@ for sdk_name in SM.sdks:
|
|||||||
compiler = binary.compiler
|
compiler = binary.compiler
|
||||||
|
|
||||||
if sdk.name == 'csgo':
|
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 += [
|
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', 'engine', 'protobuf'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||||
]
|
]
|
||||||
elif sdk.name == 'dota':
|
elif sdk.name == 'dota':
|
||||||
compiler.cxxincludes += [
|
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', 'engine', 'protobuf'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
||||||
@ -110,6 +106,7 @@ for sdk_name in SM.sdks:
|
|||||||
binary.sources += [
|
binary.sources += [
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
|
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', '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', 'ai_activity.pb.cc'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.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'),
|
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)
|
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;
|
size_t pos = m_curptr - m_pBase;
|
||||||
|
|
||||||
|
*(char *)m_curptr = Raw;
|
||||||
|
m_curptr += sizeof(char);
|
||||||
|
|
||||||
*(size_t *)m_curptr = size;
|
*(size_t *)m_curptr = size;
|
||||||
m_curptr += sizeof(size_t);
|
m_curptr += sizeof(size_t);
|
||||||
|
|
||||||
@ -88,14 +91,17 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_curptr += size;
|
m_curptr += size;
|
||||||
m_size += sizeof(size_t) + size;
|
m_size += sizeof(char) + sizeof(size_t) + size;
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDataPack::PackCell(cell_t cell)
|
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);
|
*(size_t *)m_curptr = sizeof(cell_t);
|
||||||
m_curptr += sizeof(size_t);
|
m_curptr += sizeof(size_t);
|
||||||
@ -103,12 +109,15 @@ void CDataPack::PackCell(cell_t cell)
|
|||||||
*(cell_t *)m_curptr = cell;
|
*(cell_t *)m_curptr = cell;
|
||||||
m_curptr += sizeof(cell_t);
|
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)
|
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);
|
*(size_t *)m_curptr = sizeof(float);
|
||||||
m_curptr += sizeof(size_t);
|
m_curptr += sizeof(size_t);
|
||||||
@ -116,15 +125,18 @@ void CDataPack::PackFloat(float val)
|
|||||||
*(float *)m_curptr = val;
|
*(float *)m_curptr = val;
|
||||||
m_curptr += sizeof(float);
|
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)
|
void CDataPack::PackString(const char *string)
|
||||||
{
|
{
|
||||||
size_t len = strlen(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);
|
CheckSize(maxsize);
|
||||||
|
|
||||||
|
*(char *)m_curptr = String;
|
||||||
|
m_curptr += sizeof(char);
|
||||||
|
|
||||||
// Pack the string length first for buffer overrun checking.
|
// Pack the string length first for buffer overrun checking.
|
||||||
*(size_t *)m_curptr = len;
|
*(size_t *)m_curptr = len;
|
||||||
m_curptr += sizeof(size_t);
|
m_curptr += sizeof(size_t);
|
||||||
@ -160,10 +172,16 @@ bool CDataPack::SetPosition(size_t pos) const
|
|||||||
|
|
||||||
cell_t CDataPack::ReadCell() 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;
|
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))
|
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -178,10 +196,16 @@ cell_t CDataPack::ReadCell() const
|
|||||||
|
|
||||||
float CDataPack::ReadFloat() const
|
float CDataPack::ReadFloat() const
|
||||||
{
|
{
|
||||||
if (!IsReadable(sizeof(size_t) + sizeof(float)))
|
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (*reinterpret_cast<char *>(m_curptr) != Float)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
m_curptr += sizeof(char);
|
||||||
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -201,10 +225,15 @@ bool CDataPack::IsReadable(size_t bytes) const
|
|||||||
|
|
||||||
const char *CDataPack::ReadString(size_t *len) const
|
const char *CDataPack::ReadString(size_t *len) const
|
||||||
{
|
{
|
||||||
if (!IsReadable(sizeof(size_t)))
|
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (*reinterpret_cast<char *>(m_curptr) != String)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m_curptr += sizeof(char);
|
||||||
|
|
||||||
size_t real_len = *(size_t *)m_curptr;
|
size_t real_len = *(size_t *)m_curptr;
|
||||||
|
|
||||||
@ -237,6 +266,11 @@ void *CDataPack::ReadMemory(size_t *size) const
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (*reinterpret_cast<char *>(m_curptr) != Raw)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m_curptr += sizeof(char);
|
||||||
|
|
||||||
size_t bytecount = *(size_t *)m_curptr;
|
size_t bytecount = *(size_t *)m_curptr;
|
||||||
m_curptr += sizeof(size_t);
|
m_curptr += sizeof(size_t);
|
||||||
@ -257,3 +291,43 @@ void *CDataPack::ReadMemory(size_t *size) const
|
|||||||
|
|
||||||
return ptr;
|
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;
|
const char *ReadString(size_t *len) const;
|
||||||
void *GetMemory() const;
|
void *GetMemory() const;
|
||||||
void *ReadMemory(size_t *size) const;
|
void *ReadMemory(size_t *size) const;
|
||||||
|
cell_t ReadFunction() const;
|
||||||
public: //IDataPack
|
public: //IDataPack
|
||||||
void ResetSize();
|
void ResetSize();
|
||||||
void PackCell(cell_t cell);
|
void PackCell(cell_t cell);
|
||||||
void PackFloat(float val);
|
void PackFloat(float val);
|
||||||
void PackString(const char *string);
|
void PackString(const char *string);
|
||||||
size_t CreateMemory(size_t size, void **addr);
|
size_t CreateMemory(size_t size, void **addr);
|
||||||
|
void PackFunction(cell_t function);
|
||||||
public:
|
public:
|
||||||
void Initialize();
|
void Initialize();
|
||||||
private:
|
private:
|
||||||
@ -66,6 +68,14 @@ private:
|
|||||||
mutable char *m_curptr;
|
mutable char *m_curptr;
|
||||||
size_t m_capacity;
|
size_t m_capacity;
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
|
|
||||||
|
enum DataPackType {
|
||||||
|
Raw,
|
||||||
|
Cell,
|
||||||
|
Float,
|
||||||
|
String,
|
||||||
|
Function
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||||
|
@ -383,7 +383,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
|||||||
{
|
{
|
||||||
if (!m_CmdGrps.add(i, group))
|
if (!m_CmdGrps.add(i, group))
|
||||||
return false;
|
return false;
|
||||||
i->value = NoAddRef(new CommandGroup());
|
i->value = new CommandGroup();
|
||||||
}
|
}
|
||||||
Ref<CommandGroup> cmdgroup = i->value;
|
Ref<CommandGroup> cmdgroup = i->value;
|
||||||
|
|
||||||
|
@ -648,8 +648,11 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
|
|||||||
return InvalidQueryCvarCookie;
|
return InvalidQueryCvarCookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConVarQuery query = {cookie, pCallback, (cell_t)hndl, IndexOfEdict(pPlayer)};
|
if (pCallback != NULL)
|
||||||
m_ConVarQueries.push_back(query);
|
{
|
||||||
|
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||||
|
m_ConVarQueries.push_back(query);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return cookie;
|
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)
|
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||||
#endif // SE_DOTA
|
#endif // SE_DOTA
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IPluginFunction *pCallback = NULL;
|
IPluginFunction *pCallback = NULL;
|
||||||
cell_t value = 0;
|
cell_t value = 0;
|
||||||
List<ConVarQuery>::iterator iter;
|
List<ConVarQuery>::iterator iter;
|
||||||
|
@ -195,7 +195,7 @@ class GenericCommandHooker : public IConCommandLinkListener
|
|||||||
size_t index;
|
size_t index;
|
||||||
if (!FindVtable(vtable, 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ public:
|
|||||||
|
|
||||||
if (dispatch.thisptroffs < 0)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ public:
|
|||||||
|
|
||||||
if (!vtables.size())
|
if (!vtables.size())
|
||||||
{
|
{
|
||||||
g_Logger.LogError("Command filter could not find any cvars!");
|
logger->LogError("Command filter could not find any cvars!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ void CoreConfig::Initialize()
|
|||||||
{
|
{
|
||||||
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
||||||
const char *error = textparsers->GetSMCErrorString(err);
|
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)
|
if (err == ConfigResult_Reject)
|
||||||
{
|
{
|
||||||
/* This is a fatal error */
|
/* 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;
|
return SMCResult_Continue;
|
||||||
@ -469,7 +469,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
}
|
}
|
||||||
else
|
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;
|
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 */
|
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()
|
int EventManager::GetEventDebugID()
|
||||||
{
|
{
|
||||||
return EVENT_DEBUG_ID_INIT;
|
return EVENT_DEBUG_ID_INIT;
|
||||||
|
@ -110,7 +110,7 @@ public: // IPluginsListener
|
|||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public: // IGameEventListener2
|
public: // IGameEventListener2
|
||||||
void FireGameEvent(IGameEvent *pEvent);
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||||
int GetEventDebugID();
|
int GetEventDebugID();
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
|
@ -168,7 +168,7 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
if (!addr)
|
if (!addr)
|
||||||
{
|
{
|
||||||
// Key exists so notify if lookup fails, but try other method.
|
// 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
|
else
|
||||||
{
|
{
|
||||||
@ -186,7 +186,7 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
int offset;
|
int offset;
|
||||||
if (!g_pGameConf->GetOffset("gEntList", &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;
|
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 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))
|
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;
|
g_EntList = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
|
|
||||||
if (!g_EntList && !g_pEntInfoList)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ void CHalfLife2::InitCommandLine()
|
|||||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
|
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
|
||||||
if (lib == NULL)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ void CHalfLife2::InitCommandLine()
|
|||||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
|
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
|
||||||
if (lib == NULL)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ void CHalfLife2::InitCommandLine()
|
|||||||
|
|
||||||
if (m_pGetCommandLine == NULL)
|
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 "logic_bridge.h"
|
||||||
#include <sourcemod_version.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 *);
|
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)
|
static void HookLogPrint(const char *message)
|
||||||
{
|
{
|
||||||
g_in_game_log_hook = true;
|
g_in_game_log_hook = true;
|
||||||
@ -104,477 +55,16 @@ static void HookLogPrint(const char *message)
|
|||||||
RETURN_META(MRES_SUPERCEDE);
|
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);
|
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);
|
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)
|
void Engine_LogPrintWrapper(const char *msg)
|
||||||
{
|
{
|
||||||
if (g_in_game_log_hook)
|
if (g_in_game_log_hook)
|
||||||
|
@ -38,76 +38,13 @@
|
|||||||
|
|
||||||
using namespace SourceHook;
|
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
|
public: //SMGlobalClass
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllShutdown();
|
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);
|
void Engine_LogPrintWrapper(const char *msg);
|
||||||
|
|
||||||
extern bool g_in_game_log_hook;
|
|
||||||
extern Logger g_Logger;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "sourcehook.h"
|
#include "sourcehook.h"
|
||||||
#include "sm_srvcmds.h"
|
#include "sm_srvcmds.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
NextMapManager g_NextMap;
|
NextMapManager g_NextMap;
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
|||||||
{
|
{
|
||||||
if (g_forcedChange)
|
if (g_forcedChange)
|
||||||
{
|
{
|
||||||
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
|
logger->LogMessage("[SM] Changed map to \"%s\"", map);
|
||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
|||||||
RETURN_META(MRES_IGNORED);
|
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_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
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 */
|
/* Get the client's language */
|
||||||
if (m_QueryLang)
|
if (m_QueryLang)
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||||
|
#else
|
||||||
const char *name;
|
const char *name;
|
||||||
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
||||||
{
|
{
|
||||||
@ -510,6 +513,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
|||||||
} else {
|
} else {
|
||||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IClientListener *>::iterator iter;
|
List<IClientListener *>::iterator iter;
|
||||||
@ -727,6 +731,13 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
|||||||
}
|
}
|
||||||
pPlayer->Authorize_Post();
|
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)
|
if (playerinfo)
|
||||||
{
|
{
|
||||||
@ -1227,7 +1238,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
|||||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||||
{
|
{
|
||||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
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());
|
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||||
|
|
||||||
pPlayer->Kick("NetworkID spoofing detected.");
|
pPlayer->Kick("NetworkID spoofing detected.");
|
||||||
@ -1862,6 +1873,24 @@ void CmdMaxplayersCallback()
|
|||||||
g_Players.MaxPlayersChanged();
|
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 ***
|
*** PLAYER CODE ***
|
||||||
@ -1886,6 +1915,9 @@ CPlayer::CPlayer()
|
|||||||
m_bIsReplay = false;
|
m_bIsReplay = false;
|
||||||
m_Serial.value = -1;
|
m_Serial.value = -1;
|
||||||
m_SteamAccountID = 0;
|
m_SteamAccountID = 0;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||||
@ -1966,6 +1998,9 @@ void CPlayer::Disconnect()
|
|||||||
m_bIsReplay = false;
|
m_bIsReplay = false;
|
||||||
m_Serial.value = -1;
|
m_Serial.value = -1;
|
||||||
m_SteamAccountID = 0;
|
m_SteamAccountID = 0;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayer::SetName(const char *name)
|
void CPlayer::SetName(const char *name)
|
||||||
|
@ -131,6 +131,9 @@ private:
|
|||||||
bool m_bIsReplay;
|
bool m_bIsReplay;
|
||||||
serial_t m_Serial;
|
serial_t m_Serial;
|
||||||
unsigned int m_SteamAccountID;
|
unsigned int m_SteamAccountID;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
QueryCvarCookie_t m_LanguageCookie;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerManager :
|
class PlayerManager :
|
||||||
@ -211,6 +214,9 @@ public:
|
|||||||
unsigned int GetReplyTo();
|
unsigned int GetReplyTo();
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
unsigned int SetReplyTo(unsigned int reply);
|
||||||
void MaxPlayersChanged(int newvalue = -1);
|
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:
|
private:
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
void OnServerActivate();
|
void OnServerActivate();
|
||||||
|
@ -66,6 +66,8 @@ binary.sources += [
|
|||||||
'sm_trie.cpp',
|
'sm_trie.cpp',
|
||||||
'smn_console.cpp',
|
'smn_console.cpp',
|
||||||
'ProfileTools.cpp',
|
'ProfileTools.cpp',
|
||||||
|
'Logger.cpp',
|
||||||
|
'smn_core.cpp',
|
||||||
]
|
]
|
||||||
if builder.target_platform == 'windows':
|
if builder.target_platform == 'windows':
|
||||||
binary.sources += ['thread/WinThreads.cpp']
|
binary.sources += ['thread/WinThreads.cpp']
|
||||||
|
@ -198,11 +198,11 @@ private:
|
|||||||
|
|
||||||
if (!m_bFileNameLogged)
|
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;
|
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:
|
private:
|
||||||
bool m_bFileNameLogged;
|
bool m_bFileNameLogged;
|
||||||
|
@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
|
|||||||
ke::AutoLock lock(&m_ConfigLock);
|
ke::AutoLock lock(&m_ConfigLock);
|
||||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
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)
|
if (err != SMCError_Custom)
|
||||||
{
|
{
|
||||||
const char *txt = textparsers->GetSMCErrorString(err);
|
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)
|
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;
|
s_OneTimeThreaderErrorMsg = true;
|
||||||
}
|
}
|
||||||
m_Worker = NULL;
|
m_Worker = NULL;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "DebugReporter.h"
|
#include "DebugReporter.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
DebugReport g_DbgReporter;
|
DebugReport g_DbgReporter;
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
|
|||||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||||
va_end(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, ...)
|
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)
|
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 {
|
} 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)
|
if (func_idx != -1)
|
||||||
{
|
{
|
||||||
@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
|||||||
sp_public_t *function;
|
sp_public_t *function;
|
||||||
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
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)
|
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 {
|
} 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;
|
IPluginDebugInfo *pDebug;
|
||||||
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
|
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
|
||||||
{
|
{
|
||||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
g_Logger.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] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||||
_GetPluginIndex(pContext));
|
_GetPluginIndex(pContext));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
const char *name;
|
const char *name;
|
||||||
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
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 {
|
} 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)
|
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,
|
n_err,
|
||||||
error->GetErrorString());
|
error->GetErrorString());
|
||||||
}
|
}
|
||||||
@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
|||||||
const char *custerr;
|
const char *custerr;
|
||||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
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 {
|
} 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())
|
if (!error->DebugInfoAvailable())
|
||||||
{
|
{
|
||||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
g_Logger.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] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||||
_GetPluginIndex(ctx));
|
_GetPluginIndex(ctx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallStackInfo stk_info;
|
CallStackInfo stk_info;
|
||||||
int i = 0;
|
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))
|
while (error->GetTraceInfo(&stk_info))
|
||||||
{
|
{
|
||||||
smcore.LogError("[SM] [%d] Line %d, %s::%s()",
|
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||||
i++,
|
i++,
|
||||||
stk_info.line,
|
stk_info.line,
|
||||||
stk_info.filename,
|
stk_info.filename,
|
||||||
|
@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
|||||||
{
|
{
|
||||||
if (bErrorOnMissing || libsys->IsPathFile(p->GetPath()))
|
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);
|
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()
|
const CVector<IExtension *> *CExtensionManager::ListExtensions()
|
||||||
{
|
{
|
||||||
CVector<IExtension *> *list = new CVector<IExtension *>();
|
CVector<IExtension *> *list = new CVector<IExtension *>();
|
||||||
|
@ -173,6 +173,7 @@ public:
|
|||||||
void AddLibrary(IExtension *pSource, const char *library);
|
void AddLibrary(IExtension *pSource, const char *library);
|
||||||
bool LibraryExists(const char *library);
|
bool LibraryExists(const char *library);
|
||||||
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
|
void CallOnCoreMapEnd();
|
||||||
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
||||||
const CVector<IExtension *> *ListExtensions();
|
const CVector<IExtension *> *ListExtensions();
|
||||||
void FreeExtensionList(const CVector<IExtension *> *list);
|
void FreeExtensionList(const CVector<IExtension *> *list);
|
||||||
|
@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
if (error[0] != '\0')
|
if (error[0] != '\0')
|
||||||
{
|
{
|
||||||
m_IgnoreLevel = 1;
|
m_IgnoreLevel = 1;
|
||||||
smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||||
smcore.LogError("[SM] %s", error);
|
logger->LogError("[SM] %s", error);
|
||||||
} else {
|
} else {
|
||||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
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)
|
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);
|
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||||
smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
|
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||||
}
|
}
|
||||||
m_IgnoreLevel = 1;
|
m_IgnoreLevel = 1;
|
||||||
}
|
}
|
||||||
@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
|||||||
}
|
}
|
||||||
else
|
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) {
|
} else if (strcmp(key, "signature") == 0) {
|
||||||
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
|
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)
|
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
|
||||||
&& (!m_Offsets.retrieve(m_offset)))
|
&& (!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_Class,
|
||||||
m_Prop,
|
m_Prop,
|
||||||
m_CurFile,
|
m_CurFile,
|
||||||
@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
void *final_addr = NULL;
|
void *final_addr = NULL;
|
||||||
if (addrInBase == NULL)
|
if (addrInBase == NULL)
|
||||||
{
|
{
|
||||||
smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||||
s_TempSig.library,
|
s_TempSig.library,
|
||||||
m_CurFile);
|
m_CurFile);
|
||||||
}
|
}
|
||||||
@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
|
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
|
||||||
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
|
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
|
||||||
else
|
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
|
#elif defined PLATFORM_POSIX
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
/* GNU only: returns 0 on error, inconsistent! >:[ */
|
/* 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]);
|
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
} else {
|
} else {
|
||||||
smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||||
s_TempSig.library,
|
s_TempSig.library,
|
||||||
m_File);
|
m_File);
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
s_TempSig.library,
|
||||||
m_File);
|
m_File);
|
||||||
}
|
}
|
||||||
@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
const char *msg = textparsers->GetSMCErrorString(err);
|
const char *msg = textparsers->GetSMCErrorString(err);
|
||||||
|
|
||||||
smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||||
err,
|
err,
|
||||||
state.line,
|
state.line,
|
||||||
state.col,
|
state.col,
|
||||||
@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
const char *msg = textparsers->GetSMCErrorString(err);
|
const char *msg = textparsers->GetSMCErrorString(err);
|
||||||
|
|
||||||
smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||||
err,
|
err,
|
||||||
state.line,
|
state.line,
|
||||||
state.col,
|
state.col,
|
||||||
@ -1082,6 +1082,7 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
pConfig = new CGameConfig(file);
|
pConfig = new CGameConfig(file);
|
||||||
|
pConfig->AddRef();
|
||||||
|
|
||||||
/* :HACKHACK: Don't parse the main config file */
|
/* :HACKHACK: Don't parse the main config file */
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
|
@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||||
smcore.LogFatal(message, ##__VA_ARGS__); \
|
logger->LogFatal(message, ##__VA_ARGS__); \
|
||||||
smcore.LogError(message, ##__VA_ARGS__);
|
logger->LogError(message, ##__VA_ARGS__);
|
||||||
|
|
||||||
bool HandleSystem::TryAndFreeSomeHandles()
|
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 "GameConfigs.h"
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include "Translator.h"
|
#include "Translator.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
CPluginManager g_PluginSys;
|
CPluginManager g_PluginSys;
|
||||||
HandleType_t g_PluginType = 0;
|
HandleType_t g_PluginType = 0;
|
||||||
@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
|||||||
{
|
{
|
||||||
char error[256];
|
char error[256];
|
||||||
libsys->GetPlatformError(error, sizeof(error));
|
libsys->GetPlatformError(error, sizeof(error));
|
||||||
smcore.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
||||||
smcore.LogError("[SM] Platform returned error: %s", error);
|
g_Logger.LogError("[SM] Platform returned error: %s", error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de
|
|||||||
} else {
|
} else {
|
||||||
if (bulletinUrl[0] != '\0')
|
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 {
|
} 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)
|
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->SetErrorState(
|
||||||
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
||||||
"%s",
|
"%s",
|
||||||
@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass()
|
|||||||
error[0] = '\0';
|
error[0] = '\0';
|
||||||
if (!RunSecondPass(pPlugin, error, sizeof(error)))
|
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);
|
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,13 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
|||||||
active_ = nullptr;
|
active_ = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (strcmp(cmdname, "dump") == 0) {
|
||||||
|
if (active_) {
|
||||||
|
// if we have an active profiler, dump it
|
||||||
|
active_->Dump();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args->ArgC() < 4) {
|
if (args->ArgC() < 4) {
|
||||||
if (strcmp(cmdname, "start") == 0) {
|
if (strcmp(cmdname, "start") == 0) {
|
||||||
@ -154,6 +161,15 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
|||||||
StartFromConsole(tool);
|
StartFromConsole(tool);
|
||||||
return;
|
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) {
|
if (strcmp(cmdname, "help") == 0) {
|
||||||
IProfilingTool *tool = FindToolByName(toolname);
|
IProfilingTool *tool = FindToolByName(toolname);
|
||||||
if (!tool) {
|
if (!tool) {
|
||||||
@ -169,5 +185,6 @@ ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArg
|
|||||||
rootmenu->DrawGenericOption("list", "List all available profiling tools.");
|
rootmenu->DrawGenericOption("list", "List all available profiling tools.");
|
||||||
rootmenu->DrawGenericOption("start", "Start a profile with a given tool.");
|
rootmenu->DrawGenericOption("start", "Start a profile with a given tool.");
|
||||||
rootmenu->DrawGenericOption("stop", "Stop the current profile session.");
|
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.");
|
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())
|
if (i.found())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv));
|
Ref<Native> entry = new Native(pOwner, ntv);
|
||||||
m_NtvCache.insert(ntv->name, entry);
|
m_NtvCache.insert(ntv->name, entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n
|
|||||||
|
|
||||||
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
|
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);
|
m_NtvCache.insert(name, entry);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
|
|||||||
|
|
||||||
if (!m_FileLogged)
|
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;
|
m_FileLogged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
smcore.LogError("[SM] %s", buffer);
|
logger->LogError("[SM] %s", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPhraseFile::ReparseFile()
|
void CPhraseFile::ReparseFile()
|
||||||
@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
|
|||||||
msg = m_ParseError.c_str();
|
msg = m_ParseError.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
logger->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] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *code;
|
const char *code;
|
||||||
@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
|
|||||||
msg = m_ParseError.c_str();
|
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,
|
code,
|
||||||
m_File.c_str());
|
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.line,
|
||||||
states.col,
|
states.col,
|
||||||
msg);
|
msg);
|
||||||
@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase()
|
|||||||
str_err = m_CustomError.c_str();
|
str_err = m_CustomError.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path);
|
logger->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] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang))
|
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));
|
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||||
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||||
@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase()
|
|||||||
|
|
||||||
if (!m_Languages.size())
|
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++)
|
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)
|
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;
|
return SMCResult_Continue;
|
||||||
@ -1025,11 +1025,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
|
|||||||
{
|
{
|
||||||
if (fail_phrase != NULL)
|
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
|
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;
|
return false;
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "ForwardSys.h"
|
#include "ForwardSys.h"
|
||||||
#include "AdminCache.h"
|
#include "AdminCache.h"
|
||||||
#include "ProfileTools.h"
|
#include "ProfileTools.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
sm_core_t smcore;
|
sm_core_t smcore;
|
||||||
IHandleSys *handlesys = &g_HandleSys;
|
IHandleSys *handlesys = &g_HandleSys;
|
||||||
@ -72,6 +73,8 @@ ISourcePawnEngine *g_pSourcePawn;
|
|||||||
ISourcePawnEngine2 *g_pSourcePawn2;
|
ISourcePawnEngine2 *g_pSourcePawn2;
|
||||||
CNativeOwner g_CoreNatives;
|
CNativeOwner g_CoreNatives;
|
||||||
IScriptManager *scripts = &g_PluginSys;
|
IScriptManager *scripts = &g_PluginSys;
|
||||||
|
IExtensionSys *extsys = &g_Extensions;
|
||||||
|
ILogger *logger = &g_Logger;
|
||||||
|
|
||||||
static void AddCorePhraseFile(const char *filename)
|
static void AddCorePhraseFile(const char *filename)
|
||||||
{
|
{
|
||||||
@ -140,6 +143,7 @@ static sm_logic_t logic =
|
|||||||
&g_Forwards,
|
&g_Forwards,
|
||||||
&g_Admins,
|
&g_Admins,
|
||||||
NULL,
|
NULL,
|
||||||
|
&g_Logger,
|
||||||
-1.0f
|
-1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ extern IPlayerManager *playerhelpers;
|
|||||||
extern IAdminSystem *adminsys;
|
extern IAdminSystem *adminsys;
|
||||||
extern IGameHelpers *gamehelpers;
|
extern IGameHelpers *gamehelpers;
|
||||||
extern IScriptManager *scripts;
|
extern IScriptManager *scripts;
|
||||||
|
extern IExtensionSys *extsys;
|
||||||
|
extern ILogger *logger;
|
||||||
|
|
||||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
#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
|
* Add 1 to the RHS of this expression to bump the intercom file
|
||||||
* This is to prevent mismatching core/logic binaries
|
* This is to prevent mismatching core/logic binaries
|
||||||
*/
|
*/
|
||||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 28)
|
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29)
|
||||||
|
|
||||||
#if defined SM_LOGIC
|
#if defined SM_LOGIC
|
||||||
class IVEngineServer
|
class IVEngineServer
|
||||||
@ -83,6 +83,7 @@ class IFileSystem_Logic
|
|||||||
public:
|
public:
|
||||||
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
|
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
|
||||||
virtual const char *FindNext(FileFindHandle_t handle) = 0;
|
virtual const char *FindNext(FileFindHandle_t handle) = 0;
|
||||||
|
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
|
||||||
virtual void FindClose(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 FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0;
|
||||||
virtual void Close(FileHandle_t file) = 0;
|
virtual void Close(FileHandle_t file) = 0;
|
||||||
@ -90,6 +91,17 @@ public:
|
|||||||
virtual bool EndOfFile(FileHandle_t file) = 0;
|
virtual bool EndOfFile(FileHandle_t file) = 0;
|
||||||
virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 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 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
|
namespace SourceMod
|
||||||
@ -211,6 +223,15 @@ public:
|
|||||||
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
|
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
|
||||||
virtual const CVector<IExtension *> *ListExtensions() = 0;
|
virtual const CVector<IExtension *> *ListExtensions() = 0;
|
||||||
virtual void FreeExtensionList(const CVector<IExtension *> *list) = 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
|
class AutoPluginList
|
||||||
@ -273,13 +294,10 @@ struct sm_core_t
|
|||||||
ConVar * (*FindConVar)(const char*);
|
ConVar * (*FindConVar)(const char*);
|
||||||
unsigned int (*strncopy)(char*, const char*, size_t);
|
unsigned int (*strncopy)(char*, const char*, size_t);
|
||||||
char * (*TrimWhitespace)(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 (*LogToGame)(const char *message);
|
||||||
void (*ConPrint)(const char *message);
|
void (*ConPrint)(const char *message);
|
||||||
const char * (*GetCvarString)(ConVar*);
|
const char * (*GetCvarString)(ConVar*);
|
||||||
|
bool (*GetCvarBool)(ConVar*);
|
||||||
size_t (*Format)(char*, size_t, const char*, ...);
|
size_t (*Format)(char*, size_t, const char*, ...);
|
||||||
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
|
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
|
||||||
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
|
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);
|
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
|
||||||
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
|
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
|
||||||
IGameConfig * (*GetCoreGameConfig)();
|
IGameConfig * (*GetCoreGameConfig)();
|
||||||
bool (*OnLogPrint)(const char *msg); // true to supercede
|
bool (*OnLogPrint)(const char *msg); // true to supersede
|
||||||
IDebugListener *debugger;
|
IDebugListener *debugger;
|
||||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||||
void (*AddNatives)(sp_nativeinfo_t *natives);
|
void (*AddNatives)(sp_nativeinfo_t *natives);
|
||||||
@ -339,6 +357,7 @@ struct sm_logic_t
|
|||||||
IForwardManager *forwardsys;
|
IForwardManager *forwardsys;
|
||||||
IAdminSystem *adminsys;
|
IAdminSystem *adminsys;
|
||||||
IdentityToken_t *core_ident;
|
IdentityToken_t *core_ident;
|
||||||
|
ILogger *logger;
|
||||||
float sentinel;
|
float sentinel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ private:
|
|||||||
cell_t data_;
|
cell_t data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellTrie : public ke::Refcounted<CellTrie>
|
struct CellTrie
|
||||||
{
|
{
|
||||||
StringHashMap<Entry> map;
|
StringHashMap<Entry> map;
|
||||||
};
|
};
|
||||||
@ -204,8 +204,7 @@ public: //IHandleTypeDispatch
|
|||||||
{
|
{
|
||||||
if (type == htCellTrie)
|
if (type == htCellTrie)
|
||||||
{
|
{
|
||||||
CellTrie *pTrie = (CellTrie *)object;
|
delete (CellTrie *)object;
|
||||||
pTrie->Release();
|
|
||||||
} else {
|
} else {
|
||||||
TrieSnapshot *snapshot = (TrieSnapshot *)object;
|
TrieSnapshot *snapshot = (TrieSnapshot *)object;
|
||||||
delete snapshot;
|
delete snapshot;
|
||||||
|
@ -32,14 +32,14 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "sm_stringutil.h"
|
#include "common_logic.h"
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "TimerSys.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
|
#include <ISourceMod.h>
|
||||||
|
#include <ITranslator.h>
|
||||||
|
|
||||||
|
#include <sourcehook.h>
|
||||||
#include <sh_memory.h>
|
#include <sh_memory.h>
|
||||||
#include "logic_bridge.h"
|
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -50,9 +50,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
HandleType_t g_PlIter;
|
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;
|
IForward *g_OnLogAction = NULL;
|
||||||
|
|
||||||
|
static ConVar *sm_datetime_format = NULL;
|
||||||
|
|
||||||
class CoreNativeHelpers :
|
class CoreNativeHelpers :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IHandleTypeDispatch
|
public IHandleTypeDispatch
|
||||||
@ -75,6 +77,8 @@ public:
|
|||||||
Param_Cell,
|
Param_Cell,
|
||||||
Param_Cell,
|
Param_Cell,
|
||||||
Param_String);
|
Param_String);
|
||||||
|
|
||||||
|
sm_datetime_format = smcore.FindConVar("sm_datetime_format");
|
||||||
}
|
}
|
||||||
void OnHandleDestroy(HandleType_t type, void *object)
|
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);
|
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];
|
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)
|
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)
|
static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
time_t t = GetAdjustedTime();
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
cell_t *addr;
|
cell_t *addr;
|
||||||
pContext->LocalToPhysAddr(params[1], &addr);
|
pContext->LocalToPhysAddr(params[1], &addr);
|
||||||
|
|
||||||
@ -168,14 +172,14 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
if (format == NULL)
|
if (format == NULL)
|
||||||
{
|
{
|
||||||
format = const_cast<char *>(sm_datetime_format.GetString());
|
format = const_cast<char *>(smcore.GetCvarString(sm_datetime_format));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined SUBPLATFORM_SECURECRT
|
#if defined SUBPLATFORM_SECURECRT
|
||||||
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
||||||
#endif
|
#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));
|
size_t written = strftime(buffer, params[2], format, localtime(&t));
|
||||||
|
|
||||||
#if defined SUBPLATFORM_SECURECRT
|
#if defined SUBPLATFORM_SECURECRT
|
||||||
@ -384,7 +388,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
|
|||||||
{
|
{
|
||||||
char buffer[2048];
|
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)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
pPlugin->SetErrorState(Plugin_Error, "%s", str);
|
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];
|
static char temp_file[PLATFORM_MAX_PATH];
|
||||||
char *ptr;
|
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)
|
if ((ptr = strstr(temp_str, ".smx")) != NULL)
|
||||||
{
|
{
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have the raw filename! */
|
/* 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;
|
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)
|
static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||||
|
|
||||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
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);
|
pContext->LocalToString(params[1], &file);
|
||||||
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
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");
|
FILE *fp = fopen(path, "at");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
@ -536,8 +540,8 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
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);
|
pContext->LocalToString(params[1], &file);
|
||||||
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
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");
|
FILE *fp = fopen(path, "at");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
@ -569,8 +573,8 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
@ -653,10 +657,10 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
|
|||||||
char default_message[255];
|
char default_message[255];
|
||||||
SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
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')
|
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;
|
msg = default_message;
|
||||||
}
|
}
|
||||||
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
|
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
|
||||||
@ -743,19 +747,19 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
REGISTER_NATIVES(coreNatives)
|
REGISTER_NATIVES(coreNatives)
|
||||||
{
|
{
|
||||||
{"AutoExecConfig", AutoExecConfig},
|
{"ThrowError", ThrowError},
|
||||||
{"GetPluginFilename", GetPluginFilename},
|
|
||||||
{"GetPluginInfo", GetPluginInfo},
|
|
||||||
{"GetPluginIterator", GetPluginIterator},
|
|
||||||
{"GetPluginStatus", GetPluginStatus},
|
|
||||||
{"GetSysTickCount", GetSysTickCount},
|
|
||||||
{"GetTime", GetTime},
|
{"GetTime", GetTime},
|
||||||
{"IsPluginDebugging", IsPluginDebugging},
|
{"FormatTime", FormatTime},
|
||||||
|
{"GetPluginIterator", GetPluginIterator},
|
||||||
{"MorePlugins", MorePlugins},
|
{"MorePlugins", MorePlugins},
|
||||||
{"ReadPlugin", ReadPlugin},
|
{"ReadPlugin", ReadPlugin},
|
||||||
{"ThrowError", ThrowError},
|
{"GetPluginStatus", GetPluginStatus},
|
||||||
|
{"GetPluginFilename", GetPluginFilename},
|
||||||
|
{"IsPluginDebugging", IsPluginDebugging},
|
||||||
|
{"GetPluginInfo", GetPluginInfo},
|
||||||
{"SetFailState", SetFailState},
|
{"SetFailState", SetFailState},
|
||||||
{"FormatTime", FormatTime},
|
{"GetSysTickCount", GetSysTickCount},
|
||||||
|
{"AutoExecConfig", AutoExecConfig},
|
||||||
{"MarkNativeAsOptional", MarkNativeAsOptional},
|
{"MarkNativeAsOptional", MarkNativeAsOptional},
|
||||||
{"RegPluginLibrary", RegPluginLibrary},
|
{"RegPluginLibrary", RegPluginLibrary},
|
||||||
{"LibraryExists", LibraryExists},
|
{"LibraryExists", LibraryExists},
|
||||||
@ -770,5 +774,4 @@ REGISTER_NATIVES(coreNatives)
|
|||||||
{"LoadFromAddress", LoadFromAddress},
|
{"LoadFromAddress", LoadFromAddress},
|
||||||
{"StoreToAddress", StoreToAddress},
|
{"StoreToAddress", StoreToAddress},
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
@ -148,6 +148,27 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
|
|||||||
return 1;
|
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)
|
static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
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);
|
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.");
|
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);
|
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.");
|
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;
|
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)
|
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||||
@ -318,9 +363,11 @@ REGISTER_NATIVES(datapacknatives)
|
|||||||
{"WritePackCell", smn_WritePackCell},
|
{"WritePackCell", smn_WritePackCell},
|
||||||
{"WritePackFloat", smn_WritePackFloat},
|
{"WritePackFloat", smn_WritePackFloat},
|
||||||
{"WritePackString", smn_WritePackString},
|
{"WritePackString", smn_WritePackString},
|
||||||
|
{"WritePackFunction", smn_WritePackFunction},
|
||||||
{"ReadPackCell", smn_ReadPackCell},
|
{"ReadPackCell", smn_ReadPackCell},
|
||||||
{"ReadPackFloat", smn_ReadPackFloat},
|
{"ReadPackFloat", smn_ReadPackFloat},
|
||||||
{"ReadPackString", smn_ReadPackString},
|
{"ReadPackString", smn_ReadPackString},
|
||||||
|
{"ReadPackFunction", smn_ReadPackFunction},
|
||||||
{"ResetPack", smn_ResetPack},
|
{"ResetPack", smn_ResetPack},
|
||||||
{"GetPackPosition", smn_GetPackPosition},
|
{"GetPackPosition", smn_GetPackPosition},
|
||||||
{"SetPackPosition", smn_SetPackPosition},
|
{"SetPackPosition", smn_SetPackPosition},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -202,8 +202,8 @@ public:
|
|||||||
{
|
{
|
||||||
errmsg = "Unknown error";
|
errmsg = "Unknown error";
|
||||||
}
|
}
|
||||||
smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
logger->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] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ public: //ICommandTargetProcessor
|
|||||||
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
|
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
|
||||||
AutoHandleCloner ahc(hndl, sec);
|
AutoHandleCloner ahc(hndl, sec);
|
||||||
if (ahc.getClone() == BAD_HANDLE) {
|
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;
|
delete array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,7 @@ IExtensionSys *extsys;
|
|||||||
IHandleSys *handlesys;
|
IHandleSys *handlesys;
|
||||||
IForwardManager *forwardsys;
|
IForwardManager *forwardsys;
|
||||||
IAdminSystem *adminsys;
|
IAdminSystem *adminsys;
|
||||||
|
ILogger *logger;
|
||||||
|
|
||||||
class VEngineServer_Logic : public IVEngineServer_Logic
|
class VEngineServer_Logic : public IVEngineServer_Logic
|
||||||
{
|
{
|
||||||
@ -146,6 +147,10 @@ public:
|
|||||||
{
|
{
|
||||||
return filesystem->FindNext(handle);
|
return filesystem->FindNext(handle);
|
||||||
}
|
}
|
||||||
|
bool FindIsDirectory(FileFindHandle_t handle)
|
||||||
|
{
|
||||||
|
return filesystem->FindIsDirectory(handle);
|
||||||
|
}
|
||||||
void FindClose(FileFindHandle_t handle)
|
void FindClose(FileFindHandle_t handle)
|
||||||
{
|
{
|
||||||
filesystem->FindClose(handle);
|
filesystem->FindClose(handle);
|
||||||
@ -174,6 +179,50 @@ public:
|
|||||||
{
|
{
|
||||||
return filesystem->Size(pFileName, pPathID);
|
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;
|
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_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_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)
|
static ConVar *find_convar(const char *name)
|
||||||
{
|
{
|
||||||
return icvar->FindVar(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)
|
static void log_to_game(const char *message)
|
||||||
{
|
{
|
||||||
Engine_LogPrintWrapper(message);
|
Engine_LogPrintWrapper(message);
|
||||||
@ -306,6 +322,11 @@ static const char *get_cvar_string(ConVar* cvar)
|
|||||||
return cvar->GetString();
|
return cvar->GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_cvar_bool(ConVar* cvar)
|
||||||
|
{
|
||||||
|
return cvar->GetBool();
|
||||||
|
}
|
||||||
|
|
||||||
static bool get_game_name(char *buffer, size_t maxlength)
|
static bool get_game_name(char *buffer, size_t maxlength)
|
||||||
{
|
{
|
||||||
KeyValues *pGameInfo = new KeyValues("GameInfo");
|
KeyValues *pGameInfo = new KeyValues("GameInfo");
|
||||||
@ -561,13 +582,10 @@ static sm_core_t core_bridge =
|
|||||||
find_convar,
|
find_convar,
|
||||||
strncopy,
|
strncopy,
|
||||||
UTIL_TrimWhitespace,
|
UTIL_TrimWhitespace,
|
||||||
log_error,
|
|
||||||
log_fatal,
|
|
||||||
log_message,
|
|
||||||
log_to_file,
|
|
||||||
log_to_game,
|
log_to_game,
|
||||||
conprint,
|
conprint,
|
||||||
get_cvar_string,
|
get_cvar_string,
|
||||||
|
get_cvar_bool,
|
||||||
UTIL_Format,
|
UTIL_Format,
|
||||||
UTIL_FormatArgs,
|
UTIL_FormatArgs,
|
||||||
gnprintf,
|
gnprintf,
|
||||||
@ -636,6 +654,7 @@ void InitLogicBridge()
|
|||||||
handlesys = logicore.handlesys;
|
handlesys = logicore.handlesys;
|
||||||
forwardsys = logicore.forwardsys;
|
forwardsys = logicore.forwardsys;
|
||||||
adminsys = logicore.adminsys;
|
adminsys = logicore.adminsys;
|
||||||
|
logger = logicore.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartLogicBridge(char *error, size_t maxlength)
|
bool StartLogicBridge(char *error, size_t maxlength)
|
||||||
|
@ -48,5 +48,6 @@ extern IExtensionSys *extsys;
|
|||||||
extern IHandleSys *handlesys;
|
extern IHandleSys *handlesys;
|
||||||
extern IForwardManager *forwardsys;
|
extern IForwardManager *forwardsys;
|
||||||
extern IAdminSystem *adminsys;
|
extern IAdminSystem *adminsys;
|
||||||
|
extern ILogger *logger;
|
||||||
|
|
||||||
#endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */
|
#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)
|
if (strcasecmp(name, "sm") == 0)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("Request to register \"sm\" command denied.");
|
logger->LogError("Request to register \"sm\" command denied.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
|
|||||||
/* This shouldn't happen */
|
/* This shouldn't happen */
|
||||||
if (!iface)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +395,7 @@ void SourceModBase::LevelShutdown()
|
|||||||
{
|
{
|
||||||
g_pOnMapEnd->Execute(NULL);
|
g_pOnMapEnd->Execute(NULL);
|
||||||
}
|
}
|
||||||
|
extsys->CallOnCoreMapEnd();
|
||||||
|
|
||||||
g_Timers.RemoveMapChangeTimers();
|
g_Timers.RemoveMapChangeTimers();
|
||||||
|
|
||||||
@ -572,9 +573,9 @@ void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
|||||||
|
|
||||||
if (tag)
|
if (tag)
|
||||||
{
|
{
|
||||||
g_Logger.LogMessage("[%s] %s", tag, buffer);
|
logger->LogMessage("[%s] %s", tag, buffer);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogMessage("%s", buffer);
|
logger->LogMessage("%s", buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,9 +592,9 @@ void SourceModBase::LogError(IExtension *pExt, const char *format, ...)
|
|||||||
|
|
||||||
if (tag)
|
if (tag)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[%s] %s", tag, buffer);
|
logger->LogError("[%s] %s", tag, buffer);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogError("%s", buffer);
|
logger->LogError("%s", buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,14 @@ VProfTool::Stop(void (*render)(const char *fmt, ...))
|
|||||||
RenderHelp(render);
|
RenderHelp(render);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VProfTool::Dump()
|
||||||
|
{
|
||||||
|
g_VProfCurrentProfile.Pause();
|
||||||
|
g_VProfCurrentProfile.OutputReport(VPRT_FULL);
|
||||||
|
g_VProfCurrentProfile.Resume();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VProfTool::IsActive()
|
VProfTool::IsActive()
|
||||||
{
|
{
|
||||||
@ -105,5 +113,5 @@ VProfTool::LeaveScope()
|
|||||||
void
|
void
|
||||||
VProfTool::RenderHelp(void (*render)(const char *fmt, ...))
|
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;
|
const char *Description() KE_OVERRIDE;
|
||||||
bool Start() KE_OVERRIDE;
|
bool Start() KE_OVERRIDE;
|
||||||
void Stop(void (*render)(const char *fmt, ...)) KE_OVERRIDE;
|
void Stop(void (*render)(const char *fmt, ...)) KE_OVERRIDE;
|
||||||
|
void Dump() KE_OVERRIDE;
|
||||||
bool IsActive() KE_OVERRIDE;
|
bool IsActive() KE_OVERRIDE;
|
||||||
bool IsAttached() KE_OVERRIDE;
|
bool IsAttached() KE_OVERRIDE;
|
||||||
void EnterScope(const char *group, const char *name) KE_OVERRIDE;
|
void EnterScope(const char *group, const char *name) KE_OVERRIDE;
|
||||||
|
@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect()
|
|||||||
char error[256];
|
char error[256];
|
||||||
int errCode = 0;
|
int errCode = 0;
|
||||||
|
|
||||||
Database = Newborn<IDatabase>(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||||
|
|
||||||
if (!Database)
|
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)
|
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)
|
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)
|
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)
|
if (!x)
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
}
|
}
|
||||||
"FireBullets"
|
"FireBullets"
|
||||||
{
|
{
|
||||||
"windows" "112"
|
"windows" "113"
|
||||||
"linux" "113"
|
"linux" "114"
|
||||||
"mac" "113"
|
"mac" "114"
|
||||||
}
|
}
|
||||||
"OnTakeDamage"
|
"OnTakeDamage"
|
||||||
{
|
{
|
||||||
@ -24,15 +24,15 @@
|
|||||||
}
|
}
|
||||||
"PreThink"
|
"PreThink"
|
||||||
{
|
{
|
||||||
"windows" "331"
|
"windows" "333"
|
||||||
"linux" "332"
|
"linux" "334"
|
||||||
"mac" "332"
|
"mac" "334"
|
||||||
}
|
}
|
||||||
"PostThink"
|
"PostThink"
|
||||||
{
|
{
|
||||||
"windows" "332"
|
"windows" "334"
|
||||||
"linux" "333"
|
"linux" "335"
|
||||||
"mac" "333"
|
"mac" "335"
|
||||||
}
|
}
|
||||||
"SetTransmit"
|
"SetTransmit"
|
||||||
{
|
{
|
||||||
@ -78,39 +78,39 @@
|
|||||||
}
|
}
|
||||||
"VPhysicsUpdate"
|
"VPhysicsUpdate"
|
||||||
{
|
{
|
||||||
"windows" "157"
|
"windows" "158"
|
||||||
"linux" "158"
|
"linux" "159"
|
||||||
"mac" "158"
|
"mac" "159"
|
||||||
}
|
}
|
||||||
"Weapon_CanSwitchTo"
|
"Weapon_CanSwitchTo"
|
||||||
{
|
{
|
||||||
"windows" "265"
|
"windows" "267"
|
||||||
"linux" "266"
|
"linux" "268"
|
||||||
"mac" "266"
|
"mac" "268"
|
||||||
}
|
}
|
||||||
"Weapon_CanUse"
|
"Weapon_CanUse"
|
||||||
{
|
{
|
||||||
"windows" "259"
|
"windows" "261"
|
||||||
"linux" "260"
|
"linux" "262"
|
||||||
"mac" "260"
|
"mac" "262"
|
||||||
}
|
}
|
||||||
"Weapon_Drop"
|
"Weapon_Drop"
|
||||||
|
{
|
||||||
|
"windows" "264"
|
||||||
|
"linux" "265"
|
||||||
|
"mac" "265"
|
||||||
|
}
|
||||||
|
"Weapon_Equip"
|
||||||
{
|
{
|
||||||
"windows" "262"
|
"windows" "262"
|
||||||
"linux" "263"
|
"linux" "263"
|
||||||
"mac" "263"
|
"mac" "263"
|
||||||
}
|
}
|
||||||
"Weapon_Equip"
|
|
||||||
{
|
|
||||||
"windows" "260"
|
|
||||||
"linux" "261"
|
|
||||||
"mac" "261"
|
|
||||||
}
|
|
||||||
"Weapon_Switch"
|
"Weapon_Switch"
|
||||||
{
|
{
|
||||||
"windows" "263"
|
"windows" "265"
|
||||||
"linux" "264"
|
"linux" "266"
|
||||||
"mac" "264"
|
"mac" "266"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@
|
|||||||
}
|
}
|
||||||
"PreThink"
|
"PreThink"
|
||||||
{
|
{
|
||||||
"windows" "344"
|
"windows" "345"
|
||||||
"linux" "345"
|
"linux" "346"
|
||||||
"mac" "345"
|
"mac" "346"
|
||||||
}
|
}
|
||||||
"PostThink"
|
"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 */
|
/* SetUserInfo data */
|
||||||
"#default"
|
"#default"
|
||||||
{
|
{
|
||||||
|
@ -131,57 +131,57 @@
|
|||||||
{
|
{
|
||||||
"GiveNamedItem"
|
"GiveNamedItem"
|
||||||
{
|
{
|
||||||
"windows" "400"
|
"windows" "402"
|
||||||
"linux" "401"
|
"linux" "403"
|
||||||
"mac" "401"
|
"mac" "403"
|
||||||
}
|
}
|
||||||
"RemovePlayerItem"
|
"RemovePlayerItem"
|
||||||
|
{
|
||||||
|
"windows" "271"
|
||||||
|
"linux" "272"
|
||||||
|
"mac" "272"
|
||||||
|
}
|
||||||
|
"Weapon_GetSlot"
|
||||||
{
|
{
|
||||||
"windows" "269"
|
"windows" "269"
|
||||||
"linux" "270"
|
"linux" "270"
|
||||||
"mac" "270"
|
"mac" "270"
|
||||||
}
|
}
|
||||||
"Weapon_GetSlot"
|
|
||||||
{
|
|
||||||
"windows" "267"
|
|
||||||
"linux" "268"
|
|
||||||
"mac" "268"
|
|
||||||
}
|
|
||||||
"Ignite"
|
"Ignite"
|
||||||
{
|
{
|
||||||
"windows" "208"
|
"windows" "210"
|
||||||
"linux" "209"
|
"linux" "211"
|
||||||
"mac" "209"
|
"mac" "211"
|
||||||
}
|
}
|
||||||
"Extinguish"
|
"Extinguish"
|
||||||
{
|
{
|
||||||
"windows" "212"
|
"windows" "214"
|
||||||
"linux" "213"
|
"linux" "215"
|
||||||
"mac" "213"
|
"mac" "215"
|
||||||
}
|
}
|
||||||
"Teleport"
|
"Teleport"
|
||||||
{
|
{
|
||||||
"windows" "108"
|
"windows" "109"
|
||||||
"linux" "109"
|
"linux" "110"
|
||||||
"mac" "109"
|
"mac" "110"
|
||||||
}
|
}
|
||||||
"CommitSuicide"
|
"CommitSuicide"
|
||||||
{
|
{
|
||||||
"windows" "442"
|
"windows" "444"
|
||||||
"linux" "442"
|
"linux" "444"
|
||||||
"mac" "442"
|
"mac" "444"
|
||||||
}
|
}
|
||||||
"GetVelocity"
|
"GetVelocity"
|
||||||
{
|
{
|
||||||
"windows" "140"
|
"windows" "141"
|
||||||
"linux" "141"
|
"linux" "142"
|
||||||
"mac" "141"
|
"mac" "142"
|
||||||
}
|
}
|
||||||
"EyeAngles"
|
"EyeAngles"
|
||||||
{
|
{
|
||||||
"windows" "131"
|
"windows" "132"
|
||||||
"linux" "132"
|
"linux" "133"
|
||||||
"mac" "132"
|
"mac" "133"
|
||||||
}
|
}
|
||||||
"AcceptInput"
|
"AcceptInput"
|
||||||
{
|
{
|
||||||
@ -197,9 +197,9 @@
|
|||||||
}
|
}
|
||||||
"WeaponEquip"
|
"WeaponEquip"
|
||||||
{
|
{
|
||||||
"windows" "260"
|
"windows" "262"
|
||||||
"linux" "261"
|
"linux" "263"
|
||||||
"mac" "261"
|
"mac" "263"
|
||||||
}
|
}
|
||||||
"Activate"
|
"Activate"
|
||||||
{
|
{
|
||||||
@ -209,15 +209,15 @@
|
|||||||
}
|
}
|
||||||
"PlayerRunCmd"
|
"PlayerRunCmd"
|
||||||
{
|
{
|
||||||
"windows" "418"
|
"windows" "420"
|
||||||
"linux" "419"
|
"linux" "421"
|
||||||
"mac" "419"
|
"mac" "421"
|
||||||
}
|
}
|
||||||
"GiveAmmo"
|
"GiveAmmo"
|
||||||
{
|
{
|
||||||
"windows" "251"
|
"windows" "253"
|
||||||
"linux" "252"
|
"linux" "254"
|
||||||
"mac" "252"
|
"mac" "254"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,9 +131,9 @@
|
|||||||
{
|
{
|
||||||
"GiveNamedItem"
|
"GiveNamedItem"
|
||||||
{
|
{
|
||||||
"windows" "412"
|
"windows" "413"
|
||||||
"linux" "413"
|
"linux" "414"
|
||||||
"mac" "413"
|
"mac" "414"
|
||||||
}
|
}
|
||||||
"RemovePlayerItem"
|
"RemovePlayerItem"
|
||||||
{
|
{
|
||||||
@ -167,9 +167,9 @@
|
|||||||
}
|
}
|
||||||
"CommitSuicide"
|
"CommitSuicide"
|
||||||
{
|
{
|
||||||
"windows" "451"
|
"windows" "452"
|
||||||
"linux" "451"
|
"linux" "452"
|
||||||
"mac" "451"
|
"mac" "452"
|
||||||
}
|
}
|
||||||
"GetVelocity"
|
"GetVelocity"
|
||||||
{
|
{
|
||||||
@ -209,9 +209,9 @@
|
|||||||
}
|
}
|
||||||
"PlayerRunCmd"
|
"PlayerRunCmd"
|
||||||
{
|
{
|
||||||
"windows" "430"
|
"windows" "431"
|
||||||
"linux" "431"
|
"linux" "432"
|
||||||
"mac" "431"
|
"mac" "432"
|
||||||
}
|
}
|
||||||
"GiveAmmo"
|
"GiveAmmo"
|
||||||
{
|
{
|
||||||
|
@ -118,18 +118,21 @@ LoadBanReasons()
|
|||||||
decl String:sectionName[255];
|
decl String:sectionName[255];
|
||||||
if(!KvGetSectionName(g_hKvBanReasons, sectionName, sizeof(sectionName)))
|
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)
|
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
|
//Reset kvHandle
|
||||||
KvRewind(g_hKvBanReasons);
|
KvRewind(g_hKvBanReasons);
|
||||||
} else {
|
} 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.
|
* @param maxlen Max length of the output buffer.
|
||||||
* @noreturn
|
* @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.
|
* 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.
|
* @param clients Array to fill with unique, valid client indexes.
|
||||||
* @return True if pattern was recognized, false otherwise.
|
* @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().
|
* 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
|
* @return An Action value. Not handling the command
|
||||||
* means that Source will report it as "not found."
|
* 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.
|
* 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
|
* @return An Action value. Not handling the command
|
||||||
* means that Source will report it as "not found."
|
* 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.
|
* 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.
|
* @param newValue String containing the new value of the convar.
|
||||||
* @noreturn
|
* @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.
|
* 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);
|
native GetConVarName(Handle:convar, String:name[], maxlength);
|
||||||
|
|
||||||
funcenum ConVarQueryFinished
|
union ConVarQueryFinished
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Called when a query to retrieve a client's console variable has finished.
|
* 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.
|
* @param value Value that was passed when query was started.
|
||||||
* @noreturn
|
* @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.
|
* 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.
|
* @param convarValue Value of client convar that was queried if successful. This will be "" if it was not.
|
||||||
* @noreturn
|
* @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.
|
* @param argc Argument count.
|
||||||
* @return Action to take (see extended notes above).
|
* @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"
|
#define FEATURECAP_COMMANDLISTENER "command listener"
|
||||||
|
|
||||||
|
@ -72,6 +72,16 @@ native WritePackFloat(Handle:pack, Float:val);
|
|||||||
*/
|
*/
|
||||||
native WritePackString(Handle:pack, const String:str[]);
|
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.
|
* Reads a cell from a data pack.
|
||||||
*
|
*
|
||||||
@ -101,6 +111,15 @@ native Float:ReadPackFloat(Handle:pack);
|
|||||||
*/
|
*/
|
||||||
native ReadPackString(Handle:pack, String:buffer[], maxlen);
|
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.
|
* 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.
|
* @param data Data passed in via the original threaded invocation.
|
||||||
* @noreturn
|
* @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
|
* 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().
|
* @param queryData An array of each data value passed to SQL_AddQuery().
|
||||||
* @noreturn
|
* @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.
|
* 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().
|
* @param queryData An array of each data value passed to SQL_AddQuery().
|
||||||
* @noreturn
|
* @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.
|
* Adds a query to a transaction object.
|
||||||
|
@ -48,7 +48,7 @@ enum EventHookMode
|
|||||||
/**
|
/**
|
||||||
* Hook function types for events.
|
* Hook function types for events.
|
||||||
*/
|
*/
|
||||||
funcenum EventHook
|
union EventHook
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Called when a game event is fired.
|
* 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.
|
* @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.
|
* @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.
|
* 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.
|
* @param dontBroadcast True if event was not broadcast to clients, false otherwise.
|
||||||
* @noreturn
|
* @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.
|
* @note OpenDirectory() supports the "file://" notation.
|
||||||
*
|
*
|
||||||
* @param path Path to open.
|
* @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.
|
* @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.
|
* 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 file File to open.
|
||||||
* @param mode Open mode.
|
* @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.
|
* @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.
|
* Deletes a file.
|
||||||
*
|
*
|
||||||
* @param path Path of the file to delete.
|
* @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.
|
* Reads a line from a text file.
|
||||||
@ -304,28 +319,38 @@ native FilePosition(Handle:file);
|
|||||||
* @param path Path to the file.
|
* @param path Path to the file.
|
||||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
* @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
|
* 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.
|
* 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.
|
* @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.
|
* Renames a file.
|
||||||
*
|
*
|
||||||
* @param newpath New path to the file.
|
* @param newpath New path to the file.
|
||||||
* @param oldpath Path to the existing 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.
|
* Checks if a directory exists.
|
||||||
*
|
*
|
||||||
* @param path Path to the directory.
|
* @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.
|
* @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.
|
* Get the file size in bytes.
|
||||||
@ -333,18 +358,20 @@ native bool:DirExists(const String:path[]);
|
|||||||
* @param path Path to the file.
|
* @param path Path to the file.
|
||||||
* @param use_valve_fs If true, the Valve file system will be used instead.
|
* @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
|
* 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.
|
* 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.
|
* @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
|
* Flushes a file's buffered output; any buffered output
|
||||||
* is immediately written to the file.
|
* is immediately written to the file.
|
||||||
*
|
*
|
||||||
* @param file Handle 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);
|
native FlushFile(Handle:file);
|
||||||
|
|
||||||
@ -373,8 +400,22 @@ native bool:RemoveDir(const String:path[]);
|
|||||||
* @param path Path to create.
|
* @param path Path to create.
|
||||||
* @param mode Permissions (default is o=rx,g=rx,u=rwx). Note that folders must have
|
* @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.
|
* 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.
|
* Returns a file timestamp as a unix timestamp.
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define _float_included
|
#define _float_included
|
||||||
|
|
||||||
|
#if !defined __sourcepawn2__
|
||||||
/**
|
/**
|
||||||
* Converts an integer into a floating point value.
|
* Converts an integer into a floating point value.
|
||||||
*
|
*
|
||||||
@ -42,6 +43,7 @@
|
|||||||
* @return Floating point value.
|
* @return Floating point value.
|
||||||
*/
|
*/
|
||||||
native Float:float(value);
|
native Float:float(value);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies two floats together.
|
* Multiplies two floats together.
|
||||||
|
@ -357,7 +357,7 @@ native Call_Cancel();
|
|||||||
* @param numParams Number of parameters passed to the native.
|
* @param numParams Number of parameters passed to the native.
|
||||||
* @return Value for the native call to return.
|
* @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
|
* 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.
|
* @param data Data passed to the RequestFrame native.
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
functag public void RequestFrameCallback(any:data);
|
typedef RequestFrameCallback = function void (any data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a single use Next Frame hook.
|
* Creates a single use Next Frame hook.
|
||||||
|
@ -59,7 +59,6 @@ native SetGlobalTransTarget(client);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the language number of a client.
|
* Retrieves the language number of a client.
|
||||||
* Currently this simply returns the server language index.
|
|
||||||
*
|
*
|
||||||
* @param client Client index.
|
* @param client Client index.
|
||||||
* @return Language number client is using.
|
* @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
|
* @return Plugin_Handled or Plugin_Stop will prevent the message
|
||||||
* from being written to the log file.
|
* 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.
|
* Adds a game log hook.
|
||||||
|
@ -151,7 +151,7 @@ enum MenuSource
|
|||||||
* @param param1 First action parameter (usually the client).
|
* @param param1 First action parameter (usually the client).
|
||||||
* @param param2 Second action parameter (usually the item).
|
* @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.
|
* Creates a new, empty menu using the default style.
|
||||||
@ -527,12 +527,14 @@ stock bool:VoteMenuToAll(Handle:menu, time, flags=0)
|
|||||||
* defines.
|
* defines.
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
functag public void VoteHandler(Menu:menu,
|
typedef VoteHandler = function void (
|
||||||
num_votes,
|
Menu menu,
|
||||||
num_clients,
|
int num_votes,
|
||||||
const client_info[][2],
|
int num_clients,
|
||||||
num_items,
|
const int client_info[][2],
|
||||||
const item_info[][2]);
|
int num_items,
|
||||||
|
const int item_info[][2]
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an advanced vote handling callback. If this callback is set,
|
* Sets an advanced vote handling callback. If this callback is set,
|
||||||
|
@ -197,91 +197,91 @@ enum UseType
|
|||||||
Use_Toggle
|
Use_Toggle
|
||||||
};
|
};
|
||||||
|
|
||||||
funcenum SDKHookCB
|
union SDKHookCB
|
||||||
{
|
{
|
||||||
// PreThink/Post
|
// PreThink/Post
|
||||||
// PostThink/Post
|
// PostThink/Post
|
||||||
public(client),
|
function void (int client);
|
||||||
|
|
||||||
// Spawn
|
// Spawn
|
||||||
Action:public(entity),
|
function Action (int entity);
|
||||||
|
|
||||||
// GroundEntChanged
|
// GroundEntChanged
|
||||||
// SpawnPost
|
// SpawnPost
|
||||||
// Think/Post
|
// Think/Post
|
||||||
// VPhysicsUpdate/Post
|
// VPhysicsUpdate/Post
|
||||||
public(entity),
|
function void (int entity);
|
||||||
|
|
||||||
// EndTouch
|
// EndTouch
|
||||||
// StartTouch
|
// StartTouch
|
||||||
// Touch
|
// Touch
|
||||||
// Blocked
|
// Blocked
|
||||||
Action:public(entity, other),
|
function Action (int entity, int other);
|
||||||
|
|
||||||
// EndTouchPost
|
// EndTouchPost
|
||||||
// StartTouchPost
|
// StartTouchPost
|
||||||
// TouchPost
|
// TouchPost
|
||||||
public(entity, other),
|
function void (int entity, int other);
|
||||||
|
|
||||||
// SetTransmit
|
// SetTransmit
|
||||||
Action:public(entity, client),
|
function Action (int entity, int client);
|
||||||
|
|
||||||
// WeaponCanSwitchTo
|
// WeaponCanSwitchTo
|
||||||
// WeaponCanUse
|
// WeaponCanUse
|
||||||
// WeaponDrop
|
// WeaponDrop
|
||||||
// WeaponEquip
|
// WeaponEquip
|
||||||
// WeaponSwitch
|
// WeaponSwitch
|
||||||
Action:public(client, weapon),
|
function Action (int client, int weapon);
|
||||||
|
|
||||||
// WeaponCanSwitchToPost
|
// WeaponCanSwitchToPost
|
||||||
// WeaponCanUsePost
|
// WeaponCanUsePost
|
||||||
// WeaponDropPost
|
// WeaponDropPost
|
||||||
// WeaponEquipPost
|
// WeaponEquipPost
|
||||||
// WeaponSwitchPost
|
// WeaponSwitchPost
|
||||||
public(client, weapon),
|
function void (int client, int weapon);
|
||||||
|
|
||||||
// GetMaxHealth (ep2v and later)
|
// GetMaxHealth (ep2v and later)
|
||||||
Action:public(entity, &maxhealth),
|
function Action (int entity, int &maxhealth);
|
||||||
|
|
||||||
// OnTakeDamage
|
// OnTakeDamage
|
||||||
// Note: The weapon parameter is not used by all games and damage sources.
|
// Note: The weapon parameter is not used by all games and damage sources.
|
||||||
// Note: Force application is dependent on game and damage type(s)
|
// Note: Force application is dependent on game and damage type(s)
|
||||||
// SDKHooks 1.0+
|
// 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+
|
// 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.
|
// 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
|
// DON'T attempt to access 'damagecustom' var if feature status != available
|
||||||
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon,
|
function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon,
|
||||||
Float:damageForce[3], Float:damagePosition[3], damagecustom),
|
float[3] damageForce, float[3] damagePosition, int damagecustom);
|
||||||
|
|
||||||
// OnTakeDamagePost
|
// OnTakeDamagePost
|
||||||
public(victim, attacker, inflictor, Float:damage, damagetype),
|
function void (int victim, int attacker, int inflictor, float damage, int 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, const float[3] damageForce, const float[3] damagePosition);
|
||||||
|
|
||||||
// FireBulletsPost
|
// FireBulletsPost
|
||||||
public(client, shots, const String:weaponname[]),
|
function void (int client, int shots, const char[] weaponname);
|
||||||
|
|
||||||
// TraceAttack
|
// 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
|
// 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
|
// ShouldCollide
|
||||||
bool:public(entity, collisiongroup, contentsmask, bool:originalResult),
|
function bool (int entity, int collisiongroup, int contentsmask, bool originalResult);
|
||||||
|
|
||||||
// Use
|
// Use
|
||||||
Action:public(entity, activator, caller, UseType:type, Float:value),
|
function Action (int entity, int activator, int caller, UseType type, float value);
|
||||||
|
|
||||||
// UsePost
|
// UsePost
|
||||||
public(entity, activator, caller, UseType:type, Float:value),
|
function void (int entity, int activator, int caller, UseType type, float value);
|
||||||
|
|
||||||
// Reload
|
// Reload
|
||||||
Action:public(weapon),
|
function Action (int weapon);
|
||||||
|
|
||||||
// Reload post
|
// 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.
|
* @param delay Delay in seconds? before the event gets fired.
|
||||||
* @noreturn
|
* @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
|
* 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,
|
* @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
|
||||||
* Plugin_Changed when any parameter has been modified.
|
* 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.
|
* 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,
|
* @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
|
||||||
* Plugin_Changed when any parameter has been modified.
|
* 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.
|
* Hooks all played ambient sounds.
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
* @param delay Delay in seconds to send the TE.
|
* @param delay Delay in seconds to send the TE.
|
||||||
* @return Plugin_Continue to allow the transmission of the TE, Plugin_Stop to block it.
|
* @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.
|
* 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. */
|
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.
|
* Called on entity filtering.
|
||||||
@ -119,7 +119,7 @@ funcenum TraceEntityFilter
|
|||||||
* @param contentsMask Contents Mask.
|
* @param contentsMask Contents Mask.
|
||||||
* @return True to allow the current entity to be hit, otherwise false.
|
* @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.
|
* Called on entity filtering.
|
||||||
@ -129,7 +129,7 @@ funcenum TraceEntityFilter
|
|||||||
* @param data Data value, if used.
|
* @param data Data value, if used.
|
||||||
* @return True to allow the current entity to be hit, otherwise false.
|
* @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.
|
* @param pos Vector buffer to store data in.
|
||||||
* @return True if outside world, otherwise false.
|
* @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
|
* 0 if first is equal to second
|
||||||
* 1 if first should go after 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.
|
* 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
|
* 0 if first is equal to second
|
||||||
* 1 if first should go after second
|
* 1 if first should go after second
|
||||||
*/
|
*/
|
||||||
funcenum SortFunc2D
|
union SortFunc2D
|
||||||
{
|
{
|
||||||
public(elem1[], elem2[], const array[][], Handle:hndl),
|
function int (int[] elem1, int[] elem2, const int[][] array, Handle hndl);
|
||||||
public(String:elem1[], String:elem2[], const String: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
|
* 0 if first is equal to second
|
||||||
* 1 if first should go after 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.
|
* 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.
|
* @param hndl Optional Handle to pass through the comparison calls.
|
||||||
* @noreturn
|
* @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.
|
* @param smc The SMC Parse Handle.
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
functag public void SMC_ParseStart(Handle:smc);
|
typedef SMC_ParseStart = function void (Handle smc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the SMC_ParseStart function of a parse Handle.
|
* 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.
|
* @param failed True if parsing failed, false otherwise.
|
||||||
* @noreturn
|
* @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.
|
* 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.
|
* @param opt_quotes True if the section name was quote-enclosed in the file.
|
||||||
* @return An SMCResult action to take.
|
* @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.
|
* 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.
|
* @param value_quotes Whether or not the value was enclosed in quotes.
|
||||||
* @return An SMCResult action to take.
|
* @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.
|
* 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.
|
* @param smc The SMC Parse Handle.
|
||||||
* @return An SMCResult action to take.
|
* @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.
|
* 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.
|
* @param lineno The line number it occurs on.
|
||||||
* @return An SMCResult action to take.
|
* @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.
|
* Sets a raw line reader on an SMC parser Handle.
|
||||||
|
@ -153,6 +153,10 @@ enum TFCond
|
|||||||
TFCond_HalloweenTiny,
|
TFCond_HalloweenTiny,
|
||||||
TFCond_HalloweenInHell,
|
TFCond_HalloweenInHell,
|
||||||
TFCond_HalloweenGhostMode,
|
TFCond_HalloweenGhostMode,
|
||||||
|
|
||||||
|
TFCond_DodgeChance = 79,
|
||||||
|
TFCond_Parachute,
|
||||||
|
TFCond_BlastJumping,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Float:TFCondDuration_Infinite = -1.0;
|
const Float:TFCondDuration_Infinite = -1.0;
|
||||||
@ -447,5 +451,6 @@ public __ext_tf2_SetNTVOptional()
|
|||||||
MarkNativeAsOptional("TF2_GetClass");
|
MarkNativeAsOptional("TF2_GetClass");
|
||||||
MarkNativeAsOptional("TF2_IsPlayerInDuel");
|
MarkNativeAsOptional("TF2_IsPlayerInDuel");
|
||||||
MarkNativeAsOptional("TF2_IsHolidayActive");
|
MarkNativeAsOptional("TF2_IsHolidayActive");
|
||||||
|
MarkNativeAsOptional("TF2_RemoveWearable");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -249,6 +249,7 @@ enum {
|
|||||||
TF_WEAPON_SPELLBOOK,
|
TF_WEAPON_SPELLBOOK,
|
||||||
TF_WEAPON_SPELLBOOK_PROJECTILE,
|
TF_WEAPON_SPELLBOOK_PROJECTILE,
|
||||||
TF_WEAPON_SNIPERRIFLE_CLASSIC,
|
TF_WEAPON_SNIPERRIFLE_CLASSIC,
|
||||||
|
TF_WEAPON_PARACHUTE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TF2 Weapon Loadout Slots
|
// TF2 Weapon Loadout Slots
|
||||||
@ -435,6 +436,20 @@ stock TF2_RemoveWeaponSlot(client, slot)
|
|||||||
new weaponIndex;
|
new weaponIndex;
|
||||||
while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1)
|
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);
|
RemovePlayerItem(client, weaponIndex);
|
||||||
AcceptEntityInput(weaponIndex, "Kill");
|
AcceptEntityInput(weaponIndex, "Kill");
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
/**
|
/**
|
||||||
* Any of the following prototypes will work for a timed function.
|
* Any of the following prototypes will work for a timed function.
|
||||||
*/
|
*/
|
||||||
funcenum Timer
|
union Timer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Called when the timer interval has elapsed.
|
* 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
|
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||||
* default behavior.
|
* default behavior.
|
||||||
*/
|
*/
|
||||||
Action:public(Handle:timer, Handle:hndl),
|
function Action(Handle timer, Handle hndl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the timer interval has elapsed.
|
* 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
|
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||||
* default behavior.
|
* default behavior.
|
||||||
*/
|
*/
|
||||||
Action:public(Handle:timer, any:data),
|
function Action(Handle timer, any data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the timer interval has elapsed.
|
* 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
|
* @return Plugin_Stop to stop a repeating timer, any other value for
|
||||||
* default behavior.
|
* default behavior.
|
||||||
*/
|
*/
|
||||||
Action:public(Handle:timer),
|
function Action(Handle timer);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,12 +127,14 @@ enum TopMenuObject
|
|||||||
* @param maxlength Output buffer (if used).
|
* @param maxlength Output buffer (if used).
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
functag public void TopMenuHandler(Handle:topmenu,
|
typedef TopMenuHandler = function void (
|
||||||
TopMenuAction:action,
|
Handle topmenu,
|
||||||
TopMenuObject:topobj_id,
|
TopMenuAction action,
|
||||||
param,
|
TopMenuObject topobj_id,
|
||||||
String:buffer[],
|
int param,
|
||||||
maxlength);
|
char[] buffer,
|
||||||
|
int maxlength
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a TopMenu.
|
* Creates a TopMenu.
|
||||||
|
@ -140,7 +140,7 @@ native EndMessage();
|
|||||||
* blocks the message from being sent, and Plugin_Continue
|
* blocks the message from being sent, and Plugin_Continue
|
||||||
* resumes normal functionality.
|
* 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.
|
* 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.
|
* @param sent True if message was sent, false if blocked.
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
functag public void MsgPostHook(UserMsg:msg_id, bool:sent);
|
typedef MsgPostHook = function void (UserMsg msg_id, bool sent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks a user message.
|
* Hooks a user message.
|
||||||
|
@ -113,6 +113,13 @@ namespace SourceMod
|
|||||||
* @return Pointer to the data, or NULL if out of bounds.
|
* @return Pointer to the data, or NULL if out of bounds.
|
||||||
*/
|
*/
|
||||||
virtual void *ReadMemory(size_t *size) const =0;
|
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.
|
* @return Current position of the stream beforehand.
|
||||||
*/
|
*/
|
||||||
virtual size_t CreateMemory(size_t size, void **addr) =0;
|
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.
|
* V6 - added TestFeature() to IShareSys.
|
||||||
* V7 - added OnDependenciesDropped() to IExtensionInterface.
|
* 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.
|
* @brief The interface an extension must expose.
|
||||||
@ -325,6 +326,15 @@ namespace SourceMod
|
|||||||
virtual void OnDependenciesDropped()
|
virtual void OnDependenciesDropped()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on level shutdown
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void OnCoreMapEnd()
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,12 +35,15 @@
|
|||||||
|
|
||||||
namespace ke {
|
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>
|
template <typename T>
|
||||||
class RefcountedThreadsafe
|
class RefcountedThreadsafe
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RefcountedThreadsafe()
|
RefcountedThreadsafe()
|
||||||
: refcount_(1)
|
: refcount_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,18 +37,28 @@ namespace ke {
|
|||||||
|
|
||||||
template <typename T> class Ref;
|
template <typename T> class Ref;
|
||||||
|
|
||||||
// Holds a refcounted T without addrefing it. This is similar to PassRef<>
|
// Objects in AMTL inheriting from Refcounted will have an initial refcount
|
||||||
// below, but is intended only for freshly allocated objects which start
|
// of 0. However, in some systems (such as COM), the initial refcount is 1,
|
||||||
// with reference count 1, and we don't want to add an extra ref just by
|
// or functions may return raw pointers that have been AddRef'd. In these
|
||||||
// assigning to PassRef<> or Ref<>.
|
// 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>
|
template <typename T>
|
||||||
class Newborn
|
class AlreadyRefed
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Newborn(T *t)
|
AlreadyRefed(T *t)
|
||||||
: thing_(t)
|
: thing_(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
~AlreadyRefed() {
|
||||||
|
if (thing_)
|
||||||
|
thing_->Release();
|
||||||
|
}
|
||||||
|
|
||||||
T *release() const {
|
T *release() const {
|
||||||
return ReturnAndVoid(thing_);
|
return ReturnAndVoid(thing_);
|
||||||
@ -59,10 +69,10 @@ class Newborn
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline Newborn<T>
|
static inline AlreadyRefed<T>
|
||||||
NoAddRef(T *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,
|
// 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())
|
: thing_(other.release())
|
||||||
{
|
{
|
||||||
// Don't addref, newborn means already addref'd.
|
// Don't addref, newborn means already addref'd.
|
||||||
@ -134,7 +151,7 @@ class PassRef
|
|||||||
private:
|
private:
|
||||||
// Disallowed operators.
|
// Disallowed operators.
|
||||||
PassRef &operator =(T *other);
|
PassRef &operator =(T *other);
|
||||||
PassRef &operator =(Newborn<T> &other);
|
PassRef &operator =(AlreadyRefed<T> &other);
|
||||||
|
|
||||||
void AddRef() {
|
void AddRef() {
|
||||||
if (thing_)
|
if (thing_)
|
||||||
@ -149,13 +166,18 @@ class PassRef
|
|||||||
mutable T *thing_;
|
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>
|
template <typename T>
|
||||||
class Refcounted
|
class Refcounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Refcounted()
|
Refcounted()
|
||||||
: refcount_(1)
|
: refcount_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +239,12 @@ class Ref
|
|||||||
: thing_(other.release())
|
: 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())
|
: thing_(other.release())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -255,7 +282,7 @@ class Ref
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
Ref &operator =(const Newborn<S> &other) {
|
Ref &operator =(const AlreadyRefed<S> &other) {
|
||||||
Release();
|
Release();
|
||||||
thing_ = other.release();
|
thing_ = other.release();
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -1044,6 +1044,15 @@ namespace SourcePawn
|
|||||||
* @param render Function to render any help messages.
|
* @param render Function to render any help messages.
|
||||||
*/
|
*/
|
||||||
virtual void Stop(void (*render)(const char *fmt, ...)) = 0;
|
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.
|
* @brief Returns whether or not the profiler is currently profiling.
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
* @file sp_vm_types.h
|
* @file sp_vm_types.h
|
||||||
* @brief Contains all run-time SourcePawn structures.
|
* @brief Contains all run-time SourcePawn structures.
|
||||||
*/
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
#include "sp_file_headers.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint32_t ucell_t; /**< Unsigned 32bit integer */
|
typedef uint32_t ucell_t; /**< Unsigned 32bit integer */
|
||||||
typedef int32_t cell_t; /**< Basic 32bit signed integer type for plugins */
|
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 */
|
uint32_t line; /**< Line number */
|
||||||
} sp_debug_line_t;
|
} sp_debug_line_t;
|
||||||
|
|
||||||
/**
|
// Occurs after an fdbg_symbol entry, for each dimension.
|
||||||
* @brief These structures are equivalent.
|
typedef struct sp_debug_arraydim_s
|
||||||
*/
|
{
|
||||||
typedef sp_fdbg_arraydim_t sp_debug_arraydim_t;
|
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
|
* @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
|
typedef struct sp_debug_symbol_s
|
||||||
{
|
{
|
||||||
uint32_t codestart; /**< Relocated code address */
|
uint32_t codestart; /**< Relocated code address */
|
||||||
uint32_t codeend; /**< Relocated code end address */
|
uint32_t codeend; /**< Relocated code end address */
|
||||||
const char * name; /**< Relocated name */
|
const char * name; /**< Relocated name */
|
||||||
sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */
|
sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */
|
||||||
sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */
|
sp_debug_symbol_raw_t *sym; /**< Pointer to original symbol */
|
||||||
} sp_debug_symbol_t;
|
} sp_debug_symbol_t;
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||||
|
@ -42,6 +42,7 @@ binary = SM.Program(builder, 'spcomp')
|
|||||||
compiler = binary.compiler
|
compiler = binary.compiler
|
||||||
compiler.includes += [
|
compiler.includes += [
|
||||||
os.path.join(builder.sourcePath, 'public'),
|
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, 'public', 'sourcepawn'),
|
||||||
os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'),
|
os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'),
|
||||||
os.path.join(builder.buildPath, 'includes'),
|
os.path.join(builder.buildPath, 'includes'),
|
||||||
@ -50,7 +51,8 @@ compiler.includes += [
|
|||||||
compiler.sourcedeps += packed_includes
|
compiler.sourcedeps += packed_includes
|
||||||
|
|
||||||
if compiler.cc.behavior == 'gcc':
|
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':
|
if builder.target_platform == 'linux':
|
||||||
compiler.postlink += ['-lgcc', '-lm']
|
compiler.postlink += ['-lgcc', '-lm']
|
||||||
elif compiler.cc.behavior == 'msvc':
|
elif compiler.cc.behavior == 'msvc':
|
||||||
@ -58,10 +60,10 @@ elif compiler.cc.behavior == 'msvc':
|
|||||||
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
||||||
compiler.cxxflags.remove('/TP')
|
compiler.cxxflags.remove('/TP')
|
||||||
|
|
||||||
|
compiler.defines += ['HAVE_STDINT_H']
|
||||||
if builder.target_platform == 'linux':
|
if builder.target_platform == 'linux':
|
||||||
compiler.defines += [
|
compiler.defines += [
|
||||||
'LINUX',
|
'LINUX',
|
||||||
'HAVE_STDINT_H',
|
|
||||||
'AMX_ANSIONLY',
|
'AMX_ANSIONLY',
|
||||||
'ENABLE_BINRELOC',
|
'ENABLE_BINRELOC',
|
||||||
'_GNU_SOURCE'
|
'_GNU_SOURCE'
|
||||||
@ -69,32 +71,31 @@ if builder.target_platform == 'linux':
|
|||||||
elif builder.target_platform == 'mac':
|
elif builder.target_platform == 'mac':
|
||||||
compiler.defines += [
|
compiler.defines += [
|
||||||
'DARWIN',
|
'DARWIN',
|
||||||
'HAVE_STDINT_H',
|
|
||||||
'AMX_ANSIONLY',
|
'AMX_ANSIONLY',
|
||||||
'ENABLE_BINRELOC',
|
'ENABLE_BINRELOC',
|
||||||
'HAVE_SAFESTR'
|
'HAVE_SAFESTR'
|
||||||
]
|
]
|
||||||
|
|
||||||
binary.sources += [
|
binary.sources += [
|
||||||
'libpawnc.c',
|
'libpawnc.cpp',
|
||||||
'lstring.c',
|
'lstring.cpp',
|
||||||
'memfile.c',
|
'memfile.cpp',
|
||||||
'pawncc.c',
|
'pawncc.cpp',
|
||||||
'sc1.c',
|
'sc1.cpp',
|
||||||
'sc2.c',
|
'sc2.cpp',
|
||||||
'sc3.c',
|
'sc3.cpp',
|
||||||
'sc4.c',
|
'sc4.cpp',
|
||||||
'sc5.c',
|
'sc5.cpp',
|
||||||
'sc6.c',
|
'sc6.cpp',
|
||||||
'sc7.c',
|
'sc7.cpp',
|
||||||
'scexpand.c',
|
'scexpand.cpp',
|
||||||
'sci18n.c',
|
'sci18n.cpp',
|
||||||
'sclist.c',
|
'sclist.cpp',
|
||||||
'scmemfil.c',
|
'scmemfil.cpp',
|
||||||
'scstate.c',
|
'scstate.cpp',
|
||||||
'sctracker.c',
|
'sctracker.cpp',
|
||||||
'scvars.c',
|
'scvars.cpp',
|
||||||
'sp_file.c',
|
'sp_file.cpp',
|
||||||
'zlib/adler32.c',
|
'zlib/adler32.c',
|
||||||
'zlib/compress.c',
|
'zlib/compress.c',
|
||||||
'zlib/crc32.c',
|
'zlib/crc32.c',
|
||||||
@ -107,7 +108,7 @@ binary.sources += [
|
|||||||
'zlib/trees.c',
|
'zlib/trees.c',
|
||||||
'zlib/uncompr.c',
|
'zlib/uncompr.c',
|
||||||
'zlib/zutil.c',
|
'zlib/zutil.c',
|
||||||
'sp_symhash.c'
|
'sp_symhash.cpp'
|
||||||
]
|
]
|
||||||
if builder.target_platform != 'windows':
|
if builder.target_platform != 'windows':
|
||||||
binary.sources.append('binreloc.c')
|
binary.sources.append('binreloc.c')
|
||||||
|
@ -34,8 +34,12 @@
|
|||||||
#include <sclinux.h>
|
#include <sclinux.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined HAVE_STDINT_H
|
||||||
|
# include <stddef.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
#include <stdint.h>
|
|
||||||
#if !defined HAVE_STDINT_H
|
#if !defined HAVE_STDINT_H
|
||||||
#define HAVE_STDINT_H
|
#define HAVE_STDINT_H
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,173 +1,173 @@
|
|||||||
/* Abstract Machine for the Pawn compiler, debugger support
|
/* Abstract Machine for the Pawn compiler, debugger support
|
||||||
*
|
*
|
||||||
* This file contains extra definitions that are convenient for debugger
|
* This file contains extra definitions that are convenient for debugger
|
||||||
* support.
|
* support.
|
||||||
*
|
*
|
||||||
* Copyright (c) ITB CompuPhase, 2005
|
* Copyright (c) ITB CompuPhase, 2005
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty.
|
* 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
|
* In no event will the authors be held liable for any damages arising from
|
||||||
* the use of this software.
|
* the use of this software.
|
||||||
*
|
*
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
* including commercial applications, and to alter it and redistribute it
|
* including commercial applications, and to alter it and redistribute it
|
||||||
* freely, subject to the following restrictions:
|
* freely, subject to the following restrictions:
|
||||||
*
|
*
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
* 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
|
* claim that you wrote the original software. If you use this software in
|
||||||
* a product, an acknowledgment in the product documentation would be
|
* a product, an acknowledgment in the product documentation would be
|
||||||
* appreciated but is not required.
|
* appreciated but is not required.
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
* misrepresented as being the original software.
|
* misrepresented as being the original software.
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*
|
*
|
||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AMXDBG_H_INCLUDED
|
#ifndef AMXDBG_H_INCLUDED
|
||||||
#define AMXDBG_H_INCLUDED
|
#define AMXDBG_H_INCLUDED
|
||||||
|
|
||||||
#ifndef AMX_H_INCLUDED
|
#ifndef AMX_H_INCLUDED
|
||||||
#include "amx.h"
|
#include "amx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
/* 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...
|
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||||
*/
|
*/
|
||||||
#if defined SN_TARGET_PS2 || defined __GNUC__
|
#if defined SN_TARGET_PS2 || defined __GNUC__
|
||||||
#define AMX_NO_ALIGN
|
#define AMX_NO_ALIGN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
#define PACKED __attribute__((packed))
|
#define PACKED __attribute__((packed))
|
||||||
#else
|
#else
|
||||||
#define PACKED
|
#define PACKED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined AMX_NO_ALIGN
|
#if !defined AMX_NO_ALIGN
|
||||||
#if defined LINUX || defined __FreeBSD__
|
#if defined LINUX || defined __FreeBSD__
|
||||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||||
#elif defined MACOS && defined __MWERKS__
|
#elif defined MACOS && defined __MWERKS__
|
||||||
#pragma options align=mac68k
|
#pragma options align=mac68k
|
||||||
#else
|
#else
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||||
#if defined __TURBOC__
|
#if defined __TURBOC__
|
||||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_HDR {
|
typedef struct tagAMX_DBG_HDR {
|
||||||
int32_t size PACKED; /* size of the debug information chunk */
|
int32_t size PACKED; /* size of the debug information chunk */
|
||||||
uint16_t magic PACKED; /* signature, must be 0xf1ef */
|
uint16_t magic PACKED; /* signature, must be 0xf1ef */
|
||||||
char file_version; /* file format version */
|
char file_version; /* file format version */
|
||||||
char amx_version; /* required version of the AMX */
|
char amx_version; /* required version of the AMX */
|
||||||
int16_t flags PACKED; /* currently unused */
|
int16_t flags PACKED; /* currently unused */
|
||||||
int16_t files PACKED; /* number of entries in the "file" table */
|
int16_t files PACKED; /* number of entries in the "file" table */
|
||||||
int32_t lines PACKED; /* number of entries in the "line" table */
|
int32_t lines PACKED; /* number of entries in the "line" table */
|
||||||
int32_t symbols PACKED; /* number of entries in the "symbol" 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 tags PACKED; /* number of entries in the "tag" table */
|
||||||
int16_t automatons PACKED; /* number of entries in the "automaton" table */
|
int16_t automatons PACKED; /* number of entries in the "automaton" table */
|
||||||
int16_t states PACKED; /* number of entries in the "state" table */
|
int16_t states PACKED; /* number of entries in the "state" table */
|
||||||
} PACKED AMX_DBG_HDR;
|
} PACKED AMX_DBG_HDR;
|
||||||
#define AMX_DBG_MAGIC 0xf1ef
|
#define AMX_DBG_MAGIC 0xf1ef
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_FILE {
|
typedef struct tagAMX_DBG_FILE {
|
||||||
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
|
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
|
||||||
const char name[1]; /* ASCII string, zero-terminated */
|
char name[1]; /* ASCII string, zero-terminated */
|
||||||
} PACKED AMX_DBG_FILE;
|
} PACKED AMX_DBG_FILE;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_LINE {
|
typedef struct tagAMX_DBG_LINE {
|
||||||
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
|
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
|
||||||
int32_t line PACKED; /* line number */
|
int32_t line PACKED; /* line number */
|
||||||
} PACKED AMX_DBG_LINE;
|
} PACKED AMX_DBG_LINE;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_SYMBOL {
|
typedef struct tagAMX_DBG_SYMBOL {
|
||||||
ucell address PACKED; /* address in the data segment or relative to the frame */
|
ucell address PACKED; /* address in the data segment or relative to the frame */
|
||||||
int16_t tag PACKED; /* tag for the symbol */
|
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 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) */
|
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
|
||||||
char ident; /* kind of symbol (function/variable) */
|
char ident; /* kind of symbol (function/variable) */
|
||||||
char vclass; /* class of symbol (global/local) */
|
char vclass; /* class of symbol (global/local) */
|
||||||
int16_t dim PACKED; /* number of dimensions */
|
int16_t dim PACKED; /* number of dimensions */
|
||||||
const char name[1]; /* ASCII string, zero-terminated */
|
char name[1]; /* ASCII string, zero-terminated */
|
||||||
} PACKED AMX_DBG_SYMBOL;
|
} PACKED AMX_DBG_SYMBOL;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_SYMDIM {
|
typedef struct tagAMX_DBG_SYMDIM {
|
||||||
int16_t tag PACKED; /* tag for the array dimension */
|
int16_t tag PACKED; /* tag for the array dimension */
|
||||||
ucell size PACKED; /* size of the array dimension */
|
ucell size PACKED; /* size of the array dimension */
|
||||||
} PACKED AMX_DBG_SYMDIM;
|
} PACKED AMX_DBG_SYMDIM;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_TAG {
|
typedef struct tagAMX_DBG_TAG {
|
||||||
int16_t tag PACKED; /* tag id */
|
int16_t tag PACKED; /* tag id */
|
||||||
const char name[1]; /* ASCII string, zero-terminated */
|
char name[1]; /* ASCII string, zero-terminated */
|
||||||
} PACKED AMX_DBG_TAG;
|
} PACKED AMX_DBG_TAG;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_MACHINE {
|
typedef struct tagAMX_DBG_MACHINE {
|
||||||
int16_t automaton PACKED; /* automaton id */
|
int16_t automaton PACKED; /* automaton id */
|
||||||
ucell address PACKED; /* address of state variable */
|
ucell address PACKED; /* address of state variable */
|
||||||
const char name[1]; /* ASCII string, zero-terminated */
|
char name[1]; /* ASCII string, zero-terminated */
|
||||||
} PACKED AMX_DBG_MACHINE;
|
} PACKED AMX_DBG_MACHINE;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG_STATE {
|
typedef struct tagAMX_DBG_STATE {
|
||||||
int16_t state PACKED; /* state id */
|
int16_t state PACKED; /* state id */
|
||||||
int16_t automaton PACKED; /* automaton id */
|
int16_t automaton PACKED; /* automaton id */
|
||||||
const char name[1]; /* ASCII string, zero-terminated */
|
char name[1]; /* ASCII string, zero-terminated */
|
||||||
} PACKED AMX_DBG_STATE;
|
} PACKED AMX_DBG_STATE;
|
||||||
|
|
||||||
typedef struct tagAMX_DBG {
|
typedef struct tagAMX_DBG {
|
||||||
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
|
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
|
||||||
AMX_DBG_FILE _FAR **filetbl PACKED;
|
AMX_DBG_FILE _FAR **filetbl PACKED;
|
||||||
AMX_DBG_LINE _FAR *linetbl PACKED;
|
AMX_DBG_LINE _FAR *linetbl PACKED;
|
||||||
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
|
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
|
||||||
AMX_DBG_TAG _FAR **tagtbl PACKED;
|
AMX_DBG_TAG _FAR **tagtbl PACKED;
|
||||||
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
|
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
|
||||||
AMX_DBG_STATE _FAR **statetbl PACKED;
|
AMX_DBG_STATE _FAR **statetbl PACKED;
|
||||||
} PACKED AMX_DBG;
|
} PACKED AMX_DBG;
|
||||||
|
|
||||||
#if !defined iVARIABLE
|
#if !defined iVARIABLE
|
||||||
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||||
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
||||||
#define iARRAY 3
|
#define iARRAY 3
|
||||||
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||||
#define iFUNCTN 9
|
#define iFUNCTN 9
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
|
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
|
||||||
int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr);
|
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_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
|
||||||
int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
|
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_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_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_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_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
|
||||||
int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, 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_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_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);
|
int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
|
||||||
|
|
||||||
|
|
||||||
#if !defined AMX_NO_ALIGN
|
#if !defined AMX_NO_ALIGN
|
||||||
#if defined LINUX || defined __FreeBSD__
|
#if defined LINUX || defined __FreeBSD__
|
||||||
#pragma pack() /* reset default packing */
|
#pragma pack() /* reset default packing */
|
||||||
#elif defined MACOS && defined __MWERKS__
|
#elif defined MACOS && defined __MWERKS__
|
||||||
#pragma options align=reset
|
#pragma options align=reset
|
||||||
#else
|
#else
|
||||||
#pragma pack(pop) /* reset previous packing */
|
#pragma pack(pop) /* reset previous packing */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* AMXDBG_H_INCLUDED */
|
#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).
|
* will be copied. Always NUL terminates (unless siz == 0).
|
||||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||||
*/
|
*/
|
||||||
size_t
|
extern "C" size_t
|
||||||
strlcpy(char *dst, const char *src, size_t siz)
|
strlcpy(char *dst, const char *src, size_t siz)
|
||||||
{
|
{
|
||||||
char *d = dst;
|
char *d = dst;
|
||||||
@ -93,7 +93,7 @@ strlcpy(char *dst, const char *src, size_t siz)
|
|||||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
* If retval >= siz, truncation occurred.
|
* If retval >= siz, truncation occurred.
|
||||||
*/
|
*/
|
||||||
size_t
|
extern "C" size_t
|
||||||
strlcat(char *dst, const char *src, size_t siz)
|
strlcat(char *dst, const char *src, size_t siz)
|
||||||
{
|
{
|
||||||
char *d = dst;
|
char *d = dst;
|
@ -9,10 +9,18 @@
|
|||||||
|
|
||||||
#if !defined HAVE_SAFESTR
|
#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);
|
strlcpy(char *dst, const char *src, size_t siz);
|
||||||
|
|
||||||
size_t
|
EXPORT size_t
|
||||||
strlcat(char *dst, const char *src, size_t siz);
|
strlcat(char *dst, const char *src, size_t siz);
|
||||||
|
|
||||||
|
#undef EXPORT
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,4 +52,15 @@ long memfile_tell(memfile_t *mf);
|
|||||||
*/
|
*/
|
||||||
void memfile_reset(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
|
#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()
|
/* Tokens recognized by lex()
|
||||||
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
|
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
|
||||||
*/
|
*/
|
||||||
enum {
|
enum TokenKind {
|
||||||
/* value of first multi-character operator */
|
/* value of first multi-character operator */
|
||||||
tFIRST = 256,
|
tFIRST = 256,
|
||||||
/* multi-character operators */
|
/* multi-character operators */
|
||||||
@ -431,6 +431,8 @@ enum {
|
|||||||
tSWITCH,
|
tSWITCH,
|
||||||
tTAGOF,
|
tTAGOF,
|
||||||
tTHEN,
|
tTHEN,
|
||||||
|
tTYPEDEF,
|
||||||
|
tUNION,
|
||||||
tVOID,
|
tVOID,
|
||||||
tWHILE,
|
tWHILE,
|
||||||
/* compiler directives */
|
/* compiler directives */
|
||||||
@ -536,18 +538,13 @@ typedef enum s_optmark {
|
|||||||
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
|
#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
|
* Functions you call from the "driver" program
|
||||||
*/
|
*/
|
||||||
int pc_compile(int argc, char **argv);
|
int pc_compile(int argc, char **argv);
|
||||||
int pc_addconstant(char *name,cell value,int tag);
|
int pc_addconstant(const char *name,cell value,int tag);
|
||||||
int pc_addtag(char *name);
|
int pc_addtag(const char *name);
|
||||||
int pc_addtag_flags(char *name, int flags);
|
int pc_addtag_flags(const char *name, int flags);
|
||||||
int pc_findtag(const char *name);
|
int pc_findtag(const char *name);
|
||||||
constvalue *pc_tagptr(const char *name);
|
constvalue *pc_tagptr(const char *name);
|
||||||
int pc_enablewarning(int number,int enable);
|
int pc_enablewarning(int number,int enable);
|
||||||
@ -563,7 +560,7 @@ const char *type_to_name(int tag);
|
|||||||
int pc_printf(const char *message,...);
|
int pc_printf(const char *message,...);
|
||||||
|
|
||||||
/* error report function */
|
/* 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 */
|
/* input from source file */
|
||||||
void *pc_opensrc(char *filename); /* reading only */
|
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_openasm(char *filename); /* read/write */
|
||||||
void pc_closeasm(void *handle,int deletefile);
|
void pc_closeasm(void *handle,int deletefile);
|
||||||
void pc_resetasm(void *handle);
|
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);
|
char *pc_readasm(void *handle,char *target,int maxchars);
|
||||||
|
|
||||||
/* output to binary (.AMX) file */
|
/* 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);
|
int pc_writebin(void *handle,void *buffer,int size);
|
||||||
long pc_lengthbin(void *handle); /* return the length of the file */
|
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_start(int num_natives);
|
||||||
void sp_fdbg_ntv_hook(int index, symbol *sym);
|
void sp_fdbg_ntv_hook(int index, symbol *sym);
|
||||||
|
|
||||||
/* function prototypes in SC1.C */
|
/* function prototypes in SC1.C */
|
||||||
SC_FUNC void set_extension(char *filename,char *extension,int force);
|
void set_extension(char *filename,const char *extension,int force);
|
||||||
SC_FUNC symbol *fetchfunc(char *name);
|
symbol *fetchfunc(char *name);
|
||||||
SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag);
|
char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag);
|
||||||
SC_FUNC char *funcdisplayname(char *dest,char *funcname);
|
char *funcdisplayname(char *dest,char *funcname);
|
||||||
SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr);
|
int exprconst(cell *val,int *tag,symbol **symptr);
|
||||||
SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
|
constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
|
||||||
SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index);
|
constvalue *find_constval(constvalue *table,char *name,int index);
|
||||||
SC_FUNC void delete_consttable(constvalue *table);
|
void delete_consttable(constvalue *table);
|
||||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
symbol *add_constant(const char *name,cell val,int vclass,int tag);
|
||||||
SC_FUNC void exporttag(int tag);
|
void exporttag(int tag);
|
||||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
void sc_attachdocumentation(symbol *sym);
|
||||||
SC_FUNC constvalue *find_tag_byval(int tag);
|
constvalue *find_tag_byval(int tag);
|
||||||
SC_FUNC int get_actual_compound(symbol *sym);
|
int get_actual_compound(symbol *sym);
|
||||||
|
|
||||||
/* function prototypes in SC2.C */
|
/* function prototypes in SC2.C */
|
||||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||||
#define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); }
|
#define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); }
|
||||||
#define POPSTK_P() (popstk().pv)
|
#define POPSTK_P() (popstk().pv)
|
||||||
#define POPSTK_I() (popstk().i)
|
#define POPSTK_I() (popstk().i)
|
||||||
SC_FUNC void pushstk(stkitem val);
|
void pushstk(stkitem val);
|
||||||
SC_FUNC stkitem popstk(void);
|
stkitem popstk(void);
|
||||||
SC_FUNC void clearstk(void);
|
void clearstk(void);
|
||||||
SC_FUNC int plungequalifiedfile(char *name); /* explicit path included */
|
int plungequalifiedfile(char *name); /* explicit path included */
|
||||||
SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
|
int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
|
||||||
SC_FUNC void preprocess(void);
|
void preprocess(void);
|
||||||
SC_FUNC void lexinit(void);
|
void lexinit(void);
|
||||||
SC_FUNC int lex(cell *lexvalue,char **lexsym);
|
int lex(cell *lexvalue,char **lexsym);
|
||||||
SC_FUNC int lextok(token_t *tok);
|
int lextok(token_t *tok);
|
||||||
SC_FUNC int lexpeek(int id);
|
int lexpeek(int id);
|
||||||
SC_FUNC void lexpush(void);
|
void lexpush(void);
|
||||||
SC_FUNC void lexclr(int clreol);
|
void lexclr(int clreol);
|
||||||
SC_FUNC int matchtoken(int token);
|
int matchtoken(int token);
|
||||||
SC_FUNC int tokeninfo(cell *val,char **str);
|
int tokeninfo(cell *val,char **str);
|
||||||
SC_FUNC int needtoken(int token);
|
int needtoken(int token);
|
||||||
SC_FUNC int matchtoken2(int id, token_t *tok);
|
int matchtoken2(int id, token_t *tok);
|
||||||
SC_FUNC int expecttoken(int id, token_t *tok);
|
int expecttoken(int id, token_t *tok);
|
||||||
SC_FUNC int matchsymbol(token_ident_t *ident);
|
int matchsymbol(token_ident_t *ident);
|
||||||
SC_FUNC int needsymbol(token_ident_t *ident);
|
int needsymbol(token_ident_t *ident);
|
||||||
SC_FUNC int peek_same_line();
|
int peek_same_line();
|
||||||
SC_FUNC int require_newline(int allow_semi);
|
int require_newline(int allow_semi);
|
||||||
SC_FUNC void litadd(cell value);
|
void litadd(cell value);
|
||||||
SC_FUNC void litinsert(cell value,int pos);
|
void litinsert(cell value,int pos);
|
||||||
SC_FUNC int alphanum(char c);
|
int alphanum(char c);
|
||||||
SC_FUNC int ishex(char c);
|
int ishex(char c);
|
||||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym);
|
void delete_symbol(symbol *root,symbol *sym);
|
||||||
SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
||||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
|
int refer_symbol(symbol *entry,symbol *bywhom);
|
||||||
SC_FUNC void markusage(symbol *sym,int usage);
|
void markusage(symbol *sym,int usage);
|
||||||
SC_FUNC symbol *findglb(const char *name,int filter);
|
symbol *findglb(const char *name,int filter);
|
||||||
SC_FUNC symbol *findloc(const char *name);
|
symbol *findloc(const char *name);
|
||||||
SC_FUNC symbol *findconst(const char *name,int *matchtag);
|
symbol *findconst(const char *name,int *matchtag);
|
||||||
SC_FUNC symbol *finddepend(const symbol *parent);
|
symbol *finddepend(const symbol *parent);
|
||||||
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);
|
||||||
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[]);
|
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);
|
int dim[],int numdim,int idxtag[],int slength);
|
||||||
SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
|
symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
|
||||||
SC_FUNC int getlabel(void);
|
int getlabel(void);
|
||||||
SC_FUNC char *itoh(ucell val);
|
char *itoh(ucell val);
|
||||||
|
|
||||||
#define MATCHTAG_COERCE 0x1 // allow coercion
|
#define MATCHTAG_COERCE 0x1 // allow coercion
|
||||||
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
|
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
|
||||||
#define MATCHTAG_COMMUTATIVE 0x4 // order does not matter
|
#define MATCHTAG_COMMUTATIVE 0x4 // order does not matter
|
||||||
|
|
||||||
/* function prototypes in SC3.C */
|
/* 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);
|
value *lval,int *resulttag);
|
||||||
SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
|
int matchtag(int formaltag,int actualtag,int allowcoerce);
|
||||||
SC_FUNC int checktag(int tags[],int numtags,int exprtag);
|
int checktag(int tags[],int numtags,int exprtag);
|
||||||
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);
|
||||||
SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
|
int sc_getstateid(constvalue **automaton,constvalue **state);
|
||||||
SC_FUNC cell array_totalsize(symbol *sym);
|
cell array_totalsize(symbol *sym);
|
||||||
SC_FUNC int matchtag_string(int ident, int tag);
|
int matchtag_string(int ident, int tag);
|
||||||
SC_FUNC int checktag_string(value *sym1, value *sym2);
|
int checktag_string(value *sym1, value *sym2);
|
||||||
SC_FUNC int checktags_string(int tags[], int numtags, value *sym1);
|
int checktags_string(int tags[], int numtags, value *sym1);
|
||||||
SC_FUNC int lvalexpr(svalue *sval);
|
int lvalexpr(svalue *sval);
|
||||||
|
|
||||||
/* function prototypes in SC4.C */
|
/* function prototypes in SC4.C */
|
||||||
SC_FUNC void writeleader(symbol *root);
|
void writeleader(symbol *root);
|
||||||
SC_FUNC void writetrailer(void);
|
void writetrailer(void);
|
||||||
SC_FUNC void begcseg(void);
|
void begcseg(void);
|
||||||
SC_FUNC void begdseg(void);
|
void begdseg(void);
|
||||||
SC_FUNC void setline(int chkbounds);
|
void setline(int chkbounds);
|
||||||
SC_FUNC void setfiledirect(char *name);
|
void setfiledirect(char *name);
|
||||||
SC_FUNC void setlinedirect(int line);
|
void setlinedirect(int line);
|
||||||
SC_FUNC void setlabel(int index);
|
void setlabel(int index);
|
||||||
SC_FUNC void markexpr(optmark type,const char *name,cell offset);
|
void markexpr(optmark type,const char *name,cell offset);
|
||||||
SC_FUNC void startfunc(char *fname);
|
void startfunc(char *fname);
|
||||||
SC_FUNC void endfunc(void);
|
void endfunc(void);
|
||||||
SC_FUNC void alignframe(int numbytes);
|
void alignframe(int numbytes);
|
||||||
SC_FUNC void rvalue(value *lval);
|
void rvalue(value *lval);
|
||||||
SC_FUNC void address(symbol *ptr,regid reg);
|
void address(symbol *ptr,regid reg);
|
||||||
SC_FUNC void store(value *lval);
|
void store(value *lval);
|
||||||
SC_FUNC void loadreg(cell address,regid reg);
|
void loadreg(cell address,regid reg);
|
||||||
SC_FUNC void storereg(cell address,regid reg);
|
void storereg(cell address,regid reg);
|
||||||
SC_FUNC void memcopy(cell size);
|
void memcopy(cell size);
|
||||||
SC_FUNC void copyarray(symbol *sym,cell size);
|
void copyarray(symbol *sym,cell size);
|
||||||
SC_FUNC void fillarray(symbol *sym,cell size,cell value);
|
void fillarray(symbol *sym,cell size,cell value);
|
||||||
SC_FUNC void ldconst(cell val,regid reg);
|
void ldconst(cell val,regid reg);
|
||||||
SC_FUNC void moveto1(void);
|
void moveto1(void);
|
||||||
SC_FUNC void move_alt(void);
|
void move_alt(void);
|
||||||
SC_FUNC void pushreg(regid reg);
|
void pushreg(regid reg);
|
||||||
SC_FUNC void pushval(cell val);
|
void pushval(cell val);
|
||||||
SC_FUNC void popreg(regid reg);
|
void popreg(regid reg);
|
||||||
SC_FUNC void genarray(int dims, int _autozero);
|
void genarray(int dims, int _autozero);
|
||||||
SC_FUNC void swap1(void);
|
void swap1(void);
|
||||||
SC_FUNC void ffswitch(int label);
|
void ffswitch(int label);
|
||||||
SC_FUNC void ffcase(cell value,char *labelname,int newtable);
|
void ffcase(cell value,char *labelname,int newtable);
|
||||||
SC_FUNC void ffcall(symbol *sym,const char *label,int numargs);
|
void ffcall(symbol *sym,const char *label,int numargs);
|
||||||
SC_FUNC void ffret(int remparams);
|
void ffret(int remparams);
|
||||||
SC_FUNC void ffabort(int reason);
|
void ffabort(int reason);
|
||||||
SC_FUNC void ffbounds(cell size);
|
void ffbounds(cell size);
|
||||||
SC_FUNC void jumplabel(int number);
|
void jumplabel(int number);
|
||||||
SC_FUNC void defstorage(void);
|
void defstorage(void);
|
||||||
SC_FUNC void modstk(int delta);
|
void modstk(int delta);
|
||||||
SC_FUNC void setstk(cell value);
|
void setstk(cell value);
|
||||||
SC_FUNC void modheap(int delta);
|
void modheap(int delta);
|
||||||
SC_FUNC void modheap_i();
|
void modheap_i();
|
||||||
SC_FUNC void setheap_pri(void);
|
void setheap_pri(void);
|
||||||
SC_FUNC void setheap(cell value);
|
void setheap(cell value);
|
||||||
SC_FUNC void cell2addr(void);
|
void cell2addr(void);
|
||||||
SC_FUNC void cell2addr_alt(void);
|
void cell2addr_alt(void);
|
||||||
SC_FUNC void addr2cell(void);
|
void addr2cell(void);
|
||||||
SC_FUNC void char2addr(void);
|
void char2addr(void);
|
||||||
SC_FUNC void charalign(void);
|
void charalign(void);
|
||||||
SC_FUNC void addconst(cell value);
|
void addconst(cell value);
|
||||||
SC_FUNC void setheap_save(cell value);
|
void setheap_save(cell value);
|
||||||
SC_FUNC void stradjust(regid reg);
|
void stradjust(regid reg);
|
||||||
SC_FUNC void invoke_getter(struct methodmap_method_s *method);
|
void invoke_getter(struct methodmap_method_s *method);
|
||||||
SC_FUNC void invoke_setter(struct methodmap_method_s *method, int save);
|
void invoke_setter(struct methodmap_method_s *method, int save);
|
||||||
SC_FUNC void inc_pri();
|
void inc_pri();
|
||||||
SC_FUNC void dec_pri();
|
void dec_pri();
|
||||||
|
void load_hidden_arg();
|
||||||
|
|
||||||
/* Code generation functions for arithmetic operators.
|
/* Code generation functions for arithmetic operators.
|
||||||
*
|
*
|
||||||
@ -753,218 +733,204 @@ SC_FUNC void dec_pri();
|
|||||||
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
|
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
|
||||||
* +------------- "o"perator
|
* +------------- "o"perator
|
||||||
*/
|
*/
|
||||||
SC_FUNC void os_mult(void); /* multiplication (signed) */
|
void os_mult(void); /* multiplication (signed) */
|
||||||
SC_FUNC void os_div(void); /* division (signed) */
|
void os_div(void); /* division (signed) */
|
||||||
SC_FUNC void os_mod(void); /* modulus (signed) */
|
void os_mod(void); /* modulus (signed) */
|
||||||
SC_FUNC void ob_add(void); /* addition */
|
void ob_add(void); /* addition */
|
||||||
SC_FUNC void ob_sub(void); /* subtraction */
|
void ob_sub(void); /* subtraction */
|
||||||
SC_FUNC void ob_sal(void); /* shift left (arithmetic) */
|
void ob_sal(void); /* shift left (arithmetic) */
|
||||||
SC_FUNC void os_sar(void); /* shift right (arithmetic, signed) */
|
void os_sar(void); /* shift right (arithmetic, signed) */
|
||||||
SC_FUNC void ou_sar(void); /* shift right (logical, unsigned) */
|
void ou_sar(void); /* shift right (logical, unsigned) */
|
||||||
SC_FUNC void ob_or(void); /* bitwise or */
|
void ob_or(void); /* bitwise or */
|
||||||
SC_FUNC void ob_xor(void); /* bitwise xor */
|
void ob_xor(void); /* bitwise xor */
|
||||||
SC_FUNC void ob_and(void); /* bitwise and */
|
void ob_and(void); /* bitwise and */
|
||||||
SC_FUNC void ob_eq(void); /* equality */
|
void ob_eq(void); /* equality */
|
||||||
SC_FUNC void ob_ne(void); /* inequality */
|
void ob_ne(void); /* inequality */
|
||||||
SC_FUNC void relop_prefix(void);
|
void relop_prefix(void);
|
||||||
SC_FUNC void relop_suffix(void);
|
void relop_suffix(void);
|
||||||
SC_FUNC void os_le(void); /* less or equal (signed) */
|
void os_le(void); /* less or equal (signed) */
|
||||||
SC_FUNC void os_ge(void); /* greater or equal (signed) */
|
void os_ge(void); /* greater or equal (signed) */
|
||||||
SC_FUNC void os_lt(void); /* less (signed) */
|
void os_lt(void); /* less (signed) */
|
||||||
SC_FUNC void os_gt(void); /* greater (signed) */
|
void os_gt(void); /* greater (signed) */
|
||||||
|
|
||||||
SC_FUNC void lneg(void);
|
void lneg(void);
|
||||||
SC_FUNC void neg(void);
|
void neg(void);
|
||||||
SC_FUNC void invert(void);
|
void invert(void);
|
||||||
SC_FUNC void nooperation(void);
|
void nooperation(void);
|
||||||
SC_FUNC void inc(value *lval);
|
void inc(value *lval);
|
||||||
SC_FUNC void dec(value *lval);
|
void dec(value *lval);
|
||||||
SC_FUNC void jmp_ne0(int number);
|
void jmp_ne0(int number);
|
||||||
SC_FUNC void jmp_eq0(int number);
|
void jmp_eq0(int number);
|
||||||
SC_FUNC void outval(cell val,int newline);
|
void outval(cell val,int newline);
|
||||||
|
|
||||||
/* function prototypes in SC5.C */
|
/* function prototypes in SC5.C */
|
||||||
SC_FUNC int error(int number,...);
|
int error(int number,...);
|
||||||
SC_FUNC void errorset(int code,int line);
|
void errorset(int code,int line);
|
||||||
|
|
||||||
/* function prototypes in SC6.C */
|
/* function prototypes in SC6.C */
|
||||||
SC_FUNC int assemble(FILE *fout,FILE *fin);
|
int assemble(void *fout,void *fin);
|
||||||
|
|
||||||
/* function prototypes in SC7.C */
|
/* function prototypes in SC7.C */
|
||||||
SC_FUNC void stgbuffer_cleanup(void);
|
void stgbuffer_cleanup(void);
|
||||||
SC_FUNC void stgmark(char mark);
|
void stgmark(char mark);
|
||||||
SC_FUNC void stgwrite(const char *st);
|
void stgwrite(const char *st);
|
||||||
SC_FUNC void stgout(int index);
|
void stgout(int index);
|
||||||
SC_FUNC void stgdel(int index,cell code_index);
|
void stgdel(int index,cell code_index);
|
||||||
SC_FUNC int stgget(int *index,cell *code_index);
|
int stgget(int *index,cell *code_index);
|
||||||
SC_FUNC void stgset(int onoff);
|
void stgset(int onoff);
|
||||||
SC_FUNC int phopt_init(void);
|
int phopt_init(void);
|
||||||
SC_FUNC int phopt_cleanup(void);
|
int phopt_cleanup(void);
|
||||||
|
|
||||||
/* function prototypes in SCLIST.C */
|
/* function prototypes in SCLIST.C */
|
||||||
SC_FUNC char* duplicatestring(const char* sourcestring);
|
char* duplicatestring(const char* sourcestring);
|
||||||
SC_FUNC stringpair *insert_alias(char *name,char *alias);
|
stringpair *insert_alias(char *name,char *alias);
|
||||||
SC_FUNC stringpair *find_alias(char *name);
|
stringpair *find_alias(char *name);
|
||||||
SC_FUNC int lookup_alias(char *target,char *name);
|
int lookup_alias(char *target,char *name);
|
||||||
SC_FUNC void delete_aliastable(void);
|
void delete_aliastable(void);
|
||||||
SC_FUNC stringlist *insert_path(char *path);
|
stringlist *insert_path(char *path);
|
||||||
SC_FUNC char *get_path(int index);
|
char *get_path(int index);
|
||||||
SC_FUNC void delete_pathtable(void);
|
void delete_pathtable(void);
|
||||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen);
|
stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen);
|
||||||
SC_FUNC int get_subst(int index,char **pattern,char **substitution);
|
int get_subst(int index,char **pattern,char **substitution);
|
||||||
SC_FUNC stringpair *find_subst(char *name,int length);
|
stringpair *find_subst(char *name,int length);
|
||||||
SC_FUNC int delete_subst(char *name,int length);
|
int delete_subst(char *name,int length);
|
||||||
SC_FUNC void delete_substtable(void);
|
void delete_substtable(void);
|
||||||
SC_FUNC stringlist *insert_sourcefile(char *string);
|
stringlist *insert_sourcefile(char *string);
|
||||||
SC_FUNC char *get_sourcefile(int index);
|
char *get_sourcefile(int index);
|
||||||
SC_FUNC void delete_sourcefiletable(void);
|
void delete_sourcefiletable(void);
|
||||||
SC_FUNC stringlist *insert_docstring(char *string);
|
stringlist *insert_docstring(char *string);
|
||||||
SC_FUNC char *get_docstring(int index);
|
char *get_docstring(int index);
|
||||||
SC_FUNC void delete_docstring(int index);
|
void delete_docstring(int index);
|
||||||
SC_FUNC void delete_docstringtable(void);
|
void delete_docstringtable(void);
|
||||||
SC_FUNC stringlist *insert_autolist(char *string);
|
stringlist *insert_autolist(const char *string);
|
||||||
SC_FUNC char *get_autolist(int index);
|
char *get_autolist(int index);
|
||||||
SC_FUNC void delete_autolisttable(void);
|
void delete_autolisttable(void);
|
||||||
SC_FUNC stringlist *insert_dbgfile(const char *filename);
|
stringlist *insert_dbgfile(const char *filename);
|
||||||
SC_FUNC stringlist *insert_dbgline(int linenr);
|
stringlist *insert_dbgline(int linenr);
|
||||||
SC_FUNC stringlist *insert_dbgsymbol(symbol *sym);
|
stringlist *insert_dbgsymbol(symbol *sym);
|
||||||
SC_FUNC char *get_dbgstring(int index);
|
char *get_dbgstring(int index);
|
||||||
SC_FUNC void delete_dbgstringtable(void);
|
void delete_dbgstringtable(void);
|
||||||
SC_FUNC stringlist *get_dbgstrings();
|
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);
|
|
||||||
|
|
||||||
/* function prototypes in SCI18N.C */
|
/* function prototypes in SCI18N.C */
|
||||||
#define MAXCODEPAGE 12
|
#define MAXCODEPAGE 12
|
||||||
SC_FUNC int cp_path(const char *root,const char *directory);
|
int cp_path(const char *root,const char *directory);
|
||||||
SC_FUNC int cp_set(const char *name);
|
int cp_set(const char *name);
|
||||||
SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr);
|
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);
|
cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
|
||||||
SC_FUNC int scan_utf8(FILE *fp,const char *filename);
|
int scan_utf8(void *fp,const char *filename);
|
||||||
|
|
||||||
/* function prototypes in SCSTATE.C */
|
/* function prototypes in SCSTATE.C */
|
||||||
SC_FUNC constvalue *automaton_add(const char *name);
|
constvalue *automaton_add(const char *name);
|
||||||
SC_FUNC constvalue *automaton_find(const char *name);
|
constvalue *automaton_find(const char *name);
|
||||||
SC_FUNC constvalue *automaton_findid(int id);
|
constvalue *automaton_findid(int id);
|
||||||
SC_FUNC constvalue *state_add(const char *name,int fsa_id);
|
constvalue *state_add(const char *name,int fsa_id);
|
||||||
SC_FUNC constvalue *state_find(const char *name,int fsa_id);
|
constvalue *state_find(const char *name,int fsa_id);
|
||||||
SC_FUNC constvalue *state_findid(int id);
|
constvalue *state_findid(int id);
|
||||||
SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid);
|
void state_buildlist(int **list,int *listsize,int *count,int stateid);
|
||||||
SC_FUNC int state_addlist(int *list,int count,int fsa_id);
|
int state_addlist(int *list,int count,int fsa_id);
|
||||||
SC_FUNC void state_deletetable(void);
|
void state_deletetable(void);
|
||||||
SC_FUNC int state_getfsa(int listid);
|
int state_getfsa(int listid);
|
||||||
SC_FUNC int state_count(int listid);
|
int state_count(int listid);
|
||||||
SC_FUNC int state_inlist(int listid,int state);
|
int state_inlist(int listid,int state);
|
||||||
SC_FUNC int state_listitem(int listid,int index);
|
int state_listitem(int listid,int index);
|
||||||
SC_FUNC void state_conflict(symbol *root);
|
void state_conflict(symbol *root);
|
||||||
SC_FUNC int state_conflict_id(int listid1,int listid2);
|
int state_conflict_id(int listid1,int listid2);
|
||||||
|
|
||||||
/* external variables (defined in scvars.c) */
|
/* external variables (defined in scvars.c) */
|
||||||
#if !defined SC_SKIP_VDECL
|
#if !defined SC_SKIP_VDECL
|
||||||
typedef struct HashTable HashTable;
|
typedef struct HashTable HashTable;
|
||||||
SC_VDECL struct HashTable *sp_Globals;
|
extern struct HashTable *sp_Globals;
|
||||||
SC_VDECL symbol loctab; /* local symbol table */
|
extern symbol loctab; /* local symbol table */
|
||||||
SC_VDECL symbol glbtab; /* global symbol table */
|
extern symbol glbtab; /* global symbol table */
|
||||||
SC_VDECL cell *litq; /* the literal queue */
|
extern cell *litq; /* the literal queue */
|
||||||
SC_VDECL unsigned char pline[]; /* the line read from the input file */
|
extern unsigned char pline[]; /* the line read from the input file */
|
||||||
SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */
|
extern const unsigned char *lptr;/* points to the current position in "pline" */
|
||||||
SC_VDECL constvalue tagname_tab;/* tagname table */
|
extern constvalue tagname_tab;/* tagname table */
|
||||||
SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */
|
extern constvalue libname_tab;/* library table (#pragma library "..." syntax) */
|
||||||
SC_VDECL constvalue *curlibrary;/* current library */
|
extern constvalue *curlibrary;/* current library */
|
||||||
SC_VDECL int pc_addlibtable; /* is the library table added to the AMX file? */
|
extern int pc_addlibtable; /* is the library table added to the AMX file? */
|
||||||
SC_VDECL symbol *curfunc; /* pointer to current function */
|
extern symbol *curfunc; /* pointer to current function */
|
||||||
SC_VDECL char *inpfname; /* name of the file currently read from */
|
extern char *inpfname; /* name of the file currently read from */
|
||||||
SC_VDECL char outfname[]; /* intermediate (assembler) file name */
|
extern char outfname[]; /* intermediate (assembler) file name */
|
||||||
SC_VDECL char binfname[]; /* binary file name */
|
extern char binfname[]; /* binary file name */
|
||||||
SC_VDECL char errfname[]; /* error file name */
|
extern char errfname[]; /* error file name */
|
||||||
SC_VDECL char sc_ctrlchar; /* the control character (or escape character) */
|
extern char sc_ctrlchar; /* the control character (or escape character) */
|
||||||
SC_VDECL char sc_ctrlchar_org;/* the default control character */
|
extern char sc_ctrlchar_org;/* the default control character */
|
||||||
SC_VDECL int litidx; /* index to literal table */
|
extern int litidx; /* index to literal table */
|
||||||
SC_VDECL int litmax; /* current size of the literal table */
|
extern int litmax; /* current size of the literal table */
|
||||||
SC_VDECL int stgidx; /* index to the staging buffer */
|
extern int stgidx; /* index to the staging buffer */
|
||||||
SC_VDECL int sc_labnum; /* number of (internal) labels */
|
extern int sc_labnum; /* number of (internal) labels */
|
||||||
SC_VDECL int staging; /* true if staging output */
|
extern int staging; /* true if staging output */
|
||||||
SC_VDECL cell declared; /* number of local cells declared */
|
extern cell declared; /* number of local cells declared */
|
||||||
SC_VDECL cell glb_declared; /* number of global cells declared */
|
extern cell glb_declared; /* number of global cells declared */
|
||||||
SC_VDECL cell code_idx; /* number of bytes with generated code */
|
extern cell code_idx; /* number of bytes with generated code */
|
||||||
SC_VDECL int ntv_funcid; /* incremental number of native function */
|
extern int ntv_funcid; /* incremental number of native function */
|
||||||
SC_VDECL int errnum; /* number of errors */
|
extern int errnum; /* number of errors */
|
||||||
SC_VDECL int warnnum; /* number of warnings */
|
extern int warnnum; /* number of warnings */
|
||||||
SC_VDECL int sc_debug; /* debug/optimization options (bit field) */
|
extern int sc_debug; /* debug/optimization options (bit field) */
|
||||||
SC_VDECL int sc_packstr; /* strings are packed by default? */
|
extern int sc_packstr; /* strings are packed by default? */
|
||||||
SC_VDECL int sc_asmfile; /* create .ASM file? */
|
extern int sc_asmfile; /* create .ASM file? */
|
||||||
SC_VDECL int sc_listing; /* create .LST file? */
|
extern int sc_listing; /* create .LST file? */
|
||||||
SC_VDECL int sc_compress; /* compress bytecode? */
|
extern int sc_compress; /* compress bytecode? */
|
||||||
SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */
|
extern int sc_needsemicolon;/* semicolon required to terminate expressions? */
|
||||||
SC_VDECL int sc_dataalign; /* data alignment value */
|
extern int sc_dataalign; /* data alignment value */
|
||||||
SC_VDECL int sc_alignnext; /* must frame of the next function be aligned? */
|
extern int sc_alignnext; /* must frame of the next function be aligned? */
|
||||||
SC_VDECL int pc_docexpr; /* must expression be attached to documentation comment? */
|
extern int pc_docexpr; /* must expression be attached to documentation comment? */
|
||||||
SC_VDECL int sc_showincludes; /* show include files? */
|
extern int sc_showincludes; /* show include files? */
|
||||||
SC_VDECL int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
extern int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||||
SC_VDECL cell pc_stksize; /* stack size */
|
extern cell pc_stksize; /* stack size */
|
||||||
SC_VDECL cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
|
extern cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
|
||||||
SC_VDECL cell pc_amxram; /* abstract machine data size limit */
|
extern cell pc_amxram; /* abstract machine data size limit */
|
||||||
SC_VDECL int freading; /* is there an input file ready for reading? */
|
extern int freading; /* is there an input file ready for reading? */
|
||||||
SC_VDECL int fline; /* the line number in the current file */
|
extern int fline; /* the line number in the current file */
|
||||||
SC_VDECL short fnumber; /* number of files in the file table (debugging) */
|
extern short fnumber; /* number of files in the file table (debugging) */
|
||||||
SC_VDECL short fcurrent; /* current file being processed (debugging) */
|
extern short fcurrent; /* current file being processed (debugging) */
|
||||||
SC_VDECL short sc_intest; /* true if inside a test */
|
extern short sc_intest; /* true if inside a test */
|
||||||
SC_VDECL int sideeffect; /* true if an expression causes a side-effect */
|
extern int sideeffect; /* true if an expression causes a side-effect */
|
||||||
SC_VDECL int stmtindent; /* current indent of the statement */
|
extern int stmtindent; /* current indent of the statement */
|
||||||
SC_VDECL int indent_nowarn; /* skip warning "217 loose indentation" */
|
extern int indent_nowarn; /* skip warning "217 loose indentation" */
|
||||||
SC_VDECL int sc_tabsize; /* number of spaces that a TAB represents */
|
extern int sc_tabsize; /* number of spaces that a TAB represents */
|
||||||
SC_VDECL short sc_allowtags; /* allow/detect tagnames in lex() */
|
extern short sc_allowtags; /* allow/detect tagnames in lex() */
|
||||||
SC_VDECL int sc_status; /* read/write status */
|
extern int sc_status; /* read/write status */
|
||||||
SC_VDECL int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */
|
extern int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */
|
||||||
SC_VDECL int sc_rationaltag; /* tag for rational numbers */
|
extern int sc_rationaltag; /* tag for rational numbers */
|
||||||
SC_VDECL int rational_digits; /* number of fractional digits */
|
extern int rational_digits; /* number of fractional digits */
|
||||||
SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */
|
extern int sc_allowproccall;/* allow/detect tagnames in lex() */
|
||||||
SC_VDECL short sc_is_utf8; /* is this source file in UTF-8 encoding */
|
extern 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 */
|
extern char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
|
||||||
SC_VDECL int sc_curstates; /* ID of the current state list */
|
extern int sc_curstates; /* ID of the current state list */
|
||||||
SC_VDECL int pc_optimize; /* (peephole) optimization level */
|
extern int pc_optimize; /* (peephole) optimization level */
|
||||||
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
|
extern int pc_memflags; /* special flags for the stack/heap usage */
|
||||||
SC_VDECL int pc_functag; /* global function tag */
|
extern int pc_functag; /* global function tag */
|
||||||
SC_VDECL int pc_tag_string; /* global String tag */
|
extern int pc_tag_string; /* global String tag */
|
||||||
SC_VDECL int pc_tag_void; /* global void tag */
|
extern int pc_tag_void; /* global void tag */
|
||||||
SC_VDECL int pc_tag_object; /* root object tag */
|
extern int pc_tag_object; /* root object tag */
|
||||||
SC_VDECL int pc_tag_bool; /* global bool tag */
|
extern int pc_tag_bool; /* global bool tag */
|
||||||
SC_VDECL int pc_tag_null_t; /* the null type */
|
extern int pc_tag_null_t; /* the null type */
|
||||||
SC_VDECL int pc_tag_nullfunc_t; /* the null function type */
|
extern int pc_tag_nullfunc_t; /* the null function type */
|
||||||
SC_VDECL int pc_anytag; /* global any tag */
|
extern int pc_anytag; /* global any tag */
|
||||||
SC_VDECL int glbstringread; /* last global string read */
|
extern int glbstringread; /* last global string read */
|
||||||
SC_VDECL int sc_require_newdecls; /* only newdecls are allowed */
|
extern int sc_require_newdecls; /* only newdecls are allowed */
|
||||||
|
|
||||||
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
extern constvalue sc_automaton_tab; /* automaton table */
|
||||||
SC_VDECL constvalue sc_state_tab; /* state table */
|
extern constvalue sc_state_tab; /* state table */
|
||||||
|
|
||||||
SC_VDECL FILE *inpf; /* file read from (source or include) */
|
extern void *inpf; /* file read from (source or include) */
|
||||||
SC_VDECL FILE *inpf_org; /* main source file */
|
extern void *inpf_org; /* main source file */
|
||||||
SC_VDECL FILE *outf; /* file written to */
|
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
|
#if !defined SC_LIGHT
|
||||||
SC_VDECL int sc_makereport; /* generate a cross-reference report */
|
extern int sc_makereport; /* generate a cross-reference report */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined WIN32
|
#if defined WIN32
|
||||||
#if !defined snprintf
|
# if !defined snprintf
|
||||||
#define snprintf _snprintf
|
# define snprintf _snprintf
|
||||||
#endif
|
# define vsnprintf _vsnprintf
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* SC_SKIP_VDECL */
|
#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 symbol *find_symbol(const symbol *root,const char *name,int fnumber,int automaton,int *cmptag);
|
||||||
|
|
||||||
static void substallpatterns(unsigned char *line,int buffersize);
|
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);
|
static int alpha(char c);
|
||||||
|
|
||||||
#define SKIPMODE 1 /* bit field in "#if" stack */
|
#define SKIPMODE 1 /* bit field in "#if" stack */
|
||||||
@ -86,7 +86,7 @@ static double pow10(double d)
|
|||||||
static stkitem *stack=NULL;
|
static stkitem *stack=NULL;
|
||||||
static int stkidx=0,stktop=0;
|
static int stkidx=0,stktop=0;
|
||||||
|
|
||||||
SC_FUNC void pushstk(stkitem val)
|
void pushstk(stkitem val)
|
||||||
{
|
{
|
||||||
assert(stkidx<=stktop);
|
assert(stkidx<=stktop);
|
||||||
if (stkidx==stktop) {
|
if (stkidx==stktop) {
|
||||||
@ -109,7 +109,7 @@ SC_FUNC void pushstk(stkitem val)
|
|||||||
stkidx+=1;
|
stkidx+=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC stkitem popstk(void)
|
stkitem popstk(void)
|
||||||
{
|
{
|
||||||
if (stkidx==0) {
|
if (stkidx==0) {
|
||||||
stkitem s;
|
stkitem s;
|
||||||
@ -121,7 +121,7 @@ SC_FUNC stkitem popstk(void)
|
|||||||
return stack[stkidx];
|
return stack[stkidx];
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC void clearstk(void)
|
void clearstk(void)
|
||||||
{
|
{
|
||||||
assert(stack!=NULL || stktop==0);
|
assert(stack!=NULL || stktop==0);
|
||||||
if (stack!=NULL) {
|
if (stack!=NULL) {
|
||||||
@ -132,9 +132,10 @@ SC_FUNC void clearstk(void)
|
|||||||
assert(stktop==0);
|
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;
|
void *fp;
|
||||||
char *ext;
|
char *ext;
|
||||||
int ext_idx;
|
int ext_idx;
|
||||||
@ -184,7 +185,7 @@ static char *extensions[] = { ".inc", ".p", ".pawn" };
|
|||||||
return TRUE;
|
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;
|
int result=FALSE;
|
||||||
|
|
||||||
@ -671,11 +672,11 @@ static int ftoi(cell *val,const unsigned char *curptr)
|
|||||||
exp=(exp*10)+(*ptr-'0');
|
exp=(exp*10)+(*ptr-'0');
|
||||||
ptr++;
|
ptr++;
|
||||||
} /* while */
|
} /* while */
|
||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
fmult=pow10(exp*sign);
|
fmult=pow10(exp*sign);
|
||||||
#else
|
#else
|
||||||
fmult=pow(10,exp*sign);
|
fmult=pow(10.0,exp*sign);
|
||||||
#endif
|
#endif
|
||||||
fnum *= fmult;
|
fnum *= fmult;
|
||||||
dnum *= (unsigned long)(fmult+0.5);
|
dnum *= (unsigned long)(fmult+0.5);
|
||||||
} /* if */
|
} /* if */
|
||||||
@ -796,7 +797,7 @@ static int preproc_expr(cell *val,int *tag)
|
|||||||
term=strchr((char*)pline,'\0');
|
term=strchr((char*)pline,'\0');
|
||||||
assert(term!=NULL);
|
assert(term!=NULL);
|
||||||
chrcat((char*)pline,PREPROC_TERM); /* the "DEL" code (see SC.H) */
|
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) */
|
*term='\0'; /* erase the token (if still present) */
|
||||||
lexclr(FALSE); /* clear any "pushed" tokens */
|
lexclr(FALSE); /* clear any "pushed" tokens */
|
||||||
return result;
|
return result;
|
||||||
@ -1251,7 +1252,7 @@ static int command(void)
|
|||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
char s2[20];
|
char s2[20];
|
||||||
extern char *sc_tokens[];/* forward declaration */
|
extern const char *sc_tokens[];/* forward declaration */
|
||||||
if (tok<256)
|
if (tok<256)
|
||||||
sprintf(s2,"%c",(char)tok);
|
sprintf(s2,"%c",(char)tok);
|
||||||
else
|
else
|
||||||
@ -1482,7 +1483,7 @@ static char *strdel(char *str,size_t len)
|
|||||||
return str;
|
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);
|
size_t destlen=strlen(dest);
|
||||||
assert(srclen<=strlen(src));
|
assert(srclen<=strlen(src));
|
||||||
@ -1792,7 +1793,7 @@ static int scanellipsis(const unsigned char *lptr)
|
|||||||
* pline (altered)
|
* pline (altered)
|
||||||
* freading (referred to only)
|
* freading (referred to only)
|
||||||
*/
|
*/
|
||||||
SC_FUNC void preprocess(void)
|
void preprocess(void)
|
||||||
{
|
{
|
||||||
int iscommand;
|
int iscommand;
|
||||||
|
|
||||||
@ -1931,7 +1932,7 @@ static full_token_t *next_token()
|
|||||||
return &sTokenBuffer->tokens[cursor];
|
return &sTokenBuffer->tokens[cursor];
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC void lexinit(void)
|
void lexinit(void)
|
||||||
{
|
{
|
||||||
stkidx=0; /* index for pushstk() and popstk() */
|
stkidx=0; /* index for pushstk() and popstk() */
|
||||||
iflevel=0; /* preprocessor: nesting of "#if" is currently 0 */
|
iflevel=0; /* preprocessor: nesting of "#if" is currently 0 */
|
||||||
@ -1943,7 +1944,7 @@ SC_FUNC void lexinit(void)
|
|||||||
sTokenBuffer = &sNormalBuffer;
|
sTokenBuffer = &sNormalBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *sc_tokens[] = {
|
const char *sc_tokens[] = {
|
||||||
"*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
|
"*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
|
||||||
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
||||||
"...", "..", "::",
|
"...", "..", "::",
|
||||||
@ -1961,7 +1962,8 @@ char *sc_tokens[] = {
|
|||||||
"public",
|
"public",
|
||||||
"return",
|
"return",
|
||||||
"sizeof", "sleep", "static", "stock", "struct", "switch",
|
"sizeof", "sleep", "static", "stock", "struct", "switch",
|
||||||
"tagof", "*then",
|
"tagof", "*then", "typedef",
|
||||||
|
"union",
|
||||||
"void",
|
"void",
|
||||||
"while",
|
"while",
|
||||||
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
||||||
@ -1969,7 +1971,7 @@ char *sc_tokens[] = {
|
|||||||
"#tryinclude", "#undef",
|
"#tryinclude", "#undef",
|
||||||
";", ";", "-integer value-", "-rational value-", "-identifier-",
|
";", ";", "-integer value-", "-rational value-", "-identifier-",
|
||||||
"-label-", "-string-"
|
"-label-", "-string-"
|
||||||
};
|
};
|
||||||
|
|
||||||
static full_token_t *advance_token_ptr()
|
static full_token_t *advance_token_ptr()
|
||||||
{
|
{
|
||||||
@ -2000,10 +2002,9 @@ static void lexpop()
|
|||||||
sTokenBuffer->cursor = 0;
|
sTokenBuffer->cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
int lex(cell *lexvalue,char **lexsym)
|
||||||
{
|
{
|
||||||
int i,toolong,newline;
|
int i,toolong,newline;
|
||||||
char **tokptr;
|
|
||||||
const unsigned char *starttoken;
|
const unsigned char *starttoken;
|
||||||
|
|
||||||
if (sTokenBuffer->depth > 0) {
|
if (sTokenBuffer->depth > 0) {
|
||||||
@ -2054,7 +2055,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
|||||||
tok->start.col = (int)(lptr - pline);
|
tok->start.col = (int)(lptr - pline);
|
||||||
|
|
||||||
i=tFIRST;
|
i=tFIRST;
|
||||||
tokptr=sc_tokens;
|
const char **tokptr=sc_tokens;
|
||||||
while (i<=tMIDDLE) { /* match multi-character operators */
|
while (i<=tMIDDLE) { /* match multi-character operators */
|
||||||
if (*lptr==**tokptr && match(*tokptr,FALSE)) {
|
if (*lptr==**tokptr && match(*tokptr,FALSE)) {
|
||||||
tok->id = i;
|
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 and return the information from these variables, rather than
|
||||||
* to read in a new token from the input file.
|
* to read in a new token from the input file.
|
||||||
*/
|
*/
|
||||||
SC_FUNC void lexpush(void)
|
void lexpush(void)
|
||||||
{
|
{
|
||||||
assert(sTokenBuffer->depth < MAX_TOKEN_DEPTH);
|
assert(sTokenBuffer->depth < MAX_TOKEN_DEPTH);
|
||||||
sTokenBuffer->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
|
* 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.
|
* 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;
|
sTokenBuffer->depth = 0;
|
||||||
if (clreol) {
|
if (clreol) {
|
||||||
@ -2286,7 +2287,7 @@ SC_FUNC void lexclr(int clreol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the symbol is ahead, false otherwise.
|
// Return true if the symbol is ahead, false otherwise.
|
||||||
SC_FUNC int lexpeek(int id)
|
int lexpeek(int id)
|
||||||
{
|
{
|
||||||
if (matchtoken(id)) {
|
if (matchtoken(id)) {
|
||||||
lexpush();
|
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
|
* (i.e. not present in the source code) should not be pushed back, which is
|
||||||
* why it is sometimes important to distinguish the two.
|
* why it is sometimes important to distinguish the two.
|
||||||
*/
|
*/
|
||||||
SC_FUNC int matchtoken(int token)
|
int matchtoken(int token)
|
||||||
{
|
{
|
||||||
cell val;
|
cell val;
|
||||||
char *str;
|
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.
|
* 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;
|
*val = current_token()->value;
|
||||||
*str = current_token()->str;
|
*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
|
* this function returns 1 for "token found" and 2 for "statement termination
|
||||||
* token" found; see function matchtoken() for details.
|
* token" found; see function matchtoken() for details.
|
||||||
*/
|
*/
|
||||||
SC_FUNC int needtoken(int token)
|
int needtoken(int token)
|
||||||
{
|
{
|
||||||
char s1[20],s2[20];
|
char s1[20],s2[20];
|
||||||
int t;
|
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,
|
// If the next token is on the current line, return that token. Otherwise,
|
||||||
// return tNEWLINE.
|
// return tNEWLINE.
|
||||||
SC_FUNC int peek_same_line()
|
int peek_same_line()
|
||||||
{
|
{
|
||||||
// We should not call this without having parsed at least one token.
|
// We should not call this without having parsed at least one token.
|
||||||
assert(sTokenBuffer->num_tokens > 0);
|
assert(sTokenBuffer->num_tokens > 0);
|
||||||
@ -2407,7 +2408,7 @@ SC_FUNC int peek_same_line()
|
|||||||
return tEOL;
|
return tEOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int require_newline(int allow_semi)
|
int require_newline(int allow_semi)
|
||||||
{
|
{
|
||||||
if (allow_semi) {
|
if (allow_semi) {
|
||||||
// Semicolon must be on the same line.
|
// Semicolon must be on the same line.
|
||||||
@ -2440,7 +2441,7 @@ SC_FUNC int require_newline(int allow_semi)
|
|||||||
*
|
*
|
||||||
* Global references: lptr (altered)
|
* Global references: lptr (altered)
|
||||||
*/
|
*/
|
||||||
static int match(char *st,int end)
|
static int match(const char *st,int end)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
const unsigned char *ptr;
|
const unsigned char *ptr;
|
||||||
@ -2482,7 +2483,7 @@ static void chk_grow_litq(void)
|
|||||||
* Global references: litidx (altered)
|
* Global references: litidx (altered)
|
||||||
* litq (altered)
|
* litq (altered)
|
||||||
*/
|
*/
|
||||||
SC_FUNC void litadd(cell value)
|
void litadd(cell value)
|
||||||
{
|
{
|
||||||
chk_grow_litq();
|
chk_grow_litq();
|
||||||
assert(litidx<litmax);
|
assert(litidx<litmax);
|
||||||
@ -2497,7 +2498,7 @@ SC_FUNC void litadd(cell value)
|
|||||||
* Global references: litidx (altered)
|
* Global references: litidx (altered)
|
||||||
* litq (altered)
|
* litq (altered)
|
||||||
*/
|
*/
|
||||||
SC_FUNC void litinsert(cell value,int pos)
|
void litinsert(cell value,int pos)
|
||||||
{
|
{
|
||||||
chk_grow_litq();
|
chk_grow_litq();
|
||||||
assert(litidx<litmax);
|
assert(litidx<litmax);
|
||||||
@ -2632,7 +2633,7 @@ static int alpha(char c)
|
|||||||
*
|
*
|
||||||
* Test if character "c" is alphanumeric ("a".."z", "0".."9", "_" or "@")
|
* 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));
|
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").
|
* 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');
|
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);
|
free(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
void delete_symbol(symbol *root,symbol *sym)
|
||||||
{
|
{
|
||||||
symbol *origRoot=root;
|
symbol *origRoot=root;
|
||||||
/* find the symbol and its predecessor
|
/* find the symbol and its predecessor
|
||||||
@ -2738,7 +2739,7 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
|||||||
free_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) {
|
if (sym->ident == iARRAY || sym->ident == iREFARRAY) {
|
||||||
while (sym->parent)
|
while (sym->parent)
|
||||||
@ -2748,7 +2749,7 @@ SC_FUNC int get_actual_compound(symbol *sym)
|
|||||||
return sym->compound;
|
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 *origRoot=root;
|
||||||
symbol *sym,*parent_sym;
|
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
|
* bywhom will be the function that uses a variable or that calls
|
||||||
* the function.
|
* the function.
|
||||||
*/
|
*/
|
||||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
|
int refer_symbol(symbol *entry,symbol *bywhom)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
@ -2950,7 +2951,7 @@ SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC void markusage(symbol *sym,int usage)
|
void markusage(symbol *sym,int usage)
|
||||||
{
|
{
|
||||||
assert(sym!=NULL);
|
assert(sym!=NULL);
|
||||||
sym->usage |= (char)usage;
|
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)
|
* 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 */
|
/* find a symbol with a matching automaton first */
|
||||||
symbol *sym=NULL;
|
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).
|
* 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.
|
* 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);
|
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;
|
symbol *sym;
|
||||||
|
|
||||||
@ -3033,7 +3034,7 @@ SC_FUNC symbol *findconst(const char *name,int *cmptag)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC symbol *finddepend(const symbol *parent)
|
symbol *finddepend(const symbol *parent)
|
||||||
{
|
{
|
||||||
symbol *sym;
|
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,
|
* Adds a symbol to the symbol table (either global or local variables,
|
||||||
* or global and local constants).
|
* 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;
|
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);
|
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[])
|
int dim[],int numdim,int idxtag[])
|
||||||
{
|
{
|
||||||
return addvariable2(name,addr,ident,vclass,tag,dim,numdim,idxtag,0);
|
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;
|
typeinfo_t *type = &decl->type;
|
||||||
return addvariable2(
|
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)
|
int dim[],int numdim,int idxtag[],int slength)
|
||||||
{
|
{
|
||||||
symbol *sym;
|
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
|
* Returns te next internal label number. The global variable sc_labnum is
|
||||||
* initialized to zero.
|
* initialized to zero.
|
||||||
*/
|
*/
|
||||||
SC_FUNC int getlabel(void)
|
int getlabel(void)
|
||||||
{
|
{
|
||||||
return sc_labnum++;
|
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
|
* Converts a number to a hexadecimal string and returns a pointer to that
|
||||||
* string. This function is NOT re-entrant.
|
* string. This function is NOT re-entrant.
|
||||||
*/
|
*/
|
||||||
SC_FUNC char *itoh(ucell val)
|
char *itoh(ucell val)
|
||||||
{
|
{
|
||||||
static char itohstr[30];
|
static char itohstr[30];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -3199,13 +3200,13 @@ static char itohstr[30];
|
|||||||
return itohstr;
|
return itohstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int lextok(token_t *tok)
|
int lextok(token_t *tok)
|
||||||
{
|
{
|
||||||
tok->id = lex(&tok->val, &tok->str);
|
tok->id = lex(&tok->val, &tok->str);
|
||||||
return tok->id;
|
return tok->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int expecttoken(int id, token_t *tok)
|
int expecttoken(int id, token_t *tok)
|
||||||
{
|
{
|
||||||
int rval = needtoken(id);
|
int rval = needtoken(id);
|
||||||
if (rval) {
|
if (rval) {
|
||||||
@ -3217,7 +3218,7 @@ SC_FUNC int expecttoken(int id, token_t *tok)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int matchtoken2(int id, token_t *tok)
|
int matchtoken2(int id, token_t *tok)
|
||||||
{
|
{
|
||||||
if (matchtoken(id)) {
|
if (matchtoken(id)) {
|
||||||
tok->id = tokeninfo(&tok->val, &tok->str);
|
tok->id = tokeninfo(&tok->val, &tok->str);
|
||||||
@ -3226,7 +3227,7 @@ SC_FUNC int matchtoken2(int id, token_t *tok)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int matchsymbol(token_ident_t *ident)
|
int matchsymbol(token_ident_t *ident)
|
||||||
{
|
{
|
||||||
if (lextok(&ident->tok) != tSYMBOL) {
|
if (lextok(&ident->tok) != tSYMBOL) {
|
||||||
lexpush();
|
lexpush();
|
||||||
@ -3237,7 +3238,7 @@ SC_FUNC int matchsymbol(token_ident_t *ident)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int needsymbol(token_ident_t *ident)
|
int needsymbol(token_ident_t *ident)
|
||||||
{
|
{
|
||||||
if (!expecttoken(tSYMBOL, &ident->tok))
|
if (!expecttoken(tSYMBOL, &ident->tok))
|
||||||
return FALSE;
|
return FALSE;
|
@ -35,7 +35,7 @@ static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
|
|||||||
int (*hier)(value*),value *lval);
|
int (*hier)(value*),value *lval);
|
||||||
static void dropout(int lvalue,void (*testfunc)(int val),int exit1,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,
|
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 int plnge1(int (*hier)(value *lval),value *lval);
|
||||||
static void plnge2(void (*oper)(void),
|
static void plnge2(void (*oper)(void),
|
||||||
int (*hier)(value *lval),
|
int (*hier)(value *lval),
|
||||||
@ -113,16 +113,20 @@ static int nextop(int *opidx,int *list)
|
|||||||
return FALSE; /* entire list scanned, nothing found */
|
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)
|
value *lval,int *resulttag)
|
||||||
{
|
{
|
||||||
static char *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "",
|
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 int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||||
static char *unoperstr[] = { "!", "-", "++", "--" };
|
FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||||
static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
|
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];
|
char opername[4] = "", symbolname[sNAMEMAX+1];
|
||||||
int i,swapparams,savepri,savealt;
|
int i,swapparams,savepri,savealt;
|
||||||
int paramspassed;
|
int paramspassed;
|
||||||
@ -286,7 +290,7 @@ static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
|
int checktags_string(int tags[], int numtags, value *sym1)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
|
if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
|
||||||
@ -301,7 +305,7 @@ SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
|
|||||||
return FALSE;
|
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 ||
|
if (sym1->ident == iARRAY || sym2->ident == iARRAY ||
|
||||||
sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
|
sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
|
||||||
@ -317,7 +321,7 @@ SC_FUNC int checktag_string(value *sym1, value *sym2)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC const char *type_to_name(int tag)
|
const char *type_to_name(int tag)
|
||||||
{
|
{
|
||||||
if (tag == 0)
|
if (tag == 0)
|
||||||
return "int";
|
return "int";
|
||||||
@ -335,7 +339,7 @@ SC_FUNC const char *type_to_name(int tag)
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int matchtag_string(int ident, int tag)
|
int matchtag_string(int ident, int tag)
|
||||||
{
|
{
|
||||||
if (ident == iARRAY || ident == iREFARRAY)
|
if (ident == iARRAY || ident == iREFARRAY)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -413,15 +417,81 @@ static int matchobjecttags(int formaltag, int actualtag, int flags)
|
|||||||
return obj_typeerror(133, formaltag, actualtag);
|
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)
|
if (formal->ret_tag == actual->ret_tag)
|
||||||
return TRUE;
|
|
||||||
if (t->ret_tag == pc_tag_void && (sym->tag == 0 && !(sym->usage & uRETVALUE)))
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
if (formal->ret_tag == pc_tag_void) {
|
||||||
|
if (actual->ret_tag == 0 && !(actual->usage & uRETVALUE))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
return FALSE;
|
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)
|
static int matchfunctags(int formaltag, int actualtag)
|
||||||
{
|
{
|
||||||
if (formaltag == pc_functag && (actualtag & FUNCTAG))
|
if (formaltag == pc_functag && (actualtag & FUNCTAG))
|
||||||
@ -433,141 +503,23 @@ static int matchfunctags(int formaltag, int actualtag)
|
|||||||
if (!(actualtag & FUNCTAG))
|
if (!(actualtag & FUNCTAG))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
constvalue *v = find_tag_byval(actualtag);
|
functag_t *actual = functag_find_intrinsic(actualtag);
|
||||||
int index;
|
if (!actual)
|
||||||
short usage = uPUBLIC;
|
|
||||||
symbol *sym, *found = NULL;
|
|
||||||
funcenum_t *e;
|
|
||||||
functag_t *t;
|
|
||||||
|
|
||||||
if (strncmp(v->name, "$Func", 5) != 0)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Now we have to go about looking up each function in this enum. WHICH IS IT. */
|
funcenum_t *e = funcenums_find_by_tag(formaltag);
|
||||||
e = funcenums_find_byval(formaltag);
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
assert(v->name[5] == '@' || v->name[5] == '!');
|
for (functag_t *formal = e->first; formal; formal = formal->next) {
|
||||||
|
if (functag_compare(formal, actual))
|
||||||
/* Deduce which function type this is */
|
return TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int matchtag(int formaltag, int actualtag, int flags)
|
int matchtag(int formaltag, int actualtag, int flags)
|
||||||
{
|
{
|
||||||
if (formaltag == actualtag)
|
if (formaltag == actualtag)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -771,7 +723,7 @@ static void checkfunction(value *lval)
|
|||||||
* Plunge to a lower level
|
* Plunge to a lower level
|
||||||
*/
|
*/
|
||||||
static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
|
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 lvalue,opidx;
|
||||||
int count;
|
int count;
|
||||||
@ -914,10 +866,10 @@ static void plnge2(void (*oper)(void),
|
|||||||
checkfunction(lval1);
|
checkfunction(lval1);
|
||||||
checkfunction(lval2);
|
checkfunction(lval2);
|
||||||
if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
|
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 */
|
error(33,ptr); /* array must be indexed */
|
||||||
} else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) {
|
} 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 */
|
error(33,ptr); /* array must be indexed */
|
||||||
} /* if */
|
} /* if */
|
||||||
/* ??? ^^^ should do same kind of error checking with functions */
|
/* ??? ^^^ 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int lvalexpr(svalue *sval)
|
int lvalexpr(svalue *sval)
|
||||||
{
|
{
|
||||||
memset(sval, 0, sizeof(*sval));
|
memset(sval, 0, sizeof(*sval));
|
||||||
|
|
||||||
@ -1019,7 +971,7 @@ SC_FUNC int lvalexpr(svalue *sval)
|
|||||||
return sval->val.ident;
|
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};
|
value lval={0};
|
||||||
pushheaplist();
|
pushheaplist();
|
||||||
@ -1042,7 +994,7 @@ SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,valu
|
|||||||
return lval.ident;
|
return lval.ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
int sc_getstateid(constvalue **automaton,constvalue **state)
|
||||||
{
|
{
|
||||||
char name[sNAMEMAX+1];
|
char name[sNAMEMAX+1];
|
||||||
cell val;
|
cell val;
|
||||||
@ -1085,7 +1037,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
|||||||
assert(*automaton!=NULL);
|
assert(*automaton!=NULL);
|
||||||
*state=state_find(name,fsa);
|
*state=state_find(name,fsa);
|
||||||
if (*state==NULL) {
|
if (*state==NULL) {
|
||||||
char *fsaname=(*automaton)->name;
|
const char *fsaname=(*automaton)->name;
|
||||||
if (*fsaname=='\0')
|
if (*fsaname=='\0')
|
||||||
fsaname="<main>";
|
fsaname="<main>";
|
||||||
error(87,name,fsaname); /* unknown state for automaton */
|
error(87,name,fsaname); /* unknown state for automaton */
|
||||||
@ -1095,7 +1047,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC cell array_totalsize(symbol *sym)
|
cell array_totalsize(symbol *sym)
|
||||||
{
|
{
|
||||||
cell length;
|
cell length;
|
||||||
|
|
||||||
@ -2281,48 +2233,36 @@ restart:
|
|||||||
} /* if */
|
} /* if */
|
||||||
if (sym!=NULL && lval1->ident==iFUNCTN) {
|
if (sym!=NULL && lval1->ident==iFUNCTN) {
|
||||||
assert(sym->ident==iFUNCTN);
|
assert(sym->ident==iFUNCTN);
|
||||||
if (sc_allowproccall) {
|
|
||||||
// Note: this is unreachable in SourceMod, we don't support paren-less calls.
|
if (sym->usage & uNATIVE) {
|
||||||
callfunction(sym,NULL,lval1,FALSE);
|
error(76);
|
||||||
} 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 */
|
|
||||||
return FALSE;
|
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 */
|
} /* if */
|
||||||
return lvalue;
|
return lvalue;
|
||||||
}
|
}
|
||||||
@ -2590,7 +2530,7 @@ static int nesting=0;
|
|||||||
sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */
|
sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */
|
||||||
|
|
||||||
if ((sym->flags & flgDEPRECATED)!=0) {
|
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) */
|
error(234,sym->name,ptr); /* deprecated (probably a native function) */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
@ -2621,10 +2561,9 @@ static int nesting=0;
|
|||||||
do {
|
do {
|
||||||
if (!pending_this && matchtoken('.')) {
|
if (!pending_this && matchtoken('.')) {
|
||||||
namedparams=TRUE;
|
namedparams=TRUE;
|
||||||
if (needtoken(tSYMBOL))
|
if (!needtoken(tSYMBOL))
|
||||||
tokeninfo(&lexval,&lexstr);
|
break;
|
||||||
else
|
tokeninfo(&lexval,&lexstr);
|
||||||
lexstr="";
|
|
||||||
argpos=findnamedarg(arg,lexstr);
|
argpos=findnamedarg(arg,lexstr);
|
||||||
if (argpos<0) {
|
if (argpos<0) {
|
||||||
error(17,lexstr); /* undefined symbol */
|
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