NOTE: heap fails, working on a rewrite --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40186
		
			
				
	
	
		
			668 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <assert.h>
 | |
| #include "ForwardSys.h"
 | |
| #include "PluginSys.h"
 | |
| 
 | |
| CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, 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] = va_arg(ap, ParamType);
 | |
| 			if (_types[i] == Param_VarArgs && (i != num_params - 1))
 | |
| 			{
 | |
| 				return NULL;
 | |
| 			}
 | |
| 		}
 | |
| 		types = _types;
 | |
| 	} else {
 | |
| 		for (unsigned int i=0; i<num_params; i++)
 | |
| 		{
 | |
| 			if (types[i] == Param_VarArgs && (i != num_params - 1))
 | |
| 			{
 | |
| 				return NULL;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* First parameter can never be varargs */
 | |
| 	if (types[0] == Param_VarArgs)
 | |
| 	{
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	CForward *pForward = new CForward;
 | |
| 	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 = true;
 | |
| 	} else {
 | |
| 		pForward->m_varargs = false;
 | |
| 	}
 | |
| 
 | |
| 	pForward->m_numparams = num_params;
 | |
| 	pForward->m_errstate = SP_ERROR_NONE;
 | |
| 	pForward->m_CopyBacks.numrecopy = 0;
 | |
| 
 | |
| 	return pForward;
 | |
| }
 | |
| 
 | |
| bool CForward::OnCopybackArray(unsigned int param, 
 | |
| 							   unsigned int cells, 
 | |
| 							   cell_t *source_addr, 
 | |
| 							   cell_t *orig_addr, 
 | |
| 							   int flags)
 | |
| {
 | |
| 	/* Check if the stack is empty, this should be an assertion */
 | |
| 	if (m_NextStack.empty())
 | |
| 	{
 | |
| 		/* This should never happen! */
 | |
| 		assert(!m_NextStack.empty());
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/* Check if we even want to copy to the next plugin */
 | |
| 	if (!(flags & SMFUNC_COPYBACK_ALWAYS))
 | |
| 	{
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/* Keep track of the copy back and save the info */
 | |
| 	NextCallInfo &info = m_NextStack.front();
 | |
| 	info.recopy[info.numrecopy++] = param;
 | |
| 	info.orig_addrs[param] = orig_addr;
 | |
| 	info.sizes[param] = cells;
 | |
| 
 | |
| 	/* We don't want to override the copy. */
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| int CForward::Execute(cell_t *result, IForwardFilter *filter)
 | |
| {
 | |
| 	if (m_errstate)
 | |
| 	{
 | |
| 		int err = m_errstate;
 | |
| 		Cancel();
 | |
| 		return err;
 | |
| 	}
 | |
| 
 | |
| 	/* Reset marker */
 | |
| 	m_curparam = 0;
 | |
| 
 | |
| 	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 save_numcopy = 0;
 | |
| 
 | |
| 	/** 
 | |
| 	 * Save copyback into to start the chain, 
 | |
| 	 * then reset it for re-entrancy
 | |
| 	 */
 | |
| 	m_NextStack.push(m_CopyBacks);
 | |
| 	NextCallInfo &info = m_NextStack.front();
 | |
| 	m_CopyBacks.numrecopy = 0;
 | |
| 	
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		
 | |
| 		/**
 | |
| 		 * Check if we need to copy a new array back into the plugin.
 | |
| 		 */
 | |
| 		if (info.numrecopy)
 | |
| 		{
 | |
| 			/* The last plugin has a chained copyback, we must redirect it here. */
 | |
| 			unsigned int param;
 | |
| 			cell_t *orig_addr, *targ_addr;
 | |
| 			for (unsigned int i=0; i<info.numrecopy; i++)
 | |
| 			{
 | |
| 				/* Get the parameter info to copy */
 | |
| 				param = info.recopy[i];
 | |
| 				targ_addr = func->GetAddressOfPushedParam(param);
 | |
| 				orig_addr = info.orig_addrs[param];
 | |
| 				/* Only do the copy for valid targets */
 | |
| 				if (targ_addr && orig_addr)
 | |
| 				{
 | |
| 					if (info.sizes[param] == 1)
 | |
| 					{
 | |
| 						*targ_addr = *orig_addr;
 | |
| 					} else {
 | |
| 						memcpy(targ_addr, orig_addr, info.sizes[param] * sizeof(cell_t));
 | |
| 					}
 | |
| 				}
 | |
| 				/* If this failed, the plugin will most likely be failing as well. */
 | |
| 			}
 | |
| 			save_numcopy = info.numrecopy;
 | |
| 			info.numrecopy = 0;
 | |
| 		}
 | |
| 
 | |
| 		/* Call the function and deal with the return value.
 | |
| 		 * :TODO: only pass reader if we know we have an array in the list
 | |
| 		 */
 | |
| 		if ((err=func->Execute(&cur_result, this)) != SP_ERROR_NONE)
 | |
| 		{
 | |
| 			bool handled = false;
 | |
| 			if (filter)
 | |
| 			{
 | |
| 				handled = filter->OnErrorReport(this, func, err);
 | |
| 			}
 | |
| 			if (!handled)
 | |
| 			{
 | |
| 				/* :TODO: invoke global error reporting here */
 | |
| 			}
 | |
| 			/* If we failed, we're not quite done.  The copy chain has been broken.
 | |
| 			 * We have to restore it so past changes will continue to get mirrored.
 | |
| 			 */
 | |
| 			info.numrecopy = save_numcopy;
 | |
| 			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)
 | |
| 						{
 | |
| 							iter = m_functions.end();
 | |
| 							break;
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 			case ET_Custom:
 | |
| 				{
 | |
| 					if (filter)
 | |
| 					{
 | |
| 						if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
 | |
| 						{
 | |
| 							iter = m_functions.end();
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	m_NextStack.pop();
 | |
| 
 | |
| 	if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
 | |
| 	{
 | |
| 		cur_result = high_result;
 | |
| 	} else if (m_ExecType == ET_Ignore) {
 | |
| 		cur_result = 0;
 | |
| 	}
 | |
| 
 | |
| 	*result = cur_result;
 | |
| 
 | |
| 	DumpAdditionQueue();
 | |
| 
 | |
| 	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_Cell && m_types[m_curparam] != Param_Any)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAM);
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAMS_MAX);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->PushCell(cell);
 | |
| 	}
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| int CForward::PushFloat(float number)
 | |
| {
 | |
| 	if (m_curparam < m_numparams)
 | |
| 	{
 | |
| 		if (m_types[m_curparam] != Param_Float && m_types[m_curparam] != Param_Any)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAM);
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAMS_MAX);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->PushFloat(number);
 | |
| 	}
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| int CForward::PushCellByRef(cell_t *cell, int flags)
 | |
| {
 | |
| 	if (m_curparam < m_numparams)
 | |
| 	{
 | |
| 		if (m_types[m_curparam] != Param_CellByRef && m_types[m_curparam] != Param_Any)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAM);
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAMS_MAX);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (flags & SMFUNC_COPYBACK_ALWAYS)
 | |
| 	{
 | |
| 		_Int_PushArray(cell, 1, flags);
 | |
| 	} else {
 | |
| 		FuncIter iter;
 | |
| 		IPluginFunction *func;
 | |
| 		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 		{
 | |
| 			func = (*iter);
 | |
| 			func->PushCellByRef(cell, 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_FloatByRef && m_types[m_curparam] != Param_Any)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAM);
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAMS_MAX);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (flags & SMFUNC_COPYBACK_ALWAYS)
 | |
| 	{
 | |
| 		_Int_PushArray((cell_t *)num, 1, flags);
 | |
| 	} else {
 | |
| 		FuncIter iter;
 | |
| 		IPluginFunction *func;
 | |
| 		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 		{
 | |
| 			func = (*iter);
 | |
| 			func->PushFloatByRef(num, flags);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| int CForward::PushCells(cell_t array[], unsigned int numcells, bool each)
 | |
| {
 | |
| 	if (each)
 | |
| 	{
 | |
| 		/* Type check each cell if we need to! */
 | |
| 		if (m_curparam + numcells >= m_numparams && !m_varargs)
 | |
| 		{
 | |
| 			return SetError(SP_ERROR_PARAMS_MAX);
 | |
| 		} else {
 | |
| 			for (unsigned int i=m_curparam; i<m_numparams; i++)
 | |
| 			{
 | |
| 				if (m_types[i] != Param_Any || m_types[i] != Param_Cell)
 | |
| 				{
 | |
| 					return SetError(SP_ERROR_PARAM);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (m_curparam < m_numparams)
 | |
| 		{
 | |
| 			if (m_types[m_curparam] != Param_Any || 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);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->PushCells(array, numcells, each);
 | |
| 	}
 | |
| 
 | |
| 	m_curparam += each ? numcells : 1;
 | |
| 	
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
 | |
| {
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	if (flags & SMFUNC_COPYBACK_ALWAYS)
 | |
| 	{
 | |
| 		/* As a special optimization, we create blank default arrays because they will be 
 | |
| 		* copied over anyway!
 | |
| 		*/
 | |
| 		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 		{
 | |
| 			func = (*iter);
 | |
| 			func->PushArray(inarray, cells, NULL, flags|SMFUNC_ARRAY_NOINIT);
 | |
| 		}
 | |
| 		m_CopyBacks.recopy[m_CopyBacks.numrecopy++] = m_curparam;
 | |
| 		m_CopyBacks.orig_addrs[m_curparam] = inarray;
 | |
| 		m_CopyBacks.sizes[m_curparam] = cells;
 | |
| 	} else {
 | |
| 		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 		{
 | |
| 			func = (*iter);
 | |
| 			func->PushArray(inarray, cells, NULL, flags);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, 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_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);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (phys_addr)
 | |
| 	{
 | |
| 		*phys_addr = NULL;
 | |
| 	}
 | |
| 
 | |
| 	_Int_PushArray(inarray, cells, flags);
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| int CForward::PushString(const char *string)
 | |
| {
 | |
| 	if (m_curparam < m_numparams)
 | |
| 	{
 | |
| 		if (m_types[m_curparam] != Param_Any || 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);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->PushString(string);
 | |
| 	}
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| int CForward::PushStringByRef(char *string, int flags)
 | |
| {
 | |
| 	if (m_curparam < m_numparams)
 | |
| 	{
 | |
| 		if (m_types[m_curparam] != Param_Any || 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);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->PushStringByRef(string, flags);
 | |
| 	}
 | |
| 
 | |
| 	m_curparam++;
 | |
| 
 | |
| 	return SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| void CForward::Cancel()
 | |
| {
 | |
| 	if (!m_curparam)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		func->Cancel();
 | |
| 	}
 | |
| 
 | |
| 	m_CopyBacks.numrecopy = 0;
 | |
| 
 | |
| 	DumpAdditionQueue();
 | |
| 
 | |
| 	m_errstate = SP_ERROR_NONE;
 | |
| }
 | |
| 
 | |
| bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
 | |
| {
 | |
| 	IPlugin *pPlugin = g_PluginMngr.FindPluginByContext(ctx);
 | |
| 	if (!pPlugin)
 | |
| 	{
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
 | |
| 	if (!pFunc)
 | |
| 	{
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	return AddFunction(pFunc);
 | |
| }
 | |
| 
 | |
| bool CForward::RemoveFunction(IPluginFunction *func)
 | |
| {
 | |
| 	bool found = false;
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *pNext = NULL;
 | |
| 
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end();)
 | |
| 	{
 | |
| 		if ((*iter) == func)
 | |
| 		{
 | |
| 			found = true;
 | |
| 			/* If this iterator is being used, swap in a new one !*/
 | |
| 			iter = m_functions.erase(iter);
 | |
| 		} else {
 | |
| 			iter++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* Just in case */
 | |
| 	m_AddQueue.remove(func);
 | |
| 	
 | |
| 	/* Cancel a call, if any */
 | |
| 	if (found && (!m_NextStack.empty() || m_curparam))
 | |
| 	{
 | |
| 		func->Cancel();
 | |
| 	}
 | |
| 
 | |
| 	return found;
 | |
| }
 | |
| 
 | |
| unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
 | |
| {
 | |
| 	FuncIter iter;
 | |
| 	IPluginFunction *func;
 | |
| 	unsigned int removed = 0;
 | |
| 	for (iter=m_functions.begin(); iter!=m_functions.end();)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		if (func->GetParentPlugin() == plugin)
 | |
| 		{
 | |
| 			iter = m_functions.erase(iter);
 | |
| 			removed++;
 | |
| 		} else {
 | |
| 			iter++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for (iter=m_AddQueue.begin(); iter!=m_AddQueue.end();)
 | |
| 	{
 | |
| 		func = (*iter);
 | |
| 		if (func->GetParentPlugin() == plugin)
 | |
| 		{
 | |
| 			/* Don't count these toward the total */
 | |
| 			iter = m_functions.erase(iter);
 | |
| 		} else {
 | |
| 			iter++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return removed;
 | |
| }
 | |
| 
 | |
| void CForward::DumpAdditionQueue()
 | |
| {
 | |
| 	FuncIter iter = m_AddQueue.begin();
 | |
| 	while (iter != m_AddQueue.end())
 | |
| 	{
 | |
| 		m_functions.push_back((*iter));
 | |
| 		//:TODO: eventually we will tell the plugin we're using it
 | |
| 		iter = m_AddQueue.erase(iter);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| bool CForward::AddFunction(IPluginFunction *func)
 | |
| {
 | |
| 	if (m_curparam)
 | |
| 	{
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	if (!m_NextStack.empty())
 | |
| 	{
 | |
| 		m_AddQueue.push_back(func);
 | |
| 	} else {
 | |
| 		//:TODO: eventually we will tell the plugin we're using it
 | |
| 		m_functions.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;
 | |
| }
 |