Implement a new stack and error handling model for the SourcePawn VM.

This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.

The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.

Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.

Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.

These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
This commit is contained in:
David Anderson
2015-03-04 23:45:30 -08:00
parent 04827466b0
commit a1afa23bc4
51 changed files with 2085 additions and 1766 deletions
+1
View File
@@ -218,6 +218,7 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
hook->pf->PushCell(args);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
-1
View File
@@ -62,7 +62,6 @@ binary.sources += [
'PluginSys.cpp',
'HandleSys.cpp',
'NativeOwner.cpp',
'NativeInvoker.cpp',
'ExtensionSys.cpp',
'DebugReporter.cpp',
'Database.cpp',
+44 -46
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -132,51 +132,6 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
}
}
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
{
const char *lastname;
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
int n_err = error->GetErrorCode();
if (n_err != SP_ERROR_NATIVE)
{
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
n_err,
error->GetErrorString());
}
if ((lastname=error->GetLastNative(NULL)) != NULL)
{
const char *custerr;
if ((custerr=error->GetCustomErrorString()) != NULL)
{
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
} else {
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
}
}
if (!error->DebugInfoAvailable())
{
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;
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
while (error->GetTraceInfo(&stk_info))
{
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
i++,
stk_info.line,
stk_info.filename,
stk_info.function);
}
}
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
{
int id = 1;
@@ -199,3 +154,46 @@ int DebugReport::_GetPluginIndex(IPluginContext *ctx)
return pluginsys->GetPluginCount() + 1;
}
void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
{
// Find the nearest plugin to blame.
const char *blame = nullptr;
for (; !iter.Done(); iter.Next()) {
if (iter.IsScriptedFrame()) {
IPlugin *plugin = pluginsys->FindPluginByContext(iter.Context()->GetContext());
if (plugin)
blame = plugin->GetFilename();
else
blame = iter.Context()->GetRuntime()->GetFilename();
break;
}
}
iter.Reset();
g_Logger.LogError("[SM] Exception reported: %s", report.Message());
if (blame)
g_Logger.LogError("[SM] Blaming plugin: %s", blame);
g_Logger.LogError("[SM] Call stack trace:");
for (int index = 0; !iter.Done(); iter.Next(), index++) {
const char *fn = iter.FunctionName();
if (!fn)
fn = "<unknown function>";
if (iter.IsNativeFrame()) {
g_Logger.LogError("[SM] [%d] %s", index, fn);
continue;
}
if (iter.IsScriptedFrame()) {
const char *file = iter.FilePath();
if (!file)
file = "<unknown>";
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
index,
iter.LineNumber(),
file,
fn);
}
}
}
+1 -1
View File
@@ -42,7 +42,7 @@ class DebugReport :
public: // SMGlobalClass
void OnSourceModAllInitialized();
public: // IDebugListener
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
void ReportError(const IErrorReport &report, IFrameIterator &iter);
void OnDebugSpew(const char *msg, ...);
public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
-360
View File
@@ -1,360 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourcePawn
* 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 "NativeInvoker.h"
#include "ShareSys.h"
NativeInterface g_NInvoke;
NativeInvoker::NativeInvoker()
{
}
NativeInvoker::~NativeInvoker()
{
}
const char *NativeInterface::GetInterfaceName()
{
return SMINTERFACE_NINVOKE_NAME;
}
unsigned int NativeInterface::GetInterfaceVersion()
{
return SMINTERFACE_NINVOKE_VERSION;
}
void NativeInterface::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, &g_NInvoke);
}
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
{
return g_pSourcePawn2->CreateEmptyRuntime(name, bytes);
}
INativeInvoker *NativeInterface::CreateInvoker()
{
return new NativeInvoker();
}
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
{
ke::Ref<Native> entry = g_ShareSys.FindNative(name);
if (!entry)
return false;
if (!entry->owner)
return false;
native_ = entry->func();
context_ = pContext;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
return true;
}
cell_t NativeInvoker::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
}
int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
}
int NativeInvoker::PushFloat(float number)
{
cell_t val = *(cell_t *)&number;
return PushCell(val);
}
int NativeInvoker::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
}
int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
return SP_ERROR_NONE;
}
int NativeInvoker::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
}
int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->marked = true;
info->orig_addr = (cell_t *)string;
info->flags = cp_flags;
info->size = len;
info->str.sz_flags = sz_flags;
info->str.is_sz = true;
m_curparam++;
return SP_ERROR_NONE;
}
void NativeInvoker::Cancel()
{
if (context_ == NULL)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
context_ = NULL;
native_ = NULL;
}
int NativeInvoker::SetError(int err)
{
m_errorstate = err;
return err;
}
int NativeInvoker::Invoke(cell_t *result)
{
int err = SP_ERROR_NONE;
if (context_ == NULL)
return SP_ERROR_INVALID_NATIVE;
if (m_errorstate != SP_ERROR_NONE)
{
err = m_errorstate;
Cancel();
return err;
}
cell_t tresult;
if (result == NULL)
{
result = &tresult;
}
//This is for re-entrancy!
IPluginContext *ctx = context_;
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
bool docopies = true;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
context_ = NULL;
/* Initialize 0th parameter */
_temp_params[0] = numparams;
/* Browse the parameters and build arrays */
for (i = 0; i < numparams; i++)
{
/* Is this marked as an array? */
if (temp_info[i].marked)
{
if (!temp_info[i].str.is_sz)
{
/* Allocate a normal/generic array */
if ((err = ctx->HeapAlloc(temp_info[i].size,
&temp_info[i].local_addr,
&temp_info[i].phys_addr))
!= SP_ERROR_NONE)
{
break;
}
if (temp_info[i].orig_addr)
{
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
}
}
else
{
/* Calculate cells required for the string */
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
if ((err = ctx->HeapAlloc(cells,
&temp_info[i].local_addr,
&temp_info[i].phys_addr))
!= SP_ERROR_NONE)
{
break;
}
/* Copy original string if necessary */
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
{
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
{
if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL))
!= SP_ERROR_NONE)
{
break;
}
}
/* Copy a binary blob */
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
{
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
}
/* Copy ASCII characters */
else
{
if ((err = ctx->StringToLocal(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr))
!= SP_ERROR_NONE)
{
break;
}
}
}
} /* End array/string calculation */
/* Update the pushed parameter with the byref local address */
temp_params[i] = temp_info[i].local_addr;
}
else
{
/* Just copy the value normally */
temp_params[i] = m_params[i];
}
}
/* Make the call if we can */
if (err == SP_ERROR_NONE)
{
*result = native_(ctx, _temp_params);
if (ctx->GetLastNativeError() != SP_ERROR_NONE)
{
docopies = false;
ctx->ClearLastNativeError();
}
}
else
{
docopies = false;
}
/* i should be equal to the last valid parameter + 1 */
while (i--)
{
if (!temp_info[i].marked)
{
continue;
}
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
{
if (temp_info[i].orig_addr)
{
if (temp_info[i].str.is_sz)
{
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
}
else
{
if (temp_info[i].size == 1)
{
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
}
else
{
memcpy(temp_info[i].orig_addr,
temp_info[i].phys_addr,
temp_info[i].size * sizeof(cell_t));
}
}
}
}
if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
{
return err;
}
}
return err;
}
-102
View File
@@ -1,102 +0,0 @@
/**
* vim: set ts=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$
*/
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h>
#include <INativeInvoker.h>
#include "common_logic.h"
using namespace SourceMod;
using namespace SourcePawn;
struct ParamInfo
{
int flags; /* Copy-back flags */
bool marked; /* Whether this is marked as being used */
cell_t local_addr; /* Local address to free */
cell_t *phys_addr; /* Physical address of our copy */
cell_t *orig_addr; /* Original address to copy back to */
ucell_t size; /* Size of array in bytes */
struct
{
bool is_sz; /* is a string */
int sz_flags; /* has sz flags */
} str;
};
class NativeInvoker : public INativeInvoker
{
public:
NativeInvoker();
~NativeInvoker();
public: /* ICallable */
int PushCell(cell_t cell);
int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
int PushFloat(float number);
int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
int PushString(const char *string);
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
void Cancel();
public: /* INativeInvoker */
bool Start(IPluginContext *pContext, const char *name);
int Invoke(cell_t *result);
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
IPluginContext *context_;
SPVM_NATIVE_FUNC native_;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
};
class NativeInterface :
public INativeInterface,
public SMGlobalClass
{
public: /* SMGlobalClass */
void OnSourceModAllInitialized();
public: /* SMInterface */
unsigned int GetInterfaceVersion();
const char *GetInterfaceName();
public: /* INativeInvoker */
IPluginRuntime *CreateRuntime(const char *name, size_t bytes);
INativeInvoker *CreateInvoker();
};
extern NativeInterface g_NInvoke;
#endif /* _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ */
+2 -10
View File
@@ -1175,13 +1175,9 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
if ((pFunc=pBase->GetFunctionByName(buffer)))
{
cell_t res;
pFunc->Execute(&res);
if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
{
if (pFunc->Execute(&res) != SP_ERROR_NONE) {
if (error)
{
smcore.Format(error, maxlength, "Fatal error during initializing plugin load");
}
return false;
}
}
@@ -1303,13 +1299,9 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
if ((pFunc = pBase->GetFunctionByName(buffer)) != NULL)
{
cell_t res;
pFunc->Execute(&res);
if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
{
if (pFunc->Execute(&res) != SP_ERROR_NONE) {
if (error)
{
smcore.Format(error, maxlength, "Fatal error during plugin initialization (ext req)");
}
return false;
}
}
+25 -20
View File
@@ -150,11 +150,12 @@ static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[1024];
size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
size_t len;
{
return 0;
DetectExceptions eh(pContext);
len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1);
if (eh.HasException())
return 0;
}
/* One byte for null terminator, one for newline */
@@ -171,11 +172,12 @@ static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *par
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[1024];
size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
size_t len;
{
return 0;
DetectExceptions eh(pContext);
len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1);
if (eh.HasException())
return 0;
}
/* One byte for null terminator, one for newline */
@@ -211,11 +213,12 @@ static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(params[1]);
char buffer[256];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
size_t len;
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
engine->ClientCommand(pPlayer->GetEdict(), buffer);
@@ -240,11 +243,11 @@ static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(params[1]);
char buffer[256];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
engine->FakeClientCommand(pPlayer->GetEdict(), buffer);
@@ -258,11 +261,13 @@ static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
/* Build the format string */
char buffer[1024];
size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
size_t len;
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 2);
if (eh.HasException())
return 0;
}
/* If we're printing to the server, shortcut out */
+61 -52
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -130,13 +130,14 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
}
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (eh.HasException())
return 0;
}
pContext->ReportError("%s", buffer);
return 0;
}
@@ -388,16 +389,16 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
{
char buffer[2048];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
pPlugin->SetErrorState(Plugin_Failed, "%s", str);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
}
else
{
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (eh.HasException()) {
pPlugin->SetErrorState(Plugin_Failed, "%s", str);
return 0;
}
pPlugin->SetErrorState(Plugin_Failed, "%s", buffer);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
pContext->ReportFatalError("%s", buffer);
return 0;
}
}
@@ -507,12 +508,12 @@ static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
{
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (eh.HasException())
return 0;
}
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
@@ -536,14 +537,15 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
}
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
}
{
DetectExceptions eh(pContext);
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException()) {
fclose(fp);
return 0;
}
}
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
@@ -569,14 +571,15 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
}
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
}
{
DetectExceptions eh(pContext);
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException()) {
fclose(fp);
return 0;
}
}
g_Logger.LogToOpenFile(fp, "%s", buffer);
@@ -648,21 +651,27 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
if (sharesys->TestFeature(pContext->GetRuntime(), type, name) != FeatureStatus_Available)
{
char buffer[255];
char *msg = buffer;
char default_message[255];
char buffer[255];
char *msg = buffer;
char default_message[255];
SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0')
{
g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
msg = default_message;
}
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", msg);
}
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (eh.HasException())
buffer[0] = '\0';
if (buffer[0] == '\0') {
g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
msg = default_message;
}
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
if (!eh.HasException())
pContext->ReportFatalError("%s", msg);
return 0;
}
return 1;
}
+1 -7
View File
@@ -125,7 +125,6 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
int err;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
@@ -137,12 +136,7 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
}
char *str;
if ((err=pContext->LocalToString(params[2], &str)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
pContext->LocalToString(params[2], &str);
pDataPack->PackString(str);
return 1;
+21 -31
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet:
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -81,18 +81,12 @@ cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pD
s_curparams[i] = params[i];
}
/* Push info and execute. */
// Push info and execute. If Invoke() fails, the error will propagate up.
// We still carry on below to clear our global state.
cell_t result = 0;
native->call->PushCell(pCaller->GetMyHandle());
native->call->PushCell(params[0]);
int error;
if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
{
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
}
}
native->call->Invoke(&result);
/* Restore everything from the stack if necessary */
s_curnative = pSaveNative;
@@ -141,15 +135,15 @@ static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[512];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
} else {
s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
pContext->ReportError("%s", buffer);
return 0;
}
@@ -402,36 +396,32 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
char *format_buffer;
if (out_param)
{
if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
{
return err;
}
} else {
s_curcaller->LocalToString(s_curparams[out_param], &output_buffer);
else
pContext->LocalToString(params[6], &output_buffer);
}
if (fmt_param)
{
if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
{
return err;
}
} else {
s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer);
else
pContext->LocalToString(params[7], &format_buffer);
}
/* Get maximum length */
size_t maxlen = (size_t)params[4];
/* Do the format */
size_t written = smcore.atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
size_t written;
{
DetectExceptions eh(pContext);
written = smcore.atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
if (eh.HasException())
return 0;
}
cell_t *addr;
pContext->LocalToPhysAddr(params[5], &addr);
*addr = (cell_t)written;
return s_curcaller->GetLastNativeError();
return SP_ERROR_NONE;
}
//tee hee
+37 -24
View File
@@ -765,9 +765,12 @@ static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
int arg = 3;
char buffer[2048];
smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
return 0;
{
DetectExceptions eh(pContext);
smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
if (eh.HasException())
return 0;
}
if (SystemFile *sysfile = file->AsSystemFile()) {
fprintf(sysfile->fp(), "%s\n", buffer);
@@ -797,9 +800,12 @@ static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params)
pContext->LocalToString(params[2], &buffer);
pContext->LocalToString(params[4], &fmt);
smcore.atcprintf(path, sizeof(path), fmt, pContext, params, &arg);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
return 0;
{
DetectExceptions eh(pContext);
smcore.atcprintf(path, sizeof(path), fmt, pContext, params, &arg);
if (eh.HasException())
return 0;
}
return g_pSM->BuildPath(Path_SM_Rel, buffer, params[3], "%s", path);
}
@@ -808,12 +814,13 @@ static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
{
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
size_t len;
char buffer[1024];
size_t len = g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
len = g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (eh.HasException())
return 0;
}
if (len >= sizeof(buffer)-2)
@@ -835,11 +842,11 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[1024];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (eh.HasException())
return 0;
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
@@ -853,11 +860,11 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[1024];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (eh.HasException())
return 0;
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
@@ -900,9 +907,12 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
return 0;
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
g_Logger.LogToOpenFile(sysfile->fp(), "[%s] %s", pPlugin->GetFilename(), buffer);
@@ -922,9 +932,12 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
return 0;
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
g_Logger.LogToOpenFile(sysfile->fp(), "%s", buffer);
return 1;
+1
View File
@@ -564,6 +564,7 @@ static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
pContext->LocalToPhysAddr(params[1], &result);
// Note: Execute() swallows exceptions, so this is okay.
if (s_pFunction)
{
IPluginFunction *pFunction = s_pFunction;
+40 -34
View File
@@ -1087,11 +1087,12 @@ static cell_t _ShowActivity(IPluginContext *pContext,
if (replyto == SM_REPLY_CONSOLE)
{
g_pSM->SetGlobalTarget(client);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s\n", tag, buffer);
@@ -1102,11 +1103,12 @@ static cell_t _ShowActivity(IPluginContext *pContext,
else
{
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s\n", tag, buffer);
@@ -1141,11 +1143,12 @@ static cell_t _ShowActivity(IPluginContext *pContext,
{
newsign = name;
}
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
@@ -1165,11 +1168,12 @@ static cell_t _ShowActivity(IPluginContext *pContext,
{
newsign = name;
}
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
@@ -1210,11 +1214,11 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
}
g_pSM->SetGlobalTarget(client);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
/* We don't display directly to the console because the chat text
@@ -1227,11 +1231,11 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
else
{
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s\n", tag, buffer);
@@ -1266,11 +1270,12 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
{
newsign = name;
}
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
@@ -1290,11 +1295,12 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
{
newsign = name;
}
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
if (eh.HasException())
return 0;
}
g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
@@ -1350,11 +1356,11 @@ static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(client);
char buffer[256];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
if (pPlayer->IsFakeClient())
@@ -1387,11 +1393,11 @@ static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
g_pSM->SetGlobalTarget(client);
char buffer[256];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
pPlayer->Kick(buffer);
+21 -5
View File
@@ -232,6 +232,7 @@ static cell_t sm_SortStrings(IPluginContext *pContext, const cell_t *params)
if ((err=pContext->HeapAlloc(array_size, &amx_addr, &phys_addr)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, "Ran out of memory to sort");
return 0;
}
g_CurStringArray = array;
@@ -282,12 +283,16 @@ struct sort_info
cell_t array_addr;
cell_t *array_base;
cell_t *array_remap;
ExceptionHandler *eh;
};
sort_info g_SortInfo;
int sort1d_amx_custom(const void *elem1, const void *elem2)
{
if (g_SortInfo.eh->HasException())
return 0;
cell_t c1 = *(cell_t *)elem1;
cell_t c2 = *(cell_t *)elem2;
@@ -297,7 +302,7 @@ int sort1d_amx_custom(const void *elem1, const void *elem2)
pf->PushCell(c2);
pf->PushCell(g_SortInfo.array_addr);
pf->PushCell(g_SortInfo.hndl);
pf->Execute(&result);
pf->Invoke(&result);
return result;
}
@@ -317,22 +322,25 @@ static cell_t sm_SortCustom1D(IPluginContext *pContext, const cell_t *params)
sort_info oldinfo = g_SortInfo;
DetectExceptions eh(pContext);
g_SortInfo.hndl = params[4];
g_SortInfo.array_addr = params[1];
g_SortInfo.array_remap = NULL;
g_SortInfo.array_base = NULL;
g_SortInfo.pFunc = pFunction;
g_SortInfo.eh = &eh;
qsort(array, array_size, sizeof(cell_t), sort1d_amx_custom);
g_SortInfo = oldinfo;
return 1;
}
int sort2d_amx_custom(const void *elem1, const void *elem2)
{
if (g_SortInfo.eh->HasException())
return 0;
cell_t c1 = *(cell_t *)elem1;
cell_t c2 = *(cell_t *)elem2;
@@ -349,7 +357,7 @@ int sort2d_amx_custom(const void *elem1, const void *elem2)
g_SortInfo.pFunc->PushCell(c2_addr);
g_SortInfo.pFunc->PushCell(g_SortInfo.array_addr);
g_SortInfo.pFunc->PushCell(g_SortInfo.hndl);
g_SortInfo.pFunc->Execute(&result);
g_SortInfo.pFunc->Invoke(&result);
return result;
}
@@ -378,9 +386,11 @@ static cell_t sm_SortCustom2D(IPluginContext *pContext, const cell_t *params)
sort_info oldinfo = g_SortInfo;
DetectExceptions eh(pContext);
g_SortInfo.pFunc = pFunction;
g_SortInfo.hndl = params[4];
g_SortInfo.array_addr = params[1];
g_SortInfo.eh = &eh;
/** Same process as in strings, back up the old indices for later fixup */
g_SortInfo.array_base = array;
@@ -511,19 +521,23 @@ struct sort_infoADT
cell_t array_bsize;
Handle_t array_hndl;
Handle_t hndl;
ExceptionHandler *eh;
};
sort_infoADT g_SortInfoADT;
int sort_adtarray_custom(const void *elem1, const void *elem2)
{
if (g_SortInfoADT.eh->HasException())
return 0;
cell_t result = 0;
IPluginFunction *pf = g_SortInfoADT.pFunc;
pf->PushCell(((cell_t) ((cell_t *) elem1 - g_SortInfoADT.array_base)) / g_SortInfoADT.array_bsize);
pf->PushCell(((cell_t) ((cell_t *) elem2 - g_SortInfoADT.array_base)) / g_SortInfoADT.array_bsize);
pf->PushCell(g_SortInfoADT.array_hndl);
pf->PushCell(g_SortInfoADT.hndl);
pf->Execute(&result);
pf->Invoke(&result);
return result;
}
@@ -552,11 +566,13 @@ static cell_t sm_SortADTArrayCustom(IPluginContext *pContext, const cell_t *para
sort_infoADT oldinfo = g_SortInfoADT;
DetectExceptions eh(pContext);
g_SortInfoADT.pFunc = pFunction;
g_SortInfoADT.array_base = array;
g_SortInfoADT.array_bsize = (cell_t) blocksize;
g_SortInfoADT.array_hndl = params[1];
g_SortInfoADT.hndl = params[3];
g_SortInfoADT.eh = &eh;
qsort(array, arraysize, blocksize * sizeof(cell_t), sort_adtarray_custom);
+1 -6
View File
@@ -1180,12 +1180,7 @@ reswitch:
{
CHECK_ARGS(0);
char *str;
int err;
if ((err=pCtx->LocalToString(params[arg], &str)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, "Could not deference string");
return 0;
}
pCtx->LocalToString(params[arg], &str);
AddString(&buf_p, llen, str, width, prec);
arg++;
break;
+1 -6
View File
@@ -194,7 +194,6 @@ static cell_t smn_BfWriteString(IPluginContext *pCtx, const cell_t *params)
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
int err;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
@@ -206,11 +205,7 @@ static cell_t smn_BfWriteString(IPluginContext *pCtx, const cell_t *params)
}
char *str;
if ((err=pCtx->LocalToString(params[2], &str)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToString(params[2], &str);
pBitBuf->WriteString(str);
+9 -8
View File
@@ -909,11 +909,12 @@ static cell_t sm_ServerCommandEx(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
size_t len;
{
return 0;
DetectExceptions eh(pContext);
len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 3);
if (eh.HasException())
return 0;
}
/* One byte for null terminator, one for newline */
@@ -965,11 +966,11 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params
g_SourceMod.SetGlobalTarget(params[1]);
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
g_HL2.AddToFakeCliCmdQueue(params[1], GetPlayerUserId(pPlayer->GetEdict()), buffer);
+14 -15
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -321,12 +321,12 @@ static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(client);
char buffer[192];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
if (!g_HL2.TextMsg(client, HUD_PRINTTALK, buffer))
@@ -355,12 +355,12 @@ static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(client);
char buffer[192];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
if (!g_HL2.TextMsg(client, HUD_PRINTCENTER, buffer))
@@ -389,12 +389,11 @@ static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(client);
char buffer[192];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (eh.HasException())
return 0;
}
if (!g_HL2.HintTextMsg(client, buffer))
+11 -7
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet:
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -415,10 +415,12 @@ static cell_t ShowSyncHudText(IPluginContext *pContext, const cell_t *params)
}
g_SourceMod.SetGlobalTarget(client);
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
if (eh.HasException())
return 0;
}
g_hud_params.channel = s_HudMsgHelpers.AutoSelectChannel(client, obj);
@@ -488,10 +490,12 @@ static cell_t ShowHudText(IPluginContext *pContext, const cell_t *params)
}
g_SourceMod.SetGlobalTarget(client);
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
DetectExceptions eh(pContext);
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
if (eh.HasException())
return 0;
}
if (params[2] == -1)
+11 -56
View File
@@ -52,13 +52,8 @@
// Assumes message field name is param 2, gets as strField
#define GET_FIELD_NAME_OR_ERR() \
int err; \
char *strField; \
if ((err=pCtx->LocalToString(params[2], &strField)) != SP_ERROR_NONE) \
{ \
pCtx->ThrowNativeErrorEx(err, NULL); \
return 0; \
}
pCtx->LocalToString(params[2], &strField);
static cell_t smn_PbReadInt(IPluginContext *pCtx, const cell_t *params)
{
@@ -387,11 +382,7 @@ static cell_t smn_PbSetString(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
char *strValue;
if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToString(params[3], &strValue);
int index = params[0] >= 4 ? params[4] : -1;
if (index < 0)
@@ -418,11 +409,7 @@ static cell_t smn_PbSetColor(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *clrParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &clrParams);
Color clr(
clrParams[0],
@@ -455,11 +442,7 @@ static cell_t smn_PbSetAngle(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *angParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &angParams);
QAngle ang(
sp_ctof(angParams[0]),
@@ -491,11 +474,7 @@ static cell_t smn_PbSetVector(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *vecParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &vecParams);
Vector vec(
sp_ctof(vecParams[0]),
@@ -527,11 +506,7 @@ static cell_t smn_PbSetVector2D(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *vecParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &vecParams);
Vector2D vec(
sp_ctof(vecParams[0]),
@@ -602,11 +577,7 @@ static cell_t smn_PbAddString(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
char *strValue;
if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToString(params[3], &strValue);
if (!msg->AddString(strField, strValue))
{
@@ -622,11 +593,7 @@ static cell_t smn_PbAddColor(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *clrParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &clrParams);
Color clr(
clrParams[0],
@@ -648,11 +615,7 @@ static cell_t smn_PbAddAngle(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *angParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &angParams);
QAngle ang(
sp_ctof(angParams[0]),
@@ -673,11 +636,7 @@ static cell_t smn_PbAddVector(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *vecParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &vecParams);
Vector vec(
sp_ctof(vecParams[0]),
@@ -698,11 +657,7 @@ static cell_t smn_PbAddVector2D(IPluginContext *pCtx, const cell_t *params)
GET_FIELD_NAME_OR_ERR();
cell_t *vecParams;
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pCtx->LocalToPhysAddr(params[3], &vecParams);
Vector2D vec(
sp_ctof(vecParams[0]),