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: WHAT NEEDS TO BE TESTED IN THIS BEAST
13 * - Pushing no varargs
16 // :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
17 // so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
19 void CForwardManager::OnSourceModAllInitialized()
21 g_PluginSys.AddPluginsListener(this);
24 void CForwardManager::OnSourceModShutdown()
26 g_PluginSys.RemovePluginsListener(this);
29 IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, ...)
35 fwd = CForward::CreateForward(name, et, num_params, types, ap);
41 m_managed.push_back(fwd);
47 IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, ParamType *types, ...)
53 fwd = CForward::CreateForward(name, et, num_params, types, ap);
59 m_unmanaged.push_back(fwd);
65 void CForwardManager::OnPluginLoaded(IPlugin *plugin)
67 /* Attach any globally managed forwards */
68 List<CForward *>::iterator iter;
71 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
74 IPluginFunction *pFunc = plugin->GetFunctionByName(fwd->GetForwardName());
77 fwd->AddFunction(pFunc);
82 void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
84 List<CForward *>::iterator iter;
87 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
90 fwd->RemoveFunctionsOfPlugin(plugin);
93 for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
96 fwd->RemoveFunctionsOfPlugin(plugin);
100 IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
102 List<CForward *>::iterator iter;
105 for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
108 if (strcmp(fwd->GetForwardName(), name) == 0)
118 for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
121 if (strcmp(fwd->GetForwardName(), name) == 0)
139 void CForwardManager::ReleaseForward(IForward *forward)
141 ForwardFree(static_cast<CForward *>(forward));
144 void CForwardManager::ForwardFree(CForward *fwd)
146 m_FreeForwards.push(fwd);
149 CForward *CForwardManager::ForwardMake()
152 if (m_FreeForwards.empty())
156 fwd = m_FreeForwards.front();
157 m_FreeForwards.pop();
162 /*************************************
163 * ACTUAL FORWARD API IMPLEMENTATION *
164 *************************************/
166 CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
168 ParamType _types[SP_MAX_EXEC_PARAMS];
170 if (num_params > SP_MAX_EXEC_PARAMS)
175 if (types == NULL && num_params)
177 for (unsigned int i=0; i<num_params; i++)
179 _types[i] = va_arg(ap, ParamType);
180 if (_types[i] == Param_VarArgs && (i != num_params - 1))
187 for (unsigned int i=0; i<num_params; i++)
189 if (types[i] == Param_VarArgs && (i != num_params - 1))
196 /* First parameter can never be varargs */
197 if (types[0] == Param_VarArgs)
202 CForward *pForward = g_Forwards.ForwardMake();
203 pForward->m_curparam = 0;
204 pForward->m_ExecType = et;
205 snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
207 for (unsigned int i=0; i<num_params; i++)
209 pForward->m_types[i] = types[i];
212 if (num_params && types[num_params-1] == Param_VarArgs)
214 pForward->m_varargs = num_params--;
216 pForward->m_varargs = false;
219 pForward->m_numparams = num_params;
220 pForward->m_errstate = SP_ERROR_NONE;
225 int CForward::Execute(cell_t *result, IForwardFilter *filter)
229 int err = m_errstate;
236 filter->OnExecuteBegin();
239 FuncIter iter = m_functions.begin();
240 IPluginFunction *func;
241 cell_t cur_result = 0;
242 cell_t high_result = 0;
244 unsigned int failed=0, success=0;
245 unsigned int save_numcopy = 0;
246 unsigned int num_params = m_curparam;
247 FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
251 /* Save local, reset */
252 memcpy(temp_info, m_params, sizeof(m_params));
255 for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
258 if (func->GetParentPlugin()->GetStatus() == Plugin_Paused)
263 for (unsigned int i=0; i<num_params; i++)
265 param = &temp_info[i];
266 if (i >= m_numparams || m_types[i] == Param_Any)
268 type = param->pushedas;
272 if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
274 /* If we're byref or we're vararg, we always push everything by ref.
275 * Even if they're byval, we must push them byref.
277 if (type == Param_String)
279 func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
280 } else if (type == Param_Float || type == Param_Cell) {
281 func->PushCellByRef(¶m->val, 0);
283 func->PushArray(param->byref.orig_addr, param->byref.cells, NULL, param->byref.flags);
284 assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
287 /* If we're not byref or not vararg, our job is a bit easier. */
288 assert(type == Param_Cell || type == Param_Float);
289 func->PushCell(param->val);
293 /* Call the function and deal with the return value. */
294 if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
296 bool handled = false;
299 handled = filter->OnErrorReport(this, func, err);
303 /* :TODO: invoke global error reporting here */
312 if (cur_result > high_result)
314 high_result = cur_result;
320 if (cur_result > high_result)
322 high_result = cur_result;
323 if ((ResultType)high_result == Pl_Stop)
325 iter = m_functions.end();
335 if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
337 iter = m_functions.end();
346 if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
348 cur_result = high_result;
349 } else if (m_ExecType == ET_Ignore) {
353 *result = cur_result;
357 filter->OnExecuteEnd(&cur_result, success, failed);
360 return SP_ERROR_NONE;
363 int CForward::PushCell(cell_t cell)
365 if (m_curparam < m_numparams)
367 if (m_types[m_curparam] == Param_Any)
369 m_params[m_curparam].pushedas = Param_Cell;
370 } else if (m_types[m_curparam] != Param_Cell) {
371 return SetError(SP_ERROR_PARAM);
374 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
376 return SetError(SP_ERROR_PARAMS_MAX);
378 m_params[m_curparam].pushedas = Param_Cell;
381 m_params[m_curparam++].val = cell;
383 return SP_ERROR_NONE;
386 int CForward::PushFloat(float number)
388 if (m_curparam < m_numparams)
390 if (m_types[m_curparam] == Param_Any)
392 m_params[m_curparam].pushedas = Param_Float;
393 } else if (m_types[m_curparam] != Param_Float) {
394 return SetError(SP_ERROR_PARAM);
397 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
399 return SetError(SP_ERROR_PARAMS_MAX);
401 m_params[m_curparam].pushedas = Param_Float;
404 m_params[m_curparam++].val = *(cell_t *)&number;
406 return SP_ERROR_NONE;
409 int CForward::PushCellByRef(cell_t *cell, int flags)
411 if (m_curparam < m_numparams)
413 if (m_types[m_curparam] == Param_Any)
415 m_params[m_curparam].pushedas = Param_CellByRef;
416 } else if (m_types[m_curparam] != Param_CellByRef) {
417 return SetError(SP_ERROR_PARAM);
420 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
422 return SetError(SP_ERROR_PARAMS_MAX);
424 m_params[m_curparam].pushedas = Param_CellByRef;
427 _Int_PushArray(cell, 1, flags);
430 return SP_ERROR_NONE;
433 int CForward::PushFloatByRef(float *num, int flags)
435 if (m_curparam < m_numparams)
437 if (m_types[m_curparam] == Param_Any)
439 m_params[m_curparam].pushedas = Param_FloatByRef;
440 } else if (m_types[m_curparam] != Param_FloatByRef) {
441 return SetError(SP_ERROR_PARAM);
444 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
446 return SetError(SP_ERROR_PARAMS_MAX);
448 m_params[m_curparam].pushedas = Param_FloatByRef;
451 _Int_PushArray((cell_t *)num, 1, flags);
454 return SP_ERROR_NONE;
457 void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
459 m_params[m_curparam].byref.cells = cells;
460 m_params[m_curparam].byref.flags = flags;
461 m_params[m_curparam].byref.orig_addr = inarray;
464 int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
466 /* We don't allow this here */
469 return SetError(SP_ERROR_PARAM);
472 if (m_curparam < m_numparams)
474 if (m_types[m_curparam] == Param_Any)
476 m_params[m_curparam].pushedas = Param_Array;
477 } else if (m_types[m_curparam] != Param_Array) {
478 return SetError(SP_ERROR_PARAM);
481 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
483 return SetError(SP_ERROR_PARAMS_MAX);
485 m_params[m_curparam].pushedas = Param_Array;
493 _Int_PushArray(inarray, cells, flags);
497 return SP_ERROR_NONE;
500 void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
502 m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
503 m_params[m_curparam].byref.flags = cp_flags;
504 m_params[m_curparam].byref.orig_addr = inarray;
505 m_params[m_curparam].byref.sz_flags = sz_flags;
508 int CForward::PushString(const char *string)
510 if (m_curparam < m_numparams)
512 if (m_types[m_curparam] == Param_Any)
514 m_params[m_curparam].pushedas = Param_String;
515 } else if (m_types[m_curparam] != Param_String) {
516 return SetError(SP_ERROR_PARAM);
519 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
521 return SetError(SP_ERROR_PARAMS_MAX);
523 m_params[m_curparam].pushedas = Param_String;
526 _Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
529 return SP_ERROR_NONE;
532 int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
534 if (m_curparam < m_numparams)
536 if (m_types[m_curparam] == Param_Any)
538 m_params[m_curparam].pushedas = Param_String;
539 } else if (m_types[m_curparam] != Param_String) {
540 return SetError(SP_ERROR_PARAM);
543 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
545 return SetError(SP_ERROR_PARAMS_MAX);
547 m_params[m_curparam].pushedas = Param_String;
550 _Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
553 return SP_ERROR_NONE;
556 void CForward::Cancel()
564 m_errstate = SP_ERROR_NONE;
567 bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
569 IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx);
575 IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
581 return AddFunction(pFunc);
584 bool CForward::RemoveFunction(IPluginFunction *func)
588 IPluginFunction *pNext = NULL;
590 for (iter=m_functions.begin(); iter!=m_functions.end();)
595 /* If this iterator is being used, swap in a new one !*/
596 iter = m_functions.erase(iter);
602 /* Cancel a call, if any */
603 if (found || m_curparam)
611 unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
614 IPluginFunction *func;
615 unsigned int removed = 0;
616 for (iter=m_functions.begin(); iter!=m_functions.end();)
619 if (func->GetParentPlugin() == plugin)
621 iter = m_functions.erase(iter);
631 bool CForward::AddFunction(IPluginFunction *func)
638 //:IDEA: eventually we will tell the plugin we're using it [?]
639 m_functions.push_back(func);
644 const char *CForward::GetForwardName()
649 unsigned int CForward::GetFunctionCount()
651 return m_functions.size();
654 ExecType CForward::GetExecType()