2 #include "ForwardSys.h"
5 CForwardManager g_Forwards;
8 * Gensis turns to its source, reduction occurs stepwise although the essence is all one.
9 * End of line. FTL system check.
11 * :TODO: Implement the manager. ho ho ho
13 * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST (X=done, -=TODO)
16 * X Push cells byref (copyback tested = yes)
18 * X Push floats byref (copyback tested = yes)
19 * X Push arrays (copyback tested = yes)
20 * - Push strings (copyback tested = ??)
22 * - Pushing no varargs
23 * - Push vararg cells (copyback should be verified to not happen = ??)
24 * - Push vararg cells byref (copyback tested = ??)
25 * - Push vararg floats (copyback should be verified to not happen = ??)
26 * - Push vararg floats byref (copyback tested = ??)
27 * - Push vararg arrays (copyback tested = ??)
28 * - Push vararg strings (copyback tested = ??)
31 IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, ...)
37 fwd = CForward::CreateForward(name, et, num_params, types, ap);
44 IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, ParamType *types, ...)
50 fwd = CForward::CreateForward(name, et, num_params, types, ap);
57 IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
59 List<CForward *>::iterator iter;
62 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
65 if (strcmp(fwd->GetForwardName(), name) == 0)
75 for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
78 if (strcmp(fwd->GetForwardName(), name) == 0)
96 void CForwardManager::ReleaseForward(IForward *forward)
98 ForwardFree(static_cast<CForward *>(forward));
101 void CForwardManager::ForwardFree(CForward *fwd)
103 m_FreeForwards.push(fwd);
106 CForward *CForwardManager::ForwardMake()
109 if (m_FreeForwards.empty())
113 fwd = m_FreeForwards.front();
114 m_FreeForwards.pop();
119 /*************************************
120 * ACTUAL FORWARD API IMPLEMENTATION *
121 *************************************/
123 CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
125 ParamType _types[SP_MAX_EXEC_PARAMS];
127 if (num_params > SP_MAX_EXEC_PARAMS)
132 if (types == NULL && num_params)
134 for (unsigned int i=0; i<num_params; i++)
136 _types[i] = va_arg(ap, ParamType);
137 if (_types[i] == Param_VarArgs && (i != num_params - 1))
144 for (unsigned int i=0; i<num_params; i++)
146 if (types[i] == Param_VarArgs && (i != num_params - 1))
153 /* First parameter can never be varargs */
154 if (types[0] == Param_VarArgs)
159 CForward *pForward = g_Forwards.ForwardMake();
160 pForward->m_curparam = 0;
161 pForward->m_ExecType = et;
162 snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
164 for (unsigned int i=0; i<num_params; i++)
166 pForward->m_types[i] = types[i];
169 if (num_params && types[num_params-1] == Param_VarArgs)
171 pForward->m_varargs = num_params--;
173 pForward->m_varargs = false;
176 pForward->m_numparams = num_params;
177 pForward->m_errstate = SP_ERROR_NONE;
182 int CForward::Execute(cell_t *result, IForwardFilter *filter)
186 int err = m_errstate;
193 filter->OnExecuteBegin();
196 FuncIter iter = m_functions.begin();
197 IPluginFunction *func;
198 cell_t cur_result = 0;
199 cell_t high_result = 0;
201 unsigned int failed=0, success=0;
202 unsigned int save_numcopy = 0;
203 unsigned int num_params = m_curparam;
204 FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
208 /* Save local, reset */
209 memcpy(temp_info, m_params, sizeof(m_params));
212 for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
216 for (unsigned int i=0; i<num_params; i++)
218 param = &temp_info[i];
219 if (i >= m_numparams || m_types[i] == Param_Any)
221 type = param->pushedas;
225 if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
227 /* If we're byref or we're vararg, we always push everything by ref.
228 * Even if they're byval, we must push them byref.
230 if (type == Param_String)
232 func->PushStringEx((char *)param->byref.orig_addr, param->byref.flags);
233 } else if (type == Param_Float || type == Param_Cell) {
234 func->PushCellByRef(¶m->val, 0);
236 func->PushArray(param->byref.orig_addr, param->byref.cells, NULL, param->byref.flags);
237 assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
240 /* If we're not byref or not vararg, our job is a bit easier. */
241 assert(type == Param_Cell || type == Param_Float);
242 func->PushCell(param->val);
246 /* Call the function and deal with the return value.
247 * :TODO: only pass reader if we know we have an array in the list
249 if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
251 bool handled = false;
254 handled = filter->OnErrorReport(this, func, err);
258 /* :TODO: invoke global error reporting here */
267 if (cur_result > high_result)
269 high_result = cur_result;
275 if (cur_result > high_result)
277 high_result = cur_result;
278 if ((ResultType)high_result == Pl_Stop)
280 iter = m_functions.end();
290 if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
292 iter = m_functions.end();
301 if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
303 cur_result = high_result;
304 } else if (m_ExecType == ET_Ignore) {
308 *result = cur_result;
312 filter->OnExecuteEnd(&cur_result, success, failed);
315 return SP_ERROR_NONE;
318 int CForward::PushCell(cell_t cell)
320 if (m_curparam < m_numparams)
322 if (m_types[m_curparam] == Param_Any)
324 m_params[m_curparam].pushedas = Param_Cell;
325 } else if (m_types[m_curparam] != Param_Cell) {
326 return SetError(SP_ERROR_PARAM);
329 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
331 return SetError(SP_ERROR_PARAMS_MAX);
333 m_params[m_curparam].pushedas = Param_Cell;
336 m_params[m_curparam++].val = cell;
338 return SP_ERROR_NONE;
341 int CForward::PushFloat(float number)
343 if (m_curparam < m_numparams)
345 if (m_types[m_curparam] == Param_Any)
347 m_params[m_curparam].pushedas = Param_Float;
348 } else if (m_types[m_curparam] != Param_Float) {
349 return SetError(SP_ERROR_PARAM);
352 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
354 return SetError(SP_ERROR_PARAMS_MAX);
356 m_params[m_curparam].pushedas = Param_Float;
359 m_params[m_curparam++].val = *(cell_t *)&number;
361 return SP_ERROR_NONE;
364 int CForward::PushCellByRef(cell_t *cell, int flags)
366 if (m_curparam < m_numparams)
368 if (m_types[m_curparam] != Param_CellByRef && m_types[m_curparam] != Param_Any)
370 return SetError(SP_ERROR_PARAM);
373 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
375 return SetError(SP_ERROR_PARAMS_MAX);
379 _Int_PushArray(cell, 1, flags);
382 return SP_ERROR_NONE;
385 int CForward::PushFloatByRef(float *num, int flags)
387 if (m_curparam < m_numparams)
389 if (m_types[m_curparam] != Param_FloatByRef && m_types[m_curparam] != Param_Any)
391 return SetError(SP_ERROR_PARAM);
394 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
396 return SetError(SP_ERROR_PARAMS_MAX);
400 _Int_PushArray((cell_t *)num, 1, flags);
403 return SP_ERROR_NONE;
406 void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
408 m_params[m_curparam].byref.cells = cells;
409 m_params[m_curparam].byref.flags = flags;
410 m_params[m_curparam].byref.orig_addr = inarray;
413 int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
415 /* We don't allow this here */
418 return SetError(SP_ERROR_PARAM);
421 if (m_curparam < m_numparams)
423 if (m_types[m_curparam] == Param_Any)
425 m_params[m_curparam].pushedas = Param_Array;
426 } else if (m_types[m_curparam] != Param_Array) {
427 return SetError(SP_ERROR_PARAM);
430 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
432 return SetError(SP_ERROR_PARAMS_MAX);
434 m_params[m_curparam].pushedas = Param_Array;
442 _Int_PushArray(inarray, cells, flags);
446 return SP_ERROR_NONE;
449 int CForward::PushString(const char *string)
451 if (m_curparam < m_numparams)
453 if (m_types[m_curparam] == Param_Any)
455 m_params[m_curparam].pushedas = Param_String;
456 } else if (m_types[m_curparam] == Param_String) {
457 return SetError(SP_ERROR_PARAM);
460 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
462 return SetError(SP_ERROR_PARAMS_MAX);
464 m_params[m_curparam].pushedas = Param_String;
467 _Int_PushArray((cell_t *)string, 0, 0);
470 return SP_ERROR_NONE;
473 int CForward::PushStringEx(char *string, int flags)
475 if (m_curparam < m_numparams)
477 if (m_types[m_curparam] == Param_Any)
479 m_params[m_curparam].pushedas = Param_String;
480 } else if (m_types[m_curparam] == Param_String) {
481 return SetError(SP_ERROR_PARAM);
484 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
486 return SetError(SP_ERROR_PARAMS_MAX);
488 m_params[m_curparam].pushedas = Param_String;
491 _Int_PushArray((cell_t *)string, 0, flags);
494 return SP_ERROR_NONE;
497 void CForward::Cancel()
505 m_errstate = SP_ERROR_NONE;
508 bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
510 IPlugin *pPlugin = g_PluginMngr.FindPluginByContext(ctx);
516 IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
522 return AddFunction(pFunc);
525 bool CForward::RemoveFunction(IPluginFunction *func)
529 IPluginFunction *pNext = NULL;
531 for (iter=m_functions.begin(); iter!=m_functions.end();)
536 /* If this iterator is being used, swap in a new one !*/
537 iter = m_functions.erase(iter);
543 /* Cancel a call, if any */
544 if (found || m_curparam)
552 unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
555 IPluginFunction *func;
556 unsigned int removed = 0;
557 for (iter=m_functions.begin(); iter!=m_functions.end();)
560 if (func->GetParentPlugin() == plugin)
562 iter = m_functions.erase(iter);
572 bool CForward::AddFunction(IPluginFunction *func)
579 //:TODO: eventually we will tell the plugin we're using it
580 m_functions.push_back(func);
585 const char *CForward::GetForwardName()
590 unsigned int CForward::GetFunctionCount()
592 return m_functions.size();
595 ExecType CForward::GetExecType()