Added set_error_filter()

This commit is contained in:
David Anderson 2005-09-09 23:13:34 +00:00
parent de65e65854
commit 0dc2ba85e8
3 changed files with 151 additions and 30 deletions

View File

@ -830,6 +830,27 @@ const char *Debugger::_GetFilename()
return m_FileName.c_str(); return m_FileName.c_str();
} }
void Debugger::GenericMessage(AMX *amx, int err)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
const char *filename = "";
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
if (a)
filename = (*a).getName();
size_t len = strlen(filename);
for (size_t i=len-1; i>=0; i--)
{
if (filename[i] == '/' || filename[i] == '\\' && i != len - 1)
{
filename = &(filename[i+1]);
break;
}
}
AMXXLOG_Log("[AMXX] Run time error %d (plugin \"%s\") - debug not enabled!", err, filename);
}
Debugger::~Debugger() Debugger::~Debugger()
{ {
Clear(); Clear();
@ -871,7 +892,98 @@ int Handler::SetNativeFilter(const char *function)
return error; return error;
} }
void Handler::SetErrorMsg(const char *msg)
{
if (!msg)
m_MsgCache.clear();
else
m_MsgCache.assign(msg);
}
const char *Handler::GetLastMsg()
{
if (m_MsgCache.size() < 1)
return NULL;
return m_MsgCache.c_str();
}
int Handler::HandleError(const char *msg) int Handler::HandleError(const char *msg)
{ {
return 0; if (m_iErrFunc <= 0)
return 0;
m_Handling = true;
Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER];
int error = m_pAmx->error;
if (pDebugger)
pDebugger->BeginExec();
SetErrorMsg(msg);
cell hea_addr, *phys_addr, result;
amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0);
amx_Push(m_pAmx, pDebugger ? 1 : 0);
amx_Push(m_pAmx, error);
int err = amx_Exec(m_pAmx, &result, m_iErrFunc);
if (err != AMX_ERR_NONE)
{
//handle this manually.
if (pDebugger)
{
pDebugger->SetTracedError(err);
pDebugger->DisplayTrace(msg);
} else {
if (GetLastMsg())
AMXXLOG_Log("%s", GetLastMsg());
Debugger::GenericMessage(m_pAmx, err);
}
AMXXLOG_Log("[AMXX] NOTE: Runtime failures in an error filter are not good!");
}
if (pDebugger)
pDebugger->EndExec();
amx_Release(m_pAmx, hea_addr);
m_Handling = false;
if (err != AMX_ERR_NONE || !result)
return 0;
return result;
} }
static cell AMX_NATIVE_CALL set_error_filter(AMX *amx, cell *params)
{
int len;
char *function = get_amxstring(amx, params[1], 0, len);
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (!pHandler)
{
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Log("[AMXX] Plugin not initialized correctly.");
return 0;
}
int err = pHandler->SetErrorHandler(function);
if (err != AMX_ERR_NONE)
{
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Log("[AMXX] Function not found: %s", function);
return 0;
}
return 1;
}
AMX_NATIVE_INFO g_DebugNatives[] = {
{"set_error_filter", set_error_filter},
{NULL, NULL},
};

View File

@ -123,6 +123,7 @@ public:
public: public:
//generic static opcode breaker //generic static opcode breaker
static int AMXAPI DebugHook(AMX *amx); static int AMXAPI DebugHook(AMX *amx);
static void GenericMessage(AMX *amx, int error);
private: private:
void _CacheAmxOpcodeList(); void _CacheAmxOpcodeList();
int _GetOpcodeFromCip(cell cip, cell *&addr); int _GetOpcodeFromCip(cell cip, cell *&addr);
@ -146,8 +147,9 @@ typedef Debugger::Tracer::trace_info trace_info_t;
class Handler class Handler
{ {
public: public:
Handler(AMX *pAmx) : m_pAmx(pAmx), Handler(AMX *pAmx) : m_pAmx(pAmx),
m_iErrFunc(-1), m_iModFunc(-1), m_iNatFunc(-1) m_iErrFunc(-1), m_iModFunc(-1), m_iNatFunc(-1),
m_Handling(false)
{ }; { };
~Handler() { }; ~Handler() { };
public: public:
@ -158,11 +160,19 @@ public:
int HandleError(const char *msg); int HandleError(const char *msg);
int HandleNative(const char *native); int HandleNative(const char *native);
int HandleModule(const char *module); int HandleModule(const char *module);
public:
bool IsHandling() const { return m_Handling; }
void SetErrorMsg(const char *msg);
const char *GetLastMsg();
public: public:
AMX *m_pAmx; AMX *m_pAmx;
int m_iErrFunc; int m_iErrFunc;
int m_iModFunc; int m_iModFunc;
int m_iNatFunc; int m_iNatFunc;
bool m_Handling;
String m_MsgCache;
}; };
extern AMX_NATIVE_INFO g_DebugNatives[];
#endif //_INCLUDE_DEBUGGER_H_ #endif //_INCLUDE_DEBUGGER_H_

View File

@ -209,6 +209,9 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
return (amx->error = AMX_ERR_INIT); return (amx->error = AMX_ERR_INIT);
} }
Handler *pHandler = new Handler(amx);
amx->userdata[UD_HANDLER] = (void *)pHandler;
if (will_be_debugged) if (will_be_debugged)
{ {
amx->flags |= AMX_FLAG_DEBUG; amx->flags |= AMX_FLAG_DEBUG;
@ -409,17 +412,19 @@ int set_amxnatives(AMX* amx,char error[128])
amx_Register(amx, vault_Natives, -1); amx_Register(amx, vault_Natives, -1);
amx_Register(amx, g_NewMenuNatives, -1); amx_Register(amx, g_NewMenuNatives, -1);
amx_Register(amx, g_NativeNatives, -1); amx_Register(amx, g_NativeNatives, -1);
amx_Register(amx, g_DebugNatives, -1);
//we're not actually gonna check these here anymore //we're not actually gonna check these here anymore
amx->flags |= AMX_FLAG_PRENIT; amx->flags |= AMX_FLAG_PRENIT;
int idx; int idx, err;
cell retval; cell retval;
if (amx_FindPublic(amx, "plugin_natives", &idx)==AMX_ERR_NONE) if (amx_FindPublic(amx, "plugin_natives", &idx)==AMX_ERR_NONE)
{ {
if (amx_Exec(amx, &retval, idx)!=AMX_ERR_NONE) if ( (err=amx_Exec(amx, &retval, idx))!=AMX_ERR_NONE )
{ {
//someday clear libraries that this added Debugger::GenericMessage(amx, err);
AMXXLOG_Log("An error occurred in plugins_native. This is dangerous!");
} }
} }
@ -434,6 +439,9 @@ int unload_amxscript(AMX* amx, void** program)
Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER]; Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
if (pDebugger) if (pDebugger)
delete pDebugger; delete pDebugger;
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (pHandler)
delete pHandler;
CList<CScript,AMX*>::iterator a = g_loadedscripts.find( amx ); CList<CScript,AMX*>::iterator a = g_loadedscripts.find( amx );
if ( a ) a.remove(); if ( a ) a.remove();
char *prg = (char *)*program; char *prg = (char *)*program;
@ -1256,11 +1264,6 @@ float MNF_GetPlayerHealth(int id)
return (GET_PLAYER_POINTER_I(id)->pEdict->v.health); return (GET_PLAYER_POINTER_I(id)->pEdict->v.health);
} }
void MNF_HiddenStuff()
{
// :TODO:
}
cell MNF_RealToCell(REAL x) cell MNF_RealToCell(REAL x)
{ {
return *(cell*)&x; return *(cell*)&x;
@ -1305,36 +1308,34 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER]; Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (pHandler) if (pHandler)
{ {
//give the user a first-chance at blocking the error from displaying if (pHandler->IsHandling())
if (pHandler->HandleError(msg_buffer) != 0) {
if (fmt != NULL)
pHandler->SetErrorMsg(msg_buffer);
return; return;
}
//give the user a first-chance at blocking the error from displaying
if (pHandler->HandleError(fmt ? msg_buffer : NULL) != 0)
{
amx->error = -1;
return;
}
} }
if (!pDebugger) if (!pDebugger)
{ {
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx); if (fmt)
const char *filename = "";
if (pl)
{
filename = pl->getName();
} else {
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
if (a)
filename = (*a).getName();
}
if (fmt != NULL)
AMXXLOG_Log("%s", msg_buffer); AMXXLOG_Log("%s", msg_buffer);
//give the module's error first. makes the report look nicer. Debugger::GenericMessage(amx, err);
AMXXLOG_Log("[AMXX] Run time error %d (plugin \"%s\") - debug not enabled!", err, filename);
AMXXLOG_Log("[AMXX] To enable debug mode, add \"debug\" after the plugin name in plugins.ini (without quotes)."); AMXXLOG_Log("[AMXX] To enable debug mode, add \"debug\" after the plugin name in plugins.ini (without quotes).");
//destroy original error code so the original is not displayed again //destroy original error code so the original is not displayed again
amx->error = -1;
} else { } else {
pDebugger->SetTracedError(err); pDebugger->SetTracedError(err);
//we can display error now //we can display error now
pDebugger->DisplayTrace(fmt ? msg_buffer : NULL); pDebugger->DisplayTrace(fmt ? msg_buffer : NULL);
} }
amx->error = -1;
} }
void MNF_MergeDefinitionFile(const char *file) void MNF_MergeDefinitionFile(const char *file)
@ -1516,8 +1517,6 @@ void Module_CacheFunctions()
REGISTER_FUNC("Deallocator", MNF_Deallocator) REGISTER_FUNC("Deallocator", MNF_Deallocator)
REGISTER_FUNC("Reallocator", MNF_Reallocator) REGISTER_FUNC("Reallocator", MNF_Reallocator)
#endif // MEMORY_TEST #endif // MEMORY_TEST
REGISTER_FUNC("Haha_HiddenStuff", MNF_HiddenStuff)
} }
void *Module_ReqFnptr(const char *funcName) void *Module_ReqFnptr(const char *funcName)