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 +}