core/systems/ShareSys.cpp
changeset 2086 debb2ab2c782
parent 1952 b7aa2b626807
child 2193 db7c6362f3f2
     1.1 --- a/core/systems/ShareSys.cpp	Mon May 26 07:48:26 2008 +0000
     1.2 +++ b/core/systems/ShareSys.cpp	Mon May 26 07:51:11 2008 +0000
     1.3 @@ -33,8 +33,11 @@
     1.4  #include "HandleSys.h"
     1.5  #include "ExtensionSys.h"
     1.6  #include "LibrarySys.h"
     1.7 +#include "PluginSys.h"
     1.8 +#include "sm_stringutil.h"
     1.9  
    1.10  ShareSystem g_ShareSys;
    1.11 +static unsigned int g_mark_serial = 0;
    1.12  
    1.13  ShareSystem::ShareSystem()
    1.14  {
    1.15 @@ -200,7 +203,11 @@
    1.16  
    1.17  void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
    1.18  {
    1.19 -	g_Extensions.AddNatives(myself, natives);
    1.20 +	CNativeOwner *pOwner;
    1.21 +
    1.22 +	pOwner = g_Extensions.GetNativeOwner(myself);
    1.23 +
    1.24 +	pOwner->AddNatives(natives);
    1.25  }
    1.26  
    1.27  void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
    1.28 @@ -228,7 +235,9 @@
    1.29  		if ((*iter).owner == pExtension)
    1.30  		{
    1.31  			iter = m_Interfaces.erase(iter);
    1.32 -		} else {
    1.33 +		}
    1.34 +		else
    1.35 +		{
    1.36  			iter++;
    1.37  		}
    1.38  	}
    1.39 @@ -246,5 +255,261 @@
    1.40  
    1.41  void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
    1.42  {
    1.43 -	g_Extensions.OverrideNatives(myself, natives);
    1.44 +	unsigned int i;
    1.45 +	NativeEntry *pEntry;
    1.46 +	CNativeOwner *pOwner;
    1.47 +
    1.48 +	pOwner = g_Extensions.GetNativeOwner(myself);
    1.49 +
    1.50 +	for (i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
    1.51 +	{
    1.52 +		if ((pEntry = FindNative(natives[i].name)) == NULL)
    1.53 +		{
    1.54 +			continue;
    1.55 +		}
    1.56 +
    1.57 +		if (pEntry->owner != g_pCoreNatives)
    1.58 +		{
    1.59 +			continue;
    1.60 +		}
    1.61 +
    1.62 +		if (pEntry->replacement.owner != NULL)
    1.63 +		{
    1.64 +			continue;
    1.65 +		}
    1.66 +
    1.67 +		/* Now it's safe to add the override */
    1.68 +		pEntry->replacement.func = natives[i].func;
    1.69 +		pEntry->replacement.owner = pOwner;
    1.70 +		pOwner->AddReplacedNative(pEntry);
    1.71 +	}
    1.72 +}
    1.73 +
    1.74 +NativeEntry *ShareSystem::FindNative(const char *name)
    1.75 +{
    1.76 +	NativeEntry **ppEntry;
    1.77 +
    1.78 +	if ((ppEntry = m_NtvCache.retrieve(name)) == NULL)
    1.79 +	{
    1.80 +		return NULL;
    1.81 +	}
    1.82 +
    1.83 +	return *ppEntry;
    1.84 +}
    1.85 +
    1.86 +void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
    1.87 +{
    1.88 +	NativeEntry *pEntry;
    1.89 +	sp_native_t *native;
    1.90 +	uint32_t i, native_count;
    1.91 +	IPluginContext *pContext;
    1.92 +
    1.93 +	pContext = pPlugin->GetBaseContext();
    1.94 +
    1.95 +	/* Generate a new serial ID, mark our dependencies with it. */
    1.96 +	g_mark_serial++;
    1.97 +	pPlugin->PropogateMarkSerial(g_mark_serial);
    1.98 +
    1.99 +	native_count = pContext->GetNativesNum();
   1.100 +	for (i = 0; i < native_count; i++)
   1.101 +	{
   1.102 +		if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
   1.103 +		{
   1.104 +			continue;
   1.105 +		}
   1.106 +
   1.107 +		/* If we're bound, check if there is a replacement available.  
   1.108 +		 * If not, this native is totally finalized.
   1.109 +		 */
   1.110 +		if (native->status == SP_NATIVE_BOUND)
   1.111 +		{
   1.112 +			pEntry = (NativeEntry *)native->user;
   1.113 +			assert(pEntry != NULL);
   1.114 +			if (pEntry->replacement.owner == NULL
   1.115 +				|| (pEntry->replacement.owner != NULL 
   1.116 +				&&  pEntry->replacement.func == native->pfn))
   1.117 +			{
   1.118 +				continue;
   1.119 +			}
   1.120 +		}
   1.121 +		/* Otherwise, the native must be in our cache. */
   1.122 +		else if ((pEntry = FindNative(native->name)) == NULL)
   1.123 +		{
   1.124 +			continue;
   1.125 +		}
   1.126 +
   1.127 +		if (bCoreOnly && pEntry->owner != g_pCoreNatives)
   1.128 +		{
   1.129 +			continue;
   1.130 +		}
   1.131 +
   1.132 +		BindNativeToPlugin(pPlugin, native, i, pEntry);
   1.133 +	}
   1.134 +}
   1.135 +
   1.136 +void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
   1.137 +{
   1.138 +	uint32_t i;
   1.139 +	sp_native_t *native;
   1.140 +	IPluginContext *pContext;
   1.141 +
   1.142 +	pContext = pPlugin->GetBaseContext();
   1.143 +
   1.144 +	if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE)
   1.145 +	{
   1.146 +		return;
   1.147 +	}
   1.148 +	if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
   1.149 +	{
   1.150 +		return;
   1.151 +	}
   1.152 +
   1.153 +	if (native->status == SP_NATIVE_BOUND)
   1.154 +	{
   1.155 +		return;
   1.156 +	}
   1.157 +
   1.158 +	BindNativeToPlugin(pPlugin, native, i, pEntry);
   1.159  }
   1.160 +
   1.161 +void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, 
   1.162 +									 sp_native_t *native,
   1.163 +									 uint32_t index,
   1.164 +									 NativeEntry *pEntry)
   1.165 +{
   1.166 +	/* Mark as bound... we do the rest next. */
   1.167 +	native->status = SP_NATIVE_BOUND;
   1.168 +	native->user = pEntry;
   1.169 +
   1.170 +	/* See if a replacement is available. */
   1.171 +	if (pEntry->replacement.owner != NULL)
   1.172 +	{
   1.173 +		/* Perform a replacement bind. */
   1.174 +		native->pfn = pEntry->replacement.func;
   1.175 +		pEntry->replacement.owner->AddWeakRef(WeakNative(pPlugin, index, pEntry));
   1.176 +	}
   1.177 +	else
   1.178 +	{
   1.179 +		/* Perform a normal bind. */
   1.180 +		native->pfn = pEntry->func;
   1.181 +
   1.182 +		/* We don't bother with dependency crap if the owner is Core. */
   1.183 +		if (pEntry->owner != g_pCoreNatives)
   1.184 +		{
   1.185 +			/* The native is optional, this is a special case */
   1.186 +			if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
   1.187 +			{
   1.188 +				pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
   1.189 +			}
   1.190 +			/* Otherwise, we're a strong dependent and not a weak one */
   1.191 +			else
   1.192 +			{
   1.193 +				/* See if this has already been marked as a dependent.
   1.194 +				* If it has, it means this relationship has already occurred, 
   1.195 +				* and there is no reason to do it again.
   1.196 +				*/
   1.197 +				if (pEntry->owner != pPlugin 
   1.198 +					&& pEntry->owner->GetMarkSerial() != g_mark_serial)
   1.199 +				{
   1.200 +					/* This has not been marked as a dependency yet */
   1.201 +					//pPlugin->AddDependency(pEntry->owner);
   1.202 +					pEntry->owner->AddDependent(pPlugin);
   1.203 +					pEntry->owner->SetMarkSerial(g_mark_serial);
   1.204 +				}
   1.205 +			}
   1.206 +		}
   1.207 +	}
   1.208 +}
   1.209 +
   1.210 +NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
   1.211 +{
   1.212 +	NativeEntry *pEntry;
   1.213 +
   1.214 +	if ((pEntry = FindNative(ntv->name)) == NULL)
   1.215 +	{
   1.216 +		pEntry = new NativeEntry;
   1.217 +
   1.218 +		pEntry->owner = pOwner;
   1.219 +		pEntry->name = ntv->name;
   1.220 +		pEntry->func = ntv->func;
   1.221 +		pEntry->replacement.func = NULL;
   1.222 +		pEntry->replacement.owner = NULL;
   1.223 +		pEntry->fake = NULL;
   1.224 +
   1.225 +		m_NtvCache.insert(ntv->name, pEntry);
   1.226 +
   1.227 +		return pEntry;
   1.228 +	}
   1.229 +
   1.230 +	if (pEntry->owner != NULL)
   1.231 +	{
   1.232 +		return NULL;
   1.233 +	}
   1.234 +
   1.235 +	pEntry->owner = pOwner;
   1.236 +	pEntry->func = ntv->func;
   1.237 +	pEntry->name = ntv->name;
   1.238 +	pEntry->func = NULL;
   1.239 +
   1.240 +	return pEntry;
   1.241 +}
   1.242 +
   1.243 +void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
   1.244 +{
   1.245 +	NativeEntry *pEntry;
   1.246 +
   1.247 +	if ((pEntry = FindNative(name)) == NULL)
   1.248 +	{
   1.249 +		return;
   1.250 +	}
   1.251 +
   1.252 +	if (pEntry->owner != pOwner)
   1.253 +	{
   1.254 +		return;
   1.255 +	}
   1.256 +
   1.257 +	pEntry->func = NULL;
   1.258 +	pEntry->name = NULL;
   1.259 +	pEntry->owner = NULL;
   1.260 +	pEntry->replacement.func = NULL;
   1.261 +	pEntry->replacement.owner = NULL;
   1.262 +}
   1.263 +
   1.264 +NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
   1.265 +{
   1.266 +	FakeNative *pFake;
   1.267 +	NativeEntry *pEntry;
   1.268 +	SPVM_NATIVE_FUNC gate;
   1.269 +
   1.270 +	if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
   1.271 +	{
   1.272 +		return NULL;
   1.273 +	}
   1.274 +
   1.275 +	pFake = new FakeNative;
   1.276 +
   1.277 +	if ((gate = g_pVM->CreateFakeNative(func, pFake)) == NULL)
   1.278 +	{
   1.279 +		delete pFake;
   1.280 +		return NULL;
   1.281 +	}
   1.282 +
   1.283 +	if (pEntry == NULL)
   1.284 +	{
   1.285 +		pEntry = new NativeEntry;
   1.286 +		m_NtvCache.insert(name, pEntry);
   1.287 +	}
   1.288 +
   1.289 +	pFake->call = pFunc;
   1.290 +	pFake->ctx = pFunc->GetParentContext();
   1.291 +	strncopy(pFake->name, name, sizeof(pFake->name));
   1.292 +	
   1.293 +	pEntry->fake = pFake;
   1.294 +	pEntry->func = gate;
   1.295 +	pEntry->name = pFake->name;
   1.296 +	pEntry->owner = g_PluginSys.GetPluginByCtx(pFake->ctx->GetContext());
   1.297 +	pEntry->replacement.func = NULL;
   1.298 +	pEntry->replacement.owner = NULL;
   1.299 +
   1.300 +	return pEntry;
   1.301 +}