diff -r c7b4237fff50 -r 03a67e41afbc core/vm/sp_vm_function.cpp --- a/core/vm/sp_vm_function.cpp Fri Mar 28 06:21:34 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourcePawn - * Copyright (C) 2004-2007 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 -#include -#include "sp_vm_function.h" - -/******************** -* FUNCTION CALLING * -********************/ - -void CFunction::Set(uint32_t code_addr, IPluginContext *plugin, funcid_t id) -{ - m_codeaddr = code_addr; - m_pContext = plugin; - m_curparam = 0; - m_errorstate = SP_ERROR_NONE; - m_Invalid = false; - m_pCtx = plugin ? plugin->GetContext() : NULL; - m_FnId = id; -} - -bool CFunction::IsRunnable() -{ - return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED); -} - -int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) -{ - if (!IsRunnable()) - { - return SP_ERROR_NOT_RUNNABLE; - } - - while (num_params--) - { - m_pContext->PushCell(params[num_params]); - } - - return m_pContext->Execute(m_codeaddr, result); -} - -IPluginContext *CFunction::GetParentContext() -{ - return m_pContext; -} - -CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin, funcid_t id) : - m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0), - m_errorstate(SP_ERROR_NONE), m_FnId(id) -{ - m_Invalid = false; - if (plugin) - { - m_pCtx = plugin->GetContext(); - } -} - -int CFunction::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 CFunction::PushCellByRef(cell_t *cell, int flags) -{ - return PushArray(cell, 1, flags); -} - -int CFunction::PushFloat(float number) -{ - cell_t val = *(cell_t *)&number; - - return PushCell(val); -} - -int CFunction::PushFloatByRef(float *number, int flags) -{ - return PushCellByRef((cell_t *)number, flags); -} - -int CFunction::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 CFunction::PushString(const char *string) -{ - 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) -{ - return _PushString(buffer, sz_flags, cp_flags, length); -} - -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); - } - - 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 CFunction::Cancel() -{ - if (!m_curparam) - { - return; - } - - m_errorstate = SP_ERROR_NONE; - m_curparam = 0; -} - -int CFunction::Execute(cell_t *result) -{ - int err = SP_ERROR_NONE; - if (!IsRunnable()) - { - m_errorstate = SP_ERROR_NOT_RUNNABLE; - } - 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; - - 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; iHeapAlloc(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=m_pContext->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)) - { - if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) - { - if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr, - temp_info[i].size, - (const char *)temp_info[i].orig_addr, - NULL)) - != SP_ERROR_NONE) - { - break; - } - } else { - if ((err=m_pContext->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 = CallFunction(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; - } - 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=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE) - { - return err; - } - } - - return err; -} - -funcid_t CFunction::GetFunctionID() -{ - return m_FnId; -}