Merge branch 'master' of https://github.com/alliedmodders/sourcemod
This commit is contained in:
commit
ac121ec4d2
@ -190,7 +190,7 @@ class SMConfig(object):
|
||||
cxx.cflags += ['-Wno-unused-result']
|
||||
if have_clang:
|
||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||
if (builder.target_platform == 'mac' and cxx.version >= '5.1') or cxx.version >= '3.4':
|
||||
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
||||
cxx.cxxflags += ['-Wno-deprecated-register']
|
||||
else:
|
||||
cxx.cxxflags += ['-Wno-deprecated']
|
||||
|
@ -1,6 +0,0 @@
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Please visit [our wiki](https://wiki.alliedmods.net/Contributing_to_SourceMod) for information on how to contribute to Sourcemod.
|
||||
|
||||
As a sidenote, [Travis](https://travis-ci.org/alliedmodders/sourcemod) will automatically build your PR to make sure it compiles on Linux.
|
@ -31,7 +31,6 @@ project.sources += [
|
||||
'smn_console.cpp',
|
||||
'UserMessages.cpp',
|
||||
'MenuManager.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_hudtext.cpp',
|
||||
'smn_usermsgs.cpp',
|
||||
'MenuStyle_Base.cpp',
|
||||
|
@ -383,7 +383,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
{
|
||||
if (!m_CmdGrps.add(i, group))
|
||||
return false;
|
||||
i->value = NoAddRef(new CommandGroup());
|
||||
i->value = new CommandGroup();
|
||||
}
|
||||
Ref<CommandGroup> cmdgroup = i->value;
|
||||
|
||||
|
@ -195,7 +195,7 @@ class GenericCommandHooker : public IConCommandLinkListener
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ public:
|
||||
|
||||
if (dispatch.thisptroffs < 0)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine ConCommand layout");
|
||||
logger->LogError("Command filter could not determine ConCommand layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ public:
|
||||
|
||||
if (!vtables.size())
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find any cvars!");
|
||||
logger->LogError("Command filter could not find any cvars!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ void CoreConfig::Initialize()
|
||||
{
|
||||
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
||||
const char *error = textparsers->GetSMCErrorString(err);
|
||||
g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
|
||||
logger->LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
if (err == ConfigResult_Reject)
|
||||
{
|
||||
/* This is a fatal error */
|
||||
g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
|
||||
logger->LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
@ -469,7 +469,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||
logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||
return can_create;
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
if (!addr)
|
||||
{
|
||||
// Key exists so notify if lookup fails, but try other method.
|
||||
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
logger->LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -186,7 +186,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
int offset;
|
||||
if (!g_pGameConf->GetOffset("gEntList", &offset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
logger->LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
// If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well
|
||||
if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
logger->LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
g_EntList = NULL;
|
||||
return;
|
||||
}
|
||||
@ -211,7 +211,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
|
||||
if (!g_EntList && !g_pEntInfoList)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
logger->LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -225,7 +225,7 @@ void CHalfLife2::InitCommandLine()
|
||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
|
||||
if (lib == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not load %s: %s", TIER0_NAME, error);
|
||||
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ void CHalfLife2::InitCommandLine()
|
||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
|
||||
if (lib == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
||||
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ void CHalfLife2::InitCommandLine()
|
||||
|
||||
if (m_pGetCommandLine == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not locate any command line functionality");
|
||||
logger->LogError("Could not locate any command line functionality");
|
||||
}
|
||||
}
|
||||
|
||||
|
520
core/Logger.cpp
520
core/Logger.cpp
@ -39,61 +39,12 @@
|
||||
#include "logic_bridge.h"
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
Logger g_Logger;
|
||||
bool g_in_game_log_hook = false;
|
||||
|
||||
static LoggerCore g_LoggerCore;
|
||||
|
||||
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
|
||||
|
||||
/**
|
||||
* :TODO: This should be creating the log folder if it doesn't exist
|
||||
*/
|
||||
|
||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength)
|
||||
{
|
||||
if (strcasecmp(key, "Logging") == 0)
|
||||
{
|
||||
bool state;
|
||||
|
||||
if (strcasecmp(value, "on") == 0)
|
||||
{
|
||||
state = true;
|
||||
} else if (strcasecmp(value, "off") == 0) {
|
||||
state = false;
|
||||
} else {
|
||||
UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
if (source == ConfigSource_Console)
|
||||
{
|
||||
state ? EnableLogging() : DisableLogging();
|
||||
} else {
|
||||
m_InitialState = state;
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
} else if (strcasecmp(key, "LogMode") == 0) {
|
||||
if (strcasecmp(value, "daily") == 0)
|
||||
{
|
||||
m_Mode = LoggingMode_Daily;
|
||||
} else if (strcasecmp(value, "map") == 0) {
|
||||
m_Mode = LoggingMode_PerMap;
|
||||
} else if (strcasecmp(value, "game") == 0) {
|
||||
m_Mode = LoggingMode_Game;
|
||||
} else {
|
||||
UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
static void HookLogPrint(const char *message)
|
||||
{
|
||||
g_in_game_log_hook = true;
|
||||
@ -104,477 +55,16 @@ static void HookLogPrint(const char *message)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModStartup(bool late)
|
||||
void LoggerCore::OnSourceModStartup(bool late)
|
||||
{
|
||||
InitLogger(m_Mode);
|
||||
|
||||
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModAllShutdown()
|
||||
void LoggerCore::OnSourceModAllShutdown()
|
||||
{
|
||||
CloseLogger();
|
||||
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
||||
{
|
||||
MapChange(mapName);
|
||||
}
|
||||
|
||||
void Logger::_NewMapFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Append "Log file closed" to previous log file */
|
||||
_CloseFile();
|
||||
|
||||
char _filename[256];
|
||||
int i = 0;
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
||||
FILE *fp = fopen(_filename, "r");
|
||||
if (!fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
i++;
|
||||
}
|
||||
m_NrmFileName.assign(_filename);
|
||||
|
||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
||||
if (!fp)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (!m_NrmFileName.empty())
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogMessage("Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_NrmFileName.clear();
|
||||
}
|
||||
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogError("Error log file session closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_ErrFileName.clear();
|
||||
}
|
||||
|
||||
void Logger::InitLogger(LoggingMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
m_Active = m_InitialState;
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
|
||||
char _filename[256];
|
||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
m_DelayedStart = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_DailyPrintHdr = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::CloseLogger()
|
||||
{
|
||||
_CloseFile();
|
||||
}
|
||||
|
||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogToFileOnlyEx(fp, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
|
||||
if (!sv_logecho || sv_logecho->GetBool())
|
||||
{
|
||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[3072];
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void Logger::LogMessage(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogMessageEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Mode == LoggingMode_Game)
|
||||
{
|
||||
_PrintToGameLog(vafmt, ap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_DelayedStart)
|
||||
{
|
||||
m_DelayedStart = false;
|
||||
_NewMapFile();
|
||||
}
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (m_Mode == LoggingMode_PerMap)
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
_NewMapFile();
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
goto print_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_NrmCurDay != curtime->tm_mday)
|
||||
{
|
||||
char _filename[256];
|
||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_DailyPrintHdr = true;
|
||||
}
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
if (m_DailyPrintHdr)
|
||||
{
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
} else {
|
||||
goto print_error;
|
||||
}
|
||||
|
||||
return;
|
||||
print_error:
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (curtime->tm_mday != m_ErrCurDay)
|
||||
{
|
||||
char _filename[256];
|
||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
||||
if (fp)
|
||||
{
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::MapChange(const char *mapname)
|
||||
{
|
||||
m_CurMapName.assign(mapname);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
LogMessage("-------- Mapchange to %s --------", mapname);
|
||||
break;
|
||||
}
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
_NewMapFile();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ErrMapStart)
|
||||
{
|
||||
LogError("Error log file session closed.");
|
||||
}
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
||||
{
|
||||
char msg[3072];
|
||||
size_t len;
|
||||
|
||||
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
|
||||
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
|
||||
|
||||
msg[len++] = '\n';
|
||||
msg[len] = '\0';
|
||||
|
||||
Engine_LogPrintWrapper(msg);
|
||||
}
|
||||
|
||||
const char *Logger::GetLogFileName(LogType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LogType_Normal:
|
||||
{
|
||||
return m_NrmFileName.c_str();
|
||||
}
|
||||
case LogType_Error:
|
||||
{
|
||||
return m_ErrFileName.c_str();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoggingMode Logger::GetLoggingMode() const
|
||||
{
|
||||
return m_Mode;
|
||||
}
|
||||
|
||||
void Logger::EnableLogging()
|
||||
{
|
||||
if (m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Active = true;
|
||||
LogMessage("[SM] Logging enabled manually by user.");
|
||||
}
|
||||
|
||||
void Logger::DisableLogging()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LogMessage("[SM] Logging disabled manually by user.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogFatal(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogFatalEx(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||
{
|
||||
/* :TODO: make this print all pretty-like
|
||||
* In fact, the pretty log printing function should be abstracted.
|
||||
* It's already implemented twice which is bad.
|
||||
*/
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (fp)
|
||||
{
|
||||
m_Active = true;
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
m_Active = false;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
bool g_in_game_log_hook = false;
|
||||
|
||||
void Engine_LogPrintWrapper(const char *msg)
|
||||
{
|
||||
if (g_in_game_log_hook)
|
||||
|
@ -38,76 +38,13 @@
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
enum LogType
|
||||
class LoggerCore : public SMGlobalClass
|
||||
{
|
||||
LogType_Normal,
|
||||
LogType_Error
|
||||
};
|
||||
|
||||
enum LoggingMode
|
||||
{
|
||||
LoggingMode_Daily,
|
||||
LoggingMode_PerMap,
|
||||
LoggingMode_Game
|
||||
};
|
||||
|
||||
class Logger : public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
||||
m_InitialState(true)
|
||||
{
|
||||
}
|
||||
public: //SMGlobalClass
|
||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllShutdown();
|
||||
void OnSourceModLevelChange(const char *mapName);
|
||||
public:
|
||||
void InitLogger(LoggingMode mode);
|
||||
void CloseLogger();
|
||||
void EnableLogging();
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogMessageEx(const char *msg, va_list ap);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogFatalEx(const char *msg, va_list ap);
|
||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
||||
/* This version does not print to console, and is thus thread-safe */
|
||||
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
||||
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
||||
void MapChange(const char *mapname);
|
||||
const char *GetLogFileName(LogType type) const;
|
||||
LoggingMode GetLoggingMode() const;
|
||||
private:
|
||||
void _CloseFile();
|
||||
void _NewMapFile();
|
||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
||||
private:
|
||||
String m_NrmFileName;
|
||||
String m_ErrFileName;
|
||||
String m_CurMapName;
|
||||
LoggingMode m_Mode;
|
||||
int m_NrmCurDay;
|
||||
int m_ErrCurDay;
|
||||
bool m_ErrMapStart;
|
||||
bool m_Active;
|
||||
bool m_DelayedStart;
|
||||
bool m_DailyPrintHdr;
|
||||
bool m_InitialState;
|
||||
};
|
||||
|
||||
void Engine_LogPrintWrapper(const char *msg);
|
||||
|
||||
extern bool g_in_game_log_hook;
|
||||
extern Logger g_Logger;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcehook.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
NextMapManager g_NextMap;
|
||||
|
||||
@ -130,7 +131,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
{
|
||||
if (g_forcedChange)
|
||||
{
|
||||
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
|
||||
logger->LogMessage("[SM] Changed map to \"%s\"", map);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap);
|
||||
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
|
||||
|
||||
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||
|
@ -1238,7 +1238,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||
{
|
||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
||||
g_Logger.LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
logger->LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||
|
||||
pPlayer->Kick("NetworkID spoofing detected.");
|
||||
|
@ -66,6 +66,8 @@ binary.sources += [
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
]
|
||||
if builder.target_platform == 'windows':
|
||||
binary.sources += ['thread/WinThreads.cpp']
|
||||
|
@ -198,11 +198,11 @@ private:
|
||||
|
||||
if (!m_bFileNameLogged)
|
||||
{
|
||||
smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
|
||||
logger->LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
|
||||
m_bFileNameLogged = true;
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
|
||||
logger->LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
|
||||
}
|
||||
private:
|
||||
bool m_bFileNameLogged;
|
||||
|
@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
|
||||
ke::AutoLock lock(&m_ConfigLock);
|
||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
||||
{
|
||||
smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||
if (err != SMCError_Custom)
|
||||
{
|
||||
const char *txt = textparsers->GetSMCErrorString(err);
|
||||
smcore.LogError("[SM] Line %d: %s", states.line, txt);
|
||||
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -541,7 +541,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
||||
{
|
||||
if (!s_OneTimeThreaderErrorMsg)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to create db threader (error unknown)");
|
||||
logger->LogError("[SM] Unable to create db threader (error unknown)");
|
||||
s_OneTimeThreaderErrorMsg = true;
|
||||
}
|
||||
m_Worker = NULL;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <IPluginSys.h>
|
||||
#include <stdarg.h>
|
||||
#include "DebugReporter.h"
|
||||
#include "Logger.h"
|
||||
|
||||
DebugReport g_DbgReporter;
|
||||
|
||||
@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
smcore.Log("[SM] %s", buffer);
|
||||
g_Logger.LogMessage("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
||||
@ -71,12 +72,12 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
||||
|
||||
if (error)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
} else {
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
|
||||
if (func_idx != -1)
|
||||
{
|
||||
@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
||||
sp_public_t *function;
|
||||
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,18 +107,18 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
||||
|
||||
if (error)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
} else {
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
|
||||
IPluginDebugInfo *pDebug;
|
||||
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
_GetPluginIndex(pContext));
|
||||
return;
|
||||
}
|
||||
@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
||||
const char *name;
|
||||
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
||||
g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +140,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
||||
|
||||
if (n_err != SP_ERROR_NATIVE)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin encountered error %d: %s",
|
||||
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
|
||||
n_err,
|
||||
error->GetErrorString());
|
||||
}
|
||||
@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
||||
const char *custerr;
|
||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
||||
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
||||
} else {
|
||||
smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
||||
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
||||
}
|
||||
}
|
||||
|
||||
if (!error->DebugInfoAvailable())
|
||||
{
|
||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
_GetPluginIndex(ctx));
|
||||
return;
|
||||
}
|
||||
|
||||
CallStackInfo stk_info;
|
||||
int i = 0;
|
||||
smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
||||
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
||||
while (error->GetTraceInfo(&stk_info))
|
||||
{
|
||||
smcore.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||
i++,
|
||||
stk_info.line,
|
||||
stk_info.filename,
|
||||
|
@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
||||
{
|
||||
if (bErrorOnMissing || libsys->IsPathFile(p->GetPath()))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
}
|
||||
|
||||
p->SetError(error);
|
||||
@ -1360,6 +1360,24 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount,
|
||||
}
|
||||
}
|
||||
|
||||
void CExtensionManager::CallOnCoreMapEnd()
|
||||
{
|
||||
IExtensionInterface *pAPI;
|
||||
List<CExtension *>::iterator iter;
|
||||
|
||||
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
||||
{
|
||||
if ((pAPI = (*iter)->GetAPI()) == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pAPI->GetExtensionVersion() > 7)
|
||||
{
|
||||
pAPI->OnCoreMapEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CVector<IExtension *> *CExtensionManager::ListExtensions()
|
||||
{
|
||||
CVector<IExtension *> *list = new CVector<IExtension *>();
|
||||
|
@ -173,6 +173,7 @@ public:
|
||||
void AddLibrary(IExtension *pSource, const char *library);
|
||||
bool LibraryExists(const char *library);
|
||||
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
void CallOnCoreMapEnd();
|
||||
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
||||
const CVector<IExtension *> *ListExtensions();
|
||||
void FreeExtensionList(const CVector<IExtension *> *list);
|
||||
|
@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
if (error[0] != '\0')
|
||||
{
|
||||
m_IgnoreLevel = 1;
|
||||
smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
smcore.LogError("[SM] %s", error);
|
||||
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
logger->LogError("[SM] %s", error);
|
||||
} else {
|
||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
||||
}
|
||||
@ -335,8 +335,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
{
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
|
||||
{
|
||||
smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
}
|
||||
m_IgnoreLevel = 1;
|
||||
}
|
||||
@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
}
|
||||
else
|
||||
{
|
||||
smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||
}
|
||||
} else if (strcmp(key, "signature") == 0) {
|
||||
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
|
||||
@ -503,7 +503,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
|
||||
&& (!m_Offsets.retrieve(m_offset)))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
m_Class,
|
||||
m_Prop,
|
||||
m_CurFile,
|
||||
@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
void *final_addr = NULL;
|
||||
if (addrInBase == NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_CurFile);
|
||||
}
|
||||
@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
|
||||
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
|
||||
else
|
||||
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
|
||||
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
|
||||
#elif defined PLATFORM_POSIX
|
||||
Dl_info info;
|
||||
/* GNU only: returns 0 on error, inconsistent! >:[ */
|
||||
@ -585,12 +585,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
||||
dlclose(handle);
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_File);
|
||||
}
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_File);
|
||||
}
|
||||
@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||
{
|
||||
const char *msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
state.col,
|
||||
@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
const char *msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
state.col,
|
||||
@ -1082,6 +1082,7 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
|
||||
}
|
||||
|
||||
pConfig = new CGameConfig(file);
|
||||
pConfig->AddRef();
|
||||
|
||||
/* :HACKHACK: Don't parse the main config file */
|
||||
bool retval = true;
|
||||
|
@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
||||
}
|
||||
|
||||
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||
smcore.LogFatal(message, ##__VA_ARGS__); \
|
||||
smcore.LogError(message, ##__VA_ARGS__);
|
||||
logger->LogFatal(message, ##__VA_ARGS__); \
|
||||
logger->LogError(message, ##__VA_ARGS__);
|
||||
|
||||
bool HandleSystem::TryAndFreeSomeHandles()
|
||||
{
|
||||
|
551
core/logic/Logger.cpp
Normal file
551
core/logic/Logger.cpp
Normal file
@ -0,0 +1,551 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <cstdarg>
|
||||
#include "Logger.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
Logger g_Logger;
|
||||
|
||||
/**
|
||||
* :TODO: This should be creating the log folder if it doesn't exist
|
||||
*/
|
||||
|
||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength)
|
||||
{
|
||||
if (strcasecmp(key, "Logging") == 0)
|
||||
{
|
||||
bool state;
|
||||
|
||||
if (strcasecmp(value, "on") == 0)
|
||||
{
|
||||
state = true;
|
||||
} else if (strcasecmp(value, "off") == 0) {
|
||||
state = false;
|
||||
} else {
|
||||
smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
if (source == ConfigSource_Console)
|
||||
{
|
||||
state ? EnableLogging() : DisableLogging();
|
||||
} else {
|
||||
m_InitialState = state;
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
} else if (strcasecmp(key, "LogMode") == 0) {
|
||||
if (strcasecmp(value, "daily") == 0)
|
||||
{
|
||||
m_Mode = LoggingMode_Daily;
|
||||
} else if (strcasecmp(value, "map") == 0) {
|
||||
m_Mode = LoggingMode_PerMap;
|
||||
} else if (strcasecmp(value, "game") == 0) {
|
||||
m_Mode = LoggingMode_Game;
|
||||
} else {
|
||||
smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
void Logger::OnSourceModStartup(bool late)
|
||||
{
|
||||
InitLogger(m_Mode);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModAllShutdown()
|
||||
{
|
||||
CloseLogger();
|
||||
}
|
||||
|
||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
||||
{
|
||||
MapChange(mapName);
|
||||
}
|
||||
|
||||
void Logger::_NewMapFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Append "Log file closed" to previous log file */
|
||||
_CloseFile();
|
||||
|
||||
char _filename[256];
|
||||
int i = 0;
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
||||
FILE *fp = fopen(_filename, "r");
|
||||
if (!fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
i++;
|
||||
}
|
||||
m_NrmFileName.assign(_filename);
|
||||
|
||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
||||
if (!fp)
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (!m_NrmFileName.empty())
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogMessage("Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_NrmFileName.clear();
|
||||
}
|
||||
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogError("Error log file session closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_ErrFileName.clear();
|
||||
}
|
||||
|
||||
void Logger::InitLogger(LoggingMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
m_Active = m_InitialState;
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
m_DelayedStart = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_DailyPrintHdr = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::CloseLogger()
|
||||
{
|
||||
_CloseFile();
|
||||
}
|
||||
|
||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogToFileOnlyEx(fp, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
|
||||
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
|
||||
{
|
||||
static char conBuffer[4096];
|
||||
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
|
||||
smcore.ConPrint(conBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[3072];
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void Logger::LogMessage(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogMessageEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Mode == LoggingMode_Game)
|
||||
{
|
||||
_PrintToGameLog(vafmt, ap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_DelayedStart)
|
||||
{
|
||||
m_DelayedStart = false;
|
||||
_NewMapFile();
|
||||
}
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (m_Mode == LoggingMode_PerMap)
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
_NewMapFile();
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
goto print_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_NrmCurDay != curtime->tm_mday)
|
||||
{
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_DailyPrintHdr = true;
|
||||
}
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
if (m_DailyPrintHdr)
|
||||
{
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
} else {
|
||||
goto print_error;
|
||||
}
|
||||
|
||||
return;
|
||||
print_error:
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (curtime->tm_mday != m_ErrCurDay)
|
||||
{
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
||||
if (fp)
|
||||
{
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::MapChange(const char *mapname)
|
||||
{
|
||||
m_CurMapName.assign(mapname);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
LogMessage("-------- Mapchange to %s --------", mapname);
|
||||
break;
|
||||
}
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
_NewMapFile();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ErrMapStart)
|
||||
{
|
||||
LogError("Error log file session closed.");
|
||||
}
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
||||
{
|
||||
char msg[3072];
|
||||
size_t len;
|
||||
|
||||
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
|
||||
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
|
||||
|
||||
msg[len++] = '\n';
|
||||
msg[len] = '\0';
|
||||
|
||||
smcore.LogToGame(msg);
|
||||
}
|
||||
|
||||
const char *Logger::GetLogFileName(LogType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LogType_Normal:
|
||||
{
|
||||
return m_NrmFileName.c_str();
|
||||
}
|
||||
case LogType_Error:
|
||||
{
|
||||
return m_ErrFileName.c_str();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoggingMode Logger::GetLoggingMode() const
|
||||
{
|
||||
return m_Mode;
|
||||
}
|
||||
|
||||
void Logger::EnableLogging()
|
||||
{
|
||||
if (m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Active = true;
|
||||
LogMessage("[SM] Logging enabled manually by user.");
|
||||
}
|
||||
|
||||
void Logger::DisableLogging()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LogMessage("[SM] Logging disabled manually by user.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogFatal(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogFatalEx(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||
{
|
||||
/* :TODO: make this print all pretty-like
|
||||
* In fact, the pretty log printing function should be abstracted.
|
||||
* It's already implemented twice which is bad.
|
||||
*/
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (fp)
|
||||
{
|
||||
m_Active = true;
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
m_Active = false;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
111
core/logic/Logger.h
Normal file
111
core/logic/Logger.h
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sh_string.h>
|
||||
|
||||
#include "common_logic.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
enum LogType
|
||||
{
|
||||
LogType_Normal,
|
||||
LogType_Error
|
||||
};
|
||||
|
||||
enum LoggingMode
|
||||
{
|
||||
LoggingMode_Daily,
|
||||
LoggingMode_PerMap,
|
||||
LoggingMode_Game
|
||||
};
|
||||
|
||||
class Logger : public SMGlobalClass, public ILogger
|
||||
{
|
||||
public:
|
||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
||||
m_InitialState(true)
|
||||
{
|
||||
}
|
||||
public: //SMGlobalClass
|
||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllShutdown();
|
||||
void OnSourceModLevelChange(const char *mapName);
|
||||
public:
|
||||
void InitLogger(LoggingMode mode);
|
||||
void CloseLogger();
|
||||
void EnableLogging();
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogMessageEx(const char *msg, va_list ap);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogFatalEx(const char *msg, va_list ap);
|
||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
||||
/* This version does not print to console, and is thus thread-safe */
|
||||
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
||||
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
||||
void MapChange(const char *mapname);
|
||||
const char *GetLogFileName(LogType type) const;
|
||||
LoggingMode GetLoggingMode() const;
|
||||
private:
|
||||
void _CloseFile();
|
||||
void _NewMapFile();
|
||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
||||
private:
|
||||
String m_NrmFileName;
|
||||
String m_ErrFileName;
|
||||
String m_CurMapName;
|
||||
LoggingMode m_Mode;
|
||||
int m_NrmCurDay;
|
||||
int m_ErrCurDay;
|
||||
bool m_ErrMapStart;
|
||||
bool m_Active;
|
||||
bool m_DelayedStart;
|
||||
bool m_DailyPrintHdr;
|
||||
bool m_InitialState;
|
||||
};
|
||||
|
||||
extern Logger g_Logger;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
@ -42,6 +42,7 @@
|
||||
#include "GameConfigs.h"
|
||||
#include "common_logic.h"
|
||||
#include "Translator.h"
|
||||
#include "Logger.h"
|
||||
|
||||
CPluginManager g_PluginSys;
|
||||
HandleType_t g_PluginType = 0;
|
||||
@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
{
|
||||
char error[256];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
smcore.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
||||
smcore.LogError("[SM] Platform returned error: %s", error);
|
||||
g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
||||
g_Logger.LogError("[SM] Platform returned error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de
|
||||
} else {
|
||||
if (bulletinUrl[0] != '\0')
|
||||
{
|
||||
smcore.Log("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
|
||||
g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
|
||||
} else {
|
||||
smcore.Log("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
|
||||
g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1094,7 +1095,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
|
||||
|
||||
if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
|
||||
{
|
||||
smcore.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
|
||||
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
|
||||
pl->SetErrorState(
|
||||
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
||||
"%s",
|
||||
@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass()
|
||||
error[0] = '\0';
|
||||
if (!RunSecondPass(pPlugin, error, sizeof(error)))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
|
||||
g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nat
|
||||
if (i.found())
|
||||
return NULL;
|
||||
|
||||
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv));
|
||||
Ref<Native> entry = new Native(pOwner, ntv);
|
||||
m_NtvCache.insert(ntv->name, entry);
|
||||
return entry;
|
||||
}
|
||||
@ -415,7 +415,7 @@ PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n
|
||||
|
||||
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
|
||||
|
||||
entry = Newborn<Native>(new Native(owner, fake.take()));
|
||||
entry = new Native(owner, fake.take());
|
||||
m_NtvCache.insert(name, entry);
|
||||
|
||||
return entry;
|
||||
|
@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
|
||||
|
||||
if (!m_FileLogged)
|
||||
{
|
||||
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
m_FileLogged = true;
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
logger->LogError("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void CPhraseFile::ReparseFile()
|
||||
@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
}
|
||||
|
||||
const char *code;
|
||||
@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
code,
|
||||
m_File.c_str());
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s",
|
||||
logger->LogError("[SM] Error (line %d, column %d): %s",
|
||||
states.line,
|
||||
states.col,
|
||||
msg);
|
||||
@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase()
|
||||
str_err = m_CustomError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path);
|
||||
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
logger->LogError("[SM] Failed to parse language header file: \"%s\"", path);
|
||||
logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
}
|
||||
|
||||
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang))
|
||||
{
|
||||
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
|
||||
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase()
|
||||
|
||||
if (!m_Languages.size())
|
||||
{
|
||||
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
logger->LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
}
|
||||
|
||||
for (size_t i=0; i<m_Files.size(); i++)
|
||||
@ -872,7 +872,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
|
||||
|
||||
if (!m_InLanguageSection)
|
||||
{
|
||||
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
logger->LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
@ -1025,11 +1025,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
|
||||
{
|
||||
if (fail_phrase != NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
logger->LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
}
|
||||
else
|
||||
{
|
||||
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
logger->LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "ForwardSys.h"
|
||||
#include "AdminCache.h"
|
||||
#include "ProfileTools.h"
|
||||
#include "Logger.h"
|
||||
|
||||
sm_core_t smcore;
|
||||
IHandleSys *handlesys = &g_HandleSys;
|
||||
@ -72,6 +73,8 @@ ISourcePawnEngine *g_pSourcePawn;
|
||||
ISourcePawnEngine2 *g_pSourcePawn2;
|
||||
CNativeOwner g_CoreNatives;
|
||||
IScriptManager *scripts = &g_PluginSys;
|
||||
IExtensionSys *extsys = &g_Extensions;
|
||||
ILogger *logger = &g_Logger;
|
||||
|
||||
static void AddCorePhraseFile(const char *filename)
|
||||
{
|
||||
@ -140,6 +143,7 @@ static sm_logic_t logic =
|
||||
&g_Forwards,
|
||||
&g_Admins,
|
||||
NULL,
|
||||
&g_Logger,
|
||||
-1.0f
|
||||
};
|
||||
|
||||
|
@ -53,6 +53,8 @@ extern IPlayerManager *playerhelpers;
|
||||
extern IAdminSystem *adminsys;
|
||||
extern IGameHelpers *gamehelpers;
|
||||
extern IScriptManager *scripts;
|
||||
extern IExtensionSys *extsys;
|
||||
extern ILogger *logger;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
||||
|
||||
|
@ -52,7 +52,7 @@ using namespace SourceHook;
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 28)
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
@ -211,6 +211,15 @@ public:
|
||||
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
|
||||
virtual const CVector<IExtension *> *ListExtensions() = 0;
|
||||
virtual void FreeExtensionList(const CVector<IExtension *> *list) = 0;
|
||||
virtual void CallOnCoreMapEnd() = 0;
|
||||
};
|
||||
|
||||
class ILogger
|
||||
{
|
||||
public:
|
||||
virtual void LogMessage(const char *msg, ...) = 0;
|
||||
virtual void LogError(const char *msg, ...) = 0;
|
||||
virtual void LogFatal(const char *msg, ...) = 0;
|
||||
};
|
||||
|
||||
class AutoPluginList
|
||||
@ -273,13 +282,10 @@ struct sm_core_t
|
||||
ConVar * (*FindConVar)(const char*);
|
||||
unsigned int (*strncopy)(char*, const char*, size_t);
|
||||
char * (*TrimWhitespace)(char *, size_t &);
|
||||
void (*LogError)(const char*, ...);
|
||||
void (*LogFatal)(const char*, ...);
|
||||
void (*Log)(const char*, ...);
|
||||
void (*LogToFile)(FILE *fp, const char*, ...);
|
||||
void (*LogToGame)(const char *message);
|
||||
void (*ConPrint)(const char *message);
|
||||
const char * (*GetCvarString)(ConVar*);
|
||||
bool (*GetCvarBool)(ConVar*);
|
||||
size_t (*Format)(char*, size_t, const char*, ...);
|
||||
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
|
||||
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
|
||||
@ -325,7 +331,7 @@ struct sm_logic_t
|
||||
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
|
||||
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
|
||||
IGameConfig * (*GetCoreGameConfig)();
|
||||
bool (*OnLogPrint)(const char *msg); // true to supercede
|
||||
bool (*OnLogPrint)(const char *msg); // true to supersede
|
||||
IDebugListener *debugger;
|
||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||
void (*AddNatives)(sp_nativeinfo_t *natives);
|
||||
@ -339,6 +345,7 @@ struct sm_logic_t
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
IdentityToken_t *core_ident;
|
||||
ILogger *logger;
|
||||
float sentinel;
|
||||
};
|
||||
|
||||
|
@ -163,7 +163,7 @@ private:
|
||||
cell_t data_;
|
||||
};
|
||||
|
||||
struct CellTrie : public ke::Refcounted<CellTrie>
|
||||
struct CellTrie
|
||||
{
|
||||
StringHashMap<Entry> map;
|
||||
};
|
||||
@ -204,8 +204,7 @@ public: //IHandleTypeDispatch
|
||||
{
|
||||
if (type == htCellTrie)
|
||||
{
|
||||
CellTrie *pTrie = (CellTrie *)object;
|
||||
pTrie->Release();
|
||||
delete (CellTrie *)object;
|
||||
} else {
|
||||
TrieSnapshot *snapshot = (TrieSnapshot *)object;
|
||||
delete snapshot;
|
||||
|
@ -32,14 +32,14 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemod.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "TimerSys.h"
|
||||
#include "common_logic.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <ISourceMod.h>
|
||||
#include <ITranslator.h>
|
||||
|
||||
#include <sourcehook.h>
|
||||
#include <sh_memory.h>
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
@ -50,9 +50,11 @@
|
||||
#endif
|
||||
|
||||
HandleType_t g_PlIter;
|
||||
ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules");
|
||||
|
||||
IForward *g_OnLogAction = NULL;
|
||||
|
||||
static ConVar *sm_datetime_format = NULL;
|
||||
|
||||
class CoreNativeHelpers :
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch
|
||||
@ -75,6 +77,8 @@ public:
|
||||
Param_Cell,
|
||||
Param_Cell,
|
||||
Param_String);
|
||||
|
||||
sm_datetime_format = smcore.FindConVar("sm_datetime_format");
|
||||
}
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
@ -119,14 +123,14 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess
|
||||
|
||||
g_Logger.LogMessage("[%s] %s", logtag, message);
|
||||
}
|
||||
|
||||
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
|
||||
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
|
||||
{
|
||||
@ -138,7 +142,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
time_t t = GetAdjustedTime();
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[1], &addr);
|
||||
|
||||
@ -168,14 +172,14 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (format == NULL)
|
||||
{
|
||||
format = const_cast<char *>(sm_datetime_format.GetString());
|
||||
format = const_cast<char *>(smcore.GetCvarString(sm_datetime_format));
|
||||
}
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
||||
#endif
|
||||
|
||||
time_t t = (params[4] == -1) ? GetAdjustedTime() : (time_t)params[4];
|
||||
time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4];
|
||||
size_t written = strftime(buffer, params[2], format, localtime(&t));
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
@ -384,7 +388,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
pPlugin->SetErrorState(Plugin_Error, "%s", str);
|
||||
@ -433,14 +437,14 @@ static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
|
||||
static char temp_file[PLATFORM_MAX_PATH];
|
||||
char *ptr;
|
||||
|
||||
g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
|
||||
libsys->GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
|
||||
if ((ptr = strstr(temp_str, ".smx")) != NULL)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
/* We have the raw filename! */
|
||||
UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
|
||||
g_pSM->Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
|
||||
cfg = temp_file;
|
||||
}
|
||||
|
||||
@ -506,8 +510,8 @@ static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params)
|
||||
static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@ -527,7 +531,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[1], &file);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (!fp)
|
||||
@ -536,8 +540,8 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@ -560,7 +564,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[1], &file);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (!fp)
|
||||
@ -569,8 +573,8 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@ -653,10 +657,10 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
|
||||
char default_message[255];
|
||||
SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0')
|
||||
{
|
||||
UTIL_Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
|
||||
g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
|
||||
msg = default_message;
|
||||
}
|
||||
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
|
||||
@ -743,19 +747,19 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
REGISTER_NATIVES(coreNatives)
|
||||
{
|
||||
{"AutoExecConfig", AutoExecConfig},
|
||||
{"GetPluginFilename", GetPluginFilename},
|
||||
{"GetPluginInfo", GetPluginInfo},
|
||||
{"GetPluginIterator", GetPluginIterator},
|
||||
{"GetPluginStatus", GetPluginStatus},
|
||||
{"GetSysTickCount", GetSysTickCount},
|
||||
{"ThrowError", ThrowError},
|
||||
{"GetTime", GetTime},
|
||||
{"IsPluginDebugging", IsPluginDebugging},
|
||||
{"FormatTime", FormatTime},
|
||||
{"GetPluginIterator", GetPluginIterator},
|
||||
{"MorePlugins", MorePlugins},
|
||||
{"ReadPlugin", ReadPlugin},
|
||||
{"ThrowError", ThrowError},
|
||||
{"GetPluginStatus", GetPluginStatus},
|
||||
{"GetPluginFilename", GetPluginFilename},
|
||||
{"IsPluginDebugging", IsPluginDebugging},
|
||||
{"GetPluginInfo", GetPluginInfo},
|
||||
{"SetFailState", SetFailState},
|
||||
{"FormatTime", FormatTime},
|
||||
{"GetSysTickCount", GetSysTickCount},
|
||||
{"AutoExecConfig", AutoExecConfig},
|
||||
{"MarkNativeAsOptional", MarkNativeAsOptional},
|
||||
{"RegPluginLibrary", RegPluginLibrary},
|
||||
{"LibraryExists", LibraryExists},
|
||||
@ -770,5 +774,4 @@ REGISTER_NATIVES(coreNatives)
|
||||
{"LoadFromAddress", LoadFromAddress},
|
||||
{"StoreToAddress", StoreToAddress},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
};
|
@ -38,6 +38,21 @@
|
||||
#include <ISourceMod.h>
|
||||
#include <ITranslator.h>
|
||||
#include "common_logic.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#include <io.h>
|
||||
|
||||
#define FPERM_U_READ 0x0100 /* User can read. */
|
||||
#define FPERM_U_WRITE 0x0080 /* User can write. */
|
||||
#define FPERM_U_EXEC 0x0040 /* User can exec. */
|
||||
#define FPERM_G_READ 0x0020 /* Group can read. */
|
||||
#define FPERM_G_WRITE 0x0010 /* Group can write. */
|
||||
#define FPERM_G_EXEC 0x0008 /* Group can exec. */
|
||||
#define FPERM_O_READ 0x0004 /* Anyone can read. */
|
||||
#define FPERM_O_WRITE 0x0002 /* Anyone can write. */
|
||||
#define FPERM_O_EXEC 0x0001 /* Anyone can exec. */
|
||||
#endif
|
||||
|
||||
HandleType_t g_FileType;
|
||||
HandleType_t g_DirType;
|
||||
@ -465,6 +480,31 @@ static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
|
||||
#endif
|
||||
}
|
||||
|
||||
static cell_t sm_SetFilePermissions(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
char realpath[PLATFORM_MAX_PATH];
|
||||
|
||||
pContext->LocalToString(params[1], &name);
|
||||
g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
int mask = 0;
|
||||
if (params[2] & FPERM_U_WRITE || params[2] & FPERM_G_WRITE || params[2] & FPERM_O_WRITE)
|
||||
{
|
||||
mask |= _S_IWRITE;
|
||||
}
|
||||
if (params[2] & FPERM_U_READ || params[2] & FPERM_G_READ || params[2] & FPERM_O_READ ||
|
||||
params[2] & FPERM_U_EXEC || params[2] & FPERM_G_EXEC || params[2] & FPERM_O_EXEC)
|
||||
{
|
||||
mask |= _S_IREAD;
|
||||
}
|
||||
return _chmod(realpath, mask) == 0;
|
||||
#else
|
||||
return chmod(realpath, params[2]) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
@ -598,7 +638,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
smcore.Log("[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -616,7 +656,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
smcore.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -669,7 +709,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
smcore.LogToFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -699,7 +739,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
smcore.LogToFile(pFile, "%s", buffer);
|
||||
g_Logger.LogToOpenFile(pFile, "%s", buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -971,5 +1011,6 @@ REGISTER_NATIVES(filesystem)
|
||||
{"AddGameLogHook", sm_AddGameLogHook},
|
||||
{"RemoveGameLogHook", sm_RemoveGameLogHook},
|
||||
{"CreateDirectory", sm_CreateDirectory},
|
||||
{"SetFilePermissions", sm_SetFilePermissions},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
@ -202,8 +202,8 @@ public:
|
||||
{
|
||||
errmsg = "Unknown error";
|
||||
}
|
||||
smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||
logger->LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
logger->LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -120,7 +120,7 @@ public: //ICommandTargetProcessor
|
||||
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
|
||||
AutoHandleCloner ahc(hndl, sec);
|
||||
if (ahc.getClone() == BAD_HANDLE) {
|
||||
smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
|
||||
logger->LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
|
||||
delete array;
|
||||
return false;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ IExtensionSys *extsys;
|
||||
IHandleSys *handlesys;
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
ILogger *logger;
|
||||
|
||||
class VEngineServer_Logic : public IVEngineServer_Logic
|
||||
{
|
||||
@ -251,46 +252,13 @@ static VPlayerInfo_Logic logic_playerinfo;
|
||||
|
||||
static ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)");
|
||||
static ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection");
|
||||
static ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules");
|
||||
|
||||
static ConVar *find_convar(const char *name)
|
||||
{
|
||||
return icvar->FindVar(name);
|
||||
}
|
||||
|
||||
static void log_error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogErrorEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_fatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogFatalEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_message(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogMessageEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_to_file(FILE *fp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogToOpenFileEx(fp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_to_game(const char *message)
|
||||
{
|
||||
Engine_LogPrintWrapper(message);
|
||||
@ -306,6 +274,11 @@ static const char *get_cvar_string(ConVar* cvar)
|
||||
return cvar->GetString();
|
||||
}
|
||||
|
||||
static bool get_cvar_bool(ConVar* cvar)
|
||||
{
|
||||
return cvar->GetBool();
|
||||
}
|
||||
|
||||
static bool get_game_name(char *buffer, size_t maxlength)
|
||||
{
|
||||
KeyValues *pGameInfo = new KeyValues("GameInfo");
|
||||
@ -561,13 +534,10 @@ static sm_core_t core_bridge =
|
||||
find_convar,
|
||||
strncopy,
|
||||
UTIL_TrimWhitespace,
|
||||
log_error,
|
||||
log_fatal,
|
||||
log_message,
|
||||
log_to_file,
|
||||
log_to_game,
|
||||
conprint,
|
||||
get_cvar_string,
|
||||
get_cvar_bool,
|
||||
UTIL_Format,
|
||||
UTIL_FormatArgs,
|
||||
gnprintf,
|
||||
@ -636,6 +606,7 @@ void InitLogicBridge()
|
||||
handlesys = logicore.handlesys;
|
||||
forwardsys = logicore.forwardsys;
|
||||
adminsys = logicore.adminsys;
|
||||
logger = logicore.logger;
|
||||
}
|
||||
|
||||
bool StartLogicBridge(char *error, size_t maxlength)
|
||||
|
@ -48,5 +48,6 @@ extern IExtensionSys *extsys;
|
||||
extern IHandleSys *handlesys;
|
||||
extern IForwardManager *forwardsys;
|
||||
extern IAdminSystem *adminsys;
|
||||
extern ILogger *logger;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */
|
||||
|
@ -1216,7 +1216,7 @@ static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (strcasecmp(name, "sm") == 0)
|
||||
{
|
||||
g_Logger.LogError("Request to register \"sm\" command denied.");
|
||||
logger->LogError("Request to register \"sm\" command denied.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
|
||||
/* This shouldn't happen */
|
||||
if (!iface)
|
||||
{
|
||||
g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater.");
|
||||
logger->LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -395,6 +395,7 @@ void SourceModBase::LevelShutdown()
|
||||
{
|
||||
g_pOnMapEnd->Execute(NULL);
|
||||
}
|
||||
extsys->CallOnCoreMapEnd();
|
||||
|
||||
g_Timers.RemoveMapChangeTimers();
|
||||
|
||||
@ -572,9 +573,9 @@ void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
||||
|
||||
if (tag)
|
||||
{
|
||||
g_Logger.LogMessage("[%s] %s", tag, buffer);
|
||||
logger->LogMessage("[%s] %s", tag, buffer);
|
||||
} else {
|
||||
g_Logger.LogMessage("%s", buffer);
|
||||
logger->LogMessage("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,9 +592,9 @@ void SourceModBase::LogError(IExtension *pExt, const char *format, ...)
|
||||
|
||||
if (tag)
|
||||
{
|
||||
g_Logger.LogError("[%s] %s", tag, buffer);
|
||||
logger->LogError("[%s] %s", tag, buffer);
|
||||
} else {
|
||||
g_Logger.LogError("%s", buffer);
|
||||
logger->LogError("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect()
|
||||
char error[256];
|
||||
int errCode = 0;
|
||||
|
||||
Database = Newborn<IDatabase>(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
|
||||
if (!Database)
|
||||
{
|
||||
|
@ -106,7 +106,7 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
|
||||
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
if (!x)
|
||||
@ -159,7 +159,7 @@ static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
|
||||
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
if (!x)
|
||||
|
@ -12,9 +12,9 @@
|
||||
}
|
||||
"FireBullets"
|
||||
{
|
||||
"windows" "112"
|
||||
"linux" "113"
|
||||
"mac" "113"
|
||||
"windows" "113"
|
||||
"linux" "114"
|
||||
"mac" "114"
|
||||
}
|
||||
"OnTakeDamage"
|
||||
{
|
||||
@ -24,15 +24,15 @@
|
||||
}
|
||||
"PreThink"
|
||||
{
|
||||
"windows" "331"
|
||||
"linux" "332"
|
||||
"mac" "332"
|
||||
"windows" "333"
|
||||
"linux" "334"
|
||||
"mac" "334"
|
||||
}
|
||||
"PostThink"
|
||||
{
|
||||
"windows" "332"
|
||||
"linux" "333"
|
||||
"mac" "333"
|
||||
"windows" "334"
|
||||
"linux" "335"
|
||||
"mac" "335"
|
||||
}
|
||||
"SetTransmit"
|
||||
{
|
||||
@ -78,39 +78,39 @@
|
||||
}
|
||||
"VPhysicsUpdate"
|
||||
{
|
||||
"windows" "157"
|
||||
"linux" "158"
|
||||
"mac" "158"
|
||||
"windows" "158"
|
||||
"linux" "159"
|
||||
"mac" "159"
|
||||
}
|
||||
"Weapon_CanSwitchTo"
|
||||
{
|
||||
"windows" "265"
|
||||
"linux" "266"
|
||||
"mac" "266"
|
||||
"windows" "267"
|
||||
"linux" "268"
|
||||
"mac" "268"
|
||||
}
|
||||
"Weapon_CanUse"
|
||||
{
|
||||
"windows" "259"
|
||||
"linux" "260"
|
||||
"mac" "260"
|
||||
"windows" "261"
|
||||
"linux" "262"
|
||||
"mac" "262"
|
||||
}
|
||||
"Weapon_Drop"
|
||||
{
|
||||
"windows" "264"
|
||||
"linux" "265"
|
||||
"mac" "265"
|
||||
}
|
||||
"Weapon_Equip"
|
||||
{
|
||||
"windows" "262"
|
||||
"linux" "263"
|
||||
"mac" "263"
|
||||
}
|
||||
"Weapon_Equip"
|
||||
{
|
||||
"windows" "260"
|
||||
"linux" "261"
|
||||
"mac" "261"
|
||||
}
|
||||
"Weapon_Switch"
|
||||
{
|
||||
"windows" "263"
|
||||
"linux" "264"
|
||||
"mac" "264"
|
||||
"windows" "265"
|
||||
"linux" "266"
|
||||
"mac" "266"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,9 @@
|
||||
}
|
||||
"PreThink"
|
||||
{
|
||||
"windows" "344"
|
||||
"linux" "345"
|
||||
"mac" "345"
|
||||
"windows" "345"
|
||||
"linux" "346"
|
||||
"mac" "346"
|
||||
}
|
||||
"PostThink"
|
||||
{
|
||||
|
@ -48,21 +48,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* No longer necessary. Remove later. */
|
||||
"#default"
|
||||
{
|
||||
"Signatures"
|
||||
{
|
||||
"EntityFactory"
|
||||
{
|
||||
"library" "server"
|
||||
"windows" "\xB8\x01\x00\x00\x00\x84\x2A\x2A\x2A\x2A\x2A\x75\x1D\x09\x2A\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x04\xB8\x2A\x2A\x2A\x2A\xC3"
|
||||
"linux" "@_Z23EntityFactoryDictionaryv"
|
||||
"mac" "@_Z23EntityFactoryDictionaryv"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SetUserInfo data */
|
||||
"#default"
|
||||
{
|
||||
|
@ -131,57 +131,57 @@
|
||||
{
|
||||
"GiveNamedItem"
|
||||
{
|
||||
"windows" "400"
|
||||
"linux" "401"
|
||||
"mac" "401"
|
||||
"windows" "402"
|
||||
"linux" "403"
|
||||
"mac" "403"
|
||||
}
|
||||
"RemovePlayerItem"
|
||||
{
|
||||
"windows" "271"
|
||||
"linux" "272"
|
||||
"mac" "272"
|
||||
}
|
||||
"Weapon_GetSlot"
|
||||
{
|
||||
"windows" "269"
|
||||
"linux" "270"
|
||||
"mac" "270"
|
||||
}
|
||||
"Weapon_GetSlot"
|
||||
{
|
||||
"windows" "267"
|
||||
"linux" "268"
|
||||
"mac" "268"
|
||||
}
|
||||
"Ignite"
|
||||
{
|
||||
"windows" "208"
|
||||
"linux" "209"
|
||||
"mac" "209"
|
||||
"windows" "210"
|
||||
"linux" "211"
|
||||
"mac" "211"
|
||||
}
|
||||
"Extinguish"
|
||||
{
|
||||
"windows" "212"
|
||||
"linux" "213"
|
||||
"mac" "213"
|
||||
"windows" "214"
|
||||
"linux" "215"
|
||||
"mac" "215"
|
||||
}
|
||||
"Teleport"
|
||||
{
|
||||
"windows" "108"
|
||||
"linux" "109"
|
||||
"mac" "109"
|
||||
"windows" "109"
|
||||
"linux" "110"
|
||||
"mac" "110"
|
||||
}
|
||||
"CommitSuicide"
|
||||
{
|
||||
"windows" "442"
|
||||
"linux" "442"
|
||||
"mac" "442"
|
||||
"windows" "444"
|
||||
"linux" "444"
|
||||
"mac" "444"
|
||||
}
|
||||
"GetVelocity"
|
||||
{
|
||||
"windows" "140"
|
||||
"linux" "141"
|
||||
"mac" "141"
|
||||
"windows" "141"
|
||||
"linux" "142"
|
||||
"mac" "142"
|
||||
}
|
||||
"EyeAngles"
|
||||
{
|
||||
"windows" "131"
|
||||
"linux" "132"
|
||||
"mac" "132"
|
||||
"windows" "132"
|
||||
"linux" "133"
|
||||
"mac" "133"
|
||||
}
|
||||
"AcceptInput"
|
||||
{
|
||||
@ -197,9 +197,9 @@
|
||||
}
|
||||
"WeaponEquip"
|
||||
{
|
||||
"windows" "260"
|
||||
"linux" "261"
|
||||
"mac" "261"
|
||||
"windows" "262"
|
||||
"linux" "263"
|
||||
"mac" "263"
|
||||
}
|
||||
"Activate"
|
||||
{
|
||||
@ -209,15 +209,15 @@
|
||||
}
|
||||
"PlayerRunCmd"
|
||||
{
|
||||
"windows" "418"
|
||||
"linux" "419"
|
||||
"mac" "419"
|
||||
"windows" "420"
|
||||
"linux" "421"
|
||||
"mac" "421"
|
||||
}
|
||||
"GiveAmmo"
|
||||
{
|
||||
"windows" "251"
|
||||
"linux" "252"
|
||||
"mac" "252"
|
||||
"windows" "253"
|
||||
"linux" "254"
|
||||
"mac" "254"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,9 +131,9 @@
|
||||
{
|
||||
"GiveNamedItem"
|
||||
{
|
||||
"windows" "412"
|
||||
"linux" "413"
|
||||
"mac" "413"
|
||||
"windows" "413"
|
||||
"linux" "414"
|
||||
"mac" "414"
|
||||
}
|
||||
"RemovePlayerItem"
|
||||
{
|
||||
@ -167,9 +167,9 @@
|
||||
}
|
||||
"CommitSuicide"
|
||||
{
|
||||
"windows" "451"
|
||||
"linux" "451"
|
||||
"mac" "451"
|
||||
"windows" "452"
|
||||
"linux" "452"
|
||||
"mac" "452"
|
||||
}
|
||||
"GetVelocity"
|
||||
{
|
||||
@ -209,9 +209,9 @@
|
||||
}
|
||||
"PlayerRunCmd"
|
||||
{
|
||||
"windows" "430"
|
||||
"linux" "431"
|
||||
"mac" "431"
|
||||
"windows" "431"
|
||||
"linux" "432"
|
||||
"mac" "432"
|
||||
}
|
||||
"GiveAmmo"
|
||||
{
|
||||
|
@ -376,6 +376,15 @@ native bool:RemoveDir(const String:path[]);
|
||||
*/
|
||||
native bool:CreateDirectory(const String:path[], mode);
|
||||
|
||||
/**
|
||||
* Changes a file or directories permissions.
|
||||
*
|
||||
* @param path Path to the file.
|
||||
* @param mode Permissions to set.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
native bool:SetFilePermissions(const String:path[], mode);
|
||||
|
||||
/**
|
||||
* Returns a file timestamp as a unix timestamp.
|
||||
*
|
||||
|
@ -153,6 +153,10 @@ enum TFCond
|
||||
TFCond_HalloweenTiny,
|
||||
TFCond_HalloweenInHell,
|
||||
TFCond_HalloweenGhostMode,
|
||||
|
||||
TFCond_DodgeChance = 79,
|
||||
TFCond_Parachute,
|
||||
TFCond_BlastJumping,
|
||||
};
|
||||
|
||||
const Float:TFCondDuration_Infinite = -1.0;
|
||||
@ -447,5 +451,6 @@ public __ext_tf2_SetNTVOptional()
|
||||
MarkNativeAsOptional("TF2_GetClass");
|
||||
MarkNativeAsOptional("TF2_IsPlayerInDuel");
|
||||
MarkNativeAsOptional("TF2_IsHolidayActive");
|
||||
MarkNativeAsOptional("TF2_RemoveWearable");
|
||||
}
|
||||
#endif
|
||||
|
@ -249,6 +249,7 @@ enum {
|
||||
TF_WEAPON_SPELLBOOK,
|
||||
TF_WEAPON_SPELLBOOK_PROJECTILE,
|
||||
TF_WEAPON_SNIPERRIFLE_CLASSIC,
|
||||
TF_WEAPON_PARACHUTE,
|
||||
};
|
||||
|
||||
// TF2 Weapon Loadout Slots
|
||||
|
@ -135,8 +135,9 @@ namespace SourceMod
|
||||
*
|
||||
* V6 - added TestFeature() to IShareSys.
|
||||
* V7 - added OnDependenciesDropped() to IExtensionInterface.
|
||||
* V8 - added OnCoreMapEnd() to IExtensionInterface.
|
||||
*/
|
||||
#define SMINTERFACE_EXTENSIONAPI_VERSION 7
|
||||
#define SMINTERFACE_EXTENSIONAPI_VERSION 8
|
||||
|
||||
/**
|
||||
* @brief The interface an extension must expose.
|
||||
@ -325,6 +326,15 @@ namespace SourceMod
|
||||
virtual void OnDependenciesDropped()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called on level shutdown
|
||||
*
|
||||
*/
|
||||
|
||||
virtual void OnCoreMapEnd()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -35,12 +35,15 @@
|
||||
|
||||
namespace ke {
|
||||
|
||||
// See the comment above Refcounted<T> for more information. This class is
|
||||
// identical, except changing the reference count is guaranteed to be atomic
|
||||
// with respect to other threads changing the reference count.
|
||||
template <typename T>
|
||||
class RefcountedThreadsafe
|
||||
{
|
||||
public:
|
||||
RefcountedThreadsafe()
|
||||
: refcount_(1)
|
||||
: refcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,18 +37,28 @@ namespace ke {
|
||||
|
||||
template <typename T> class Ref;
|
||||
|
||||
// Holds a refcounted T without addrefing it. This is similar to PassRef<>
|
||||
// below, but is intended only for freshly allocated objects which start
|
||||
// with reference count 1, and we don't want to add an extra ref just by
|
||||
// assigning to PassRef<> or Ref<>.
|
||||
// Objects in AMTL inheriting from Refcounted will have an initial refcount
|
||||
// of 0. However, in some systems (such as COM), the initial refcount is 1,
|
||||
// or functions may return raw pointers that have been AddRef'd. In these
|
||||
// cases it would be a mistake to use Ref<> or PassRef<>, since the object
|
||||
// would leak an extra reference.
|
||||
//
|
||||
// This container holds a refcounted object without addrefing it. This is
|
||||
// intended only for interacting with functions which return an object that
|
||||
// has been manually AddRef'd. Note that this will perform a Release(), so
|
||||
// so it is necessary to assign it to retain the object.
|
||||
template <typename T>
|
||||
class Newborn
|
||||
class AlreadyRefed
|
||||
{
|
||||
public:
|
||||
Newborn(T *t)
|
||||
AlreadyRefed(T *t)
|
||||
: thing_(t)
|
||||
{
|
||||
}
|
||||
~AlreadyRefed() {
|
||||
if (thing_)
|
||||
thing_->Release();
|
||||
}
|
||||
|
||||
T *release() const {
|
||||
return ReturnAndVoid(thing_);
|
||||
@ -59,10 +69,10 @@ class Newborn
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static inline Newborn<T>
|
||||
NoAddRef(T *t)
|
||||
static inline AlreadyRefed<T>
|
||||
AdoptRef(T *t)
|
||||
{
|
||||
return Newborn<T>(t);
|
||||
return AlreadyRefed<T>(t);
|
||||
}
|
||||
|
||||
// When returning a value, we'd rather not be needlessly changing the refcount,
|
||||
@ -81,7 +91,14 @@ class PassRef
|
||||
{
|
||||
}
|
||||
|
||||
PassRef(const Newborn<T *> &other)
|
||||
PassRef(const AlreadyRefed<T *> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
// Don't addref, newborn means already addref'd.
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
PassRef(const AlreadyRefed<S *> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
// Don't addref, newborn means already addref'd.
|
||||
@ -134,7 +151,7 @@ class PassRef
|
||||
private:
|
||||
// Disallowed operators.
|
||||
PassRef &operator =(T *other);
|
||||
PassRef &operator =(Newborn<T> &other);
|
||||
PassRef &operator =(AlreadyRefed<T> &other);
|
||||
|
||||
void AddRef() {
|
||||
if (thing_)
|
||||
@ -149,13 +166,18 @@ class PassRef
|
||||
mutable T *thing_;
|
||||
};
|
||||
|
||||
// Classes which are refcounted should inherit from this.
|
||||
// Classes which are refcounted should inherit from this. Note that reference
|
||||
// counts start at 0 in AMTL, rather than 1. This avoids the complexity of
|
||||
// having to adopt the initial ref upon allocation. However, this also means
|
||||
// invoking Release() on a newly allocated object is illegal. Newborn objects
|
||||
// must either be assigned to a Ref or PassRef (NOT an AdoptRef/AlreadyRefed),
|
||||
// or must be deleted using |delete|.
|
||||
template <typename T>
|
||||
class Refcounted
|
||||
{
|
||||
public:
|
||||
Refcounted()
|
||||
: refcount_(1)
|
||||
: refcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -217,7 +239,12 @@ class Ref
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
Ref(const Newborn<T> &other)
|
||||
Ref(const AlreadyRefed<T> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
template <typename S>
|
||||
Ref(const AlreadyRefed<S> &other)
|
||||
: thing_(other.release())
|
||||
{
|
||||
}
|
||||
@ -255,7 +282,7 @@ class Ref
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
Ref &operator =(const Newborn<S> &other) {
|
||||
Ref &operator =(const AlreadyRefed<S> &other) {
|
||||
Release();
|
||||
thing_ = other.release();
|
||||
return *this;
|
||||
|
@ -36,8 +36,8 @@
|
||||
* @file sp_vm_types.h
|
||||
* @brief Contains all run-time SourcePawn structures.
|
||||
*/
|
||||
|
||||
#include "sp_file_headers.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint32_t ucell_t; /**< Unsigned 32bit integer */
|
||||
typedef int32_t cell_t; /**< Basic 32bit signed integer type for plugins */
|
||||
@ -189,10 +189,25 @@ typedef struct sp_debug_line_s
|
||||
uint32_t line; /**< Line number */
|
||||
} sp_debug_line_t;
|
||||
|
||||
/**
|
||||
* @brief These structures are equivalent.
|
||||
*/
|
||||
typedef sp_fdbg_arraydim_t sp_debug_arraydim_t;
|
||||
// Occurs after an fdbg_symbol entry, for each dimension.
|
||||
typedef struct sp_debug_arraydim_s
|
||||
{
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t size; /**< Size of dimension */
|
||||
} sp_debug_arraydim_t;
|
||||
|
||||
// Same as from <smx/smx-v1-headers.h>.
|
||||
typedef struct sp_debug_symbol_raw_s
|
||||
{
|
||||
int32_t addr; /**< Address rel to DAT or stack frame */
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t codestart; /**< Start scope validity in code */
|
||||
uint32_t codeend; /**< End scope validity in code */
|
||||
uint8_t ident; /**< Variable type */
|
||||
uint8_t vclass; /**< Scope class (local vs global) */
|
||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
||||
uint32_t name; /**< Offset into debug nametable */
|
||||
} sp_debug_symbol_raw_t;
|
||||
|
||||
/**
|
||||
* @brief The majority of this struct is already located in the parent
|
||||
@ -200,11 +215,11 @@ typedef sp_fdbg_arraydim_t sp_debug_arraydim_t;
|
||||
*/
|
||||
typedef struct sp_debug_symbol_s
|
||||
{
|
||||
uint32_t codestart; /**< Relocated code address */
|
||||
uint32_t codeend; /**< Relocated code end address */
|
||||
const char * name; /**< Relocated name */
|
||||
sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */
|
||||
sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */
|
||||
uint32_t codestart; /**< Relocated code address */
|
||||
uint32_t codeend; /**< Relocated code end address */
|
||||
const char * name; /**< Relocated name */
|
||||
sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */
|
||||
sp_debug_symbol_raw_t *sym; /**< Pointer to original symbol */
|
||||
} sp_debug_symbol_t;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||
|
@ -42,6 +42,7 @@ binary = SM.Program(builder, 'spcomp')
|
||||
compiler = binary.compiler
|
||||
compiler.includes += [
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'),
|
||||
os.path.join(builder.buildPath, 'includes'),
|
||||
@ -50,7 +51,8 @@ compiler.includes += [
|
||||
compiler.sourcedeps += packed_includes
|
||||
|
||||
if compiler.cc.behavior == 'gcc':
|
||||
compiler.cflags += ['-std=c99', '-Wno-format']
|
||||
compiler.cflags += ['-Wno-format']
|
||||
compiler.c_only_flags += ['-std=c99']
|
||||
if builder.target_platform == 'linux':
|
||||
compiler.postlink += ['-lgcc', '-lm']
|
||||
elif compiler.cc.behavior == 'msvc':
|
||||
@ -58,10 +60,10 @@ elif compiler.cc.behavior == 'msvc':
|
||||
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
||||
compiler.cxxflags.remove('/TP')
|
||||
|
||||
compiler.defines += ['HAVE_STDINT_H']
|
||||
if builder.target_platform == 'linux':
|
||||
compiler.defines += [
|
||||
'LINUX',
|
||||
'HAVE_STDINT_H',
|
||||
'AMX_ANSIONLY',
|
||||
'ENABLE_BINRELOC',
|
||||
'_GNU_SOURCE'
|
||||
@ -69,32 +71,31 @@ if builder.target_platform == 'linux':
|
||||
elif builder.target_platform == 'mac':
|
||||
compiler.defines += [
|
||||
'DARWIN',
|
||||
'HAVE_STDINT_H',
|
||||
'AMX_ANSIONLY',
|
||||
'ENABLE_BINRELOC',
|
||||
'HAVE_SAFESTR'
|
||||
]
|
||||
|
||||
binary.sources += [
|
||||
'libpawnc.c',
|
||||
'lstring.c',
|
||||
'memfile.c',
|
||||
'pawncc.c',
|
||||
'sc1.c',
|
||||
'sc2.c',
|
||||
'sc3.c',
|
||||
'sc4.c',
|
||||
'sc5.c',
|
||||
'sc6.c',
|
||||
'sc7.c',
|
||||
'scexpand.c',
|
||||
'sci18n.c',
|
||||
'sclist.c',
|
||||
'scmemfil.c',
|
||||
'scstate.c',
|
||||
'sctracker.c',
|
||||
'scvars.c',
|
||||
'sp_file.c',
|
||||
'libpawnc.cpp',
|
||||
'lstring.cpp',
|
||||
'memfile.cpp',
|
||||
'pawncc.cpp',
|
||||
'sc1.cpp',
|
||||
'sc2.cpp',
|
||||
'sc3.cpp',
|
||||
'sc4.cpp',
|
||||
'sc5.cpp',
|
||||
'sc6.cpp',
|
||||
'sc7.cpp',
|
||||
'scexpand.cpp',
|
||||
'sci18n.cpp',
|
||||
'sclist.cpp',
|
||||
'scmemfil.cpp',
|
||||
'scstate.cpp',
|
||||
'sctracker.cpp',
|
||||
'scvars.cpp',
|
||||
'sp_file.cpp',
|
||||
'zlib/adler32.c',
|
||||
'zlib/compress.c',
|
||||
'zlib/crc32.c',
|
||||
@ -107,7 +108,7 @@ binary.sources += [
|
||||
'zlib/trees.c',
|
||||
'zlib/uncompr.c',
|
||||
'zlib/zutil.c',
|
||||
'sp_symhash.c'
|
||||
'sp_symhash.cpp'
|
||||
]
|
||||
if builder.target_platform != 'windows':
|
||||
binary.sources.append('binreloc.c')
|
||||
|
@ -34,8 +34,12 @@
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_STDINT_H
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#include <stdint.h>
|
||||
#if !defined HAVE_STDINT_H
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
|
@ -1,173 +1,173 @@
|
||||
/* Abstract Machine for the Pawn compiler, debugger support
|
||||
*
|
||||
* This file contains extra definitions that are convenient for debugger
|
||||
* support.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef AMXDBG_H_INCLUDED
|
||||
#define AMXDBG_H_INCLUDED
|
||||
|
||||
#ifndef AMX_H_INCLUDED
|
||||
#include "amx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||
*/
|
||||
#if defined SN_TARGET_PS2 || defined __GNUC__
|
||||
#define AMX_NO_ALIGN
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#if defined __TURBOC__
|
||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct tagAMX_DBG_HDR {
|
||||
int32_t size PACKED; /* size of the debug information chunk */
|
||||
uint16_t magic PACKED; /* signature, must be 0xf1ef */
|
||||
char file_version; /* file format version */
|
||||
char amx_version; /* required version of the AMX */
|
||||
int16_t flags PACKED; /* currently unused */
|
||||
int16_t files PACKED; /* number of entries in the "file" table */
|
||||
int32_t lines PACKED; /* number of entries in the "line" table */
|
||||
int32_t symbols PACKED; /* number of entries in the "symbol" table */
|
||||
int16_t tags PACKED; /* number of entries in the "tag" table */
|
||||
int16_t automatons PACKED; /* number of entries in the "automaton" table */
|
||||
int16_t states PACKED; /* number of entries in the "state" table */
|
||||
} PACKED AMX_DBG_HDR;
|
||||
#define AMX_DBG_MAGIC 0xf1ef
|
||||
|
||||
typedef struct tagAMX_DBG_FILE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_FILE;
|
||||
|
||||
typedef struct tagAMX_DBG_LINE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
|
||||
int32_t line PACKED; /* line number */
|
||||
} PACKED AMX_DBG_LINE;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMBOL {
|
||||
ucell address PACKED; /* address in the data segment or relative to the frame */
|
||||
int16_t tag PACKED; /* tag for the symbol */
|
||||
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
|
||||
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
|
||||
char ident; /* kind of symbol (function/variable) */
|
||||
char vclass; /* class of symbol (global/local) */
|
||||
int16_t dim PACKED; /* number of dimensions */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_SYMBOL;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMDIM {
|
||||
int16_t tag PACKED; /* tag for the array dimension */
|
||||
ucell size PACKED; /* size of the array dimension */
|
||||
} PACKED AMX_DBG_SYMDIM;
|
||||
|
||||
typedef struct tagAMX_DBG_TAG {
|
||||
int16_t tag PACKED; /* tag id */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_TAG;
|
||||
|
||||
typedef struct tagAMX_DBG_MACHINE {
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
ucell address PACKED; /* address of state variable */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_MACHINE;
|
||||
|
||||
typedef struct tagAMX_DBG_STATE {
|
||||
int16_t state PACKED; /* state id */
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_STATE;
|
||||
|
||||
typedef struct tagAMX_DBG {
|
||||
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
|
||||
AMX_DBG_FILE _FAR **filetbl PACKED;
|
||||
AMX_DBG_LINE _FAR *linetbl PACKED;
|
||||
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
|
||||
AMX_DBG_TAG _FAR **tagtbl PACKED;
|
||||
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
|
||||
AMX_DBG_STATE _FAR **statetbl PACKED;
|
||||
} PACKED AMX_DBG;
|
||||
|
||||
#if !defined iVARIABLE
|
||||
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
||||
#define iARRAY 3
|
||||
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||
#define iFUNCTN 9
|
||||
#endif
|
||||
|
||||
|
||||
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
|
||||
int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr);
|
||||
|
||||
int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
|
||||
int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
|
||||
int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line);
|
||||
|
||||
int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
|
||||
int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name);
|
||||
int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name);
|
||||
int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym);
|
||||
int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
|
||||
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMXDBG_H_INCLUDED */
|
||||
|
||||
/* Abstract Machine for the Pawn compiler, debugger support
|
||||
*
|
||||
* This file contains extra definitions that are convenient for debugger
|
||||
* support.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef AMXDBG_H_INCLUDED
|
||||
#define AMXDBG_H_INCLUDED
|
||||
|
||||
#ifndef AMX_H_INCLUDED
|
||||
#include "amx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||
*/
|
||||
#if defined SN_TARGET_PS2 || defined __GNUC__
|
||||
#define AMX_NO_ALIGN
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#if defined __TURBOC__
|
||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct tagAMX_DBG_HDR {
|
||||
int32_t size PACKED; /* size of the debug information chunk */
|
||||
uint16_t magic PACKED; /* signature, must be 0xf1ef */
|
||||
char file_version; /* file format version */
|
||||
char amx_version; /* required version of the AMX */
|
||||
int16_t flags PACKED; /* currently unused */
|
||||
int16_t files PACKED; /* number of entries in the "file" table */
|
||||
int32_t lines PACKED; /* number of entries in the "line" table */
|
||||
int32_t symbols PACKED; /* number of entries in the "symbol" table */
|
||||
int16_t tags PACKED; /* number of entries in the "tag" table */
|
||||
int16_t automatons PACKED; /* number of entries in the "automaton" table */
|
||||
int16_t states PACKED; /* number of entries in the "state" table */
|
||||
} PACKED AMX_DBG_HDR;
|
||||
#define AMX_DBG_MAGIC 0xf1ef
|
||||
|
||||
typedef struct tagAMX_DBG_FILE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
|
||||
char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_FILE;
|
||||
|
||||
typedef struct tagAMX_DBG_LINE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
|
||||
int32_t line PACKED; /* line number */
|
||||
} PACKED AMX_DBG_LINE;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMBOL {
|
||||
ucell address PACKED; /* address in the data segment or relative to the frame */
|
||||
int16_t tag PACKED; /* tag for the symbol */
|
||||
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
|
||||
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
|
||||
char ident; /* kind of symbol (function/variable) */
|
||||
char vclass; /* class of symbol (global/local) */
|
||||
int16_t dim PACKED; /* number of dimensions */
|
||||
char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_SYMBOL;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMDIM {
|
||||
int16_t tag PACKED; /* tag for the array dimension */
|
||||
ucell size PACKED; /* size of the array dimension */
|
||||
} PACKED AMX_DBG_SYMDIM;
|
||||
|
||||
typedef struct tagAMX_DBG_TAG {
|
||||
int16_t tag PACKED; /* tag id */
|
||||
char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_TAG;
|
||||
|
||||
typedef struct tagAMX_DBG_MACHINE {
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
ucell address PACKED; /* address of state variable */
|
||||
char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_MACHINE;
|
||||
|
||||
typedef struct tagAMX_DBG_STATE {
|
||||
int16_t state PACKED; /* state id */
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_STATE;
|
||||
|
||||
typedef struct tagAMX_DBG {
|
||||
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
|
||||
AMX_DBG_FILE _FAR **filetbl PACKED;
|
||||
AMX_DBG_LINE _FAR *linetbl PACKED;
|
||||
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
|
||||
AMX_DBG_TAG _FAR **tagtbl PACKED;
|
||||
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
|
||||
AMX_DBG_STATE _FAR **statetbl PACKED;
|
||||
} PACKED AMX_DBG;
|
||||
|
||||
#if !defined iVARIABLE
|
||||
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
||||
#define iARRAY 3
|
||||
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||
#define iFUNCTN 9
|
||||
#endif
|
||||
|
||||
|
||||
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
|
||||
int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr);
|
||||
|
||||
int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
|
||||
int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
|
||||
int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line);
|
||||
|
||||
int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
|
||||
int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name);
|
||||
int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name);
|
||||
int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym);
|
||||
int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
|
||||
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMXDBG_H_INCLUDED */
|
||||
|
||||
|
@ -1,409 +0,0 @@
|
||||
// vim: set sts=8 ts=4 sw=4 tw=99 noet:
|
||||
/* LIBPAWNC.C
|
||||
*
|
||||
* A "glue file" for building the Pawn compiler as a DLL or shared library.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2000-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/* pc_printf()
|
||||
* Called for general purpose "console" output. This function prints general
|
||||
* purpose messages; errors go through pc_error(). The function is modelled
|
||||
* after printf().
|
||||
*/
|
||||
int pc_printf(const char *message,...)
|
||||
{
|
||||
int ret;
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr,message);
|
||||
ret=vprintf(message,argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pc_error()
|
||||
* Called for producing error output.
|
||||
* number the error number (as documented in the manual)
|
||||
* message a string describing the error with embedded %d and %s tokens
|
||||
* filename the name of the file currently being parsed
|
||||
* firstline the line number at which the expression started on which
|
||||
* the error was found, or -1 if there is no "starting line"
|
||||
* lastline the line number at which the error was detected
|
||||
* argptr a pointer to the first of a series of arguments (for macro
|
||||
* "va_arg")
|
||||
* Return:
|
||||
* If the function returns 0, the parser attempts to continue compilation.
|
||||
* On a non-zero return value, the parser aborts.
|
||||
*/
|
||||
int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr)
|
||||
{
|
||||
static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
|
||||
if (number!=0) {
|
||||
char *pre;
|
||||
int idx;
|
||||
|
||||
if (number < 160)
|
||||
idx = 0;
|
||||
else if (number < 200)
|
||||
idx = 1;
|
||||
else
|
||||
idx = 2;
|
||||
|
||||
pre=prefix[idx];
|
||||
if (firstline>=0)
|
||||
fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
|
||||
else
|
||||
fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
|
||||
} /* if */
|
||||
vfprintf(stdout,message,argptr);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct src_file_s {
|
||||
FILE *fp; // Set if writing.
|
||||
char *buffer; // IO buffer.
|
||||
char *pos; // IO position.
|
||||
char *end; // End of buffer.
|
||||
size_t maxlength; // Maximum length of the writable buffer.
|
||||
} src_file_t;
|
||||
|
||||
/* pc_opensrc()
|
||||
* Opens a source file (or include file) for reading. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to read from
|
||||
* Return:
|
||||
* The function must return a pointer, which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_opensrc(char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
long length;
|
||||
src_file_t *src = NULL;
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
struct stat fileInfo;
|
||||
if (stat(filename, &fileInfo) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(fileInfo.st_mode)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
return NULL;
|
||||
if (fseek(fp, 0, SEEK_END) == -1)
|
||||
goto err;
|
||||
if ((length = ftell(fp)) == -1)
|
||||
goto err;
|
||||
if (fseek(fp, 0, SEEK_SET) == -1)
|
||||
goto err;
|
||||
|
||||
if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL)
|
||||
goto err;
|
||||
if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL)
|
||||
goto err;
|
||||
if (fread(src->buffer, length, 1, fp) != 1)
|
||||
goto err;
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer + length;
|
||||
fclose(fp);
|
||||
return src;
|
||||
|
||||
err:
|
||||
pc_closesrc(src);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pc_createsrc()
|
||||
* Creates/overwrites a source file for writing. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to create
|
||||
* Return:
|
||||
* The function must return a pointer which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_createsrc(char *filename)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t));
|
||||
if (!src)
|
||||
return NULL;
|
||||
if ((src->fp = fopen(filename, "wt")) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->maxlength = 1024;
|
||||
if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer + src->maxlength;
|
||||
return src;
|
||||
}
|
||||
|
||||
/* pc_closesrc()
|
||||
* Closes a source file (or include file). The "handle" parameter has the
|
||||
* value that pc_opensrc() returned in an earlier call.
|
||||
*/
|
||||
void pc_closesrc(void *handle)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
if (!src)
|
||||
return;
|
||||
if (src->fp) {
|
||||
fwrite(src->buffer, src->pos - src->buffer, 1, src->fp);
|
||||
fclose(src->fp);
|
||||
}
|
||||
free(src->buffer);
|
||||
free(src);
|
||||
}
|
||||
|
||||
/* pc_readsrc()
|
||||
* Reads a single line from the source file (or up to a maximum number of
|
||||
* characters if the line in the input file is too long).
|
||||
*/
|
||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
char *outptr = (char *)target;
|
||||
char *outend = outptr + maxchars;
|
||||
|
||||
assert(!src->fp);
|
||||
|
||||
if (src->pos == src->end)
|
||||
return NULL;
|
||||
|
||||
while (outptr < outend && src->pos < src->end) {
|
||||
char c = *src->pos++;
|
||||
*outptr++ = c;
|
||||
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c == '\r') {
|
||||
// Handle CRLF.
|
||||
if (src->pos < src->end && *src->pos == '\n') {
|
||||
src->pos++;
|
||||
if (outptr < outend)
|
||||
*outptr++ = '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Caller passes in a buffer of size >= maxchars+1.
|
||||
*outptr = '\0';
|
||||
return (char *)target;
|
||||
}
|
||||
|
||||
/* pc_writesrc()
|
||||
* Writes to to the source file. There is no automatic line ending; to end a
|
||||
* line, write a "\n".
|
||||
*/
|
||||
int pc_writesrc(void *handle,unsigned char *source)
|
||||
{
|
||||
char *str = (char *)source;
|
||||
size_t len = strlen(str);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(src->fp && src->maxlength);
|
||||
|
||||
if (src->pos + len > src->end) {
|
||||
char *newbuf;
|
||||
size_t newmax = src->maxlength;
|
||||
size_t newlen = (src->pos - src->buffer) + len;
|
||||
while (newmax < newlen) {
|
||||
// Grow by 1.5X
|
||||
newmax += newmax + newmax / 2;
|
||||
if (newmax < src->maxlength)
|
||||
abort();
|
||||
}
|
||||
|
||||
newbuf = (char *)realloc(src->buffer, newmax);
|
||||
if (!newbuf)
|
||||
abort();
|
||||
src->pos = newbuf + (src->pos - src->buffer);
|
||||
src->end = newbuf + newmax;
|
||||
src->buffer = newbuf;
|
||||
src->maxlength = newmax;
|
||||
}
|
||||
|
||||
strcpy(src->pos, str);
|
||||
src->pos += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pc_getpossrc(void *handle,void *position)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(!src->fp);
|
||||
return (void *)(ptrdiff_t)(src->pos - src->buffer);
|
||||
}
|
||||
|
||||
/* pc_resetsrc()
|
||||
* "position" may only hold a pointer that was previously obtained from
|
||||
* pc_getpossrc()
|
||||
*/
|
||||
void pc_resetsrc(void *handle,void *position)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
ptrdiff_t pos = (ptrdiff_t)position;
|
||||
|
||||
assert(!src->fp);
|
||||
assert(pos >= 0 && src->buffer + pos <= src->end);
|
||||
src->pos = src->buffer + pos;
|
||||
}
|
||||
|
||||
int pc_eofsrc(void *handle)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(!src->fp);
|
||||
return src->pos == src->end;
|
||||
}
|
||||
|
||||
/* should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure
|
||||
*/
|
||||
void *pc_openasm(char *filename)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fopen(filename,"w+t");
|
||||
#else
|
||||
return mfcreate(filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pc_closeasm(void *handle, int deletefile)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
if (handle!=NULL)
|
||||
fclose((FILE*)handle);
|
||||
if (deletefile)
|
||||
remove(outfname);
|
||||
#else
|
||||
if (handle!=NULL) {
|
||||
if (!deletefile)
|
||||
mfdump((MEMFILE*)handle);
|
||||
mfclose((MEMFILE*)handle);
|
||||
} /* if */
|
||||
#endif
|
||||
}
|
||||
|
||||
void pc_resetasm(void *handle)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
fflush((FILE*)handle);
|
||||
fseek((FILE*)handle,0,SEEK_SET);
|
||||
#else
|
||||
mfseek((MEMFILE*)handle,0,SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
int pc_writeasm(void *handle,char *string)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fputs(string,(FILE*)handle) >= 0;
|
||||
#else
|
||||
return mfputs((MEMFILE*)handle,string);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *pc_readasm(void *handle, char *string, int maxchars)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fgets(string,maxchars,(FILE*)handle);
|
||||
#else
|
||||
return mfgets((MEMFILE*)handle,string,maxchars);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern memfile_t *bin_file;
|
||||
|
||||
/* Should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure.
|
||||
*/
|
||||
void *pc_openbin(char *filename)
|
||||
{
|
||||
return memfile_creat(filename, 1);
|
||||
}
|
||||
|
||||
void pc_closebin(void *handle,int deletefile)
|
||||
{
|
||||
if (deletefile)
|
||||
{
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
bin_file = NULL;
|
||||
} else {
|
||||
bin_file = (memfile_t *)handle;
|
||||
}
|
||||
}
|
||||
|
||||
/* pc_resetbin()
|
||||
* Can seek to any location in the file.
|
||||
* The offset is always from the start of the file.
|
||||
*/
|
||||
void pc_resetbin(void *handle,long offset)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, offset);
|
||||
}
|
||||
|
||||
int pc_writebin(void *handle,void *buffer,int size)
|
||||
{
|
||||
return memfile_write((memfile_t *)handle, buffer, size);
|
||||
}
|
||||
|
||||
long pc_lengthbin(void *handle)
|
||||
{
|
||||
return memfile_tell((memfile_t *)handle);
|
||||
}
|
382
sourcepawn/compiler/libpawnc.cpp
Normal file
382
sourcepawn/compiler/libpawnc.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
// vim: set sts=8 ts=4 sw=4 tw=99 noet:
|
||||
/* LIBPAWNC.C
|
||||
*
|
||||
* A "glue file" for building the Pawn compiler as a DLL or shared library.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2000-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/* pc_printf()
|
||||
* Called for general purpose "console" output. This function prints general
|
||||
* purpose messages; errors go through pc_error(). The function is modelled
|
||||
* after printf().
|
||||
*/
|
||||
int pc_printf(const char *message,...)
|
||||
{
|
||||
int ret;
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr,message);
|
||||
ret=vprintf(message,argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pc_error()
|
||||
* Called for producing error output.
|
||||
* number the error number (as documented in the manual)
|
||||
* message a string describing the error with embedded %d and %s tokens
|
||||
* filename the name of the file currently being parsed
|
||||
* firstline the line number at which the expression started on which
|
||||
* the error was found, or -1 if there is no "starting line"
|
||||
* lastline the line number at which the error was detected
|
||||
* argptr a pointer to the first of a series of arguments (for macro
|
||||
* "va_arg")
|
||||
* Return:
|
||||
* If the function returns 0, the parser attempts to continue compilation.
|
||||
* On a non-zero return value, the parser aborts.
|
||||
*/
|
||||
int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr)
|
||||
{
|
||||
static const char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
|
||||
if (number!=0) {
|
||||
int idx;
|
||||
|
||||
if (number < 160)
|
||||
idx = 0;
|
||||
else if (number < 200)
|
||||
idx = 1;
|
||||
else
|
||||
idx = 2;
|
||||
|
||||
const char *pre=prefix[idx];
|
||||
if (firstline>=0)
|
||||
fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
|
||||
else
|
||||
fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
|
||||
} /* if */
|
||||
vfprintf(stdout,message,argptr);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct src_file_s {
|
||||
FILE *fp; // Set if writing.
|
||||
char *buffer; // IO buffer.
|
||||
char *pos; // IO position.
|
||||
char *end; // End of buffer.
|
||||
size_t maxlength; // Maximum length of the writable buffer.
|
||||
} src_file_t;
|
||||
|
||||
/* pc_opensrc()
|
||||
* Opens a source file (or include file) for reading. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to read from
|
||||
* Return:
|
||||
* The function must return a pointer, which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_opensrc(char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
long length;
|
||||
src_file_t *src = NULL;
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
struct stat fileInfo;
|
||||
if (stat(filename, &fileInfo) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(fileInfo.st_mode)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
return NULL;
|
||||
if (fseek(fp, 0, SEEK_END) == -1)
|
||||
goto err;
|
||||
if ((length = ftell(fp)) == -1)
|
||||
goto err;
|
||||
if (fseek(fp, 0, SEEK_SET) == -1)
|
||||
goto err;
|
||||
|
||||
if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL)
|
||||
goto err;
|
||||
if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL)
|
||||
goto err;
|
||||
if (fread(src->buffer, length, 1, fp) != 1)
|
||||
goto err;
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer + length;
|
||||
fclose(fp);
|
||||
return src;
|
||||
|
||||
err:
|
||||
pc_closesrc(src);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pc_createsrc()
|
||||
* Creates/overwrites a source file for writing. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to create
|
||||
* Return:
|
||||
* The function must return a pointer which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_createsrc(char *filename)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t));
|
||||
if (!src)
|
||||
return NULL;
|
||||
if ((src->fp = fopen(filename, "wt")) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->maxlength = 1024;
|
||||
if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer + src->maxlength;
|
||||
return src;
|
||||
}
|
||||
|
||||
/* pc_closesrc()
|
||||
* Closes a source file (or include file). The "handle" parameter has the
|
||||
* value that pc_opensrc() returned in an earlier call.
|
||||
*/
|
||||
void pc_closesrc(void *handle)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
if (!src)
|
||||
return;
|
||||
if (src->fp) {
|
||||
fwrite(src->buffer, src->pos - src->buffer, 1, src->fp);
|
||||
fclose(src->fp);
|
||||
}
|
||||
free(src->buffer);
|
||||
free(src);
|
||||
}
|
||||
|
||||
/* pc_readsrc()
|
||||
* Reads a single line from the source file (or up to a maximum number of
|
||||
* characters if the line in the input file is too long).
|
||||
*/
|
||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
char *outptr = (char *)target;
|
||||
char *outend = outptr + maxchars;
|
||||
|
||||
assert(!src->fp);
|
||||
|
||||
if (src->pos == src->end)
|
||||
return NULL;
|
||||
|
||||
while (outptr < outend && src->pos < src->end) {
|
||||
char c = *src->pos++;
|
||||
*outptr++ = c;
|
||||
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c == '\r') {
|
||||
// Handle CRLF.
|
||||
if (src->pos < src->end && *src->pos == '\n') {
|
||||
src->pos++;
|
||||
if (outptr < outend)
|
||||
*outptr++ = '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Caller passes in a buffer of size >= maxchars+1.
|
||||
*outptr = '\0';
|
||||
return (char *)target;
|
||||
}
|
||||
|
||||
/* pc_writesrc()
|
||||
* Writes to to the source file. There is no automatic line ending; to end a
|
||||
* line, write a "\n".
|
||||
*/
|
||||
int pc_writesrc(void *handle,unsigned char *source)
|
||||
{
|
||||
char *str = (char *)source;
|
||||
size_t len = strlen(str);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(src->fp && src->maxlength);
|
||||
|
||||
if (src->pos + len > src->end) {
|
||||
char *newbuf;
|
||||
size_t newmax = src->maxlength;
|
||||
size_t newlen = (src->pos - src->buffer) + len;
|
||||
while (newmax < newlen) {
|
||||
// Grow by 1.5X
|
||||
newmax += newmax + newmax / 2;
|
||||
if (newmax < src->maxlength)
|
||||
abort();
|
||||
}
|
||||
|
||||
newbuf = (char *)realloc(src->buffer, newmax);
|
||||
if (!newbuf)
|
||||
abort();
|
||||
src->pos = newbuf + (src->pos - src->buffer);
|
||||
src->end = newbuf + newmax;
|
||||
src->buffer = newbuf;
|
||||
src->maxlength = newmax;
|
||||
}
|
||||
|
||||
strcpy(src->pos, str);
|
||||
src->pos += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pc_getpossrc(void *handle,void *position)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(!src->fp);
|
||||
return (void *)(ptrdiff_t)(src->pos - src->buffer);
|
||||
}
|
||||
|
||||
/* pc_resetsrc()
|
||||
* "position" may only hold a pointer that was previously obtained from
|
||||
* pc_getpossrc()
|
||||
*/
|
||||
void pc_resetsrc(void *handle,void *position)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
ptrdiff_t pos = (ptrdiff_t)position;
|
||||
|
||||
assert(!src->fp);
|
||||
assert(pos >= 0 && src->buffer + pos <= src->end);
|
||||
src->pos = src->buffer + pos;
|
||||
}
|
||||
|
||||
int pc_eofsrc(void *handle)
|
||||
{
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(!src->fp);
|
||||
return src->pos == src->end;
|
||||
}
|
||||
|
||||
/* should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure
|
||||
*/
|
||||
void *pc_openasm(char *filename)
|
||||
{
|
||||
return mfcreate(filename);
|
||||
}
|
||||
|
||||
void pc_closeasm(void *handle, int deletefile)
|
||||
{
|
||||
if (handle!=NULL) {
|
||||
if (!deletefile)
|
||||
mfdump((MEMFILE*)handle);
|
||||
mfclose((MEMFILE*)handle);
|
||||
} /* if */
|
||||
}
|
||||
|
||||
void pc_resetasm(void *handle)
|
||||
{
|
||||
mfseek((MEMFILE*)handle,0,SEEK_SET);
|
||||
}
|
||||
|
||||
int pc_writeasm(void *handle,const char *string)
|
||||
{
|
||||
return mfputs((MEMFILE*)handle,string);
|
||||
}
|
||||
|
||||
char *pc_readasm(void *handle, char *string, int maxchars)
|
||||
{
|
||||
return mfgets((MEMFILE*)handle,string,maxchars);
|
||||
}
|
||||
|
||||
extern memfile_t *bin_file;
|
||||
|
||||
/* Should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure.
|
||||
*/
|
||||
void *pc_openbin(char *filename)
|
||||
{
|
||||
return memfile_creat(filename, 1);
|
||||
}
|
||||
|
||||
void pc_closebin(void *handle,int deletefile)
|
||||
{
|
||||
if (deletefile) {
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
bin_file = NULL;
|
||||
} else {
|
||||
bin_file = (memfile_t *)handle;
|
||||
}
|
||||
}
|
||||
|
||||
/* pc_resetbin()
|
||||
* Can seek to any location in the file.
|
||||
* The offset is always from the start of the file.
|
||||
*/
|
||||
void pc_resetbin(void *handle,long offset)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, offset);
|
||||
}
|
||||
|
||||
int pc_writebin(void *handle,void *buffer,int size)
|
||||
{
|
||||
return memfile_write((memfile_t *)handle, buffer, size);
|
||||
}
|
||||
|
||||
long pc_lengthbin(void *handle)
|
||||
{
|
||||
return memfile_tell((memfile_t *)handle);
|
||||
}
|
@ -37,7 +37,7 @@
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
extern "C" size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
@ -93,7 +93,7 @@ strlcpy(char *dst, const char *src, size_t siz)
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
extern "C" size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
@ -9,10 +9,18 @@
|
||||
|
||||
#if !defined HAVE_SAFESTR
|
||||
|
||||
size_t
|
||||
#if defined(__cplusplus)
|
||||
# define EXPORT extern "C"
|
||||
#else
|
||||
# define EXPORT
|
||||
#endif
|
||||
|
||||
EXPORT size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
size_t
|
||||
EXPORT size_t
|
||||
strlcat(char *dst, const char *src, size_t siz);
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
#endif
|
||||
|
@ -52,4 +52,15 @@ long memfile_tell(memfile_t *mf);
|
||||
*/
|
||||
void memfile_reset(memfile_t *mf);
|
||||
|
||||
typedef memfile_t MEMFILE;
|
||||
MEMFILE *mfcreate(const char *filename);
|
||||
void mfclose(MEMFILE *mf);
|
||||
int mfdump(MEMFILE *mf);
|
||||
long mflength(const MEMFILE *mf);
|
||||
long mfseek(MEMFILE *mf,long offset,int whence);
|
||||
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size);
|
||||
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size);
|
||||
char *mfgets(MEMFILE *mf,char *string,unsigned int size);
|
||||
int mfputs(MEMFILE *mf,const char *string);
|
||||
|
||||
#endif //_INCLUDE_MEMFILE_H
|
||||
|
@ -1,615 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "memfile.h"
|
||||
#include "sp_file.h"
|
||||
#include "amx.h"
|
||||
#include "amxdbg.h"
|
||||
#include "osdefs.h"
|
||||
#include "zlib/zlib.h"
|
||||
#if defined LINUX || defined DARWIN
|
||||
#include <unistd.h>
|
||||
#elif defined WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
enum FileSections
|
||||
{
|
||||
FS_Code, /* required */
|
||||
FS_Data, /* required */
|
||||
FS_Publics,
|
||||
FS_Pubvars,
|
||||
FS_Natives,
|
||||
FS_Nametable, /* required */
|
||||
FS_DbgFile,
|
||||
FS_DbgSymbol,
|
||||
FS_DbgLine,
|
||||
FS_DbgTags,
|
||||
FS_DbgNatives,
|
||||
FS_DbgAutomaton,
|
||||
FS_DbgState,
|
||||
FS_DbgStrings,
|
||||
FS_DbgInfo,
|
||||
FS_Tags,
|
||||
/* --- */
|
||||
FS_Number,
|
||||
};
|
||||
|
||||
int pc_printf(const char *message,...);
|
||||
int pc_compile(int argc, char **argv);
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
|
||||
|
||||
memfile_t *bin_file = NULL;
|
||||
jmp_buf brkout;
|
||||
|
||||
#define sARGS_MAX 32 /* number of arguments a function can have, max */
|
||||
#define sDIMEN_MAX 4 /* maximum number of array dimensions */
|
||||
|
||||
typedef struct t_arg_s
|
||||
{
|
||||
uint8_t ident;
|
||||
int16_t tag;
|
||||
char *name;
|
||||
uint16_t dimcount;
|
||||
sp_fdbg_arraydim_t dims[sDIMEN_MAX];
|
||||
} t_arg;
|
||||
|
||||
typedef struct t_native_s
|
||||
{
|
||||
char *name;
|
||||
int16_t ret_tag;
|
||||
uint16_t num_args;
|
||||
t_arg args[sARGS_MAX];
|
||||
} t_native;
|
||||
|
||||
t_native *native_list = NULL;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (pc_compile(argc,argv) == 0)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
AMX_DBG_HDR *dbg = NULL;
|
||||
int err;
|
||||
uint32_t i;
|
||||
sp_file_t *spf;
|
||||
memfile_t *dbgtab = NULL; //dbgcrab
|
||||
unsigned char *dbgptr = NULL;
|
||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
|
||||
FILE *fp;
|
||||
|
||||
if (bin_file == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr = (AMX_HEADER *)bin_file->base;
|
||||
|
||||
if ((spf=spfw_create(bin_file->name, NULL)) == NULL)
|
||||
{
|
||||
pc_printf("Error creating binary file!\n");
|
||||
memfile_destroy(bin_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err=setjmp(brkout))!=0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
spfw_add_section(spf, ".code");
|
||||
spfw_add_section(spf, ".data");
|
||||
|
||||
sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
|
||||
if (sections[FS_Publics])
|
||||
{
|
||||
spfw_add_section(spf, ".publics");
|
||||
}
|
||||
sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
|
||||
if (sections[FS_Pubvars])
|
||||
{
|
||||
spfw_add_section(spf, ".pubvars");
|
||||
}
|
||||
sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
if (sections[FS_Natives])
|
||||
{
|
||||
spfw_add_section(spf, ".natives");
|
||||
}
|
||||
sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize;
|
||||
if (sections[FS_Tags])
|
||||
{
|
||||
spfw_add_section(spf, ".tags");
|
||||
}
|
||||
|
||||
spfw_add_section(spf, ".names");
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
|
||||
if (dbg->magic != AMX_DBG_MAGIC)
|
||||
{
|
||||
pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
|
||||
} else {
|
||||
dbgtab = memfile_creat("", 512);
|
||||
dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
|
||||
if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.natives");
|
||||
}
|
||||
if (dbg->files)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.files");
|
||||
sections[FS_DbgFile] = dbg->files;
|
||||
}
|
||||
if (dbg->lines)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.lines");
|
||||
sections[FS_DbgLine] = dbg->lines;
|
||||
}
|
||||
if (dbg->symbols)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.symbols");
|
||||
sections[FS_DbgSymbol] = dbg->symbols;
|
||||
}
|
||||
sections[FS_DbgInfo] = 1;
|
||||
sections[FS_DbgStrings] = 1;
|
||||
spfw_add_section(spf, ".dbg.info");
|
||||
spfw_add_section(spf, ".dbg.strings");
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_header(spf);
|
||||
|
||||
/**
|
||||
* Begin writing each of our known tables out
|
||||
*/
|
||||
|
||||
if (sections[FS_Code])
|
||||
{
|
||||
sp_file_code_t cod;
|
||||
unsigned char *cbase;
|
||||
|
||||
cod.cellsize = sizeof(cell);
|
||||
|
||||
cod.codesize = hdr->dat - hdr->cod;
|
||||
cod.codeversion = hdr->amx_version;
|
||||
cod.flags = 0;
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
cod.flags |= SP_FLAG_DEBUG;
|
||||
}
|
||||
cod.code = sizeof(cod);
|
||||
cod.main = hdr->cip;
|
||||
|
||||
/* write the code */
|
||||
cbase = (unsigned char *)hdr + hdr->cod;
|
||||
sfwrite(&cod, sizeof(cod), 1, spf);
|
||||
sfwrite(cbase, cod.codesize, 1, spf);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Data])
|
||||
{
|
||||
sp_file_data_t dat;
|
||||
unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
|
||||
|
||||
dat.datasize = hdr->hea - hdr->dat;
|
||||
dat.memsize = hdr->stp;
|
||||
dat.data = sizeof(dat);
|
||||
|
||||
/* write header */
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
|
||||
if (dat.datasize)
|
||||
{
|
||||
/* write data */
|
||||
sfwrite(dbase, dat.datasize, 1, spf);
|
||||
}
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Publics])
|
||||
{
|
||||
sp_file_publics_t *pbtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t publics = sections[FS_Publics];
|
||||
|
||||
pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
|
||||
stubptr = (unsigned char *)hdr + hdr->publics;
|
||||
|
||||
for (i=0; i<publics; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbtbl[i].address = stub->address;
|
||||
pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (publics)
|
||||
{
|
||||
sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
|
||||
}
|
||||
free(pbtbl);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Pubvars])
|
||||
{
|
||||
sp_file_pubvars_t *pbvars;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t pubvars = sections[FS_Pubvars];
|
||||
|
||||
pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
|
||||
stubptr = (unsigned char *)hdr + hdr->pubvars;
|
||||
|
||||
for (i=0; i<pubvars; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbvars[i].address = stub->address;
|
||||
pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (pubvars)
|
||||
{
|
||||
sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
|
||||
}
|
||||
free(pbvars);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Natives])
|
||||
{
|
||||
sp_file_natives_t *nvtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
|
||||
nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives);
|
||||
stubptr = (unsigned char *)hdr + hdr->natives;
|
||||
|
||||
for (i=0; i<natives; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
nvtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (natives)
|
||||
{
|
||||
sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
|
||||
}
|
||||
free(nvtbl);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Tags])
|
||||
{
|
||||
uint32_t numTags = (uint32_t)sections[FS_Tags];
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
sp_file_tag_t tag;
|
||||
|
||||
for (i=0; i<numTags; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (i * hdr->defsize));
|
||||
tag.tag_id = stub->address;
|
||||
tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf);
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Nametable])
|
||||
{
|
||||
unsigned char *base;
|
||||
uint32_t namelen;
|
||||
|
||||
/* write the entire block */
|
||||
base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t);
|
||||
/**
|
||||
* note - the name table will be padded to sizeof(cell) bytes.
|
||||
* this may clip at most an extra three bytes in!
|
||||
*/
|
||||
namelen = hdr->cod - hdr->nametable;
|
||||
sfwrite(base, namelen, 1, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
sp_fdbg_info_t info;
|
||||
|
||||
memset(&info, 0, sizeof(sp_fdbg_info_t));
|
||||
|
||||
if (sections[FS_Natives])
|
||||
{
|
||||
uint16_t j;
|
||||
uint32_t idx;
|
||||
uint32_t name;
|
||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
|
||||
sfwrite(&natives, sizeof(uint32_t), 1, spf);
|
||||
for (idx=0; idx<natives; idx++)
|
||||
{
|
||||
sfwrite(&idx, sizeof(uint32_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
|
||||
|
||||
/* Go through arguments */
|
||||
for (j = 0; j < native_list[idx].num_args; j++)
|
||||
{
|
||||
sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
memfile_write(dbgtab,
|
||||
native_list[idx].args[j].name,
|
||||
strlen(native_list[idx].args[j].name) + 1);
|
||||
if (native_list[idx].args[j].dimcount)
|
||||
{
|
||||
sfwrite(native_list[idx].args[j].dims,
|
||||
sizeof(sp_fdbg_arraydim_t),
|
||||
native_list[idx].args[j].dimcount,
|
||||
spf);
|
||||
}
|
||||
free(native_list[idx].args[j].name);
|
||||
}
|
||||
free(native_list[idx].name);
|
||||
}
|
||||
free(native_list);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgFile])
|
||||
{
|
||||
uint32_t idx;
|
||||
sp_fdbg_file_t dbgfile;
|
||||
AMX_DBG_FILE *_ptr;
|
||||
uint32_t len;
|
||||
for (idx=0; idx<sections[FS_DbgFile]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
||||
len = strlen(_ptr->name);
|
||||
/* store */
|
||||
dbgfile.addr = _ptr->address;
|
||||
dbgfile.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
|
||||
/* write to tab, then move to next */
|
||||
memfile_write(dbgtab, _ptr->name, len + 1);
|
||||
dbgptr += sizeof(AMX_DBG_FILE) + len;
|
||||
info.num_files++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgLine])
|
||||
{
|
||||
uint32_t idx;
|
||||
AMX_DBG_LINE *line;
|
||||
sp_fdbg_line_t dbgline;
|
||||
for (idx=0; idx<sections[FS_DbgLine]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
line = (AMX_DBG_LINE *)dbgptr;
|
||||
/* store */
|
||||
dbgline.addr = (uint32_t)line->address;
|
||||
dbgline.line = (uint32_t)line->line;
|
||||
sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_LINE);
|
||||
info.num_lines++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgSymbol])
|
||||
{
|
||||
uint32_t idx;
|
||||
uint32_t dnum;
|
||||
AMX_DBG_SYMBOL *sym;
|
||||
AMX_DBG_SYMDIM *dim;
|
||||
sp_fdbg_symbol_t dbgsym;
|
||||
sp_fdbg_arraydim_t dbgdim;
|
||||
uint32_t len;
|
||||
|
||||
for (idx=0; idx<sections[FS_DbgSymbol]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
||||
/* store */
|
||||
dbgsym.addr = (int32_t)sym->address;
|
||||
dbgsym.tagid = sym->tag;
|
||||
dbgsym.codestart = (uint32_t)sym->codestart;
|
||||
dbgsym.codeend = (uint32_t)sym->codeend;
|
||||
dbgsym.dimcount = (uint16_t)sym->dim;
|
||||
dbgsym.vclass = (uint8_t)sym->vclass;
|
||||
dbgsym.ident = (uint8_t)sym->ident;
|
||||
dbgsym.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
|
||||
/* write to tab */
|
||||
len = strlen(sym->name);
|
||||
memfile_write(dbgtab, sym->name, len + 1);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
|
||||
/* look for any dimensions */
|
||||
info.num_syms++;
|
||||
for (dnum=0; dnum<dbgsym.dimcount; dnum++)
|
||||
{
|
||||
/* get entry info */
|
||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
||||
/* store */
|
||||
dbgdim.size = (uint32_t)dim->size;
|
||||
dbgdim.tagid = dim->tag;
|
||||
sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMDIM);
|
||||
info.num_arrays++;
|
||||
}
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf);
|
||||
spfw_next_section(spf);
|
||||
|
||||
if (sections[FS_DbgStrings])
|
||||
{
|
||||
sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_all(spf);
|
||||
|
||||
/**
|
||||
* do compression
|
||||
* new block for scoping only
|
||||
*/
|
||||
{
|
||||
memfile_t *pOrig = (memfile_t *)spf->handle;
|
||||
sp_file_hdr_t *pHdr;
|
||||
unsigned char *proper;
|
||||
size_t size;
|
||||
Bytef *zcmp;
|
||||
uLong disksize;
|
||||
size_t header_size;
|
||||
int err = Z_OK;
|
||||
|
||||
/* reuse this memory block! */
|
||||
memfile_reset(bin_file);
|
||||
|
||||
/* copy tip of header */
|
||||
memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
|
||||
|
||||
/* get pointer to header */
|
||||
pHdr = (sp_file_hdr_t *)bin_file->base;
|
||||
|
||||
/* copy the rest of the header */
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
|
||||
pHdr->dataoffs - sizeof(sp_file_hdr_t));
|
||||
|
||||
header_size = pHdr->dataoffs;
|
||||
size = pHdr->imagesize - header_size;
|
||||
proper = (unsigned char *)pOrig->base + header_size;
|
||||
|
||||
/* get initial size estimate */
|
||||
disksize = compressBound(pHdr->imagesize);
|
||||
pHdr->disksize = (uint32_t)disksize;
|
||||
zcmp = (Bytef *)malloc(pHdr->disksize);
|
||||
|
||||
if ((err=compress2(zcmp,
|
||||
&disksize,
|
||||
(Bytef *)proper,
|
||||
(uLong)size,
|
||||
Z_BEST_COMPRESSION))
|
||||
!= Z_OK)
|
||||
{
|
||||
free(zcmp);
|
||||
pc_printf("Unable to compress (Z): error %d\n", err);
|
||||
pc_printf("Falling back to no compression.");
|
||||
memfile_write(bin_file,
|
||||
proper,
|
||||
size);
|
||||
} else {
|
||||
pHdr->disksize = (uint32_t)disksize + header_size;
|
||||
pHdr->compression = SPFILE_COMPRESSION_GZ;
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)zcmp,
|
||||
disksize);
|
||||
free(zcmp);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_destroy(spf);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
/**
|
||||
* write file
|
||||
*/
|
||||
if ((fp=fopen(bin_file->name, "wb")) != NULL)
|
||||
{
|
||||
fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
|
||||
fclose(fp);
|
||||
} else {
|
||||
pc_printf("Unable to open %s for writing!", bin_file->name);
|
||||
}
|
||||
|
||||
memfile_destroy(bin_file);
|
||||
|
||||
return 0;
|
||||
|
||||
write_error:
|
||||
pc_printf("Error writing to file: %s", bin_file->name);
|
||||
|
||||
spfw_destroy(spf);
|
||||
unlink(bin_file->name);
|
||||
memfile_destroy(bin_file);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
|
||||
{
|
||||
if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
|
||||
{
|
||||
longjmp(brkout, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void sp_fdbg_ntv_start(int num_natives)
|
||||
{
|
||||
if (num_natives == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
native_list = (t_native *)malloc(sizeof(t_native) * num_natives);
|
||||
memset(native_list, 0, sizeof(t_native) * num_natives);
|
||||
}
|
||||
|
||||
#include "sc.h"
|
||||
|
||||
void sp_fdbg_ntv_hook(int index, symbol *sym)
|
||||
{
|
||||
int i, j;
|
||||
t_native *native;
|
||||
|
||||
native = &native_list[index];
|
||||
native->name = strdup(sym->name);
|
||||
|
||||
for (i = 0; i < sMAXARGS; i++)
|
||||
{
|
||||
if (sym->dim.arglist[i].ident == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
native->num_args++;
|
||||
native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0];
|
||||
native->args[i].name = strdup(sym->dim.arglist[i].name);
|
||||
native->args[i].ident = sym->dim.arglist[i].ident;
|
||||
native->args[i].dimcount = sym->dim.arglist[i].numdim;
|
||||
for (j = 0; j < native->args[i].dimcount; j++)
|
||||
{
|
||||
native->args[i].dims[j].size = sym->dim.arglist[i].dim[j];
|
||||
native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j];
|
||||
}
|
||||
}
|
||||
|
||||
native->ret_tag = sym->tag;
|
||||
}
|
581
sourcepawn/compiler/pawncc.cpp
Normal file
581
sourcepawn/compiler/pawncc.cpp
Normal file
@ -0,0 +1,581 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "memfile.h"
|
||||
#include "sp_file.h"
|
||||
#include "amx.h"
|
||||
#include "amxdbg.h"
|
||||
#include "osdefs.h"
|
||||
#include "zlib/zlib.h"
|
||||
#if defined LINUX || defined DARWIN
|
||||
#include <unistd.h>
|
||||
#elif defined WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
enum FileSections
|
||||
{
|
||||
FS_Code, /* required */
|
||||
FS_Data, /* required */
|
||||
FS_Publics,
|
||||
FS_Pubvars,
|
||||
FS_Natives,
|
||||
FS_Nametable, /* required */
|
||||
FS_DbgFile,
|
||||
FS_DbgSymbol,
|
||||
FS_DbgLine,
|
||||
FS_DbgTags,
|
||||
FS_DbgNatives,
|
||||
FS_DbgAutomaton,
|
||||
FS_DbgState,
|
||||
FS_DbgStrings,
|
||||
FS_DbgInfo,
|
||||
FS_Tags,
|
||||
/* --- */
|
||||
FS_Number,
|
||||
};
|
||||
|
||||
int pc_printf(const char *message,...);
|
||||
int pc_compile(int argc, char **argv);
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
|
||||
|
||||
memfile_t *bin_file = NULL;
|
||||
jmp_buf brkout;
|
||||
|
||||
#define sARGS_MAX 32 /* number of arguments a function can have, max */
|
||||
#define sDIMEN_MAX 4 /* maximum number of array dimensions */
|
||||
|
||||
typedef struct t_arg_s
|
||||
{
|
||||
uint8_t ident;
|
||||
int16_t tag;
|
||||
char *name;
|
||||
uint16_t dimcount;
|
||||
sp_fdbg_arraydim_t dims[sDIMEN_MAX];
|
||||
} t_arg;
|
||||
|
||||
typedef struct t_native_s
|
||||
{
|
||||
char *name;
|
||||
int16_t ret_tag;
|
||||
uint16_t num_args;
|
||||
t_arg args[sARGS_MAX];
|
||||
} t_native;
|
||||
|
||||
t_native *native_list = NULL;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (pc_compile(argc,argv) != 0)
|
||||
return 1;
|
||||
|
||||
AMX_HEADER *hdr;
|
||||
AMX_DBG_HDR *dbg = NULL;
|
||||
int err;
|
||||
uint32_t i;
|
||||
sp_file_t *spf;
|
||||
memfile_t *dbgtab = NULL; //dbgcrab
|
||||
unsigned char *dbgptr = NULL;
|
||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
|
||||
FILE *fp;
|
||||
|
||||
if (bin_file == NULL)
|
||||
return 0;
|
||||
|
||||
hdr = (AMX_HEADER *)bin_file->base;
|
||||
|
||||
if ((spf=spfw_create(bin_file->name, NULL)) == NULL) {
|
||||
pc_printf("Error creating binary file!\n");
|
||||
memfile_destroy(bin_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err=setjmp(brkout))!=0)
|
||||
goto write_error;
|
||||
|
||||
spfw_add_section(spf, ".code");
|
||||
spfw_add_section(spf, ".data");
|
||||
|
||||
sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
|
||||
if (sections[FS_Publics])
|
||||
spfw_add_section(spf, ".publics");
|
||||
sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
|
||||
if (sections[FS_Pubvars])
|
||||
spfw_add_section(spf, ".pubvars");
|
||||
sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
if (sections[FS_Natives])
|
||||
spfw_add_section(spf, ".natives");
|
||||
sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize;
|
||||
if (sections[FS_Tags])
|
||||
spfw_add_section(spf, ".tags");
|
||||
|
||||
spfw_add_section(spf, ".names");
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG) {
|
||||
dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
|
||||
if (dbg->magic != AMX_DBG_MAGIC) {
|
||||
pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
|
||||
} else {
|
||||
dbgtab = memfile_creat("", 512);
|
||||
dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
|
||||
if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0)
|
||||
spfw_add_section(spf, ".dbg.natives");
|
||||
if (dbg->files) {
|
||||
spfw_add_section(spf, ".dbg.files");
|
||||
sections[FS_DbgFile] = dbg->files;
|
||||
}
|
||||
if (dbg->lines) {
|
||||
spfw_add_section(spf, ".dbg.lines");
|
||||
sections[FS_DbgLine] = dbg->lines;
|
||||
}
|
||||
if (dbg->symbols) {
|
||||
spfw_add_section(spf, ".dbg.symbols");
|
||||
sections[FS_DbgSymbol] = dbg->symbols;
|
||||
}
|
||||
sections[FS_DbgInfo] = 1;
|
||||
sections[FS_DbgStrings] = 1;
|
||||
spfw_add_section(spf, ".dbg.info");
|
||||
spfw_add_section(spf, ".dbg.strings");
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_header(spf);
|
||||
|
||||
/**
|
||||
* Begin writing each of our known tables out
|
||||
*/
|
||||
|
||||
if (sections[FS_Code]) {
|
||||
sp_file_code_t cod;
|
||||
unsigned char *cbase;
|
||||
|
||||
cod.cellsize = sizeof(cell);
|
||||
|
||||
cod.codesize = hdr->dat - hdr->cod;
|
||||
cod.codeversion = hdr->amx_version;
|
||||
cod.flags = 0;
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
cod.flags |= SP_FLAG_DEBUG;
|
||||
}
|
||||
cod.code = sizeof(cod);
|
||||
cod.main = hdr->cip;
|
||||
|
||||
/* write the code */
|
||||
cbase = (unsigned char *)hdr + hdr->cod;
|
||||
sfwrite(&cod, sizeof(cod), 1, spf);
|
||||
sfwrite(cbase, cod.codesize, 1, spf);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Data]) {
|
||||
sp_file_data_t dat;
|
||||
unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
|
||||
|
||||
dat.datasize = hdr->hea - hdr->dat;
|
||||
dat.memsize = hdr->stp;
|
||||
dat.data = sizeof(dat);
|
||||
|
||||
/* write header */
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
|
||||
if (dat.datasize) {
|
||||
/* write data */
|
||||
sfwrite(dbase, dat.datasize, 1, spf);
|
||||
}
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Publics]) {
|
||||
sp_file_publics_t *pbtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t publics = sections[FS_Publics];
|
||||
|
||||
pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
|
||||
stubptr = (unsigned char *)hdr + hdr->publics;
|
||||
|
||||
for (i=0; i<publics; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbtbl[i].address = stub->address;
|
||||
pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (publics)
|
||||
sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
|
||||
free(pbtbl);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Pubvars]) {
|
||||
sp_file_pubvars_t *pbvars;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t pubvars = sections[FS_Pubvars];
|
||||
|
||||
pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
|
||||
stubptr = (unsigned char *)hdr + hdr->pubvars;
|
||||
|
||||
for (i=0; i<pubvars; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbvars[i].address = stub->address;
|
||||
pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (pubvars)
|
||||
sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
|
||||
free(pbvars);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Natives]) {
|
||||
sp_file_natives_t *nvtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
|
||||
nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives);
|
||||
stubptr = (unsigned char *)hdr + hdr->natives;
|
||||
|
||||
for (i=0; i<natives; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
nvtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (natives) {
|
||||
sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
|
||||
}
|
||||
free(nvtbl);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Tags]) {
|
||||
uint32_t numTags = (uint32_t)sections[FS_Tags];
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
sp_file_tag_t tag;
|
||||
|
||||
for (i=0; i<numTags; i++) {
|
||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (i * hdr->defsize));
|
||||
tag.tag_id = stub->address;
|
||||
tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf);
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Nametable]) {
|
||||
unsigned char *base;
|
||||
uint32_t namelen;
|
||||
|
||||
/* write the entire block */
|
||||
base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t);
|
||||
/**
|
||||
* note - the name table will be padded to sizeof(cell) bytes.
|
||||
* this may clip at most an extra three bytes in!
|
||||
*/
|
||||
namelen = hdr->cod - hdr->nametable;
|
||||
sfwrite(base, namelen, 1, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG) {
|
||||
sp_fdbg_info_t info;
|
||||
|
||||
memset(&info, 0, sizeof(sp_fdbg_info_t));
|
||||
|
||||
if (sections[FS_Natives]) {
|
||||
uint16_t j;
|
||||
uint32_t idx;
|
||||
uint32_t name;
|
||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
|
||||
sfwrite(&natives, sizeof(uint32_t), 1, spf);
|
||||
for (idx=0; idx<natives; idx++) {
|
||||
sfwrite(&idx, sizeof(uint32_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
|
||||
|
||||
/* Go through arguments */
|
||||
for (j = 0; j < native_list[idx].num_args; j++) {
|
||||
sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
|
||||
sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
|
||||
name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
||||
memfile_write(dbgtab,
|
||||
native_list[idx].args[j].name,
|
||||
strlen(native_list[idx].args[j].name) + 1);
|
||||
if (native_list[idx].args[j].dimcount) {
|
||||
sfwrite(native_list[idx].args[j].dims,
|
||||
sizeof(sp_fdbg_arraydim_t),
|
||||
native_list[idx].args[j].dimcount,
|
||||
spf);
|
||||
}
|
||||
free(native_list[idx].args[j].name);
|
||||
}
|
||||
free(native_list[idx].name);
|
||||
}
|
||||
free(native_list);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgFile]) {
|
||||
uint32_t idx;
|
||||
sp_fdbg_file_t dbgfile;
|
||||
AMX_DBG_FILE *_ptr;
|
||||
uint32_t len;
|
||||
for (idx=0; idx<sections[FS_DbgFile]; idx++) {
|
||||
/* get entry info */
|
||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
||||
len = strlen(_ptr->name);
|
||||
/* store */
|
||||
dbgfile.addr = _ptr->address;
|
||||
dbgfile.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
|
||||
/* write to tab, then move to next */
|
||||
memfile_write(dbgtab, _ptr->name, len + 1);
|
||||
dbgptr += sizeof(AMX_DBG_FILE) + len;
|
||||
info.num_files++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgLine]) {
|
||||
uint32_t idx;
|
||||
AMX_DBG_LINE *line;
|
||||
sp_fdbg_line_t dbgline;
|
||||
for (idx=0; idx<sections[FS_DbgLine]; idx++) {
|
||||
/* get entry info */
|
||||
line = (AMX_DBG_LINE *)dbgptr;
|
||||
/* store */
|
||||
dbgline.addr = (uint32_t)line->address;
|
||||
dbgline.line = (uint32_t)line->line;
|
||||
sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_LINE);
|
||||
info.num_lines++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgSymbol]) {
|
||||
uint32_t idx;
|
||||
uint32_t dnum;
|
||||
AMX_DBG_SYMBOL *sym;
|
||||
AMX_DBG_SYMDIM *dim;
|
||||
sp_fdbg_symbol_t dbgsym;
|
||||
sp_fdbg_arraydim_t dbgdim;
|
||||
uint32_t len;
|
||||
|
||||
for (idx=0; idx<sections[FS_DbgSymbol]; idx++) {
|
||||
/* get entry info */
|
||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
||||
/* store */
|
||||
dbgsym.addr = (int32_t)sym->address;
|
||||
dbgsym.tagid = sym->tag;
|
||||
dbgsym.codestart = (uint32_t)sym->codestart;
|
||||
dbgsym.codeend = (uint32_t)sym->codeend;
|
||||
dbgsym.dimcount = (uint16_t)sym->dim;
|
||||
dbgsym.vclass = (uint8_t)sym->vclass;
|
||||
dbgsym.ident = (uint8_t)sym->ident;
|
||||
dbgsym.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
|
||||
/* write to tab */
|
||||
len = strlen(sym->name);
|
||||
memfile_write(dbgtab, sym->name, len + 1);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
|
||||
/* look for any dimensions */
|
||||
info.num_syms++;
|
||||
for (dnum=0; dnum<dbgsym.dimcount; dnum++)
|
||||
{
|
||||
/* get entry info */
|
||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
||||
/* store */
|
||||
dbgdim.size = (uint32_t)dim->size;
|
||||
dbgdim.tagid = dim->tag;
|
||||
sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMDIM);
|
||||
info.num_arrays++;
|
||||
}
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf);
|
||||
spfw_next_section(spf);
|
||||
|
||||
if (sections[FS_DbgStrings]) {
|
||||
sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_all(spf);
|
||||
|
||||
/**
|
||||
* do compression
|
||||
* new block for scoping only
|
||||
*/
|
||||
{
|
||||
memfile_t *pOrig = (memfile_t *)spf->handle;
|
||||
sp_file_hdr_t *pHdr;
|
||||
unsigned char *proper;
|
||||
size_t size;
|
||||
Bytef *zcmp;
|
||||
uLong disksize;
|
||||
size_t header_size;
|
||||
int err = Z_OK;
|
||||
|
||||
/* reuse this memory block! */
|
||||
memfile_reset(bin_file);
|
||||
|
||||
/* copy tip of header */
|
||||
memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
|
||||
|
||||
/* get pointer to header */
|
||||
pHdr = (sp_file_hdr_t *)bin_file->base;
|
||||
|
||||
/* copy the rest of the header */
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
|
||||
pHdr->dataoffs - sizeof(sp_file_hdr_t));
|
||||
|
||||
header_size = pHdr->dataoffs;
|
||||
size = pHdr->imagesize - header_size;
|
||||
proper = (unsigned char *)pOrig->base + header_size;
|
||||
|
||||
/* get initial size estimate */
|
||||
disksize = compressBound(pHdr->imagesize);
|
||||
pHdr->disksize = (uint32_t)disksize;
|
||||
zcmp = (Bytef *)malloc(pHdr->disksize);
|
||||
|
||||
if ((err=compress2(zcmp,
|
||||
&disksize,
|
||||
(Bytef *)proper,
|
||||
(uLong)size,
|
||||
Z_BEST_COMPRESSION))
|
||||
!= Z_OK)
|
||||
{
|
||||
free(zcmp);
|
||||
pc_printf("Unable to compress (Z): error %d\n", err);
|
||||
pc_printf("Falling back to no compression.");
|
||||
memfile_write(bin_file,
|
||||
proper,
|
||||
size);
|
||||
} else {
|
||||
pHdr->disksize = (uint32_t)disksize + header_size;
|
||||
pHdr->compression = SPFILE_COMPRESSION_GZ;
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)zcmp,
|
||||
disksize);
|
||||
free(zcmp);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_destroy(spf);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
/**
|
||||
* write file
|
||||
*/
|
||||
if ((fp=fopen(bin_file->name, "wb")) != NULL) {
|
||||
fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
|
||||
fclose(fp);
|
||||
} else {
|
||||
pc_printf("Unable to open %s for writing!", bin_file->name);
|
||||
}
|
||||
|
||||
memfile_destroy(bin_file);
|
||||
|
||||
return 0;
|
||||
|
||||
write_error:
|
||||
pc_printf("Error writing to file: %s", bin_file->name);
|
||||
|
||||
spfw_destroy(spf);
|
||||
unlink(bin_file->name);
|
||||
memfile_destroy(bin_file);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
|
||||
{
|
||||
if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
|
||||
longjmp(brkout, 1);
|
||||
}
|
||||
|
||||
void sp_fdbg_ntv_start(int num_natives)
|
||||
{
|
||||
if (num_natives == 0)
|
||||
return;
|
||||
|
||||
native_list = (t_native *)malloc(sizeof(t_native) * num_natives);
|
||||
memset(native_list, 0, sizeof(t_native) * num_natives);
|
||||
}
|
||||
|
||||
#include "sc.h"
|
||||
void sp_fdbg_ntv_hook(int index, symbol *sym)
|
||||
{
|
||||
int i, j;
|
||||
t_native *native;
|
||||
|
||||
native = &native_list[index];
|
||||
native->name = strdup(sym->name);
|
||||
|
||||
for (i = 0; i < sMAXARGS; i++) {
|
||||
if (sym->dim.arglist[i].ident == 0)
|
||||
break;
|
||||
native->num_args++;
|
||||
native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0];
|
||||
native->args[i].name = strdup(sym->dim.arglist[i].name);
|
||||
native->args[i].ident = sym->dim.arglist[i].ident;
|
||||
native->args[i].dimcount = sym->dim.arglist[i].numdim;
|
||||
for (j = 0; j < native->args[i].dimcount; j++) {
|
||||
native->args[i].dims[j].size = sym->dim.arglist[i].dim[j];
|
||||
native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j];
|
||||
}
|
||||
}
|
||||
|
||||
native->ret_tag = sym->tag;
|
||||
}
|
||||
|
||||
|
||||
#if defined __linux__ || defined __APPLE__
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
@ -537,18 +537,13 @@ typedef enum s_optmark {
|
||||
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
|
||||
|
||||
|
||||
/* interface functions */
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions you call from the "driver" program
|
||||
*/
|
||||
int pc_compile(int argc, char **argv);
|
||||
int pc_addconstant(char *name,cell value,int tag);
|
||||
int pc_addtag(char *name);
|
||||
int pc_addtag_flags(char *name, int flags);
|
||||
int pc_addconstant(const char *name,cell value,int tag);
|
||||
int pc_addtag(const char *name);
|
||||
int pc_addtag_flags(const char *name, int flags);
|
||||
int pc_findtag(const char *name);
|
||||
constvalue *pc_tagptr(const char *name);
|
||||
int pc_enablewarning(int number,int enable);
|
||||
@ -564,7 +559,7 @@ const char *type_to_name(int tag);
|
||||
int pc_printf(const char *message,...);
|
||||
|
||||
/* error report function */
|
||||
int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr);
|
||||
int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr);
|
||||
|
||||
/* input from source file */
|
||||
void *pc_opensrc(char *filename); /* reading only */
|
||||
@ -580,7 +575,7 @@ int pc_eofsrc(void *handle);
|
||||
void *pc_openasm(char *filename); /* read/write */
|
||||
void pc_closeasm(void *handle,int deletefile);
|
||||
void pc_resetasm(void *handle);
|
||||
int pc_writeasm(void *handle,char *str);
|
||||
int pc_writeasm(void *handle,const char *str);
|
||||
char *pc_readasm(void *handle,char *target,int maxchars);
|
||||
|
||||
/* output to binary (.AMX) file */
|
||||
@ -590,161 +585,144 @@ void pc_resetbin(void *handle,long offset);
|
||||
int pc_writebin(void *handle,void *buffer,int size);
|
||||
long pc_lengthbin(void *handle); /* return the length of the file */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* by default, functions and variables used in throughout the compiler
|
||||
* files are "external"
|
||||
*/
|
||||
#if !defined SC_FUNC
|
||||
#define SC_FUNC
|
||||
#endif
|
||||
#if !defined SC_VDECL
|
||||
#define SC_VDECL extern
|
||||
#endif
|
||||
#if !defined SC_VDEFINE
|
||||
#define SC_VDEFINE
|
||||
#endif
|
||||
|
||||
void sp_fdbg_ntv_start(int num_natives);
|
||||
void sp_fdbg_ntv_hook(int index, symbol *sym);
|
||||
|
||||
/* function prototypes in SC1.C */
|
||||
SC_FUNC void set_extension(char *filename,char *extension,int force);
|
||||
SC_FUNC symbol *fetchfunc(char *name);
|
||||
SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag);
|
||||
SC_FUNC char *funcdisplayname(char *dest,char *funcname);
|
||||
SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr);
|
||||
SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
|
||||
SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index);
|
||||
SC_FUNC void delete_consttable(constvalue *table);
|
||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
||||
SC_FUNC void exporttag(int tag);
|
||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
||||
SC_FUNC constvalue *find_tag_byval(int tag);
|
||||
SC_FUNC int get_actual_compound(symbol *sym);
|
||||
void set_extension(char *filename,const char *extension,int force);
|
||||
symbol *fetchfunc(char *name);
|
||||
char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag);
|
||||
char *funcdisplayname(char *dest,char *funcname);
|
||||
int exprconst(cell *val,int *tag,symbol **symptr);
|
||||
constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
|
||||
constvalue *find_constval(constvalue *table,char *name,int index);
|
||||
void delete_consttable(constvalue *table);
|
||||
symbol *add_constant(const char *name,cell val,int vclass,int tag);
|
||||
void exporttag(int tag);
|
||||
void sc_attachdocumentation(symbol *sym);
|
||||
constvalue *find_tag_byval(int tag);
|
||||
int get_actual_compound(symbol *sym);
|
||||
|
||||
/* function prototypes in SC2.C */
|
||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||
#define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); }
|
||||
#define POPSTK_P() (popstk().pv)
|
||||
#define POPSTK_I() (popstk().i)
|
||||
SC_FUNC void pushstk(stkitem val);
|
||||
SC_FUNC stkitem popstk(void);
|
||||
SC_FUNC void clearstk(void);
|
||||
SC_FUNC int plungequalifiedfile(char *name); /* explicit path included */
|
||||
SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
|
||||
SC_FUNC void preprocess(void);
|
||||
SC_FUNC void lexinit(void);
|
||||
SC_FUNC int lex(cell *lexvalue,char **lexsym);
|
||||
SC_FUNC int lextok(token_t *tok);
|
||||
SC_FUNC int lexpeek(int id);
|
||||
SC_FUNC void lexpush(void);
|
||||
SC_FUNC void lexclr(int clreol);
|
||||
SC_FUNC int matchtoken(int token);
|
||||
SC_FUNC int tokeninfo(cell *val,char **str);
|
||||
SC_FUNC int needtoken(int token);
|
||||
SC_FUNC int matchtoken2(int id, token_t *tok);
|
||||
SC_FUNC int expecttoken(int id, token_t *tok);
|
||||
SC_FUNC int matchsymbol(token_ident_t *ident);
|
||||
SC_FUNC int needsymbol(token_ident_t *ident);
|
||||
SC_FUNC int peek_same_line();
|
||||
SC_FUNC int require_newline(int allow_semi);
|
||||
SC_FUNC void litadd(cell value);
|
||||
SC_FUNC void litinsert(cell value,int pos);
|
||||
SC_FUNC int alphanum(char c);
|
||||
SC_FUNC int ishex(char c);
|
||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym);
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
|
||||
SC_FUNC void markusage(symbol *sym,int usage);
|
||||
SC_FUNC symbol *findglb(const char *name,int filter);
|
||||
SC_FUNC symbol *findloc(const char *name);
|
||||
SC_FUNC symbol *findconst(const char *name,int *matchtag);
|
||||
SC_FUNC symbol *finddepend(const symbol *parent);
|
||||
SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage);
|
||||
SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
void pushstk(stkitem val);
|
||||
stkitem popstk(void);
|
||||
void clearstk(void);
|
||||
int plungequalifiedfile(char *name); /* explicit path included */
|
||||
int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
|
||||
void preprocess(void);
|
||||
void lexinit(void);
|
||||
int lex(cell *lexvalue,char **lexsym);
|
||||
int lextok(token_t *tok);
|
||||
int lexpeek(int id);
|
||||
void lexpush(void);
|
||||
void lexclr(int clreol);
|
||||
int matchtoken(int token);
|
||||
int tokeninfo(cell *val,char **str);
|
||||
int needtoken(int token);
|
||||
int matchtoken2(int id, token_t *tok);
|
||||
int expecttoken(int id, token_t *tok);
|
||||
int matchsymbol(token_ident_t *ident);
|
||||
int needsymbol(token_ident_t *ident);
|
||||
int peek_same_line();
|
||||
int require_newline(int allow_semi);
|
||||
void litadd(cell value);
|
||||
void litinsert(cell value,int pos);
|
||||
int alphanum(char c);
|
||||
int ishex(char c);
|
||||
void delete_symbol(symbol *root,symbol *sym);
|
||||
void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
||||
int refer_symbol(symbol *entry,symbol *bywhom);
|
||||
void markusage(symbol *sym,int usage);
|
||||
symbol *findglb(const char *name,int filter);
|
||||
symbol *findloc(const char *name);
|
||||
symbol *findconst(const char *name,int *matchtag);
|
||||
symbol *finddepend(const symbol *parent);
|
||||
symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage);
|
||||
symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[]);
|
||||
SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[],int slength);
|
||||
SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
|
||||
SC_FUNC int getlabel(void);
|
||||
SC_FUNC char *itoh(ucell val);
|
||||
symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
|
||||
int getlabel(void);
|
||||
char *itoh(ucell val);
|
||||
|
||||
#define MATCHTAG_COERCE 0x1 // allow coercion
|
||||
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
|
||||
#define MATCHTAG_COMMUTATIVE 0x4 // order does not matter
|
||||
|
||||
/* function prototypes in SC3.C */
|
||||
SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
value *lval,int *resulttag);
|
||||
SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
|
||||
SC_FUNC int checktag(int tags[],int numtags,int exprtag);
|
||||
SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval);
|
||||
SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
|
||||
SC_FUNC cell array_totalsize(symbol *sym);
|
||||
SC_FUNC int matchtag_string(int ident, int tag);
|
||||
SC_FUNC int checktag_string(value *sym1, value *sym2);
|
||||
SC_FUNC int checktags_string(int tags[], int numtags, value *sym1);
|
||||
SC_FUNC int lvalexpr(svalue *sval);
|
||||
int matchtag(int formaltag,int actualtag,int allowcoerce);
|
||||
int checktag(int tags[],int numtags,int exprtag);
|
||||
int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval);
|
||||
int sc_getstateid(constvalue **automaton,constvalue **state);
|
||||
cell array_totalsize(symbol *sym);
|
||||
int matchtag_string(int ident, int tag);
|
||||
int checktag_string(value *sym1, value *sym2);
|
||||
int checktags_string(int tags[], int numtags, value *sym1);
|
||||
int lvalexpr(svalue *sval);
|
||||
|
||||
/* function prototypes in SC4.C */
|
||||
SC_FUNC void writeleader(symbol *root);
|
||||
SC_FUNC void writetrailer(void);
|
||||
SC_FUNC void begcseg(void);
|
||||
SC_FUNC void begdseg(void);
|
||||
SC_FUNC void setline(int chkbounds);
|
||||
SC_FUNC void setfiledirect(char *name);
|
||||
SC_FUNC void setlinedirect(int line);
|
||||
SC_FUNC void setlabel(int index);
|
||||
SC_FUNC void markexpr(optmark type,const char *name,cell offset);
|
||||
SC_FUNC void startfunc(char *fname);
|
||||
SC_FUNC void endfunc(void);
|
||||
SC_FUNC void alignframe(int numbytes);
|
||||
SC_FUNC void rvalue(value *lval);
|
||||
SC_FUNC void address(symbol *ptr,regid reg);
|
||||
SC_FUNC void store(value *lval);
|
||||
SC_FUNC void loadreg(cell address,regid reg);
|
||||
SC_FUNC void storereg(cell address,regid reg);
|
||||
SC_FUNC void memcopy(cell size);
|
||||
SC_FUNC void copyarray(symbol *sym,cell size);
|
||||
SC_FUNC void fillarray(symbol *sym,cell size,cell value);
|
||||
SC_FUNC void ldconst(cell val,regid reg);
|
||||
SC_FUNC void moveto1(void);
|
||||
SC_FUNC void move_alt(void);
|
||||
SC_FUNC void pushreg(regid reg);
|
||||
SC_FUNC void pushval(cell val);
|
||||
SC_FUNC void popreg(regid reg);
|
||||
SC_FUNC void genarray(int dims, int _autozero);
|
||||
SC_FUNC void swap1(void);
|
||||
SC_FUNC void ffswitch(int label);
|
||||
SC_FUNC void ffcase(cell value,char *labelname,int newtable);
|
||||
SC_FUNC void ffcall(symbol *sym,const char *label,int numargs);
|
||||
SC_FUNC void ffret(int remparams);
|
||||
SC_FUNC void ffabort(int reason);
|
||||
SC_FUNC void ffbounds(cell size);
|
||||
SC_FUNC void jumplabel(int number);
|
||||
SC_FUNC void defstorage(void);
|
||||
SC_FUNC void modstk(int delta);
|
||||
SC_FUNC void setstk(cell value);
|
||||
SC_FUNC void modheap(int delta);
|
||||
SC_FUNC void modheap_i();
|
||||
SC_FUNC void setheap_pri(void);
|
||||
SC_FUNC void setheap(cell value);
|
||||
SC_FUNC void cell2addr(void);
|
||||
SC_FUNC void cell2addr_alt(void);
|
||||
SC_FUNC void addr2cell(void);
|
||||
SC_FUNC void char2addr(void);
|
||||
SC_FUNC void charalign(void);
|
||||
SC_FUNC void addconst(cell value);
|
||||
SC_FUNC void setheap_save(cell value);
|
||||
SC_FUNC void stradjust(regid reg);
|
||||
SC_FUNC void invoke_getter(struct methodmap_method_s *method);
|
||||
SC_FUNC void invoke_setter(struct methodmap_method_s *method, int save);
|
||||
SC_FUNC void inc_pri();
|
||||
SC_FUNC void dec_pri();
|
||||
void writeleader(symbol *root);
|
||||
void writetrailer(void);
|
||||
void begcseg(void);
|
||||
void begdseg(void);
|
||||
void setline(int chkbounds);
|
||||
void setfiledirect(char *name);
|
||||
void setlinedirect(int line);
|
||||
void setlabel(int index);
|
||||
void markexpr(optmark type,const char *name,cell offset);
|
||||
void startfunc(char *fname);
|
||||
void endfunc(void);
|
||||
void alignframe(int numbytes);
|
||||
void rvalue(value *lval);
|
||||
void address(symbol *ptr,regid reg);
|
||||
void store(value *lval);
|
||||
void loadreg(cell address,regid reg);
|
||||
void storereg(cell address,regid reg);
|
||||
void memcopy(cell size);
|
||||
void copyarray(symbol *sym,cell size);
|
||||
void fillarray(symbol *sym,cell size,cell value);
|
||||
void ldconst(cell val,regid reg);
|
||||
void moveto1(void);
|
||||
void move_alt(void);
|
||||
void pushreg(regid reg);
|
||||
void pushval(cell val);
|
||||
void popreg(regid reg);
|
||||
void genarray(int dims, int _autozero);
|
||||
void swap1(void);
|
||||
void ffswitch(int label);
|
||||
void ffcase(cell value,char *labelname,int newtable);
|
||||
void ffcall(symbol *sym,const char *label,int numargs);
|
||||
void ffret(int remparams);
|
||||
void ffabort(int reason);
|
||||
void ffbounds(cell size);
|
||||
void jumplabel(int number);
|
||||
void defstorage(void);
|
||||
void modstk(int delta);
|
||||
void setstk(cell value);
|
||||
void modheap(int delta);
|
||||
void modheap_i();
|
||||
void setheap_pri(void);
|
||||
void setheap(cell value);
|
||||
void cell2addr(void);
|
||||
void cell2addr_alt(void);
|
||||
void addr2cell(void);
|
||||
void char2addr(void);
|
||||
void charalign(void);
|
||||
void addconst(cell value);
|
||||
void setheap_save(cell value);
|
||||
void stradjust(regid reg);
|
||||
void invoke_getter(struct methodmap_method_s *method);
|
||||
void invoke_setter(struct methodmap_method_s *method, int save);
|
||||
void inc_pri();
|
||||
void dec_pri();
|
||||
void load_hidden_arg();
|
||||
|
||||
/* Code generation functions for arithmetic operators.
|
||||
*
|
||||
@ -754,218 +732,204 @@ SC_FUNC void dec_pri();
|
||||
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
|
||||
* +------------- "o"perator
|
||||
*/
|
||||
SC_FUNC void os_mult(void); /* multiplication (signed) */
|
||||
SC_FUNC void os_div(void); /* division (signed) */
|
||||
SC_FUNC void os_mod(void); /* modulus (signed) */
|
||||
SC_FUNC void ob_add(void); /* addition */
|
||||
SC_FUNC void ob_sub(void); /* subtraction */
|
||||
SC_FUNC void ob_sal(void); /* shift left (arithmetic) */
|
||||
SC_FUNC void os_sar(void); /* shift right (arithmetic, signed) */
|
||||
SC_FUNC void ou_sar(void); /* shift right (logical, unsigned) */
|
||||
SC_FUNC void ob_or(void); /* bitwise or */
|
||||
SC_FUNC void ob_xor(void); /* bitwise xor */
|
||||
SC_FUNC void ob_and(void); /* bitwise and */
|
||||
SC_FUNC void ob_eq(void); /* equality */
|
||||
SC_FUNC void ob_ne(void); /* inequality */
|
||||
SC_FUNC void relop_prefix(void);
|
||||
SC_FUNC void relop_suffix(void);
|
||||
SC_FUNC void os_le(void); /* less or equal (signed) */
|
||||
SC_FUNC void os_ge(void); /* greater or equal (signed) */
|
||||
SC_FUNC void os_lt(void); /* less (signed) */
|
||||
SC_FUNC void os_gt(void); /* greater (signed) */
|
||||
void os_mult(void); /* multiplication (signed) */
|
||||
void os_div(void); /* division (signed) */
|
||||
void os_mod(void); /* modulus (signed) */
|
||||
void ob_add(void); /* addition */
|
||||
void ob_sub(void); /* subtraction */
|
||||
void ob_sal(void); /* shift left (arithmetic) */
|
||||
void os_sar(void); /* shift right (arithmetic, signed) */
|
||||
void ou_sar(void); /* shift right (logical, unsigned) */
|
||||
void ob_or(void); /* bitwise or */
|
||||
void ob_xor(void); /* bitwise xor */
|
||||
void ob_and(void); /* bitwise and */
|
||||
void ob_eq(void); /* equality */
|
||||
void ob_ne(void); /* inequality */
|
||||
void relop_prefix(void);
|
||||
void relop_suffix(void);
|
||||
void os_le(void); /* less or equal (signed) */
|
||||
void os_ge(void); /* greater or equal (signed) */
|
||||
void os_lt(void); /* less (signed) */
|
||||
void os_gt(void); /* greater (signed) */
|
||||
|
||||
SC_FUNC void lneg(void);
|
||||
SC_FUNC void neg(void);
|
||||
SC_FUNC void invert(void);
|
||||
SC_FUNC void nooperation(void);
|
||||
SC_FUNC void inc(value *lval);
|
||||
SC_FUNC void dec(value *lval);
|
||||
SC_FUNC void jmp_ne0(int number);
|
||||
SC_FUNC void jmp_eq0(int number);
|
||||
SC_FUNC void outval(cell val,int newline);
|
||||
void lneg(void);
|
||||
void neg(void);
|
||||
void invert(void);
|
||||
void nooperation(void);
|
||||
void inc(value *lval);
|
||||
void dec(value *lval);
|
||||
void jmp_ne0(int number);
|
||||
void jmp_eq0(int number);
|
||||
void outval(cell val,int newline);
|
||||
|
||||
/* function prototypes in SC5.C */
|
||||
SC_FUNC int error(int number,...);
|
||||
SC_FUNC void errorset(int code,int line);
|
||||
int error(int number,...);
|
||||
void errorset(int code,int line);
|
||||
|
||||
/* function prototypes in SC6.C */
|
||||
SC_FUNC int assemble(FILE *fout,FILE *fin);
|
||||
int assemble(void *fout,void *fin);
|
||||
|
||||
/* function prototypes in SC7.C */
|
||||
SC_FUNC void stgbuffer_cleanup(void);
|
||||
SC_FUNC void stgmark(char mark);
|
||||
SC_FUNC void stgwrite(const char *st);
|
||||
SC_FUNC void stgout(int index);
|
||||
SC_FUNC void stgdel(int index,cell code_index);
|
||||
SC_FUNC int stgget(int *index,cell *code_index);
|
||||
SC_FUNC void stgset(int onoff);
|
||||
SC_FUNC int phopt_init(void);
|
||||
SC_FUNC int phopt_cleanup(void);
|
||||
void stgbuffer_cleanup(void);
|
||||
void stgmark(char mark);
|
||||
void stgwrite(const char *st);
|
||||
void stgout(int index);
|
||||
void stgdel(int index,cell code_index);
|
||||
int stgget(int *index,cell *code_index);
|
||||
void stgset(int onoff);
|
||||
int phopt_init(void);
|
||||
int phopt_cleanup(void);
|
||||
|
||||
/* function prototypes in SCLIST.C */
|
||||
SC_FUNC char* duplicatestring(const char* sourcestring);
|
||||
SC_FUNC stringpair *insert_alias(char *name,char *alias);
|
||||
SC_FUNC stringpair *find_alias(char *name);
|
||||
SC_FUNC int lookup_alias(char *target,char *name);
|
||||
SC_FUNC void delete_aliastable(void);
|
||||
SC_FUNC stringlist *insert_path(char *path);
|
||||
SC_FUNC char *get_path(int index);
|
||||
SC_FUNC void delete_pathtable(void);
|
||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen);
|
||||
SC_FUNC int get_subst(int index,char **pattern,char **substitution);
|
||||
SC_FUNC stringpair *find_subst(char *name,int length);
|
||||
SC_FUNC int delete_subst(char *name,int length);
|
||||
SC_FUNC void delete_substtable(void);
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string);
|
||||
SC_FUNC char *get_sourcefile(int index);
|
||||
SC_FUNC void delete_sourcefiletable(void);
|
||||
SC_FUNC stringlist *insert_docstring(char *string);
|
||||
SC_FUNC char *get_docstring(int index);
|
||||
SC_FUNC void delete_docstring(int index);
|
||||
SC_FUNC void delete_docstringtable(void);
|
||||
SC_FUNC stringlist *insert_autolist(char *string);
|
||||
SC_FUNC char *get_autolist(int index);
|
||||
SC_FUNC void delete_autolisttable(void);
|
||||
SC_FUNC stringlist *insert_dbgfile(const char *filename);
|
||||
SC_FUNC stringlist *insert_dbgline(int linenr);
|
||||
SC_FUNC stringlist *insert_dbgsymbol(symbol *sym);
|
||||
SC_FUNC char *get_dbgstring(int index);
|
||||
SC_FUNC void delete_dbgstringtable(void);
|
||||
SC_FUNC stringlist *get_dbgstrings();
|
||||
|
||||
/* function prototypes in SCMEMFILE.C */
|
||||
#if !defined tMEMFILE
|
||||
typedef unsigned char MEMFILE;
|
||||
#define tMEMFILE 1
|
||||
#endif
|
||||
MEMFILE *mfcreate(const char *filename);
|
||||
void mfclose(MEMFILE *mf);
|
||||
int mfdump(MEMFILE *mf);
|
||||
long mflength(const MEMFILE *mf);
|
||||
long mfseek(MEMFILE *mf,long offset,int whence);
|
||||
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size);
|
||||
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size);
|
||||
char *mfgets(MEMFILE *mf,char *string,unsigned int size);
|
||||
int mfputs(MEMFILE *mf,const char *string);
|
||||
char* duplicatestring(const char* sourcestring);
|
||||
stringpair *insert_alias(char *name,char *alias);
|
||||
stringpair *find_alias(char *name);
|
||||
int lookup_alias(char *target,char *name);
|
||||
void delete_aliastable(void);
|
||||
stringlist *insert_path(char *path);
|
||||
char *get_path(int index);
|
||||
void delete_pathtable(void);
|
||||
stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen);
|
||||
int get_subst(int index,char **pattern,char **substitution);
|
||||
stringpair *find_subst(char *name,int length);
|
||||
int delete_subst(char *name,int length);
|
||||
void delete_substtable(void);
|
||||
stringlist *insert_sourcefile(char *string);
|
||||
char *get_sourcefile(int index);
|
||||
void delete_sourcefiletable(void);
|
||||
stringlist *insert_docstring(char *string);
|
||||
char *get_docstring(int index);
|
||||
void delete_docstring(int index);
|
||||
void delete_docstringtable(void);
|
||||
stringlist *insert_autolist(const char *string);
|
||||
char *get_autolist(int index);
|
||||
void delete_autolisttable(void);
|
||||
stringlist *insert_dbgfile(const char *filename);
|
||||
stringlist *insert_dbgline(int linenr);
|
||||
stringlist *insert_dbgsymbol(symbol *sym);
|
||||
char *get_dbgstring(int index);
|
||||
void delete_dbgstringtable(void);
|
||||
stringlist *get_dbgstrings();
|
||||
|
||||
/* function prototypes in SCI18N.C */
|
||||
#define MAXCODEPAGE 12
|
||||
SC_FUNC int cp_path(const char *root,const char *directory);
|
||||
SC_FUNC int cp_set(const char *name);
|
||||
SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr);
|
||||
SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
|
||||
SC_FUNC int scan_utf8(FILE *fp,const char *filename);
|
||||
int cp_path(const char *root,const char *directory);
|
||||
int cp_set(const char *name);
|
||||
cell cp_translate(const unsigned char *string,const unsigned char **endptr);
|
||||
cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
|
||||
int scan_utf8(void *fp,const char *filename);
|
||||
|
||||
/* function prototypes in SCSTATE.C */
|
||||
SC_FUNC constvalue *automaton_add(const char *name);
|
||||
SC_FUNC constvalue *automaton_find(const char *name);
|
||||
SC_FUNC constvalue *automaton_findid(int id);
|
||||
SC_FUNC constvalue *state_add(const char *name,int fsa_id);
|
||||
SC_FUNC constvalue *state_find(const char *name,int fsa_id);
|
||||
SC_FUNC constvalue *state_findid(int id);
|
||||
SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid);
|
||||
SC_FUNC int state_addlist(int *list,int count,int fsa_id);
|
||||
SC_FUNC void state_deletetable(void);
|
||||
SC_FUNC int state_getfsa(int listid);
|
||||
SC_FUNC int state_count(int listid);
|
||||
SC_FUNC int state_inlist(int listid,int state);
|
||||
SC_FUNC int state_listitem(int listid,int index);
|
||||
SC_FUNC void state_conflict(symbol *root);
|
||||
SC_FUNC int state_conflict_id(int listid1,int listid2);
|
||||
constvalue *automaton_add(const char *name);
|
||||
constvalue *automaton_find(const char *name);
|
||||
constvalue *automaton_findid(int id);
|
||||
constvalue *state_add(const char *name,int fsa_id);
|
||||
constvalue *state_find(const char *name,int fsa_id);
|
||||
constvalue *state_findid(int id);
|
||||
void state_buildlist(int **list,int *listsize,int *count,int stateid);
|
||||
int state_addlist(int *list,int count,int fsa_id);
|
||||
void state_deletetable(void);
|
||||
int state_getfsa(int listid);
|
||||
int state_count(int listid);
|
||||
int state_inlist(int listid,int state);
|
||||
int state_listitem(int listid,int index);
|
||||
void state_conflict(symbol *root);
|
||||
int state_conflict_id(int listid1,int listid2);
|
||||
|
||||
/* external variables (defined in scvars.c) */
|
||||
#if !defined SC_SKIP_VDECL
|
||||
typedef struct HashTable HashTable;
|
||||
SC_VDECL struct HashTable *sp_Globals;
|
||||
SC_VDECL symbol loctab; /* local symbol table */
|
||||
SC_VDECL symbol glbtab; /* global symbol table */
|
||||
SC_VDECL cell *litq; /* the literal queue */
|
||||
SC_VDECL unsigned char pline[]; /* the line read from the input file */
|
||||
SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */
|
||||
SC_VDECL constvalue tagname_tab;/* tagname table */
|
||||
SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */
|
||||
SC_VDECL constvalue *curlibrary;/* current library */
|
||||
SC_VDECL int pc_addlibtable; /* is the library table added to the AMX file? */
|
||||
SC_VDECL symbol *curfunc; /* pointer to current function */
|
||||
SC_VDECL char *inpfname; /* name of the file currently read from */
|
||||
SC_VDECL char outfname[]; /* intermediate (assembler) file name */
|
||||
SC_VDECL char binfname[]; /* binary file name */
|
||||
SC_VDECL char errfname[]; /* error file name */
|
||||
SC_VDECL char sc_ctrlchar; /* the control character (or escape character) */
|
||||
SC_VDECL char sc_ctrlchar_org;/* the default control character */
|
||||
SC_VDECL int litidx; /* index to literal table */
|
||||
SC_VDECL int litmax; /* current size of the literal table */
|
||||
SC_VDECL int stgidx; /* index to the staging buffer */
|
||||
SC_VDECL int sc_labnum; /* number of (internal) labels */
|
||||
SC_VDECL int staging; /* true if staging output */
|
||||
SC_VDECL cell declared; /* number of local cells declared */
|
||||
SC_VDECL cell glb_declared; /* number of global cells declared */
|
||||
SC_VDECL cell code_idx; /* number of bytes with generated code */
|
||||
SC_VDECL int ntv_funcid; /* incremental number of native function */
|
||||
SC_VDECL int errnum; /* number of errors */
|
||||
SC_VDECL int warnnum; /* number of warnings */
|
||||
SC_VDECL int sc_debug; /* debug/optimization options (bit field) */
|
||||
SC_VDECL int sc_packstr; /* strings are packed by default? */
|
||||
SC_VDECL int sc_asmfile; /* create .ASM file? */
|
||||
SC_VDECL int sc_listing; /* create .LST file? */
|
||||
SC_VDECL int sc_compress; /* compress bytecode? */
|
||||
SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */
|
||||
SC_VDECL int sc_dataalign; /* data alignment value */
|
||||
SC_VDECL int sc_alignnext; /* must frame of the next function be aligned? */
|
||||
SC_VDECL int pc_docexpr; /* must expression be attached to documentation comment? */
|
||||
SC_VDECL int sc_showincludes; /* show include files? */
|
||||
SC_VDECL int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
SC_VDECL cell pc_stksize; /* stack size */
|
||||
SC_VDECL cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
|
||||
SC_VDECL cell pc_amxram; /* abstract machine data size limit */
|
||||
SC_VDECL int freading; /* is there an input file ready for reading? */
|
||||
SC_VDECL int fline; /* the line number in the current file */
|
||||
SC_VDECL short fnumber; /* number of files in the file table (debugging) */
|
||||
SC_VDECL short fcurrent; /* current file being processed (debugging) */
|
||||
SC_VDECL short sc_intest; /* true if inside a test */
|
||||
SC_VDECL int sideeffect; /* true if an expression causes a side-effect */
|
||||
SC_VDECL int stmtindent; /* current indent of the statement */
|
||||
SC_VDECL int indent_nowarn; /* skip warning "217 loose indentation" */
|
||||
SC_VDECL int sc_tabsize; /* number of spaces that a TAB represents */
|
||||
SC_VDECL short sc_allowtags; /* allow/detect tagnames in lex() */
|
||||
SC_VDECL int sc_status; /* read/write status */
|
||||
SC_VDECL int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */
|
||||
SC_VDECL int sc_rationaltag; /* tag for rational numbers */
|
||||
SC_VDECL int rational_digits; /* number of fractional digits */
|
||||
SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */
|
||||
SC_VDECL short sc_is_utf8; /* is this source file in UTF-8 encoding */
|
||||
SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
|
||||
SC_VDECL int sc_curstates; /* ID of the current state list */
|
||||
SC_VDECL int pc_optimize; /* (peephole) optimization level */
|
||||
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
|
||||
SC_VDECL int pc_functag; /* global function tag */
|
||||
SC_VDECL int pc_tag_string; /* global String tag */
|
||||
SC_VDECL int pc_tag_void; /* global void tag */
|
||||
SC_VDECL int pc_tag_object; /* root object tag */
|
||||
SC_VDECL int pc_tag_bool; /* global bool tag */
|
||||
SC_VDECL int pc_tag_null_t; /* the null type */
|
||||
SC_VDECL int pc_tag_nullfunc_t; /* the null function type */
|
||||
SC_VDECL int pc_anytag; /* global any tag */
|
||||
SC_VDECL int glbstringread; /* last global string read */
|
||||
SC_VDECL int sc_require_newdecls; /* only newdecls are allowed */
|
||||
extern struct HashTable *sp_Globals;
|
||||
extern symbol loctab; /* local symbol table */
|
||||
extern symbol glbtab; /* global symbol table */
|
||||
extern cell *litq; /* the literal queue */
|
||||
extern unsigned char pline[]; /* the line read from the input file */
|
||||
extern const unsigned char *lptr;/* points to the current position in "pline" */
|
||||
extern constvalue tagname_tab;/* tagname table */
|
||||
extern constvalue libname_tab;/* library table (#pragma library "..." syntax) */
|
||||
extern constvalue *curlibrary;/* current library */
|
||||
extern int pc_addlibtable; /* is the library table added to the AMX file? */
|
||||
extern symbol *curfunc; /* pointer to current function */
|
||||
extern char *inpfname; /* name of the file currently read from */
|
||||
extern char outfname[]; /* intermediate (assembler) file name */
|
||||
extern char binfname[]; /* binary file name */
|
||||
extern char errfname[]; /* error file name */
|
||||
extern char sc_ctrlchar; /* the control character (or escape character) */
|
||||
extern char sc_ctrlchar_org;/* the default control character */
|
||||
extern int litidx; /* index to literal table */
|
||||
extern int litmax; /* current size of the literal table */
|
||||
extern int stgidx; /* index to the staging buffer */
|
||||
extern int sc_labnum; /* number of (internal) labels */
|
||||
extern int staging; /* true if staging output */
|
||||
extern cell declared; /* number of local cells declared */
|
||||
extern cell glb_declared; /* number of global cells declared */
|
||||
extern cell code_idx; /* number of bytes with generated code */
|
||||
extern int ntv_funcid; /* incremental number of native function */
|
||||
extern int errnum; /* number of errors */
|
||||
extern int warnnum; /* number of warnings */
|
||||
extern int sc_debug; /* debug/optimization options (bit field) */
|
||||
extern int sc_packstr; /* strings are packed by default? */
|
||||
extern int sc_asmfile; /* create .ASM file? */
|
||||
extern int sc_listing; /* create .LST file? */
|
||||
extern int sc_compress; /* compress bytecode? */
|
||||
extern int sc_needsemicolon;/* semicolon required to terminate expressions? */
|
||||
extern int sc_dataalign; /* data alignment value */
|
||||
extern int sc_alignnext; /* must frame of the next function be aligned? */
|
||||
extern int pc_docexpr; /* must expression be attached to documentation comment? */
|
||||
extern int sc_showincludes; /* show include files? */
|
||||
extern int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
extern cell pc_stksize; /* stack size */
|
||||
extern cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
|
||||
extern cell pc_amxram; /* abstract machine data size limit */
|
||||
extern int freading; /* is there an input file ready for reading? */
|
||||
extern int fline; /* the line number in the current file */
|
||||
extern short fnumber; /* number of files in the file table (debugging) */
|
||||
extern short fcurrent; /* current file being processed (debugging) */
|
||||
extern short sc_intest; /* true if inside a test */
|
||||
extern int sideeffect; /* true if an expression causes a side-effect */
|
||||
extern int stmtindent; /* current indent of the statement */
|
||||
extern int indent_nowarn; /* skip warning "217 loose indentation" */
|
||||
extern int sc_tabsize; /* number of spaces that a TAB represents */
|
||||
extern short sc_allowtags; /* allow/detect tagnames in lex() */
|
||||
extern int sc_status; /* read/write status */
|
||||
extern int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */
|
||||
extern int sc_rationaltag; /* tag for rational numbers */
|
||||
extern int rational_digits; /* number of fractional digits */
|
||||
extern int sc_allowproccall;/* allow/detect tagnames in lex() */
|
||||
extern short sc_is_utf8; /* is this source file in UTF-8 encoding */
|
||||
extern char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
|
||||
extern int sc_curstates; /* ID of the current state list */
|
||||
extern int pc_optimize; /* (peephole) optimization level */
|
||||
extern int pc_memflags; /* special flags for the stack/heap usage */
|
||||
extern int pc_functag; /* global function tag */
|
||||
extern int pc_tag_string; /* global String tag */
|
||||
extern int pc_tag_void; /* global void tag */
|
||||
extern int pc_tag_object; /* root object tag */
|
||||
extern int pc_tag_bool; /* global bool tag */
|
||||
extern int pc_tag_null_t; /* the null type */
|
||||
extern int pc_tag_nullfunc_t; /* the null function type */
|
||||
extern int pc_anytag; /* global any tag */
|
||||
extern int glbstringread; /* last global string read */
|
||||
extern int sc_require_newdecls; /* only newdecls are allowed */
|
||||
|
||||
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
||||
SC_VDECL constvalue sc_state_tab; /* state table */
|
||||
extern constvalue sc_automaton_tab; /* automaton table */
|
||||
extern constvalue sc_state_tab; /* state table */
|
||||
|
||||
SC_VDECL FILE *inpf; /* file read from (source or include) */
|
||||
SC_VDECL FILE *inpf_org; /* main source file */
|
||||
SC_VDECL FILE *outf; /* file written to */
|
||||
extern void *inpf; /* file read from (source or include) */
|
||||
extern void *inpf_org; /* main source file */
|
||||
extern void *outf; /* file written to */
|
||||
|
||||
SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */
|
||||
extern jmp_buf errbuf; /* target of longjmp() on a fatal error */
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
SC_VDECL int sc_makereport; /* generate a cross-reference report */
|
||||
extern int sc_makereport; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
||||
#if defined WIN32
|
||||
#if !defined snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
# if !defined snprintf
|
||||
# define snprintf _snprintf
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* SC_SKIP_VDECL */
|
||||
|
@ -193,9 +193,6 @@ char g_tmpfile[_MAX_PATH] = {0};
|
||||
|
||||
/* "main" of the compiler
|
||||
*/
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int pc_compile(int argc, char *argv[])
|
||||
{
|
||||
int entry,i,jmpcode;
|
||||
@ -582,10 +579,7 @@ cleanup:
|
||||
return retcode;
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int pc_addconstant(char *name,cell value,int tag)
|
||||
int pc_addconstant(const char *name,cell value,int tag)
|
||||
{
|
||||
errorset(sFORCESET,0); /* make sure error engine is silenced */
|
||||
sc_status=statIDLE;
|
||||
@ -678,20 +672,19 @@ int pc_findtag(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int pc_addtag(char *name)
|
||||
int pc_addtag(const char *name)
|
||||
{
|
||||
int val;
|
||||
int flags = 0;
|
||||
|
||||
if (name==NULL) {
|
||||
/* no tagname was given, check for one */
|
||||
if (lex(&val,&name)!=tLABEL) {
|
||||
char *nameptr;
|
||||
if (lex(&val,&nameptr)!=tLABEL) {
|
||||
lexpush();
|
||||
return 0; /* untagged */
|
||||
} /* if */
|
||||
name = nameptr;
|
||||
} /* if */
|
||||
|
||||
if (isupper(*name))
|
||||
@ -700,12 +693,12 @@ int pc_addtag(char *name)
|
||||
return pc_addtag_flags(name, flags);
|
||||
}
|
||||
|
||||
int pc_addtag_flags(char *name, int flags)
|
||||
int pc_addtag_flags(const char *name, int flags)
|
||||
{
|
||||
constvalue *ptr;
|
||||
int last,tag;
|
||||
|
||||
assert(strchr(name,':')==NULL); /* colon should already have been stripped */
|
||||
assert((flags & FUNCTAG) || strchr(name,':')==NULL); /* colon should already have been stripped */
|
||||
last=0;
|
||||
ptr=tagname_tab.next;
|
||||
while (ptr!=NULL) {
|
||||
@ -831,7 +824,7 @@ static char *get_extension(char *filename)
|
||||
* Set the default extension, or force an extension. To erase the
|
||||
* extension of a filename, set "extension" to an empty string.
|
||||
*/
|
||||
SC_FUNC void set_extension(char *filename,char *extension,int force)
|
||||
void set_extension(char *filename,const char *extension,int force)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
@ -1362,35 +1355,14 @@ static void setconstants(void)
|
||||
add_constant("false",0,sGLOBAL,1);
|
||||
add_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */
|
||||
add_constant("INVALID_FUNCTION", -1, sGLOBAL, pc_tag_nullfunc_t);
|
||||
#if PAWN_CELL_SIZE==16
|
||||
add_constant("cellbits",16,sGLOBAL,0);
|
||||
#if defined _I16_MAX
|
||||
add_constant("cellmax",_I16_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",_I16_MIN,sGLOBAL,0);
|
||||
#else
|
||||
add_constant("cellmax",SHRT_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",SHRT_MIN,sGLOBAL,0);
|
||||
#endif
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
add_constant("cellbits",32,sGLOBAL,0);
|
||||
#if defined _I32_MAX
|
||||
add_constant("cellmax",_I32_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",_I32_MIN,sGLOBAL,0);
|
||||
#else
|
||||
add_constant("cellmax",LONG_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",LONG_MIN,sGLOBAL,0);
|
||||
#endif
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#if !defined _I64_MIN
|
||||
#define _I64_MIN (-9223372036854775807ULL - 1)
|
||||
#define _I64_MAX 9223372036854775807ULL
|
||||
#endif
|
||||
add_constant("cellbits",64,sGLOBAL,0);
|
||||
add_constant("cellmax",_I64_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",_I64_MIN,sGLOBAL,0);
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
add_constant("cellbits",32,sGLOBAL,0);
|
||||
#if defined _I32_MAX
|
||||
add_constant("cellmax",_I32_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",_I32_MIN,sGLOBAL,0);
|
||||
#else
|
||||
add_constant("cellmax",LONG_MAX,sGLOBAL,0);
|
||||
add_constant("cellmin",LONG_MIN,sGLOBAL,0);
|
||||
#endif
|
||||
add_constant("charbits",sCHARBITS,sGLOBAL,0);
|
||||
add_constant("charmin",0,sGLOBAL,0);
|
||||
add_constant("charmax",~(-1 << sCHARBITS) - 1,sGLOBAL,0);
|
||||
@ -1948,14 +1920,12 @@ static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct)
|
||||
static void declglb(declinfo_t *decl,int fpublic,int fstatic,int fstock)
|
||||
{
|
||||
int ispublic;
|
||||
cell val,cidx;
|
||||
cell cidx;
|
||||
ucell address;
|
||||
int glb_incr;
|
||||
char *str;
|
||||
int slength=0;
|
||||
short filenum;
|
||||
symbol *sym;
|
||||
constvalue *enumroot;
|
||||
#if !defined NDEBUG
|
||||
cell glbdecl=0;
|
||||
#endif
|
||||
@ -2750,8 +2720,11 @@ static cell initvector(int ident,int tag,cell size,int fillzero,
|
||||
} while (matchtoken(',')); /* do */
|
||||
needtoken('}');
|
||||
} else {
|
||||
init(ident,&ctag,errorfound);
|
||||
matchtag(tag,ctag,TRUE);
|
||||
if (!lexpeek('}'))
|
||||
{
|
||||
init(ident,&ctag,errorfound);
|
||||
matchtag(tag,ctag,TRUE);
|
||||
}
|
||||
} /* if */
|
||||
/* fill up the literal queue with a series */
|
||||
if (ellips) {
|
||||
@ -2794,7 +2767,7 @@ static cell init(int ident,int *tag,int *errorfound)
|
||||
litidx=1; /* reset literal queue */
|
||||
} /* if */
|
||||
*tag=pc_tag_string;
|
||||
} else if (constexpr(&i,tag,NULL)){
|
||||
} else if (exprconst(&i,tag,NULL)){
|
||||
litadd(i); /* store expression result in literal table */
|
||||
} else {
|
||||
if (errorfound!=NULL)
|
||||
@ -2819,7 +2792,7 @@ static cell needsub(int *tag,constvalue **enumroot)
|
||||
if (matchtoken(']')) /* we have already seen "[" */
|
||||
return 0; /* zero size (like "char msg[]") */
|
||||
|
||||
constexpr(&val,tag,&sym); /* get value (must be constant expression) */
|
||||
exprconst(&val,tag,&sym); /* get value (must be constant expression) */
|
||||
if (val<0) {
|
||||
error(9); /* negative array size is invalid; assumed zero */
|
||||
val=0;
|
||||
@ -2891,7 +2864,7 @@ static void decl_const(int vclass)
|
||||
|
||||
symbolline=fline; /* save line where symbol was found */
|
||||
needtoken('=');
|
||||
constexpr(&val,&exprtag,NULL); /* get value */
|
||||
exprconst(&val,&exprtag,NULL); /* get value */
|
||||
|
||||
/* add_constant() checks for duplicate definitions */
|
||||
/* temporarily reset the line number to where the symbol was defined */
|
||||
@ -3202,8 +3175,6 @@ static void parse_old_array_dims(declinfo_t *decl, int flags)
|
||||
stgset(FALSE);
|
||||
} else {
|
||||
do {
|
||||
cell size;
|
||||
|
||||
if (type->numdim == sDIMEN_MAX) {
|
||||
error(53);
|
||||
return;
|
||||
@ -3281,7 +3252,7 @@ static int parse_old_decl(declinfo_t *decl, int flags)
|
||||
strcpy(decl->name, "__unknown__");
|
||||
} else {
|
||||
if (!lexpeek(tSYMBOL)) {
|
||||
extern char *sc_tokens[];
|
||||
extern const char *sc_tokens[];
|
||||
switch (lextok(&tok)) {
|
||||
case tOBJECT:
|
||||
case tCHAR:
|
||||
@ -3404,7 +3375,6 @@ static int reparse_new_decl(declinfo_t *decl, int flags)
|
||||
//
|
||||
int parse_decl(declinfo_t *decl, int flags)
|
||||
{
|
||||
token_t tok;
|
||||
token_ident_t ident;
|
||||
|
||||
memset(decl, 0, sizeof(*decl));
|
||||
@ -4059,19 +4029,36 @@ static void domethodmap(LayoutSpec spec)
|
||||
require_newline(TRUE);
|
||||
}
|
||||
|
||||
class AutoStage
|
||||
{
|
||||
public:
|
||||
AutoStage() : lcl_staging_(FALSE)
|
||||
{
|
||||
if (!staging) {
|
||||
stgset(TRUE);
|
||||
lcl_staging_ = TRUE;
|
||||
lcl_stgidx_ = stgidx;
|
||||
assert(stgidx == 0);
|
||||
}
|
||||
}
|
||||
~AutoStage() {
|
||||
if (lcl_staging_) {
|
||||
stgout(lcl_stgidx_);
|
||||
stgset(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int lcl_staging_;
|
||||
int lcl_stgidx_;
|
||||
};
|
||||
|
||||
// delete ::= "delete" expr
|
||||
static void dodelete()
|
||||
{
|
||||
AutoStage staging_on;
|
||||
|
||||
svalue sval;
|
||||
|
||||
int lcl_staging = FALSE;
|
||||
if (!staging) {
|
||||
stgset(TRUE);
|
||||
lcl_staging = TRUE;
|
||||
assert(stgidx == 0);
|
||||
}
|
||||
int lcl_stgidx = stgidx;
|
||||
|
||||
int ident = lvalexpr(&sval);
|
||||
needtoken(tTERM);
|
||||
|
||||
@ -4079,7 +4066,7 @@ static void dodelete()
|
||||
case iFUNCTN:
|
||||
case iREFFUNC:
|
||||
error(115, "functions");
|
||||
goto cleanup;
|
||||
return;
|
||||
|
||||
case iARRAY:
|
||||
case iREFARRAY:
|
||||
@ -4089,7 +4076,7 @@ static void dodelete()
|
||||
symbol *sym = sval.val.sym;
|
||||
if (!sym || sym->dim.array.level > 0) {
|
||||
error(115, "arrays");
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4097,13 +4084,13 @@ static void dodelete()
|
||||
|
||||
if (sval.val.tag == 0) {
|
||||
error(115, "primitive types or enums");
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
|
||||
methodmap_t *map = methodmap_find_by_tag(sval.val.tag);
|
||||
if (!map) {
|
||||
error(115, pc_tagname(sval.val.tag));
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
@ -4119,7 +4106,7 @@ static void dodelete()
|
||||
|
||||
if (!map || !map->dtor) {
|
||||
error(115, layout_spec_name(map->spec), map->name);
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only zap non-const lvalues.
|
||||
@ -4180,12 +4167,6 @@ static void dodelete()
|
||||
}
|
||||
|
||||
markexpr(sEXPR, NULL, 0);
|
||||
|
||||
cleanup:
|
||||
if (lcl_staging) {
|
||||
stgout(lcl_stgidx);
|
||||
stgset(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4201,7 +4182,7 @@ static void parse_function_type(functag_t *type)
|
||||
needtoken(tFUNCTION);
|
||||
|
||||
type->ret_tag = parse_new_typename(NULL);
|
||||
type->type = uPUBLIC;
|
||||
type->usage = uPUBLIC;
|
||||
|
||||
needtoken('(');
|
||||
|
||||
@ -4223,6 +4204,9 @@ static void parse_function_type(functag_t *type)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Account for strings.
|
||||
fix_char_size(&decl);
|
||||
|
||||
funcarg_t *arg = &type->args[type->argcount++];
|
||||
arg->tagcount = 1;
|
||||
arg->tags[0] = decl.type.tag;
|
||||
@ -4367,13 +4351,13 @@ static void dofuncenum(int listmode)
|
||||
* rather than the constant value. And even if we could, we'd have to change the assembler recognize that.
|
||||
*/
|
||||
if (l == tPUBLIC) {
|
||||
func.type = uPUBLIC;
|
||||
func.usage = uPUBLIC;
|
||||
} else {
|
||||
error(1, "-public-", str);
|
||||
}
|
||||
} else {
|
||||
func.ret_tag = newStyleTag;
|
||||
func.type = uPUBLIC;
|
||||
func.usage = uPUBLIC;
|
||||
}
|
||||
needtoken('(');
|
||||
do {
|
||||
@ -4523,11 +4507,11 @@ static void decl_enum(int vclass)
|
||||
multiplier=1;
|
||||
if (matchtoken('(')) {
|
||||
if (matchtoken(taADD)) {
|
||||
constexpr(&increment,NULL,NULL);
|
||||
exprconst(&increment,NULL,NULL);
|
||||
} else if (matchtoken(taMULT)) {
|
||||
constexpr(&multiplier,NULL,NULL);
|
||||
exprconst(&multiplier,NULL,NULL);
|
||||
} else if (matchtoken(taSHL)) {
|
||||
constexpr(&val,NULL,NULL);
|
||||
exprconst(&val,NULL,NULL);
|
||||
while (val-->0)
|
||||
multiplier*=2;
|
||||
} /* if */
|
||||
@ -4568,12 +4552,12 @@ static void decl_enum(int vclass)
|
||||
size=increment; /* default increment of 'val' */
|
||||
fieldtag=0; /* default field tag */
|
||||
if (matchtoken('[')) {
|
||||
constexpr(&size,&fieldtag,NULL); /* get size */
|
||||
exprconst(&size,&fieldtag,NULL); /* get size */
|
||||
needtoken(']');
|
||||
} /* if */
|
||||
/* :TODO: do we need a size modifier here for pc_tag_string? */
|
||||
if (matchtoken('='))
|
||||
constexpr(&value,NULL,NULL); /* get value */
|
||||
exprconst(&value,NULL,NULL); /* get value */
|
||||
/* add_constant() checks whether a variable (global or local) or
|
||||
* a constant with the same name already exists
|
||||
*/
|
||||
@ -4734,7 +4718,7 @@ static int compare_tag(int tag1, int tag2)
|
||||
* Finds a function in the global symbol table or creates a new entry.
|
||||
* It does some basic processing and error checking.
|
||||
*/
|
||||
SC_FUNC symbol *fetchfunc(char *name)
|
||||
symbol *fetchfunc(char *name)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -4963,7 +4947,7 @@ static char *tag2str(char *dest,int tag)
|
||||
return isdigit(dest[1]) ? &dest[1] : dest;
|
||||
}
|
||||
|
||||
SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag)
|
||||
char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag)
|
||||
{
|
||||
char tagstr1[10], tagstr2[10];
|
||||
int opertok;
|
||||
@ -5013,7 +4997,7 @@ constvalue *find_tag_byval(int tag)
|
||||
return tagsym;
|
||||
}
|
||||
|
||||
SC_FUNC char *funcdisplayname(char *dest,char *funcname)
|
||||
char *funcdisplayname(char *dest,char *funcname)
|
||||
{
|
||||
int tags[2];
|
||||
char opname[10];
|
||||
@ -5064,7 +5048,7 @@ static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag)
|
||||
int tok;
|
||||
char *str;
|
||||
cell val,size;
|
||||
symbol *sym,*sub;
|
||||
symbol *sym;
|
||||
int fnative = (tokid == tNATIVE || tokid == tMETHODMAP);
|
||||
int fpublic = (tokid == tPUBLIC);
|
||||
|
||||
@ -5125,7 +5109,7 @@ static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag)
|
||||
tokeninfo(&val,&str);
|
||||
insert_alias(sym->name,str);
|
||||
} else {
|
||||
constexpr(&val,NULL,NULL);
|
||||
exprconst(&val,NULL,NULL);
|
||||
sym->addr=val;
|
||||
/* At the moment, I have assumed that this syntax is only valid if
|
||||
* val < 0. To properly mix "normal" native functions and indexed
|
||||
@ -5172,7 +5156,6 @@ static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstati
|
||||
char *str;
|
||||
cell val,cidx,glbdecl;
|
||||
short filenum;
|
||||
int state_id;
|
||||
|
||||
assert(litidx==0); /* literal queue should be empty */
|
||||
litidx=0; /* clear the literal pool (should already be empty) */
|
||||
@ -5279,7 +5262,7 @@ static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstati
|
||||
} /* if */
|
||||
|
||||
if ((sym->flags & flgDEPRECATED) != 0 && (sym->usage & uSTOCK) == 0) {
|
||||
char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
|
||||
const char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
|
||||
error(234, decl->name, ptr); /* deprecated (probably a public function) */
|
||||
} /* if */
|
||||
begcseg();
|
||||
@ -5443,10 +5426,9 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
|
||||
{
|
||||
char *ptr;
|
||||
int argcnt,oldargcnt,tok;
|
||||
cell val;
|
||||
arginfo arg, *arglist;
|
||||
char name[sNAMEMAX+1];
|
||||
int ident,fpublic;
|
||||
int fpublic;
|
||||
int idx;
|
||||
|
||||
/* if the function is already defined earlier, get the number of arguments
|
||||
@ -5470,7 +5452,7 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
|
||||
memset(argptr, 0, sizeof(*argptr));
|
||||
strcpy(argptr->name, "this");
|
||||
argptr->ident = iVARIABLE;
|
||||
argptr->tags = malloc(sizeof(int));
|
||||
argptr->tags = (int *)malloc(sizeof(int));
|
||||
argptr->tags[0] = *thistag;
|
||||
argptr->numtags = 1;
|
||||
} else {
|
||||
@ -5632,7 +5614,6 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
|
||||
static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, arginfo *arg)
|
||||
{
|
||||
symbol *argsym;
|
||||
constvalue *enumroot;
|
||||
int slength=0;
|
||||
typeinfo_t *type = &decl->type;
|
||||
|
||||
@ -5728,7 +5709,7 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi
|
||||
while (paranthese--)
|
||||
needtoken(')');
|
||||
} else {
|
||||
constexpr(&arg->defvalue.val,&arg->defvalue_tag,NULL);
|
||||
exprconst(&arg->defvalue.val,&arg->defvalue_tag,NULL);
|
||||
assert(type->numtags > 0);
|
||||
matchtag(type->tags[0], arg->defvalue_tag, TRUE);
|
||||
} /* if */
|
||||
@ -5773,11 +5754,12 @@ static int count_referrers(symbol *entry)
|
||||
}
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
static int find_xmltag(char *source,char *xmltag,char *xmlparam,char *xmlvalue,
|
||||
static int find_xmltag(char *source, const char *xmltag, const char *xmlparam, const char *xmlvalue,
|
||||
char **outer_start,int *outer_length,
|
||||
char **inner_start,int *inner_length)
|
||||
const char **inner_start,int *inner_length)
|
||||
{
|
||||
char *ptr,*inner_end;
|
||||
char *ptr;
|
||||
const char *inner_end;
|
||||
int xmltag_len,xmlparam_len,xmlvalue_len;
|
||||
int match;
|
||||
|
||||
@ -6120,7 +6102,8 @@ static void make_report(symbol *root,FILE *log,char *sourcefile)
|
||||
assert(sym->dim.arglist!=NULL);
|
||||
for (arg=0; sym->dim.arglist[arg].ident!=0; arg++) {
|
||||
int dim,paraminfo;
|
||||
char *outer_start,*inner_start;
|
||||
char *outer_start;
|
||||
const char *inner_start;
|
||||
int outer_length,inner_length;
|
||||
if (sym->dim.arglist[arg].ident==iVARARGS)
|
||||
fprintf(log,"\t\t\t<param name=\"...\">\n");
|
||||
@ -6173,10 +6156,9 @@ static void make_report(symbol *root,FILE *log,char *sourcefile)
|
||||
&& find_xmltag(sym->documentation, "param", "name", sym->dim.arglist[arg].name,
|
||||
&outer_start, &outer_length, &inner_start, &inner_length))
|
||||
{
|
||||
char *tail;
|
||||
fprintf(log,"\t\t\t\t%.*s\n",inner_length,inner_start);
|
||||
/* delete from documentation string */
|
||||
tail=outer_start+outer_length;
|
||||
char *tail=outer_start+outer_length;
|
||||
memmove(outer_start,tail,strlen(tail)+1);
|
||||
} /* if */
|
||||
fprintf(log,"\t\t\t</param>\n");
|
||||
@ -6500,7 +6482,7 @@ static constvalue *insert_constval(constvalue *prev,constvalue *next,const char
|
||||
return cur;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index)
|
||||
constvalue *append_constval(constvalue *table,const char *name,cell val,int index)
|
||||
{
|
||||
constvalue *cur,*prev;
|
||||
|
||||
@ -6510,7 +6492,7 @@ SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,
|
||||
return insert_constval(prev,NULL,name,val,index);
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index)
|
||||
constvalue *find_constval(constvalue *table,char *name,int index)
|
||||
{
|
||||
constvalue *ptr = table->next;
|
||||
|
||||
@ -6553,7 +6535,7 @@ static int delete_constval(constvalue *table,char *name)
|
||||
}
|
||||
#endif
|
||||
|
||||
SC_FUNC void delete_consttable(constvalue *table)
|
||||
void delete_consttable(constvalue *table)
|
||||
{
|
||||
constvalue *cur=table->next, *next;
|
||||
|
||||
@ -6569,7 +6551,7 @@ SC_FUNC void delete_consttable(constvalue *table)
|
||||
*
|
||||
* Adds a symbol to the symbol table. Returns NULL on failure.
|
||||
*/
|
||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag)
|
||||
symbol *add_constant(const char *name,cell val,int vclass,int tag)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -6901,9 +6883,9 @@ static int doexpr2(int comma,int chkeffect,int allowarray,int mark_endexpr,
|
||||
return ident;
|
||||
}
|
||||
|
||||
/* constexpr
|
||||
/* exprconst
|
||||
*/
|
||||
SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr)
|
||||
int exprconst(cell *val,int *tag,symbol **symptr)
|
||||
{
|
||||
int ident,index;
|
||||
cell cidx;
|
||||
@ -6978,7 +6960,7 @@ static int test(int label,int parens,int invert)
|
||||
if (endtok!=0)
|
||||
needtoken(endtok);
|
||||
if (ident==iARRAY || ident==iREFARRAY) {
|
||||
char *ptr=(sym->name!=NULL) ? sym->name : "-unknown-";
|
||||
const char *ptr=(sym->name!=NULL) ? sym->name : "-unknown-";
|
||||
error(33,ptr); /* array must be indexed */
|
||||
} /* if */
|
||||
if (ident==iCONSTEXPR) { /* constant expression */
|
||||
@ -7294,7 +7276,7 @@ static void doswitch(void)
|
||||
* parse all expressions until that special token.
|
||||
*/
|
||||
|
||||
constexpr(&val,NULL,NULL);
|
||||
exprconst(&val,NULL,NULL);
|
||||
/* Search the insertion point (the table is kept in sorted order, so
|
||||
* that advanced abstract machines can sift the case table with a
|
||||
* binary search). Check for duplicate case values at the same time.
|
||||
@ -7466,6 +7448,18 @@ static symbol *fetchlab(char *name)
|
||||
return sym;
|
||||
}
|
||||
|
||||
static int is_variadic(symbol *sym)
|
||||
{
|
||||
assert(sym->ident==iFUNCTN);
|
||||
arginfo *arg = sym->dim.arglist;
|
||||
while (arg->ident) {
|
||||
if (arg->ident == iVARARGS)
|
||||
return TRUE;
|
||||
arg++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* doreturn
|
||||
*
|
||||
* Global references: rettype (altered)
|
||||
@ -7574,7 +7568,11 @@ static void doreturn(void)
|
||||
* it stays on the heap for the moment, and it is removed -usually- at
|
||||
* the end of the expression/statement, see expression() in SC3.C)
|
||||
*/
|
||||
address(sub,sALT); /* ALT = destination */
|
||||
if (is_variadic(curfunc)) {
|
||||
load_hidden_arg();
|
||||
} else {
|
||||
address(sub,sALT); /* ALT = destination */
|
||||
}
|
||||
arraysize=calc_arraysize(dim,numdim,0);
|
||||
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
||||
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
||||
@ -7624,7 +7622,7 @@ static void docont(void)
|
||||
jumplabel(ptr[wqLOOP]);
|
||||
}
|
||||
|
||||
SC_FUNC void exporttag(int tag)
|
||||
void exporttag(int tag)
|
||||
{
|
||||
/* find the tag by value in the table, then set the top bit to mark it
|
||||
* "public"
|
@ -47,7 +47,7 @@ static cell litchar(const unsigned char **lptr,int flags);
|
||||
static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int automaton,int *cmptag);
|
||||
|
||||
static void substallpatterns(unsigned char *line,int buffersize);
|
||||
static int match(char *st,int end);
|
||||
static int match(const char *st,int end);
|
||||
static int alpha(char c);
|
||||
|
||||
#define SKIPMODE 1 /* bit field in "#if" stack */
|
||||
@ -86,7 +86,7 @@ static double pow10(double d)
|
||||
static stkitem *stack=NULL;
|
||||
static int stkidx=0,stktop=0;
|
||||
|
||||
SC_FUNC void pushstk(stkitem val)
|
||||
void pushstk(stkitem val)
|
||||
{
|
||||
assert(stkidx<=stktop);
|
||||
if (stkidx==stktop) {
|
||||
@ -109,7 +109,7 @@ SC_FUNC void pushstk(stkitem val)
|
||||
stkidx+=1;
|
||||
}
|
||||
|
||||
SC_FUNC stkitem popstk(void)
|
||||
stkitem popstk(void)
|
||||
{
|
||||
if (stkidx==0) {
|
||||
stkitem s;
|
||||
@ -121,7 +121,7 @@ SC_FUNC stkitem popstk(void)
|
||||
return stack[stkidx];
|
||||
}
|
||||
|
||||
SC_FUNC void clearstk(void)
|
||||
void clearstk(void)
|
||||
{
|
||||
assert(stack!=NULL || stktop==0);
|
||||
if (stack!=NULL) {
|
||||
@ -132,9 +132,10 @@ SC_FUNC void clearstk(void)
|
||||
assert(stktop==0);
|
||||
}
|
||||
|
||||
SC_FUNC int plungequalifiedfile(char *name)
|
||||
int plungequalifiedfile(char *name)
|
||||
{
|
||||
static char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||
static const char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||
|
||||
void *fp;
|
||||
char *ext;
|
||||
int ext_idx;
|
||||
@ -184,7 +185,7 @@ static char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths)
|
||||
int plungefile(char *name,int try_currentpath,int try_includepaths)
|
||||
{
|
||||
int result=FALSE;
|
||||
|
||||
@ -671,11 +672,11 @@ static int ftoi(cell *val,const unsigned char *curptr)
|
||||
exp=(exp*10)+(*ptr-'0');
|
||||
ptr++;
|
||||
} /* while */
|
||||
#if defined __GNUC__
|
||||
fmult=pow10(exp*sign);
|
||||
#else
|
||||
fmult=pow(10,exp*sign);
|
||||
#endif
|
||||
#if defined __GNUC__
|
||||
fmult=pow10(exp*sign);
|
||||
#else
|
||||
fmult=pow(10.0,exp*sign);
|
||||
#endif
|
||||
fnum *= fmult;
|
||||
dnum *= (unsigned long)(fmult+0.5);
|
||||
} /* if */
|
||||
@ -796,7 +797,7 @@ static int preproc_expr(cell *val,int *tag)
|
||||
term=strchr((char*)pline,'\0');
|
||||
assert(term!=NULL);
|
||||
chrcat((char*)pline,PREPROC_TERM); /* the "DEL" code (see SC.H) */
|
||||
result=constexpr(val,tag,NULL); /* get value (or 0 on error) */
|
||||
result=exprconst(val,tag,NULL); /* get value (or 0 on error) */
|
||||
*term='\0'; /* erase the token (if still present) */
|
||||
lexclr(FALSE); /* clear any "pushed" tokens */
|
||||
return result;
|
||||
@ -1251,7 +1252,7 @@ static int command(void)
|
||||
break;
|
||||
default: {
|
||||
char s2[20];
|
||||
extern char *sc_tokens[];/* forward declaration */
|
||||
extern const char *sc_tokens[];/* forward declaration */
|
||||
if (tok<256)
|
||||
sprintf(s2,"%c",(char)tok);
|
||||
else
|
||||
@ -1482,7 +1483,7 @@ static char *strdel(char *str,size_t len)
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *strins(char *dest,char *src,size_t srclen)
|
||||
static char *strins(char *dest,const char *src,size_t srclen)
|
||||
{
|
||||
size_t destlen=strlen(dest);
|
||||
assert(srclen<=strlen(src));
|
||||
@ -1792,7 +1793,7 @@ static int scanellipsis(const unsigned char *lptr)
|
||||
* pline (altered)
|
||||
* freading (referred to only)
|
||||
*/
|
||||
SC_FUNC void preprocess(void)
|
||||
void preprocess(void)
|
||||
{
|
||||
int iscommand;
|
||||
|
||||
@ -1931,7 +1932,7 @@ static full_token_t *next_token()
|
||||
return &sTokenBuffer->tokens[cursor];
|
||||
}
|
||||
|
||||
SC_FUNC void lexinit(void)
|
||||
void lexinit(void)
|
||||
{
|
||||
stkidx=0; /* index for pushstk() and popstk() */
|
||||
iflevel=0; /* preprocessor: nesting of "#if" is currently 0 */
|
||||
@ -1943,7 +1944,7 @@ SC_FUNC void lexinit(void)
|
||||
sTokenBuffer = &sNormalBuffer;
|
||||
}
|
||||
|
||||
char *sc_tokens[] = {
|
||||
const char *sc_tokens[] = {
|
||||
"*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
|
||||
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
||||
"...", "..", "::",
|
||||
@ -2000,10 +2001,9 @@ static void lexpop()
|
||||
sTokenBuffer->cursor = 0;
|
||||
}
|
||||
|
||||
SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
||||
int lex(cell *lexvalue,char **lexsym)
|
||||
{
|
||||
int i,toolong,newline;
|
||||
char **tokptr;
|
||||
const unsigned char *starttoken;
|
||||
|
||||
if (sTokenBuffer->depth > 0) {
|
||||
@ -2054,7 +2054,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
||||
tok->start.col = (int)(lptr - pline);
|
||||
|
||||
i=tFIRST;
|
||||
tokptr=sc_tokens;
|
||||
const char **tokptr=sc_tokens;
|
||||
while (i<=tMIDDLE) { /* match multi-character operators */
|
||||
if (*lptr==**tokptr && match(*tokptr,FALSE)) {
|
||||
tok->id = i;
|
||||
@ -2259,7 +2259,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
||||
* to read and return the information from these variables, rather than
|
||||
* to read in a new token from the input file.
|
||||
*/
|
||||
SC_FUNC void lexpush(void)
|
||||
void lexpush(void)
|
||||
{
|
||||
assert(sTokenBuffer->depth < MAX_TOKEN_DEPTH);
|
||||
sTokenBuffer->depth++;
|
||||
@ -2276,7 +2276,7 @@ SC_FUNC void lexpush(void)
|
||||
* symbol (a not continue with some old one). This is required upon return
|
||||
* from Assembler mode, and in a few cases after detecting an syntax error.
|
||||
*/
|
||||
SC_FUNC void lexclr(int clreol)
|
||||
void lexclr(int clreol)
|
||||
{
|
||||
sTokenBuffer->depth = 0;
|
||||
if (clreol) {
|
||||
@ -2286,7 +2286,7 @@ SC_FUNC void lexclr(int clreol)
|
||||
}
|
||||
|
||||
// Return true if the symbol is ahead, false otherwise.
|
||||
SC_FUNC int lexpeek(int id)
|
||||
int lexpeek(int id)
|
||||
{
|
||||
if (matchtoken(id)) {
|
||||
lexpush();
|
||||
@ -2305,7 +2305,7 @@ SC_FUNC int lexpeek(int id)
|
||||
* (i.e. not present in the source code) should not be pushed back, which is
|
||||
* why it is sometimes important to distinguish the two.
|
||||
*/
|
||||
SC_FUNC int matchtoken(int token)
|
||||
int matchtoken(int token)
|
||||
{
|
||||
cell val;
|
||||
char *str;
|
||||
@ -2338,7 +2338,7 @@ SC_FUNC int matchtoken(int token)
|
||||
*
|
||||
* The token itself is the return value. Normally, this one is already known.
|
||||
*/
|
||||
SC_FUNC int tokeninfo(cell *val,char **str)
|
||||
int tokeninfo(cell *val,char **str)
|
||||
{
|
||||
*val = current_token()->value;
|
||||
*str = current_token()->str;
|
||||
@ -2352,7 +2352,7 @@ SC_FUNC int tokeninfo(cell *val,char **str)
|
||||
* this function returns 1 for "token found" and 2 for "statement termination
|
||||
* token" found; see function matchtoken() for details.
|
||||
*/
|
||||
SC_FUNC int needtoken(int token)
|
||||
int needtoken(int token)
|
||||
{
|
||||
char s1[20],s2[20];
|
||||
int t;
|
||||
@ -2379,7 +2379,7 @@ SC_FUNC int needtoken(int token)
|
||||
|
||||
// If the next token is on the current line, return that token. Otherwise,
|
||||
// return tNEWLINE.
|
||||
SC_FUNC int peek_same_line()
|
||||
int peek_same_line()
|
||||
{
|
||||
// We should not call this without having parsed at least one token.
|
||||
assert(sTokenBuffer->num_tokens > 0);
|
||||
@ -2407,7 +2407,7 @@ SC_FUNC int peek_same_line()
|
||||
return tEOL;
|
||||
}
|
||||
|
||||
SC_FUNC int require_newline(int allow_semi)
|
||||
int require_newline(int allow_semi)
|
||||
{
|
||||
if (allow_semi) {
|
||||
// Semicolon must be on the same line.
|
||||
@ -2440,7 +2440,7 @@ SC_FUNC int require_newline(int allow_semi)
|
||||
*
|
||||
* Global references: lptr (altered)
|
||||
*/
|
||||
static int match(char *st,int end)
|
||||
static int match(const char *st,int end)
|
||||
{
|
||||
int k;
|
||||
const unsigned char *ptr;
|
||||
@ -2482,7 +2482,7 @@ static void chk_grow_litq(void)
|
||||
* Global references: litidx (altered)
|
||||
* litq (altered)
|
||||
*/
|
||||
SC_FUNC void litadd(cell value)
|
||||
void litadd(cell value)
|
||||
{
|
||||
chk_grow_litq();
|
||||
assert(litidx<litmax);
|
||||
@ -2497,7 +2497,7 @@ SC_FUNC void litadd(cell value)
|
||||
* Global references: litidx (altered)
|
||||
* litq (altered)
|
||||
*/
|
||||
SC_FUNC void litinsert(cell value,int pos)
|
||||
void litinsert(cell value,int pos)
|
||||
{
|
||||
chk_grow_litq();
|
||||
assert(litidx<litmax);
|
||||
@ -2632,7 +2632,7 @@ static int alpha(char c)
|
||||
*
|
||||
* Test if character "c" is alphanumeric ("a".."z", "0".."9", "_" or "@")
|
||||
*/
|
||||
SC_FUNC int alphanum(char c)
|
||||
int alphanum(char c)
|
||||
{
|
||||
return (alpha(c) || isdigit(c));
|
||||
}
|
||||
@ -2641,7 +2641,7 @@ SC_FUNC int alphanum(char c)
|
||||
*
|
||||
* Test if character "c" is a hexadecimal digit ("0".."9" or "a".."f").
|
||||
*/
|
||||
SC_FUNC int ishex(char c)
|
||||
int ishex(char c)
|
||||
{
|
||||
return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F');
|
||||
}
|
||||
@ -2717,7 +2717,7 @@ static void free_symbol(symbol *sym)
|
||||
free(sym);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
void delete_symbol(symbol *root,symbol *sym)
|
||||
{
|
||||
symbol *origRoot=root;
|
||||
/* find the symbol and its predecessor
|
||||
@ -2738,7 +2738,7 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
free_symbol(sym);
|
||||
}
|
||||
|
||||
SC_FUNC int get_actual_compound(symbol *sym)
|
||||
int get_actual_compound(symbol *sym)
|
||||
{
|
||||
if (sym->ident == iARRAY || sym->ident == iREFARRAY) {
|
||||
while (sym->parent)
|
||||
@ -2748,7 +2748,7 @@ SC_FUNC int get_actual_compound(symbol *sym)
|
||||
return sym->compound;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions)
|
||||
void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions)
|
||||
{
|
||||
symbol *origRoot=root;
|
||||
symbol *sym,*parent_sym;
|
||||
@ -2908,7 +2908,7 @@ static symbol *find_symbol_child(const symbol *root,const symbol *sym)
|
||||
* bywhom will be the function that uses a variable or that calls
|
||||
* the function.
|
||||
*/
|
||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
|
||||
int refer_symbol(symbol *entry,symbol *bywhom)
|
||||
{
|
||||
int count;
|
||||
|
||||
@ -2950,7 +2950,7 @@ SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC void markusage(symbol *sym,int usage)
|
||||
void markusage(symbol *sym,int usage)
|
||||
{
|
||||
assert(sym!=NULL);
|
||||
sym->usage |= (char)usage;
|
||||
@ -2974,7 +2974,7 @@ SC_FUNC void markusage(symbol *sym,int usage)
|
||||
*
|
||||
* Returns a pointer to the global symbol (if found) or NULL (if not found)
|
||||
*/
|
||||
SC_FUNC symbol *findglb(const char *name,int filter)
|
||||
symbol *findglb(const char *name,int filter)
|
||||
{
|
||||
/* find a symbol with a matching automaton first */
|
||||
symbol *sym=NULL;
|
||||
@ -3010,12 +3010,12 @@ SC_FUNC symbol *findglb(const char *name,int filter)
|
||||
* Returns a pointer to the local symbol (if found) or NULL (if not found).
|
||||
* See add_symbol() how the deepest nesting level is searched first.
|
||||
*/
|
||||
SC_FUNC symbol *findloc(const char *name)
|
||||
symbol *findloc(const char *name)
|
||||
{
|
||||
return find_symbol(&loctab,name,-1,-1,NULL);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *findconst(const char *name,int *cmptag)
|
||||
symbol *findconst(const char *name,int *cmptag)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -3033,7 +3033,7 @@ SC_FUNC symbol *findconst(const char *name,int *cmptag)
|
||||
return sym;
|
||||
}
|
||||
|
||||
SC_FUNC symbol *finddepend(const symbol *parent)
|
||||
symbol *finddepend(const symbol *parent)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -3048,7 +3048,7 @@ SC_FUNC symbol *finddepend(const symbol *parent)
|
||||
* Adds a symbol to the symbol table (either global or local variables,
|
||||
* or global and local constants).
|
||||
*/
|
||||
SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,int usage)
|
||||
symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,int usage)
|
||||
{
|
||||
symbol entry, **refer;
|
||||
|
||||
@ -3083,13 +3083,13 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i
|
||||
return add_symbol(&loctab,&entry,FALSE);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[])
|
||||
{
|
||||
return addvariable2(name,addr,ident,vclass,tag,dim,numdim,idxtag,0);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength)
|
||||
symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength)
|
||||
{
|
||||
typeinfo_t *type = &decl->type;
|
||||
return addvariable2(
|
||||
@ -3105,7 +3105,7 @@ SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength)
|
||||
);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[],int slength)
|
||||
{
|
||||
symbol *sym;
|
||||
@ -3154,7 +3154,7 @@ SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int
|
||||
* Returns te next internal label number. The global variable sc_labnum is
|
||||
* initialized to zero.
|
||||
*/
|
||||
SC_FUNC int getlabel(void)
|
||||
int getlabel(void)
|
||||
{
|
||||
return sc_labnum++;
|
||||
}
|
||||
@ -3164,7 +3164,7 @@ SC_FUNC int getlabel(void)
|
||||
* Converts a number to a hexadecimal string and returns a pointer to that
|
||||
* string. This function is NOT re-entrant.
|
||||
*/
|
||||
SC_FUNC char *itoh(ucell val)
|
||||
char *itoh(ucell val)
|
||||
{
|
||||
static char itohstr[30];
|
||||
char *ptr;
|
||||
@ -3199,13 +3199,13 @@ static char itohstr[30];
|
||||
return itohstr;
|
||||
}
|
||||
|
||||
SC_FUNC int lextok(token_t *tok)
|
||||
int lextok(token_t *tok)
|
||||
{
|
||||
tok->id = lex(&tok->val, &tok->str);
|
||||
return tok->id;
|
||||
}
|
||||
|
||||
SC_FUNC int expecttoken(int id, token_t *tok)
|
||||
int expecttoken(int id, token_t *tok)
|
||||
{
|
||||
int rval = needtoken(id);
|
||||
if (rval) {
|
||||
@ -3217,7 +3217,7 @@ SC_FUNC int expecttoken(int id, token_t *tok)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int matchtoken2(int id, token_t *tok)
|
||||
int matchtoken2(int id, token_t *tok)
|
||||
{
|
||||
if (matchtoken(id)) {
|
||||
tok->id = tokeninfo(&tok->val, &tok->str);
|
||||
@ -3226,7 +3226,7 @@ SC_FUNC int matchtoken2(int id, token_t *tok)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int matchsymbol(token_ident_t *ident)
|
||||
int matchsymbol(token_ident_t *ident)
|
||||
{
|
||||
if (lextok(&ident->tok) != tSYMBOL) {
|
||||
lexpush();
|
||||
@ -3237,7 +3237,7 @@ SC_FUNC int matchsymbol(token_ident_t *ident)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC int needsymbol(token_ident_t *ident)
|
||||
int needsymbol(token_ident_t *ident)
|
||||
{
|
||||
if (!expecttoken(tSYMBOL, &ident->tok))
|
||||
return FALSE;
|
@ -35,7 +35,7 @@ static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
|
||||
int (*hier)(value*),value *lval);
|
||||
static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval);
|
||||
static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
|
||||
char *forcetag,int chkbitwise);
|
||||
const char *forcetag,int chkbitwise);
|
||||
static int plnge1(int (*hier)(value *lval),value *lval);
|
||||
static void plnge2(void (*oper)(void),
|
||||
int (*hier)(value *lval),
|
||||
@ -113,16 +113,20 @@ static int nextop(int *opidx,int *list)
|
||||
return FALSE; /* entire list scanned, nothing found */
|
||||
}
|
||||
|
||||
SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
value *lval,int *resulttag)
|
||||
{
|
||||
static char *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "",
|
||||
"", "", "", "<=", ">=", "<", ">", "==", "!=" };
|
||||
static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
TRUE, TRUE, TRUE, TRUE, FALSE, FALSE };
|
||||
static char *unoperstr[] = { "!", "-", "++", "--" };
|
||||
static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
|
||||
static const char *binoperstr[] = {
|
||||
"*", "/", "%", "+", "-", "", "", "",
|
||||
"", "", "", "<=", ">=", "<", ">", "==", "!="
|
||||
};
|
||||
static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
TRUE, TRUE, TRUE, TRUE, FALSE, FALSE
|
||||
};
|
||||
static const char *unoperstr[] = { "!", "-", "++", "--" };
|
||||
static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
|
||||
|
||||
char opername[4] = "", symbolname[sNAMEMAX+1];
|
||||
int i,swapparams,savepri,savealt;
|
||||
int paramspassed;
|
||||
@ -286,7 +290,7 @@ static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
|
||||
int checktags_string(int tags[], int numtags, value *sym1)
|
||||
{
|
||||
int i;
|
||||
if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
|
||||
@ -301,7 +305,7 @@ SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int checktag_string(value *sym1, value *sym2)
|
||||
int checktag_string(value *sym1, value *sym2)
|
||||
{
|
||||
if (sym1->ident == iARRAY || sym2->ident == iARRAY ||
|
||||
sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
|
||||
@ -317,7 +321,7 @@ SC_FUNC int checktag_string(value *sym1, value *sym2)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC const char *type_to_name(int tag)
|
||||
const char *type_to_name(int tag)
|
||||
{
|
||||
if (tag == 0)
|
||||
return "int";
|
||||
@ -335,7 +339,7 @@ SC_FUNC const char *type_to_name(int tag)
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
SC_FUNC int matchtag_string(int ident, int tag)
|
||||
int matchtag_string(int ident, int tag)
|
||||
{
|
||||
if (ident == iARRAY || ident == iREFARRAY)
|
||||
return FALSE;
|
||||
@ -413,15 +417,81 @@ static int matchobjecttags(int formaltag, int actualtag, int flags)
|
||||
return obj_typeerror(133, formaltag, actualtag);
|
||||
}
|
||||
|
||||
static int matchreturntag(functag_t *t, symbol *sym)
|
||||
static int matchreturntag(const functag_t *formal, const functag_t *actual)
|
||||
{
|
||||
if (t->ret_tag == sym->tag)
|
||||
return TRUE;
|
||||
if (t->ret_tag == pc_tag_void && (sym->tag == 0 && !(sym->usage & uRETVALUE)))
|
||||
if (formal->ret_tag == actual->ret_tag)
|
||||
return TRUE;
|
||||
if (formal->ret_tag == pc_tag_void) {
|
||||
if (actual->ret_tag == 0 && !(actual->usage & uRETVALUE))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int funcarg_compare(const funcarg_t *formal, const funcarg_t *actual)
|
||||
{
|
||||
// Check type.
|
||||
if (actual->ident != formal->ident)
|
||||
return FALSE;
|
||||
|
||||
// Check rank.
|
||||
if (actual->dimcount != formal->dimcount)
|
||||
return FALSE;
|
||||
|
||||
// Check arity.
|
||||
for (int i = 0; i < formal->dimcount; i++) {
|
||||
if (actual->dims[i] != formal->dims[i])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check tags.
|
||||
if (actual->tagcount != formal->tagcount)
|
||||
return FALSE;
|
||||
for (int i = 0; i < formal->tagcount; i++) {
|
||||
// Note we invert the order we pass things to matchtag() here. If the
|
||||
// typedef specifies base type X, and the function specifies derived
|
||||
// type Y, we want this to type since such an assignment is valid.
|
||||
//
|
||||
// Most programming languages do not subtype arguments like this. We do
|
||||
// it in SourcePawn to preserve compatibility during the Transitional
|
||||
// Syntax effort.
|
||||
int actual_tag = actual->tags[i];
|
||||
int formal_tag = formal->tags[i];
|
||||
if (!matchtag(actual_tag, formal_tag, MATCHTAG_SILENT|MATCHTAG_COERCE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int functag_compare(const functag_t *formal, const functag_t *actual)
|
||||
{
|
||||
// Check return types.
|
||||
if (!matchreturntag(formal, actual))
|
||||
return FALSE;
|
||||
|
||||
// Make sure there are no trailing arguments.
|
||||
if (actual->argcount > formal->argcount)
|
||||
return FALSE;
|
||||
|
||||
// Check arguments.
|
||||
for (int i = 0; i < formal->argcount; i++) {
|
||||
const funcarg_t *formal_arg = &formal->args[i];
|
||||
|
||||
if (i >= actual->argcount) {
|
||||
if (formal_arg->ommittable)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const funcarg_t *actual_arg = &actual->args[i];
|
||||
if (!funcarg_compare(formal_arg, actual_arg))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int matchfunctags(int formaltag, int actualtag)
|
||||
{
|
||||
if (formaltag == pc_functag && (actualtag & FUNCTAG))
|
||||
@ -433,141 +503,23 @@ static int matchfunctags(int formaltag, int actualtag)
|
||||
if (!(actualtag & FUNCTAG))
|
||||
return FALSE;
|
||||
|
||||
constvalue *v = find_tag_byval(actualtag);
|
||||
int index;
|
||||
short usage = uPUBLIC;
|
||||
symbol *sym, *found = NULL;
|
||||
funcenum_t *e;
|
||||
functag_t *t;
|
||||
|
||||
if (strncmp(v->name, "$Func", 5) != 0)
|
||||
functag_t *actual = functag_find_intrinsic(actualtag);
|
||||
if (!actual)
|
||||
return FALSE;
|
||||
|
||||
/* Now we have to go about looking up each function in this enum. WHICH IS IT. */
|
||||
e = funcenums_find_byval(formaltag);
|
||||
funcenum_t *e = funcenums_find_by_tag(formaltag);
|
||||
if (!e)
|
||||
return FALSE;
|
||||
|
||||
assert(v->name[5] == '@' || v->name[5] == '!');
|
||||
|
||||
/* Deduce which function type this is */
|
||||
if (v->name[5] == '@')
|
||||
{
|
||||
usage = uPUBLIC;
|
||||
} else if (v->name[5] == '!') {
|
||||
usage = uSTOCK;
|
||||
}
|
||||
|
||||
index = atoi(&v->name[6]);
|
||||
|
||||
assert(index >= 0);
|
||||
|
||||
/* Find the function, either by public idx or code addr */
|
||||
if (usage == uPUBLIC) {
|
||||
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||
if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL)) {
|
||||
if (index-- == 0) {
|
||||
found = sym;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (usage == uSTOCK) {
|
||||
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||
if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL)) {
|
||||
if (sym->codeaddr == index) {
|
||||
found = sym;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
assert(found);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Wow, we now have:
|
||||
* 1) The functional enum deduced from formaltag
|
||||
* 2) The function trying to be shoved in deduced from actualtag
|
||||
* Now we have to check if it matches any one of the functags inside the enum.
|
||||
*/
|
||||
t = e->first;
|
||||
while (t) {
|
||||
int curarg,skip=0,i;
|
||||
arginfo *func_arg;
|
||||
funcarg_t *enum_arg;
|
||||
/* Check return type first. */
|
||||
if (!matchreturntag(t, sym)) {
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
/* Check usage */
|
||||
if (t->type != usage) {
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
/* Begin iterating arguments */
|
||||
for (curarg=0; curarg<t->argcount; curarg++) {
|
||||
enum_arg = &t->args[curarg];
|
||||
/* Check whether we've exhausted our arguments */
|
||||
if (sym->dim.arglist[curarg].ident == 0) {
|
||||
/* Can we bail out early? */
|
||||
if (!enum_arg->ommittable) {
|
||||
/* No! */
|
||||
skip = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
func_arg = &sym->dim.arglist[curarg];
|
||||
/* First check the ident type */
|
||||
if (enum_arg->ident != func_arg->ident) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
/* Next check arrayness */
|
||||
if (enum_arg->dimcount != func_arg->numdim) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
if (enum_arg->dimcount > 0) {
|
||||
for (i=0; i<enum_arg->dimcount; i++) {
|
||||
if (enum_arg->dims[i] != func_arg->dim[i]) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
break;
|
||||
}
|
||||
/* Lastly, check the tags */
|
||||
if (enum_arg->tagcount != func_arg->numtags) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
/* They should all be in the same order just for clarity... */
|
||||
for (i=0; i<enum_arg->tagcount; i++) {
|
||||
if (!matchtag(func_arg->tags[i], enum_arg->tags[i], MATCHTAG_SILENT|MATCHTAG_COERCE)) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
break;
|
||||
}
|
||||
if (!skip) {
|
||||
/* Make sure there are no trailing arguments */
|
||||
if (sym->dim.arglist[curarg].ident == 0)
|
||||
return TRUE;
|
||||
}
|
||||
t = t->next;
|
||||
for (functag_t *formal = e->first; formal; formal = formal->next) {
|
||||
if (functag_compare(formal, actual))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int matchtag(int formaltag, int actualtag, int flags)
|
||||
int matchtag(int formaltag, int actualtag, int flags)
|
||||
{
|
||||
if (formaltag == actualtag)
|
||||
return TRUE;
|
||||
@ -771,7 +723,7 @@ static void checkfunction(value *lval)
|
||||
* Plunge to a lower level
|
||||
*/
|
||||
static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
|
||||
char *forcetag,int chkbitwise)
|
||||
const char *forcetag,int chkbitwise)
|
||||
{
|
||||
int lvalue,opidx;
|
||||
int count;
|
||||
@ -914,10 +866,10 @@ static void plnge2(void (*oper)(void),
|
||||
checkfunction(lval1);
|
||||
checkfunction(lval2);
|
||||
if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
|
||||
char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
|
||||
const char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
|
||||
error(33,ptr); /* array must be indexed */
|
||||
} else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) {
|
||||
char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-";
|
||||
const char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-";
|
||||
error(33,ptr); /* array must be indexed */
|
||||
} /* if */
|
||||
/* ??? ^^^ should do same kind of error checking with functions */
|
||||
@ -1006,7 +958,7 @@ static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SC_FUNC int lvalexpr(svalue *sval)
|
||||
int lvalexpr(svalue *sval)
|
||||
{
|
||||
memset(sval, 0, sizeof(*sval));
|
||||
|
||||
@ -1019,7 +971,7 @@ SC_FUNC int lvalexpr(svalue *sval)
|
||||
return sval->val.ident;
|
||||
}
|
||||
|
||||
SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval)
|
||||
int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval)
|
||||
{
|
||||
value lval={0};
|
||||
pushheaplist();
|
||||
@ -1042,7 +994,7 @@ SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,valu
|
||||
return lval.ident;
|
||||
}
|
||||
|
||||
SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
||||
int sc_getstateid(constvalue **automaton,constvalue **state)
|
||||
{
|
||||
char name[sNAMEMAX+1];
|
||||
cell val;
|
||||
@ -1085,7 +1037,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
||||
assert(*automaton!=NULL);
|
||||
*state=state_find(name,fsa);
|
||||
if (*state==NULL) {
|
||||
char *fsaname=(*automaton)->name;
|
||||
const char *fsaname=(*automaton)->name;
|
||||
if (*fsaname=='\0')
|
||||
fsaname="<main>";
|
||||
error(87,name,fsaname); /* unknown state for automaton */
|
||||
@ -1095,7 +1047,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
|
||||
return 1;
|
||||
}
|
||||
|
||||
SC_FUNC cell array_totalsize(symbol *sym)
|
||||
cell array_totalsize(symbol *sym)
|
||||
{
|
||||
cell length;
|
||||
|
||||
@ -2281,48 +2233,36 @@ restart:
|
||||
} /* if */
|
||||
if (sym!=NULL && lval1->ident==iFUNCTN) {
|
||||
assert(sym->ident==iFUNCTN);
|
||||
if (sc_allowproccall) {
|
||||
// Note: this is unreachable in SourceMod, we don't support paren-less calls.
|
||||
callfunction(sym,NULL,lval1,FALSE);
|
||||
} else if ((sym->usage & uNATIVE) != uNATIVE) {
|
||||
symbol *oldsym=sym;
|
||||
int n=-1,iter=0;
|
||||
int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0;
|
||||
cell code_addr=0;
|
||||
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||
if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage)))
|
||||
{
|
||||
if (strcmp(sym->name, lval1->sym->name)==0) {
|
||||
n = iter;
|
||||
code_addr = sym->codeaddr;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
if (n!=-1) {
|
||||
char faketag[sNAMEMAX+1];
|
||||
lval1->sym=NULL;
|
||||
lval1->ident=iCONSTEXPR;
|
||||
/* Generate a quick pseudo-tag! */
|
||||
if (usage == uPUBLIC) {
|
||||
lval1->constval=(n<<1)|1;
|
||||
snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n);
|
||||
} else {
|
||||
lval1->constval=(code_addr<<1)|0;
|
||||
snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr);
|
||||
error(153);
|
||||
}
|
||||
lval1->tag=pc_addtag_flags(faketag, FIXEDTAG|FUNCTAG);
|
||||
oldsym->usage |= uREAD;
|
||||
sym->usage |= uREAD;
|
||||
} else {
|
||||
error(76); /* invalid function call, or syntax error */
|
||||
} /* if */
|
||||
|
||||
if (sym->usage & uNATIVE) {
|
||||
error(76);
|
||||
return FALSE;
|
||||
} else {
|
||||
error(76); /* invalid function call, or syntax error */
|
||||
}
|
||||
|
||||
int public_index = 0;
|
||||
symbol *target = NULL;
|
||||
for (symbol *iter = glbtab.next; iter; iter = iter->next) {
|
||||
if (iter->ident != iFUNCTN || iter->vclass != sGLOBAL)
|
||||
continue;
|
||||
if (strcmp(iter->name, lval1->sym->name) == 0) {
|
||||
target = iter;
|
||||
break;
|
||||
}
|
||||
if (iter->usage & uPUBLIC)
|
||||
public_index++;
|
||||
}
|
||||
|
||||
if (!target || !(target->usage & uPUBLIC)) {
|
||||
error(76);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
funcenum_t *fe = funcenum_for_symbol(target);
|
||||
lval1->sym = NULL;
|
||||
lval1->ident = iCONSTEXPR;
|
||||
lval1->constval = (public_index << 1) | 1;
|
||||
lval1->tag = fe->tag;
|
||||
target->usage |= uREAD;
|
||||
} /* if */
|
||||
return lvalue;
|
||||
}
|
||||
@ -2590,7 +2530,7 @@ static int nesting=0;
|
||||
sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */
|
||||
|
||||
if ((sym->flags & flgDEPRECATED)!=0) {
|
||||
char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
|
||||
const char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
|
||||
error(234,sym->name,ptr); /* deprecated (probably a native function) */
|
||||
} /* if */
|
||||
|
||||
@ -2621,10 +2561,9 @@ static int nesting=0;
|
||||
do {
|
||||
if (!pending_this && matchtoken('.')) {
|
||||
namedparams=TRUE;
|
||||
if (needtoken(tSYMBOL))
|
||||
tokeninfo(&lexval,&lexstr);
|
||||
else
|
||||
lexstr="";
|
||||
if (!needtoken(tSYMBOL))
|
||||
break;
|
||||
tokeninfo(&lexval,&lexstr);
|
||||
argpos=findnamedarg(arg,lexstr);
|
||||
if (argpos<0) {
|
||||
error(17,lexstr); /* undefined symbol */
|
@ -34,13 +34,14 @@
|
||||
|
||||
static int fcurseg; /* the file number (fcurrent) for the active segment */
|
||||
|
||||
void load_i();
|
||||
|
||||
/* When a subroutine returns to address 0, the AMX must halt. In earlier
|
||||
* releases, the RET and RETN opcodes checked for the special case 0 address.
|
||||
* Today, the compiler simply generates a HALT instruction at address 0. So
|
||||
* a subroutine can savely return to 0, and then encounter a HALT.
|
||||
*/
|
||||
SC_FUNC void writeleader(symbol *root)
|
||||
void writeleader(symbol *root)
|
||||
{
|
||||
int lbl_nostate,lbl_table;
|
||||
int statecount;
|
||||
@ -174,7 +175,7 @@ SC_FUNC void writeleader(symbol *root)
|
||||
* code_idx (altered)
|
||||
* glb_declared (altered)
|
||||
*/
|
||||
SC_FUNC void writetrailer(void)
|
||||
void writetrailer(void)
|
||||
{
|
||||
assert(sc_dataalign % opcodes(1) == 0); /* alignment must be a multiple of
|
||||
* the opcode size */
|
||||
@ -214,7 +215,7 @@ SC_FUNC void writetrailer(void)
|
||||
* Global references: curseg
|
||||
* fcurrent
|
||||
*/
|
||||
SC_FUNC void begcseg(void)
|
||||
void begcseg(void)
|
||||
{
|
||||
if (sc_status!=statSKIP && (curseg!=sIN_CSEG || fcurrent!=fcurseg)) {
|
||||
stgwrite("\n");
|
||||
@ -232,7 +233,7 @@ SC_FUNC void begcseg(void)
|
||||
*
|
||||
* Global references: curseg
|
||||
*/
|
||||
SC_FUNC void begdseg(void)
|
||||
void begdseg(void)
|
||||
{
|
||||
if (sc_status!=statSKIP && (curseg!=sIN_DSEG || fcurrent!=fcurseg)) {
|
||||
stgwrite("\n");
|
||||
@ -245,7 +246,7 @@ SC_FUNC void begdseg(void)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC void setline(int chkbounds)
|
||||
void setline(int chkbounds)
|
||||
{
|
||||
if (sc_asmfile) {
|
||||
stgwrite("\t; line ");
|
||||
@ -262,7 +263,7 @@ SC_FUNC void setline(int chkbounds)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC void setfiledirect(char *name)
|
||||
void setfiledirect(char *name)
|
||||
{
|
||||
if (sc_status==statFIRST && sc_listing) {
|
||||
assert(name!=NULL);
|
||||
@ -272,7 +273,7 @@ SC_FUNC void setfiledirect(char *name)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC void setlinedirect(int line)
|
||||
void setlinedirect(int line)
|
||||
{
|
||||
if (sc_status==statFIRST && sc_listing) {
|
||||
char string[40];
|
||||
@ -285,7 +286,7 @@ SC_FUNC void setlinedirect(int line)
|
||||
*
|
||||
* Post a code label (specified as a number), on a new line.
|
||||
*/
|
||||
SC_FUNC void setlabel(int number)
|
||||
void setlabel(int number)
|
||||
{
|
||||
assert(number>=0);
|
||||
stgwrite("l.");
|
||||
@ -306,7 +307,7 @@ SC_FUNC void setlabel(int number)
|
||||
* statement. This allows several simple optimizations by the peephole
|
||||
* optimizer.
|
||||
*/
|
||||
SC_FUNC void markexpr(optmark type,const char *name,cell offset)
|
||||
void markexpr(optmark type,const char *name,cell offset)
|
||||
{
|
||||
switch (type) {
|
||||
case sEXPR:
|
||||
@ -331,7 +332,7 @@ SC_FUNC void markexpr(optmark type,const char *name,cell offset)
|
||||
*
|
||||
* Global references: funcstatus (referred to only)
|
||||
*/
|
||||
SC_FUNC void startfunc(char *fname)
|
||||
void startfunc(char *fname)
|
||||
{
|
||||
stgwrite("\tproc");
|
||||
if (sc_asmfile) {
|
||||
@ -348,7 +349,7 @@ SC_FUNC void startfunc(char *fname)
|
||||
*
|
||||
* Declare a CODE ending point (function end)
|
||||
*/
|
||||
SC_FUNC void endfunc(void)
|
||||
void endfunc(void)
|
||||
{
|
||||
stgwrite("\n"); /* skip a line */
|
||||
}
|
||||
@ -360,7 +361,7 @@ SC_FUNC void endfunc(void)
|
||||
* be a power of 2, and this alignment must be done right after the frame
|
||||
* is set up (before the first variable is declared)
|
||||
*/
|
||||
SC_FUNC void alignframe(int numbytes)
|
||||
void alignframe(int numbytes)
|
||||
{
|
||||
#if !defined NDEBUG
|
||||
/* "numbytes" should be a power of 2 for this code to work */
|
||||
@ -384,15 +385,14 @@ SC_FUNC void alignframe(int numbytes)
|
||||
*
|
||||
* Generate code to get the value of a symbol into "primary".
|
||||
*/
|
||||
SC_FUNC void rvalue(value *lval)
|
||||
void rvalue(value *lval)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
sym=lval->sym;
|
||||
if (lval->ident==iARRAYCELL) {
|
||||
/* indirect fetch, address already in PRI */
|
||||
stgwrite("\tload.i\n");
|
||||
code_idx+=opcodes(1);
|
||||
load_i();
|
||||
} else if (lval->ident==iARRAYCHAR) {
|
||||
/* indirect fetch of a character from a pack, address already in PRI */
|
||||
stgwrite("\tlodb.i ");
|
||||
@ -429,7 +429,7 @@ SC_FUNC void rvalue(value *lval)
|
||||
/* Get the address of a symbol into the primary or alternate register (used
|
||||
* for arrays, and for passing arguments by reference).
|
||||
*/
|
||||
SC_FUNC void address(symbol *sym,regid reg)
|
||||
void address(symbol *sym,regid reg)
|
||||
{
|
||||
assert(sym!=NULL);
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
@ -469,12 +469,71 @@ SC_FUNC void address(symbol *sym,regid reg)
|
||||
code_idx+=opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
static void addr_reg(int val, regid reg)
|
||||
{
|
||||
if (reg == sPRI)
|
||||
stgwrite("\taddr.pri ");
|
||||
else
|
||||
stgwrite("\taddr.alt ");
|
||||
outval(val, TRUE);
|
||||
code_idx += opcodes(1) + opargs(1);
|
||||
}
|
||||
|
||||
// Load the number of arguments into PRI. Frame layout:
|
||||
// base + 0*sizeof(cell) == previous "base"
|
||||
// base + 1*sizeof(cell) == function return address
|
||||
// base + 2*sizeof(cell) == number of arguments
|
||||
// base + 3*sizeof(cell) == first argument of the function
|
||||
static void load_argcount(regid reg)
|
||||
{
|
||||
if (reg == sPRI)
|
||||
stgwrite("\tload.s.pri ");
|
||||
else
|
||||
stgwrite("\tload.s.alt ");
|
||||
outval(2 * sizeof(cell), TRUE);
|
||||
code_idx += opcodes(1) + opargs(1);
|
||||
}
|
||||
|
||||
// PRI = ALT + (PRI * cellsize)
|
||||
void idxaddr()
|
||||
{
|
||||
stgwrite("\tidxaddr\n");
|
||||
code_idx += opcodes(1);
|
||||
}
|
||||
|
||||
void load_i()
|
||||
{
|
||||
stgwrite("\tload.i\n");
|
||||
code_idx+=opcodes(1);
|
||||
}
|
||||
|
||||
// Load the hidden array argument into ALT.
|
||||
void load_hidden_arg()
|
||||
{
|
||||
pushreg(sPRI);
|
||||
|
||||
// Compute an address to the first argument, then add the argument count
|
||||
// to find the address after the final argument:
|
||||
// addr.alt 0xc ; Compute &first_arg
|
||||
// load.s.alt 0x8 ; Load arg count
|
||||
// idxaddr ; Compute (&first_arg) + argcount
|
||||
// load.i ; Load *(&first_arg + argcount)
|
||||
// move.alt ; Move result into ALT.
|
||||
addr_reg(0xc, sALT);
|
||||
load_argcount(sPRI);
|
||||
idxaddr();
|
||||
load_i();
|
||||
move_alt();
|
||||
|
||||
popreg(sPRI);
|
||||
}
|
||||
|
||||
/* store
|
||||
*
|
||||
* Saves the contents of "primary" into a memory cell, either directly
|
||||
* or indirectly (at the address given in the alternate register).
|
||||
*/
|
||||
SC_FUNC void store(value *lval)
|
||||
void store(value *lval)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -511,7 +570,7 @@ SC_FUNC void store(value *lval)
|
||||
}
|
||||
|
||||
/* Get a cell from a fixed address in memory */
|
||||
SC_FUNC void loadreg(cell address,regid reg)
|
||||
void loadreg(cell address,regid reg)
|
||||
{
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
if (reg==sPRI)
|
||||
@ -523,7 +582,7 @@ SC_FUNC void loadreg(cell address,regid reg)
|
||||
}
|
||||
|
||||
/* Store a cell into a fixed address in memory */
|
||||
SC_FUNC void storereg(cell address,regid reg)
|
||||
void storereg(cell address,regid reg)
|
||||
{
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
if (reg==sPRI)
|
||||
@ -537,7 +596,7 @@ SC_FUNC void storereg(cell address,regid reg)
|
||||
/* source must in PRI, destination address in ALT. The "size"
|
||||
* parameter is in bytes, not cells.
|
||||
*/
|
||||
SC_FUNC void memcopy(cell size)
|
||||
void memcopy(cell size)
|
||||
{
|
||||
stgwrite("\tmovs ");
|
||||
outval(size,TRUE);
|
||||
@ -548,7 +607,7 @@ SC_FUNC void memcopy(cell size)
|
||||
/* Address of the source must already have been loaded in PRI
|
||||
* "size" is the size in bytes (not cells).
|
||||
*/
|
||||
SC_FUNC void copyarray(symbol *sym,cell size)
|
||||
void copyarray(symbol *sym,cell size)
|
||||
{
|
||||
assert(sym!=NULL);
|
||||
/* the symbol can be a local array, a global array, or an array
|
||||
@ -572,7 +631,7 @@ SC_FUNC void copyarray(symbol *sym,cell size)
|
||||
memcopy(size);
|
||||
}
|
||||
|
||||
SC_FUNC void fillarray(symbol *sym,cell size,cell value)
|
||||
void fillarray(symbol *sym,cell size,cell value)
|
||||
{
|
||||
ldconst(value,sPRI); /* load value in PRI */
|
||||
|
||||
@ -601,7 +660,7 @@ SC_FUNC void fillarray(symbol *sym,cell size,cell value)
|
||||
code_idx+=opcodes(2)+opargs(2);
|
||||
}
|
||||
|
||||
SC_FUNC void stradjust(regid reg)
|
||||
void stradjust(regid reg)
|
||||
{
|
||||
assert(reg==sPRI);
|
||||
stgwrite("\tstradjust.pri\n");
|
||||
@ -611,7 +670,7 @@ SC_FUNC void stradjust(regid reg)
|
||||
/* Instruction to get an immediate value into the primary or the alternate
|
||||
* register
|
||||
*/
|
||||
SC_FUNC void ldconst(cell val,regid reg)
|
||||
void ldconst(cell val,regid reg)
|
||||
{
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
switch (reg) {
|
||||
@ -639,13 +698,13 @@ SC_FUNC void ldconst(cell val,regid reg)
|
||||
}
|
||||
|
||||
/* Copy value in alternate register to the primary register */
|
||||
SC_FUNC void moveto1(void)
|
||||
void moveto1(void)
|
||||
{
|
||||
stgwrite("\tmove.pri\n");
|
||||
code_idx+=opcodes(1)+opargs(0);
|
||||
}
|
||||
|
||||
SC_FUNC void move_alt(void)
|
||||
void move_alt(void)
|
||||
{
|
||||
stgwrite("\tmove.alt\n");
|
||||
code_idx+=opcodes(1)+opargs(0);
|
||||
@ -653,7 +712,7 @@ SC_FUNC void move_alt(void)
|
||||
|
||||
/* Push primary or the alternate register onto the stack
|
||||
*/
|
||||
SC_FUNC void pushreg(regid reg)
|
||||
void pushreg(regid reg)
|
||||
{
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
switch (reg) {
|
||||
@ -670,7 +729,7 @@ SC_FUNC void pushreg(regid reg)
|
||||
/*
|
||||
* Push a constant value onto the stack
|
||||
*/
|
||||
SC_FUNC void pushval(cell val)
|
||||
void pushval(cell val)
|
||||
{
|
||||
stgwrite("\tpush.c ");
|
||||
outval(val, TRUE);
|
||||
@ -679,7 +738,7 @@ SC_FUNC void pushval(cell val)
|
||||
|
||||
/* Pop stack into the primary or the alternate register
|
||||
*/
|
||||
SC_FUNC void popreg(regid reg)
|
||||
void popreg(regid reg)
|
||||
{
|
||||
assert(reg==sPRI || reg==sALT);
|
||||
switch (reg) {
|
||||
@ -696,7 +755,7 @@ SC_FUNC void popreg(regid reg)
|
||||
/*
|
||||
* Generate an array
|
||||
*/
|
||||
SC_FUNC void genarray(int dims, int _autozero)
|
||||
void genarray(int dims, int _autozero)
|
||||
{
|
||||
if (_autozero) {
|
||||
stgwrite("\tgenarray.z ");
|
||||
@ -710,7 +769,7 @@ SC_FUNC void genarray(int dims, int _autozero)
|
||||
/*
|
||||
* swap the top-of-stack with the value in primary register
|
||||
*/
|
||||
SC_FUNC void swap1(void)
|
||||
void swap1(void)
|
||||
{
|
||||
stgwrite("\tswap.pri\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -725,14 +784,14 @@ SC_FUNC void swap1(void)
|
||||
* The case table is sorted on the comparison value. This allows more advanced
|
||||
* abstract machines to sift the case table with a binary search.
|
||||
*/
|
||||
SC_FUNC void ffswitch(int label)
|
||||
void ffswitch(int label)
|
||||
{
|
||||
stgwrite("\tswitch ");
|
||||
outval(label,TRUE); /* the label is the address of the case table */
|
||||
code_idx+=opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
SC_FUNC void ffcase(cell value,char *labelname,int newtable)
|
||||
void ffcase(cell value,char *labelname,int newtable)
|
||||
{
|
||||
if (newtable) {
|
||||
stgwrite("\tcasetbl\n");
|
||||
@ -749,7 +808,7 @@ SC_FUNC void ffcase(cell value,char *labelname,int newtable)
|
||||
/*
|
||||
* Call specified function
|
||||
*/
|
||||
SC_FUNC void ffcall(symbol *sym,const char *label,int numargs)
|
||||
void ffcall(symbol *sym,const char *label,int numargs)
|
||||
{
|
||||
char symname[2*sNAMEMAX+16];
|
||||
char aliasname[sNAMEMAX+1];
|
||||
@ -809,7 +868,7 @@ SC_FUNC void ffcall(symbol *sym,const char *label,int numargs)
|
||||
*
|
||||
* Global references: funcstatus (referred to only)
|
||||
*/
|
||||
SC_FUNC void ffret(int remparams)
|
||||
void ffret(int remparams)
|
||||
{
|
||||
if (remparams)
|
||||
stgwrite("\tretn\n");
|
||||
@ -818,14 +877,14 @@ SC_FUNC void ffret(int remparams)
|
||||
code_idx+=opcodes(1);
|
||||
}
|
||||
|
||||
SC_FUNC void ffabort(int reason)
|
||||
void ffabort(int reason)
|
||||
{
|
||||
stgwrite("\thalt ");
|
||||
outval(reason,TRUE);
|
||||
code_idx+=opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
SC_FUNC void ffbounds(cell size)
|
||||
void ffbounds(cell size)
|
||||
{
|
||||
if ((sc_debug & sCHKBOUNDS)!=0) {
|
||||
stgwrite("\tbounds ");
|
||||
@ -837,7 +896,7 @@ SC_FUNC void ffbounds(cell size)
|
||||
/*
|
||||
* Jump to local label number (the number is converted to a name)
|
||||
*/
|
||||
SC_FUNC void jumplabel(int number)
|
||||
void jumplabel(int number)
|
||||
{
|
||||
stgwrite("\tjump ");
|
||||
outval(number,TRUE);
|
||||
@ -847,7 +906,7 @@ SC_FUNC void jumplabel(int number)
|
||||
/*
|
||||
* Define storage (global and static variables)
|
||||
*/
|
||||
SC_FUNC void defstorage(void)
|
||||
void defstorage(void)
|
||||
{
|
||||
stgwrite("dump ");
|
||||
}
|
||||
@ -856,7 +915,7 @@ SC_FUNC void defstorage(void)
|
||||
* Inclrement/decrement stack pointer. Note that this routine does
|
||||
* nothing if the delta is zero.
|
||||
*/
|
||||
SC_FUNC void modstk(int delta)
|
||||
void modstk(int delta)
|
||||
{
|
||||
if (delta) {
|
||||
stgwrite("\tstack ");
|
||||
@ -866,7 +925,7 @@ SC_FUNC void modstk(int delta)
|
||||
}
|
||||
|
||||
/* set the stack to a hard offset from the frame */
|
||||
SC_FUNC void setstk(cell value)
|
||||
void setstk(cell value)
|
||||
{
|
||||
stgwrite("\tstackadjust ");
|
||||
assert(value<=0); /* STK should always become <= FRM */
|
||||
@ -874,7 +933,7 @@ SC_FUNC void setstk(cell value)
|
||||
code_idx+=opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
SC_FUNC void modheap(int delta)
|
||||
void modheap(int delta)
|
||||
{
|
||||
if (delta) {
|
||||
stgwrite("\theap ");
|
||||
@ -883,13 +942,13 @@ SC_FUNC void modheap(int delta)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC void modheap_i()
|
||||
void modheap_i()
|
||||
{
|
||||
stgwrite("\ttracker.pop.setheap\n");
|
||||
code_idx+=opcodes(1);
|
||||
}
|
||||
|
||||
SC_FUNC void setheap_save(cell value)
|
||||
void setheap_save(cell value)
|
||||
{
|
||||
assert(value);
|
||||
stgwrite("\ttracker.push.c ");
|
||||
@ -897,7 +956,7 @@ SC_FUNC void setheap_save(cell value)
|
||||
code_idx+=opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
SC_FUNC void setheap_pri(void)
|
||||
void setheap_pri(void)
|
||||
{
|
||||
stgwrite("\theap "); /* ALT = HEA++ */
|
||||
outval(sizeof(cell), TRUE);
|
||||
@ -906,7 +965,7 @@ SC_FUNC void setheap_pri(void)
|
||||
code_idx+=opcodes(3)+opargs(1);
|
||||
}
|
||||
|
||||
SC_FUNC void setheap(cell value)
|
||||
void setheap(cell value)
|
||||
{
|
||||
stgwrite("\tconst.pri "); /* load default value in PRI */
|
||||
outval(value, TRUE);
|
||||
@ -918,7 +977,7 @@ SC_FUNC void setheap(cell value)
|
||||
* Convert a cell number to a "byte" address; i.e. double or quadruple
|
||||
* the primary register.
|
||||
*/
|
||||
SC_FUNC void cell2addr(void)
|
||||
void cell2addr(void)
|
||||
{
|
||||
#if PAWN_CELL_SIZE==16
|
||||
stgwrite("\tshl.c.pri 1\n");
|
||||
@ -935,7 +994,7 @@ SC_FUNC void cell2addr(void)
|
||||
/*
|
||||
* Double or quadruple the alternate register.
|
||||
*/
|
||||
SC_FUNC void cell2addr_alt(void)
|
||||
void cell2addr_alt(void)
|
||||
{
|
||||
#if PAWN_CELL_SIZE==16
|
||||
stgwrite("\tshl.c.alt 1\n");
|
||||
@ -954,7 +1013,7 @@ SC_FUNC void cell2addr_alt(void)
|
||||
* Or convert a number of packed characters to the number of cells (with
|
||||
* truncation).
|
||||
*/
|
||||
SC_FUNC void addr2cell(void)
|
||||
void addr2cell(void)
|
||||
{
|
||||
#if PAWN_CELL_SIZE==16
|
||||
stgwrite("\tshr.c.pri 1\n");
|
||||
@ -971,7 +1030,7 @@ SC_FUNC void addr2cell(void)
|
||||
/* Convert from character index to byte address. This routine does
|
||||
* nothing if a character has the size of a byte.
|
||||
*/
|
||||
SC_FUNC void char2addr(void)
|
||||
void char2addr(void)
|
||||
{
|
||||
#if sCHARBITS==16
|
||||
stgwrite("\tshl.c.pri 1\n");
|
||||
@ -989,7 +1048,7 @@ SC_FUNC void char2addr(void)
|
||||
*
|
||||
* NOTE: For Source Pawn, this is fliped. It will do nothing on Little-Endian.
|
||||
*/
|
||||
SC_FUNC void charalign(void)
|
||||
void charalign(void)
|
||||
{
|
||||
#if 0 /* TEMPORARILY DISABLED BECAUSE WE DON'T USE BIG ENDIAN */
|
||||
stgwrite("\talign.pri ");
|
||||
@ -1001,7 +1060,7 @@ SC_FUNC void charalign(void)
|
||||
/*
|
||||
* Add a constant to the primary register.
|
||||
*/
|
||||
SC_FUNC void addconst(cell value)
|
||||
void addconst(cell value)
|
||||
{
|
||||
if (value!=0) {
|
||||
stgwrite("\tadd.c ");
|
||||
@ -1013,7 +1072,7 @@ SC_FUNC void addconst(cell value)
|
||||
/*
|
||||
* signed multiply of primary and secundairy registers (result in primary)
|
||||
*/
|
||||
SC_FUNC void os_mult(void)
|
||||
void os_mult(void)
|
||||
{
|
||||
stgwrite("\tsmul\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1023,7 +1082,7 @@ SC_FUNC void os_mult(void)
|
||||
* signed divide of alternate register by primary register (quotient in
|
||||
* primary; remainder in alternate)
|
||||
*/
|
||||
SC_FUNC void os_div(void)
|
||||
void os_div(void)
|
||||
{
|
||||
stgwrite("\tsdiv.alt\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1032,7 +1091,7 @@ SC_FUNC void os_div(void)
|
||||
/*
|
||||
* modulus of (alternate % primary), result in primary (signed)
|
||||
*/
|
||||
SC_FUNC void os_mod(void)
|
||||
void os_mod(void)
|
||||
{
|
||||
stgwrite("\tsdiv.alt\n");
|
||||
stgwrite("\tmove.pri\n"); /* move ALT to PRI */
|
||||
@ -1042,7 +1101,7 @@ SC_FUNC void os_mod(void)
|
||||
/*
|
||||
* Add primary and alternate registers (result in primary).
|
||||
*/
|
||||
SC_FUNC void ob_add(void)
|
||||
void ob_add(void)
|
||||
{
|
||||
stgwrite("\tadd\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1051,7 +1110,7 @@ SC_FUNC void ob_add(void)
|
||||
/*
|
||||
* subtract primary register from alternate register (result in primary)
|
||||
*/
|
||||
SC_FUNC void ob_sub(void)
|
||||
void ob_sub(void)
|
||||
{
|
||||
stgwrite("\tsub.alt\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1063,7 +1122,7 @@ SC_FUNC void ob_sub(void)
|
||||
* There is no need for a "logical shift left" routine, since
|
||||
* logical shift left is identical to arithmic shift left.
|
||||
*/
|
||||
SC_FUNC void ob_sal(void)
|
||||
void ob_sal(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tshl\n");
|
||||
@ -1074,7 +1133,7 @@ SC_FUNC void ob_sal(void)
|
||||
* arithmic shift right alternate register the number of bits
|
||||
* given in the primary register (result in primary).
|
||||
*/
|
||||
SC_FUNC void os_sar(void)
|
||||
void os_sar(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tsshr\n");
|
||||
@ -1085,7 +1144,7 @@ SC_FUNC void os_sar(void)
|
||||
* logical (unsigned) shift right of the alternate register by the
|
||||
* number of bits given in the primary register (result in primary).
|
||||
*/
|
||||
SC_FUNC void ou_sar(void)
|
||||
void ou_sar(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tshr\n");
|
||||
@ -1095,7 +1154,7 @@ SC_FUNC void ou_sar(void)
|
||||
/*
|
||||
* inclusive "or" of primary and alternate registers (result in primary)
|
||||
*/
|
||||
SC_FUNC void ob_or(void)
|
||||
void ob_or(void)
|
||||
{
|
||||
stgwrite("\tor\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1104,7 +1163,7 @@ SC_FUNC void ob_or(void)
|
||||
/*
|
||||
* "exclusive or" of primary and alternate registers (result in primary)
|
||||
*/
|
||||
SC_FUNC void ob_xor(void)
|
||||
void ob_xor(void)
|
||||
{
|
||||
stgwrite("\txor\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1113,7 +1172,7 @@ SC_FUNC void ob_xor(void)
|
||||
/*
|
||||
* "and" of primary and secundairy registers (result in primary)
|
||||
*/
|
||||
SC_FUNC void ob_and(void)
|
||||
void ob_and(void)
|
||||
{
|
||||
stgwrite("\tand\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1122,7 +1181,7 @@ SC_FUNC void ob_and(void)
|
||||
/*
|
||||
* test ALT==PRI; result in primary register (1 or 0).
|
||||
*/
|
||||
SC_FUNC void ob_eq(void)
|
||||
void ob_eq(void)
|
||||
{
|
||||
stgwrite("\teq\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1131,7 +1190,7 @@ SC_FUNC void ob_eq(void)
|
||||
/*
|
||||
* test ALT!=PRI
|
||||
*/
|
||||
SC_FUNC void ob_ne(void)
|
||||
void ob_ne(void)
|
||||
{
|
||||
stgwrite("\tneq\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1157,14 +1216,14 @@ SC_FUNC void ob_ne(void)
|
||||
* stack and moves the value of ALT into PRI. If there is a next comparison,
|
||||
* PRI can now serve as the "left" operand of the relational operator.
|
||||
*/
|
||||
SC_FUNC void relop_prefix(void)
|
||||
void relop_prefix(void)
|
||||
{
|
||||
stgwrite("\tpush.pri\n");
|
||||
stgwrite("\tmove.pri\n");
|
||||
code_idx+=opcodes(2);
|
||||
}
|
||||
|
||||
SC_FUNC void relop_suffix(void)
|
||||
void relop_suffix(void)
|
||||
{
|
||||
stgwrite("\tswap.alt\n");
|
||||
stgwrite("\tand\n");
|
||||
@ -1175,7 +1234,7 @@ SC_FUNC void relop_suffix(void)
|
||||
/*
|
||||
* test ALT<PRI (signed)
|
||||
*/
|
||||
SC_FUNC void os_lt(void)
|
||||
void os_lt(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tsless\n");
|
||||
@ -1185,7 +1244,7 @@ SC_FUNC void os_lt(void)
|
||||
/*
|
||||
* test ALT<=PRI (signed)
|
||||
*/
|
||||
SC_FUNC void os_le(void)
|
||||
void os_le(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tsleq\n");
|
||||
@ -1195,7 +1254,7 @@ SC_FUNC void os_le(void)
|
||||
/*
|
||||
* test ALT>PRI (signed)
|
||||
*/
|
||||
SC_FUNC void os_gt(void)
|
||||
void os_gt(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tsgrtr\n");
|
||||
@ -1205,7 +1264,7 @@ SC_FUNC void os_gt(void)
|
||||
/*
|
||||
* test ALT>=PRI (signed)
|
||||
*/
|
||||
SC_FUNC void os_ge(void)
|
||||
void os_ge(void)
|
||||
{
|
||||
stgwrite("\txchg\n");
|
||||
stgwrite("\tsgeq\n");
|
||||
@ -1215,7 +1274,7 @@ SC_FUNC void os_ge(void)
|
||||
/*
|
||||
* logical negation of primary register
|
||||
*/
|
||||
SC_FUNC void lneg(void)
|
||||
void lneg(void)
|
||||
{
|
||||
stgwrite("\tnot\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1224,7 +1283,7 @@ SC_FUNC void lneg(void)
|
||||
/*
|
||||
* two's complement primary register
|
||||
*/
|
||||
SC_FUNC void neg(void)
|
||||
void neg(void)
|
||||
{
|
||||
stgwrite("\tneg\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1233,7 +1292,7 @@ SC_FUNC void neg(void)
|
||||
/*
|
||||
* one's complement of primary register
|
||||
*/
|
||||
SC_FUNC void invert(void)
|
||||
void invert(void)
|
||||
{
|
||||
stgwrite("\tinvert\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1242,19 +1301,19 @@ SC_FUNC void invert(void)
|
||||
/*
|
||||
* nop
|
||||
*/
|
||||
SC_FUNC void nooperation(void)
|
||||
void nooperation(void)
|
||||
{
|
||||
stgwrite("\tnop\n");
|
||||
code_idx+=opcodes(1);
|
||||
}
|
||||
|
||||
SC_FUNC void inc_pri()
|
||||
void inc_pri()
|
||||
{
|
||||
stgwrite("\tinc.pri\n");
|
||||
code_idx+=opcodes(1);
|
||||
}
|
||||
|
||||
SC_FUNC void dec_pri()
|
||||
void dec_pri()
|
||||
{
|
||||
stgwrite("\tdec.pri\n");
|
||||
code_idx+=opcodes(1);
|
||||
@ -1262,7 +1321,7 @@ SC_FUNC void dec_pri()
|
||||
|
||||
/* increment symbol
|
||||
*/
|
||||
SC_FUNC void inc(value *lval)
|
||||
void inc(value *lval)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -1320,7 +1379,7 @@ SC_FUNC void inc(value *lval)
|
||||
*
|
||||
* in case of an integer pointer, the symbol must be incremented by 2.
|
||||
*/
|
||||
SC_FUNC void dec(value *lval)
|
||||
void dec(value *lval)
|
||||
{
|
||||
symbol *sym;
|
||||
|
||||
@ -1377,7 +1436,7 @@ SC_FUNC void dec(value *lval)
|
||||
/*
|
||||
* Jumps to "label" if PRI != 0
|
||||
*/
|
||||
SC_FUNC void jmp_ne0(int number)
|
||||
void jmp_ne0(int number)
|
||||
{
|
||||
stgwrite("\tjnz ");
|
||||
outval(number,TRUE);
|
||||
@ -1387,7 +1446,7 @@ SC_FUNC void jmp_ne0(int number)
|
||||
/*
|
||||
* Jumps to "label" if PRI == 0
|
||||
*/
|
||||
SC_FUNC void jmp_eq0(int number)
|
||||
void jmp_eq0(int number)
|
||||
{
|
||||
stgwrite("\tjzer ");
|
||||
outval(number,TRUE);
|
||||
@ -1395,14 +1454,14 @@ SC_FUNC void jmp_eq0(int number)
|
||||
}
|
||||
|
||||
/* write a value in hexadecimal; optionally adds a newline */
|
||||
SC_FUNC void outval(cell val,int newline)
|
||||
void outval(cell val,int newline)
|
||||
{
|
||||
stgwrite(itoh(val));
|
||||
if (newline)
|
||||
stgwrite("\n");
|
||||
}
|
||||
|
||||
SC_FUNC void invoke_getter(methodmap_method_t *method)
|
||||
void invoke_getter(methodmap_method_t *method)
|
||||
{
|
||||
if (!method->getter) {
|
||||
error(149, method->name);
|
||||
@ -1420,7 +1479,7 @@ SC_FUNC void invoke_getter(methodmap_method_t *method)
|
||||
markusage(method->getter, uREAD);
|
||||
}
|
||||
|
||||
SC_FUNC void invoke_setter(methodmap_method_t *method, int save)
|
||||
void invoke_setter(methodmap_method_t *method, int save)
|
||||
{
|
||||
if (!method->setter) {
|
||||
error(152, method->name);
|
@ -21,7 +21,7 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
|
||||
int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
|
||||
|
||||
#ifndef SCPACK
|
||||
# define SCPACK
|
||||
@ -42,7 +42,7 @@ unsigned char errstr_table
[][2] = {
|
||||
};
|
||||
/*-*SCPACK end of pair table, do not change or remove this line */
|
||||
|
||||
static char *errmsg[] = {
|
||||
static const char *errmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*001*/ "expected token: \"%s\", but found \"%s\"\n",
|
||||
/*002*/ "only a single statement (or expression) can follow each \"case\"\n",
|
||||
@ -362,7 +362,7 @@ static char *errmsg[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static char *fatalmsg[] = {
|
||||
static const char *fatalmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*160*/ "cannot read from file: \"%s\"\n",
|
||||
/*161*/ "cannot write to file: \"%s\"\n",
|
||||
@ -398,7 +398,7 @@ static char *fatalmsg[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static char *warnmsg[] = {
|
||||
static const char *warnmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*200*/ "symbol \"%s\" is truncated to %d characters\n",
|
||||
/*201*/ "redefinition of constant/macro (symbol \"%s\")\n",
|
||||
|
@ -67,12 +67,12 @@ static int sErrLine; /* forced line number for the error message */
|
||||
* fcurrent (reffered to only)
|
||||
* errflag (altered)
|
||||
*/
|
||||
SC_FUNC int error(int number,...)
|
||||
int error(int number,...)
|
||||
{
|
||||
static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
static const char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
static int lastline,errorcount;
|
||||
static short lastfile;
|
||||
char *msg,*pre;
|
||||
const char *msg,*pre;
|
||||
va_list argptr;
|
||||
|
||||
// sErrLine is used to temporarily change the line number of reported errors.
|
||||
@ -172,7 +172,7 @@ static short lastfile;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SC_FUNC void errorset(int code,int line)
|
||||
void errorset(int code,int line)
|
||||
{
|
||||
switch (code) {
|
||||
case sRESET:
|
@ -37,14 +37,14 @@
|
||||
#endif
|
||||
|
||||
|
||||
static void append_dbginfo(FILE *fout);
|
||||
static void append_dbginfo(void *fout);
|
||||
|
||||
|
||||
typedef cell (*OPCODE_PROC)(FILE *fbin,char *params,cell opcode);
|
||||
typedef cell (*OPCODE_PROC)(void *fbin,char *params,cell opcode);
|
||||
|
||||
typedef struct {
|
||||
cell opcode;
|
||||
char *name;
|
||||
const char *name;
|
||||
int segment; /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */
|
||||
OPCODE_PROC func;
|
||||
} OPCODEC;
|
||||
@ -192,7 +192,7 @@ static char *stripcomment(char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
static void write_encoded(FILE *fbin,ucell *c,int num)
|
||||
static void write_encoded(void *fbin,ucell *c,int num)
|
||||
{
|
||||
#if PAWN_CELL_SIZE == 16
|
||||
#define ENC_MAX 3 /* a 16-bit cell is encoded in max. 3 bytes */
|
||||
@ -246,7 +246,7 @@ static void write_encoded(FILE *fbin,ucell *c,int num)
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell noop(FILE *fbin,char *params,cell opcode)
|
||||
static cell noop(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -254,7 +254,7 @@ static cell noop(FILE *fbin,char *params,cell opcode)
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell set_currentfile(FILE *fbin,char *params,cell opcode)
|
||||
static cell set_currentfile(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
fcurrent=(short)getparam(params,NULL);
|
||||
return 0;
|
||||
@ -263,14 +263,14 @@ static cell set_currentfile(FILE *fbin,char *params,cell opcode)
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell parm0(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm0(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
if (fbin!=NULL)
|
||||
write_encoded(fbin,(ucell*)&opcode,1);
|
||||
return opcodes(1);
|
||||
}
|
||||
|
||||
static cell parm1(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm1(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p=getparam(params,NULL);
|
||||
if (fbin!=NULL) {
|
||||
@ -280,7 +280,7 @@ static cell parm1(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
static cell parm2(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm2(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p1=getparam(params,¶ms);
|
||||
ucell p2=getparam(params,NULL);
|
||||
@ -292,7 +292,7 @@ static cell parm2(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(2);
|
||||
}
|
||||
|
||||
static cell parm3(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm3(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p1=getparam(params,¶ms);
|
||||
ucell p2=getparam(params,¶ms);
|
||||
@ -306,7 +306,7 @@ static cell parm3(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(3);
|
||||
}
|
||||
|
||||
static cell parm4(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm4(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p1=getparam(params,¶ms);
|
||||
ucell p2=getparam(params,¶ms);
|
||||
@ -322,7 +322,7 @@ static cell parm4(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(4);
|
||||
}
|
||||
|
||||
static cell parm5(FILE *fbin,char *params,cell opcode)
|
||||
static cell parm5(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p1=getparam(params,¶ms);
|
||||
ucell p2=getparam(params,¶ms);
|
||||
@ -343,7 +343,7 @@ static cell parm5(FILE *fbin,char *params,cell opcode)
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell do_dump(FILE *fbin,char *params,cell opcode)
|
||||
static cell do_dump(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p;
|
||||
int num = 0;
|
||||
@ -359,7 +359,7 @@ static cell do_dump(FILE *fbin,char *params,cell opcode)
|
||||
return num*sizeof(cell);
|
||||
}
|
||||
|
||||
static cell do_call(FILE *fbin,char *params,cell opcode)
|
||||
static cell do_call(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
char name[sNAMEMAX+1];
|
||||
int i;
|
||||
@ -399,7 +399,7 @@ static cell do_call(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
static cell do_jump(FILE *fbin,char *params,cell opcode)
|
||||
static cell do_jump(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
int i;
|
||||
ucell p;
|
||||
@ -416,7 +416,7 @@ static cell do_jump(FILE *fbin,char *params,cell opcode)
|
||||
return opcodes(1)+opargs(1);
|
||||
}
|
||||
|
||||
static cell do_switch(FILE *fbin,char *params,cell opcode)
|
||||
static cell do_switch(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
int i;
|
||||
ucell p;
|
||||
@ -436,7 +436,7 @@ static cell do_switch(FILE *fbin,char *params,cell opcode)
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell do_case(FILE *fbin,char *params,cell opcode)
|
||||
static cell do_case(void *fbin,char *params,cell opcode)
|
||||
{
|
||||
int i;
|
||||
ucell p,v;
|
||||
@ -659,7 +659,7 @@ static int findopcode(char *instr,int maxlen)
|
||||
return 0; /* not found, return special index */
|
||||
}
|
||||
|
||||
SC_FUNC int assemble(FILE *fout,FILE *fin)
|
||||
int assemble(void *fout, void *fin)
|
||||
{
|
||||
AMX_HEADER hdr;
|
||||
AMX_FUNCSTUBNT func;
|
||||
@ -1058,7 +1058,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void append_dbginfo(FILE *fout)
|
||||
static void append_dbginfo(void *fout)
|
||||
{
|
||||
AMX_DBG_HDR dbghdr;
|
||||
AMX_DBG_LINE dbgline;
|
@ -22,7 +22,7 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
|
||||
int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
|
||||
|
||||
#define SCPACK_TERMINATOR , /* end each section with a comma */
|
||||
|
||||
@ -41,12 +41,17 @@ unsigned char sequences_table[][2] = {
|
||||
/*-*SCPACK end of pair table, do not change or remove this line */
|
||||
|
||||
#define seqsize(o,p) (opcodes(o)+opargs(p))
|
||||
typedef struct {
|
||||
const char *find;
|
||||
const char *replace;
|
||||
int savesize; /* number of bytes saved (in bytecode) */
|
||||
} SETUP_SEQUENCE;
|
||||
typedef struct {
|
||||
char *find;
|
||||
char *replace;
|
||||
int savesize; /* number of bytes saved (in bytecode) */
|
||||
} SEQUENCE;
|
||||
static SEQUENCE sequences_cmp[] = {
|
||||
static SETUP_SEQUENCE sequences_cmp[] = {
|
||||
/* A very common sequence in four varieties
|
||||
* load.s.pri n1 load.s.pri n2
|
||||
* push.pri load.s.alt n1
|
||||
|
@ -108,7 +108,7 @@ static void grow_stgbuffer(char **buffer, int *curmax, int requiredsize)
|
||||
**buffer='\0';
|
||||
}
|
||||
|
||||
SC_FUNC void stgbuffer_cleanup(void)
|
||||
void stgbuffer_cleanup(void)
|
||||
{
|
||||
if (stgbuf!=NULL) {
|
||||
free(stgbuf);
|
||||
@ -141,7 +141,7 @@ SC_FUNC void stgbuffer_cleanup(void)
|
||||
* stgbuf (altered)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgmark(char mark)
|
||||
void stgmark(char mark)
|
||||
{
|
||||
if (staging) {
|
||||
CHECK_STGBUFFER(stgidx);
|
||||
@ -188,7 +188,7 @@ static int filewrite(char *str)
|
||||
* stgbuf (altered)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgwrite(const char *st)
|
||||
void stgwrite(const char *st)
|
||||
{
|
||||
int len;
|
||||
|
||||
@ -224,7 +224,7 @@ SC_FUNC void stgwrite(const char *st)
|
||||
* stgbuf (referred to only)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgout(int index)
|
||||
void stgout(int index)
|
||||
{
|
||||
int reordered=0;
|
||||
int idx;
|
||||
@ -348,7 +348,7 @@ static int stgstring(char *start,char *end)
|
||||
* Global references: stgidx (altered)
|
||||
* staging (reffered to only)
|
||||
*/
|
||||
SC_FUNC void stgdel(int index,cell code_index)
|
||||
void stgdel(int index,cell code_index)
|
||||
{
|
||||
if (staging) {
|
||||
stgidx=index;
|
||||
@ -356,7 +356,7 @@ SC_FUNC void stgdel(int index,cell code_index)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC int stgget(int *index,cell *code_index)
|
||||
int stgget(int *index,cell *code_index)
|
||||
{
|
||||
if (staging) {
|
||||
*index=stgidx;
|
||||
@ -375,7 +375,7 @@ SC_FUNC int stgget(int *index,cell *code_index)
|
||||
* stgidx (altered)
|
||||
* stgbuf (contents altered)
|
||||
*/
|
||||
SC_FUNC void stgset(int onoff)
|
||||
void stgset(int onoff)
|
||||
{
|
||||
staging=onoff;
|
||||
if (staging){
|
||||
@ -398,7 +398,7 @@ SC_FUNC void stgset(int onoff)
|
||||
*/
|
||||
static SEQUENCE *sequences;
|
||||
|
||||
SC_FUNC int phopt_init(void)
|
||||
int phopt_init(void)
|
||||
{
|
||||
int number, i, len;
|
||||
char str[160];
|
||||
@ -440,7 +440,7 @@ SC_FUNC int phopt_init(void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC int phopt_cleanup(void)
|
||||
int phopt_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
if (sequences!=NULL) {
|
@ -16,7 +16,7 @@
|
||||
|
||||
#define STACKSIZE 16
|
||||
|
||||
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2])
|
||||
int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2])
|
||||
{
|
||||
unsigned char stack[STACKSIZE];
|
||||
short c, top = 0;
|
@ -113,7 +113,7 @@ static int cp_readline(FILE *fp,char *string,size_t size)
|
||||
* codepages are most conveniently stored in a subdirectory of this home
|
||||
* directory.
|
||||
*/
|
||||
SC_FUNC int cp_path(const char *root, const char *directory)
|
||||
int cp_path(const char *root, const char *directory)
|
||||
{
|
||||
size_t len1,len2;
|
||||
int add_slash1,add_slash2;
|
||||
@ -154,7 +154,7 @@ SC_FUNC int cp_path(const char *root, const char *directory)
|
||||
* <cprootpath>/cp<name>
|
||||
* <cprootpath>/cp<name>.txt
|
||||
*/
|
||||
SC_FUNC int cp_set(const char *name)
|
||||
int cp_set(const char *name)
|
||||
{
|
||||
char filename[_MAX_PATH];
|
||||
FILE *fp=NULL;
|
||||
@ -277,7 +277,7 @@ SC_FUNC int cp_set(const char *name)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr)
|
||||
cell cp_translate(const unsigned char *string,const unsigned char **endptr)
|
||||
{
|
||||
wchar_t result;
|
||||
|
||||
@ -312,7 +312,7 @@ SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endp
|
||||
#endif /* NO_CODEPAGE */
|
||||
|
||||
#if !defined NO_UTF8
|
||||
SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr)
|
||||
cell get_utf8_char(const unsigned char *string,const unsigned char **endptr)
|
||||
{
|
||||
int follow=0;
|
||||
long lowmark=0;
|
||||
@ -391,7 +391,7 @@ SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **end
|
||||
}
|
||||
#endif
|
||||
|
||||
SC_FUNC int scan_utf8(FILE *fp,const char *filename)
|
||||
int scan_utf8(void *fp,const char *filename)
|
||||
{
|
||||
#if defined NO_UTF8
|
||||
return 0;
|
@ -41,7 +41,7 @@
|
||||
* to other memory allocators becomes easier.
|
||||
* By Søren Hannibal.
|
||||
*/
|
||||
SC_FUNC char* duplicatestring(const char* sourcestring)
|
||||
char* duplicatestring(const char* sourcestring)
|
||||
{
|
||||
char* result=(char*)malloc(strlen(sourcestring)+1);
|
||||
strcpy(result,sourcestring);
|
||||
@ -49,7 +49,7 @@ SC_FUNC char* duplicatestring(const char* sourcestring)
|
||||
}
|
||||
|
||||
|
||||
static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
|
||||
static stringpair *insert_stringpair(stringpair *root,const char *first,const char *second,int matchlength)
|
||||
{
|
||||
stringpair *cur,*pred;
|
||||
|
||||
@ -137,7 +137,7 @@ static int delete_stringpair(stringpair *root,stringpair *item)
|
||||
}
|
||||
|
||||
/* ----- string list functions ----------------------------------- */
|
||||
static stringlist *insert_string(stringlist *root,char *string)
|
||||
static stringlist *insert_string(stringlist *root,const char *string)
|
||||
{
|
||||
stringlist *cur;
|
||||
|
||||
@ -190,7 +190,7 @@ static int delete_string(stringlist *root,int index)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_stringtable(stringlist *root)
|
||||
void delete_stringtable(stringlist *root)
|
||||
{
|
||||
stringlist *cur,*next;
|
||||
|
||||
@ -210,7 +210,7 @@ SC_FUNC void delete_stringtable(stringlist *root)
|
||||
/* ----- alias table --------------------------------------------- */
|
||||
static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */
|
||||
|
||||
SC_FUNC stringpair *insert_alias(char *name,char *alias)
|
||||
stringpair *insert_alias(char *name,char *alias)
|
||||
{
|
||||
stringpair *cur;
|
||||
|
||||
@ -223,7 +223,7 @@ SC_FUNC stringpair *insert_alias(char *name,char *alias)
|
||||
return cur;
|
||||
}
|
||||
|
||||
SC_FUNC int lookup_alias(char *target,char *name)
|
||||
int lookup_alias(char *target,char *name)
|
||||
{
|
||||
stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
|
||||
if (cur!=NULL) {
|
||||
@ -233,7 +233,7 @@ SC_FUNC int lookup_alias(char *target,char *name)
|
||||
return cur!=NULL;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_aliastable(void)
|
||||
void delete_aliastable(void)
|
||||
{
|
||||
delete_stringpairtable(&alias_tab);
|
||||
}
|
||||
@ -241,17 +241,17 @@ SC_FUNC void delete_aliastable(void)
|
||||
/* ----- include paths list -------------------------------------- */
|
||||
static stringlist includepaths; /* directory list for include files */
|
||||
|
||||
SC_FUNC stringlist *insert_path(char *path)
|
||||
stringlist *insert_path(char *path)
|
||||
{
|
||||
return insert_string(&includepaths,path);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_path(int index)
|
||||
char *get_path(int index)
|
||||
{
|
||||
return get_string(&includepaths,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_pathtable(void)
|
||||
void delete_pathtable(void)
|
||||
{
|
||||
delete_stringtable(&includepaths);
|
||||
assert(includepaths.next==NULL);
|
||||
@ -275,7 +275,7 @@ static void adjustindex(char c)
|
||||
substindex[(int)c-PUBLIC_CHAR]=cur;
|
||||
}
|
||||
|
||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
|
||||
stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen)
|
||||
{
|
||||
stringpair *cur;
|
||||
|
||||
@ -306,7 +306,7 @@ SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
|
||||
return cur;
|
||||
}
|
||||
|
||||
SC_FUNC stringpair *find_subst(char *name,int length)
|
||||
stringpair *find_subst(char *name,int length)
|
||||
{
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
@ -319,12 +319,13 @@ SC_FUNC stringpair *find_subst(char *name,int length)
|
||||
if (item && (item->flags & flgDEPRECATED) != 0)
|
||||
{
|
||||
static char macro[128];
|
||||
char *rem, *msg = (item->documentation != NULL) ? item->documentation : "";
|
||||
const char *msg = (item->documentation != NULL) ? item->documentation : "";
|
||||
strlcpy(macro, item->first, sizeof(macro));
|
||||
|
||||
/* If macro contains an opening parentheses and a percent sign, then assume that
|
||||
* it takes arguments and remove them from the warning message.
|
||||
*/
|
||||
char *rem;
|
||||
if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem)
|
||||
{
|
||||
*rem = '\0';
|
||||
@ -335,7 +336,7 @@ SC_FUNC stringpair *find_subst(char *name,int length)
|
||||
return item;
|
||||
}
|
||||
|
||||
SC_FUNC int delete_subst(char *name,int length)
|
||||
int delete_subst(char *name,int length)
|
||||
{
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
@ -356,7 +357,7 @@ SC_FUNC int delete_subst(char *name,int length)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_substtable(void)
|
||||
void delete_substtable(void)
|
||||
{
|
||||
int i;
|
||||
delete_stringpairtable(&substpair);
|
||||
@ -370,17 +371,17 @@ SC_FUNC void delete_substtable(void)
|
||||
/* ----- input file list ----------------------------------------- */
|
||||
static stringlist sourcefiles;
|
||||
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string)
|
||||
stringlist *insert_sourcefile(char *string)
|
||||
{
|
||||
return insert_string(&sourcefiles,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_sourcefile(int index)
|
||||
char *get_sourcefile(int index)
|
||||
{
|
||||
return get_string(&sourcefiles,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_sourcefiletable(void)
|
||||
void delete_sourcefiletable(void)
|
||||
{
|
||||
delete_stringtable(&sourcefiles);
|
||||
assert(sourcefiles.next==NULL);
|
||||
@ -391,22 +392,22 @@ SC_FUNC void delete_sourcefiletable(void)
|
||||
#if !defined SC_LIGHT
|
||||
static stringlist docstrings;
|
||||
|
||||
SC_FUNC stringlist *insert_docstring(char *string)
|
||||
stringlist *insert_docstring(char *string)
|
||||
{
|
||||
return insert_string(&docstrings,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_docstring(int index)
|
||||
char *get_docstring(int index)
|
||||
{
|
||||
return get_string(&docstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_docstring(int index)
|
||||
void delete_docstring(int index)
|
||||
{
|
||||
delete_string(&docstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_docstringtable(void)
|
||||
void delete_docstringtable(void)
|
||||
{
|
||||
delete_stringtable(&docstrings);
|
||||
assert(docstrings.next==NULL);
|
||||
@ -417,17 +418,17 @@ SC_FUNC void delete_docstringtable(void)
|
||||
/* ----- autolisting --------------------------------------------- */
|
||||
static stringlist autolist;
|
||||
|
||||
SC_FUNC stringlist *insert_autolist(char *string)
|
||||
stringlist *insert_autolist(const char *string)
|
||||
{
|
||||
return insert_string(&autolist,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_autolist(int index)
|
||||
char *get_autolist(int index)
|
||||
{
|
||||
return get_string(&autolist,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_autolisttable(void)
|
||||
void delete_autolisttable(void)
|
||||
{
|
||||
delete_stringtable(&autolist);
|
||||
assert(autolist.next==NULL);
|
||||
@ -463,7 +464,7 @@ SC_FUNC void delete_autolisttable(void)
|
||||
|
||||
static stringlist dbgstrings;
|
||||
|
||||
SC_FUNC stringlist *insert_dbgfile(const char *filename)
|
||||
stringlist *insert_dbgfile(const char *filename)
|
||||
{
|
||||
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
@ -476,7 +477,7 @@ SC_FUNC stringlist *insert_dbgfile(const char *filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC stringlist *insert_dbgline(int linenr)
|
||||
stringlist *insert_dbgline(int linenr)
|
||||
{
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
char string[40];
|
||||
@ -488,7 +489,7 @@ SC_FUNC stringlist *insert_dbgline(int linenr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
|
||||
stringlist *insert_dbgsymbol(symbol *sym)
|
||||
{
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
char string[2*sNAMEMAX+128];
|
||||
@ -521,17 +522,17 @@ SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC stringlist *get_dbgstrings()
|
||||
stringlist *get_dbgstrings()
|
||||
{
|
||||
return &dbgstrings;
|
||||
}
|
||||
|
||||
SC_FUNC char *get_dbgstring(int index)
|
||||
char *get_dbgstring(int index)
|
||||
{
|
||||
return get_string(&dbgstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_dbgstringtable(void)
|
||||
void delete_dbgstringtable(void)
|
||||
{
|
||||
delete_stringtable(&dbgstrings);
|
||||
assert(dbgstrings.next==NULL);
|
@ -34,8 +34,6 @@
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
typedef memfile_t MEMFILE;
|
||||
#define tMEMFILE 1
|
||||
|
||||
#include "sc.h"
|
||||
|
@ -87,7 +87,7 @@ static constvalue *find_automaton(const char *name,int *last)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_add(const char *name)
|
||||
constvalue *automaton_add(const char *name)
|
||||
{
|
||||
constvalue *ptr;
|
||||
int last;
|
||||
@ -101,13 +101,13 @@ SC_FUNC constvalue *automaton_add(const char *name)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_find(const char *name)
|
||||
constvalue *automaton_find(const char *name)
|
||||
{
|
||||
int last;
|
||||
return find_automaton(name,&last);
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_findid(int id)
|
||||
constvalue *automaton_findid(int id)
|
||||
{
|
||||
constvalue *ptr;
|
||||
for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next)
|
||||
@ -135,7 +135,7 @@ static constvalue *find_state(const char *name,int fsa,int *last)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_add(const char *name,int fsa)
|
||||
constvalue *state_add(const char *name,int fsa)
|
||||
{
|
||||
constvalue *ptr;
|
||||
int last;
|
||||
@ -149,13 +149,13 @@ SC_FUNC constvalue *state_add(const char *name,int fsa)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_find(const char *name,int fsa_id)
|
||||
constvalue *state_find(const char *name,int fsa_id)
|
||||
{
|
||||
int last; /* dummy */
|
||||
return find_state(name,fsa_id,&last);
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_findid(int id)
|
||||
constvalue *state_findid(int id)
|
||||
{
|
||||
constvalue *ptr;
|
||||
for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next)
|
||||
@ -163,7 +163,7 @@ SC_FUNC constvalue *state_findid(int id)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid)
|
||||
void state_buildlist(int **list,int *listsize,int *count,int stateid)
|
||||
{
|
||||
int idx;
|
||||
|
||||
@ -227,7 +227,7 @@ static statelist *state_getlist_ptr(int listid)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC int state_addlist(int *list,int count,int fsa)
|
||||
int state_addlist(int *list,int count,int fsa)
|
||||
{
|
||||
statelist *ptr;
|
||||
int last;
|
||||
@ -253,7 +253,7 @@ SC_FUNC int state_addlist(int *list,int count,int fsa)
|
||||
return ptr->listid;
|
||||
}
|
||||
|
||||
SC_FUNC void state_deletetable(void)
|
||||
void state_deletetable(void)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
@ -268,7 +268,7 @@ SC_FUNC void state_deletetable(void)
|
||||
} /* while */
|
||||
}
|
||||
|
||||
SC_FUNC int state_getfsa(int listid)
|
||||
int state_getfsa(int listid)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
@ -280,7 +280,7 @@ SC_FUNC int state_getfsa(int listid)
|
||||
return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */
|
||||
}
|
||||
|
||||
SC_FUNC int state_count(int listid)
|
||||
int state_count(int listid)
|
||||
{
|
||||
statelist *ptr=state_getlist_ptr(listid);
|
||||
if (ptr==NULL)
|
||||
@ -288,7 +288,7 @@ SC_FUNC int state_count(int listid)
|
||||
return ptr->numstates;
|
||||
}
|
||||
|
||||
SC_FUNC int state_inlist(int listid,int state)
|
||||
int state_inlist(int listid,int state)
|
||||
{
|
||||
statelist *ptr;
|
||||
int i;
|
||||
@ -302,7 +302,7 @@ SC_FUNC int state_inlist(int listid,int state)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int state_listitem(int listid,int index)
|
||||
int state_listitem(int listid,int index)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
@ -329,7 +329,7 @@ static int checkconflict(statelist *psrc,statelist *ptgt)
|
||||
* of a symbol exists in any other statelist id's of the same function; it also
|
||||
* verifies that all definitions of the symbol are in the same automaton.
|
||||
*/
|
||||
SC_FUNC void state_conflict(symbol *root)
|
||||
void state_conflict(symbol *root)
|
||||
{
|
||||
statelist *psrc,*ptgt;
|
||||
constvalue *srcptr,*tgtptr;
|
||||
@ -363,7 +363,7 @@ SC_FUNC void state_conflict(symbol *root)
|
||||
/* check whether the two state lists (whose ids are passed in) share any
|
||||
* states
|
||||
*/
|
||||
SC_FUNC int state_conflict_id(int listid1,int listid2)
|
||||
int state_conflict_id(int listid1,int listid2)
|
||||
{
|
||||
statelist *psrc,*ptgt;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include "sc.h"
|
||||
#include "sctracker.h"
|
||||
|
||||
@ -16,187 +17,213 @@ methodmap_t *methodmap_last = NULL;
|
||||
|
||||
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=0; i<pstruct->argcount; i++)
|
||||
{
|
||||
if (strcmp(pstruct->args[i]->name, member) == 0)
|
||||
{
|
||||
return pstruct->args[i];
|
||||
}
|
||||
}
|
||||
for (i=0; i<pstruct->argcount; i++) {
|
||||
if (strcmp(pstruct->args[i]->name, member) == 0)
|
||||
return pstruct->args[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pstruct_t *pstructs_add(const char *name)
|
||||
{
|
||||
pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
|
||||
|
||||
memset(p, 0, sizeof(pstruct_t));
|
||||
strcpy(p->name, name);
|
||||
|
||||
if (!firststruct)
|
||||
{
|
||||
firststruct = p;
|
||||
laststruct = p;
|
||||
} else {
|
||||
laststruct->next = p;
|
||||
laststruct = p;
|
||||
}
|
||||
pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
|
||||
|
||||
memset(p, 0, sizeof(pstruct_t));
|
||||
strcpy(p->name, name);
|
||||
|
||||
if (!firststruct) {
|
||||
firststruct = p;
|
||||
laststruct = p;
|
||||
} else {
|
||||
laststruct->next = p;
|
||||
laststruct = p;
|
||||
}
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
||||
void pstructs_free()
|
||||
{
|
||||
pstruct_t *p, *next;
|
||||
pstruct_t *p, *next;
|
||||
|
||||
p = firststruct;
|
||||
while (p)
|
||||
{
|
||||
while (p->argcount--)
|
||||
{
|
||||
free(p->args[p->argcount]);
|
||||
}
|
||||
free(p->args);
|
||||
next = p->next;
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
firststruct = NULL;
|
||||
laststruct = NULL;
|
||||
p = firststruct;
|
||||
while (p) {
|
||||
while (p->argcount--)
|
||||
free(p->args[p->argcount]);
|
||||
free(p->args);
|
||||
next = p->next;
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
firststruct = NULL;
|
||||
laststruct = NULL;
|
||||
}
|
||||
|
||||
pstruct_t *pstructs_find(const char *name)
|
||||
{
|
||||
pstruct_t *p = firststruct;
|
||||
pstruct_t *p = firststruct;
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
while (p) {
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
|
||||
{
|
||||
structarg_t *newarg;
|
||||
int i;
|
||||
structarg_t *newarg;
|
||||
int i;
|
||||
|
||||
for (i=0; i<pstruct->argcount; i++)
|
||||
{
|
||||
if (strcmp(pstruct->args[i]->name, arg->name) == 0)
|
||||
{
|
||||
/* Don't allow dup names */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
newarg = (structarg_t *)malloc(sizeof(structarg_t));
|
||||
for (i=0; i<pstruct->argcount; i++) {
|
||||
if (strcmp(pstruct->args[i]->name, arg->name) == 0) {
|
||||
/* Don't allow dup names */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
newarg = (structarg_t *)malloc(sizeof(structarg_t));
|
||||
|
||||
memcpy(newarg, arg, sizeof(structarg_t));
|
||||
memcpy(newarg, arg, sizeof(structarg_t));
|
||||
|
||||
if (pstruct->argcount == 0)
|
||||
{
|
||||
pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
|
||||
} else {
|
||||
pstruct->args = (structarg_t **)realloc(
|
||||
pstruct->args,
|
||||
sizeof(structarg_t *) * (pstruct->argcount + 1));
|
||||
}
|
||||
if (pstruct->argcount == 0) {
|
||||
pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
|
||||
} else {
|
||||
pstruct->args = (structarg_t **)realloc(
|
||||
pstruct->args,
|
||||
sizeof(structarg_t *) * (pstruct->argcount + 1));
|
||||
}
|
||||
|
||||
newarg->offs = pstruct->argcount * sizeof(cell);
|
||||
newarg->index = pstruct->argcount;
|
||||
pstruct->args[pstruct->argcount++] = newarg;
|
||||
newarg->offs = pstruct->argcount * sizeof(cell);
|
||||
newarg->index = pstruct->argcount;
|
||||
pstruct->args[pstruct->argcount++] = newarg;
|
||||
|
||||
return newarg;
|
||||
return newarg;
|
||||
}
|
||||
|
||||
void funcenums_free()
|
||||
{
|
||||
funcenum_t *e, *next;
|
||||
funcenum_t *e, *next;
|
||||
|
||||
e = firstenum;
|
||||
while (e)
|
||||
{
|
||||
functag_t *tag, *nexttag;
|
||||
tag = e->first;
|
||||
while (tag)
|
||||
{
|
||||
nexttag = tag->next;
|
||||
free(tag);
|
||||
tag = nexttag;
|
||||
}
|
||||
next = e->next;
|
||||
free(e);
|
||||
e = next;
|
||||
}
|
||||
e = firstenum;
|
||||
while (e) {
|
||||
functag_t *tag, *nexttag;
|
||||
tag = e->first;
|
||||
while (tag) {
|
||||
nexttag = tag->next;
|
||||
free(tag);
|
||||
tag = nexttag;
|
||||
}
|
||||
next = e->next;
|
||||
free(e);
|
||||
e = next;
|
||||
}
|
||||
|
||||
firstenum = NULL;
|
||||
lastenum = NULL;
|
||||
firstenum = NULL;
|
||||
lastenum = NULL;
|
||||
}
|
||||
|
||||
funcenum_t *funcenums_find_byval(int value)
|
||||
funcenum_t *funcenums_find_by_tag(int tag)
|
||||
{
|
||||
funcenum_t *e = firstenum;
|
||||
funcenum_t *e = firstenum;
|
||||
|
||||
while (e)
|
||||
{
|
||||
if (e->value == value)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
while (e) {
|
||||
if (e->tag == tag)
|
||||
return e;
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
funcenum_t *funcenums_add(const char *name)
|
||||
{
|
||||
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
|
||||
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
|
||||
|
||||
memset(e, 0, sizeof(funcenum_t));
|
||||
memset(e, 0, sizeof(funcenum_t));
|
||||
|
||||
if (firstenum == NULL)
|
||||
{
|
||||
firstenum = e;
|
||||
lastenum = e;
|
||||
} else {
|
||||
lastenum->next = e;
|
||||
lastenum = e;
|
||||
}
|
||||
if (!firstenum) {
|
||||
firstenum = e;
|
||||
lastenum = e;
|
||||
} else {
|
||||
lastenum->next = e;
|
||||
lastenum = e;
|
||||
}
|
||||
|
||||
strcpy(e->name, name);
|
||||
e->value = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG);
|
||||
strcpy(e->name, name);
|
||||
e->tag = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG);
|
||||
|
||||
return e;
|
||||
return e;
|
||||
}
|
||||
|
||||
funcenum_t *funcenum_for_symbol(symbol *sym)
|
||||
{
|
||||
functag_t ft;
|
||||
memset(&ft, 0, sizeof(ft));
|
||||
|
||||
ft.ret_tag = sym->tag;
|
||||
ft.usage = uPUBLIC & (sym->usage & uRETVALUE);
|
||||
ft.argcount = 0;
|
||||
ft.ommittable = FALSE;
|
||||
for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) {
|
||||
funcarg_t *dest = &ft.args[ft.argcount++];
|
||||
|
||||
dest->tagcount = arg->numtags;
|
||||
memcpy(dest->tags, arg->tags, arg->numtags * sizeof(int));
|
||||
|
||||
dest->dimcount = arg->numdim;
|
||||
memcpy(dest->dims, arg->dim, arg->numdim * sizeof(int));
|
||||
|
||||
dest->ident = arg->ident;
|
||||
dest->fconst = !!(arg->usage & uCONST);
|
||||
dest->ommittable = FALSE;
|
||||
}
|
||||
|
||||
char name[METHOD_NAMEMAX+1];
|
||||
UTIL_Format(name, sizeof(name), "::ft:%s:%d:%d", sym->name, sym->addr, sym->codeaddr);
|
||||
|
||||
funcenum_t *fe = funcenums_add(name);
|
||||
functags_add(fe, &ft);
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
||||
// Finds a functag that was created intrinsically.
|
||||
functag_t *functag_find_intrinsic(int tag)
|
||||
{
|
||||
funcenum_t *fe = funcenums_find_by_tag(tag);
|
||||
if (!fe)
|
||||
return NULL;
|
||||
|
||||
if (strncmp(fe->name, "::ft:", 5) != 0)
|
||||
return NULL;
|
||||
|
||||
assert(fe->first && fe->first == fe->last);
|
||||
return fe->first;
|
||||
}
|
||||
|
||||
functag_t *functags_add(funcenum_t *en, functag_t *src)
|
||||
{
|
||||
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
|
||||
|
||||
memcpy(t, src, sizeof(functag_t));
|
||||
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
|
||||
|
||||
memcpy(t, src, sizeof(functag_t));
|
||||
|
||||
t->next = NULL;
|
||||
t->next = NULL;
|
||||
|
||||
if (en->first == NULL)
|
||||
{
|
||||
en->first = t;
|
||||
en->last = t;
|
||||
} else {
|
||||
en->last->next = t;
|
||||
en->last = t;
|
||||
}
|
||||
if (en->first == NULL) {
|
||||
en->first = t;
|
||||
en->last = t;
|
||||
} else {
|
||||
en->last->next = t;
|
||||
en->last = t;
|
||||
}
|
||||
|
||||
return t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,16 +345,13 @@ void _heap_freeusage(memuse_list_t *heap, int dofree)
|
||||
{
|
||||
memuse_t *cur=heap->head;
|
||||
memuse_t *tmp;
|
||||
while (cur)
|
||||
{
|
||||
if (cur->type == MEMUSE_STATIC)
|
||||
{
|
||||
while (cur) {
|
||||
if (cur->type == MEMUSE_STATIC) {
|
||||
modheap((-1)*cur->size*sizeof(cell));
|
||||
} else {
|
||||
modheap_i();
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
if (dofree) {
|
||||
tmp=cur->prev;
|
||||
free(cur);
|
||||
cur=tmp;
|
||||
@ -336,9 +360,7 @@ void _heap_freeusage(memuse_list_t *heap, int dofree)
|
||||
}
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
heap->head=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void _stack_genusage(memuse_list_t *stack, int dofree)
|
||||
@ -575,3 +597,18 @@ int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len >= maxlength) {
|
||||
buffer[maxlength - 1] = '\0';
|
||||
return maxlength - 1;
|
||||
}
|
||||
return len;
|
||||
}
|
@ -31,7 +31,7 @@ typedef struct funcarg_s
|
||||
typedef struct functag_s
|
||||
{
|
||||
int ret_tag;
|
||||
int type;
|
||||
int usage;
|
||||
int argcount;
|
||||
int ommittable;
|
||||
funcarg_t args[sARGS_MAX];
|
||||
@ -40,8 +40,8 @@ typedef struct functag_s
|
||||
|
||||
typedef struct funcenum_s
|
||||
{
|
||||
int value;
|
||||
char name[sNAMEMAX+1];
|
||||
int tag;
|
||||
char name[METHOD_NAMEMAX+1];
|
||||
functag_t *first;
|
||||
functag_t *last;
|
||||
struct funcenum_s *next;
|
||||
@ -116,8 +116,10 @@ structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member);
|
||||
*/
|
||||
void funcenums_free();
|
||||
funcenum_t *funcenums_add(const char *name);
|
||||
funcenum_t *funcenums_find_byval(int value);
|
||||
funcenum_t *funcenums_find_by_tag(int tag);
|
||||
functag_t *functags_add(funcenum_t *en, functag_t *src);
|
||||
funcenum_t *funcenum_for_symbol(symbol *sym);
|
||||
functag_t *functag_find_intrinsic(int tag);
|
||||
|
||||
/**
|
||||
* Given a name or tag, find any extra weirdness it has associated with it.
|
||||
@ -167,4 +169,6 @@ void methodmaps_free();
|
||||
extern memuse_list_t *heapusage;
|
||||
extern memuse_list_t *stackusage;
|
||||
|
||||
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
|
||||
|
@ -1,119 +0,0 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Global (cross-module) variables.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for _MAX_PATH */
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
/* global variables
|
||||
*
|
||||
* All global variables that are shared amongst the compiler files are
|
||||
* declared here.
|
||||
*/
|
||||
SC_VDEFINE symbol loctab; /* local symbol table */
|
||||
SC_VDEFINE symbol glbtab; /* global symbol table */
|
||||
SC_VDEFINE cell *litq; /* the literal queue */
|
||||
SC_VDEFINE unsigned char pline[sLINEMAX+1]; /* the line read from the input file */
|
||||
SC_VDEFINE const unsigned char *lptr; /* points to the current position in "pline" */
|
||||
SC_VDEFINE constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */
|
||||
SC_VDEFINE constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */
|
||||
SC_VDEFINE constvalue *curlibrary = NULL; /* current library */
|
||||
SC_VDEFINE int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */
|
||||
SC_VDEFINE symbol *curfunc; /* pointer to current function */
|
||||
SC_VDEFINE char *inpfname; /* pointer to name of the file currently read from */
|
||||
SC_VDEFINE char outfname[_MAX_PATH]; /* intermediate (assembler) file name */
|
||||
SC_VDEFINE char binfname[_MAX_PATH]; /* binary file name */
|
||||
SC_VDEFINE char errfname[_MAX_PATH]; /* error file name */
|
||||
SC_VDEFINE char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/
|
||||
SC_VDEFINE char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */
|
||||
SC_VDEFINE int litidx = 0; /* index to literal table */
|
||||
SC_VDEFINE int litmax = sDEF_LITMAX; /* current size of the literal table */
|
||||
SC_VDEFINE int stgidx = 0; /* index to the staging buffer */
|
||||
SC_VDEFINE int sc_labnum = 0; /* number of (internal) labels */
|
||||
SC_VDEFINE int staging = 0; /* true if staging output */
|
||||
SC_VDEFINE cell declared = 0; /* number of local cells declared */
|
||||
SC_VDEFINE cell glb_declared=0; /* number of global cells declared */
|
||||
SC_VDEFINE cell code_idx = 0; /* number of bytes with generated code */
|
||||
SC_VDEFINE int ntv_funcid= 0; /* incremental number of native function */
|
||||
SC_VDEFINE int errnum = 0; /* number of errors */
|
||||
SC_VDEFINE int warnnum = 0; /* number of warnings */
|
||||
SC_VDEFINE int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */
|
||||
SC_VDEFINE int sc_packstr= FALSE; /* strings are packed by default? */
|
||||
SC_VDEFINE int sc_asmfile= FALSE; /* create .ASM file? */
|
||||
SC_VDEFINE int sc_listing= FALSE; /* create .LST file? */
|
||||
SC_VDEFINE int sc_compress=TRUE; /* compress bytecode? */
|
||||
SC_VDEFINE int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
|
||||
SC_VDEFINE int sc_dataalign=sizeof(cell);/* data alignment value */
|
||||
SC_VDEFINE int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
|
||||
SC_VDEFINE int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */
|
||||
SC_VDEFINE int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
SC_VDEFINE cell pc_stksize=sDEF_AMXSTACK;/* default stack size */
|
||||
SC_VDEFINE cell pc_amxlimit=0; /* default abstract machine size limit = none */
|
||||
SC_VDEFINE cell pc_amxram=0; /* default abstract machine data size limit = none */
|
||||
SC_VDEFINE int freading = FALSE; /* Is there an input file ready for reading? */
|
||||
SC_VDEFINE int fline = 0; /* the line number in the current file */
|
||||
SC_VDEFINE short fnumber = 0; /* the file number in the file table (debugging) */
|
||||
SC_VDEFINE short fcurrent= 0; /* current file being processed (debugging) */
|
||||
SC_VDEFINE short sc_intest=FALSE; /* true if inside a test */
|
||||
SC_VDEFINE int sideeffect= 0; /* true if an expression causes a side-effect */
|
||||
SC_VDEFINE int stmtindent= 0; /* current indent of the statement */
|
||||
SC_VDEFINE int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
|
||||
SC_VDEFINE int sc_tabsize=8; /* number of spaces that a TAB represents */
|
||||
SC_VDEFINE short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */
|
||||
SC_VDEFINE int sc_status; /* read/write status */
|
||||
SC_VDEFINE int sc_err_status;
|
||||
SC_VDEFINE int sc_rationaltag=0; /* tag for rational numbers */
|
||||
SC_VDEFINE int rational_digits=0; /* number of fractional digits */
|
||||
SC_VDEFINE int sc_allowproccall=0; /* allow/detect tagnames in lex() */
|
||||
SC_VDEFINE short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
|
||||
SC_VDEFINE char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */
|
||||
SC_VDEFINE int sc_curstates=0; /* ID of the current state list */
|
||||
SC_VDEFINE int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
|
||||
SC_VDEFINE int pc_memflags=0; /* special flags for the stack/heap usage */
|
||||
SC_VDEFINE int sc_showincludes=0; /* show include files */
|
||||
SC_VDEFINE int sc_require_newdecls=0; /* Require new-style declarations */
|
||||
|
||||
SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
|
||||
SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */
|
||||
|
||||
SC_VDEFINE FILE *inpf = NULL; /* file read from (source or include) */
|
||||
SC_VDEFINE FILE *inpf_org= NULL; /* main source file */
|
||||
SC_VDEFINE FILE *outf = NULL; /* (intermediate) text file written to */
|
||||
|
||||
SC_VDEFINE jmp_buf errbuf;
|
||||
|
||||
SC_VDEFINE HashTable *sp_Globals = NULL;
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
||||
#if defined __WATCOMC__ && !defined NDEBUG
|
||||
/* Watcom's CVPACK dislikes .OBJ files without functions */
|
||||
static int dummyfunc(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
119
sourcepawn/compiler/scvars.cpp
Normal file
119
sourcepawn/compiler/scvars.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Global (cross-module) variables.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for _MAX_PATH */
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
/* global variables
|
||||
*
|
||||
* All global variables that are shared amongst the compiler files are
|
||||
* declared here.
|
||||
*/
|
||||
symbol loctab; /* local symbol table */
|
||||
symbol glbtab; /* global symbol table */
|
||||
cell *litq; /* the literal queue */
|
||||
unsigned char pline[sLINEMAX+1]; /* the line read from the input file */
|
||||
const unsigned char *lptr; /* points to the current position in "pline" */
|
||||
constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */
|
||||
constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */
|
||||
constvalue *curlibrary = NULL; /* current library */
|
||||
int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */
|
||||
symbol *curfunc; /* pointer to current function */
|
||||
char *inpfname; /* pointer to name of the file currently read from */
|
||||
char outfname[_MAX_PATH]; /* intermediate (assembler) file name */
|
||||
char binfname[_MAX_PATH]; /* binary file name */
|
||||
char errfname[_MAX_PATH]; /* error file name */
|
||||
char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/
|
||||
char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */
|
||||
int litidx = 0; /* index to literal table */
|
||||
int litmax = sDEF_LITMAX; /* current size of the literal table */
|
||||
int stgidx = 0; /* index to the staging buffer */
|
||||
int sc_labnum = 0; /* number of (internal) labels */
|
||||
int staging = 0; /* true if staging output */
|
||||
cell declared = 0; /* number of local cells declared */
|
||||
cell glb_declared=0; /* number of global cells declared */
|
||||
cell code_idx = 0; /* number of bytes with generated code */
|
||||
int ntv_funcid= 0; /* incremental number of native function */
|
||||
int errnum = 0; /* number of errors */
|
||||
int warnnum = 0; /* number of warnings */
|
||||
int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */
|
||||
int sc_packstr= FALSE; /* strings are packed by default? */
|
||||
int sc_asmfile= FALSE; /* create .ASM file? */
|
||||
int sc_listing= FALSE; /* create .LST file? */
|
||||
int sc_compress=TRUE; /* compress bytecode? */
|
||||
int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
|
||||
int sc_dataalign=sizeof(cell);/* data alignment value */
|
||||
int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
|
||||
int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */
|
||||
int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
cell pc_stksize=sDEF_AMXSTACK;/* default stack size */
|
||||
cell pc_amxlimit=0; /* default abstract machine size limit = none */
|
||||
cell pc_amxram=0; /* default abstract machine data size limit = none */
|
||||
int freading = FALSE; /* Is there an input file ready for reading? */
|
||||
int fline = 0; /* the line number in the current file */
|
||||
short fnumber = 0; /* the file number in the file table (debugging) */
|
||||
short fcurrent= 0; /* current file being processed (debugging) */
|
||||
short sc_intest=FALSE; /* true if inside a test */
|
||||
int sideeffect= 0; /* true if an expression causes a side-effect */
|
||||
int stmtindent= 0; /* current indent of the statement */
|
||||
int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
|
||||
int sc_tabsize=8; /* number of spaces that a TAB represents */
|
||||
short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */
|
||||
int sc_status; /* read/write status */
|
||||
int sc_err_status;
|
||||
int sc_rationaltag=0; /* tag for rational numbers */
|
||||
int rational_digits=0; /* number of fractional digits */
|
||||
int sc_allowproccall=0; /* allow/detect tagnames in lex() */
|
||||
short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
|
||||
char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */
|
||||
int sc_curstates=0; /* ID of the current state list */
|
||||
int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
|
||||
int pc_memflags=0; /* special flags for the stack/heap usage */
|
||||
int sc_showincludes=0; /* show include files */
|
||||
int sc_require_newdecls=0; /* Require new-style declarations */
|
||||
|
||||
constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
|
||||
constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */
|
||||
|
||||
void *inpf = NULL; /* file read from (source or include) */
|
||||
void *inpf_org= NULL; /* main source file */
|
||||
void *outf = NULL; /* (intermediate) text file written to */
|
||||
|
||||
jmp_buf errbuf;
|
||||
|
||||
HashTable *sp_Globals = NULL;
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
int sc_makereport=FALSE; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
||||
#if defined __WATCOMC__ && !defined NDEBUG
|
||||
/* Watcom's CVPACK dislikes .OBJ files without functions */
|
||||
static int dummyfunc(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
@ -1,276 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sp_file.h"
|
||||
#include "memfile.h"
|
||||
|
||||
void *mf_open(const char *name);
|
||||
void mf_close(void *handle);
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_getpos(void *handle);
|
||||
int mf_setpos(void *handle, size_t pos);
|
||||
|
||||
sp_writefuncs_t cstd_funcs =
|
||||
{
|
||||
mf_open,
|
||||
mf_close,
|
||||
mf_write,
|
||||
mf_read,
|
||||
mf_getpos,
|
||||
mf_setpos
|
||||
};
|
||||
|
||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
|
||||
{
|
||||
sp_file_t file;
|
||||
sp_file_t *pFile;
|
||||
|
||||
if (!optfuncs)
|
||||
{
|
||||
optfuncs = &cstd_funcs;
|
||||
}
|
||||
|
||||
file.handle = optfuncs->fnOpen(name);
|
||||
if (!file.handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFile = (sp_file_t *)malloc(sizeof(sp_file_t));
|
||||
|
||||
pFile->handle = file.handle;
|
||||
memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t));
|
||||
pFile->curoffs = 0;
|
||||
pFile->header.magic = SPFILE_MAGIC;
|
||||
pFile->header.sections = 0;
|
||||
pFile->header.stringtab = 0;
|
||||
pFile->header.version = SPFILE_VERSION;
|
||||
pFile->header.imagesize = 0;
|
||||
pFile->header.disksize = 0;
|
||||
pFile->header.compression = SPFILE_COMPRESSION_NONE;
|
||||
pFile->header.dataoffs = 0;
|
||||
pFile->lastsection = 0;
|
||||
pFile->offsets = NULL;
|
||||
pFile->sections = NULL;
|
||||
pFile->state = -1;
|
||||
pFile->nametab = NULL;
|
||||
pFile->nametab_idx = 0;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
void spfw_destroy(sp_file_t *spf)
|
||||
{
|
||||
free(spf->sections);
|
||||
free(spf->nametab);
|
||||
free(spf->offsets);
|
||||
spf->funcs.fnClose(spf->handle);
|
||||
free(spf);
|
||||
}
|
||||
|
||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name)
|
||||
{
|
||||
size_t namelen;
|
||||
uint8_t s;
|
||||
if (spf->state != -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
namelen = strlen(name) + 1;
|
||||
|
||||
if (spf->header.sections == 0)
|
||||
{
|
||||
/** allocate for first section */
|
||||
spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t));
|
||||
spf->offsets = (size_t *)malloc(sizeof(size_t));
|
||||
spf->nametab = (char *)malloc(namelen);
|
||||
} else {
|
||||
uint16_t num = spf->header.sections + 1;
|
||||
spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num);
|
||||
spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num);
|
||||
spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen);
|
||||
}
|
||||
|
||||
s = spf->header.sections;
|
||||
|
||||
spf->sections[s].nameoffs = spf->nametab_idx;
|
||||
/**
|
||||
* "fix" offset will be the second uint2 slot, which is after the previous sections after the header.
|
||||
*/
|
||||
spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t);
|
||||
strcpy(&spf->nametab[spf->nametab_idx], name);
|
||||
spf->nametab_idx += namelen;
|
||||
|
||||
return ++spf->header.sections;
|
||||
}
|
||||
|
||||
int spfw_finalize_header(sp_file_t *spf)
|
||||
{
|
||||
uint32_t size;
|
||||
if (spf->state != -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = sizeof(sp_file_section_t) * spf->header.sections;
|
||||
|
||||
spf->header.stringtab = sizeof(spf->header) + size;
|
||||
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx;
|
||||
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) !=
|
||||
spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->lastsection = spf->curoffs;
|
||||
spf->state++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spfw_next_section(sp_file_t *spf)
|
||||
{
|
||||
uint8_t s;
|
||||
uint32_t rest[2];
|
||||
|
||||
if (spf->state < 0 || spf->state > spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spf->state == (int)spf->header.sections)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = (uint8_t)spf->state;
|
||||
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->offsets[s]);
|
||||
|
||||
rest[0] = spf->lastsection;
|
||||
rest[1] = spf->curoffs - spf->lastsection;
|
||||
if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
spf->funcs.fnSetPos(spf->handle, spf->curoffs);
|
||||
spf->lastsection = spf->curoffs;
|
||||
|
||||
spf->state++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int spfw_finalize_all(sp_file_t *spf)
|
||||
{
|
||||
uint8_t offs;
|
||||
|
||||
if (spf->state < spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
offs = offsetof(sp_file_hdr_t, imagesize);
|
||||
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, offs);
|
||||
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->header.imagesize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* More memory file operations
|
||||
*/
|
||||
|
||||
void *mf_open(const char *name)
|
||||
{
|
||||
return memfile_creat(name, 1024);
|
||||
}
|
||||
|
||||
void mf_close(void *handle)
|
||||
{
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
}
|
||||
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memfile_write((memfile_t *)handle, buf, size*count))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return memfile_read((memfile_t *)handle, buf, size*count) / count;
|
||||
}
|
||||
|
||||
size_t mf_getpos(void *handle)
|
||||
{
|
||||
return (long)memfile_tell((memfile_t *)handle);
|
||||
}
|
||||
|
||||
int mf_setpos(void *handle, size_t pos)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, (long)pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if UNUSED_FOR_NOW
|
||||
/**
|
||||
* Default file operations...
|
||||
* Based on C standard library calls.
|
||||
*/
|
||||
|
||||
void *fp_open(const char *name)
|
||||
{
|
||||
return fopen(name, "wb");
|
||||
}
|
||||
|
||||
void fp_close(void *handle)
|
||||
{
|
||||
fclose((FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_write(const void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return fwrite(buf, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_read(void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return fread(buf, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_getpos(void *handle)
|
||||
{
|
||||
return (size_t)ftell((FILE *)handle);
|
||||
}
|
||||
|
||||
int fp_setpos(void *handle, size_t pos)
|
||||
{
|
||||
return fseek((FILE *)handle, (long)pos, SEEK_SET);
|
||||
}
|
||||
#endif
|
213
sourcepawn/compiler/sp_file.cpp
Normal file
213
sourcepawn/compiler/sp_file.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sp_file.h"
|
||||
#include "memfile.h"
|
||||
|
||||
void *mf_open(const char *name);
|
||||
void mf_close(void *handle);
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_getpos(void *handle);
|
||||
int mf_setpos(void *handle, size_t pos);
|
||||
|
||||
sp_writefuncs_t cstd_funcs =
|
||||
{
|
||||
mf_open,
|
||||
mf_close,
|
||||
mf_write,
|
||||
mf_read,
|
||||
mf_getpos,
|
||||
mf_setpos
|
||||
};
|
||||
|
||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
|
||||
{
|
||||
sp_file_t file;
|
||||
sp_file_t *pFile;
|
||||
|
||||
if (!optfuncs)
|
||||
optfuncs = &cstd_funcs;
|
||||
|
||||
file.handle = optfuncs->fnOpen(name);
|
||||
if (!file.handle)
|
||||
return NULL;
|
||||
|
||||
pFile = (sp_file_t *)malloc(sizeof(sp_file_t));
|
||||
|
||||
pFile->handle = file.handle;
|
||||
memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t));
|
||||
pFile->curoffs = 0;
|
||||
pFile->header.magic = SPFILE_MAGIC;
|
||||
pFile->header.sections = 0;
|
||||
pFile->header.stringtab = 0;
|
||||
pFile->header.version = SPFILE_VERSION;
|
||||
pFile->header.imagesize = 0;
|
||||
pFile->header.disksize = 0;
|
||||
pFile->header.compression = SPFILE_COMPRESSION_NONE;
|
||||
pFile->header.dataoffs = 0;
|
||||
pFile->lastsection = 0;
|
||||
pFile->offsets = NULL;
|
||||
pFile->sections = NULL;
|
||||
pFile->state = -1;
|
||||
pFile->nametab = NULL;
|
||||
pFile->nametab_idx = 0;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
void spfw_destroy(sp_file_t *spf)
|
||||
{
|
||||
free(spf->sections);
|
||||
free(spf->nametab);
|
||||
free(spf->offsets);
|
||||
spf->funcs.fnClose(spf->handle);
|
||||
free(spf);
|
||||
}
|
||||
|
||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name)
|
||||
{
|
||||
size_t namelen;
|
||||
uint8_t s;
|
||||
if (spf->state != -1)
|
||||
return 0;
|
||||
|
||||
namelen = strlen(name) + 1;
|
||||
|
||||
if (spf->header.sections == 0)
|
||||
{
|
||||
/** allocate for first section */
|
||||
spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t));
|
||||
spf->offsets = (size_t *)malloc(sizeof(size_t));
|
||||
spf->nametab = (char *)malloc(namelen);
|
||||
} else {
|
||||
uint16_t num = spf->header.sections + 1;
|
||||
spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num);
|
||||
spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num);
|
||||
spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen);
|
||||
}
|
||||
|
||||
s = spf->header.sections;
|
||||
|
||||
spf->sections[s].nameoffs = spf->nametab_idx;
|
||||
/**
|
||||
* "fix" offset will be the second uint2 slot, which is after the previous sections after the header.
|
||||
*/
|
||||
spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t);
|
||||
strcpy(&spf->nametab[spf->nametab_idx], name);
|
||||
spf->nametab_idx += namelen;
|
||||
|
||||
return ++spf->header.sections;
|
||||
}
|
||||
|
||||
int spfw_finalize_header(sp_file_t *spf)
|
||||
{
|
||||
uint32_t size;
|
||||
if (spf->state != -1)
|
||||
return -1;
|
||||
|
||||
size = sizeof(sp_file_section_t) * spf->header.sections;
|
||||
|
||||
spf->header.stringtab = sizeof(spf->header) + size;
|
||||
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx;
|
||||
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
|
||||
return -1;
|
||||
if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) !=
|
||||
spf->header.sections)
|
||||
return -1;
|
||||
if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx)
|
||||
return -1;
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->lastsection = spf->curoffs;
|
||||
spf->state++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spfw_next_section(sp_file_t *spf)
|
||||
{
|
||||
uint8_t s;
|
||||
uint32_t rest[2];
|
||||
|
||||
if (spf->state < 0 || spf->state > spf->header.sections)
|
||||
return -1;
|
||||
|
||||
if (spf->state == (int)spf->header.sections)
|
||||
return 0;
|
||||
|
||||
s = (uint8_t)spf->state;
|
||||
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->offsets[s]);
|
||||
|
||||
rest[0] = spf->lastsection;
|
||||
rest[1] = spf->curoffs - spf->lastsection;
|
||||
if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2)
|
||||
return -1;
|
||||
|
||||
spf->funcs.fnSetPos(spf->handle, spf->curoffs);
|
||||
spf->lastsection = spf->curoffs;
|
||||
|
||||
spf->state++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int spfw_finalize_all(sp_file_t *spf)
|
||||
{
|
||||
uint8_t offs;
|
||||
|
||||
if (spf->state < spf->header.sections)
|
||||
return -1;
|
||||
|
||||
offs = offsetof(sp_file_hdr_t, imagesize);
|
||||
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, offs);
|
||||
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->header.imagesize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* More memory file operations
|
||||
*/
|
||||
|
||||
void *mf_open(const char *name)
|
||||
{
|
||||
return memfile_creat(name, 1024);
|
||||
}
|
||||
|
||||
void mf_close(void *handle)
|
||||
{
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
}
|
||||
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (memfile_write((memfile_t *)handle, buf, size*count))
|
||||
return count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return memfile_read((memfile_t *)handle, buf, size*count) / count;
|
||||
}
|
||||
|
||||
size_t mf_getpos(void *handle)
|
||||
{
|
||||
return (long)memfile_tell((memfile_t *)handle);
|
||||
}
|
||||
|
||||
int mf_setpos(void *handle, size_t pos)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, (long)pos);
|
||||
return 1;
|
||||
}
|
||||
|
@ -8,30 +8,30 @@
|
||||
*/
|
||||
typedef struct sp_writefuncs_s
|
||||
{
|
||||
void *(*fnOpen)(const char *); /* filename, returns handle */
|
||||
void (*fnClose)(void *); /* handle */
|
||||
/* buffer, size, count, handle, returns count written */
|
||||
size_t (*fnWrite)(const void *, size_t, size_t, void *);
|
||||
/* buffer, size, count, handle, returns count read */
|
||||
size_t (*fnRead)(void *, size_t, size_t, void *);
|
||||
/* returns current position from start */
|
||||
size_t (*fnGetPos)(void *);
|
||||
/* sets current position from start, return 0 for success, nonzero for error */
|
||||
int (*fnSetPos)(void *, size_t);
|
||||
void *(*fnOpen)(const char *); /* filename, returns handle */
|
||||
void (*fnClose)(void *); /* handle */
|
||||
/* buffer, size, count, handle, returns count written */
|
||||
size_t (*fnWrite)(const void *, size_t, size_t, void *);
|
||||
/* buffer, size, count, handle, returns count read */
|
||||
size_t (*fnRead)(void *, size_t, size_t, void *);
|
||||
/* returns current position from start */
|
||||
size_t (*fnGetPos)(void *);
|
||||
/* sets current position from start, return 0 for success, nonzero for error */
|
||||
int (*fnSetPos)(void *, size_t);
|
||||
} sp_writefuncs_t;
|
||||
|
||||
typedef struct sp_file_s
|
||||
{
|
||||
sp_file_hdr_t header;
|
||||
sp_file_section_t *sections;
|
||||
size_t *offsets;
|
||||
sp_writefuncs_t funcs;
|
||||
size_t lastsection;
|
||||
size_t curoffs;
|
||||
void *handle;
|
||||
int state;
|
||||
char *nametab;
|
||||
size_t nametab_idx;
|
||||
sp_file_hdr_t header;
|
||||
sp_file_section_t *sections;
|
||||
size_t *offsets;
|
||||
sp_writefuncs_t funcs;
|
||||
size_t lastsection;
|
||||
size_t curoffs;
|
||||
void *handle;
|
||||
int state;
|
||||
char *nametab;
|
||||
size_t nametab_idx;
|
||||
} sp_file_t;
|
||||
|
||||
/**
|
||||
|
@ -1,230 +0,0 @@
|
||||
/* vim: set ts=4 sw=4 tw=99 et: */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sp_file_headers.h"
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
SC_FUNC uint32_t
|
||||
NameHash(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
const uint8_t *data = (uint8_t *)str;
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
|
||||
#undef get16bits
|
||||
}
|
||||
|
||||
SC_FUNC HashTable *NewHashTable()
|
||||
{
|
||||
HashTable *ht = (HashTable*)malloc(sizeof(HashTable));
|
||||
if (!ht)
|
||||
return ht;
|
||||
ht->buckets = (HashEntry **)calloc(32, sizeof(HashEntry *));
|
||||
if (!ht->buckets) {
|
||||
free(ht);
|
||||
return NULL;
|
||||
}
|
||||
ht->nbuckets = 32;
|
||||
ht->nused = 0;
|
||||
ht->bucketmask = 32 - 1;
|
||||
return ht;
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
DestroyHashTable(HashTable *ht)
|
||||
{
|
||||
uint32_t i;
|
||||
if (!ht)
|
||||
return;
|
||||
for (i = 0; i < ht->nbuckets; i++) {
|
||||
HashEntry *he = ht->buckets[i];
|
||||
while (he != NULL) {
|
||||
HashEntry *next = he->next;
|
||||
free(he);
|
||||
he = next;
|
||||
}
|
||||
}
|
||||
free(ht->buckets);
|
||||
free(ht);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *
|
||||
FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
|
||||
int *cmptag)
|
||||
{
|
||||
int count=0;
|
||||
symbol *firstmatch=NULL;
|
||||
uint32_t hash = NameHash(name);
|
||||
uint32_t bucket = hash & ht->bucketmask;
|
||||
HashEntry *he = ht->buckets[bucket];
|
||||
|
||||
assert(cmptag!=NULL);
|
||||
|
||||
while (he != NULL) {
|
||||
symbol *sym = he->sym;
|
||||
if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
|
||||
(sym->fnumber<0 || sym->fnumber==fnumber) &&
|
||||
(strcmp(sym->name, name) == 0))
|
||||
{
|
||||
/* return closest match or first match; count number of matches */
|
||||
if (firstmatch==NULL)
|
||||
firstmatch=sym;
|
||||
if (*cmptag==0)
|
||||
count++;
|
||||
if (*cmptag==sym->tag) {
|
||||
*cmptag=1; /* good match found, set number of matches to 1 */
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
he = he->next;
|
||||
}
|
||||
|
||||
if (firstmatch!=NULL)
|
||||
*cmptag=count;
|
||||
return firstmatch;
|
||||
}
|
||||
|
||||
SC_FUNC symbol *
|
||||
FindInHashTable(HashTable *ht, const char *name, int fnumber)
|
||||
{
|
||||
uint32_t hash = NameHash(name);
|
||||
uint32_t bucket = hash & ht->bucketmask;
|
||||
HashEntry *he = ht->buckets[bucket];
|
||||
|
||||
while (he != NULL) {
|
||||
symbol *sym = he->sym;
|
||||
if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
|
||||
(sym->fnumber<0 || sym->fnumber==fnumber) &&
|
||||
(strcmp(sym->name, name) == 0))
|
||||
{
|
||||
return sym;
|
||||
}
|
||||
he = he->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ResizeHashTable(HashTable *ht)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t xnbuckets = ht->nbuckets * 2;
|
||||
uint32_t xbucketmask = xnbuckets - 1;
|
||||
HashEntry **xbuckets = (HashEntry **)calloc(xnbuckets, sizeof(HashEntry*));
|
||||
if (!xbuckets)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ht->nbuckets; i++) {
|
||||
HashEntry *he = ht->buckets[i];
|
||||
while (he != NULL) {
|
||||
HashEntry *next = he->next;
|
||||
uint32_t bucket = he->sym->hash & xbucketmask;
|
||||
he->next = xbuckets[bucket];
|
||||
xbuckets[bucket] = he;
|
||||
he = next;
|
||||
}
|
||||
}
|
||||
free(ht->buckets);
|
||||
ht->buckets = xbuckets;
|
||||
ht->nbuckets = xnbuckets;
|
||||
ht->bucketmask = xbucketmask;
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
AddToHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
uint32_t bucket = sym->hash & ht->bucketmask;
|
||||
HashEntry **hep, *he;
|
||||
|
||||
hep = &ht->buckets[bucket];
|
||||
while (*hep) {
|
||||
assert((*hep)->sym != sym);
|
||||
hep = &(*hep)->next;
|
||||
}
|
||||
|
||||
he = (HashEntry *)malloc(sizeof(HashEntry));
|
||||
if (!he)
|
||||
error(163);
|
||||
he->sym = sym;
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
ht->nused++;
|
||||
|
||||
if (ht->nused > ht->nbuckets && ht->nbuckets <= INT_MAX / 2)
|
||||
ResizeHashTable(ht);
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
RemoveFromHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
uint32_t bucket = sym->hash & ht->bucketmask;
|
||||
HashEntry **hep = &ht->buckets[bucket];
|
||||
HashEntry *he = *hep;
|
||||
|
||||
while (he != NULL) {
|
||||
if (he->sym == sym) {
|
||||
*hep = he->next;
|
||||
free(he);
|
||||
ht->nused--;
|
||||
return;
|
||||
}
|
||||
hep = &he->next;
|
||||
he = *hep;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
130
sourcepawn/compiler/sp_symhash.cpp
Normal file
130
sourcepawn/compiler/sp_symhash.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
// vim: set ts=8 sts=2 sw=2 tw=99 et:
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sp_file_headers.h"
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
#include <am-hashtable.h>
|
||||
|
||||
struct NameAndScope
|
||||
{
|
||||
const char *name;
|
||||
int fnumber;
|
||||
int *cmptag;
|
||||
mutable symbol *matched;
|
||||
mutable int count;
|
||||
|
||||
NameAndScope(const char *name, int fnumber, int *cmptag)
|
||||
: name(name),
|
||||
fnumber(fnumber),
|
||||
cmptag(cmptag),
|
||||
matched(nullptr),
|
||||
count(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct SymbolHashPolicy
|
||||
{
|
||||
typedef symbol *Payload;
|
||||
|
||||
// Everything with the same name has the same hash, because the compiler
|
||||
// wants to know two names that have the same tag for some reason. Even
|
||||
// so, we can't be that accurate, since we might match the right symbol
|
||||
// very early.
|
||||
static uint32_t hash(const NameAndScope &key) {
|
||||
return ke::HashCharSequence(key.name, strlen(key.name));
|
||||
}
|
||||
static uint32_t hash(const symbol *s) {
|
||||
return ke::HashCharSequence(s->name, strlen(s->name));
|
||||
}
|
||||
|
||||
static bool matches(const NameAndScope &key, symbol *sym) {
|
||||
if (sym->parent && sym->ident != iCONSTEXPR)
|
||||
return false;
|
||||
if (sym->fnumber >= 0 && sym->fnumber != key.fnumber)
|
||||
return false;
|
||||
if (strcmp(key.name, sym->name) != 0)
|
||||
return false;
|
||||
if (key.cmptag) {
|
||||
key.count++;
|
||||
key.matched = sym;
|
||||
if (*key.cmptag != sym->tag)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool matches(const symbol *key, symbol *sym) {
|
||||
return key == sym;
|
||||
}
|
||||
};
|
||||
|
||||
struct HashTable : public ke::HashTable<SymbolHashPolicy>
|
||||
{
|
||||
};
|
||||
|
||||
uint32_t
|
||||
NameHash(const char *str)
|
||||
{
|
||||
return ke::HashCharSequence(str, strlen(str));
|
||||
}
|
||||
|
||||
HashTable *NewHashTable()
|
||||
{
|
||||
HashTable *ht = new HashTable();
|
||||
if (!ht->init()) {
|
||||
delete ht;
|
||||
return nullptr;
|
||||
}
|
||||
return ht;
|
||||
}
|
||||
|
||||
void
|
||||
DestroyHashTable(HashTable *ht)
|
||||
{
|
||||
delete ht;
|
||||
}
|
||||
|
||||
symbol *
|
||||
FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, int *cmptag)
|
||||
{
|
||||
NameAndScope nas(name, fnumber, cmptag);
|
||||
HashTable::Result r = ht->find(nas);
|
||||
if (!r.found()) {
|
||||
if (nas.matched) {
|
||||
*cmptag = nas.count;
|
||||
return nas.matched;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*cmptag = 1;
|
||||
return *r;
|
||||
}
|
||||
|
||||
symbol *
|
||||
FindInHashTable(HashTable *ht, const char *name, int fnumber)
|
||||
{
|
||||
NameAndScope nas(name, fnumber, nullptr);
|
||||
HashTable::Result r = ht->find(nas);
|
||||
if (!r.found())
|
||||
return nullptr;
|
||||
return *r;
|
||||
}
|
||||
|
||||
void
|
||||
AddToHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
HashTable::Insert i = ht->findForAdd(sym);
|
||||
assert(!i.found());
|
||||
ht->add(i, sym);
|
||||
}
|
||||
|
||||
void
|
||||
RemoveFromHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
HashTable::Result r = ht->find(sym);
|
||||
assert(r.found());
|
||||
ht->remove(r);
|
||||
}
|
@ -1,28 +1,18 @@
|
||||
/* vim: set ts=4 sw=4 tw=99 et: */
|
||||
#ifndef _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
#define _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
|
||||
SC_FUNC uint32_t NameHash(const char *str);
|
||||
|
||||
typedef struct HashEntry {
|
||||
symbol *sym;
|
||||
struct HashEntry *next;
|
||||
} HashEntry;
|
||||
|
||||
struct HashTable {
|
||||
uint32_t nbuckets;
|
||||
uint32_t nused;
|
||||
uint32_t bucketmask;
|
||||
HashEntry **buckets;
|
||||
};
|
||||
|
||||
SC_FUNC HashTable *NewHashTable();
|
||||
SC_FUNC void DestroyHashTable(HashTable *ht);
|
||||
SC_FUNC void AddToHashTable(HashTable *ht, symbol *sym);
|
||||
SC_FUNC void RemoveFromHashTable(HashTable *ht, symbol *sym);
|
||||
SC_FUNC symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber);
|
||||
SC_FUNC symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
|
||||
int *cmptag);
|
||||
|
||||
#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */
|
||||
|
||||
/* vim: set ts=4 sw=4 tw=99 et: */
|
||||
#ifndef _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
#define _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
|
||||
uint32_t NameHash(const char *str);
|
||||
|
||||
struct HashTable;
|
||||
|
||||
HashTable *NewHashTable();
|
||||
void DestroyHashTable(HashTable *ht);
|
||||
void AddToHashTable(HashTable *ht, symbol *sym);
|
||||
void RemoveFromHashTable(HashTable *ht, symbol *sym);
|
||||
symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber);
|
||||
symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
|
||||
int *cmptag);
|
||||
|
||||
#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */
|
||||
|
||||
|
20
sourcepawn/compiler/tests/ok-trailing-comma-in-literal.sp
Normal file
20
sourcepawn/compiler/tests/ok-trailing-comma-in-literal.sp
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
new String:oldArray[][] =
|
||||
{
|
||||
"string",
|
||||
"string2",
|
||||
};
|
||||
|
||||
char newArray[][] =
|
||||
{
|
||||
"another string",
|
||||
"more strings",
|
||||
};
|
||||
|
||||
native Print( const String:string[] );
|
||||
|
||||
public OnPluginStart()
|
||||
{
|
||||
Print( oldArray[ 0 ] );
|
||||
Print( newArray[ 0 ] );
|
||||
}
|
26
sourcepawn/compiler/tests/ok-typedef-func-chars.sp
Normal file
26
sourcepawn/compiler/tests/ok-typedef-func-chars.sp
Normal file
@ -0,0 +1,26 @@
|
||||
enum Action: {}
|
||||
functag public Action:OldFuncTag( String:someString[128] );
|
||||
typedef NewFuncTag = function Action ( char someString[128] );
|
||||
|
||||
native UseOldFuncTag( OldFuncTag func );
|
||||
native UseNewFuncTag( NewFuncTag func );
|
||||
|
||||
public OnPluginStart()
|
||||
{
|
||||
// fine
|
||||
UseOldFuncTag( MyOldFunc );
|
||||
// also fine
|
||||
UseOldFuncTag( MyNewFunc );
|
||||
|
||||
// error 100: function prototypes do not match
|
||||
UseNewFuncTag( MyOldFunc );
|
||||
// error 100: function prototypes do not match
|
||||
UseNewFuncTag( MyNewFunc );
|
||||
}
|
||||
|
||||
public Action:MyOldFunc( String:someString[128] )
|
||||
{
|
||||
}
|
||||
public Action MyNewFunc( char someString[128] )
|
||||
{
|
||||
}
|
164
sourcepawn/include/smx/smx-headers.h
Normal file
164
sourcepawn/include/smx/smx-headers.h
Normal file
@ -0,0 +1,164 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
// =============================================================================
|
||||
// SourcePawn
|
||||
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
// =============================================================================
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||
// Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <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>.
|
||||
|
||||
#ifndef _INCLUDE_SPFILE_HEADERS_H
|
||||
#define _INCLUDE_SPFILE_HEADERS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace sp {
|
||||
|
||||
struct SmxConsts
|
||||
{
|
||||
// SourcePawn File Format (SPFF) magic number.
|
||||
static const uint32_t FILE_MAGIC = 0x53504646;
|
||||
|
||||
// File format verison number.
|
||||
// 0x0101 - Initial version used by spcomp1 and SourceMod 1.0.
|
||||
// 0x0102 - Used by spcomp1 and SourceMod 1.1+.
|
||||
// 0x0103 - Used by SourceMod 1.7+.
|
||||
// 0x0200 - Used by spcomp2.
|
||||
//
|
||||
// The major version bits (8-15) indicate a product number. Consumers should
|
||||
// reject any version for a different product.
|
||||
//
|
||||
// The minor version bits (0-7) indicate a compatibility revision. Any minor
|
||||
// version higher than the current version should be rejected.
|
||||
static const uint16_t SP1_VERSION_MIN = 0x0101;
|
||||
static const uint16_t SP1_VERSION_MAX = 0x0103;
|
||||
static const uint16_t SP2_VERSION_MIN = 0x0200;
|
||||
static const uint16_t SP2_VERSION_MAX = 0x0200;
|
||||
|
||||
// Compression types.
|
||||
static const uint8_t FILE_COMPRESSION_NONE = 0;
|
||||
static const uint8_t FILE_COMPRESSION_GZ = 1;
|
||||
|
||||
// SourcePawn 1.0.
|
||||
static const uint8_t CODE_VERSION_JIT1 = 9;
|
||||
|
||||
// SourcePawn 1.1.
|
||||
static const uint8_t CODE_VERSION_JIT2 = 10;
|
||||
|
||||
// For SP1 consumers, the container version may not be checked, but usually
|
||||
// the code version is. This constant allows newer containers to be rejected
|
||||
// in those applications.
|
||||
static const uint8_t CODE_VERSION_REJECT = 0x7F;
|
||||
};
|
||||
|
||||
// These structures are byte-packed.
|
||||
#if defined __GNUC__
|
||||
# pragma pack(1)
|
||||
#else
|
||||
# pragma pack(push)
|
||||
# pragma pack(1)
|
||||
#endif
|
||||
|
||||
// The very first bytes in a .smx file. The .smx file format is a container for
|
||||
// arbitrary sections, though to actually load a .smx file certain sections
|
||||
// must be present. The on-disk format has four major regions, in order:
|
||||
// 1. The header (sp_file_hdr_t).
|
||||
// 2. The section list (sp_file_section_t).
|
||||
// 3. The string table.
|
||||
// 4. The section contents.
|
||||
//
|
||||
// Although any part of the file after the header can be compressed, by default
|
||||
// only the section contents are, and the section list and string table are not.
|
||||
typedef struct sp_file_hdr_s
|
||||
{
|
||||
// Magic number and version number.
|
||||
uint32_t magic;
|
||||
uint16_t version;
|
||||
|
||||
// Compression algorithm. If the file is not compressed, then imagesize and
|
||||
// disksize are the same value, and dataoffs is 0.
|
||||
//
|
||||
// The start of the compressed region is indicated by dataoffs. The length
|
||||
// of the compressed region is (disksize - dataoffs). The amount of memory
|
||||
// required to hold the decompressed bytes is (imagesize - dataoffs). The
|
||||
// compressed region should be expanded in-place. That is, bytes before
|
||||
// "dataoffs" should be retained, and the decompressed region should be
|
||||
// appended.
|
||||
//
|
||||
// |imagesize| is the amount of memory required to hold the entire container
|
||||
// in memory.
|
||||
//
|
||||
// Note: This scheme may seem odd. It's a combination of historical debt and
|
||||
// previously unspecified behavior. The original .amx file format contained
|
||||
// an on-disk structure that supported an endian-agnostic variable-length
|
||||
// encoding of its data section, and this structure was loaded directly into
|
||||
// memory and used as the VM context. AMX Mod X later developed a container
|
||||
// format called ".amxx" as a "universal binary" for 32-bit and 64-bit
|
||||
// plugins. This format dropped compact encoding, but supported gzip. The
|
||||
// disksize/imagesize oddness made its way to this file format. When .smx
|
||||
// was created for SourceMod, it persisted even though AMX was dropped
|
||||
// entirely. So it goes.
|
||||
uint8_t compression;
|
||||
uint32_t disksize;
|
||||
uint32_t imagesize;
|
||||
|
||||
// Number of named file sections.
|
||||
uint8_t sections;
|
||||
|
||||
// Offset to the string table. Each string is null-terminated. The string
|
||||
// table is only used for strings related to parsing the container itself.
|
||||
// For SourcePawn, a separate ".names" section exists for Pawn-specific data.
|
||||
uint32_t stringtab;
|
||||
|
||||
// Offset to where compression begins.
|
||||
uint32_t dataoffs;
|
||||
} sp_file_hdr_t;
|
||||
|
||||
// Each section is written immediately after the header.
|
||||
typedef struct sp_file_section_s
|
||||
{
|
||||
uint32_t nameoffs; /**< Offset into the string table. */
|
||||
uint32_t dataoffs; /**< Offset into the file for the section contents. */
|
||||
uint32_t size; /**< Size of this section's contents. */
|
||||
} sp_file_section_t;
|
||||
|
||||
// Code section. This is used only in SP1, but is emitted by default for legacy
|
||||
// systems which check |codeversion| but not the SMX file version.
|
||||
typedef struct sp_file_code_s
|
||||
{
|
||||
uint32_t codesize; /**< Size of the code section. */
|
||||
uint8_t cellsize; /**< Cellsize in bytes. */
|
||||
uint8_t codeversion; /**< Version of opcodes supported. */
|
||||
uint16_t flags; /**< Flags. */
|
||||
uint32_t main; /**< Address to "main". */
|
||||
uint32_t code; /**< Offset to bytecode, relative to the start of this section. */
|
||||
} sp_file_code_t;
|
||||
|
||||
#if defined __GNUC__
|
||||
# pragma pack()
|
||||
#else
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
} // namespace sp
|
||||
|
||||
#endif //_INCLUDE_SPFILE_HEADERS_H
|
266
sourcepawn/include/smx/smx-v1-opcodes.h
Normal file
266
sourcepawn/include/smx/smx-v1-opcodes.h
Normal file
@ -0,0 +1,266 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
// =============================================================================
|
||||
// SourcePawn
|
||||
// Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved.
|
||||
// =============================================================================
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||
// Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <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>.
|
||||
|
||||
#ifndef _INCLUDE_SPFILE_HEADERS_v1_opcodes_H
|
||||
#define _INCLUDE_SPFILE_HEADERS_v1_opcodes_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace sp {
|
||||
|
||||
// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few,
|
||||
// if they could, make little sense in the context of a JIT and could not
|
||||
// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively,
|
||||
// the code emitter and peephole optimizer) are not necessarily ever generated.
|
||||
// For example, lref.pri and lref.alt would be used if a reference could be
|
||||
// stored in the global scope; but they can't, so they are unreachable.
|
||||
//
|
||||
// Most opcodes have been manually verified. A few have not, as they are only
|
||||
// produced by the peephole optimizer, or not produced at all, or eliminated
|
||||
// during optimization. We generate them anyway, just in case, but they have
|
||||
// not been tested.
|
||||
// lref.s.alt (phopt only)
|
||||
// stor.alt (never)
|
||||
// stor.s.alt (never)
|
||||
// sref.s.alt (never)
|
||||
// lidx.b (phopt only, probably impossible)
|
||||
// idxaddr.b (phopt only, looks difficult)
|
||||
// move.pri (eliminated in phopt)
|
||||
// shl.c.pri (eliminated in phopt)
|
||||
// shl.c.alt (eliminated in phopt)
|
||||
// shr.c.pri (eliminated in phopt)
|
||||
// shr.c.alt (eliminated in phopt)
|
||||
// eq.c.alt (never)
|
||||
// inc.alt (never)
|
||||
// dec.alt (never)
|
||||
// sdiv (never)
|
||||
// nop (never in function bodies)
|
||||
//
|
||||
// Additionally, some opcodes which were supported in the earlier JIT are no
|
||||
// longer supported because of the above:
|
||||
// lref.pri/alt
|
||||
// sref.pri/alt
|
||||
// sign.pri/alt
|
||||
|
||||
#define OPCODE_LIST(_) \
|
||||
_(NONE, "none") \
|
||||
_(LOAD_PRI, "load.pri") \
|
||||
_(LOAD_ALT, "load.alt") \
|
||||
_(LOAD_S_PRI, "load.s.pri") \
|
||||
_(LOAD_S_ALT, "load.s.alt") \
|
||||
_(UNGEN_LREF_PRI, "lref.pri") \
|
||||
_(UNGEN_LREF_ALT, "lref.alt") \
|
||||
_(LREF_S_PRI, "lref.s.pri") \
|
||||
_(LREF_S_ALT, "lref.s.alt") \
|
||||
_(LOAD_I, "load.i") \
|
||||
_(LODB_I, "lodb.i") \
|
||||
_(CONST_PRI, "const.pri") \
|
||||
_(CONST_ALT, "const.alt") \
|
||||
_(ADDR_PRI, "addr.pri") \
|
||||
_(ADDR_ALT, "addr.alt") \
|
||||
_(STOR_PRI, "stor.pri") \
|
||||
_(STOR_ALT, "stor.alt") \
|
||||
_(STOR_S_PRI, "stor.s.pri") \
|
||||
_(STOR_S_ALT, "stor.s.alt") \
|
||||
_(UNGEN_SREF_PRI, "sref.pri") \
|
||||
_(UNGEN_SREF_ALT, "sref.alt") \
|
||||
_(SREF_S_PRI, "sref.s.pri") \
|
||||
_(SREF_S_ALT, "sref.s.alt") \
|
||||
_(STOR_I, "stor.i") \
|
||||
_(STRB_I, "strb.i") \
|
||||
_(LIDX, "lidx") \
|
||||
_(LIDX_B, "lidx.b") \
|
||||
_(IDXADDR, "idxaddr") \
|
||||
_(IDXADDR_B, "idxaddr.b") \
|
||||
_(UNGEN_ALIGN_PRI,"align.pri") \
|
||||
_(UNGEN_ALIGN_ALT,"align.alt") \
|
||||
_(UNGEN_LCTRL, "lctrl") \
|
||||
_(UNGEN_SCTRL, "sctrl") \
|
||||
_(MOVE_PRI, "move.pri") \
|
||||
_(MOVE_ALT, "move.alt") \
|
||||
_(XCHG, "xchg") \
|
||||
_(PUSH_PRI, "push.pri") \
|
||||
_(PUSH_ALT, "push.alt") \
|
||||
_(UNGEN_PUSH_R, "push.r") \
|
||||
_(PUSH_C, "push.c") \
|
||||
_(PUSH, "push") \
|
||||
_(PUSH_S, "push.s") \
|
||||
_(POP_PRI, "pop.pri") \
|
||||
_(POP_ALT, "pop.alt") \
|
||||
_(STACK, "stack") \
|
||||
_(HEAP, "heap") \
|
||||
_(PROC, "proc") \
|
||||
_(UNGEN_RET, "ret") \
|
||||
_(RETN, "retn") \
|
||||
_(CALL, "call") \
|
||||
_(UNGEN_CALL_PRI, "call.pri") \
|
||||
_(JUMP, "jump") \
|
||||
_(UNGEN_JREL, "jrel") \
|
||||
_(JZER, "jzer") \
|
||||
_(JNZ, "jnz") \
|
||||
_(JEQ, "jeq") \
|
||||
_(JNEQ, "jneq") \
|
||||
_(UNGEN_JLESS, "jsless") \
|
||||
_(UNGEN_JLEQ, "jleq") \
|
||||
_(UNGEN_JGRTR, "jgrtr") \
|
||||
_(UNGEN_JGEQ, "jgeq") \
|
||||
_(JSLESS, "jsless") \
|
||||
_(JSLEQ, "jsleq") \
|
||||
_(JSGRTR, "jsgrtr") \
|
||||
_(JSGEQ, "jsgeq") \
|
||||
_(SHL, "shl") \
|
||||
_(SHR, "shr") \
|
||||
_(SSHR, "sshr") \
|
||||
_(SHL_C_PRI, "shl.c.pri") \
|
||||
_(SHL_C_ALT, "shl.c.alt") \
|
||||
_(SHR_C_PRI, "shr.c.pri") \
|
||||
_(SHR_C_ALT, "shr.c.alt") \
|
||||
_(SMUL, "smul") \
|
||||
_(SDIV, "sdiv") \
|
||||
_(SDIV_ALT, "sdiv.alt") \
|
||||
_(UNGEN_UMUL, "umul") \
|
||||
_(UNGEN_UDIV, "udiv") \
|
||||
_(UNGEN_UDIV_ALT, "udiv.alt") \
|
||||
_(ADD, "add") \
|
||||
_(SUB, "sub") \
|
||||
_(SUB_ALT, "sub.alt") \
|
||||
_(AND, "and") \
|
||||
_(OR, "or") \
|
||||
_(XOR, "xor") \
|
||||
_(NOT, "not") \
|
||||
_(NEG, "neg") \
|
||||
_(INVERT, "invert") \
|
||||
_(ADD_C, "add.c") \
|
||||
_(SMUL_C, "smul.c") \
|
||||
_(ZERO_PRI, "zero.pri") \
|
||||
_(ZERO_ALT, "zero.alt") \
|
||||
_(ZERO, "zero") \
|
||||
_(ZERO_S, "zero.s") \
|
||||
_(UNGEN_SIGN_PRI, "sign.pri") \
|
||||
_(UNGEN_SIGN_ALT, "sign.alt") \
|
||||
_(EQ, "eq") \
|
||||
_(NEQ, "neq") \
|
||||
_(UNGEN_LESS, "less") \
|
||||
_(UNGEN_LEQ, "leq") \
|
||||
_(UNGEN_GRTR, "grtr") \
|
||||
_(UNGEN_GEQ, "geq") \
|
||||
_(SLESS, "sless") \
|
||||
_(SLEQ, "sleq") \
|
||||
_(SGRTR, "sgrtr") \
|
||||
_(SGEQ, "sgeq") \
|
||||
_(EQ_C_PRI, "eq.c.pri") \
|
||||
_(EQ_C_ALT, "eq.c.alt") \
|
||||
_(INC_PRI, "inc.pri") \
|
||||
_(INC_ALT, "inc.alt") \
|
||||
_(INC, "inc") \
|
||||
_(INC_S, "inc.s") \
|
||||
_(INC_I, "inc.i") \
|
||||
_(DEC_PRI, "dec.pri") \
|
||||
_(DEC_ALT, "dec.alt") \
|
||||
_(DEC, "dec") \
|
||||
_(DEC_S, "dec.s") \
|
||||
_(DEC_I, "dec.i") \
|
||||
_(MOVS, "movs") \
|
||||
_(UNGEN_CMPS, "cmps") \
|
||||
_(FILL, "fill") \
|
||||
_(HALT, "halt") \
|
||||
_(BOUNDS, "bounds") \
|
||||
_(UNGEN_SYSREQ_PRI,"sysreq.pri") \
|
||||
_(SYSREQ_C, "sysreq.c") \
|
||||
_(UNGEN_FILE, "file") \
|
||||
_(UNGEN_LINE, "line") \
|
||||
_(UNGEN_SYMBOL, "symbol") \
|
||||
_(UNGEN_SRANGE, "srange") \
|
||||
_(UNGEN_JUMP_PRI, "jump.pri") \
|
||||
_(SWITCH, "switch") \
|
||||
_(CASETBL, "casetbl") \
|
||||
_(SWAP_PRI, "swap.pri") \
|
||||
_(SWAP_ALT, "swap.alt") \
|
||||
_(PUSH_ADR, "push.adr") \
|
||||
_(NOP, "nop") \
|
||||
_(SYSREQ_N, "sysreq.n") \
|
||||
_(UNGEN_SYMTAG, "symtag") \
|
||||
_(BREAK, "break") \
|
||||
_(PUSH2_C, "push2.c") \
|
||||
_(PUSH2, "push2") \
|
||||
_(PUSH2_S, "push2.s") \
|
||||
_(PUSH2_ADR, "push2.adr") \
|
||||
_(PUSH3_C, "push3.c") \
|
||||
_(PUSH3, "push3") \
|
||||
_(PUSH3_S, "push3.s") \
|
||||
_(PUSH3_ADR, "push3.adr") \
|
||||
_(PUSH4_C, "push4.c") \
|
||||
_(PUSH4, "push4") \
|
||||
_(PUSH4_S, "push4.s") \
|
||||
_(PUSH4_ADR, "push4.adr") \
|
||||
_(PUSH5_C, "push5.c") \
|
||||
_(PUSH5, "push5") \
|
||||
_(PUSH5_S, "push5.s") \
|
||||
_(PUSH5_ADR, "push5.adr") \
|
||||
_(LOAD_BOTH, "load.both") \
|
||||
_(LOAD_S_BOTH, "load.s.both") \
|
||||
_(CONST, "const") \
|
||||
_(CONST_S, "const.s") \
|
||||
_(UNGEN_SYSREQ_D, "sysreq.d") \
|
||||
_(UNGEB_SYSREQ_ND,"sysreq.nd") \
|
||||
_(TRACKER_PUSH_C, "trk.push.c") \
|
||||
_(TRACKER_POP_SETHEAP,"trk.pop") \
|
||||
_(GENARRAY, "genarray") \
|
||||
_(GENARRAY_Z, "genarray.z") \
|
||||
_(STRADJUST_PRI, "stradjust.pri") \
|
||||
_(UNGEN_STKADJUST,"stackadjust") \
|
||||
_(ENDPROC, "endproc") \
|
||||
_(FABS, "fabs") \
|
||||
_(FLOAT, "float") \
|
||||
_(FLOATADD, "float.add") \
|
||||
_(FLOATSUB, "float.sub") \
|
||||
_(FLOATMUL, "float.mul") \
|
||||
_(FLOATDIV, "float.div") \
|
||||
_(RND_TO_NEAREST, "round") \
|
||||
_(RND_TO_FLOOR, "floor") \
|
||||
_(RND_TO_CEIL, "ceil") \
|
||||
_(RND_TO_ZERO, "rndtozero") \
|
||||
_(FLOATCMP, "float.cmp") \
|
||||
_(FLOAT_GT, "float.gt") \
|
||||
_(FLOAT_GE, "float.ge") \
|
||||
_(FLOAT_LT, "float.lt") \
|
||||
_(FLOAT_LE, "float.le") \
|
||||
_(FLOAT_NE, "float.ne") \
|
||||
_(FLOAT_EQ, "float.eq") \
|
||||
_(FLOAT_NOT, "float.not")
|
||||
|
||||
enum OPCODE {
|
||||
#define _(op, text) OP_##op,
|
||||
OPCODE_LIST(_)
|
||||
#undef _
|
||||
OPCODES_TOTAL
|
||||
};
|
||||
|
||||
} // namespace sp
|
||||
|
||||
#endif // _INCLUDE_SPFILE_HEADERS_v1_opcodes_H
|
205
sourcepawn/include/smx/smx-v1.h
Normal file
205
sourcepawn/include/smx/smx-v1.h
Normal file
@ -0,0 +1,205 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
// =============================================================================
|
||||
// SourcePawn
|
||||
// Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved.
|
||||
// =============================================================================
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||
// Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <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>.
|
||||
|
||||
#ifndef _INCLUDE_SPFILE_HEADERS_v1_H
|
||||
#define _INCLUDE_SPFILE_HEADERS_v1_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <smx/smx-headers.h>
|
||||
|
||||
namespace sp {
|
||||
|
||||
// These structures are byte-packed.
|
||||
#if defined __GNUC__
|
||||
# pragma pack(1)
|
||||
#else
|
||||
# pragma pack(push)
|
||||
# pragma pack(1)
|
||||
#endif
|
||||
|
||||
// (Obsolete) debug-information is present.
|
||||
static const uint16_t CODEFLAG_DEBUG = 0x1;
|
||||
|
||||
// The ".data" section.
|
||||
typedef struct sp_file_data_s
|
||||
{
|
||||
uint32_t datasize; /**< Size of data section in memory */
|
||||
uint32_t memsize; /**< Total mem required (includes data) */
|
||||
uint32_t data; /**< File offset to data (helper) */
|
||||
} sp_file_data_t;
|
||||
|
||||
// The ".publics" section.
|
||||
typedef struct sp_file_publics_s
|
||||
{
|
||||
uint32_t address; /**< Address relative to code section */
|
||||
uint32_t name; /**< Index into nametable */
|
||||
} sp_file_publics_t;
|
||||
|
||||
// The ".natives" section.
|
||||
typedef struct sp_file_natives_s
|
||||
{
|
||||
uint32_t name; /**< Index into nametable */
|
||||
} sp_file_natives_t;
|
||||
|
||||
// The ".pubvars" section.
|
||||
typedef struct sp_file_pubvars_s
|
||||
{
|
||||
uint32_t address; /**< Address relative to the DAT section */
|
||||
uint32_t name; /**< Index into nametable */
|
||||
} sp_file_pubvars_t;
|
||||
|
||||
// The ".tags" section.
|
||||
typedef struct sp_file_tag_s
|
||||
{
|
||||
uint32_t tag_id; /**< Tag ID from compiler */
|
||||
uint32_t name; /**< Index into nametable */
|
||||
} sp_file_tag_t;
|
||||
|
||||
// The ".dbg.info" section.
|
||||
typedef struct sp_fdbg_info_s
|
||||
{
|
||||
uint32_t num_files; /**< number of files */
|
||||
uint32_t num_lines; /**< number of lines */
|
||||
uint32_t num_syms; /**< number of symbols */
|
||||
uint32_t num_arrays; /**< number of symbols which are arrays */
|
||||
} sp_fdbg_info_t;
|
||||
|
||||
// The ".dbg.files" section.
|
||||
typedef struct sp_fdbg_file_s
|
||||
{
|
||||
uint32_t addr; /**< Address into code */
|
||||
uint32_t name; /**< Offset into debug nametable */
|
||||
} sp_fdbg_file_t;
|
||||
|
||||
// The ".dbg.lines" section.
|
||||
typedef struct sp_fdbg_line_s
|
||||
{
|
||||
uint32_t addr; /**< Address into code */
|
||||
uint32_t line; /**< Line number */
|
||||
} sp_fdbg_line_t;
|
||||
|
||||
static const uint8_t IDENT_VARIABLE = 1; // Scalar local variable.
|
||||
static const uint8_t IDENT_REFERENCE = 2; // Reference to a scalar argument.
|
||||
static const uint8_t IDENT_ARRAY = 3; // Array with known dimensions.
|
||||
static const uint8_t IDENT_REFARRAY = 4; // Array with unknown dimensions.
|
||||
static const uint8_t IDENT_FUNCTION = 9; // Symbolic function.
|
||||
static const uint8_t IDENT_VARARGS = 11; // Variadic argument (...).
|
||||
|
||||
// The ".dbg.symbols" table.
|
||||
typedef struct sp_fdbg_symbol_s
|
||||
{
|
||||
int32_t addr; /**< Address rel to DAT or stack frame */
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t codestart; /**< Start scope validity in code */
|
||||
uint32_t codeend; /**< End scope validity in code */
|
||||
uint8_t ident; /**< Variable type */
|
||||
uint8_t vclass; /**< Scope class (local vs global) */
|
||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
||||
uint32_t name; /**< Offset into debug nametable */
|
||||
} sp_fdbg_symbol_t;
|
||||
|
||||
// Occurs after an fdbg_symbol entry, for each dimension.
|
||||
typedef struct sp_fdbg_arraydim_s
|
||||
{
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t size; /**< Size of dimension */
|
||||
} sp_fdbg_arraydim_t;
|
||||
|
||||
// Typedef for the ".names" section.
|
||||
typedef char * sp_file_nametab_t;
|
||||
|
||||
// Header for the ".dbg.natives" section. It is followed by a number of
|
||||
// sp_fdbg_native_t entries.
|
||||
typedef struct sp_fdbg_ntvtab_s
|
||||
{
|
||||
uint32_t num_entries; /**< Number of entries. */
|
||||
} sp_fdbg_ntvtab_t;
|
||||
|
||||
// An entry in the .dbg.natives section. Each is followed by an
|
||||
// sp_fdbg_ntvarg_t for each argument.
|
||||
typedef struct sp_fdbg_native_s
|
||||
{
|
||||
uint32_t index; /**< Native index in the plugin. */
|
||||
uint32_t name; /**< Offset into debug nametable. */
|
||||
int16_t tagid; /**< Return tag. */
|
||||
uint16_t nargs; /**< Number of formal arguments. */
|
||||
} sp_fdbg_native_t;
|
||||
|
||||
static const uint8_t IDENT_NATIVE_VARARGS = 1;
|
||||
|
||||
// Each entry is followed by an sp_fdbg_arraydim_t for each dimcount.
|
||||
typedef struct sp_fdbg_ntvarg_s
|
||||
{
|
||||
uint8_t ident; /**< Variable type */
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
||||
uint32_t name; /**< Offset into debug nametable */
|
||||
} sp_fdbg_ntvarg_t;
|
||||
|
||||
#if defined __GNUC__
|
||||
# pragma pack() /* reset default packing */
|
||||
#else
|
||||
# pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
|
||||
// The packing for files changed by accident for a small window of time, and
|
||||
// some files may have unparsable debug information using sp_fdbg_arraydim_t or
|
||||
// sp_fdbg_symbol_t.
|
||||
//
|
||||
// If the file version is >= 0x0102, all structures will be packed. If the
|
||||
// file version is < 0x0101, and the ".dbg.natives" table is present,
|
||||
// all structures will be packed.
|
||||
//
|
||||
// If the version is 0x0101 and ".dbg.natives" is not present, then you must
|
||||
// use the unpacked versions of those structures below. There is an extremely
|
||||
// small chance, if the plugin used no natives, that the packing is
|
||||
// indeterminate. This case is unlikely to be interesting, but if such a file
|
||||
// exists, the only solution is to re-parse if the data looks corrupt.
|
||||
|
||||
typedef struct sp_u_fdbg_arraydim_s
|
||||
{
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t size; /**< Size of dimension */
|
||||
} sp_u_fdbg_arraydim_t;
|
||||
|
||||
typedef struct sp_u_fdbg_symbol_s
|
||||
{
|
||||
int32_t addr; /**< Address rel to DAT or stack frame */
|
||||
int16_t tagid; /**< Tag id */
|
||||
uint32_t codestart; /**< Start scope validity in code */
|
||||
uint32_t codeend; /**< End scope validity in code */
|
||||
uint8_t ident; /**< Variable type */
|
||||
uint8_t vclass; /**< Scope class (local vs global) */
|
||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
||||
uint32_t name; /**< Offset into debug nametable */
|
||||
} sp_u_fdbg_symbol_t;
|
||||
|
||||
} // namespace sp
|
||||
|
||||
#endif //_INCLUDE_SPFILE_HEADERS_v1_H
|
||||
|
218
sourcepawn/include/smx/smx-v2.h
Normal file
218
sourcepawn/include/smx/smx-v2.h
Normal file
@ -0,0 +1,218 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
// =============================================================================
|
||||
// SourcePawn
|
||||
// Copyright (C) 2004-2014 AlliedModders LLC. All rights RESERVED.
|
||||
// =============================================================================
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||
// Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <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>.
|
||||
|
||||
#ifndef _INCLUDE_SPFILE_HEADERS_v2_H
|
||||
#define _INCLUDE_SPFILE_HEADERS_v2_H
|
||||
|
||||
#include <smx-headers.h>
|
||||
|
||||
namespace sp {
|
||||
|
||||
// These structures are byte-packed.
|
||||
#if defined __GNUC__
|
||||
# pragma pack(1)
|
||||
#else
|
||||
# pragma pack(push)
|
||||
# pragma pack(1)
|
||||
#endif
|
||||
|
||||
// Tables present in smx v2:
|
||||
// .names Blob of null-terminated strings.
|
||||
// .methods Table of smx_method_t entries.
|
||||
// .pcode Blob of smx_pcode_header_t entries.
|
||||
// .globals Table of smx_global_var_t entries.
|
||||
// .types Blob of type information.
|
||||
|
||||
// TypeSpec is a variable-length encoding referenced anywhere that "typespec"
|
||||
// is specified.
|
||||
//
|
||||
// Whenever a TypeSpec is referenced from outside the .types table, specifically
|
||||
// as a "typeid", it has an encoding to save space: If the id is < 0x20, then
|
||||
// the id is a single-byte TypeSpec. Otherwise, the |id - 0x20| is an offset
|
||||
// into the .types section.
|
||||
enum class TypeSpec : uint8_t
|
||||
{
|
||||
// The void type is special in that it is not a storable type.
|
||||
void_t = 0x0,
|
||||
|
||||
// Standard C++ datatypes.
|
||||
boolean = 0x1,
|
||||
RESERVED_int8 = 0x2,
|
||||
RESERVED_uint8 = 0x3,
|
||||
RESERVED_int16 = 0x4,
|
||||
RESERVED_uint16 = 0x5,
|
||||
int32 = 0x6,
|
||||
RESERVED_uint32 = 0x7,
|
||||
RESERVED_int64 = 0x8,
|
||||
RESERVED_uint64 = 0x9,
|
||||
|
||||
// platform-width int and uint.
|
||||
RESERVED_intptr = 0xA,
|
||||
RESERVED_uintptr = 0xB,
|
||||
|
||||
float32 = 0xC,
|
||||
RESERVED_float64 = 0xD,
|
||||
|
||||
// char8 is semantically an alias for int8.
|
||||
char8 = 0xE,
|
||||
|
||||
RESERVED_char32 = 0xF, // Full unicode point.
|
||||
|
||||
RESERVED_string = 0x16, // String reference.
|
||||
RESERVED_object = 0x17, // Opaque object reference.
|
||||
|
||||
// Followed by an int32 index into the .classes table.
|
||||
RESERVED_classdef = 0x40,
|
||||
|
||||
// Followed by an int32 index into the .structs table.
|
||||
RESERVED_structdef = 0x41,
|
||||
|
||||
// Followed by:
|
||||
// [int8 formalCount] ; Number of formal parameters, counting varargs.
|
||||
// [typespec *formals] ; Sequence of formal parameter specifications.
|
||||
//
|
||||
// When the type spec is for a method definition (for example, the .method
|
||||
// table), then each type in |formals| must begin with "named" (0x7e) or,
|
||||
// if it is the last formal, may be "variadic" (0x7a).
|
||||
method = 0x50,
|
||||
|
||||
// Fixed arrays have their size as part of their type, are copied by-value,
|
||||
// and passed by-reference.
|
||||
//
|
||||
// Followed by:
|
||||
// typespec type ; Type specification of innermost elements.
|
||||
// uint8 rank ; Number of dimensions
|
||||
// int32* dims ; One dimension for each rank.
|
||||
fixedarray = 0x60,
|
||||
|
||||
// Arrays are true arrays. They are copied by-reference and passed by-
|
||||
// reference.
|
||||
//
|
||||
// Followed by:
|
||||
// typesec type ; Type specification of innermost elements.
|
||||
// uint8 rank ; Number of dimensions.
|
||||
RESERVED_array = 0x61,
|
||||
|
||||
// Only legal as the initial byte or byte following "named" (0x7e) in a
|
||||
// parameter for a method signature.
|
||||
//
|
||||
// Followed by a typespec. Only typespecs < 0x60 ar elegal.
|
||||
byref = 0x70,
|
||||
|
||||
// Only legal as the initial byte or byte following "named" (0x7e) in a
|
||||
// parameter for a method signature.
|
||||
//
|
||||
// Followed by a typespec.
|
||||
variadic = 0x7A,
|
||||
|
||||
// Only legal as the initial byte in a parameter or local variable signature.
|
||||
//
|
||||
// Followed by:
|
||||
// uint32 name ; Index into the .names section.
|
||||
// typespec type ; Type.
|
||||
named = 0x7E,
|
||||
|
||||
// For readability, this may be emitted at the end of typespec lists. It must
|
||||
// not be emitted at the end of nested typespecs.
|
||||
terminator = 0x7F
|
||||
};
|
||||
|
||||
// Flags for method definitions.
|
||||
enum class MethodFlags : uint32_t
|
||||
{
|
||||
STATIC = 0x1,
|
||||
VARIADIC = 0x2,
|
||||
PUBLIC = 0x4,
|
||||
NATIVE = 0x8,
|
||||
OPTIONAL = 0x10
|
||||
};
|
||||
|
||||
// Specifies an entry in the .methods table.
|
||||
struct smx_method_t
|
||||
{
|
||||
// Offset into the .names section.
|
||||
uint32_t name;
|
||||
|
||||
MethodFlags flags;
|
||||
|
||||
// Offset into .types, which must point at a TypeSpec::method.
|
||||
uint32_t typespec;
|
||||
|
||||
// Offset into .pcode. If flags contains NATIVE, this must be 0.
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
enum class GlobalVarFlags : uint32_t
|
||||
{
|
||||
PUBLIC = 0x04,
|
||||
CONST = 0x08
|
||||
};
|
||||
|
||||
// Specifies an entry in the .globals table.
|
||||
struct smx_global_var_t
|
||||
{
|
||||
// Offset into the .names section.
|
||||
uint32_t name;
|
||||
|
||||
GlobalVarFlags flags;
|
||||
|
||||
// TypeId of the global.
|
||||
uint32_t type_id;
|
||||
};
|
||||
|
||||
// Specifies the layout we expect at a valid pcode starting position.
|
||||
struct smx_pcode_header_t
|
||||
{
|
||||
// Must be 0.
|
||||
uint32_t reserved;
|
||||
|
||||
// Number of local variables.
|
||||
uint16_t nlocals;
|
||||
|
||||
// Maximum depth of the operand stack.
|
||||
uint16_t max_depth;
|
||||
|
||||
// Pointer to .types section where local information begins.
|
||||
uint32_t local_specs;
|
||||
|
||||
// Number of bytes of pcode in the method.
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// DO NOT DEFINE NEW STRUCTURES BELOW.
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#if defined __GNUC__
|
||||
# pragma pack()
|
||||
#else
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
} // namespace sp
|
||||
|
||||
#endif // _INCLUDE_SPFILE_HEADERS_v2_H
|
@ -12,6 +12,9 @@ binary.compiler.includes += [
|
||||
os.path.join(builder.sourcePath, 'public', 'jit'),
|
||||
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
||||
os.path.join(builder.sourcePath, 'knight', 'shared'),
|
||||
|
||||
# The include path for SP v2 stuff.
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
]
|
||||
|
||||
if builder.target_platform == 'linux':
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "md5/md5.h"
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
|
||||
static inline bool
|
||||
@ -171,9 +172,9 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
|
||||
if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
|
||||
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
||||
|
||||
if (cod->codeversion < SP_CODEVERS_JIT1)
|
||||
if (cod->codeversion < SmxConsts::CODE_VERSION_JIT1)
|
||||
return SP_ERROR_CODE_TOO_OLD;
|
||||
if (cod->codeversion > SP_CODEVERS_JIT2)
|
||||
if (cod->codeversion > SmxConsts::CODE_VERSION_JIT2)
|
||||
return SP_ERROR_CODE_TOO_NEW;
|
||||
|
||||
m_plugin.pcode = base + secptr->dataoffs + cod->code;
|
||||
@ -266,7 +267,7 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
|
||||
if (m_plugin.pcode == NULL || m_plugin.data == NULL)
|
||||
return SP_ERROR_FILE_FORMAT;
|
||||
|
||||
if ((m_plugin.flags & SP_FLAG_DEBUG) && (
|
||||
if ((m_plugin.flags & sp::CODEFLAG_DEBUG) && (
|
||||
!(m_plugin.debug.files) ||
|
||||
!(m_plugin.debug.lines) ||
|
||||
!(m_plugin.debug.symbols) ||
|
||||
|
@ -37,7 +37,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
|
||||
/* Rewind for safety */
|
||||
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
|
||||
|
||||
if (hdr.magic != SPFILE_MAGIC)
|
||||
if (hdr.magic != SmxConsts::FILE_MAGIC)
|
||||
{
|
||||
error = SP_ERROR_FILE_FORMAT;
|
||||
goto return_error;
|
||||
@ -45,7 +45,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
|
||||
|
||||
switch (hdr.compression)
|
||||
{
|
||||
case SPFILE_COMPRESSION_GZ:
|
||||
case SmxConsts::FILE_COMPRESSION_GZ:
|
||||
{
|
||||
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
|
||||
uint32_t compsize = hdr.disksize - hdr.dataoffs;
|
||||
@ -77,7 +77,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
|
||||
free(uncompdata);
|
||||
break;
|
||||
}
|
||||
case SPFILE_COMPRESSION_NONE:
|
||||
case SmxConsts::FILE_COMPRESSION_NONE:
|
||||
{
|
||||
base = (uint8_t *)malloc(hdr.imagesize);
|
||||
rewind(fp);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#define STACK_MARGIN 64
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
|
||||
static inline bool
|
||||
|
@ -3,7 +3,9 @@
|
||||
#define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <smx/smx-v1.h>
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
|
||||
#define SP_MAX_RETURN_STACK 1024
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "opcodes.h"
|
||||
#include "jit_shared.h"
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
|
||||
const char *OpcodeNames[] = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user