4 CPluginManager g_PluginMngr;
6 CPluginManager::CPluginManager()
10 void CFunction::Set(funcid_t funcid, CPlugin *plugin)
16 int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
18 IPluginContext *ctx = m_pPlugin->m_ctx_current.base;
20 for (unsigned int i=0; i<num_params; i++)
22 ctx->PushCell(params[i]);
25 return ctx->Execute(m_funcid, result);
28 IPlugin *CFunction::GetParentPlugin()
33 CFunction::CFunction(funcid_t funcid, CPlugin *plugin) :
34 m_funcid(funcid), m_pPlugin(plugin)
38 CPlugin *CPlugin::CreatePlugin(const char *file,
44 static unsigned int MySerial = 0;
45 FILE *fp = fopen(file, "rb");
49 snprintf(error, maxlen, "Could not open file");
54 sp_plugin_t *pl = g_pSourcePawn->LoadFromFilePointer(fp, &err);
57 snprintf(error, maxlen, "Could not load plugin, error %d", err);
63 ICompilation *co = g_pVM->StartCompilation(pl);
67 if (!g_pVM->SetCompilationOption(co, "debug", "1"))
69 g_pVM->AbortCompilation(co);
70 snprintf(error, maxlen, "Could not set plugin to debug mode");
75 sp_context_t *ctx = g_pVM->CompileToContext(co, &err);
78 snprintf(error, maxlen, "Plugin failed to load, JIT error: %d", err);
82 IPluginContext *base = g_pSourcePawn->CreateBaseContext(ctx);
83 CPlugin *pPlugin = new CPlugin;
85 snprintf(pPlugin->m_filename, PLATFORM_MAX_PATH, "%s", file);
86 pPlugin->m_debugging = debug_default;
87 pPlugin->m_ctx_current.base = base;
88 pPlugin->m_ctx_current.ctx = ctx;
89 pPlugin->m_type = type;
90 pPlugin->m_serial = ++MySerial;
91 pPlugin->m_status = Plugin_Loaded;
92 pPlugin->m_plugin = pl;
94 pPlugin->UpdateInfo();
96 ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)(IPlugin *)pPlugin;
98 /* Build function information loosely */
99 pPlugin->m_funcsnum = g_pVM->FunctionCount(ctx);
101 if (pPlugin->m_funcsnum)
103 pPlugin->m_priv_funcs = new CFunction *[pPlugin->m_funcsnum];
104 memset(pPlugin->m_priv_funcs, 0, sizeof(CFunction *) * pPlugin->m_funcsnum);
106 pPlugin->m_priv_funcs = NULL;
109 if (pl->info.publics_num)
111 pPlugin->m_pub_funcs = new CFunction *[pl->info.publics_num];
112 memset(pPlugin->m_pub_funcs, 0, sizeof(CFunction *) * pl->info.publics_num);
114 pPlugin->m_pub_funcs = NULL;
120 IPluginFunction *CPlugin::GetFunctionById(funcid_t func_id)
122 CFunction *pFunc = NULL;
123 funcid_t save = func_id;
128 if (func_id >= m_plugin->info.publics_num)
132 pFunc = m_pub_funcs[func_id];
135 pFunc = g_PluginMngr.GetFunctionFromPool(save, this);
136 m_pub_funcs[func_id] = pFunc;
141 if (!g_pVM->FunctionLookup(m_ctx_current.ctx, func_id, &index))
145 pFunc = m_priv_funcs[func_id];
148 pFunc = g_PluginMngr.GetFunctionFromPool(save, this);
149 m_priv_funcs[func_id] = pFunc;
156 IPluginFunction *CPlugin::GetFunctionByName(const char *public_name)
159 IPluginContext *base = m_ctx_current.base;
161 if (base->FindPublicByName(public_name, &index) != SP_ERROR_NONE)
166 CFunction *pFunc = m_pub_funcs[index];
169 sp_public_t *pub = NULL;
170 base->GetPublicByIndex(index, &pub);
173 pFunc = g_PluginMngr.GetFunctionFromPool(pub->funcid, this);
174 m_pub_funcs[index] = pFunc;
181 void CPlugin::UpdateInfo()
183 /* Now grab the info */
185 IPluginContext *base = GetBaseContext();
186 int err = base->FindPubvarByName("myinfo", &idx);
188 if (err == SP_ERROR_NONE)
190 struct sm_plugininfo_c_t
198 sm_plugininfo_c_t *cinfo;
201 base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&cinfo);
202 base->LocalToString(cinfo->name, (char **)&m_info.name);
203 base->LocalToString(cinfo->description, (char **)&m_info.description);
204 base->LocalToString(cinfo->author, (char **)&m_info.author);
205 base->LocalToString(cinfo->url, (char **)&m_info.url);
206 base->LocalToString(cinfo->version, (char **)&m_info.version);
209 m_info.author = m_info.author ? m_info.author : "";
210 m_info.description = m_info.description ? m_info.description : "";
211 m_info.name = m_info.name ? m_info.name : "";
212 m_info.url = m_info.url ? m_info.url : "";
213 m_info.version = m_info.version ? m_info.version : "";
216 const sp_plugin_t *CPlugin::GetPluginStructure() const
221 IPluginContext *CPlugin::GetBaseContext() const
223 return m_ctx_current.base;
226 sp_context_t *CPlugin::GetContext() const
228 return m_ctx_current.ctx;
231 const char *CPlugin::GetFilename() const
236 PluginType CPlugin::GetType() const
241 const sm_plugininfo_t *CPlugin::GetPublicInfo() const
246 unsigned int CPlugin::GetSerial() const
251 PluginStatus CPlugin::GetStatus() const
256 bool CPlugin::IsDebugging() const
261 bool CPlugin::SetPauseState(bool paused)
263 if (paused && GetStatus() != Plugin_Paused)
266 } else if (!paused && GetStatus() != Plugin_Running) {
270 /* :TODO: execute some forwards or some crap */
278 CPluginManager::CPluginIterator::CPluginIterator(List<IPlugin *> *_mylist)
283 IPlugin *CPluginManager::CPluginIterator::GetPlugin()
288 bool CPluginManager::CPluginIterator::MorePlugins()
290 return (current != mylist->end());
293 void CPluginManager::CPluginIterator::NextPlugin()
298 void CPluginManager::CPluginIterator::Release()
300 g_PluginMngr.ReleaseIterator(this);
303 CPluginManager::CPluginIterator::~CPluginIterator()
307 void CPluginManager::CPluginIterator::Reset()
309 current = mylist->begin();
316 IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t err_max)
318 CPlugin *pPlugin = CPlugin::CreatePlugin(path, debug, type, error, err_max);
325 m_plugins.push_back(pPlugin);
327 List<IPluginsListener *>::iterator iter;
328 IPluginsListener *pListener;
329 for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
332 pListener->OnPluginCreated(pPlugin);
335 /* :TODO: a lot more... */
340 bool CPluginManager::UnloadPlugin(IPlugin *plugin)
342 CPlugin *pPlugin = (CPlugin *)plugin;
346 List<IPluginsListener *>::iterator iter;
347 IPluginsListener *pListener;
348 for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
351 pListener->OnPluginDestroyed(pPlugin);
354 if (pPlugin->m_pub_funcs)
356 for (uint32_t i=0; i<pPlugin->m_plugin->info.publics_num; i++)
358 delete pPlugin->m_pub_funcs[i];
360 delete [] pPlugin->m_pub_funcs;
361 pPlugin->m_pub_funcs = NULL;
364 if (pPlugin->m_priv_funcs)
366 for (unsigned int i=0; i<pPlugin->m_funcsnum; i++)
368 delete pPlugin->m_priv_funcs[i];
370 delete [] pPlugin->m_priv_funcs;
371 pPlugin->m_priv_funcs = NULL;
374 if (pPlugin->m_ctx_current.base)
376 g_pSourcePawn->FreeBaseContext(pPlugin->m_ctx_current.base);
378 if (pPlugin->m_ctx_backup.base)
380 g_pSourcePawn->FreeBaseContext(pPlugin->m_ctx_backup.base);
382 if (pPlugin->m_ctx_current.ctx)
384 pPlugin->m_ctx_current.ctx->vmbase->FreeContext(pPlugin->m_ctx_current.ctx);
386 if (pPlugin->m_ctx_backup.ctx)
388 pPlugin->m_ctx_backup.ctx->vmbase->FreeContext(pPlugin->m_ctx_backup.ctx);
391 g_pSourcePawn->FreeFromMemory(pPlugin->m_plugin);
398 IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx)
400 IPlugin *pl = (IPlugin *)ctx->user[SM_CONTEXTVAR_MYSELF];
404 unsigned int CPluginManager::GetPluginCount()
406 return m_plugins.size();
409 void CPluginManager::AddPluginsListener(IPluginsListener *listener)
411 m_listeners.push_back(listener);
414 void CPluginManager::RemovePluginsListener(IPluginsListener *listener)
416 m_listeners.remove(listener);
419 IPluginIterator *CPluginManager::GetPluginIterator()
423 return new CPluginIterator(&m_plugins);
425 CPluginIterator *iter = m_iters.front();
431 void CPluginManager::ReleaseIterator(CPluginIterator *iter)
436 void CPluginManager::ReleaseFunctionToPool(CFunction *func)
438 m_funcpool.push(func);
441 CFunction *CPluginManager::GetFunctionFromPool(funcid_t f, CPlugin *plugin)
443 if (m_funcpool.empty())
445 return new CFunction(f, plugin);
447 CFunction *func = m_funcpool.front();
449 func->Set(f, plugin);
454 CPluginManager::~CPluginManager()
456 //:TODO: we need a good way to free what we're holding