This commit is contained in:
Nicholas Hastings 2014-08-29 09:54:13 -07:00
commit ac121ec4d2
104 changed files with 4696 additions and 4030 deletions

View File

@ -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']

View File

@ -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.

View File

@ -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',

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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)

View File

@ -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_

View File

@ -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");

View File

@ -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.");

View File

@ -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']

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 *>();

View File

@ -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);

View File

@ -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;

View File

@ -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
View 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
View 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_

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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
};

View File

@ -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_ */

View File

@ -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;
};

View File

@ -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;

View File

@ -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},
};
};

View File

@ -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},
};

View File

@ -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
{

View File

@ -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;
}

View File

@ -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)

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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)
{

View File

@ -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)

View File

@ -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"
}
}
}

View File

@ -30,9 +30,9 @@
}
"PreThink"
{
"windows" "344"
"linux" "345"
"mac" "345"
"windows" "345"
"linux" "346"
"mac" "346"
}
"PostThink"
{

View File

@ -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"
{

View File

@ -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"
}
}
}

View File

@ -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"
{

View File

@ -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.
*

View File

@ -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

View File

@ -249,6 +249,7 @@ enum {
TF_WEAPON_SPELLBOOK,
TF_WEAPON_SPELLBOOK_PROJECTILE,
TF_WEAPON_SNIPERRIFLE_CLASSIC,
TF_WEAPON_PARACHUTE,
};
// TF2 Weapon Loadout Slots

View File

@ -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()
{
}
};
/**

View File

@ -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)
{
}

View File

@ -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;

View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View 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);
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;
}

View 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

View File

@ -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 */

View File

@ -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"

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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",

View File

@ -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:

View File

@ -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,&params);
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,&params);
ucell p2=getparam(params,&params);
@ -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,&params);
ucell p2=getparam(params,&params);
@ -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,&params);
ucell p2=getparam(params,&params);
@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -34,8 +34,6 @@
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
typedef memfile_t MEMFILE;
#define tMEMFILE 1
#include "sc.h"

View File

@ -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;

View File

@ -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;
}

View File

@ -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_

View File

@ -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

View 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

View File

@ -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

View 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;
}

View File

@ -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;
/**

View File

@ -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);
}

View 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);
}

View File

@ -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_ */

View 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 ] );
}

View 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] )
{
}

View 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

View 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

View 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

View 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

View File

@ -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':

View File

@ -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) ||

View File

@ -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);

View File

@ -22,6 +22,7 @@
#define STACK_MARGIN 64
using namespace sp;
using namespace SourcePawn;
static inline bool

View File

@ -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

View File

@ -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