core/systems/PluginSys.cpp
changeset 1112 152ceef17866
parent 1089 275107f9ca95
child 1122 f07d8e10433b
     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 */