diff -r 7602d7fb60d9 -r 026da5437111 core/systems/ForwardSys.cpp --- a/core/systems/ForwardSys.cpp Fri Jul 11 06:51:21 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,737 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * 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$ - */ - -#include -#include -#include -#include "ForwardSys.h" -#include "PluginSys.h" -#include "ShareSys.h" -#include "DebugReporter.h" - -CForwardManager g_Forwards; - -/** - * Genesis turns to its source, reduction occurs stepwise although the essence is all one. - * End of line. FTL system check. - * - * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST - * VARARG FUNCTIONS: - * - Pushing no varargs - */ - -// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails -// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS! - -CForwardManager::~CForwardManager() -{ - CStack::iterator iter; - for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++) - { - delete (*iter); - } - m_FreeForwards.popall(); -} - -void CForwardManager::OnSourceModAllInitialized() -{ - g_PluginSys.AddPluginsListener(this); - g_ShareSys.AddInterface(NULL, this); -} - -IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...) -{ - CForward *fwd; - va_list ap; - va_start(ap, types); - - fwd = CForward::CreateForward(name, et, num_params, types, ap); - - va_end(ap); - - if (fwd) - { - g_PluginSys.AddFunctionsToForward(name, fwd); - - m_managed.push_back(fwd); - } - - return fwd; -} - -IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...) -{ - CForward *fwd; - va_list ap; - va_start(ap, types); - - fwd = CForward::CreateForward(name, et, num_params, types, ap); - - va_end(ap); - - if (fwd) - { - m_unmanaged.push_back(fwd); - } - - return fwd; -} - -void CForwardManager::OnPluginLoaded(IPlugin *plugin) -{ - /* Attach any globally managed forwards */ - List::iterator iter; - CForward *fwd; - - for (iter=m_managed.begin(); iter!=m_managed.end(); iter++) - { - fwd = (*iter); - IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName()); - if (pFunc) - { - fwd->AddFunction(pFunc); - } - } -} - -void CForwardManager::OnPluginUnloaded(IPlugin *plugin) -{ - List::iterator iter; - CForward *fwd; - - for (iter=m_managed.begin(); iter!=m_managed.end(); iter++) - { - fwd = (*iter); - fwd->RemoveFunctionsOfPlugin(plugin); - } - - for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++) - { - fwd = (*iter); - fwd->RemoveFunctionsOfPlugin(plugin); - } -} - -IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng) -{ - List::iterator iter; - CForward *fwd; - - for (iter=m_managed.begin(); iter!=m_managed.end(); iter++) - { - fwd = (*iter); - if (strcmp(fwd->GetForwardName(), name) == 0) - { - if (ifchng) - { - *ifchng = NULL; - } - return fwd; - } - } - - for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++) - { - fwd = (*iter); - if (strcmp(fwd->GetForwardName(), name) == 0) - { - if (ifchng) - { - *ifchng = fwd; - } - return fwd; - } - } - - if (ifchng) - { - *ifchng = NULL; - } - - return NULL; -} - -void CForwardManager::ReleaseForward(IForward *forward) -{ - ForwardFree(static_cast(forward)); -} - -void CForwardManager::ForwardFree(CForward *fwd) -{ - if (fwd == NULL) - { - return; - } - - m_FreeForwards.push(fwd); - m_managed.remove(fwd); -} - -CForward *CForwardManager::ForwardMake() -{ - CForward *fwd; - if (m_FreeForwards.empty()) - { - fwd = new CForward; - } else { - fwd = m_FreeForwards.front(); - m_FreeForwards.pop(); - } - return fwd; -} - -void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused) -{ - /* No longer used */ -} - -/************************************* - * ACTUAL FORWARD API IMPLEMENTATION * - *************************************/ - -CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap) -{ - ParamType _types[SP_MAX_EXEC_PARAMS]; - - if (num_params > SP_MAX_EXEC_PARAMS) - { - return NULL; - } - - if (types == NULL && num_params) - { - for (unsigned int i=0; im_curparam = 0; - pForward->m_ExecType = et; - snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : ""); - - for (unsigned int i=0; im_types[i] = _types[i]; - } - - if (num_params && _types[num_params-1] == Param_VarArgs) - { - pForward->m_varargs = num_params--; - } else { - pForward->m_varargs = false; - } - - pForward->m_numparams = num_params; - pForward->m_errstate = SP_ERROR_NONE; - - pForward->m_functions.clear(); - - return pForward; -} - -int CForward::Execute(cell_t *result, IForwardFilter *filter) -{ - if (m_errstate) - { - int err = m_errstate; - Cancel(); - return err; - } - - if (filter) - { - filter->OnExecuteBegin(); - } - - FuncIter iter = m_functions.begin(); - IPluginFunction *func; - cell_t cur_result = 0; - cell_t high_result = 0; - int err; - unsigned int failed=0, success=0; - unsigned int num_params = m_curparam; - FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS]; - FwdParamInfo *param; - ParamType type; - - /* Save local, reset */ - memcpy(temp_info, m_params, sizeof(m_params)); - m_curparam = 0; - - for (iter=m_functions.begin(); iter!=m_functions.end(); iter++) - { - func = (*iter); - - for (unsigned int i=0; i= m_numparams || m_types[i] == Param_Any) - { - type = param->pushedas; - } else { - type = m_types[i]; - } - if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF)) - { - /* If we're byref or we're vararg, we always push everything by ref. - * Even if they're byval, we must push them byref. - */ - if (type == Param_String) - { - err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); - } else if (type == Param_Float || type == Param_Cell) { - err = func->PushCellByRef(¶m->val); - } else { - err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); - assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef); - } - } else { - /* If we're not byref or not vararg, our job is a bit easier. */ - assert(type == Param_Cell || type == Param_Float); - err = func->PushCell(param->val); - } - if (err != SP_ERROR_NONE) - { - if (!filter || !filter->OnErrorReport(this, func, err)) - { - g_DbgReporter.GenerateError(func->GetParentContext(), - func->GetFunctionID(), - err, - "Failed to push parameter while executing forward"); - } - continue; - } - } - - /* Call the function and deal with the return value. */ - if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE) - { - if (filter) - { - filter->OnErrorReport(this, func, err); - } - failed++; - } else { - success++; - switch (m_ExecType) - { - case ET_Event: - { - if (cur_result > high_result) - { - high_result = cur_result; - } - break; - } - case ET_Hook: - { - if (cur_result > high_result) - { - high_result = cur_result; - if ((ResultType)high_result == Pl_Stop) - { - goto done; - } - } - break; - } - case ET_Custom: - { - if (filter) - { - if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop) - { - goto done; - } - } - break; - } - default: - { - break; - } - } - } - } - -done: - if (success) - { - if (m_ExecType == ET_Event || m_ExecType == ET_Hook) - { - cur_result = high_result; - } else if (m_ExecType == ET_Ignore) { - cur_result = 0; - } - if (result) - { - *result = cur_result; - } - } - - if (filter) - { - filter->OnExecuteEnd(&cur_result, success, failed); - } - - return SP_ERROR_NONE; -} - -int CForward::PushCell(cell_t cell) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_Cell; - } else if (m_types[m_curparam] != Param_Cell) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_Cell; - } - - m_params[m_curparam++].val = cell; - - return SP_ERROR_NONE; -} - -int CForward::PushFloat(float number) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_Float; - } else if (m_types[m_curparam] != Param_Float) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_Float; - } - - m_params[m_curparam++].val = *(cell_t *)&number; - - return SP_ERROR_NONE; -} - -int CForward::PushCellByRef(cell_t *cell, int flags) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_CellByRef; - } else if (m_types[m_curparam] != Param_CellByRef) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_CellByRef; - } - - _Int_PushArray(cell, 1, flags); - m_curparam++; - - return SP_ERROR_NONE; -} - -int CForward::PushFloatByRef(float *num, int flags) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_FloatByRef; - } else if (m_types[m_curparam] != Param_FloatByRef) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_FloatByRef; - } - - _Int_PushArray((cell_t *)num, 1, flags); - m_curparam++; - - return SP_ERROR_NONE; -} - -void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags) -{ - m_params[m_curparam].byref.cells = cells; - m_params[m_curparam].byref.flags = flags; - m_params[m_curparam].byref.orig_addr = inarray; -} - -int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags) -{ - /* We don't allow this here */ - if (!inarray) - { - return SetError(SP_ERROR_PARAM); - } - - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_Array; - } else if (m_types[m_curparam] != Param_Array) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_Array; - } - - _Int_PushArray(inarray, cells, flags); - - m_curparam++; - - return SP_ERROR_NONE; -} - -void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags) -{ - m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */ - m_params[m_curparam].byref.flags = cp_flags; - m_params[m_curparam].byref.orig_addr = inarray; - m_params[m_curparam].byref.sz_flags = sz_flags; -} - -int CForward::PushString(const char *string) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_String; - } else if (m_types[m_curparam] != Param_String) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_String; - } - - _Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0); - m_curparam++; - - return SP_ERROR_NONE; -} - -int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) -{ - if (m_curparam < m_numparams) - { - if (m_types[m_curparam] == Param_Any) - { - m_params[m_curparam].pushedas = Param_String; - } else if (m_types[m_curparam] != Param_String) { - return SetError(SP_ERROR_PARAM); - } - } else { - if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS) - { - return SetError(SP_ERROR_PARAMS_MAX); - } - m_params[m_curparam].pushedas = Param_String; - } - - _Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags); - m_curparam++; - - return SP_ERROR_NONE; -} - -void CForward::Cancel() -{ - if (!m_curparam) - { - return; - } - - m_curparam = 0; - m_errstate = SP_ERROR_NONE; -} - -bool CForward::AddFunction(IPluginContext *pContext, funcid_t index) -{ - IPluginFunction *pFunc = pContext->GetFunctionById(index); - - if (!pFunc) - { - return false; - } - - return AddFunction(pFunc); -} - -bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index) -{ - IPluginFunction *pFunc = pContext->GetFunctionById(index); - - if (!pFunc) - { - return false; - } - - return RemoveFunction(pFunc); -} - -bool CForward::RemoveFunction(IPluginFunction *func) -{ - bool found = false; - FuncIter iter; - List *lst; - - if (func->IsRunnable()) - { - lst = &m_functions; - } else { - lst = &m_paused; - } - - for (iter=m_functions.begin(); iter!=m_functions.end(); iter++) - { - if ((*iter) == func) - { - found = true; - lst->erase(iter); - break; - } - } - - /* Cancel a call, if any */ - if (found || m_curparam) - { - func->Cancel(); - } - - return found; -} - -unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin) -{ - FuncIter iter; - IPluginFunction *func; - unsigned int removed = 0; - IPluginContext *pContext = plugin->GetBaseContext(); - for (iter=m_functions.begin(); iter!=m_functions.end();) - { - func = (*iter); - if (func->GetParentContext() == pContext) - { - iter = m_functions.erase(iter); - removed++; - } else { - iter++; - } - } - - return removed; -} - -bool CForward::AddFunction(IPluginFunction *func) -{ - if (m_curparam) - { - return false; - } - - if (func->IsRunnable()) - { - m_functions.push_back(func); - } else { - m_paused.push_back(func); - } - - return true; -} - -const char *CForward::GetForwardName() -{ - return m_name; -} - -unsigned int CForward::GetFunctionCount() -{ - return m_functions.size(); -} - -ExecType CForward::GetExecType() -{ - return m_ExecType; -}