1.1 --- a/core/systems/PluginSys.cpp Sat Jul 14 17:36:11 2007 +0000
1.2 +++ b/core/systems/PluginSys.cpp Sun Jul 15 01:04:34 2007 +0000
1.3 @@ -47,6 +47,7 @@
1.4 m_ident = NULL;
1.5 m_pProps = sm_trie_create();
1.6 m_FakeNativesMissing = false;
1.7 + m_LibraryMissing = false;
1.8 }
1.9
1.10 CPlugin::~CPlugin()
1.11 @@ -91,6 +92,13 @@
1.12 delete m_configs[i];
1.13 }
1.14 m_configs.clear();
1.15 +
1.16 + List<WeakNative *>::iterator iter;
1.17 + for (iter=m_WeakNatives.begin(); iter!=m_WeakNatives.end(); iter++)
1.18 + {
1.19 + delete (*iter);
1.20 + }
1.21 + m_WeakNatives.clear();
1.22 }
1.23
1.24 void CPlugin::InitIdentity()
1.25 @@ -357,19 +365,15 @@
1.26 return true;
1.27 }
1.28
1.29 - m_IsInAskPluginLoad = true;
1.30 pFunction->PushCell(m_handle);
1.31 pFunction->PushCell(g_PluginSys.IsLateLoadTime() ? 1 : 0);
1.32 pFunction->PushStringEx(error, maxlength, 0, SM_PARAM_COPYBACK);
1.33 pFunction->PushCell(maxlength);
1.34 if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE)
1.35 {
1.36 - m_IsInAskPluginLoad = false;
1.37 return false;
1.38 }
1.39
1.40 - m_IsInAskPluginLoad = false;
1.41 -
1.42 if (!result || m_status != Plugin_Loaded)
1.43 {
1.44 return false;
1.45 @@ -592,6 +596,19 @@
1.46 return;
1.47 }
1.48
1.49 + List<String>::iterator reqlib_iter;
1.50 + List<String>::iterator lib_iter;
1.51 + for (lib_iter=pOwner->m_Libraries.begin(); lib_iter!=pOwner->m_Libraries.end(); lib_iter++)
1.52 + {
1.53 + for (reqlib_iter=m_RequiredLibs.begin(); reqlib_iter!=m_RequiredLibs.end(); reqlib_iter++)
1.54 + {
1.55 + if ((*reqlib_iter) == (*lib_iter))
1.56 + {
1.57 + m_LibraryMissing = true;
1.58 + }
1.59 + }
1.60 + }
1.61 +
1.62 List<FakeNative *>::iterator iter;
1.63 FakeNative *pNative;
1.64 sp_native_t *native;
1.65 @@ -615,10 +632,14 @@
1.66 unbound++;
1.67 }
1.68
1.69 - /* :IDEA: in the future, add native trapping? */
1.70 if (unbound)
1.71 {
1.72 m_FakeNativesMissing = true;
1.73 + }
1.74 +
1.75 + /* :IDEA: in the future, add native trapping? */
1.76 + if (m_FakeNativesMissing || m_LibraryMissing)
1.77 + {
1.78 SetErrorState(Plugin_Error, "Depends on plugin: %s", pOwner->GetFilename());
1.79 }
1.80
1.81 @@ -1001,6 +1022,96 @@
1.82 m_AllPluginsLoaded = true;
1.83 }
1.84
1.85 +bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength)
1.86 +{
1.87 + struct _pl
1.88 + {
1.89 + cell_t name;
1.90 + cell_t file;
1.91 + cell_t required;
1.92 + } *pl;
1.93 +
1.94 + IPluginContext *pBase = pPlugin->GetBaseContext();
1.95 + uint32_t num = pBase->GetPubVarsNum();
1.96 + sp_pubvar_t *pubvar;
1.97 + char *name, *file;
1.98 + char pathfile[PLATFORM_MAX_PATH];
1.99 +
1.100 + for (uint32_t i=0; i<num; i++)
1.101 + {
1.102 + if (pBase->GetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE)
1.103 + {
1.104 + continue;
1.105 + }
1.106 + if (strncmp(pubvar->name, "__pl_", 5) == 0)
1.107 + {
1.108 + pl = (_pl *)pubvar->offs;
1.109 + if (pBase->LocalToString(pl->file, &file) != SP_ERROR_NONE)
1.110 + {
1.111 + continue;
1.112 + }
1.113 + if (pBase->LocalToString(pl->name, &name) != SP_ERROR_NONE)
1.114 + {
1.115 + continue;
1.116 + }
1.117 + g_LibSys.GetFileFromPath(pathfile, sizeof(pathfile), pPlugin->GetFilename());
1.118 + if (strcmp(pathfile, file) == 0)
1.119 + {
1.120 + continue;
1.121 + }
1.122 + if (pl->required == false)
1.123 + {
1.124 + IPluginFunction *pFunc;
1.125 + char buffer[64];
1.126 + UTIL_Format(buffer, sizeof(buffer), "__pl_%s_SetNTVOptional", &pubvar->name[6]);
1.127 + if ((pFunc=pBase->GetFunctionByName(buffer)))
1.128 + {
1.129 + cell_t res;
1.130 + pFunc->Execute(&res);
1.131 + if (pPlugin->GetContext()->n_err != SP_ERROR_NONE)
1.132 + {
1.133 + if (error)
1.134 + {
1.135 + snprintf(error, maxlength, "Fatal error during initializing plugin load");
1.136 + }
1.137 + return false;
1.138 + }
1.139 + }
1.140 + } else {
1.141 + /* Check that we aren't registering the same library twice */
1.142 + if (pPlugin->m_RequiredLibs.find(name) == pPlugin->m_RequiredLibs.end())
1.143 + {
1.144 + pPlugin->m_RequiredLibs.push_back(name);
1.145 + } else {
1.146 + continue;
1.147 + }
1.148 + List<CPlugin *>::iterator iter;
1.149 + CPlugin *pl;
1.150 + bool found = false;
1.151 + for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++)
1.152 + {
1.153 + pl = (*iter);
1.154 + if (pl->m_Libraries.find(name) != pl->m_Libraries.end())
1.155 + {
1.156 + found = true;
1.157 + break;
1.158 + }
1.159 + }
1.160 + if (!found)
1.161 + {
1.162 + if (error)
1.163 + {
1.164 + snprintf(error, maxlength, "Could not find required plugin \"%s\"", name);
1.165 + }
1.166 + return false;
1.167 + }
1.168 + }
1.169 + }
1.170 + }
1.171 +
1.172 + return true;
1.173 +}
1.174 +
1.175 bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength)
1.176 {
1.177 /* Find any extensions this plugin needs */
1.178 @@ -1089,6 +1200,11 @@
1.179 g_Extensions.BindAllNativesToPlugin(pPlugin);
1.180 AddFakeNativesToPlugin(pPlugin);
1.181
1.182 + if (!FindOrRequirePluginDeps(pPlugin, error, maxlength))
1.183 + {
1.184 + return false;
1.185 + }
1.186 +
1.187 /* Find any unbound natives
1.188 * Right now, these are not allowed
1.189 */
1.190 @@ -1136,9 +1252,9 @@
1.191 {
1.192 pOther = (*pl_iter);
1.193 if (pOther->GetStatus() == Plugin_Error
1.194 - && pOther->m_FakeNativesMissing)
1.195 + && (pOther->m_FakeNativesMissing || pOther->m_LibraryMissing))
1.196 {
1.197 - TryRefreshNatives(pOther);
1.198 + TryRefreshDependencies(pOther);
1.199 }
1.200 }
1.201 }
1.202 @@ -1163,12 +1279,37 @@
1.203 }
1.204 }
1.205
1.206 -void CPluginManager::TryRefreshNatives(CPlugin *pPlugin)
1.207 +void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
1.208 {
1.209 assert(pPlugin->GetBaseContext() != NULL);
1.210
1.211 AddFakeNativesToPlugin(pPlugin);
1.212
1.213 + List<String>::iterator lib_iter;
1.214 + List<String>::iterator req_iter;
1.215 + List<CPlugin *>::iterator pl_iter;
1.216 + CPlugin *pl;
1.217 + for (req_iter=pPlugin->m_RequiredLibs.begin(); req_iter!=pPlugin->m_RequiredLibs.end(); req_iter++)
1.218 + {
1.219 + bool found = false;
1.220 + for (pl_iter=m_plugins.begin(); pl_iter!=m_plugins.end(); pl_iter++)
1.221 + {
1.222 + pl = (*pl_iter);
1.223 + for (lib_iter=pl->m_Libraries.begin(); lib_iter!=pl->m_Libraries.end(); lib_iter++)
1.224 + {
1.225 + if ((*req_iter) == (*lib_iter))
1.226 + {
1.227 + found = true;
1.228 + }
1.229 + }
1.230 + }
1.231 + if (!found)
1.232 + {
1.233 + pPlugin->SetErrorState(Plugin_Error, "Library not found: %s", (*req_iter).c_str());
1.234 + return;
1.235 + }
1.236 + }
1.237 +
1.238 /* Find any unbound natives
1.239 * Right now, these are not allowed
1.240 */
1.241 @@ -1220,8 +1361,10 @@
1.242 {
1.243 uint32_t idx;
1.244 pContext->FindNativeByName(native.name, &idx);
1.245 - if (!(pPlugin->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL))
1.246 + if (pPlugin->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL)
1.247 {
1.248 + WeakNative *wkn = new WeakNative(pPlugin, idx);
1.249 + GetPluginByCtx(ctx)->m_WeakNatives.push_back(wkn);
1.250 continue;
1.251 }
1.252 /* Add us as a dependency, but we're careful not to do this circularly! */
1.253 @@ -1275,20 +1418,6 @@
1.254 pOther->m_dependents.remove(pPlugin);
1.255 }
1.256
1.257 - /* Remove all of our native functions */
1.258 - List<FakeNative *>::iterator fn_iter;
1.259 - FakeNative *pNative;
1.260 - for (fn_iter = pPlugin->m_fakeNatives.begin();
1.261 - fn_iter != pPlugin->m_fakeNatives.end();
1.262 - fn_iter++)
1.263 - {
1.264 - pNative = (*fn_iter);
1.265 - m_Natives.remove(pNative);
1.266 - sm_trie_delete(m_pNativeLookup, pNative->name.c_str());
1.267 - g_pVM->DestroyFakeNative(pNative->func);
1.268 - delete pNative;
1.269 - }
1.270 -
1.271 List<IPluginsListener *>::iterator iter;
1.272 IPluginsListener *pListener;
1.273
1.274 @@ -1304,6 +1433,30 @@
1.275 pPlugin->Call_OnPluginEnd();
1.276 }
1.277
1.278 + /* Remove all of our native functions */
1.279 + List<FakeNative *>::iterator fn_iter;
1.280 + FakeNative *pNative;
1.281 + for (fn_iter = pPlugin->m_fakeNatives.begin();
1.282 + fn_iter != pPlugin->m_fakeNatives.end();
1.283 + fn_iter++)
1.284 + {
1.285 + pNative = (*fn_iter);
1.286 + m_Natives.remove(pNative);
1.287 + sm_trie_delete(m_pNativeLookup, pNative->name.c_str());
1.288 + g_pVM->DestroyFakeNative(pNative->func);
1.289 + delete pNative;
1.290 + }
1.291 +
1.292 + /* Unbound weak natives */
1.293 + WeakNative *wkn;
1.294 + List<WeakNative *>::iterator wk_iter;
1.295 + for (wk_iter=pPlugin->m_WeakNatives.begin(); wk_iter!=pPlugin->m_WeakNatives.end(); wk_iter++)
1.296 + {
1.297 + wkn = (*wk_iter);
1.298 + sp_context_t *ctx = wkn->pl->GetContext();
1.299 + ctx->natives[wkn->idx].status = SP_NATIVE_UNBOUND;
1.300 + }
1.301 +
1.302 for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
1.303 {
1.304 /* Notify listeners of destruction */