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 * X Push strings (copyback tested = yes)
22 * - Pushing no varargs
23 * X Push vararg cells (copyback should be verified to not happen = didnt happen)
24 * X Push vararg cells byref (copyback tested = yes)
25 * X Push vararg floats (copyback should be verified to not happen = didnt happen)
26 * X Push vararg floats byref (copyback tested = yes)
27 * X Push vararg arrays (copyback tested = yes)
28 * X Push vararg strings (copyback tested = :TODO:)
31 // :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
32 // so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
34 void CForwardManager::OnSourceModAllInitialized()
36 g_PluginSys.AddPluginsListener(this);
39 void CForwardManager::OnSourceModShutdown()
41 g_PluginSys.RemovePluginsListener(this);
44 IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, ...)
50 fwd = CForward::CreateForward(name, et, num_params, types, ap);
56 m_managed.push_back(fwd);
62 IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, ParamType *types, ...)
68 fwd = CForward::CreateForward(name, et, num_params, types, ap);
74 m_unmanaged.push_back(fwd);
80 void CForwardManager::OnPluginLoaded(IPlugin *plugin)
82 /* Attach any globally managed forwards */
83 List<CForward *>::iterator iter;
86 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
89 IPluginFunction *pFunc = plugin->GetFunctionByName(fwd->GetForwardName());
92 fwd->AddFunction(pFunc);
97 void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
99 List<CForward *>::iterator iter;
102 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
105 fwd->RemoveFunctionsOfPlugin(plugin);
108 for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
111 fwd->RemoveFunctionsOfPlugin(plugin);
115 IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
117 List<CForward *>::iterator iter;
120 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
123 if (strcmp(fwd->GetForwardName(), name) == 0)
133 for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
136 if (strcmp(fwd->GetForwardName(), name) == 0)
154 void CForwardManager::ReleaseForward(IForward *forward)
156 ForwardFree(static_cast<CForward *>(forward));
159 void CForwardManager::ForwardFree(CForward *fwd)
161 m_FreeForwards.push(fwd);
164 CForward *CForwardManager::ForwardMake()
167 if (m_FreeForwards.empty())
171 fwd = m_FreeForwards.front();
172 m_FreeForwards.pop();
177 /*************************************
178 * ACTUAL FORWARD API IMPLEMENTATION *
179 *************************************/
181 CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
183 ParamType _types[SP_MAX_EXEC_PARAMS];
185 if (num_params > SP_MAX_EXEC_PARAMS)
190 if (types == NULL && num_params)
192 for (unsigned int i=0; i<num_params; i++)
194 _types[i] = va_arg(ap, ParamType);
195 if (_types[i] == Param_VarArgs && (i != num_params - 1))
202 for (unsigned int i=0; i<num_params; i++)
204 if (types[i] == Param_VarArgs && (i != num_params - 1))
211 /* First parameter can never be varargs */
212 if (types[0] == Param_VarArgs)
217 CForward *pForward = g_Forwards.ForwardMake();
218 pForward->m_curparam = 0;
219 pForward->m_ExecType = et;
220 snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
222 for (unsigned int i=0; i<num_params; i++)
224 pForward->m_types[i] = types[i];
227 if (num_params && types[num_params-1] == Param_VarArgs)
229 pForward->m_varargs = num_params--;
231 pForward->m_varargs = false;
234 pForward->m_numparams = num_params;
235 pForward->m_errstate = SP_ERROR_NONE;
240 int CForward::Execute(cell_t *result, IForwardFilter *filter)
244 int err = m_errstate;
251 filter->OnExecuteBegin();
254 FuncIter iter = m_functions.begin();
255 IPluginFunction *func;
256 cell_t cur_result = 0;
257 cell_t high_result = 0;
259 unsigned int failed=0, success=0;
260 unsigned int save_numcopy = 0;
261 unsigned int num_params = m_curparam;
262 FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
266 /* Save local, reset */
267 memcpy(temp_info, m_params, sizeof(m_params));
270 for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
274 for (unsigned int i=0; i<num_params; i++)
276 param = &temp_info[i];
277 if (i >= m_numparams || m_types[i] == Param_Any)
279 type = param->pushedas;
283 if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
285 /* If we're byref or we're vararg, we always push everything by ref.
286 * Even if they're byval, we must push them byref.
288 if (type == Param_String)
290 func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
291 } else if (type == Param_Float || type == Param_Cell) {
292 func->PushCellByRef(¶m->val, 0);
294 func->PushArray(param->byref.orig_addr, param->byref.cells, NULL, param->byref.flags);
295 assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
298 /* If we're not byref or not vararg, our job is a bit easier. */
299 assert(type == Param_Cell || type == Param_Float);
300 func->PushCell(param->val);
304 /* Call the function and deal with the return value. */
305 if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
307 bool handled = false;
310 handled = filter->OnErrorReport(this, func, err);
314 /* :TODO: invoke global error reporting here */
323 if (cur_result > high_result)
325 high_result = cur_result;
331 if (cur_result > high_result)
333 high_result = cur_result;
334 if ((ResultType)high_result == Pl_Stop)
336 iter = m_functions.end();
346 if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
348 iter = m_functions.end();
357 if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
359 cur_result = high_result;
360 } else if (m_ExecType == ET_Ignore) {
364 *result = cur_result;
368 filter->OnExecuteEnd(&cur_result, success, failed);
371 return SP_ERROR_NONE;
374 int CForward::PushCell(cell_t cell)
376 if (m_curparam < m_numparams)
378 if (m_types[m_curparam] == Param_Any)
380 m_params[m_curparam].pushedas = Param_Cell;
381 } else if (m_types[m_curparam] != Param_Cell) {
382 return SetError(SP_ERROR_PARAM);
385 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
387 return SetError(SP_ERROR_PARAMS_MAX);
389 m_params[m_curparam].pushedas = Param_Cell;
392 m_params[m_curparam++].val = cell;
394 return SP_ERROR_NONE;
397 int CForward::PushFloat(float number)
399 if (m_curparam < m_numparams)
401 if (m_types[m_curparam] == Param_Any)
403 m_params[m_curparam].pushedas = Param_Float;
404 } else if (m_types[m_curparam] != Param_Float) {
405 return SetError(SP_ERROR_PARAM);
408 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
410 return SetError(SP_ERROR_PARAMS_MAX);
412 m_params[m_curparam].pushedas = Param_Float;
415 m_params[m_curparam++].val = *(cell_t *)&number;
417 return SP_ERROR_NONE;
420 int CForward::PushCellByRef(cell_t *cell, int flags)
422 if (m_curparam < m_numparams)
424 if (m_types[m_curparam] == Param_Any)
426 m_params[m_curparam].pushedas = Param_CellByRef;
427 } else if (m_types[m_curparam] != Param_CellByRef) {
428 return SetError(SP_ERROR_PARAM);
431 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
433 return SetError(SP_ERROR_PARAMS_MAX);
435 m_params[m_curparam].pushedas = Param_CellByRef;
438 _Int_PushArray(cell, 1, flags);
441 return SP_ERROR_NONE;
444 int CForward::PushFloatByRef(float *num, int flags)
446 if (m_curparam < m_numparams)
448 if (m_types[m_curparam] == Param_Any)
450 m_params[m_curparam].pushedas = Param_FloatByRef;
451 } else if (m_types[m_curparam] != Param_FloatByRef) {
452 return SetError(SP_ERROR_PARAM);
455 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
457 return SetError(SP_ERROR_PARAMS_MAX);
459 m_params[m_curparam].pushedas = Param_FloatByRef;
462 _Int_PushArray((cell_t *)num, 1, flags);
465 return SP_ERROR_NONE;
468 void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
470 m_params[m_curparam].byref.cells = cells;
471 m_params[m_curparam].byref.flags = flags;
472 m_params[m_curparam].byref.orig_addr = inarray;
475 int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
477 /* We don't allow this here */
480 return SetError(SP_ERROR_PARAM);
483 if (m_curparam < m_numparams)
485 if (m_types[m_curparam] == Param_Any)
487 m_params[m_curparam].pushedas = Param_Array;
488 } else if (m_types[m_curparam] != Param_Array) {
489 return SetError(SP_ERROR_PARAM);
492 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
494 return SetError(SP_ERROR_PARAMS_MAX);
496 m_params[m_curparam].pushedas = Param_Array;
504 _Int_PushArray(inarray, cells, flags);
508 return SP_ERROR_NONE;
511 void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
513 m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
514 m_params[m_curparam].byref.flags = cp_flags;
515 m_params[m_curparam].byref.orig_addr = inarray;
516 m_params[m_curparam].byref.sz_flags = sz_flags;
519 int CForward::PushString(const char *string)
521 if (m_curparam < m_numparams)
523 if (m_types[m_curparam] == Param_Any)
525 m_params[m_curparam].pushedas = Param_String;
526 } else if (m_types[m_curparam] != Param_String) {
527 return SetError(SP_ERROR_PARAM);
530 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
532 return SetError(SP_ERROR_PARAMS_MAX);
534 m_params[m_curparam].pushedas = Param_String;
537 _Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
540 return SP_ERROR_NONE;
543 int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
545 if (m_curparam < m_numparams)
547 if (m_types[m_curparam] == Param_Any)
549 m_params[m_curparam].pushedas = Param_String;
550 } else if (m_types[m_curparam] != Param_String) {
551 return SetError(SP_ERROR_PARAM);
554 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
556 return SetError(SP_ERROR_PARAMS_MAX);
558 m_params[m_curparam].pushedas = Param_String;
561 _Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
564 return SP_ERROR_NONE;
567 void CForward::Cancel()
575 m_errstate = SP_ERROR_NONE;
578 bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
580 IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx);
586 IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
592 return AddFunction(pFunc);
595 bool CForward::RemoveFunction(IPluginFunction *func)
599 IPluginFunction *pNext = NULL;
601 for (iter=m_functions.begin(); iter!=m_functions.end();)
606 /* If this iterator is being used, swap in a new one !*/
607 iter = m_functions.erase(iter);
613 /* Cancel a call, if any */
614 if (found || m_curparam)
622 unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
625 IPluginFunction *func;
626 unsigned int removed = 0;
627 for (iter=m_functions.begin(); iter!=m_functions.end();)
630 if (func->GetParentPlugin() == plugin)
632 iter = m_functions.erase(iter);
642 bool CForward::AddFunction(IPluginFunction *func)
649 //:TODO: eventually we will tell the plugin we're using it [?]
650 m_functions.push_back(func);
655 const char *CForward::GetForwardName()
660 unsigned int CForward::GetFunctionCount()
662 return m_functions.size();
665 ExecType CForward::GetExecType()