From 45c43f4aee40192e59bfca9153904135ad1560f4 Mon Sep 17 00:00:00 2001 From: "dvander@alliedmods.net" Date: Mon, 23 Feb 2015 13:40:01 -0800 Subject: [PATCH] Modernize sp_vm_basecontext. --- sourcepawn/jit/sp_vm_basecontext.cpp | 1098 ++++++++++++-------------- sourcepawn/jit/sp_vm_basecontext.h | 179 ++--- 2 files changed, 606 insertions(+), 671 deletions(-) diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp index dbd4c1dd..f7a9e10b 100644 --- a/sourcepawn/jit/sp_vm_basecontext.cpp +++ b/sourcepawn/jit/sp_vm_basecontext.cpp @@ -1,34 +1,15 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet: - * ============================================================================= - * 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 . - * - * 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 . - * - * 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 #include #include @@ -43,652 +24,636 @@ using namespace SourcePawn; -#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t)) -#define STACKMARGIN ((cell_t)(16*sizeof(cell_t))) +#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t)) +#define STACKMARGIN ((cell_t)(16*sizeof(cell_t))) BaseContext::BaseContext(BaseRuntime *pRuntime) { - m_pRuntime = pRuntime; + m_pRuntime = pRuntime; - m_InExec = false; - m_CustomMsg = false; + m_InExec = false; + m_CustomMsg = false; - /* Initialize the null references */ - uint32_t index; - if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE) - { - sp_pubvar_t *pubvar; - GetPubvarByIndex(index, &pubvar); - m_pNullVec = pubvar->offs; - } - else - { - m_pNullVec = NULL; - } + /* Initialize the null references */ + uint32_t index; + if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE) { + sp_pubvar_t *pubvar; + GetPubvarByIndex(index, &pubvar); + m_pNullVec = pubvar->offs; + } else { + m_pNullVec = NULL; + } - if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE) - { - sp_pubvar_t *pubvar; - GetPubvarByIndex(index, &pubvar); - m_pNullString = pubvar->offs; - } - else - { - m_pNullString = NULL; - } + if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE) { + sp_pubvar_t *pubvar; + GetPubvarByIndex(index, &pubvar); + m_pNullString = pubvar->offs; + } else { + m_pNullString = NULL; + } - m_ctx.hp = m_pRuntime->plugin()->data_size; - m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); - m_ctx.frm = m_ctx.sp; - m_ctx.n_err = SP_ERROR_NONE; - m_ctx.n_idx = SP_ERROR_NONE; - m_ctx.rp = 0; + m_ctx.hp = m_pRuntime->plugin()->data_size; + m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); + m_ctx.frm = m_ctx.sp; + m_ctx.n_err = SP_ERROR_NONE; + m_ctx.n_idx = SP_ERROR_NONE; + m_ctx.rp = 0; - g_Jit.SetupContextVars(m_pRuntime, this, &m_ctx); + g_Jit.SetupContextVars(m_pRuntime, this, &m_ctx); } BaseContext::~BaseContext() { - g_Jit.FreeContextVars(&m_ctx); + g_Jit.FreeContextVars(&m_ctx); } -IVirtualMachine *BaseContext::GetVirtualMachine() +IVirtualMachine * +BaseContext::GetVirtualMachine() { - return NULL; + return NULL; } -sp_context_t *BaseContext::GetContext() +sp_context_t * +BaseContext::GetContext() { - return reinterpret_cast((IPluginContext * )this); + return reinterpret_cast((IPluginContext * )this); } -sp_context_t *BaseContext::GetCtx() +sp_context_t * +BaseContext::GetCtx() { - return &m_ctx; + return &m_ctx; } -bool BaseContext::IsDebugging() +bool +BaseContext::IsDebugging() { - return true; + return true; } -int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn) +int +BaseContext::SetDebugBreak(void *newpfn, void *oldpfn) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -IPluginDebugInfo *BaseContext::GetDebugInfo() +IPluginDebugInfo * +BaseContext::GetDebugInfo() { - return NULL; + return NULL; } -int BaseContext::Execute(uint32_t code_addr, cell_t *result) +int +BaseContext::Execute(uint32_t code_addr, cell_t *result) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -void BaseContext::SetErrorMessage(const char *msg, va_list ap) +void +BaseContext::SetErrorMessage(const char *msg, va_list ap) { - m_CustomMsg = true; + m_CustomMsg = true; - vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap); + vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap); } -void BaseContext::_SetErrorMessage(const char *msg, ...) +void +BaseContext::_SetErrorMessage(const char *msg, ...) { - va_list ap; - va_start(ap, msg); - SetErrorMessage(msg, ap); - va_end(ap); + va_list ap; + va_start(ap, msg); + SetErrorMessage(msg, ap); + va_end(ap); } -cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...) +cell_t +BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...) { - if (!m_InExec) - { - return 0; - } + if (!m_InExec) + return 0; - m_ctx.n_err = error; - - if (msg) - { - va_list ap; - va_start(ap, msg); - SetErrorMessage(msg, ap); - va_end(ap); - } + m_ctx.n_err = error; + + if (msg) { + va_list ap; + va_start(ap, msg); + SetErrorMessage(msg, ap); + va_end(ap); + } - return 0; + return 0; } -cell_t BaseContext::ThrowNativeError(const char *msg, ...) +cell_t +BaseContext::ThrowNativeError(const char *msg, ...) { - if (!m_InExec) - { - return 0; - } + if (!m_InExec) + return 0; - m_ctx.n_err = SP_ERROR_NATIVE; + m_ctx.n_err = SP_ERROR_NATIVE; - if (msg) - { - va_list ap; - va_start(ap, msg); - SetErrorMessage(msg, ap); - va_end(ap); - } + if (msg) { + va_list ap; + va_start(ap, msg); + SetErrorMessage(msg, ap); + va_end(ap); + } - return 0; + return 0; } -int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) +int +BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) { - cell_t *addr; - ucell_t realmem; + cell_t *addr; + ucell_t realmem; #if 0 - if (cells > CELLBOUNDMAX) - { - return SP_ERROR_ARAM; - } + if (cells > CELLBOUNDMAX) + { + return SP_ERROR_ARAM; + } #else - assert(cells < CELLBOUNDMAX); + assert(cells < CELLBOUNDMAX); #endif - realmem = cells * sizeof(cell_t); + realmem = cells * sizeof(cell_t); - /** - * Check if the space between the heap and stack is sufficient. - */ - if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN) - { - return SP_ERROR_HEAPLOW; - } + /** + * Check if the space between the heap and stack is sufficient. + */ + if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN) + return SP_ERROR_HEAPLOW; - addr = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.hp); - /* store size of allocation in cells */ - *addr = (cell_t)cells; - addr++; - m_ctx.hp += sizeof(cell_t); + addr = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.hp); + /* store size of allocation in cells */ + *addr = (cell_t)cells; + addr++; + m_ctx.hp += sizeof(cell_t); - *local_addr = m_ctx.hp; + *local_addr = m_ctx.hp; - if (phys_addr) - { - *phys_addr = addr; - } + if (phys_addr) + *phys_addr = addr; - m_ctx.hp += realmem; + m_ctx.hp += realmem; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -int BaseContext::HeapPop(cell_t local_addr) +int +BaseContext::HeapPop(cell_t local_addr) { - cell_t cellcount; - cell_t *addr; + cell_t cellcount; + cell_t *addr; - /* check the bounds of this address */ - local_addr -= sizeof(cell_t); - if (local_addr < (cell_t)m_pRuntime->plugin()->data_size || local_addr >= m_ctx.sp) - { - return SP_ERROR_INVALID_ADDRESS; - } + /* check the bounds of this address */ + local_addr -= sizeof(cell_t); + if (local_addr < (cell_t)m_pRuntime->plugin()->data_size || local_addr >= m_ctx.sp) + return SP_ERROR_INVALID_ADDRESS; - addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); - cellcount = (*addr) * sizeof(cell_t); - /* check if this memory count looks valid */ - if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr) - { - return SP_ERROR_INVALID_ADDRESS; - } + addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); + cellcount = (*addr) * sizeof(cell_t); + /* check if this memory count looks valid */ + if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr) + return SP_ERROR_INVALID_ADDRESS; - m_ctx.hp = local_addr; + m_ctx.hp = local_addr; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -int BaseContext::HeapRelease(cell_t local_addr) +int +BaseContext::HeapRelease(cell_t local_addr) { - if (local_addr < (cell_t)m_pRuntime->plugin()->data_size) - { - return SP_ERROR_INVALID_ADDRESS; - } + if (local_addr < (cell_t)m_pRuntime->plugin()->data_size) + return SP_ERROR_INVALID_ADDRESS; - m_ctx.hp = local_addr - sizeof(cell_t); + m_ctx.hp = local_addr - sizeof(cell_t); - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -int BaseContext::FindNativeByName(const char *name, uint32_t *index) +int +BaseContext::FindNativeByName(const char *name, uint32_t *index) { - return m_pRuntime->FindNativeByName(name, index); + return m_pRuntime->FindNativeByName(name, index); } -int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native) +int +BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native) { - return m_pRuntime->GetNativeByIndex(index, native); + return m_pRuntime->GetNativeByIndex(index, native); } - -uint32_t BaseContext::GetNativesNum() +uint32_t +BaseContext::GetNativesNum() { - return m_pRuntime->GetNativesNum(); + return m_pRuntime->GetNativesNum(); } -int BaseContext::FindPublicByName(const char *name, uint32_t *index) +int +BaseContext::FindPublicByName(const char *name, uint32_t *index) { - return m_pRuntime->FindPublicByName(name, index); + return m_pRuntime->FindPublicByName(name, index); } -int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic) +int +BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic) { - return m_pRuntime->GetPublicByIndex(index, pblic); + return m_pRuntime->GetPublicByIndex(index, pblic); } -uint32_t BaseContext::GetPublicsNum() +uint32_t +BaseContext::GetPublicsNum() { - return m_pRuntime->GetPublicsNum(); + return m_pRuntime->GetPublicsNum(); } -int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) +int +BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) { - return m_pRuntime->GetPubvarByIndex(index, pubvar); + return m_pRuntime->GetPubvarByIndex(index, pubvar); } -int BaseContext::FindPubvarByName(const char *name, uint32_t *index) +int +BaseContext::FindPubvarByName(const char *name, uint32_t *index) { - return m_pRuntime->FindPubvarByName(name, index); + return m_pRuntime->FindPubvarByName(name, index); } -int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) +int +BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) { - return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr); + return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr); } -uint32_t BaseContext::GetPubVarsNum() +uint32_t +BaseContext::GetPubVarsNum() { - return m_pRuntime->GetPubVarsNum(); + return m_pRuntime->GetPubVarsNum(); } -int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) +int +BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::BindNative(const sp_nativeinfo_t *native) +int +BaseContext::BindNative(const sp_nativeinfo_t *native) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func) +int +BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native) +int +BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) +int +BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) - || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) - { - return SP_ERROR_INVALID_ADDRESS; - } + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) + { + return SP_ERROR_INVALID_ADDRESS; + } - if (phys_addr) - { - *phys_addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); - } + if (phys_addr) + *phys_addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -int BaseContext::PushCell(cell_t value) +int +BaseContext::PushCell(cell_t value) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells) +int +BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) +int +BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::LocalToString(cell_t local_addr, char **addr) +int +BaseContext::LocalToString(cell_t local_addr, char **addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) - || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) - { - return SP_ERROR_INVALID_ADDRESS; - } - *addr = (char *)(m_pRuntime->plugin()->memory + local_addr); + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) + { + return SP_ERROR_INVALID_ADDRESS; + } + *addr = (char *)(m_pRuntime->plugin()->memory + local_addr); - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string) +int +BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string) { - return SP_ERROR_ABORTED; + return SP_ERROR_ABORTED; } -int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source) +int +BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source) { - char *dest; - size_t len; + char *dest; + size_t len; - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) - || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) - { - return SP_ERROR_INVALID_ADDRESS; - } + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) + { + return SP_ERROR_INVALID_ADDRESS; + } - if (bytes == 0) - { - return SP_ERROR_NONE; - } + if (bytes == 0) + return SP_ERROR_NONE; - len = strlen(source); - dest = (char *)(m_pRuntime->plugin()->memory + local_addr); + len = strlen(source); + dest = (char *)(m_pRuntime->plugin()->memory + local_addr); - if (len >= bytes) - { - len = bytes - 1; - } + if (len >= bytes) + len = bytes - 1; - memmove(dest, source, len); - dest[len] = '\0'; + memmove(dest, source, len); + dest[len] = '\0'; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -inline int __CheckValidChar(char *c) +static inline int +__CheckValidChar(char *c) { - int count; - int bytecount = 0; + int count; + int bytecount = 0; - for (count=1; (*c & 0xC0) == 0x80; count++) - { - c--; - } + for (count=1; (*c & 0xC0) == 0x80; count++) + c--; - switch (*c & 0xF0) - { - case 0xC0: - case 0xD0: - { - bytecount = 2; - break; - } - case 0xE0: - { - bytecount = 3; - break; - } - case 0xF0: - { - bytecount = 4; - break; - } - } + switch (*c & 0xF0) + { + case 0xC0: + case 0xD0: + { + bytecount = 2; + break; + } + case 0xE0: + { + bytecount = 3; + break; + } + case 0xF0: + { + bytecount = 4; + break; + } + } - if (bytecount != count) - { - return count; - } + if (bytecount != count) + return count; - return 0; + return 0; } -int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes) +int +BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes) { - char *dest; - size_t len; - bool needtocheck = false; + char *dest; + size_t len; + bool needtocheck = false; - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) - || (local_addr < 0) - || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) - { - return SP_ERROR_INVALID_ADDRESS; - } - - if (maxbytes == 0) - { - return SP_ERROR_NONE; - } + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + (local_addr < 0) || + ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) + { + return SP_ERROR_INVALID_ADDRESS; + } + + if (maxbytes == 0) + return SP_ERROR_NONE; - len = strlen(source); - dest = (char *)(m_pRuntime->plugin()->memory + local_addr); + len = strlen(source); + dest = (char *)(m_pRuntime->plugin()->memory + local_addr); - if ((size_t)len >= maxbytes) - { - len = maxbytes - 1; - needtocheck = true; - } + if ((size_t)len >= maxbytes) { + len = maxbytes - 1; + needtocheck = true; + } - memmove(dest, source, len); - if ((dest[len-1] & 1<<7) && needtocheck) - { - len -= __CheckValidChar(dest+len-1); - } - dest[len] = '\0'; + memmove(dest, source, len); + if ((dest[len-1] & 1<<7) && needtocheck) + len -= __CheckValidChar(dest+len-1); + dest[len] = '\0'; - if (wrtnbytes) - { - *wrtnbytes = len; - } + if (wrtnbytes) + *wrtnbytes = len; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id) +IPluginFunction * +BaseContext::GetFunctionById(funcid_t func_id) { - return m_pRuntime->GetFunctionById(func_id); + return m_pRuntime->GetFunctionById(func_id); } -IPluginFunction *BaseContext::GetFunctionByName(const char *public_name) +IPluginFunction * +BaseContext::GetFunctionByName(const char *public_name) { - return m_pRuntime->GetFunctionByName(public_name); + return m_pRuntime->GetFunctionByName(public_name); } -int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr) +int +BaseContext::LocalToStringNULL(cell_t local_addr, char **addr) { - int err; - if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE) - { - return err; - } + int err; + if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE) + return err; - if ((cell_t *)*addr == m_pNullString) - { - *addr = NULL; - } + if ((cell_t *)*addr == m_pNullString) + *addr = NULL; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } -SourceMod::IdentityToken_t *BaseContext::GetIdentity() +SourceMod::IdentityToken_t * +BaseContext::GetIdentity() { - SourceMod::IdentityToken_t *tok; + SourceMod::IdentityToken_t *tok; - if (GetKey(1, (void **)&tok)) - { - return tok; - } - - return NULL; + if (GetKey(1, (void **)&tok)) + return tok; + return NULL; } -cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type) +cell_t * +BaseContext::GetNullRef(SP_NULL_TYPE type) { - if (type == SP_NULL_VECTOR) - { - return m_pNullVec; - } + if (type == SP_NULL_VECTOR) + return m_pNullVec; - return NULL; + return NULL; } -bool BaseContext::IsInExec() +bool +BaseContext::IsInExec() { - return m_InExec; + return m_InExec; } -int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result) +int +BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result) { - int ir; - int serial; - cell_t *sp; - JitFunction *fn; - cell_t _ignore_result; + int ir; + int serial; + cell_t *sp; + JitFunction *fn; + cell_t _ignore_result; - EnterProfileScope profileScope("SourcePawn", "EnterJIT"); + EnterProfileScope profileScope("SourcePawn", "EnterJIT"); - if (!g_WatchdogTimer.HandleInterrupt()) - return SP_ERROR_TIMEOUT; + if (!g_WatchdogTimer.HandleInterrupt()) + return SP_ERROR_TIMEOUT; - funcid_t fnid = function->GetFunctionID(); - if (!(fnid & 1)) - return SP_ERROR_INVALID_ADDRESS; + funcid_t fnid = function->GetFunctionID(); + if (!(fnid & 1)) + return SP_ERROR_INVALID_ADDRESS; - unsigned public_id = fnid >> 1; - CFunction *cfun = m_pRuntime->GetPublicFunction(public_id); - if (!cfun) - return SP_ERROR_NOT_FOUND; + unsigned public_id = fnid >> 1; + CFunction *cfun = m_pRuntime->GetPublicFunction(public_id); + if (!cfun) + return SP_ERROR_NOT_FOUND; - if (m_pRuntime->IsPaused()) - return SP_ERROR_NOT_RUNNABLE; + if (m_pRuntime->IsPaused()) + return SP_ERROR_NOT_RUNNABLE; - if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1)))) - return SP_ERROR_STACKLOW; + if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1)))) + return SP_ERROR_STACKLOW; - if (result == NULL) - result = &_ignore_result; + if (result == NULL) + result = &_ignore_result; - /* We got this far. It's time to start profiling. */ - EnterProfileScope scriptScope("SourcePawn", cfun->FullName()); + /* We got this far. It's time to start profiling. */ + EnterProfileScope scriptScope("SourcePawn", cfun->FullName()); - /* See if we have to compile the callee. */ - if (g_engine2.IsJitEnabled() && (fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL) - { - /* We might not have to - check pcode offset. */ - fn = m_pRuntime->GetJittedFunctionByOffset(cfun->Public()->code_offs); - if (fn) - { - m_pRuntime->m_PubJitFuncs[public_id] = fn; - } - else - { - if ((fn = g_Jit.CompileFunction(m_pRuntime, cfun->Public()->code_offs, &ir)) == NULL) - { - return ir; - } - m_pRuntime->m_PubJitFuncs[public_id] = fn; - } - } + /* See if we have to compile the callee. */ + if (g_engine2.IsJitEnabled() && + (fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL) + { + /* We might not have to - check pcode offset. */ + fn = m_pRuntime->GetJittedFunctionByOffset(cfun->Public()->code_offs); + if (fn) { + m_pRuntime->m_PubJitFuncs[public_id] = fn; + } else { + if ((fn = g_Jit.CompileFunction(m_pRuntime, cfun->Public()->code_offs, &ir)) == NULL) + return ir; + m_pRuntime->m_PubJitFuncs[public_id] = fn; + } + } - /* Save our previous state. */ + /* Save our previous state. */ - bool save_exec; - uint32_t save_n_idx; - cell_t save_sp, save_hp, save_rp, save_cip; + bool save_exec; + uint32_t save_n_idx; + cell_t save_sp, save_hp, save_rp, save_cip; - save_sp = m_ctx.sp; - save_hp = m_ctx.hp; - save_exec = m_InExec; - save_n_idx = m_ctx.n_idx; - save_rp = m_ctx.rp; - save_cip = m_ctx.cip; + save_sp = m_ctx.sp; + save_hp = m_ctx.hp; + save_exec = m_InExec; + save_n_idx = m_ctx.n_idx; + save_rp = m_ctx.rp; + save_cip = m_ctx.cip; - /* Push parameters */ + /* Push parameters */ - m_ctx.sp -= sizeof(cell_t) * (num_params + 1); - sp = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.sp); + m_ctx.sp -= sizeof(cell_t) * (num_params + 1); + sp = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.sp); - sp[0] = num_params; - for (unsigned int i = 0; i < num_params; i++) - { - sp[i + 1] = params[i]; - } + sp[0] = num_params; + for (unsigned int i = 0; i < num_params; i++) + sp[i + 1] = params[i]; - /* Clear internal state */ - m_ctx.n_err = SP_ERROR_NONE; - m_ctx.n_idx = 0; - m_MsgCache[0] = '\0'; - m_CustomMsg = false; - m_InExec = true; + /* Clear internal state */ + m_ctx.n_err = SP_ERROR_NONE; + m_ctx.n_idx = 0; + m_MsgCache[0] = '\0'; + m_CustomMsg = false; + m_InExec = true; - /* Start the frame tracer */ + /* Start the frame tracer */ - if (g_engine2.IsJitEnabled()) - ir = g_Jit.InvokeFunction(m_pRuntime, fn, result); - else - ir = Interpret(m_pRuntime, cfun->Public()->code_offs, result); + if (g_engine2.IsJitEnabled()) + ir = g_Jit.InvokeFunction(m_pRuntime, fn, result); + else + ir = Interpret(m_pRuntime, cfun->Public()->code_offs, result); - /* Restore some states, stop the frame tracer */ + /* Restore some states, stop the frame tracer */ - m_InExec = save_exec; + m_InExec = save_exec; - if (ir == SP_ERROR_NONE) - { - m_ctx.n_err = SP_ERROR_NONE; - if (m_ctx.sp != save_sp) - { - ir = SP_ERROR_STACKLEAK; - _SetErrorMessage("Stack leak detected: sp:%d should be %d!", - m_ctx.sp, - save_sp); - } - if (m_ctx.hp != save_hp) - { - ir = SP_ERROR_HEAPLEAK; - _SetErrorMessage("Heap leak detected: hp:%d should be %d!", - m_ctx.hp, - save_hp); - } - if (m_ctx.rp != save_rp) - { - ir = SP_ERROR_STACKLEAK; - _SetErrorMessage("Return stack leak detected: rp:%d should be %d!", - m_ctx.rp, - save_rp); - } - } + if (ir == SP_ERROR_NONE) { + m_ctx.n_err = SP_ERROR_NONE; + if (m_ctx.sp != save_sp) { + ir = SP_ERROR_STACKLEAK; + _SetErrorMessage("Stack leak detected: sp:%d should be %d!", + m_ctx.sp, + save_sp); + } + if (m_ctx.hp != save_hp) { + ir = SP_ERROR_HEAPLEAK; + _SetErrorMessage("Heap leak detected: hp:%d should be %d!", + m_ctx.hp, + save_hp); + } + if (m_ctx.rp != save_rp) { + ir = SP_ERROR_STACKLEAK; + _SetErrorMessage("Return stack leak detected: rp:%d should be %d!", + m_ctx.rp, + save_rp); + } + } - if (ir == SP_ERROR_TIMEOUT) - g_WatchdogTimer.NotifyTimeoutReceived(); + if (ir == SP_ERROR_TIMEOUT) + g_WatchdogTimer.NotifyTimeoutReceived(); - if (ir != SP_ERROR_NONE) - { - g_engine1.ReportError(m_pRuntime, ir, m_MsgCache, save_rp); - } + if (ir != SP_ERROR_NONE) + g_engine1.ReportError(m_pRuntime, ir, m_MsgCache, save_rp); - m_ctx.sp = save_sp; - m_ctx.hp = save_hp; - m_ctx.rp = save_rp; - - m_ctx.cip = save_cip; - m_ctx.n_idx = save_n_idx; - m_ctx.n_err = SP_ERROR_NONE; - m_MsgCache[0] = '\0'; - m_CustomMsg = false; + m_ctx.sp = save_sp; + m_ctx.hp = save_hp; + m_ctx.rp = save_rp; + + m_ctx.cip = save_cip; + m_ctx.n_idx = save_n_idx; + m_ctx.n_err = SP_ERROR_NONE; + m_MsgCache[0] = '\0'; + m_CustomMsg = false; - return ir; + return ir; } -IPluginRuntime *BaseContext::GetRuntime() +IPluginRuntime * +BaseContext::GetRuntime() { - return m_pRuntime; + return m_pRuntime; } DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin) @@ -697,165 +662,150 @@ DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin) #define USHR(x) ((unsigned int)(x)>>1) -int DebugInfo::LookupFile(ucell_t addr, const char **filename) +int +DebugInfo::LookupFile(ucell_t addr, const char **filename) { - int high, low, mid; + int high, low, mid; - high = m_pPlugin->debug.files_num; - low = -1; + high = m_pPlugin->debug.files_num; + low = -1; - while (high - low > 1) - { - mid = USHR(low + high); - if (m_pPlugin->debug.files[mid].addr <= addr) - { - low = mid; - } else { - high = mid; - } - } + while (high - low > 1) { + mid = USHR(low + high); + if (m_pPlugin->debug.files[mid].addr <= addr) + low = mid; + else + high = mid; + } - if (low == -1) - { - return SP_ERROR_NOT_FOUND; - } + if (low == -1) + return SP_ERROR_NOT_FOUND; - *filename = m_pPlugin->debug.stringbase + m_pPlugin->debug.files[low].name; - - return SP_ERROR_NONE; + *filename = m_pPlugin->debug.stringbase + m_pPlugin->debug.files[low].name; + return SP_ERROR_NONE; } -int DebugInfo::LookupFunction(ucell_t addr, const char **name) +int +DebugInfo::LookupFunction(ucell_t addr, const char **name) { - if (!m_pPlugin->debug.unpacked) - { - uint32_t max, iter; - sp_fdbg_symbol_t *sym; - uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols); + if (!m_pPlugin->debug.unpacked) { + uint32_t max, iter; + sp_fdbg_symbol_t *sym; + uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols); - max = m_pPlugin->debug.syms_num; - for (iter = 0; iter < max; iter++) - { - sym = (sp_fdbg_symbol_t *)cursor; + max = m_pPlugin->debug.syms_num; + for (iter = 0; iter < max; iter++) { + sym = (sp_fdbg_symbol_t *)cursor; - if (sym->ident == sp::IDENT_FUNCTION - && sym->codestart <= addr - && sym->codeend > addr) - { - *name = m_pPlugin->debug.stringbase + sym->name; - return SP_ERROR_NONE; - } + if (sym->ident == sp::IDENT_FUNCTION && + sym->codestart <= addr && + sym->codeend > addr) + { + *name = m_pPlugin->debug.stringbase + sym->name; + return SP_ERROR_NONE; + } - if (sym->dimcount > 0) - { - cursor += sizeof(sp_fdbg_symbol_t); - cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; - continue; - } + if (sym->dimcount > 0) { + cursor += sizeof(sp_fdbg_symbol_t); + cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; + continue; + } - cursor += sizeof(sp_fdbg_symbol_t); - } + cursor += sizeof(sp_fdbg_symbol_t); + } - return SP_ERROR_NOT_FOUND; - } - else - { - uint32_t max, iter; - sp_u_fdbg_symbol_t *sym; - uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols); + return SP_ERROR_NOT_FOUND; + } else { + uint32_t max, iter; + sp_u_fdbg_symbol_t *sym; + uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols); - max = m_pPlugin->debug.syms_num; - for (iter = 0; iter < max; iter++) - { - sym = (sp_u_fdbg_symbol_t *)cursor; + max = m_pPlugin->debug.syms_num; + for (iter = 0; iter < max; iter++) { + sym = (sp_u_fdbg_symbol_t *)cursor; - if (sym->ident == sp::IDENT_FUNCTION - && sym->codestart <= addr - && sym->codeend > addr) - { - *name = m_pPlugin->debug.stringbase + sym->name; - return SP_ERROR_NONE; - } + if (sym->ident == sp::IDENT_FUNCTION && + sym->codestart <= addr && + sym->codeend > addr) + { + *name = m_pPlugin->debug.stringbase + sym->name; + return SP_ERROR_NONE; + } - if (sym->dimcount > 0) - { - cursor += sizeof(sp_u_fdbg_symbol_t); - cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount; - continue; - } + if (sym->dimcount > 0) { + cursor += sizeof(sp_u_fdbg_symbol_t); + cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount; + continue; + } - cursor += sizeof(sp_u_fdbg_symbol_t); - } + cursor += sizeof(sp_u_fdbg_symbol_t); + } - return SP_ERROR_NOT_FOUND; - } + return SP_ERROR_NOT_FOUND; + } } -int DebugInfo::LookupLine(ucell_t addr, uint32_t *line) +int +DebugInfo::LookupLine(ucell_t addr, uint32_t *line) { - int high, low, mid; + int high, low, mid; - high = m_pPlugin->debug.lines_num; - low = -1; + high = m_pPlugin->debug.lines_num; + low = -1; - while (high - low > 1) - { - mid = USHR(low + high); - if (m_pPlugin->debug.lines[mid].addr <= addr) - { - low = mid; - } else { - high = mid; - } - } + while (high - low > 1) { + mid = USHR(low + high); + if (m_pPlugin->debug.lines[mid].addr <= addr) + low = mid; + else + high = mid; + } - if (low == -1) - { - return SP_ERROR_NOT_FOUND; - } + if (low == -1) + return SP_ERROR_NOT_FOUND; - /* Since the CIP occurs BEFORE the line, we have to add one */ - *line = m_pPlugin->debug.lines[low].line + 1; + /* Since the CIP occurs BEFORE the line, we have to add one */ + *line = m_pPlugin->debug.lines[low].line + 1; - return SP_ERROR_NONE; + return SP_ERROR_NONE; } #undef USHR -int BaseContext::GetLastNativeError() +int +BaseContext::GetLastNativeError() { - return m_ctx.n_err; + return m_ctx.n_err; } -cell_t *BaseContext::GetLocalParams() +cell_t * +BaseContext::GetLocalParams() { - return (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.frm + (2 * sizeof(cell_t))); + return (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.frm + (2 * sizeof(cell_t))); } -void BaseContext::SetKey(int k, void *value) +void +BaseContext::SetKey(int k, void *value) { - if (k < 1 || k > 4) - { - return; - } + if (k < 1 || k > 4) + return; - m_keys[k - 1] = value; - m_keys_set[k - 1] = true; + m_keys[k - 1] = value; + m_keys_set[k - 1] = true; } -bool BaseContext::GetKey(int k, void **value) +bool +BaseContext::GetKey(int k, void **value) { - if (k < 1 || k > 4 || m_keys_set[k - 1] == false) - { - return false; - } + if (k < 1 || k > 4 || m_keys_set[k - 1] == false) + return false; - *value = m_keys[k - 1]; - - return true; + *value = m_keys[k - 1]; + return true; } -void BaseContext::ClearLastNativeError() +void +BaseContext::ClearLastNativeError() { - m_ctx.n_err = SP_ERROR_NONE; + m_ctx.n_err = SP_ERROR_NONE; } diff --git a/sourcepawn/jit/sp_vm_basecontext.h b/sourcepawn/jit/sp_vm_basecontext.h index dce3c9fa..7eb1e990 100644 --- a/sourcepawn/jit/sp_vm_basecontext.h +++ b/sourcepawn/jit/sp_vm_basecontext.h @@ -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 . - * - * 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 . - * - * 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_