Merge pull request #270 from alliedmodders/modernize-vm-style

Modernize sourcepawn/jit style.
This commit is contained in:
David Anderson 2015-02-23 14:38:28 -08:00
commit 7d64ade621
8 changed files with 1382 additions and 1497 deletions

View File

@ -1,4 +1,15 @@
// vim: set ts=4 sw=4 tw=99 noet:
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -14,199 +25,208 @@ using namespace SourcePawn;
SourcePawnEngine2::SourcePawnEngine2()
{
profiler_ = NULL;
jit_enabled_ = true;
profiler_ = NULL;
jit_enabled_ = true;
}
IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
IPluginRuntime *
SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
{
sp_file_hdr_t hdr;
uint8_t *base;
int z_result;
int error;
BaseRuntime *pRuntime;
sp_file_hdr_t hdr;
uint8_t *base;
int z_result;
int error;
size_t ignore;
BaseRuntime *pRuntime;
FILE *fp = fopen(file, "rb");
FILE *fp = fopen(file, "rb");
if (!fp)
{
error = SP_ERROR_NOT_FOUND;
goto return_error;
}
if (!fp) {
error = SP_ERROR_NOT_FOUND;
goto return_error;
}
/* Rewind for safety */
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
/* Rewind for safety */
ignore = fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
if (hdr.magic != SmxConsts::FILE_MAGIC)
{
error = SP_ERROR_FILE_FORMAT;
goto return_error;
}
if (hdr.magic != SmxConsts::FILE_MAGIC) {
error = SP_ERROR_FILE_FORMAT;
goto return_error;
}
switch (hdr.compression)
{
case SmxConsts::FILE_COMPRESSION_GZ:
{
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
uint32_t compsize = hdr.disksize - hdr.dataoffs;
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
uLongf destlen = uncompsize;
switch (hdr.compression)
{
case SmxConsts::FILE_COMPRESSION_GZ:
{
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
uint32_t compsize = hdr.disksize - hdr.dataoffs;
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
uLongf destlen = uncompsize;
char *tempbuf = (char *)malloc(compsize);
void *uncompdata = malloc(uncompsize);
void *sectheader = malloc(sectsize);
char *tempbuf = (char *)malloc(compsize);
void *uncompdata = malloc(uncompsize);
void *sectheader = malloc(sectsize);
fread(sectheader, sectsize, 1, fp);
fread(tempbuf, compsize, 1, fp);
ignore = fread(sectheader, sectsize, 1, fp);
ignore = fread(tempbuf, compsize, 1, fp);
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
free(tempbuf);
if (z_result != Z_OK)
{
free(sectheader);
free(uncompdata);
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
free(tempbuf);
if (z_result != Z_OK)
{
free(sectheader);
free(uncompdata);
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
base = (uint8_t *)malloc(hdr.imagesize);
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
free(sectheader);
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
free(uncompdata);
break;
}
case SmxConsts::FILE_COMPRESSION_NONE:
{
base = (uint8_t *)malloc(hdr.imagesize);
rewind(fp);
fread(base, hdr.imagesize, 1, fp);
break;
}
default:
{
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
}
base = (uint8_t *)malloc(hdr.imagesize);
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
free(sectheader);
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
free(uncompdata);
break;
}
case SmxConsts::FILE_COMPRESSION_NONE:
{
base = (uint8_t *)malloc(hdr.imagesize);
rewind(fp);
ignore = fread(base, hdr.imagesize, 1, fp);
break;
}
default:
{
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
}
pRuntime = new BaseRuntime();
if ((error = pRuntime->CreateFromMemory(&hdr, base)) != SP_ERROR_NONE)
{
delete pRuntime;
goto return_error;
}
pRuntime = new BaseRuntime();
if ((error = pRuntime->CreateFromMemory(&hdr, base)) != SP_ERROR_NONE) {
delete pRuntime;
goto return_error;
}
size_t len;
len = strlen(file);
for (size_t i = len - 1; i < len; i--)
{
if (file[i] == '/'
#if defined WIN32
|| file[i] == '\\'
#endif
)
{
pRuntime->SetName(&file[i+1]);
break;
}
}
size_t len;
len = strlen(file);
for (size_t i = len - 1; i < len; i--)
{
if (file[i] == '/'
#if defined WIN32
|| file[i] == '\\'
#endif
)
{
pRuntime->SetName(&file[i+1]);
break;
}
}
if (!pRuntime->plugin()->name)
{
pRuntime->SetName(file);
}
(void)ignore;
pRuntime->ApplyCompilationOptions(co);
if (!pRuntime->plugin()->name)
pRuntime->SetName(file);
fclose(fp);
pRuntime->ApplyCompilationOptions(co);
return pRuntime;
fclose(fp);
return pRuntime;
return_error:
*err = error;
if (fp != NULL)
{
fclose(fp);
}
*err = error;
if (fp != NULL)
{
fclose(fp);
}
return NULL;
return NULL;
}
SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
SPVM_NATIVE_FUNC
SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
{
return g_Jit.CreateFakeNative(callback, pData);
return g_Jit.CreateFakeNative(callback, pData);
}
void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
void
SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
{
g_Jit.DestroyFakeNative(func);
g_Jit.DestroyFakeNative(func);
}
const char *SourcePawnEngine2::GetEngineName()
const char *
SourcePawnEngine2::GetEngineName()
{
return "SourcePawn 1.7, jit-x86";
return "SourcePawn 1.7, jit-x86";
}
const char *SourcePawnEngine2::GetVersionString()
const char *
SourcePawnEngine2::GetVersionString()
{
return SOURCEMOD_VERSION;
return SOURCEMOD_VERSION;
}
IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
IDebugListener *
SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
{
return g_engine1.SetDebugListener(listener);
return g_engine1.SetDebugListener(listener);
}
unsigned int SourcePawnEngine2::GetAPIVersion()
unsigned int
SourcePawnEngine2::GetAPIVersion()
{
return SOURCEPAWN_ENGINE2_API_VERSION;
return SOURCEPAWN_ENGINE2_API_VERSION;
}
ICompilation *SourcePawnEngine2::StartCompilation()
ICompilation *
SourcePawnEngine2::StartCompilation()
{
return g_Jit.StartCompilation();
return g_Jit.StartCompilation();
}
const char *SourcePawnEngine2::GetErrorString(int err)
const char *
SourcePawnEngine2::GetErrorString(int err)
{
return g_engine1.GetErrorString(err);
return g_engine1.GetErrorString(err);
}
bool SourcePawnEngine2::Initialize()
bool
SourcePawnEngine2::Initialize()
{
return g_Jit.InitializeJIT();
return g_Jit.InitializeJIT();
}
void SourcePawnEngine2::Shutdown()
void
SourcePawnEngine2::Shutdown()
{
g_WatchdogTimer.Shutdown();
g_Jit.ShutdownJIT();
g_WatchdogTimer.Shutdown();
g_Jit.ShutdownJIT();
}
IPluginRuntime *SourcePawnEngine2::CreateEmptyRuntime(const char *name, uint32_t memory)
IPluginRuntime *
SourcePawnEngine2::CreateEmptyRuntime(const char *name, uint32_t memory)
{
int err;
BaseRuntime *rt;
int err;
rt = new BaseRuntime();
if ((err = rt->CreateBlank(memory)) != SP_ERROR_NONE)
{
delete rt;
return NULL;
}
BaseRuntime *rt = new BaseRuntime();
if ((err = rt->CreateBlank(memory)) != SP_ERROR_NONE) {
delete rt;
return NULL;
}
rt->SetName(name != NULL ? name : "<anonymous>");
rt->SetName(name != NULL ? name : "<anonymous>");
rt->ApplyCompilationOptions(NULL);
return rt;
rt->ApplyCompilationOptions(NULL);
return rt;
}
bool SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms)
bool
SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms)
{
return g_WatchdogTimer.Initialize(timeout_ms);
return g_WatchdogTimer.Initialize(timeout_ms);
}

View File

@ -1,86 +1,100 @@
// vim: set ts=4 sw=4 tw=99 noet:
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_
#define _INCLUDE_SOURCEPAWN_ENGINE_2_H_
#include <sp_vm_api.h>
namespace SourcePawn
namespace SourcePawn {
/**
* @brief Outlines the interface a Virtual Machine (JIT) must expose
*/
class SourcePawnEngine2 : public ISourcePawnEngine2
{
/**
* @brief Outlines the interface a Virtual Machine (JIT) must expose
*/
class SourcePawnEngine2 : public ISourcePawnEngine2
{
public:
SourcePawnEngine2();
public:
unsigned int GetAPIVersion();
const char *GetEngineName();
const char *GetVersionString();
IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err);
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
IDebugListener *SetDebugListener(IDebugListener *listener);
ICompilation *StartCompilation();
const char *GetErrorString(int err);
bool Initialize();
void Shutdown();
IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory);
bool InstallWatchdogTimer(size_t timeout_ms);
public:
SourcePawnEngine2();
bool SetJitEnabled(bool enabled) {
jit_enabled_ = enabled;
return true;
}
public:
unsigned int GetAPIVersion();
const char *GetEngineName();
const char *GetVersionString();
IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err);
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
IDebugListener *SetDebugListener(IDebugListener *listener);
ICompilation *StartCompilation();
const char *GetErrorString(int err);
bool Initialize();
void Shutdown();
IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory);
bool InstallWatchdogTimer(size_t timeout_ms);
bool IsJitEnabled() {
return jit_enabled_;
}
bool SetJitEnabled(bool enabled) {
jit_enabled_ = enabled;
return true;
}
void SetProfiler(IProfiler *profiler) {
// Deprecated.
}
bool IsJitEnabled() {
return jit_enabled_;
}
void EnableProfiling() {
profiling_enabled_ = !!profiler_;
}
void DisableProfiling() {
profiling_enabled_ = false;
}
bool IsProfilingEnabled() {
return profiling_enabled_;
}
void SetProfilingTool(IProfilingTool *tool) {
profiler_ = tool;
}
void SetProfiler(IProfiler *profiler) {
// Deprecated.
}
public:
IProfilingTool *GetProfiler() {
return profiler_;
}
private:
IProfilingTool *profiler_;
bool jit_enabled_;
bool profiling_enabled_;
};
}
void EnableProfiling() {
profiling_enabled_ = !!profiler_;
}
void DisableProfiling() {
profiling_enabled_ = false;
}
bool IsProfilingEnabled() {
return profiling_enabled_;
}
void SetProfilingTool(IProfilingTool *tool) {
profiler_ = tool;
}
public:
IProfilingTool *GetProfiler() {
return profiler_;
}
private:
IProfilingTool *profiler_;
bool jit_enabled_;
bool profiling_enabled_;
};
} // namespace SourcePawn
extern SourcePawn::SourcePawnEngine2 g_engine2;
class EnterProfileScope
{
public:
EnterProfileScope(const char *group, const char *name)
{
if (g_engine2.IsProfilingEnabled())
g_engine2.GetProfiler()->EnterScope(group, name);
}
public:
EnterProfileScope(const char *group, const char *name)
{
if (g_engine2.IsProfilingEnabled())
g_engine2.GetProfiler()->EnterScope(group, name);
}
~EnterProfileScope()
{
if (g_engine2.IsProfilingEnabled())
g_engine2.GetProfiler()->LeaveScope();
}
~EnterProfileScope()
{
if (g_engine2.IsProfilingEnabled())
g_engine2.GetProfiler()->LeaveScope();
}
};
#endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,15 @@
/**
* vim: set ts=4 :
* =============================================================================
* 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>.
*
* Version: $Id$
*/
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
@ -43,72 +24,76 @@
class BaseContext : public IPluginContext
{
public:
BaseContext(BaseRuntime *pRuntime);
~BaseContext();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
sp_context_t *GetCtx();
bool IsDebugging();
int SetDebugBreak(void *newpfn, void *oldpfn);
IPluginDebugInfo *GetDebugInfo();
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
int HeapPop(cell_t local_addr);
int HeapRelease(cell_t local_addr);
int FindNativeByName(const char *name, uint32_t *index);
int GetNativeByIndex(uint32_t index, sp_native_t **native);
uint32_t GetNativesNum();
int FindPublicByName(const char *name, uint32_t *index);
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
uint32_t GetPublicsNum();
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
int FindPubvarByName(const char *name, uint32_t *index);
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
uint32_t GetPubVarsNum();
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
int LocalToString(cell_t local_addr, char **addr);
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
int PushCell(cell_t value);
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
int PushCellsFromArray(cell_t array[], unsigned int numcells);
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
int BindNative(const sp_nativeinfo_t *native);
int BindNativeToAny(SPVM_NATIVE_FUNC native);
int Execute(uint32_t code_addr, cell_t *result);
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
cell_t ThrowNativeError(const char *msg, ...);
IPluginFunction *GetFunctionByName(const char *public_name);
IPluginFunction *GetFunctionById(funcid_t func_id);
SourceMod::IdentityToken_t *GetIdentity();
cell_t *GetNullRef(SP_NULL_TYPE type);
int LocalToStringNULL(cell_t local_addr, char **addr);
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
int Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
IPluginRuntime *GetRuntime();
int GetLastNativeError();
cell_t *GetLocalParams();
void SetKey(int k, void *value);
bool GetKey(int k, void **value);
void Refresh();
void ClearLastNativeError();
public:
bool IsInExec();
private:
void SetErrorMessage(const char *msg, va_list ap);
void _SetErrorMessage(const char *msg, ...);
private:
cell_t *m_pNullVec;
cell_t *m_pNullString;
char m_MsgCache[1024];
bool m_CustomMsg;
bool m_InExec;
BaseRuntime *m_pRuntime;
sp_context_t m_ctx;
void *m_keys[4];
bool m_keys_set[4];
public:
BaseContext(BaseRuntime *pRuntime);
~BaseContext();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
sp_context_t *GetCtx();
bool IsDebugging();
int SetDebugBreak(void *newpfn, void *oldpfn);
IPluginDebugInfo *GetDebugInfo();
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
int HeapPop(cell_t local_addr);
int HeapRelease(cell_t local_addr);
int FindNativeByName(const char *name, uint32_t *index);
int GetNativeByIndex(uint32_t index, sp_native_t **native);
uint32_t GetNativesNum();
int FindPublicByName(const char *name, uint32_t *index);
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
uint32_t GetPublicsNum();
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
int FindPubvarByName(const char *name, uint32_t *index);
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
uint32_t GetPubVarsNum();
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
int LocalToString(cell_t local_addr, char **addr);
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
int PushCell(cell_t value);
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
int PushCellsFromArray(cell_t array[], unsigned int numcells);
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
int BindNative(const sp_nativeinfo_t *native);
int BindNativeToAny(SPVM_NATIVE_FUNC native);
int Execute(uint32_t code_addr, cell_t *result);
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
cell_t ThrowNativeError(const char *msg, ...);
IPluginFunction *GetFunctionByName(const char *public_name);
IPluginFunction *GetFunctionById(funcid_t func_id);
SourceMod::IdentityToken_t *GetIdentity();
cell_t *GetNullRef(SP_NULL_TYPE type);
int LocalToStringNULL(cell_t local_addr, char **addr);
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
int Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
IPluginRuntime *GetRuntime();
int GetLastNativeError();
cell_t *GetLocalParams();
void SetKey(int k, void *value);
bool GetKey(int k, void **value);
void Refresh();
void ClearLastNativeError();
public:
bool IsInExec();
private:
void SetErrorMessage(const char *msg, va_list ap);
void _SetErrorMessage(const char *msg, ...);
private:
cell_t *m_pNullVec;
cell_t *m_pNullString;
char m_MsgCache[1024];
bool m_CustomMsg;
bool m_InExec;
BaseRuntime *m_pRuntime;
sp_context_t m_ctx;
void *m_keys[4];
bool m_keys_set[4];
};
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_

View File

@ -1,34 +1,15 @@
/**
* vim: set ts=4 sw=4 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>.
*
* Version: $Id$
*/
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@ -57,298 +38,294 @@ SourcePawnEngine g_engine1;
using namespace SourcePawn;
#define ERROR_MESSAGE_MAX 30
#define ERROR_MESSAGE_MAX 30
static const char *g_ErrorMsgTable[] =
{
NULL,
"Unrecognizable file format",
"Decompressor was not found",
"Not enough space on the heap",
"Invalid parameter or parameter type",
"Invalid plugin address",
"Object or index not found",
"Invalid index or index not found",
"Not enough space on the stack",
"Debug section not found or debug not enabled",
"Invalid instruction",
"Invalid memory access",
"Stack went below stack boundary",
"Heap went below heap boundary",
"Divide by zero",
"Array index is out of bounds",
"Instruction contained invalid parameter",
"Stack memory leaked by native",
"Heap memory leaked by native",
"Dynamic array is too big",
"Tracker stack is out of bounds",
"Native is not bound",
"Maximum number of parameters reached",
"Native detected error",
"Plugin not runnable",
"Call was aborted",
"Plugin format is too old",
"Plugin format is too new",
"Out of memory",
"Integer overflow",
"Script execution timed out"
NULL,
"Unrecognizable file format",
"Decompressor was not found",
"Not enough space on the heap",
"Invalid parameter or parameter type",
"Invalid plugin address",
"Object or index not found",
"Invalid index or index not found",
"Not enough space on the stack",
"Debug section not found or debug not enabled",
"Invalid instruction",
"Invalid memory access",
"Stack went below stack boundary",
"Heap went below heap boundary",
"Divide by zero",
"Array index is out of bounds",
"Instruction contained invalid parameter",
"Stack memory leaked by native",
"Heap memory leaked by native",
"Dynamic array is too big",
"Tracker stack is out of bounds",
"Native is not bound",
"Maximum number of parameters reached",
"Native detected error",
"Plugin not runnable",
"Call was aborted",
"Plugin format is too old",
"Plugin format is too new",
"Out of memory",
"Integer overflow",
"Script execution timed out"
};
const char *SourcePawnEngine::GetErrorString(int error)
const char *
SourcePawnEngine::GetErrorString(int error)
{
if (error < 1 || error > ERROR_MESSAGE_MAX)
{
return NULL;
}
return g_ErrorMsgTable[error];
if (error < 1 || error > ERROR_MESSAGE_MAX)
return NULL;
return g_ErrorMsgTable[error];
}
SourcePawnEngine::SourcePawnEngine()
{
m_pDebugHook = NULL;
m_pDebugHook = NULL;
}
SourcePawnEngine::~SourcePawnEngine()
{
}
void *SourcePawnEngine::ExecAlloc(size_t size)
void *
SourcePawnEngine::ExecAlloc(size_t size)
{
#if defined WIN32
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined __GNUC__
# if defined __APPLE__
void *base = valloc(size);
void *base = valloc(size);
# else
void *base = memalign(sysconf(_SC_PAGESIZE), size);
void *base = memalign(sysconf(_SC_PAGESIZE), size);
# endif
if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
{
free(base);
return NULL;
}
return base;
if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
free(base);
return NULL;
}
return base;
#endif
}
void *SourcePawnEngine::AllocatePageMemory(size_t size)
void *
SourcePawnEngine::AllocatePageMemory(size_t size)
{
return g_Jit.AllocCode(size);
return g_Jit.AllocCode(size);
}
void SourcePawnEngine::SetReadExecute(void *ptr)
void
SourcePawnEngine::SetReadExecute(void *ptr)
{
/* already re */
/* already re */
}
void SourcePawnEngine::SetReadWrite(void *ptr)
void
SourcePawnEngine::SetReadWrite(void *ptr)
{
/* already rw */
/* already rw */
}
void SourcePawnEngine::FreePageMemory(void *ptr)
void
SourcePawnEngine::FreePageMemory(void *ptr)
{
g_Jit.FreeCode(ptr);
g_Jit.FreeCode(ptr);
}
void SourcePawnEngine::ExecFree(void *address)
void
SourcePawnEngine::ExecFree(void *address)
{
#if defined WIN32
VirtualFree(address, 0, MEM_RELEASE);
VirtualFree(address, 0, MEM_RELEASE);
#elif defined __GNUC__
free(address);
free(address);
#endif
}
void SourcePawnEngine::SetReadWriteExecute(void *ptr)
void
SourcePawnEngine::SetReadWriteExecute(void *ptr)
{
//:TODO: g_ExeMemory.SetRWE(ptr);
SetReadExecute(ptr);
//:TODO: g_ExeMemory.SetRWE(ptr);
SetReadExecute(ptr);
}
void *SourcePawnEngine::BaseAlloc(size_t size)
void *
SourcePawnEngine::BaseAlloc(size_t size)
{
return malloc(size);
return malloc(size);
}
void SourcePawnEngine::BaseFree(void *memory)
void
SourcePawnEngine::BaseFree(void *memory)
{
free(memory);
free(memory);
}
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
sp_plugin_t *
SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
{
if (err != NULL)
{
*err = SP_ERROR_ABORTED;
}
if (err != NULL)
*err = SP_ERROR_ABORTED;
return NULL;
return NULL;
}
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
sp_plugin_t *
SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
{
if (err != NULL)
{
*err = SP_ERROR_ABORTED;
}
if (err != NULL)
*err = SP_ERROR_ABORTED;
return NULL;
return NULL;
}
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
int
SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
{
return SP_ERROR_ABORTED;
return SP_ERROR_ABORTED;
}
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
IDebugListener *
SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{
IDebugListener *old = m_pDebugHook;
IDebugListener *old = m_pDebugHook;
m_pDebugHook = pListener;
m_pDebugHook = pListener;
return old;
return old;
}
unsigned int SourcePawnEngine::GetEngineAPIVersion()
unsigned int
SourcePawnEngine::GetEngineAPIVersion()
{
return SOURCEPAWN_ENGINE_API_VERSION;
return SOURCEPAWN_ENGINE_API_VERSION;
}
unsigned int SourcePawnEngine::GetContextCallCount()
unsigned int
SourcePawnEngine::GetContextCallCount()
{
return 0;
return 0;
}
void SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start)
void
SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start)
{
if (m_pDebugHook == NULL)
{
return;
}
if (m_pDebugHook == NULL)
return;
CContextTrace trace(runtime, err, errstr, rp_start);
CContextTrace trace(runtime, err, errstr, rp_start);
m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace);
m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace);
}
CContextTrace::CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp)
: m_pRuntime(pRuntime), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), m_Level(0)
: m_pRuntime(pRuntime),
m_Error(err),
m_pMsg(errstr),
m_StartRp(start_rp),
m_Level(0)
{
m_ctx = pRuntime->m_pCtx->GetCtx();
m_pDebug = m_pRuntime->GetDebugInfo();
m_ctx = pRuntime->m_pCtx->GetCtx();
m_pDebug = m_pRuntime->GetDebugInfo();
}
bool CContextTrace::DebugInfoAvailable()
bool
CContextTrace::DebugInfoAvailable()
{
return (m_pDebug != NULL);
return (m_pDebug != NULL);
}
const char *CContextTrace::GetCustomErrorString()
const char *
CContextTrace::GetCustomErrorString()
{
return m_pMsg;
return m_pMsg;
}
int CContextTrace::GetErrorCode()
int
CContextTrace::GetErrorCode()
{
return m_Error;
return m_Error;
}
const char *CContextTrace::GetErrorString()
const char *
CContextTrace::GetErrorString()
{
if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1)
{
return "Invalid error code";
}
else
{
return g_ErrorMsgTable[m_Error];
}
if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1)
return "Invalid error code";
return g_ErrorMsgTable[m_Error];
}
void CContextTrace::ResetTrace()
void
CContextTrace::ResetTrace()
{
m_Level = 0;
m_Level = 0;
}
bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
bool
CContextTrace::GetTraceInfo(CallStackInfo *trace)
{
cell_t cip;
cell_t cip;
if (m_Level == 0)
{
cip = m_ctx->cip;
}
else if (m_ctx->rp > 0)
{
/* Entries go from ctx.rp - 1 to m_StartRp */
cell_t offs, start, end;
if (m_Level == 0) {
cip = m_ctx->cip;
} else if (m_ctx->rp > 0) {
/* Entries go from ctx.rp - 1 to m_StartRp */
cell_t offs, start, end;
offs = m_Level - 1;
start = m_ctx->rp - 1;
end = m_StartRp;
offs = m_Level - 1;
start = m_ctx->rp - 1;
end = m_StartRp;
if (start - offs < end)
{
return false;
}
if (start - offs < end)
{
return false;
}
cip = m_ctx->rstk_cips[start - offs];
}
else
{
return false;
}
cip = m_ctx->rstk_cips[start - offs];
} else {
return false;
}
if (trace == NULL)
{
m_Level++;
return true;
}
if (trace == NULL) {
m_Level++;
return true;
}
if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE)
{
trace->filename = NULL;
}
if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE)
trace->filename = NULL;
if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE)
{
trace->function = NULL;
}
if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE)
trace->function = NULL;
if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE)
{
trace->line = 0;
}
if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE)
trace->line = 0;
m_Level++;
m_Level++;
return true;
return true;
}
const char *CContextTrace::GetLastNative(uint32_t *index)
const char *
CContextTrace::GetLastNative(uint32_t *index)
{
if (m_ctx->n_err == SP_ERROR_NONE)
{
return NULL;
}
if (m_ctx->n_err == SP_ERROR_NONE)
return NULL;
sp_native_t *native;
if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE)
{
return NULL;
}
sp_native_t *native;
if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE)
return NULL;
if (index)
{
*index = m_ctx->n_idx;
}
if (index)
*index = m_ctx->n_idx;
return native->name;
return native->name;
}
IDebugListener *SourcePawnEngine::GetDebugHook()
IDebugListener *
SourcePawnEngine::GetDebugHook()
{
return m_pDebugHook;
return m_pDebugHook;
}

View File

@ -1,34 +1,15 @@
/**
* vim: set ts=4 :
* =============================================================================
* 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>.
*
* Version: $Id$
*/
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_VM_ENGINE_H_
#define _INCLUDE_SOURCEPAWN_VM_ENGINE_H_
@ -39,55 +20,60 @@ class BaseContext;
class CContextTrace : public IContextTrace
{
public:
CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp);
public:
int GetErrorCode();
const char *GetErrorString();
bool DebugInfoAvailable();
const char *GetCustomErrorString();
bool GetTraceInfo(CallStackInfo *trace);
void ResetTrace();
const char *GetLastNative(uint32_t *index);
private:
BaseRuntime *m_pRuntime;
sp_context_t *m_ctx;
int m_Error;
const char *m_pMsg;
cell_t m_StartRp;
cell_t m_Level;
IPluginDebugInfo *m_pDebug;
public:
CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp);
public:
int GetErrorCode();
const char *GetErrorString();
bool DebugInfoAvailable();
const char *GetCustomErrorString();
bool GetTraceInfo(CallStackInfo *trace);
void ResetTrace();
const char *GetLastNative(uint32_t *index);
private:
BaseRuntime *m_pRuntime;
sp_context_t *m_ctx;
int m_Error;
const char *m_pMsg;
cell_t m_StartRp;
cell_t m_Level;
IPluginDebugInfo *m_pDebug;
};
class SourcePawnEngine : public ISourcePawnEngine
{
public:
SourcePawnEngine();
~SourcePawnEngine();
public: //ISourcePawnEngine
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
int FreeFromMemory(sp_plugin_t *plugin);
void *BaseAlloc(size_t size);
void BaseFree(void *memory);
void *ExecAlloc(size_t size);
void ExecFree(void *address);
IDebugListener *SetDebugListener(IDebugListener *pListener);
unsigned int GetContextCallCount();
unsigned int GetEngineAPIVersion();
void *AllocatePageMemory(size_t size);
void SetReadWrite(void *ptr);
void SetReadExecute(void *ptr);
void SetReadWriteExecute(void *ptr);
void FreePageMemory(void *ptr);
const char *GetErrorString(int err);
void ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start);
public: //Plugin function stuff
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func);
IDebugListener *GetDebugHook();
private:
IDebugListener *m_pDebugHook;
public:
SourcePawnEngine();
~SourcePawnEngine();
public: //ISourcePawnEngine
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
int FreeFromMemory(sp_plugin_t *plugin);
void *BaseAlloc(size_t size);
void BaseFree(void *memory);
void *ExecAlloc(size_t size);
void ExecFree(void *address);
IDebugListener *SetDebugListener(IDebugListener *pListener);
unsigned int GetContextCallCount();
unsigned int GetEngineAPIVersion();
void *AllocatePageMemory(size_t size);
void SetReadWrite(void *ptr);
void SetReadExecute(void *ptr);
void SetReadWriteExecute(void *ptr);
void FreePageMemory(void *ptr);
const char *GetErrorString(int err);
void ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start);
public: //Plugin function stuff
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func);
IDebugListener *GetDebugHook();
private:
IDebugListener *m_pDebugHook;
};
extern SourcePawnEngine g_engine1;

View File

@ -1,31 +1,15 @@
/**
* 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>.
*/
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <string.h>
@ -38,319 +22,303 @@
CFunction::~CFunction()
{
delete [] full_name_;
delete [] full_name_;
}
bool CFunction::IsRunnable()
bool
CFunction::IsRunnable()
{
return !m_pRuntime->IsPaused();
return !m_pRuntime->IsPaused();
}
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
int
CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
{
return CallFunction2(m_pRuntime->GetDefaultContext(), params, num_params, result);
return CallFunction2(m_pRuntime->GetDefaultContext(), params, num_params, result);
}
int CFunction::CallFunction2(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
int
CFunction::CallFunction2(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
{
return pContext->Execute2(this, params, num_params, result);
return pContext->Execute2(this, params, num_params, result);
}
IPluginContext *CFunction::GetParentContext()
IPluginContext *
CFunction::GetParentContext()
{
return m_pRuntime->GetDefaultContext();
return m_pRuntime->GetDefaultContext();
}
CFunction::CFunction(BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
CFunction::CFunction(BaseRuntime *runtime, funcid_t id, uint32_t pub_id)
: m_curparam(0),
m_errorstate(SP_ERROR_NONE),
m_FnId(id)
{
m_pRuntime = runtime;
m_pRuntime = runtime;
runtime->GetPublicByIndex(pub_id, &public_);
runtime->GetPublicByIndex(pub_id, &public_);
size_t rt_len = strlen(runtime->plugin()->name);
size_t len = rt_len + strlen("::") + strlen(public_->name);
size_t rt_len = strlen(runtime->plugin()->name);
size_t len = rt_len + strlen("::") + strlen(public_->name);
full_name_ = new char[len + 1];
strcpy(full_name_, runtime->plugin()->name);
strcpy(&full_name_[rt_len], "::");
strcpy(&full_name_[rt_len + 2], public_->name);
full_name_ = new char[len + 1];
strcpy(full_name_, runtime->plugin()->name);
strcpy(&full_name_[rt_len], "::");
strcpy(&full_name_[rt_len + 2], public_->name);
}
int CFunction::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
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++;
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
return SP_ERROR_NONE;
}
int CFunction::PushCellByRef(cell_t *cell, int flags)
int
CFunction::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
return PushArray(cell, 1, flags);
}
int CFunction::PushFloat(float number)
int
CFunction::PushFloat(float number)
{
cell_t val = *(cell_t *)&number;
cell_t val = *(cell_t *)&number;
return PushCell(val);
return PushCell(val);
}
int CFunction::PushFloatByRef(float *number, int flags)
int
CFunction::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
return PushCellByRef((cell_t *)number, flags);
}
int CFunction::PushArray(cell_t *inarray, unsigned int cells, int copyback)
int
CFunction::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
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;
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
m_curparam++;
return SP_ERROR_NONE;
return SP_ERROR_NONE;
}
int CFunction::PushString(const char *string)
int
CFunction::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int CFunction::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
int
CFunction::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
return _PushString(buffer, sz_flags, cp_flags, length);
}
int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
int
CFunction::_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);
}
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
ParamInfo *info = &m_info[m_curparam];
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;
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++;
m_curparam++;
return SP_ERROR_NONE;
return SP_ERROR_NONE;
}
void CFunction::Cancel()
void
CFunction::Cancel()
{
if (!m_curparam)
{
return;
}
if (!m_curparam)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
}
int CFunction::Execute(cell_t *result)
int
CFunction::Execute(cell_t *result)
{
return Execute2(m_pRuntime->GetDefaultContext(), result);
return Execute2(m_pRuntime->GetDefaultContext(), result);
}
int CFunction::Execute2(IPluginContext *ctx, cell_t *result)
int
CFunction::Execute2(IPluginContext *ctx, cell_t *result)
{
int err = SP_ERROR_NONE;
int err = SP_ERROR_NONE;
if (!IsRunnable())
{
m_errorstate = SP_ERROR_NOT_RUNNABLE;
}
if (!IsRunnable())
m_errorstate = SP_ERROR_NOT_RUNNABLE;
if (m_errorstate != SP_ERROR_NONE)
{
err = m_errorstate;
Cancel();
return err;
}
if (m_errorstate != SP_ERROR_NONE) {
err = m_errorstate;
Cancel();
return err;
}
//This is for re-entrancy!
cell_t temp_params[SP_MAX_EXEC_PARAMS];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
bool docopies = true;
//This is for re-entrancy!
cell_t temp_params[SP_MAX_EXEC_PARAMS];
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;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
/* 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);
/* 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];
}
}
/* 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)
{
if ((err = CallFunction2(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
{
docopies = false;
}
}
else
{
docopies = false;
}
/* Make the call if we can */
if (err == SP_ERROR_NONE) {
if ((err = CallFunction2(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
docopies = false;
} else {
docopies = false;
}
/* i should be equal to the last valid parameter + 1 */
while (i--)
{
if (!temp_info[i].marked)
{
continue;
}
/* 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 (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;
}
}
if ((err=ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
return err;
}
return err;
return err;
}
IPluginRuntime *CFunction::GetParentRuntime()
IPluginRuntime *
CFunction::GetParentRuntime()
{
return m_pRuntime;
return m_pRuntime;
}
funcid_t CFunction::GetFunctionID()
funcid_t
CFunction::GetFunctionID()
{
return m_FnId;
return m_FnId;
}
int CFunction::SetError(int err)
int
CFunction::SetError(int err)
{
m_errorstate = err;
m_errorstate = err;
return err;
return err;
}

View File

@ -1,32 +1,15 @@
/**
* 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>.
*/
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
@ -38,17 +21,16 @@ 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;
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 CPlugin;
@ -56,51 +38,54 @@ class JitFunction;
class CFunction : public IPluginFunction
{
friend class SourcePawnEngine;
public:
CFunction(BaseRuntime *pRuntime,
funcid_t fnid,
uint32_t pub_id);
~CFunction();
public:
virtual int PushCell(cell_t cell);
virtual int PushCellByRef(cell_t *cell, int flags);
virtual int PushFloat(float number);
virtual int PushFloatByRef(float *number, int flags);
virtual int PushArray(cell_t *inarray, unsigned int cells, int copyback);
virtual int PushString(const char *string);
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
virtual int Execute(cell_t *result);
virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext();
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
int CallFunction2(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
IPluginRuntime *GetParentRuntime();
public:
const char *FullName() const {
return full_name_;
}
sp_public_t *Public() const {
return public_;
}
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
BaseRuntime *m_pRuntime;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
funcid_t m_FnId;
char *full_name_;
sp_public_t *public_;
friend class SourcePawnEngine;
public:
CFunction(BaseRuntime *pRuntime, funcid_t fnid, uint32_t pub_id);
~CFunction();
public:
virtual int PushCell(cell_t cell);
virtual int PushCellByRef(cell_t *cell, int flags);
virtual int PushFloat(float number);
virtual int PushFloatByRef(float *number, int flags);
virtual int PushArray(cell_t *inarray, unsigned int cells, int copyback);
virtual int PushString(const char *string);
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
virtual int Execute(cell_t *result);
virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext();
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
int CallFunction2(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
IPluginRuntime *GetParentRuntime();
public:
const char *FullName() const {
return full_name_;
}
sp_public_t *Public() const {
return public_;
}
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
BaseRuntime *m_pRuntime;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
funcid_t m_FnId;
char *full_name_;
sp_public_t *public_;
};
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_