Redesigned how server commands work. The "plugins" command will be back soon.
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);
147 m_managed.remove(fwd);
150 CForward *CForwardManager::ForwardMake()
153 if (m_FreeForwards.empty())
157 fwd = m_FreeForwards.front();
158 m_FreeForwards.pop();
163 /*************************************
164 * ACTUAL FORWARD API IMPLEMENTATION *
165 *************************************/
167 CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
169 ParamType _types[SP_MAX_EXEC_PARAMS];
171 if (num_params > SP_MAX_EXEC_PARAMS)
176 if (types == NULL && num_params)
178 for (unsigned int i=0; i<num_params; i++)
180 _types[i] = va_arg(ap, ParamType);
181 if (_types[i] == Param_VarArgs && (i != num_params - 1))
188 for (unsigned int i=0; i<num_params; i++)
190 if (types[i] == Param_VarArgs && (i != num_params - 1))
197 /* First parameter can never be varargs */
198 if (types[0] == Param_VarArgs)
203 CForward *pForward = g_Forwards.ForwardMake();
204 pForward->m_curparam = 0;
205 pForward->m_ExecType = et;
206 snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
208 for (unsigned int i=0; i<num_params; i++)
210 pForward->m_types[i] = types[i];
213 if (num_params && types[num_params-1] == Param_VarArgs)
215 pForward->m_varargs = num_params--;
217 pForward->m_varargs = false;
220 pForward->m_numparams = num_params;
221 pForward->m_errstate = SP_ERROR_NONE;
226 int CForward::Execute(cell_t *result, IForwardFilter *filter)
230 int err = m_errstate;
237 filter->OnExecuteBegin();
240 FuncIter iter = m_functions.begin();
241 IPluginFunction *func;
242 cell_t cur_result = 0;
243 cell_t high_result = 0;
245 unsigned int failed=0, success=0;
246 unsigned int save_numcopy = 0;
247 unsigned int num_params = m_curparam;
248 FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
252 /* Save local, reset */
253 memcpy(temp_info, m_params, sizeof(m_params));
256 for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
259 if (func->GetParentPlugin()->GetStatus() == Plugin_Paused)
264 for (unsigned int i=0; i<num_params; i++)
266 param = &temp_info[i];
267 if (i >= m_numparams || m_types[i] == Param_Any)
269 type = param->pushedas;
273 if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
275 /* If we're byref or we're vararg, we always push everything by ref.
276 * Even if they're byval, we must push them byref.
278 if (type == Param_String)
280 func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
281 } else if (type == Param_Float || type == Param_Cell) {
282 func->PushCellByRef(¶m->val, 0);
284 func->PushArray(param->byref.orig_addr, param->byref.cells, NULL, param->byref.flags);
285 assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
288 /* If we're not byref or not vararg, our job is a bit easier. */
289 assert(type == Param_Cell || type == Param_Float);
290 func->PushCell(param->val);
294 /* Call the function and deal with the return value. */
295 if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
297 bool handled = false;
300 handled = filter->OnErrorReport(this, func, err);
304 /* :TODO: invoke global error reporting here */
313 if (cur_result > high_result)
315 high_result = cur_result;
321 if (cur_result > high_result)
323 high_result = cur_result;
324 if ((ResultType)high_result == Pl_Stop)
326 iter = m_functions.end();
336 if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
338 iter = m_functions.end();
347 if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
349 cur_result = high_result;
350 } else if (m_ExecType == ET_Ignore) {
354 *result = cur_result;
358 filter->OnExecuteEnd(&cur_result, success, failed);
361 return SP_ERROR_NONE;
364 int CForward::PushCell(cell_t cell)
366 if (m_curparam < m_numparams)
368 if (m_types[m_curparam] == Param_Any)
370 m_params[m_curparam].pushedas = Param_Cell;
371 } else if (m_types[m_curparam] != Param_Cell) {
372 return SetError(SP_ERROR_PARAM);
375 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
377 return SetError(SP_ERROR_PARAMS_MAX);
379 m_params[m_curparam].pushedas = Param_Cell;
382 m_params[m_curparam++].val = cell;
384 return SP_ERROR_NONE;
387 int CForward::PushFloat(float number)
389 if (m_curparam < m_numparams)
391 if (m_types[m_curparam] == Param_Any)
393 m_params[m_curparam].pushedas = Param_Float;
394 } else if (m_types[m_curparam] != Param_Float) {
395 return SetError(SP_ERROR_PARAM);
398 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
400 return SetError(SP_ERROR_PARAMS_MAX);
402 m_params[m_curparam].pushedas = Param_Float;
405 m_params[m_curparam++].val = *(cell_t *)&number;
407 return SP_ERROR_NONE;
410 int CForward::PushCellByRef(cell_t *cell, int flags)
412 if (m_curparam < m_numparams)
414 if (m_types[m_curparam] == Param_Any)
416 m_params[m_curparam].pushedas = Param_CellByRef;
417 } else if (m_types[m_curparam] != Param_CellByRef) {
418 return SetError(SP_ERROR_PARAM);
421 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
423 return SetError(SP_ERROR_PARAMS_MAX);
425 m_params[m_curparam].pushedas = Param_CellByRef;
428 _Int_PushArray(cell, 1, flags);
431 return SP_ERROR_NONE;
434 int CForward::PushFloatByRef(float *num, int flags)
436 if (m_curparam < m_numparams)
438 if (m_types[m_curparam] == Param_Any)
440 m_params[m_curparam].pushedas = Param_FloatByRef;
441 } else if (m_types[m_curparam] != Param_FloatByRef) {
442 return SetError(SP_ERROR_PARAM);
445 if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
447 return SetError(SP_ERROR_PARAMS_MAX);
449 m_params[m_curparam].pushedas = Param_FloatByRef;
452 _Int_PushArray((cell_t *)num, 1, flags);
455 return SP_ERROR_NONE;
458 void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
460 m_params[m_curparam].byref.cells = cells;
461 m_params[m_curparam].byref.flags = flags;
462 m_params[m_curparam].byref.orig_addr = inarray;
465 int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
467 /* We don't allow this here */
470 return SetError(SP_ERROR_PARAM);
473 if (m_curparam < m_numparams)
475 if (m_types[m_curparam] == Param_Any)
477 m_params[m_curparam].pushedas = Param_Array;
478 } else if (m_types[m_curparam] != Param_Array) {
479 return SetError(SP_ERROR_PARAM);
482 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
484 return SetError(SP_ERROR_PARAMS_MAX);
486 m_params[m_curparam].pushedas = Param_Array;
494 _Int_PushArray(inarray, cells, flags);
498 return SP_ERROR_NONE;
501 void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
503 m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
504 m_params[m_curparam].byref.flags = cp_flags;
505 m_params[m_curparam].byref.orig_addr = inarray;
506 m_params[m_curparam].byref.sz_flags = sz_flags;
509 int CForward::PushString(const char *string)
511 if (m_curparam < m_numparams)
513 if (m_types[m_curparam] == Param_Any)
515 m_params[m_curparam].pushedas = Param_String;
516 } else if (m_types[m_curparam] != Param_String) {
517 return SetError(SP_ERROR_PARAM);
520 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
522 return SetError(SP_ERROR_PARAMS_MAX);
524 m_params[m_curparam].pushedas = Param_String;
527 _Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
530 return SP_ERROR_NONE;
533 int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
535 if (m_curparam < m_numparams)
537 if (m_types[m_curparam] == Param_Any)
539 m_params[m_curparam].pushedas = Param_String;
540 } else if (m_types[m_curparam] != Param_String) {
541 return SetError(SP_ERROR_PARAM);
544 if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
546 return SetError(SP_ERROR_PARAMS_MAX);
548 m_params[m_curparam].pushedas = Param_String;
551 _Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
554 return SP_ERROR_NONE;
557 void CForward::Cancel()
565 m_errstate = SP_ERROR_NONE;
568 bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
570 IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx);
576 IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
582 return AddFunction(pFunc);
585 bool CForward::RemoveFunction(IPluginFunction *func)
589 IPluginFunction *pNext = NULL;
591 for (iter=m_functions.begin(); iter!=m_functions.end();)
596 /* If this iterator is being used, swap in a new one !*/
597 iter = m_functions.erase(iter);
603 /* Cancel a call, if any */
604 if (found || m_curparam)
612 unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
615 IPluginFunction *func;
616 unsigned int removed = 0;
617 for (iter=m_functions.begin(); iter!=m_functions.end();)
620 if (func->GetParentPlugin() == plugin)
622 iter = m_functions.erase(iter);
632 bool CForward::AddFunction(IPluginFunction *func)
639 //:IDEA: eventually we will tell the plugin we're using it [?]
640 m_functions.push_back(func);
645 const char *CForward::GetForwardName()
650 unsigned int CForward::GetFunctionCount()
652 return m_functions.size();
655 ExecType CForward::GetExecType()