diff -r 4edce76aefe3 -r 4c93f74cae51 core/NativeInvoker.cpp --- a/core/NativeInvoker.cpp Fri Mar 29 12:28:02 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,379 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * 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 . - * - * 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$ - */ - -#include "NativeInvoker.h" -#include "ShareSys.h" - -NativeInterface g_NInvoke; - -NativeInvoker::NativeInvoker() -{ -} - -NativeInvoker::~NativeInvoker() -{ -} - -const char *NativeInterface::GetInterfaceName() -{ - return SMINTERFACE_NINVOKE_NAME; -} - -unsigned int NativeInterface::GetInterfaceVersion() -{ - return SMINTERFACE_NINVOKE_VERSION; -} - -void NativeInterface::OnSourceModAllInitialized() -{ - g_ShareSys.AddInterface(NULL, &g_NInvoke); -} - -IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes) -{ - return g_pSourcePawn2->CreateEmptyRuntime(name, bytes); -} - -INativeInvoker *NativeInterface::CreateInvoker() -{ - return new NativeInvoker(); -} - -bool NativeInvoker::Start(IPluginContext *pContext, const char *name) -{ - NativeEntry *entry; - - entry = g_ShareSys.FindNative(name); - if (entry == NULL) - { - return false; - } - - native = NULL; - if (entry->replacement.owner != NULL) - { - native = entry->replacement.func; - } - else if (entry->owner != NULL) - { - native = entry->func; - } - - if (native == NULL) - { - return false; - } - - this->pContext = pContext; - - m_curparam = 0; - m_errorstate = SP_ERROR_NONE; - - return true; -} - -cell_t NativeInvoker::PushCell(cell_t cell) -{ - if (m_curparam >= SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - - m_info[m_curparam].marked = false; - m_params[m_curparam] = cell; - m_curparam++; - - return SP_ERROR_NONE; -} - -int NativeInvoker::PushCellByRef(cell_t *cell, int flags) -{ - return PushArray(cell, 1, flags); -} - -int NativeInvoker::PushFloat(float number) -{ - cell_t val = *(cell_t *)&number; - - return PushCell(val); -} - -int NativeInvoker::PushFloatByRef(float *number, int flags) -{ - return PushCellByRef((cell_t *)number, flags); -} - -int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback) -{ - if (m_curparam >= SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - - ParamInfo *info = &m_info[m_curparam]; - - info->flags = inarray ? copyback : 0; - info->marked = true; - info->size = cells; - info->str.is_sz = false; - info->orig_addr = inarray; - - m_curparam++; - - return SP_ERROR_NONE; -} - -int NativeInvoker::PushString(const char *string) -{ - return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1); -} - -int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) -{ - return _PushString(buffer, sz_flags, cp_flags, length); -} - -int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len) -{ - if (m_curparam >= SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - - ParamInfo *info = &m_info[m_curparam]; - - info->marked = true; - info->orig_addr = (cell_t *)string; - info->flags = cp_flags; - info->size = len; - info->str.sz_flags = sz_flags; - info->str.is_sz = true; - - m_curparam++; - - return SP_ERROR_NONE; -} - -void NativeInvoker::Cancel() -{ - if (pContext == NULL) - { - return; - } - - m_errorstate = SP_ERROR_NONE; - m_curparam = 0; - pContext = NULL; - native = NULL; -} - -int NativeInvoker::SetError(int err) -{ - m_errorstate = err; - return err; -} - -int NativeInvoker::Invoke(cell_t *result) -{ - int err = SP_ERROR_NONE; - - if (pContext == NULL) - { - return SP_ERROR_INVALID_NATIVE; - } - - if (m_errorstate != SP_ERROR_NONE) - { - err = m_errorstate; - Cancel(); - return err; - } - - cell_t tresult; - - if (result == NULL) - { - result = &tresult; - } - - //This is for re-entrancy! - IPluginContext *ctx = pContext; - cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1]; - cell_t *temp_params = &_temp_params[1]; - ParamInfo temp_info[SP_MAX_EXEC_PARAMS]; - unsigned int numparams = m_curparam; - unsigned int i; - bool docopies = true; - - if (numparams) - { - //Save the info locally, then reset it for re-entrant calls. - memcpy(temp_info, m_info, numparams * sizeof(ParamInfo)); - } - m_curparam = 0; - pContext = NULL; - - /* Initialize 0th parameter */ - _temp_params[0] = numparams; - - /* Browse the parameters and build arrays */ - for (i = 0; i < numparams; i++) - { - /* Is this marked as an array? */ - if (temp_info[i].marked) - { - if (!temp_info[i].str.is_sz) - { - /* Allocate a normal/generic array */ - if ((err = ctx->HeapAlloc(temp_info[i].size, - &temp_info[i].local_addr, - &temp_info[i].phys_addr)) - != SP_ERROR_NONE) - { - break; - } - if (temp_info[i].orig_addr) - { - memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size); - } - } - else - { - /* Calculate cells required for the string */ - size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t); - - /* Allocate the buffer */ - if ((err = ctx->HeapAlloc(cells, - &temp_info[i].local_addr, - &temp_info[i].phys_addr)) - != SP_ERROR_NONE) - { - break; - } - /* Copy original string if necessary */ - if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL)) - { - /* Cut off UTF-8 properly */ - if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) - { - if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr, - temp_info[i].size, - (const char *)temp_info[i].orig_addr, - NULL)) - != SP_ERROR_NONE) - { - break; - } - } - /* Copy a binary blob */ - else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY) - { - memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size); - } - /* Copy ASCII characters */ - else - { - if ((err = ctx->StringToLocal(temp_info[i].local_addr, - temp_info[i].size, - (const char *)temp_info[i].orig_addr)) - != SP_ERROR_NONE) - { - break; - } - } - } - } /* End array/string calculation */ - /* Update the pushed parameter with the byref local address */ - temp_params[i] = temp_info[i].local_addr; - } - else - { - /* Just copy the value normally */ - temp_params[i] = m_params[i]; - } - } - - /* Make the call if we can */ - if (err == SP_ERROR_NONE) - { - *result = native(ctx, _temp_params); - if (ctx->GetLastNativeError() != SP_ERROR_NONE) - { - docopies = false; - ctx->ClearLastNativeError(); - } - } - else - { - docopies = false; - } - - /* i should be equal to the last valid parameter + 1 */ - while (i--) - { - if (!temp_info[i].marked) - { - continue; - } - - if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) - { - if (temp_info[i].orig_addr) - { - if (temp_info[i].str.is_sz) - { - memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size); - - } - else - { - if (temp_info[i].size == 1) - { - *temp_info[i].orig_addr = *(temp_info[i].phys_addr); - } - else - { - memcpy(temp_info[i].orig_addr, - temp_info[i].phys_addr, - temp_info[i].size * sizeof(cell_t)); - } - } - } - } - - if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE) - { - return err; - } - } - - return err; -}