2008-03-30 09:00:22 +02:00
|
|
|
/**
|
2009-12-20 03:16:41 +01:00
|
|
|
* vim: set ts=4 sw=4 tw=99 noet :
|
2008-03-30 09:00:22 +02:00
|
|
|
* =============================================================================
|
|
|
|
* 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 <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$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "ForwardSys.h"
|
2013-10-09 14:43:08 +02:00
|
|
|
#include "DebugReporter.h"
|
|
|
|
#include "common_logic.h"
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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<CForward *>::iterator iter;
|
|
|
|
for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
|
|
|
|
{
|
|
|
|
delete (*iter);
|
|
|
|
}
|
|
|
|
m_FreeForwards.popall();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CForwardManager::OnSourceModAllInitialized()
|
|
|
|
{
|
2013-03-29 19:37:29 +01:00
|
|
|
scripts->AddPluginsListener(this);
|
|
|
|
sharesys->AddInterface(NULL, this);
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2013-03-29 19:37:29 +01:00
|
|
|
scripts->AddFunctionsToForward(name, fwd);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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<CForward *>::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<CForward *>::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<CForward *>::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<CForward *>(forward));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CForwardManager::ForwardFree(CForward *fwd)
|
|
|
|
{
|
2008-08-23 11:46:52 +02:00
|
|
|
if (fwd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
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)
|
|
|
|
{
|
2013-08-28 01:06:18 +02:00
|
|
|
if(paused)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Attach any globally managed forwards */
|
|
|
|
List<CForward *>::iterator iter;
|
|
|
|
CForward *fwd;
|
|
|
|
|
|
|
|
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
|
|
|
{
|
|
|
|
fwd = (*iter);
|
|
|
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
|
|
|
// Only add functions, if they aren't registered yet!
|
|
|
|
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
|
|
|
|
{
|
|
|
|
fwd->AddFunction(pFunc);
|
|
|
|
}
|
|
|
|
}
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************
|
|
|
|
* 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; i<num_params; i++)
|
|
|
|
{
|
|
|
|
_types[i] = (ParamType)va_arg(ap, int);
|
|
|
|
if (_types[i] == Param_VarArgs && (i != num_params - 1))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
types = _types;
|
|
|
|
} else {
|
|
|
|
for (unsigned int i=0; i<num_params; i++)
|
|
|
|
{
|
|
|
|
_types[i] = types[i];
|
|
|
|
if (types[i] == Param_VarArgs && (i != num_params - 1))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First parameter can never be varargs */
|
|
|
|
if (num_params && _types[0] == Param_VarArgs)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CForward *pForward = g_Forwards.ForwardMake();
|
2010-01-11 01:58:17 +01:00
|
|
|
pForward->m_IterGuard = NULL;
|
2008-03-30 09:00:22 +02:00
|
|
|
pForward->m_curparam = 0;
|
|
|
|
pForward->m_ExecType = et;
|
|
|
|
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<num_params; i++)
|
|
|
|
{
|
|
|
|
pForward->m_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
FuncIter iter = m_functions.begin();
|
|
|
|
IPluginFunction *func;
|
|
|
|
cell_t cur_result = 0;
|
|
|
|
cell_t high_result = 0;
|
2008-07-08 11:20:47 +02:00
|
|
|
cell_t low_result = 0;
|
2008-03-30 09:00:22 +02:00
|
|
|
int err;
|
2010-01-11 01:58:17 +01:00
|
|
|
unsigned int success=0;
|
2008-03-30 09:00:22 +02:00
|
|
|
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;
|
|
|
|
|
2010-01-11 01:58:17 +01:00
|
|
|
FuncIteratorGuard guard(&m_IterGuard, &iter);
|
|
|
|
|
|
|
|
while (iter != m_functions.end())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
func = (*iter);
|
|
|
|
|
2009-12-20 03:16:41 +01:00
|
|
|
if (filter)
|
|
|
|
filter->Preprocess(func, temp_info);
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
for (unsigned int i=0; i<num_params; i++)
|
|
|
|
{
|
|
|
|
int err = SP_ERROR_PARAM;
|
|
|
|
param = &temp_info[i];
|
2008-07-08 11:20:47 +02:00
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
if (i >= m_numparams || m_types[i] == Param_Any)
|
|
|
|
{
|
|
|
|
type = param->pushedas;
|
2008-07-08 11:20:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-30 09:00:22 +02:00
|
|
|
type = m_types[i];
|
|
|
|
}
|
2008-07-08 11:20:47 +02:00
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
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);
|
2008-07-08 11:20:47 +02:00
|
|
|
}
|
|
|
|
else if (type == Param_Float || type == Param_Cell)
|
|
|
|
{
|
2008-03-30 09:00:22 +02:00
|
|
|
err = func->PushCellByRef(¶m->val);
|
2008-07-08 11:20:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-30 09:00:22 +02:00
|
|
|
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
|
|
|
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
|
|
|
}
|
2008-07-08 11:20:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-30 09:00:22 +02:00
|
|
|
/* 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);
|
|
|
|
}
|
2008-07-08 11:20:47 +02:00
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
if (err != SP_ERROR_NONE)
|
|
|
|
{
|
2013-10-09 14:43:08 +02:00
|
|
|
g_DbgReporter.GenerateError(func->GetParentContext(),
|
2008-07-08 11:20:47 +02:00
|
|
|
func->GetFunctionID(),
|
|
|
|
err,
|
|
|
|
"Failed to push parameter while executing forward");
|
2008-03-30 09:00:22 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Call the function and deal with the return value. */
|
2010-01-11 01:58:17 +01:00
|
|
|
if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
|
2008-07-08 11:20:47 +02:00
|
|
|
{
|
2008-03-30 09:00:22 +02:00
|
|
|
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;
|
|
|
|
}
|
2008-07-08 11:20:47 +02:00
|
|
|
case ET_LowEvent:
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2008-07-09 01:55:29 +02:00
|
|
|
/* Check if the current result is the lowest so far (or if it's the first result) */
|
|
|
|
if (cur_result < low_result || success == 1)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2008-07-08 11:20:47 +02:00
|
|
|
low_result = cur_result;
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-11 01:58:17 +01:00
|
|
|
|
|
|
|
if (!guard.Triggered())
|
|
|
|
iter++;
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
2008-07-08 11:20:47 +02:00
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
if (success)
|
|
|
|
{
|
2008-07-08 11:20:47 +02:00
|
|
|
switch (m_ExecType)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2008-07-08 11:20:47 +02:00
|
|
|
case ET_Ignore:
|
|
|
|
{
|
|
|
|
cur_result = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ET_Event:
|
|
|
|
case ET_Hook:
|
|
|
|
{
|
|
|
|
cur_result = high_result;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ET_LowEvent:
|
|
|
|
{
|
|
|
|
cur_result = low_result;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
2008-07-08 11:20:47 +02:00
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
*result = cur_result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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<IPluginFunction *> *lst;
|
|
|
|
|
|
|
|
if (func->IsRunnable())
|
|
|
|
{
|
|
|
|
lst = &m_functions;
|
|
|
|
} else {
|
|
|
|
lst = &m_paused;
|
|
|
|
}
|
|
|
|
|
2013-08-12 01:44:22 +02:00
|
|
|
for (iter=lst->begin(); iter!=lst->end(); iter++)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
if ((*iter) == func)
|
|
|
|
{
|
2010-01-11 01:58:17 +01:00
|
|
|
m_IterGuard->FixIteratorChain(iter);
|
2008-03-30 09:00:22 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-28 01:06:18 +02:00
|
|
|
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
|
|
|
{
|
|
|
|
FuncIter iter;
|
|
|
|
List<IPluginFunction *> *lst;
|
|
|
|
|
|
|
|
if (func->IsRunnable())
|
|
|
|
{
|
|
|
|
lst = &m_functions;
|
|
|
|
} else {
|
|
|
|
lst = &m_paused;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
|
|
|
{
|
|
|
|
if ((*iter) == func)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
const char *CForward::GetForwardName()
|
|
|
|
{
|
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CForward::GetFunctionCount()
|
|
|
|
{
|
|
|
|
return m_functions.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExecType CForward::GetExecType()
|
|
|
|
{
|
|
|
|
return m_ExecType;
|
|
|
|
}
|