From 8a8e6ef5940fc420451609cca0d9cf6d31bb366f Mon Sep 17 00:00:00 2001 From: Borja Ferrer Date: Thu, 12 Jul 2007 02:57:43 +0000 Subject: [PATCH] added experimental optional natives (part 1) --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401095 --- core/smn_core.cpp | 52 ++++++++++++++++++++++++--------- core/systems/ExtensionSys.cpp | 10 +++++-- core/systems/PluginSys.cpp | 15 ++++++++-- core/systems/PluginSys.h | 5 ++++ public/sourcepawn/sp_vm_types.h | 3 ++ sourcepawn/jit/x86/jit_x86.cpp | 1 + 6 files changed, 68 insertions(+), 18 deletions(-) diff --git a/core/smn_core.cpp b/core/smn_core.cpp index 8548ab66..e8484243 100644 --- a/core/smn_core.cpp +++ b/core/smn_core.cpp @@ -330,20 +330,44 @@ static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *params) +{ + char *name; + uint32_t idx; + sp_context_t *ctx = pContext->GetContext(); + CPlugin *pl = g_PluginSys.GetPluginByCtx(ctx); + + if (!pl->IsInAskPluginLoad()) + { + return pContext->ThrowNativeError("Calling MarkNativeAsOptional outside AskPluginLoad is not allowed"); + } + + pContext->LocalToString(params[1], &name); + if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE) + { + return pContext->ThrowNativeError("Unable to find native \"%s\"", name); + } + + ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL; + + return 1; +} + REGISTER_NATIVES(coreNatives) { - {"AutoExecConfig", AutoExecConfig}, - {"GetPluginFilename", GetPluginFilename}, - {"GetPluginInfo", GetPluginInfo}, - {"GetPluginIterator", GetPluginIterator}, - {"GetPluginStatus", GetPluginStatus}, - {"GetSysTickCount", GetSysTickCount}, - {"GetTime", GetTime}, - {"IsPluginDebugging", IsPluginDebugging}, - {"MorePlugins", MorePlugins}, - {"ReadPlugin", ReadPlugin}, - {"ThrowError", ThrowError}, - {"SetFailState", SetFailState}, - {"FormatTime", FormatTime}, - {NULL, NULL}, + {"AutoExecConfig", AutoExecConfig}, + {"GetPluginFilename", GetPluginFilename}, + {"GetPluginInfo", GetPluginInfo}, + {"GetPluginIterator", GetPluginIterator}, + {"GetPluginStatus", GetPluginStatus}, + {"GetSysTickCount", GetSysTickCount}, + {"GetTime", GetTime}, + {"IsPluginDebugging", IsPluginDebugging}, + {"MorePlugins", MorePlugins}, + {"ReadPlugin", ReadPlugin}, + {"ThrowError", ThrowError}, + {"SetFailState", SetFailState}, + {"FormatTime", FormatTime}, + {"MarkNativeAsOptional", MarkNativeAsOptional}, + {NULL, NULL}, }; diff --git a/core/systems/ExtensionSys.cpp b/core/systems/ExtensionSys.cpp index 50b374fc..1dab719e 100644 --- a/core/systems/ExtensionSys.cpp +++ b/core/systems/ExtensionSys.cpp @@ -529,13 +529,19 @@ void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin) n_iter++) { natives = (*n_iter); + uint32_t idx; unsigned int i=0; while (natives[i].func != NULL && natives[i].name != NULL) { - if (pContext->BindNative(&natives[i++]) == SP_ERROR_NONE) + if (pContext->BindNative(&natives[i]) == SP_ERROR_NONE) { - set = true; + pContext->FindNativeByName(natives[i].name, &idx); + if (!(pContext->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL)) + { + set = true; + } } + i++; } } if (set && (pExt->m_Plugins.find(pPlugin) == pExt->m_Plugins.end())) diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index b5ed2383..7227a73d 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -357,15 +357,19 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) return true; } + m_IsInAskPluginLoad = true; pFunction->PushCell(m_handle); pFunction->PushCell(g_PluginSys.IsLateLoadTime() ? 1 : 0); pFunction->PushStringEx(error, maxlength, 0, SM_PARAM_COPYBACK); pFunction->PushCell(maxlength); if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE) { + m_IsInAskPluginLoad = false; return false; } + m_IsInAskPluginLoad = false; + if (!result || m_status != Plugin_Loaded) { return false; @@ -1098,7 +1102,8 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng break; } if (native->status == SP_NATIVE_UNBOUND - && native->name[0] != '@') + && native->name[0] != '@' + && !(native->flags & SP_NTVFLAG_OPTIONAL)) { if (error) { @@ -1176,7 +1181,7 @@ void CPluginManager::TryRefreshNatives(CPlugin *pPlugin) { break; } - if (native->status == SP_NATIVE_UNBOUND) + if (native->status == SP_NATIVE_UNBOUND && !(native->flags & SP_NTVFLAG_OPTIONAL)) { pPlugin->SetErrorState(Plugin_Error, "Native not found: %s", native->name); return; @@ -1213,6 +1218,12 @@ void CPluginManager::AddFakeNativesToPlugin(CPlugin *pPlugin) native.func = pNative->func; if (pContext->BindNative(&native) == SP_ERROR_NONE) { + uint32_t idx; + pContext->FindNativeByName(native.name, &idx); + if (!(pPlugin->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL)) + { + continue; + } /* Add us as a dependency, but we're careful not to do this circularly! */ if (pNative->ctx != pContext) { diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index 8e9610fe..e9abf70c 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -234,6 +234,10 @@ public: void AddConfig(bool autoCreate, const char *cfg, const char *folder); unsigned int GetConfigCount(); AutoConfig *GetConfig(unsigned int i); + inline bool IsInAskPluginLoad() + { + return m_IsInAskPluginLoad; + } protected: void UpdateInfo(); void SetTimeStamp(time_t t); @@ -258,6 +262,7 @@ private: Trie *m_pProps; bool m_FakeNativesMissing; CVector m_configs; + bool m_IsInAskPluginLoad; }; class CPluginManager : diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h index 4c3e1be5..c3ce9dce 100644 --- a/public/sourcepawn/sp_vm_types.h +++ b/public/sourcepawn/sp_vm_types.h @@ -171,6 +171,8 @@ typedef struct sp_pubvar_s #define SP_NATIVE_UNBOUND (0) /**< Native is undefined */ #define SP_NATIVE_BOUND (1) /**< Native is bound */ +#define SP_NTVFLAG_OPTIONAL (1<<0) /**< Native is optional */ + /** * @brief Native lookup table, by default names point back to the sp_plugin_infotab_t structure. */ @@ -179,6 +181,7 @@ typedef struct sp_native_s SPVM_NATIVE_FUNC pfn; /**< Function pointer */ const char * name; /**< Name of function */ uint32_t status; /**< Status flags */ + uint32_t flags; /**< Native flags */ } sp_native_t; /** diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index e5328a3f..7f85a3f7 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -2445,6 +2445,7 @@ jit_rewind: ctx->natives[iter].name = strbase + plugin->info.natives[iter].name; ctx->natives[iter].pfn = &InvalidNative; ctx->natives[iter].status = SP_NATIVE_UNBOUND; + ctx->natives[iter].flags = 0; } }