diff --git a/amxmodx/CEvent.cpp b/amxmodx/CEvent.cpp index 82d02de3..769ae38e 100755 --- a/amxmodx/CEvent.cpp +++ b/amxmodx/CEvent.cpp @@ -396,40 +396,21 @@ void EventsMngr::parseValue(const char *sz) void EventsMngr::executeEvents() { - int err; - if (!m_ParseFun) { return; } -#ifdef ENABLEEXEPTIONS - try + for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter) { -#endif // #ifdef ENABLEEXEPTIONS - for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter) + if ( (*iter).m_Done ) { - if ( (*iter).m_Done ) - { - (*iter).m_Done = false; - continue; - } - - (*iter).m_Stamp = (float)*m_Timer; - - if ((err = amx_Exec((*iter).m_Plugin->getAMX(), NULL, (*iter).m_Func, 1, m_ParseVault ? m_ParseVault[0].iValue : 0)) != AMX_ERR_NONE) - { - LogError((*iter).m_Plugin->getAMX(), err, ""); - } + (*iter).m_Done = false; + continue; } - -#ifdef ENABLEEXEPTIONS + (*iter).m_Stamp = (float)*m_Timer; + executeForwards((*iter).m_Func, m_ParseVault ? m_ParseVault[0].iValue : 0); } - catch( ... ) - { - AMXXLOG_Log( "[AMXX] fatal error at event execution"); - } -#endif // #ifdef ENABLEEXEPTIONS m_CurrentMsgType = -1; m_ParseFun = NULL; diff --git a/amxmodx/CForward.cpp b/amxmodx/CForward.cpp index 4bbbc66b..6641d4ff 100755 --- a/amxmodx/CForward.cpp +++ b/amxmodx/CForward.cpp @@ -71,7 +71,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) if (iter->pPlugin->isExecutable(iter->func)) { // handle strings & arrays - int i; + int i, ax=0; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) @@ -80,7 +80,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast(params[i]))+1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); - amx_SetString(tmp, (const char *)(params[i]), 0, 0); + amx_SetStringOld(tmp, (const char *)(params[i]), 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) @@ -105,9 +105,14 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) realParams[i] = params[i]; } } + //Push the parameters in reverse order. Weird, unfriendly part of Small 3.0! + for (i=m_NumParams-1; i>=0; i--) + { + amx_Push(iter->pPlugin->getAMX(), realParams[i]); + } // exec cell retVal; - int err = amx_Execv(iter->pPlugin->getAMX(), &retVal, iter->func, m_NumParams, realParams); + int err = amx_Exec(iter->pPlugin->getAMX(), &retVal, iter->func); // log runtime error, if any if (err != AMX_ERR_NONE) LogError(iter->pPlugin->getAMX(), err, ""); @@ -122,7 +127,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back - amx_GetString(reinterpret_cast(params[i]), physAddrs[i], 0); + amx_GetStringOld(reinterpret_cast(params[i]), physAddrs[i], 0); amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) @@ -216,7 +221,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) amx_Allot(m_Amx, (m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast(params[i]))+1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); - amx_SetString(tmp, (const char *)(params[i]), 0, 0); + amx_SetStringOld(tmp, (const char *)(params[i]), 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) @@ -241,10 +246,11 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) realParams[i] = params[i]; } } - + for (i=m_NumParams-1; i>=0; i--) + amx_Push(m_Amx, realParams[i]); // exec cell retVal; - int err = amx_Execv(m_Amx, &retVal, m_Func, m_NumParams, realParams); + int err = amx_Exec(m_Amx, &retVal, m_Func); // log runtime error, if any if (err != AMX_ERR_NONE) @@ -260,7 +266,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back - amx_GetString(reinterpret_cast(params[i]), physAddrs[i], 0); + amx_GetStringOld(reinterpret_cast(params[i]), physAddrs[i], 0); amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) diff --git a/amxmodx/CLogEvent.cpp b/amxmodx/CLogEvent.cpp index c6e07692..85d606f7 100755 --- a/amxmodx/CLogEvent.cpp +++ b/amxmodx/CLogEvent.cpp @@ -151,7 +151,6 @@ LogEventsMngr::CLogEvent* LogEventsMngr::registerLogEvent( CPluginMngr::CPlugin* void LogEventsMngr::executeLogEvents() { - int err; bool valid; for(CLogEvent* a = logevents[ logArgc ]; a ; a = a->next) { @@ -171,8 +170,7 @@ void LogEventsMngr::executeLogEvents() if (valid) { - if ((err = amx_Exec(a->plugin->getAMX(), NULL , a->func , 0)) != AMX_ERR_NONE) - LogError(a->plugin->getAMX(), err, ""); + executeForwards(a->func); } } } diff --git a/amxmodx/CMenu.cpp b/amxmodx/CMenu.cpp index 72ccac58..7c346284 100755 --- a/amxmodx/CMenu.cpp +++ b/amxmodx/CMenu.cpp @@ -51,7 +51,7 @@ MenuMngr::~MenuMngr() int MenuMngr::findMenuId(const char* name, AMX* amx) { for( MenuIdEle* b = headid; b ; b = b->next) { - if ( (!b->amx || amx == b->amx) && strstr(name,b->name.c_str()) ) + if ( (!amx || !b->amx || amx == b->amx) && strstr(name,b->name.c_str()) ) return b->id; } return 0; diff --git a/amxmodx/CModule.cpp b/amxmodx/CModule.cpp index e6a471f2..ce551223 100755 --- a/amxmodx/CModule.cpp +++ b/amxmodx/CModule.cpp @@ -35,11 +35,6 @@ #define FAR #endif -// Old -typedef int (FAR *QUERYMOD)(module_info_s**); -typedef int (FAR *ATTACHMOD)(pfnamx_engine_g*,pfnmodule_engine_g*); -typedef int (FAR *DETACHMOD)(void); - // New typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/); typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/); @@ -47,81 +42,6 @@ typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/); typedef int (FAR *DETACHMOD_NEW)(void); typedef void (FAR *PLUGINSLOADED_NEW)(void); -// Old -// These functions are needed since Small Abstract Machine 2.5.0 -int wamx_FindPublic(AMX *amx, char *name, int *index) -{ return amx_FindPublic(amx, name, index); } - -int wamx_FindPubVar(AMX *amx, char *varname, cell *amx_addr) -{ return amx_FindPubVar(amx, varname, amx_addr); } - -int wamx_GetString(char *dest, cell *source) -{ return amx_GetString(dest, source, 0); } - -AMX_NATIVE_INFO *wamx_NativeInfo(char *name, AMX_NATIVE func) -{ return amx_NativeInfo(name, func); } - -int wamx_SetString(cell *dest, char *source, int pack) -{ return amx_SetString(dest, source, pack, 0); } - -pfnamx_engine_g engAmxFunc = { - amx_Align16, - amx_Align32, - amx_Allot, - amx_Callback, - amx_Clone, - amx_Debug, - amx_Exec, - amx_Execv, - wamx_FindPublic, - wamx_FindPubVar, - amx_FindTagId, - amx_Flags, - amx_GetAddr, - amx_GetPublic, - amx_GetPubVar, - wamx_GetString, - amx_GetTag, - amx_GetUserData, - amx_Init, - amx_InitJIT, - amx_MemInfo, - amx_NameLength, - wamx_NativeInfo, - amx_NumPublics, - amx_NumPubVars, - amx_NumTags, - amx_RaiseError, - amx_Register, - amx_Release, - amx_SetCallback, - amx_SetDebugHook, - wamx_SetString, - amx_SetUserData, - amx_StrLen, -}; - -pfnmodule_engine_g engModuleFunc = { - add_amxnatives, - build_pathname, - copy_amxmemory, - format_amxstring, - get_amxaddr, - get_amxscript, - get_amxscriptname, - get_amxstring, - get_modname, - load_amxscript, - print_srvconsole, - report_error, - set_amxnatives, - set_amxstring, - amxstring_len, - unload_amxscript, - alloc_amxmemory, - free_amxmemory, -}; - // ***************************************************** // class CModule // ***************************************************** @@ -150,8 +70,6 @@ void CModule::clear(bool clearFilename) if (clearFilename) m_Filename.assign("unknown"); - // old - m_InfoOld = NULL; // new m_Amxx = false; m_InfoNew.author = "unknown"; @@ -220,17 +138,11 @@ bool CModule::attachModule() m_Status = MODULE_BADLOAD; return false; } + } else { + m_Status = MODULE_BADLOAD; } - else - { - // old - ATTACHMOD AttachFunc = (ATTACHMOD)DLPROC(m_Handle, "AMX_Attach"); - if (AttachFunc) - (*AttachFunc)(&engAmxFunc,&engModuleFunc); - m_Status = MODULE_LOADED; - return true; - } + return false; } bool CModule::queryModule() @@ -292,44 +204,9 @@ bool CModule::queryModule() } else { - // old interface not 64 bit compatible -#if SMALL_CELL_SIZE == 64 - m_Status = MODULE_NOT64BIT; + m_Status = MODULE_NOQUERY; + m_Amxx = false; return false; -#else - // Try old interface - QUERYMOD queryFunc_Old = (QUERYMOD)DLPROC(m_Handle,"AMX_Query"); // check what version - if (!queryFunc_Old) - { - m_Status = MODULE_NOQUERY; - return false; - } - - (*queryFunc_Old)(&m_InfoOld); - - if (!m_InfoOld) - { - m_Status = MODULE_NOINFO; - return false; - } - - if (m_InfoOld->ivers != AMX_INTERFACE_VERSION) - { - m_Status = MODULE_OLD; - return false; - } - - // Check for attach - if (!DLPROC(m_Handle, "AMX_Attach")) - { - m_Status = MODULE_NOATTACH; - return false; - } - - m_InfoOld->serial = (long int)this; - m_Status = MODULE_QUERY; - return true; -#endif } } @@ -350,12 +227,6 @@ bool CModule::detachModule() g_ModuleCallReason = ModuleCall_NotCalled; } } - else - { - DETACHMOD detachFunc_Old = (DETACHMOD)DLPROC(m_Handle, "AMX_Detach"); - if (detachFunc_Old) - (*detachFunc_Old)(); - } #ifndef FAKEMETA if (IsMetamod()) { diff --git a/amxmodx/CModule.h b/amxmodx/CModule.h index c7b7f915..848455fe 100755 --- a/amxmodx/CModule.h +++ b/amxmodx/CModule.h @@ -66,14 +66,13 @@ struct amxx_module_info_s #define AMXX_PARAM 2 /* Invalid parameter */ #define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */ -#define AMXX_INTERFACE_VERSION 2 +#define AMXX_INTERFACE_VERSION 3 class CModule { String m_Filename; // Filename bool m_Metamod; // Using metamod? bool m_Amxx; // Using new module interface? - module_info_s* m_InfoOld; // module info (old module interface) amxx_module_info_s m_InfoNew; // module info (new module interface) DLHANDLE m_Handle; // handle MODULE_STATUS m_Status; // status @@ -93,14 +92,13 @@ public: #endif const char* getStatus() const; inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); } - inline const char* getAuthor() const { return m_Amxx ? (m_InfoNew.author) : (m_InfoOld ? m_InfoOld->author : "unknown"); } - inline const char* getVersion() const { return m_Amxx ? (m_InfoNew.version) : (m_InfoOld ? m_InfoOld->version : "unknown"); } - inline const char* getName() const { return m_Amxx ? (m_InfoNew.name) : (m_InfoOld ? m_InfoOld->name : "unknown"); } - inline module_info_s* getInfo() const { return m_InfoOld; } // old + inline const char* getAuthor() const { return m_InfoNew.author; } + inline const char* getVersion() const { return m_InfoNew.version; } + inline const char* getName() const { return m_InfoNew.name; } inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new inline int getStatusValue() { return m_Status; } inline bool operator==( const char* fname ) { return !strcmp( m_Filename.c_str() , fname ); } - inline bool isReloadable() { return m_Amxx ? ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)) : ( (m_Status==MODULE_LOADED) && (m_InfoOld->type==RELOAD_MODULE)); } + inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); } inline bool isAmxx() const { return m_Amxx; } inline const char *getMissingFunc() const { return m_MissingFunc; } inline const char *getFilename() { return m_Filename.c_str(); } diff --git a/amxmodx/CPlugin.cpp b/amxmodx/CPlugin.cpp index f3c44048..b6c10710 100755 --- a/amxmodx/CPlugin.cpp +++ b/amxmodx/CPlugin.cpp @@ -172,38 +172,12 @@ CPluginMngr::CPlugin::CPlugin(int i, const char* p,const char* n, char* e, int d paused_fun = 0; next = 0; id = i; + m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause"); + m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause"); } CPluginMngr::CPlugin::~CPlugin( ) { - AMX_DBG *pDbg = (AMX_DBG *)amx.userdata[0]; - - if (pDbg) - { - if (pDbg->files) - { - for (int i=0; inumFiles; i++) - { - if (pDbg->files[i]) - { - free(pDbg->files[i]); - pDbg->files[i] = NULL; - } - } - free(pDbg->files); - } - AMX_TRACE *pTrace = pDbg->head; - AMX_TRACE *pNext = NULL; - while (pTrace) - { - pNext = pTrace->next; - free(pTrace); - pTrace = pNext; - } - free(pDbg); - amx.userdata[0] = NULL; - } - unload_amxscript( &amx, &code ); } @@ -232,16 +206,8 @@ void CPluginMngr::CPlugin::pausePlugin() if (isValid()) { // call plugin_pause if provided - int func; - cell retval; - if (amx_FindPublic(&amx, "plugin_pause", &func) == AMX_ERR_NONE) - { - if (isExecutable(func)) - { - - amx_Exec(&amx, &retval, func, 0); - } - } + if (m_PauseFwd != -1) + executeForwards(m_PauseFwd); setStatus(ps_paused); } @@ -256,14 +222,7 @@ void CPluginMngr::CPlugin::unpausePlugin() setStatus(ps_running); // call plugin_unpause if provided - int func; - cell retval; - if (amx_FindPublic(&amx, "plugin_unpause", &func) == AMX_ERR_NONE) - { - if (isExecutable(func)) - { - amx_Exec(&amx, &retval, func, 0); - } - } + if (m_UnpauseFwd != -1) + executeForwards(m_UnpauseFwd); } } diff --git a/amxmodx/CPlugin.h b/amxmodx/CPlugin.h index 252761d4..55efb3e2 100755 --- a/amxmodx/CPlugin.h +++ b/amxmodx/CPlugin.h @@ -64,6 +64,8 @@ public: String title; String author; String errorMsg; + int m_PauseFwd; + int m_UnpauseFwd; int paused_fun; int status; CPlugin* next; @@ -88,8 +90,8 @@ public: inline void setError( const char* n ) { errorMsg.assign(n); } inline bool isValid() const { return ((status != ps_bad_load) && (status != ps_locked)); } inline bool isPaused() const { return ( (status == ps_paused) || (status == ps_stopped)); } - inline bool isFunctionPaused( int id ) const { return (paused_fun & (1< class CVector return false; if (m_Data) { - memcpy(newData, m_Data, m_Size * sizeof(T)); + for (size_t i=0; i class CVector return false; if (m_Data) { - memcpy(newData, m_Data, (m_Size < size) ? (m_Size * sizeof(T)) : (size * sizeof(T))); + size_t end = (m_Size < size) ? (m_Size) : size; + for (size_t i=0; i(const CVector & other) { // copy data - m_Data = new T [other.m_Size]; - m_Size = other.m_Size; + m_Data = new T [other.m_CurrentUsedSize]; + m_Size = other.m_CurrentUsedSize; m_CurrentUsedSize = other.m_CurrentUsedSize; - memcpy(m_Data, other.m_Data, m_CurrentUsedSize * sizeof(T)); + for (size_t i=0; i() diff --git a/amxmodx/JIT/amxexecn.o b/amxmodx/JIT/amxexecn.o new file mode 100755 index 00000000..c0c6f00f Binary files /dev/null and b/amxmodx/JIT/amxexecn.o differ diff --git a/amxmodx/JIT/amxexecn.obj b/amxmodx/JIT/amxexecn.obj new file mode 100755 index 00000000..08d307a4 Binary files /dev/null and b/amxmodx/JIT/amxexecn.obj differ diff --git a/amxmodx/JIT/amxjitsn.o b/amxmodx/JIT/amxjitsn.o new file mode 100755 index 00000000..541585fb Binary files /dev/null and b/amxmodx/JIT/amxjitsn.o differ diff --git a/amxmodx/JIT/amxjitsn.obj b/amxmodx/JIT/amxjitsn.obj new file mode 100755 index 00000000..92fcd240 Binary files /dev/null and b/amxmodx/JIT/amxjitsn.obj differ diff --git a/amxmodx/JIT/jits.o b/amxmodx/JIT/jits.o deleted file mode 100755 index a781020a..00000000 Binary files a/amxmodx/JIT/jits.o and /dev/null differ diff --git a/amxmodx/JIT/jits.obj b/amxmodx/JIT/jits.obj deleted file mode 100755 index 372b7029..00000000 Binary files a/amxmodx/JIT/jits.obj and /dev/null differ diff --git a/amxmodx/amx.cpp b/amxmodx/amx.cpp index 18d57420..32271968 100755 --- a/amxmodx/amx.cpp +++ b/amxmodx/amx.cpp @@ -1,6 +1,6 @@ -/* Abstract Machine for the Small compiler +/* Pawn Abstract Machine (for the Pawn language) * - * Copyright (c) ITB CompuPhase, 1997-2004 + * Copyright (c) ITB CompuPhase, 1997-2005 * * This software is provided "as-is", without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -21,11 +21,11 @@ * Version: $Id$ */ -// not used #define AMX_NODYNALOAD +#define AMX_ANSIONLY -// bad bad workaround but we have to prevent a compiler crash :/ -#if (BUILD_PLATFORM== WINDOWS) && (BUILD_TYPE== RELEASE) && (BUILD_COMPILER== MSVC) && (SMALL_CELL_SIZE== 64) +#if BUILD_PLATFORM == WINDOWS && BUILD_TYPE == RELEASE && BUILD_COMPILER == MSVC && PAWN_CELL_SIZE == 64 + /* bad bad workaround but we have to prevent a compiler crash :/ */ #pragma optimize("g",off) #endif @@ -39,45 +39,31 @@ # endif #endif -#include -#include #include #include #include #include /* for wchar_t */ #include -#include +#include #include "osdefs.h" -#if defined LINUX +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ #include #if !defined AMX_NODYNALOAD #include #endif + #if defined JIT + #include + #include + #endif #endif -#if defined __LCC__ || defined __GNUC__ +#if defined __LCC__ #include /* for wcslen() */ #endif -#if (defined _Windows && !defined AMX_NODYNALOAD) || (defined JIT && !defined __linux__) +#include "amx.h" +#if (defined _Windows && !defined AMX_NODYNALOAD) || (defined JIT && __WIN32__) #include #endif -// this file does not include amxmodx.h, so we have to include the memory manager here -#ifdef MEMORY_TEST -#include "mmgr/mmgr.h" -#endif // MEMORY_TEST - -#include "amx.h" - -#ifdef JIT -# ifdef __WIN32__ -# include // DWORD, VirtualProtect, ... -# elif defined __linux__ -# include // mprotect, PROT_* -# include -# else - // :TODO: -# endif -#endif // JIT /* When one or more of the AMX_funcname macris are defined, we want * to compile only those functions. However, when none of these macros @@ -109,11 +95,11 @@ #endif #if !defined AMX_EXPLIT_FUNCTIONS /* no constant set, set them all */ - #define AMX_ALIGN /* amx_Align16() and amx_Align32() */ + #define AMX_ALIGN /* amx_Align16(), amx_Align32() and amx_Align64() */ #define AMX_ALLOT /* amx_Allot() and amx_Release() */ #define AMX_CLEANUP /* amx_Cleanup() */ #define AMX_CLONE /* amx_Clone() */ - #define AMX_EXEC /* amx_Exec() and amx_Execv() */ + #define AMX_EXEC /* amx_Exec() plus amx_Push(), amx_PushArray() and amx_PushString() */ #define AMX_FLAGS /* amx_Flags() */ #define AMX_GETADDR /* amx_GetAddr() */ #define AMX_INIT /* amx_Init() and amx_InitJIT() */ @@ -127,12 +113,15 @@ #define AMX_XXXNATIVES /* amx_NumNatives(), amx_GetNative() and amx_FindNative() */ #define AMX_XXXPUBLICS /* amx_NumPublics(), amx_GetPublic() and amx_FindPublic() */ #define AMX_XXXPUBVARS /* amx_NumPubVars(), amx_GetPubVar() and amx_FindPubVar() */ - #define AMX_XXXSTRING /* amx_StrLength(), amx_GetString() and amx_SetString() */ + #define AMX_XXXSTRING /* amx_StrLen(), amx_GetString() and amx_SetString() */ #define AMX_XXXTAGS /* amx_NumTags(), amx_GetTag() and amx_FindTagId() */ #define AMX_XXXUSERDATA /* amx_GetUserData() and amx_SetUserData() */ #define AMX_UTF8XXX /* amx_UTF8Get(), amx_UTF8Put(), amx_UTF8Check() */ #endif #undef AMX_EXPLIT_FUNCTIONS +#if defined AMX_ANSIONLY + #undef AMX_UTF8XXX /* no UTF-8 support in ANSI/ASCII-only version */ +#endif typedef enum { OP_NONE, /* invalid opcode */ @@ -259,10 +248,10 @@ typedef enum { OP_BOUNDS, OP_SYSREQ_PRI, OP_SYSREQ_C, - OP_FILE, - OP_LINE, - OP_SYMBOL, - OP_SRANGE, + OP_FILE, /* obsolete */ + OP_LINE, /* obsolete */ + OP_SYMBOL, /* obsolete */ + OP_SRANGE, /* obsolete */ OP_JUMP_PRI, OP_SWITCH, OP_CASETBL, @@ -271,135 +260,138 @@ typedef enum { OP_PUSHADDR, OP_NOP, OP_SYSREQ_D, - OP_SYMTAG, + OP_SYMTAG, /* obsolete */ + OP_BREAK, /* ----- */ OP_NUM_OPCODES } OPCODE; -typedef struct tagFUNCSTUBNT { - ucell address PACKED; - ucell nameofs PACKED; -} FUNCSTUBNT PACKED; - #define USENAMETABLE(hdr) \ - ((hdr)->defsize==sizeof(FUNCSTUBNT)) + ((hdr)->defsize==sizeof(AMX_FUNCSTUBNT)) #define NUMENTRIES(hdr,field,nextfield) \ - (int)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize) + (unsigned)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize) #define GETENTRY(hdr,table,index) \ - (AMX_FUNCSTUB *)((unsigned char*)(hdr) + (int)(hdr)->table + (int)index*(hdr)->defsize) + (AMX_FUNCSTUB *)((unsigned char*)(hdr) + (unsigned)(hdr)->table + (unsigned)index*(hdr)->defsize) #define GETENTRYNAME(hdr,entry) \ ( USENAMETABLE(hdr) \ - ? (char *)((unsigned char*)(hdr) + ((FUNCSTUBNT*)(entry))->nameofs) \ + ? (char *)((unsigned char*)(hdr) + (unsigned)((AMX_FUNCSTUBNT*)(entry))->nameofs) \ : ((AMX_FUNCSTUB*)(entry))->name ) -static int amx_LittleEndian = -1; /* set to TRUE for Little Endian, and - * to FALSE for Big Endian */ - -static void init_little_endian(void) -{ - if (amx_LittleEndian < 0) { /* initialize this variable only once */ +#if !defined NDEBUG + static int check_endian(void) + { uint16_t val=0x00ff; unsigned char *ptr=(unsigned char *)&val; - /* "ptr" points to the starting address of "val". If that address * holds the byte "0xff", the computer stored the low byte of "val" * at the lower address, and so the memory lay out is Little Endian. */ assert(*ptr==0xff || *ptr==0x00); - amx_LittleEndian= *ptr==0xff; - } /* if */ -} + #if BYTE_ORDER==BIG_ENDIAN + return *ptr==0x00; /* return "true" if big endian */ + #else + return *ptr==0xff; /* return "true" if little endian */ + #endif + } +#endif -static void swap16(uint16_t *v) -{ - unsigned char *s = (unsigned char *)v; - unsigned char t; +#if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==16 + static void swap16(uint16_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; - assert(sizeof(*v)==2); - /* swap two bytes */ - t=s[0]; - s[0]=s[1]; - s[1]=t; -} + assert(sizeof(*v)==2); + /* swap two bytes */ + t=s[0]; + s[0]=s[1]; + s[1]=t; + } +#endif -static void swap32(uint32_t *v) -{ - unsigned char *s = (unsigned char *)v; - unsigned char t; +#if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==32 + static void swap32(uint32_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; - assert(sizeof(*v)==4); - /* swap outer two bytes */ - t=s[0]; - s[0]=s[3]; - s[3]=t; - /* swap inner two bytes */ - t=s[1]; - s[1]=s[2]; - s[2]=t; -} + assert(sizeof(*v)==4); + /* swap outer two bytes */ + t=s[0]; + s[0]=s[3]; + s[3]=t; + /* swap inner two bytes */ + t=s[1]; + s[1]=s[2]; + s[2]=t; + } +#endif -#if defined _I64_MAX || defined HAVE_I64 -static void swap64(uint64_t *v) -{ - unsigned char *s = (unsigned char *)v; - unsigned char t; +#if (BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==64) && (defined _I64_MAX || defined HAVE_I64) + static void swap64(uint64_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; - assert(sizeof(*v)==8); + assert(sizeof(*v)==8); - t=s[0]; - s[0]=s[7]; - s[7]=t; + t=s[0]; + s[0]=s[7]; + s[7]=t; - t=s[1]; - s[1]=s[6]; - s[6]=t; + t=s[1]; + s[1]=s[6]; + s[6]=t; - t=s[2]; - s[2]=s[5]; - s[5]=t; + t=s[2]; + s[2]=s[5]; + s[5]=t; - t=s[3]; - s[3]=s[4]; - s[4]=t; -} + t=s[3]; + s[3]=s[4]; + s[4]=t; + } #endif #if defined AMX_ALIGN || defined AMX_INIT uint16_t * AMXAPI amx_Align16(uint16_t *v) { assert(sizeof(*v)==2); - init_little_endian(); - if (!amx_LittleEndian) + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN swap16(v); + #endif return v; } uint32_t * AMXAPI amx_Align32(uint32_t *v) { assert(sizeof(*v)==4); - init_little_endian(); - if (!amx_LittleEndian) + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN swap32(v); + #endif return v; } #if defined _I64_MAX || defined HAVE_I64 uint64_t * AMXAPI amx_Align64(uint64_t *v) { - assert(sizeof(*v)==8); - init_little_endian(); - if (!amx_LittleEndian) - swap64(v); - return v; + assert(sizeof(*v)==8); + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN + swap64(v); + #endif + return v; } #endif /* _I64_MAX || HAVE_I64 */ #endif /* AMX_ALIGN || AMX_INIT */ -#if SMALL_CELL_SIZE==16 +#if PAWN_CELL_SIZE==16 #define swapcell swap16 -#elif SMALL_CELL_SIZE==32 +#elif PAWN_CELL_SIZE==32 #define swapcell swap32 -#elif SMALL_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) +#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) #define swapcell swap64 #else #error Unsupported cell size @@ -423,29 +415,56 @@ int AMXAPI amx_Flags(AMX *amx,uint16_t *flags) } #endif /* AMX_FLAGS */ +void debug(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + FILE *fp = fopen("c:\\dump.txt", "at"); + if (fp) + { + vfprintf(fp, fmt, ap); + fclose(fp); + } + va_end(ap); +} + + #if defined AMX_INIT int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) { AMX_HEADER *hdr; AMX_FUNCSTUB *func; AMX_NATIVE f; - int i =0; assert(amx!=NULL); hdr=(AMX_HEADER *)amx->base; assert(hdr!=NULL); assert(hdr->magic==AMX_MAGIC); assert(hdr->natives<=hdr->libraries); - assert(index>=0 && index<(cell)NUMENTRIES(hdr,natives,libraries)); - func=GETENTRY(hdr,natives,index); - f=(AMX_NATIVE)func->address; - amx->userdata[2] = (char *)GETENTRYNAME(hdr, func); +#if defined AMX_NATIVETABLE + if (index=0 && index<(cell)NUMENTRIES(hdr,natives,libraries)); + func=GETENTRY(hdr,natives,index); + f=(AMX_NATIVE)func->address; +#if defined AMX_NATIVETABLE + } /* if */ +#endif assert(f!=NULL); - /* now that we have found the function, patch the program so that any + /* Now that we have found the function, patch the program so that any * subsequent call will call the function directly (bypassing this - * callback) + * callback). + * This trick cannot work in the JIT, because the program would need to + * be re-JIT-compiled after patching a P-code instruction. */ + #if defined JIT && !defined NDEBUG + if ((amx->flags & AMX_FLAG_JITC)!=0) + assert(amx->sysreq_d==0); + #endif if (amx->sysreq_d!=0) { /* at the point of the call, the CIP pseudo-register points directly * behind the SYSREQ instruction and its parameter. @@ -453,7 +472,7 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) unsigned char *code=amx->base+(int)hdr->cod+(int)amx->cip-4; assert(amx->cip >= 4 && amx->cip < (hdr->dat - hdr->cod)); assert(sizeof(f)<=sizeof(cell)); /* function pointer must fit in a cell */ -#if defined __GNUC__ || defined ASM32 || defined JIT +#if defined __GNUC__ || defined ASM32 if (*(cell*)code==index) { #else if (*(cell*)code!=OP_SYSREQ_PRI) { @@ -475,93 +494,28 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) *result = f(amx,params); return amx->error; } +#endif /* defined AMX_INIT */ -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -int AMXAPI amx_Debug(AMX *amx) -{ - return AMX_ERR_DEBUG; -} - -//Here is the actual debugger that AMX Mod X uses -int AMXAPI amx_DebugCall(AMX *amx, int mode) -{ - //right away, check for debugging - AMX_HEADER *hdr; - AMX_DBG *p = 0; - AMX_TRACE *t = 0; - hdr = (AMX_HEADER *)amx->base; - if ( !(amx->flags & AMX_FLAG_DEBUG) || !(amx->flags & AMX_FLAG_LINEOPS)) - return AMX_ERR_NONE; - p = (AMX_DBG *)(amx->userdata[0]); - if ( !p ) - return AMX_ERR_NONE; - if (mode == 2) - { - //mode - push onto the stack - t = (AMX_TRACE *)malloc(sizeof(AMX_TRACE)); - memset(t, 0, sizeof(AMX_TRACE)); - if (!p->head) - { - p->head = t; - t->prev = NULL; - } else { - t->prev = p->tail; - p->tail->next = t; - } - p->tail = t; - t->line = amx->curline; - t->file = amx->curfile; - } else if (mode == 1) { - //mode <0 - pop from the stack - t = p->tail; - if (t) - { - p->tail = t->prev; - free(t); - } - if (p->tail == NULL) - p->head = NULL; - } else if (mode == 0) { - AMX_TRACE *m; - //mode == 0 - clear stack - t = p->head; - while (t) - { - m = t->next; - free(t); - t = m; - } - p->head = 0; - p->tail = 0; - } - - return AMX_ERR_NONE; -} #if defined JIT -#if defined WIN32 || defined __cplusplus extern "C" int AMXAPI getMaxCodeSize(void); extern "C" int AMXAPI asm_runJIT(void *sourceAMXbase, void *jumparray, void *compiledAMXbase); -#else - extern int AMXAPI getMaxCodeSize(void); - extern int AMXAPI asm_runJIT(void *sourceAMXbase, void *jumparray, void *compiledAMXbase); -#endif #endif -#if SMALL_CELL_SIZE==16 - #define JUMPABS(base,ip) ((cell *)(base+*ip)) +#if PAWN_CELL_SIZE==16 + #define JUMPABS(base,ip) ((cell *)((base) + *(ip))) #define RELOC_ABS(base, off) #define RELOC_VALUE(base, v) #else - #define JUMPABS(base, ip) ((cell *)*ip) - #define RELOC_ABS(base, off) *(ucell *)(base+(int)off) += (ucell)base + #define JUMPABS(base, ip) ((cell *)*(ip)) + #define RELOC_ABS(base, off) (*(ucell *)((base)+(int)(off)) += (ucell)(base)) #define RELOC_VALUE(base, v) ((v)+((ucell)(base))) #endif #define DBGPARAM(v) ( (v)=*(cell *)(code+(int)cip), cip+=sizeof(cell) ) +#if defined AMX_INIT + static int amx_BrowseRelocate(AMX *amx) { AMX_HEADER *hdr; @@ -569,7 +523,6 @@ static int amx_BrowseRelocate(AMX *amx) cell cip; long codesize; OPCODE op; - int last_sym_global = 0; #if defined __GNUC__ || defined ASM32 || defined JIT cell *opcode_list; #endif @@ -584,6 +537,7 @@ static int amx_BrowseRelocate(AMX *amx) assert(hdr->magic==AMX_MAGIC); code=amx->base+(int)hdr->cod; codesize=hdr->dat - hdr->cod; + amx->flags=AMX_FLAG_BROWSE; /* sanity checks */ assert(OP_PUSH_PRI==36); @@ -595,38 +549,26 @@ static int amx_BrowseRelocate(AMX *amx) assert(OP_MOVS==117); assert(OP_SYMBOL==126); - amx->flags=AMX_FLAG_BROWSE; - - /* check the debug hook */ - if ((hdr->flags & AMX_FLAG_LINEOPS) && !(hdr->flags & AMX_FLAG_TRACED)) - { - amx->userdata[0] = (AMX_DBG *)malloc(sizeof(AMX_DBG)); - amx->userdata[1] = (void *)amx_DebugCall; - memset(amx->userdata[0], 0, sizeof(AMX_DBG)); - amx->flags |= AMX_FLAG_LINEOPS; - amx->flags |= AMX_FLAG_TRACED; - amx->flags |= AMX_FLAG_DEBUG; - } else { - amx->userdata[0] = 0; - amx->userdata[1] = 0; - amx->userdata[2] = 0; - } - - #if defined __GNUC__ || defined ASM32 || defined JIT && !defined __64BIT__ - amx_Exec(amx, (cell*)&opcode_list, 0, 0); - #if !defined JIT - amx->sysreq_d=(sizeof(AMX_NATIVE)<=sizeof(cell)) ? opcode_list[OP_SYSREQ_D] : 0; - #endif - #else - /* ANSI C - * to use direct system requests, a function pointer must fit in a cell; + amx->sysreq_d=0; /* preset */ + #if (defined __GNUC__ || defined ASM32 || defined JIT) && !defined __64BIT__ + amx_Exec(amx, (cell*)(void*)&opcode_list, 0); + /* to use direct system requests, a function pointer must fit in a cell; * because the native function's address will be stored as the parameter * of SYSREQ.D */ - amx->sysreq_d= (sizeof(AMX_NATIVE)<=sizeof(cell)) ? OP_SYSREQ_D : 0; + if ((amx->flags & AMX_FLAG_JITC)==0 && sizeof(AMX_NATIVE)<=sizeof(cell)) + amx->sysreq_d=opcode_list[OP_SYSREQ_D]; + #else + /* ANSI C + * to use direct system requests, a function pointer must fit in a cell; + * see the comment above + */ + if (sizeof(AMX_NATIVE)<=sizeof(cell)) + amx->sysreq_d=OP_SYSREQ_D; #endif /* start browsing code */ + debug("opcode_list=%p\n", opcode_list); for (cip=0; cip0 && opcurfile); - amx->dbgname=(char *)(code+(int)cip); - cip+=num - sizeof(cell); - if (!(hdr->flags & AMX_FLAG_TRACED) && amx->userdata[0] != NULL) - { - AMX_DBG *pDbg = (AMX_DBG *)(amx->userdata[0]); - if (pDbg->numFiles == 0) - { - pDbg->numFiles++; - pDbg->files = (char **)malloc(sizeof(char *) * 1); - } else { - pDbg->numFiles++; - pDbg->files = (char **)realloc(pDbg->files, pDbg->numFiles * sizeof(char*)); - } - pDbg->files[pDbg->numFiles-1] = (char *)malloc((sizeof(char) * strlen(amx->dbgname)) + 1); - strcpy(pDbg->files[pDbg->numFiles-1], amx->dbgname); - } /* if */ - break; - } /* case */ - case OP_LINE: - DBGPARAM(amx->curline); - DBGPARAM(amx->curfile); - break; + case OP_FILE: case OP_SYMBOL: { cell num; DBGPARAM(num); - DBGPARAM(amx->dbgaddr); - DBGPARAM(amx->dbgparam); - amx->dbgname=(char *)(code+(int)cip); - cip+=num - 2*sizeof(cell); - last_sym_global = (amx->dbgparam >> 8)==0; + cip+=num; break; } /* case */ + case OP_LINE: case OP_SRANGE: - DBGPARAM(amx->dbgaddr); /* dimension level */ - DBGPARAM(amx->dbgparam); /* length */ + cip+=2*sizeof(cell); break; case OP_SYMTAG: - DBGPARAM(amx->dbgparam); /* tag id */ + cip+=sizeof(cell); break; case OP_CASETBL: { cell num; @@ -855,17 +772,17 @@ static int amx_BrowseRelocate(AMX *amx) amx->flags &= ~AMX_FLAG_BROWSE; amx->flags |= AMX_FLAG_RELOC; - amx->flags |= AMX_FLAG_TRACED; return AMX_ERR_NONE; } +#if AMX_COMPACTMARGIN > 2 static void expand(unsigned char *code, long codesize, long memsize) { ucell c; struct { long memloc; ucell c; - } spare[AMX_EXPANDMARGIN]; + } spare[AMX_COMPACTMARGIN]; int sh=0,st=0,sc=0; int shift; @@ -886,15 +803,15 @@ static void expand(unsigned char *code, long codesize, long memsize) } while (codesize>0 && (code[(size_t)codesize-1] & 0x80)!=0); /* sign expand */ if ((code[(size_t)codesize] & 0x40)!=0) { - while (shift < 8*sizeof(cell)) { + while (shift < (int)(8*sizeof(cell))) { c|=(ucell)0xff << shift; shift+=8; } /* while */ } /* if */ /* store */ - while (sc&&(spare[sh].memloc>codesize)) { + while (sc && (spare[sh].memloc>codesize)) { *(ucell *)(code+(int)spare[sh].memloc)=spare[sh].c; - sh=(sh+1)%AMX_EXPANDMARGIN; + sh=(sh+1)%AMX_COMPACTMARGIN; sc--; } /* while */ memsize -= sizeof(cell); @@ -902,26 +819,27 @@ static void expand(unsigned char *code, long codesize, long memsize) if ((memsize>codesize)||((memsize==codesize)&&(memsize==0))) { *(ucell *)(code+(size_t)memsize)=c; } else { - assert(scsize); amx_Align16(&hdr->magic); amx_Align16((uint16_t*)&hdr->flags); @@ -953,13 +871,13 @@ int AMXAPI amx_Init(AMX *amx,void *program) amx_Align32((uint32_t*)&hdr->libraries); amx_Align32((uint32_t*)&hdr->pubvars); amx_Align32((uint32_t*)&hdr->tags); - } /* if */ + #endif if (hdr->magic!=AMX_MAGIC) return AMX_ERR_FORMAT; if (hdr->file_versionamx_version>CUR_FILE_VERSION) return AMX_ERR_VERSION; - if (hdr->defsize!=sizeof(AMX_FUNCSTUB) && hdr->defsize!=sizeof(FUNCSTUBNT)) + if (hdr->defsize!=sizeof(AMX_FUNCSTUB) && hdr->defsize!=sizeof(AMX_FUNCSTUBNT)) return AMX_ERR_FORMAT; if (USENAMETABLE(hdr)) { uint16_t *namelength; @@ -967,19 +885,29 @@ int AMXAPI amx_Init(AMX *amx,void *program) * in that table */ amx_Align32((uint32_t*)&hdr->nametable); - namelength=(uint16_t*)((unsigned char*)program + hdr->nametable); + namelength=(uint16_t*)((unsigned char*)program + (unsigned)hdr->nametable); amx_Align16(namelength); if (*namelength>sNAMEMAX) return AMX_ERR_FORMAT; } /* if */ if (hdr->stp<=0) return AMX_ERR_FORMAT; - if (!amx_LittleEndian && (hdr->flags & AMX_FLAG_COMPACT)==0) - return AMX_ERR_FORMAT; /* On Big Endian machines, use compact encoding */ + #if BYTE_ORDER==BIG_ENDIAN + if ((hdr->flags & AMX_FLAG_COMPACT)==0) { + ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod); + while (code<(ucell *)((unsigned char *)program+(int)hdr->hea)) + swapcell(code++); + } /* if */ + #endif assert((hdr->flags & AMX_FLAG_COMPACT)!=0 || hdr->hea == hdr->size); - if ((hdr->flags & AMX_FLAG_COMPACT)!=0) - expand((unsigned char *)program+(int)hdr->cod, - hdr->size - hdr->cod, hdr->hea - hdr->cod); + if ((hdr->flags & AMX_FLAG_COMPACT)!=0) { + #if AMX_COMPACTMARGIN > 2 + expand((unsigned char *)program+(int)hdr->cod, + hdr->size - hdr->cod, hdr->hea - hdr->cod); + #else + return AMX_ERR_FORMAT; + #endif + } /* if */ amx->base=(unsigned char *)program; @@ -995,25 +923,33 @@ int AMXAPI amx_Init(AMX *amx,void *program) amx->stk=amx->stp; if (amx->callback==NULL) amx->callback=amx_Callback; - amx->curline=0; - amx->curfile=0; amx->data=NULL; - /* also align all addresses in the public function, public variable and - * public tag tables --offsets into the name table (if present) must also - * be swapped. + /* also align all addresses in the public function, public variable, + * public tag and native function tables --offsets into the name table + * (if present) must also be swapped. */ - if (!amx_LittleEndian) { + #if BYTE_ORDER==BIG_ENDIAN + { /* local */ AMX_FUNCSTUB *fs; int i,num; + fs=GETENTRY(hdr,natives,0); + num=NUMENTRIES(hdr,natives,libraries); + for (i=0; iaddress); /* redundant, because it should be zero */ + if (USENAMETABLE(hdr)) + amx_Align32(&((AMX_FUNCSTUBNT*)fs)->nameofs); + fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); + } /* for */ + fs=GETENTRY(hdr,publics,0); assert(hdr->publics<=hdr->natives); num=NUMENTRIES(hdr,publics,natives); for (i=0; iaddress); if (USENAMETABLE(hdr)) - amx_AlignCell(&((FUNCSTUBNT*)fs)->nameofs); + amx_Align32(&((AMX_FUNCSTUBNT*)fs)->nameofs); fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); } /* for */ @@ -1023,7 +959,7 @@ int AMXAPI amx_Init(AMX *amx,void *program) for (i=0; iaddress); if (USENAMETABLE(hdr)) - amx_AlignCell(&((FUNCSTUBNT*)fs)->nameofs); + amx_Align32(&((AMX_FUNCSTUBNT*)fs)->nameofs); fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); } /* for */ @@ -1038,16 +974,17 @@ int AMXAPI amx_Init(AMX *amx,void *program) for (i=0; iaddress); if (USENAMETABLE(hdr)) - amx_AlignCell(&((FUNCSTUBNT*)fs)->nameofs); + amx_Align32(&((AMX_FUNCSTUBNT*)fs)->nameofs); fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); } /* for */ - } /* if */ + } /* local */ + #endif - /* relocate call and jump instructions, optionally gather debug information */ + /* relocate call and jump instructions */ amx_BrowseRelocate(amx); /* load any extension modules that the AMX refers to */ - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD + #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD hdr=(AMX_HEADER *)amx->base; numlibraries=NUMENTRIES(hdr,libraries,pubvars); for (i=0; iaddress=(uint32_t)hlib; + lib->address=(ucell)hlib; } /* for */ #endif @@ -1092,109 +1029,101 @@ int AMXAPI amx_Init(AMX *amx,void *program) #if defined JIT + #define CODESIZE_JIT 8192 /* approximate size of the code for the JIT */ + #if defined __WIN32__ /* this also applies to Win32 "console" applications */ - int memoryFullAccess( void* addr, int len ) + #define PROT_READ 0x1 /* page can be read */ + #define PROT_WRITE 0x2 /* page can be written */ + #define PROT_EXEC 0x4 /* page can be executed */ + #define PROT_NONE 0x0 /* page can not be accessed */ + + static int mprotect(void *addr, size_t len, int prot) { - DWORD op; - if ( VirtualProtect( addr, len, PAGE_EXECUTE_READWRITE, &op ) ) - return op; - return 0; + DWORD prev, p = 0; + if ((prot & PROT_WRITE)!=0) + p = PAGE_EXECUTE_READWRITE; + else + p |= PAGE_EXECUTE_READ; + return !VirtualProtect(addr, len, p, &prev); } - int memorySetAccess( void* addr, int len, int access ) - { - DWORD op; - if ( access == 0 ) - return 0; - return VirtualProtect( addr, len, access, &op ); - } + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ - #else /* #if defined __WIN32 __ */ - // DOS32 has no imposed limits on its segments. - #if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused - #endif - int memoryFullAccess( void* addr, int len ) - { - return mprotect(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC); - } + /* Linux already has mprotect() */ - #if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused - #endif - int memorySetAccess( void* addr, int len, int access ) - { - return mprotect(addr, len, PROT_READ|PROT_EXEC); - } + #else + + // TODO: Add cases for Linux, Unix, OS/2, ... + + /* DOS32 has no imposed limits on its segments */ + #define mprotect(addr, len, prot) (0) #endif /* #if defined __WIN32 __ */ int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code) { - int mac, res; + int res; AMX_HEADER *hdr; -#ifdef __linux__ - mac = memoryFullAccess( (void *)((int)((void*)asm_runJIT)-(int)((void*)asm_runJIT)%sysconf(_SC_PAGESIZE)), 20000 ); - if ( mac ) -#else - mac = memoryFullAccess((void *)asm_runJIT, 20000); - if ( !mac ) -#endif - return AMX_ERR_INIT_JIT; - - /* copy the prefix */ - memcpy( native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod ); - hdr = (AMX_HEADER*)native_code; - - /* JIT rulz! (TM) */ - /* MP: added check for correct compilation */ - res = asm_runJIT( amx->base, reloc_table, native_code ); - if ( res != 0 ) + if ((amx->flags & AMX_FLAG_JITC)==0) { - memorySetAccess( (void*)asm_runJIT, 20000, mac ); + debug("failing at line %d\n", __LINE__); + return AMX_ERR_INIT_JIT; /* flag not set, this AMX is not prepared for JIT */ + } + + /* Patching SYSREQ opcodes to SYSREQ_D cannot work in the JIT, because the + * program would need to be re-JIT-compiled after patching a P-code + * instruction. If this field is not zero, something went wrong with the + * amx_BrowseRelocate(). + */ + assert(amx->sysreq_d==0); + + if (mprotect(asm_runJIT, CODESIZE_JIT, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + debug("failing at line %d\n", __LINE__); return AMX_ERR_INIT_JIT; } - /* update the required memory size (the previous value was a - * conservative estimate, now we know the exact size) - */ - amx->code_size = (hdr->dat + hdr->stp + 3) & ~3; - /* The compiled code is relocatable, since only relative jumps are - * used for destinations within the generated code and absoulute - * addresses for jumps into the runtime, which is fixed in memory. - */ - amx->base = (unsigned char*) native_code; - amx->cip = hdr->cip; - amx->hea = hdr->hea; - amx->stp = hdr->stp - sizeof(cell); - /* also put a sentinel for strings at the top the stack */ - *(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0; - amx->stk = amx->stp; + /* copy the prefix */ + memcpy(native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod); + hdr = (AMX_HEADER *)native_code; - memorySetAccess( (void*)asm_runJIT, 20000, mac ); - return AMX_ERR_NONE; + /* JIT rulz! (TM) */ + /* MP: added check for correct compilation */ + if ((res = asm_runJIT(amx->base, reloc_table, native_code)) != 0) { + /* update the required memory size (the previous value was a + * conservative estimate, now we know the exact size) + */ + amx->code_size = (hdr->dat + hdr->stp + 3) & ~3; + /* The compiled code is relocatable, since only relative jumps are + * used for destinations within the generated code and absoulute + * addresses for jumps into the runtime, which is fixed in memory. + */ + amx->base = (unsigned char*) native_code; + amx->cip = hdr->cip; + amx->hea = hdr->hea; + amx->stp = hdr->stp - sizeof(cell); + /* also put a sentinel for strings at the top the stack */ + *(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0; + amx->stk = amx->stp; + } /* if */ + + debug("return value is %d\n", res); + + return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT; } #else /* #if defined JIT */ -#if defined _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4100) // unreferenced formal parameter -#endif -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table) { + (void)amx; + (void)compiled_program; + (void)reloc_table; return AMX_ERR_INIT_JIT; } -#if defined _MSC_VER - #pragma warning(pop) -#endif - #endif /* #if defined JIT */ #endif /* AMX_INIT */ @@ -1202,10 +1131,10 @@ int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table) #if defined AMX_CLEANUP int AMXAPI amx_Cleanup(AMX *amx) { - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD + #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD #if defined _Windows typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx); - #elif defined LINUX + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ typedef int (*AMX_ENTRY)(AMX *amx); #endif AMX_HEADER *hdr; @@ -1215,7 +1144,7 @@ int AMXAPI amx_Cleanup(AMX *amx) #endif /* unload all extension modules */ - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD + #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD hdr=(AMX_HEADER *)amx->base; assert(hdr->magic==AMX_MAGIC); numlibraries=NUMENTRIES(hdr,libraries,pubvars); @@ -1228,18 +1157,20 @@ int AMXAPI amx_Cleanup(AMX *amx) strcat(funcname,"Cleanup"); #if defined _Windows libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname); - #elif defined LINUX + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname); #endif if (libcleanup!=NULL) libcleanup(amx); #if defined _Windows FreeLibrary((HINSTANCE)lib->address); - #elif defined LINUX + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ dlclose((void*)lib->address); #endif } /* if */ } /* for */ + #else + (void)amx; #endif return AMX_ERR_NONE; } @@ -1274,8 +1205,6 @@ int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data) if (amxClone->debug==NULL) amxClone->debug=amxSource->debug; amxClone->flags=amxSource->flags; - amxClone->curline=0; - amxClone->curfile=0; /* copy the data segment; the stack and the heap can be left uninitialized */ assert(data!=NULL); @@ -1323,11 +1252,11 @@ int AMXAPI amx_NameLength(AMX *amx, int *length) assert(hdr!=NULL); assert(hdr->magic==AMX_MAGIC); if (USENAMETABLE(hdr)) { - uint16_t *namelength=(uint16_t*)(amx->base + hdr->nametable); + uint16_t *namelength=(uint16_t*)(amx->base + (unsigned)hdr->nametable); *length=*namelength; assert(hdr->file_version>=7); /* name table exists only for file version 7+ */ } else { - *length=hdr->defsize - sizeof(cell); + *length=hdr->defsize - sizeof(ucell); } /* if */ return AMX_ERR_NONE; } @@ -1632,7 +1561,7 @@ int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr) #endif /* AMX_XXXUSERDATA */ #if defined AMX_REGISTER || defined AMX_EXEC || defined AMX_INIT -static AMX_NATIVE findfunction(const char *name, AMX_NATIVE_INFO *list, int number) +static AMX_NATIVE findfunction(const char *name, const AMX_NATIVE_INFO *list, int number) { int i; @@ -1643,8 +1572,8 @@ static AMX_NATIVE findfunction(const char *name, AMX_NATIVE_INFO *list, int numb return NULL; } -const char *no_function; // PM: Nice hack ;) -int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *list, int number) +const char *no_function; +int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number) { AMX_FUNCSTUB *func; AMX_HEADER *hdr; @@ -1664,51 +1593,19 @@ int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *list, int number) /* this function is not yet located */ funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL; if (funcptr!=NULL) + { func->address=(ucell)funcptr; - else - { + } else { no_function = GETENTRYNAME(hdr,func); err=AMX_ERR_NOTFOUND; - } + } } /* if */ func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize); } /* for */ + if (err==AMX_ERR_NONE) + amx->flags|=AMX_FLAG_NTVREG; return err; } - -static cell AMX_NATIVE_CALL null_native(AMX *amx, cell *params) -{ - return 0; -} - -void amx_NullNativeTable(AMX *amx) -{ - AMX_FUNCSTUB *func; - AMX_HEADER *hdr; - int i, numnatives; - - hdr=(AMX_HEADER *)amx->base; - if (hdr == NULL) - return; - if (hdr->magic!=AMX_MAGIC) - return; - - numnatives = NUMENTRIES(hdr, natives, libraries); - - func=GETENTRY(hdr, natives, 0); - - for (i=0; iaddress = NULL; - } else { - func->address = (ucell)null_native; - } - func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize); - } -} - #endif /* AMX_REGISTER || AMX_EXEC || AMX_INIT */ #if defined AMX_NATIVEINFO @@ -1723,26 +1620,88 @@ AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func) #if defined AMX_EXEC || defined AMX_INIT +#define STKMARGIN ((cell)(16*sizeof(cell))) + +int AMXAPI amx_Push(AMX *amx, cell value) +{ + AMX_HEADER *hdr; + unsigned char *data; + + if (amx->hea+STKMARGIN>amx->stk) + return AMX_ERR_STACKERR; + hdr=(AMX_HEADER *)amx->base; + data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; + amx->stk-=sizeof(cell); + amx->paramcount+=1; + *(cell *)(data+(int)amx->stk)=value; + return AMX_ERR_NONE; +} + +int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells) +{ + cell *paddr; + int err; + + assert(amx!=NULL); + assert(amx_addr!=NULL); + assert(array!=NULL); + + err=amx_Allot(amx,numcells,amx_addr,&paddr); + if (err==AMX_ERR_NONE) { + if (phys_addr!=NULL) + *phys_addr=paddr; + memcpy(paddr,array,numcells*sizeof(cell)); + err=amx_Push(amx,*amx_addr); + } /* if */ + return err; +} + +int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar) +{ + cell *paddr; + int numcells,err; + + assert(amx!=NULL); + assert(amx_addr!=NULL); + assert(string!=NULL); + + #if defined AMX_ANSIONLY + numcells=strlen(string) + 1; + #else + numcells= (use_wchar ? wcslen((const wchar_t*)string) : strlen(string)) + 1; + #endif + if (pack) + numcells=(numcells+sizeof(cell)-1)/sizeof(cell); + err=amx_Allot(amx,numcells,amx_addr,&paddr); + if (err==AMX_ERR_NONE) { + if (phys_addr!=NULL) + *phys_addr=paddr; + amx_SetString(paddr,string,pack,use_wchar,UNLIMITED); + err=amx_Push(amx,*amx_addr); + } /* if */ + return err; +} + #define GETPARAM(v) ( v=*(cell *)cip++ ) +#define SKIPPARAM(n) ( cip=(cell *)cip+(n) ) #define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v ) #define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) ) #define ABORT(amx,v) { (amx)->stk=reset_stk; (amx)->hea=reset_hea; return v; } -#define STKMARGIN ((cell)(16*sizeof(cell))) #define CHKMARGIN() if (hea+STKMARGIN>stk) return AMX_ERR_STACKERR #define CHKSTACK() if (stk>amx->stp) return AMX_ERR_STACKLOW #define CHKHEAP() if (heahlw) return AMX_ERR_HEAPLOW -#if defined __GNUC__ && !defined ASM32 && !defined JIT +#if defined __GNUC__ && !(defined ASM32 || defined JIT) /* GNU C version uses the "labels as values" extension to create * fast "indirect threaded" interpreter. */ #define NEXT(cip) goto **cip++ -int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) { -static void *amx_opcodelist[] = { +static const void * const amx_opcodelist[] = { &&op_none, &&op_load_pri, &&op_load_alt, &&op_load_s_pri, &&op_load_s_alt,&&op_lref_pri, &&op_lref_alt, &&op_lref_s_pri, &&op_lref_s_alt,&&op_load_i, &&op_lodb_i, &&op_const_pri, @@ -1777,43 +1736,7 @@ static void *amx_opcodelist[] = { &&op_file, &&op_line, &&op_symbol, &&op_srange, &&op_jump_pri, &&op_switch, &&op_casetbl, &&op_swap_pri, &&op_swap_alt, &&op_pushaddr, &&op_nop, &&op_sysreq_d, - &&op_symtag }; -static void *amx_opcodelist_nodebug[] = { - &&op_none, &&op_load_pri, &&op_load_alt, &&op_load_s_pri, - &&op_load_s_alt,&&op_lref_pri, &&op_lref_alt, &&op_lref_s_pri, - &&op_lref_s_alt,&&op_load_i, &&op_lodb_i, &&op_const_pri, - &&op_const_alt, &&op_addr_pri, &&op_addr_alt, &&op_stor_pri, - &&op_stor_alt, &&op_stor_s_pri,&&op_stor_s_alt,&&op_sref_pri, - &&op_sref_alt, &&op_sref_s_pri,&&op_sref_s_alt,&&op_stor_i, - &&op_strb_i, &&op_lidx, &&op_lidx_b, &&op_idxaddr, - &&op_idxaddr_b, &&op_align_pri, &&op_align_alt, &&op_lctrl, - &&op_sctrl, &&op_move_pri, &&op_move_alt, &&op_xchg, - &&op_push_pri, &&op_push_alt, &&op_push_r, &&op_push_c, - &&op_push, &&op_push_s, &&op_pop_pri, &&op_pop_alt, - &&op_stack_nodebug, &&op_heap, &&op_proc, &&op_ret_nodebug, - &&op_retn_nodebug, &&op_call_nodebug, &&op_call_pri_nodebug, &&op_jump, - &&op_jrel, &&op_jzer, &&op_jnz, &&op_jeq, - &&op_jneq, &&op_jless, &&op_jleq, &&op_jgrtr, - &&op_jgeq, &&op_jsless, &&op_jsleq, &&op_jsgrtr, - &&op_jsgeq, &&op_shl, &&op_shr, &&op_sshr, - &&op_shl_c_pri, &&op_shl_c_alt, &&op_shr_c_pri, &&op_shr_c_alt, - &&op_smul, &&op_sdiv, &&op_sdiv_alt, &&op_umul, - &&op_udiv, &&op_udiv_alt, &&op_add, &&op_sub, - &&op_sub_alt, &&op_and, &&op_or, &&op_xor, - &&op_not, &&op_neg, &&op_invert, &&op_add_c, - &&op_smul_c, &&op_zero_pri, &&op_zero_alt, &&op_zero, - &&op_zero_s, &&op_sign_pri, &&op_sign_alt, &&op_eq, - &&op_neq, &&op_less, &&op_leq, &&op_grtr, - &&op_geq, &&op_sless, &&op_sleq, &&op_sgrtr, - &&op_sgeq, &&op_eq_c_pri, &&op_eq_c_alt, &&op_inc_pri, - &&op_inc_alt, &&op_inc, &&op_inc_s, &&op_inc_i, - &&op_dec_pri, &&op_dec_alt, &&op_dec, &&op_dec_s, - &&op_dec_i, &&op_movs, &&op_cmps, &&op_fill, - &&op_halt, &&op_bounds, &&op_sysreq_pri,&&op_sysreq_c, - &&op_file, &&op_line_nodebug, &&op_symbol_nodebug, &&op_srange_nodebug, - &&op_jump_pri, &&op_switch, &&op_casetbl, &&op_swap_pri, - &&op_swap_alt, &&op_pushaddr, &&op_nop, &&op_sysreq_d, - &&op_symtag_nodebug }; + &&op_symtag, &&op_break }; AMX_HEADER *hdr; AMX_FUNCSTUB *func; unsigned char *code, *data; @@ -1822,31 +1745,22 @@ static void *amx_opcodelist_nodebug[] = { cell offs; ucell codesize; int num,i; - va_list ap; - AMX_DEBUGCALL tracer = 0; - AMX_DBG *pdbg = 0; /* HACK: return label table (for amx_BrowseRelocate) if amx structure * has the AMX_FLAG_BROWSE flag set. */ + assert(amx!=NULL); if ((amx->flags & AMX_FLAG_BROWSE)==AMX_FLAG_BROWSE) { assert(sizeof(cell)==sizeof(void *)); assert(retval!=NULL); - if (amx->flags & AMX_FLAG_DEBUG) - { - *retval=(cell)(amx_opcodelist); - } else { - *retval=(cell)(amx_opcodelist_nodebug); - } + *retval=(cell)amx_opcodelist; return 0; } /* if */ if (amx->callback==NULL) return AMX_ERR_CALLBACK; - i=amx_Register(amx,NULL,0); /* verify that all natives are registered */ - if (i!=AMX_ERR_NONE) - return i; - + if ((amx->flags & AMX_FLAG_NTVREG)==0) + return AMX_ERR_NOTFOUND; if ((amx->flags & AMX_FLAG_RELOC)==0) return AMX_ERR_INIT; assert((amx->flags & AMX_FLAG_BROWSE)==0); @@ -1861,7 +1775,8 @@ static void *amx_opcodelist_nodebug[] = { stk=amx->stk; reset_stk=stk; reset_hea=hea; - frm=0; /* just to avoid compiler warnings */ + alt=frm=0; /* just to avoid compiler warnings */ + num=0; /* just to avoid compiler warnings */ /* get the start address */ if (index==AMX_EXEC_MAIN) { @@ -1881,7 +1796,7 @@ static void *amx_opcodelist_nodebug[] = { } else if (index<0) { return AMX_ERR_INDEX; } else { - if (index>=NUMENTRIES(hdr,publics,natives)) + if (index>=(int)NUMENTRIES(hdr,publics,natives)) return AMX_ERR_INDEX; func=GETENTRY(hdr,publics,index); cip=(cell *)(code + (int)func->address); @@ -1889,7 +1804,7 @@ static void *amx_opcodelist_nodebug[] = { /* check values just copied */ CHKSTACK(); CHKHEAP(); - init_little_endian(); + assert(check_endian()); /* sanity checks */ assert(OP_PUSH_PRI==36); @@ -1900,53 +1815,25 @@ static void *amx_opcodelist_nodebug[] = { assert(OP_INC_PRI==107); assert(OP_MOVS==117); assert(OP_SYMBOL==126); - #if SMALL_CELL_SIZE==16 + #if PAWN_CELL_SIZE==16 assert(sizeof(cell)==2); - #elif SMALL_CELL_SIZE==32 + #elif PAWN_CELL_SIZE==32 assert(sizeof(cell)==4); - #elif SMALL_CELL_SIZE==64 + #elif PAWN_CELL_SIZE==64 assert(sizeof(cell)==8); #else #error Unsupported cell size #endif if (index!=AMX_EXEC_CONT) { - /* push the parameters to the stack (in reverse order) */ - if (numparams & 0xFFFF0000) { - cell *params; - stk-=(numparams>>=16)*sizeof(cell); - va_start(ap,numparams); - params = va_arg(ap,cell*); - va_end(ap); - for (i=0; iparamcount*sizeof(cell); + PUSH(amx->paramcount*sizeof(cell)); + amx->paramcount=0; /* push the parameter count to the stack & reset */ PUSH(0); /* zero return address */ } /* if */ /* check stack/heap before starting to run */ CHKMARGIN(); - if ((amx->flags & AMX_FLAG_DEBUG) && (amx->flags & AMX_FLAG_LINEOPS)) - { - if (amx->userdata[0]) - { - tracer = (AMX_DEBUGCALL)amx->userdata[1]; - pdbg = (AMX_DBG *)(amx->userdata[0]); - if (tracer) - { - //as a precaution, clear the call stack - (tracer)(amx, 0); - } - } - } - /* start running */ NEXT(cip); @@ -1990,14 +1877,14 @@ static void *amx_opcodelist_nodebug[] = { NEXT(cip); op_load_i: /* verify address */ - if ((pri>=hea && pri=(ucell)amx->stp) + if (pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri= * (cell *)(data+(int)pri); NEXT(cip); op_lodb_i: GETPARAM(offs); /* verify address */ - if ((pri>=hea && pri=(ucell)amx->stp) + if (pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); switch (offs) { case 1: @@ -2063,14 +1950,14 @@ static void *amx_opcodelist_nodebug[] = { NEXT(cip); op_stor_i: /* verify address */ - if ((alt>=hea && alt=(ucell)amx->stp) + if (alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); *(cell *)(data+(int)alt)=pri; NEXT(cip); op_strb_i: GETPARAM(offs); /* verify address */ - if ((alt>=hea && alt=(ucell)amx->stp) + if (alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); switch (offs) { case 1: @@ -2087,7 +1974,7 @@ static void *amx_opcodelist_nodebug[] = { op_lidx: offs=pri*sizeof(cell)+alt; /* verify address */ - if ((offs>=hea && offs=(ucell)amx->stp) + if (offs>=hea && offs=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri= * (cell *)(data+(int)offs); NEXT(cip); @@ -2095,7 +1982,7 @@ static void *amx_opcodelist_nodebug[] = { GETPARAM(offs); offs=(pri << (int)offs)+alt; /* verify address */ - if ((offs>=hea && offs=(ucell)amx->stp) + if (offs>=hea && offs=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri= * (cell *)(data+(int)offs); NEXT(cip); @@ -2108,13 +1995,17 @@ static void *amx_opcodelist_nodebug[] = { NEXT(cip); op_align_pri: GETPARAM(offs); - if (amx_LittleEndian && offs=codesize) - ABORT(amx,AMX_ERR_MEMACCESS); - cip=(cell *)(code+(int)offs); - NEXT(cip); - op_ret_nodebug: POP(frm); POP(offs); /* verify the return address */ @@ -2251,19 +2123,6 @@ static void *amx_opcodelist_nodebug[] = { cip=(cell *)(code+(int)offs); NEXT(cip); op_retn: - if (tracer) - { - (tracer)(amx, 1); - } - POP(frm); - POP(offs); - /* verify the return address */ - if ((ucell)offs>=codesize) - ABORT(amx,AMX_ERR_MEMACCESS); - cip=(cell *)(code+(int)offs); - stk+= *(cell *)(data+(int)stk) + sizeof(cell); /* remove parameters from the stack */ - NEXT(cip); - op_retn_nodebug: POP(frm); POP(offs); /* verify the return address */ @@ -2273,26 +2132,10 @@ static void *amx_opcodelist_nodebug[] = { stk+= *(cell *)(data+(int)stk) + sizeof(cell); /* remove parameters from the stack */ NEXT(cip); op_call: - if (tracer) - { - (tracer)(amx, 2); - } - PUSH(((unsigned char *)cip-code)+sizeof(cell));/* push address behind instruction */ - cip=JUMPABS(code, cip); /* jump to the address */ - NEXT(cip); - op_call_nodebug: PUSH(((unsigned char *)cip-code)+sizeof(cell));/* push address behind instruction */ cip=JUMPABS(code, cip); /* jump to the address */ NEXT(cip); op_call_pri: - if (tracer) - { - (tracer)(amx, 2); - } - PUSH((unsigned char *)cip-code); - cip=(cell *)(code+(int)pri); - NEXT(cip); - op_call_pri_nodebug: PUSH((unsigned char *)cip-code); cip=(cell *)(code+(int)pri); NEXT(cip); @@ -2576,13 +2419,13 @@ static void *amx_opcodelist_nodebug[] = { /* verify top & bottom memory addresses, for both source and destination * addresses */ - if ((pri>=hea && pri=(ucell)amx->stp) + if (pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) + if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt>=hea && alt=(ucell)amx->stp) + if (alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); memcpy(data+(int)alt, data+(int)pri, (int)offs); NEXT(cip); @@ -2591,34 +2434,32 @@ static void *amx_opcodelist_nodebug[] = { /* verify top & bottom memory addresses, for both source and destination * addresses */ - if ((pri>=hea && pri=(ucell)amx->stp) + if (pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) + if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt>=hea && alt=(ucell)amx->stp) + if (alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri=memcmp(data+(int)alt, data+(int)pri, (int)offs); NEXT(cip); op_fill: GETPARAM(offs); /* verify top & bottom memory addresses */ - if ((alt>=hea && alt=(ucell)amx->stp) + if (alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - for (i=(int)alt; offs>=sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) + for (i=(int)alt; offs>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) *(cell *)(data+i) = pri; NEXT(cip); op_halt: GETPARAM(offs); if (retval!=NULL) *retval=pri; - /* store complete status */ + /* store complete status (stk and hea are already set in the ABORT macro) */ amx->frm=frm; - amx->stk=stk; - amx->hea=hea; amx->pri=pri; amx->alt=alt; amx->cip=(cell)((unsigned char*)cip-code); @@ -2695,61 +2536,30 @@ static void *amx_opcodelist_nodebug[] = { assert(0); /* this code should not occur during execution */ NEXT(cip); op_line: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->curline); - GETPARAM(amx->curfile); - NEXT(cip); - op_line_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->curline); - GETPARAM(amx->curfile); + SKIPPARAM(2); NEXT(cip); op_symbol: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(offs); - GETPARAM(amx->dbgaddr); - GETPARAM(amx->dbgparam); - amx->dbgname=(char *)cip; - cip=(cell *)((unsigned char *)cip + (int)offs - 2*sizeof(cell)); - amx->dbgcode=DBG_SYMBOL; - assert((amx->dbgparam >> 8)>0); /* local symbols only */ - NEXT(cip); - op_symbol_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); GETPARAM(offs); cip=(cell *)((unsigned char *)cip + (int)offs); NEXT(cip); op_srange: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgaddr); /* dimension level */ - GETPARAM(amx->dbgparam); /* length */ - amx->dbgcode=DBG_SRANGE; - NEXT(cip); - op_srange_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - cip+=2; + SKIPPARAM(2); NEXT(cip); op_symtag: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgparam); /* tag id */ - amx->dbgcode=DBG_SYMTAG; - NEXT(cip); - op_symtag_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - cip+=1; + SKIPPARAM(1); NEXT(cip); op_jump_pri: cip=(cell *)(code+(int)pri); NEXT(cip); op_switch: { cell *cptr; - cptr=(cell *)*cip + 1; /* +1, to skip the "casetbl" opcode */ - cip=(cell *)*(cptr+1); /* preset to "none-matched" case */ + cptr=JUMPABS(code,cip)+1; /* +1, to skip the "casetbl" opcode */ + cip=JUMPABS(code,cptr+1); /* preset to "none-matched" case */ num=(int)*cptr; /* number of records in the case table */ for (cptr+=2; num>0 && *cptr!=pri; num--,cptr+=2) /* nothing */; if (num>0) - cip=(cell *)*(cptr+1); /* case found */ + cip=JUMPABS(code,cptr+1); /* case found */ NEXT(cip); } op_casetbl: @@ -2771,6 +2581,26 @@ static void *amx_opcodelist_nodebug[] = { NEXT(cip); op_nop: NEXT(cip); + op_break: + if (amx->debug!=NULL) { + /* store status */ + amx->frm=frm; + amx->stk=stk; + amx->hea=hea; + amx->cip=(cell)((unsigned char*)cip-code); + num=amx->debug(amx); + if (num!=AMX_ERR_NONE) { + if (num==AMX_ERR_SLEEP) { + amx->pri=pri; + amx->alt=alt; + amx->reset_stk=reset_stk; + amx->reset_hea=reset_hea; + return num; + } /* if */ + ABORT(amx,num); + } /* if */ + } /* if */ + NEXT(cip); } #else @@ -2781,7 +2611,8 @@ static void *amx_opcodelist_nodebug[] = { * Microsoft C/C++ (and most other C compilers) use "cdecl". * The important point is that you assemble AMXEXEC.ASM with the matching * calling convention, or the right JIT, respectively. - * jitr.asm is for Watcom's register calling convention, jits.asm for "cdecl". + * AMXJITR.ASM is for Watcom's register calling convention, AMXJITS.ASM and + * AMXJITSN.ASM are for "cdecl". */ #if defined __WATCOMC__ #if !defined STACKARGS /* for AMX32.DLL */ @@ -2789,33 +2620,37 @@ static void *amx_opcodelist_nodebug[] = { /* The following pragma tells the compiler into which registers * the parameters have to go. */ #pragma aux amx_exec_asm parm [eax] [edx] [ebx] [ecx]; + extern cell amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); + #pragma aux amx_exec_jit parm [eax] [edx] [ebx] [ecx]; #else extern cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); + extern cell __cdecl amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); #endif #elif defined __GNUC__ /* force "cdecl" by adding an "attribute" to the declaration */ - #if defined __cplusplus extern "C" cell amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea) __attribute__((cdecl)); - #else - extern cell amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea) __attribute__((cdecl)); - #endif + extern "C" cell amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea) __attribute__((cdecl)); #else /* force "cdecl" by specifying it as a "function class" with the "__cdecl" keyword */ extern "C" cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); + extern "C" cell __cdecl amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); #endif #endif -#if defined ASM32 || defined JIT -#if defined WIN32 || defined __cplusplus - extern "C" void *amx_opcodelist[]; - extern "C" void *amx_opcodelist_nodebug[]; -#else - extern void *amx_opcodelist[]; - extern void *amx_opcodelist_nodebug[]; +#if defined ASM32 + extern "C" void *amx_opcodelist[]; + #ifdef __WATCOMC__ + #pragma aux amx_opcodelist "_*" + #endif #endif +#if defined JIT + extern "C" void const *amx_opcodelist_jit[]; + #ifdef __WATCOMC__ + #pragma aux amx_opcodelist_jit "_*" + #endif #endif -int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) { AMX_HEADER *hdr; AMX_FUNCSTUB *func; @@ -2824,21 +2659,14 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) cell reset_stk, reset_hea, *cip; ucell codesize; int i; - va_list ap; #if defined ASM32 || defined JIT - #ifdef __WATCOMC__ - #pragma aux amx_opcodelist "_*" - #pragma aux amx_opcodelist_nodebug "_*" - #endif cell parms[9]; /* registers and parameters for assembler AMX */ #else OPCODE op; cell offs; int num; #endif - AMX_DEBUGCALL tracer = 0; - AMX_DBG *pdbg = 0; - + assert(amx!=NULL); #if defined ASM32 || defined JIT /* HACK: return label table (for amx_BrowseRelocate) if amx structure * is not passed. @@ -2846,43 +2674,28 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) if ((amx->flags & AMX_FLAG_BROWSE)==AMX_FLAG_BROWSE) { assert(sizeof(cell)==sizeof(void *)); assert(retval!=NULL); - #if defined JIT - /* The JIT does not support a "debug" opcode list; however, its single - * opcode list is called "amx_opcodelist", although it should be called - * amx_opcodelist_nodebug - */ + #if defined ASM32 && defined JIT + if ((amx->flags & AMX_FLAG_JITC)!=0) + *retval=(cell)amx_opcodelist_jit; + else + *retval=(cell)amx_opcodelist; + #elif defined ASM32 *retval=(cell)amx_opcodelist; #else - if (amx->flags & AMX_FLAG_DEBUG) - { - *retval=(cell)(amx_opcodelist); - } else { - *retval=(cell)(amx_opcodelist_nodebug); - } + *retval=(cell)amx_opcodelist_jit; #endif return 0; } /* if */ #endif - - if ((amx->flags & AMX_FLAG_DEBUG) && (amx->flags & AMX_FLAG_LINEOPS)) - { - if (amx->userdata[0]) - { - tracer = (AMX_DEBUGCALL)amx->userdata[1]; - pdbg = (AMX_DBG *)(amx->userdata[0]); - } - } - if (amx->callback==NULL) return AMX_ERR_CALLBACK; - i=amx_Register(amx,NULL,0); /* verify that all natives are registered */ - if (i!=AMX_ERR_NONE) - return i; - + if ((amx->flags & AMX_FLAG_NTVREG)==0) + return AMX_ERR_NOTFOUND; if ((amx->flags & AMX_FLAG_RELOC)==0) return AMX_ERR_INIT; assert((amx->flags & AMX_FLAG_BROWSE)==0); + /* set up the registers */ hdr=(AMX_HEADER *)amx->base; assert(hdr->magic==AMX_MAGIC); @@ -2917,11 +2730,12 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) return AMX_ERR_INDEX; func=GETENTRY(hdr,publics,index); cip=(cell *)(code + (int)func->address); + debug("CIP: %p. CIP op: %p. opcode_list: %p", cip, *cip, amx_opcodelist); } /* if */ /* check values just copied */ CHKSTACK(); CHKHEAP(); - init_little_endian(); + assert(check_endian()); /* sanity checks */ assert(OP_PUSH_PRI==36); @@ -2932,34 +2746,21 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) assert(OP_INC_PRI==107); assert(OP_MOVS==117); assert(OP_SYMBOL==126); - #if SMALL_CELL_SIZE==16 + #if PAWN_CELL_SIZE==16 assert(sizeof(cell)==2); - #elif SMALL_CELL_SIZE==32 + #elif PAWN_CELL_SIZE==32 assert(sizeof(cell)==4); - #elif SMALL_CELL_SIZE==64 + #elif PAWN_CELL_SIZE==64 assert(sizeof(cell)==8); #else #error Unsupported cell size #endif - if (index!=AMX_EXEC_CONT) { - /* push the parameters to the stack (in reverse order) */ - if (numparams & 0xFFFF0000L) { - cell *params; - stk-=(numparams>>=16)*sizeof(cell); - va_start(ap,numparams); - params = va_arg(ap,cell*); - va_end(ap); - for (i=0; iparamcount*sizeof(cell); + PUSH(amx->paramcount*sizeof(cell)); + amx->paramcount=0; /* push the parameter count to the stack & reset */ #if defined ASM32 || defined JIT PUSH(RELOC_VALUE(code,0));/* relocated zero return address */ #else @@ -2983,7 +2784,16 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) parms[7] = (cell)code; parms[8] = (cell)codesize; - i = amx_exec_asm(parms,retval,amx->stp,hea); + #if defined ASM32 && defined JIT + if ((amx->flags & AMX_FLAG_JITC)!=0) + i = amx_exec_jit(parms,retval,amx->stp,hea); + else + i = amx_exec_asm(parms,retval,amx->stp,hea); + #elif defined ASM32 + i = amx_exec_asm(parms,retval,amx->stp,hea); + #else + i = amx_exec_jit(parms,retval,amx->stp,hea); + #endif if (i == AMX_ERR_SLEEP) { amx->reset_stk=reset_stk; amx->reset_hea=reset_hea; @@ -3158,13 +2968,17 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) break; case OP_ALIGN_PRI: GETPARAM(offs); - if (amx_LittleEndian && (size_t)offsstk=stk; - if (tracer) - { - (tracer)(amx, 1); - } break; case OP_CALL: PUSH(((unsigned char *)cip-code)+sizeof(cell));/* skip address */ cip=JUMPABS(code, cip); /* jump to the address */ - if (tracer) - { - (tracer)(amx, 2); - } break; case OP_CALL_PRI: PUSH((unsigned char *)cip-code); @@ -3420,6 +3226,7 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) if (alt==0) ABORT(amx,AMX_ERR_DIVIDE); /* divide must always round down; this is a bit + * involved to do in a machine-independent way. */ offs=(pri % alt + alt) % alt; /* true modulus */ pri=(pri - offs) / alt; /* division result */ @@ -3625,10 +3432,8 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) GETPARAM(offs); if (retval!=NULL) *retval=pri; - /* store complete status */ + /* store complete status (stk and hea are already set in the ABORT macro) */ amx->frm=frm; - amx->stk=stk; - amx->hea=hea; amx->pri=pri; amx->alt=alt; amx->cip=(cell)((unsigned char*)cip-code); @@ -3699,33 +3504,18 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) ABORT(amx,amx->error); } /* if */ break; - case OP_FILE: - GETPARAM(offs); - cip=(cell *)((unsigned char *)cip+(int)offs); - assert(0); /* this code should not occur during execution */ - break; case OP_LINE: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->curline); - GETPARAM(amx->curfile); + SKIPPARAM(2); break; case OP_SYMBOL: - assert((amx->flags & AMX_FLAG_BROWSE)==0); GETPARAM(offs); - GETPARAM(amx->dbgaddr); - GETPARAM(amx->dbgparam); - amx->dbgname=(char *)cip; - cip=(cell *)((unsigned char *)cip + (int)offs - 2*sizeof(cell)); - assert((amx->dbgparam >> 8)>0); /* local symbols only */ + cip=(cell *)((unsigned char *)cip + (int)offs); break; case OP_SRANGE: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgaddr); /* dimension level */ - GETPARAM(amx->dbgparam); /* length */ + SKIPPARAM(2); break; case OP_SYMTAG: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgparam); /* tag id */ + SKIPPARAM(1); break; case OP_JUMP_PRI: cip=(cell *)(code+(int)pri); @@ -3733,13 +3523,13 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) case OP_SWITCH: { cell *cptr; - cptr=(cell *)*cip + 1; /* +1, to skip the "casetbl" opcode */ - cip=(cell *)*(cptr+1); /* preset to "none-matched" case */ + cptr=JUMPABS(code,cip)+1; /* +1, to skip the "casetbl" opcode */ + cip=JUMPABS(code,cptr+1); /* preset to "none-matched" case */ num=(int)*cptr; /* number of records in the case table */ for (cptr+=2; num>0 && *cptr!=pri; num--,cptr+=2) /* nothing */; if (num>0) - cip=(cell *)*(cptr+1); /* case found */ + cip=JUMPABS(code,cptr+1); /* case found */ break; } /* case */ case OP_SWAP_PRI: @@ -3758,10 +3548,32 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) break; case OP_NOP: break; - case OP_CASETBL: - assert(0); /* should not occur during execution */ - /* drop through to "invalid instruction" */ + case OP_BREAK: + assert((amx->flags & AMX_FLAG_BROWSE)==0); + if (amx->debug!=NULL) { + /* store status */ + amx->frm=frm; + amx->stk=stk; + amx->hea=hea; + amx->cip=(cell)((unsigned char*)cip-code); + num=amx->debug(amx); + if (num!=AMX_ERR_NONE) { + if (num==AMX_ERR_SLEEP) { + amx->pri=pri; + amx->alt=alt; + amx->reset_stk=reset_stk; + amx->reset_hea=reset_hea; + return num; + } /* if */ + ABORT(amx,num); + } /* if */ + } /* if */ + break; default: + /* case OP_FILE: should not occur during execution + * case OP_CASETBL: should not occur during execution + */ + assert(0); ABORT(amx,AMX_ERR_INVINSTR); } /* switch */ } /* for */ @@ -3770,14 +3582,6 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) #endif /* __GNUC__ */ -/* For interfacing applications not written in C/C++, amx_Execv() works like - * amx_Exec(), but has all parameters passed via an array. - */ -int AMXAPI amx_Execv(AMX *amx, cell *retval, int index, int numparams, cell params[]) -{ - return amx_Exec(amx, retval, index, numparams<<16, params); -} - #endif /* AMX_EXEC || AMX_INIT */ #if defined AMX_SETCALLBACK @@ -3794,7 +3598,6 @@ int AMXAPI amx_SetCallback(AMX *amx,AMX_CALLBACK callback) int AMXAPI amx_SetDebugHook(AMX *amx,AMX_DEBUG debug) { assert(amx!=NULL); - assert(debug!=NULL); amx->debug=debug; return AMX_ERR_NONE; } @@ -3822,7 +3625,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr) data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; assert(phys_addr!=NULL); - if ((amx_addr>=amx->hea && amx_addrstk) || amx_addr<0 || amx_addr>=amx->stp) { + if (amx_addr>=amx->hea && amx_addrstk || amx_addr<0 || amx_addr>=amx->stp) { *phys_addr=NULL; return AMX_ERR_MEMACCESS; } /* if */ @@ -3832,7 +3635,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr) } #endif /* AMX_GETADDR */ -#if defined AMX_ALLOT +#if defined AMX_ALLOT || defined AMX_EXEC int AMXAPI amx_Allot(AMX *amx,int cells,cell *amx_addr,cell **phys_addr) { AMX_HEADER *hdr; @@ -3862,22 +3665,25 @@ int AMXAPI amx_Release(AMX *amx,cell amx_addr) } #endif /* AMX_ALLOT */ -#if defined AMX_XXXSTRING +#if defined AMX_XXXSTRING || defined AMX_UTF8XXX #define CHARBITS (8*sizeof(char)) -#if SMALL_CELL_SIZE==16 +#if PAWN_CELL_SIZE==16 #define CHARMASK (0xffffu << 8*(2-sizeof(char))) -#elif SMALL_CELL_SIZE==32 +#elif PAWN_CELL_SIZE==32 #define CHARMASK (0xffffffffuL << 8*(4-sizeof(char))) -#elif SMALL_CELL_SIZE==64 +#elif PAWN_CELL_SIZE==64 #define CHARMASK (0xffffffffffffffffuLL << 8*(8-sizeof(char))) #else #error Unsupported cell size #endif -int AMXAPI amx_StrLen(cell *cstr, int *length) +int AMXAPI amx_StrLen(const cell *cstr, int *length) { int len; + #if BYTE_ORDER==LITTLE_ENDIAN + cell c; + #endif assert(length!=NULL); if (cstr==NULL) { @@ -3889,16 +3695,16 @@ int AMXAPI amx_StrLen(cell *cstr, int *length) /* packed string */ assert(sizeof(char)==1); len=strlen((char *)cstr); /* find '\0' */ - init_little_endian(); - if (amx_LittleEndian) { + assert(check_endian()); + #if BYTE_ORDER==LITTLE_ENDIAN /* on Little Endian machines, toggle the last bytes */ - cell c=cstr[len/sizeof(cell)]; /* get last cell */ + c=cstr[len/sizeof(cell)]; /* get last cell */ len=len - len % sizeof(cell); /* len = multiple of "cell" bytes */ while ((c & CHARMASK)!=0) { len++; c <<= 8*sizeof(char); } /* if */ - } /* if */ + #endif } else { for (len=0; cstr[len]!=0; len++) /* nothing */; @@ -3906,72 +3712,112 @@ int AMXAPI amx_StrLen(cell *cstr, int *length) *length = len; return AMX_ERR_NONE; } +#endif -int AMXAPI amx_SetString(cell *dest,const char *source,int pack,int use_wchar) +#if defined AMX_XXXSTRING || defined AMX_EXEC +int AMXAPI amx_SetString(cell *dest,const char *source,int pack,int use_wchar,size_t size) { /* the memory blocks should not overlap */ - int len= use_wchar ? wcslen((const wchar_t*)source) : strlen(source); - int i; + int len, i; + + assert(UNLIMITED>0); + #if defined AMX_ANSIONLY + (void)use_wchar; + len=strlen(source); + #else + len= use_wchar ? wcslen((const wchar_t*)source) : strlen(source); + #endif if (pack) { /* create a packed string */ + if (size=size*sizeof(cell)) + len=size*sizeof(cell)-1; dest[len/sizeof(cell)]=0; /* clear last bytes of last (semi-filled) cell*/ - if (use_wchar) { - for (i=0; i=0) swapcell((ucell *)&dest[len--]); - } /* if */ + #endif + } else { /* create an unpacked string */ - if (use_wchar) { - for (i=0; i=size) + len=size-1; + #if defined AMX_ANSIONLY for (i=0; iUNPACKEDMAX) { /* source string is packed */ cell c = 0; /* to avoid a compiler warning */ int i=sizeof(cell)-1; - for ( ;; ) { + while ((size_t)len> i*CHARBITS); - else + #if defined AMX_ANSIONLY dest[len++]=(char)(c >> i*CHARBITS); + #else + if (use_wchar) + ((wchar_t*)dest)[len++]=(char)(c >> i*CHARBITS); + else + dest[len++]=(char)(c >> i*CHARBITS); + #endif if (dest[len-1]=='\0') break; /* terminating zero character found */ i=(i+sizeof(cell)-1) % sizeof(cell); } /* for */ } else { /* source string is unpacked */ - if (use_wchar) { - while (*source!=0) - ((wchar_t*)dest)[len++]=(wchar_t)*source++; - } else { - while (*source!=0) + #if defined AMX_ANSIONLY + while (*source!=0 && (size_t)len=size) + len=size-1; + if (len>=0) + dest[len]='\0'; /* store terminator */ return AMX_ERR_NONE; } #endif /* AMX_XXXSTRING */ @@ -3989,8 +3835,8 @@ int AMXAPI amx_GetString(char *dest,const cell *source,int use_wchar) */ int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value) { -static char utf8_count[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4 }; -static long utf8_lowmark[5] = { 0x80, 0x800, 0x10000, 0x200000, 0x4000000 }; +static const char utf8_count[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4 }; +static const long utf8_lowmark[5] = { 0x80, 0x800, 0x10000L, 0x200000L, 0x4000000L }; unsigned char c; cell result; int followup; @@ -4028,19 +3874,19 @@ static long utf8_lowmark[5] = { 0x80, 0x800, 0x10000, 0x200000, 0x4000000 }; switch (followup) { case 4: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); + result = (result << 6) | c & 0x3f; case 3: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); + result = (result << 6) | c & 0x3f; case 2: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); + result = (result << 6) | c & 0x3f; case 1: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); + result = (result << 6) | c & 0x3f; case 0: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); + result = (result << 6) | c & 0x3f; } /* switch */ /* Do additional checks: shortest encoding & reserved positions. The * lowmark limits also depends on the code length; it can be read from @@ -4048,7 +3894,7 @@ static long utf8_lowmark[5] = { 0x80, 0x800, 0x10000, 0x200000, 0x4000000 }; */ if (result=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff) + if (result>=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff) goto error; } /* if */ @@ -4064,9 +3910,9 @@ error: } /* amx_UTF8Put() - * Encode a single character into a character string. The character may be - * up to 6 bytes long. The function returns an error code if "maxchars" is - * lower than the requried number of characters; in this case nothing is + * Encode a single character into a byte string. The character may result in + * a string of up to 6 bytes. The function returns an error code if "maxchars" + * is lower than the required number of characters; in this case nothing is * stored. * The function does not zero-terminate the string. */ @@ -4083,40 +3929,40 @@ int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value) } else if (value<0x800) { /* 110xxxxx 10xxxxxx */ if (maxchars < 2) goto error; - *string++ = (char)(((value>>6) & 0x1f) | 0xc0); - *string++ = (char)((value & 0x3f) | 0x80); + *string++ = (char)((value>>6) & 0x1f | 0xc0); + *string++ = (char)(value & 0x3f | 0x80); } else if (value<0x10000) { /* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */ if (maxchars < 3) goto error; - if ((value>=0xd800 && value<=0xdfff) || value==0xfffe || value==0xffff) + if (value>=0xd800 && value<=0xdfff || value==0xfffe || value==0xffff) goto error; /* surrogate pairs and invalid characters */ - *string++ = (char)(((value>>12) & 0x0f) | 0xe0); - *string++ = (char)(((value>>6) & 0x3f) | 0x80); - *string++ = (char)((value & 0x3f) | 0x80); + *string++ = (char)((value>>12) & 0x0f | 0xe0); + *string++ = (char)((value>>6) & 0x3f | 0x80); + *string++ = (char)(value & 0x3f | 0x80); } else if (value<0x200000) { /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (maxchars < 4) goto error; - *string++ = (char)(((value>>18) & 0x07) | 0xf0); - *string++ = (char)(((value>>12) & 0x3f) | 0x80); - *string++ = (char)(((value>>6) & 0x3f) | 0x80); - *string++ = (char)((value & 0x3f) | 0x80); + *string++ = (char)((value>>18) & 0x07 | 0xf0); + *string++ = (char)((value>>12) & 0x3f | 0x80); + *string++ = (char)((value>>6) & 0x3f | 0x80); + *string++ = (char)(value & 0x3f | 0x80); } else if (value<0x4000000) { /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (maxchars < 5) goto error; - *string++ = (char)(((value>>24) & 0x03) | 0xf8); - *string++ = (char)(((value>>18) & 0x3f) | 0x80); - *string++ = (char)(((value>>12) & 0x3f) | 0x80); - *string++ = (char)(((value>>6) & 0x3f) | 0x80); - *string++ = (char)((value & 0x3f) | 0x80); + *string++ = (char)((value>>24) & 0x03 | 0xf8); + *string++ = (char)((value>>18) & 0x3f | 0x80); + *string++ = (char)((value>>12) & 0x3f | 0x80); + *string++ = (char)((value>>6) & 0x3f | 0x80); + *string++ = (char)(value & 0x3f | 0x80); } else { /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (31 bits) */ if (maxchars < 6) goto error; - *string++ = (char)(((value>>30) & 0x01) | 0xfc); - *string++ = (char)(((value>>24) & 0x3f) | 0x80); - *string++ = (char)(((value>>18) & 0x3f) | 0x80); - *string++ = (char)(((value>>12) & 0x3f) | 0x80); - *string++ = (char)(((value>>6) & 0x3f) | 0x80); - *string++ = (char)((value & 0x3f) | 0x80); + *string++ = (char)((value>>30) & 0x01 | 0xfc); + *string++ = (char)((value>>24) & 0x3f | 0x80); + *string++ = (char)((value>>18) & 0x3f | 0x80); + *string++ = (char)((value>>12) & 0x3f | 0x80); + *string++ = (char)((value>>6) & 0x3f | 0x80); + *string++ = (char)(value & 0x3f | 0x80); } /* if */ if (endptr!=NULL) @@ -4132,11 +3978,40 @@ error: * encoding. The function returns an error code, it is AMX_ERR_NONE if the * string is valid UTF-8 (or valid ASCII for that matter). */ -int AMXAPI amx_UTF8Check(const char *string) +int AMXAPI amx_UTF8Check(const char *string, int *length) { int err=AMX_ERR_NONE; - while (err==AMX_ERR_NONE && *string!='\0') + int len=0; + while (err==AMX_ERR_NONE && *string!='\0') { err=amx_UTF8Get(string,&string,NULL); + len++; + } /* while */ + if (length!=NULL) + *length=len; + return err; +} + +/* amx_UTF8Len() + * Run through a wide string and return how many 8-bit characters are needed to + * store the string in UTF-8 format. The returned cound excludes the terminating + * zero byte. The function returns an error code. + */ +int AMXAPI amx_UTF8Len(const cell *cstr, int *length) +{ + int err; + + assert(length!=NULL); + err=amx_StrLen(cstr, length); + if (err==AMX_ERR_NONE && (ucell)*cstr<=UNPACKEDMAX) { + char buffer[10]; /* maximum UTF-8 code is 6 characters */ + char *endptr; + int len=*length, count=0; + while (len-->0) { + amx_UTF8Put(buffer, &endptr, sizeof buffer, *cstr++); + count+=(int)(endptr-buffer); + } /* while */ + *length=count; + } /* while */ return err; } #endif /* AMX_UTF8XXX */ @@ -4163,3 +4038,74 @@ const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len) return buffer; } + +int AMXAPI amx_SetStringOld(cell *dest,const char *source,int pack,int use_wchar) +{ /* the memory blocks should not overlap */ + int len= use_wchar ? wcslen((const wchar_t*)source) : strlen(source); + int i; + if (pack) { + //FOR AMX MOD X WE DON'T CARE ABOUT PACKING +#if 0 + /* create a packed string */ + dest[len/sizeof(cell)]=0; /* clear last bytes of last (semi-filled) cell*/ + if (use_wchar) { + for (i=0; i=0) + swapcell((ucell *)&dest[len--]); + } /* if */ +#endif + } else { + /* create an unpacked string */ + if (use_wchar) { + for (i=0; iUNPACKEDMAX) { + /* source string is packed */ + cell c = 0; /* to avoid a compiler warning */ + int i=sizeof(cell)-1; + for ( ;; ) { + if (i==sizeof(cell)-1) + c=*source++; + if (use_wchar) + ((wchar_t*)dest)[len++]=(char)(c >> i*CHARBITS); + else + dest[len++]=(char)(c >> i*CHARBITS); + if (dest[len-1]=='\0') + break; /* terminating zero character found */ + i=(i+sizeof(cell)-1) % sizeof(cell); + } /* for */ + } else { + /* source string is unpacked */ + if (use_wchar) { + while (*source!=0) + ((wchar_t*)dest)[len++]=(wchar_t)*source++; + } else { + while (*source!=0) + dest[len++]=(char)*source++; + } /* if */ + } /* if */ + dest[len]='\0'; /* store terminator */ + return AMX_ERR_NONE; +} diff --git a/amxmodx/amx.h b/amxmodx/amx.h index 1ec389b5..480e75bf 100755 --- a/amxmodx/amx.h +++ b/amxmodx/amx.h @@ -1,6 +1,6 @@ -/* Abstract Machine for the Small compiler +/* Pawn Abstract Machine (for the Pawn language) * - * Copyright (c) ITB CompuPhase, 1997-2004 + * Copyright (c) ITB CompuPhase, 1997-2005 * * This software is provided "as-is", without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -21,54 +21,98 @@ * Version: $Id$ */ -#if defined __linux__ +#if defined FREEBSD && !defined __FreeBSD__ + #define __FreeBSD__ +#endif +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ #include #endif #ifndef AMX_H_INCLUDED #define AMX_H_INCLUDED -#if defined __LCC__ || defined __DMC__ || defined __linux__ +#if defined HAVE_STDINT_H #include -#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L - /* The ISO C99 defines the int16_t and int_32t types. If the compiler got - * here, these types are probably undefined. - */ - #if defined __FreeBSD__ - #include - #else - typedef short int int16_t; - typedef unsigned short int uint16_t; - #if defined SN_TARGET_PS2 - typedef int int32_t; - typedef unsigned int uint32_t; +#else + #if defined __LCC__ || defined __DMC__ || defined LINUX + #if defined HAVE_INTTYPES_H + #include #else - typedef long int int32_t; - typedef unsigned long int uint32_t; + #include #endif - // evilspy's fix for mingw - #if defined __GNUC__ - typedef long long int64_t; - typedef unsigned long long uint64_t; - #define HAVE_I64 - #elif defined __WIN32__ || defined _WIN32 || defined WIN32 - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - #define HAVE_I64 + #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* The ISO C99 defines the int16_t and int_32t types. If the compiler got + * here, these types are probably undefined. + */ + #if defined __MACH__ + #include + typedef unsigned short int uint16_t; + typedef unsigned long int uint32_t; + #elif defined __FreeBSD__ + #include + #else + typedef short int int16_t; + typedef unsigned short int uint16_t; + #if defined SN_TARGET_PS2 + typedef int int32_t; + typedef unsigned int uint32_t; + #else + typedef long int int32_t; + typedef unsigned long int uint32_t; + #endif + #if defined __WIN32__ || defined _WIN32 || defined WIN32 + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #define HAVE_I64 + #elif defined __GNUC__ + typedef long long int64_t; + typedef unsigned long long uint64_t; + #define HAVE_I64 + #endif #endif #endif + #define HAVE_STDINT_H +#endif +#if defined _LP64 || defined WIN64 || defined _WIN64 + #if !defined __64BIT__ + #define __64BIT__ + #endif #endif +#if HAVE_ALLOCA_H + #include +#endif #if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */ #if !defined alloca #define alloca(n) _alloca(n) #endif #endif +#if !defined arraysize + #define arraysize(array) (sizeof(array) / sizeof((array)[0])) +#endif + #ifdef __cplusplus extern "C" { #endif +#if PAWN_CELL_SIZE==32 + #define REAL float +#elif PAWN_CELL_SIZE==64 + #define REAL double +#else + #error Unsupported cell size +#endif + +#if defined PAWN_DLL + #if !defined AMX_NATIVE_CALL + #define AMX_NATIVE_CALL __stdcall + #endif + #if !defined AMXAPI + #define AMXAPI __stdcall + #endif +#endif + /* calling convention for native functions */ #if !defined AMX_NATIVE_CALL #define AMX_NATIVE_CALL @@ -79,6 +123,8 @@ extern "C" { #define AMXAPI __stdcall #elif defined CDECL #define AMXAPI __cdecl + #elif defined GCC_HASCLASSVISIBILITY + #define AMXAPI __attribute__ ((visibility("default"))) #else #define AMXAPI #endif @@ -96,46 +142,36 @@ extern "C" { * 5 (tagnames table) 4 * 6 (reformatted header) 6 * 7 (name table, opcodes SYMTAG & SYSREQ.D) 7 + * 8 (opcode STMT, renewed debug interface) 8 */ -#define CUR_FILE_VERSION 7 /* current file version; also the current AMX version */ +#define CUR_FILE_VERSION 8 /* current file version; also the current AMX version */ #define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */ -#define MIN_AMX_VERSION 7 /* minimum AMX version needed to support the current file format */ +#define MIN_AMX_VERSION 8 /* minimum AMX version needed to support the current file format */ -#if defined BIT16 - #define SMALL_CELL_SIZE 16 /* for backward compatibility */ +#if !defined PAWN_CELL_SIZE + #define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */ #endif -#if !defined SMALL_CELL_SIZE - #define SMALL_CELL_SIZE 32 /* by default, use 32-bit cells */ -#endif -#if SMALL_CELL_SIZE==16 +#if PAWN_CELL_SIZE==16 typedef uint16_t ucell; typedef int16_t cell; -#elif SMALL_CELL_SIZE==32 +#elif PAWN_CELL_SIZE==32 typedef uint32_t ucell; typedef int32_t cell; -#elif SMALL_CELL_SIZE==64 +#elif PAWN_CELL_SIZE==64 typedef uint64_t ucell; typedef int64_t cell; #else - #error Unsupported cell size (SMALL_CELL_SIZE) + #error Unsupported cell size (PAWN_CELL_SIZE) #endif -#if SMALL_CELL_SIZE==32 - #define REAL float -#elif SMALL_CELL_SIZE==64 - #define REAL double -#else - #error Unsupported cell size -#endif - -#define UNPACKEDMAX ((1 << (sizeof(cell)-1)*8) - 1) +#define UNPACKEDMAX ((1L << (sizeof(cell)-1)*8) - 1) +#define UNLIMITED (~1u >> 1) struct tagAMX; typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params); typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index, cell *result, cell *params); typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx); -typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode); #if !defined _FAR #define _FAR #endif @@ -149,7 +185,7 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode); /* Some compilers do not support the #pragma align, which should be fine. Some * compilers give a warning on unknown #pragmas, which is not so fine... */ -#if defined SN_TARGET_PS2 || defined __GNUC__ +#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN #define AMX_NO_ALIGN #endif @@ -160,8 +196,10 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode); #endif #if !defined AMX_NO_ALIGN - #if defined __linux__ + #if defined LINUX || defined __FreeBSD__ #pragma pack(1) /* structures must be packed (byte-aligned) */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=mac68k #else #pragma pack(push) #pragma pack(1) /* structures must be packed (byte-aligned) */ @@ -171,25 +209,30 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode); #endif #endif -typedef struct { +typedef struct tagAMX_NATIVE_INFO { const char _FAR *name PACKED; AMX_NATIVE func PACKED; -} AMX_NATIVE_INFO; +} PACKED AMX_NATIVE_INFO; #define AMX_USERNUM 4 #define sEXPMAX 19 /* maximum name length for file version <= 6 */ #define sNAMEMAX 31 /* maximum name length of symbol name */ typedef struct tagAMX_FUNCSTUB { - ucell address PACKED; - const char name[sEXPMAX+1] PACKED; -} AMX_FUNCSTUB; + ucell address PACKED; + char name[sEXPMAX+1] PACKED; +} PACKED AMX_FUNCSTUB; + +typedef struct tagFUNCSTUBNT { + ucell address PACKED; + ucell nameofs PACKED; //we need this for amxx to be backwards comaptible +} PACKED AMX_FUNCSTUBNT; /* The AMX structure is the internal structure for many functions. Not all * fields are valid at all times; many fields are cached in local variables. */ typedef struct tagAMX { - unsigned char _FAR *base PACKED; /* points to the AMX header ("amxhdr") plus the code, optionally also the data */ + unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */ unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */ AMX_CALLBACK callback PACKED; AMX_DEBUG debug PACKED; /* debug callback */ @@ -201,28 +244,23 @@ typedef struct tagAMX { cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */ cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */ int flags PACKED; /* current status, see amx_Flags() */ - /* for assertions and debug hook */ - cell curline PACKED; - cell curfile PACKED; - int dbgcode PACKED; - cell dbgaddr PACKED; - cell dbgparam PACKED; - char _FAR *dbgname PACKED; /* user data */ long usertags[AMX_USERNUM] PACKED; void _FAR *userdata[AMX_USERNUM] PACKED; /* native functions can raise an error */ int error PACKED; + /* passing parameters requires a "count" field */ + int paramcount; /* the sleep opcode needs to store the full AMX status */ cell pri PACKED; cell alt PACKED; cell reset_stk PACKED; cell reset_hea PACKED; cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */ - /* support variables for the JIT */ + /* support variables for the JIT */ int reloc_size PACKED; /* required temporary buffer for relocations */ long code_size PACKED; /* estimated memory footprint of the native code */ -} AMX; +} PACKED AMX; /* The AMX_HEADER structure is both the memory format as the file format. The * structure is used internaly. @@ -244,26 +282,11 @@ typedef struct tagAMX_HEADER { int32_t libraries PACKED; /* offset to the table of libraries */ int32_t pubvars PACKED; /* the "public variables" table */ int32_t tags PACKED; /* the "public tagnames" table */ - int32_t nametable PACKED; /* name table, file version 7 only */ -} AMX_HEADER PACKED; -#define AMX_MAGIC 0xf1e0 + int32_t nametable PACKED; /* name table */ +} PACKED AMX_HEADER; -//double linked list for stack -typedef struct tagAMX_TRACE -{ - cell line PACKED; - cell file PACKED; - struct tagAMX_TRACE *next PACKED; - struct tagAMX_TRACE *prev PACKED; -} AMX_TRACE PACKED; - -typedef struct tagAMX_DBG -{ - int32_t numFiles PACKED; /* number of chars in array */ - char **files PACKED; /* array of files */ - AMX_TRACE *head PACKED; /* begin of link list */ - AMX_TRACE *tail PACKED; /* end of link list */ -} AMX_DBG PACKED; +//This is always the same for us +#define AMX_MAGIC 0xf1e0 enum { AMX_ERR_NONE, @@ -280,6 +303,7 @@ enum { AMX_ERR_NATIVE, /* native function failed */ AMX_ERR_DIVIDE, /* divide by zero */ AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */ + AMX_ERR_INVSTATE, /* invalid state for this access */ AMX_ERR_MEMORY = 16, /* out of memory */ AMX_ERR_FORMAT, /* invalid file format */ @@ -292,29 +316,17 @@ enum { AMX_ERR_INIT_JIT, /* cannot initialize the JIT */ AMX_ERR_PARAMS, /* parameter error */ AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */ -}; - -enum { - DBG_INIT, /* query/initialize */ - DBG_FILE, /* file number in curfile, filename in name */ - DBG_LINE, /* line number in curline, file number in curfile */ - DBG_SYMBOL, /* address in dbgaddr, class/type in dbgparam */ - DBG_CLRSYM, /* stack address below which locals should be removed. stack address in stk */ - DBG_CALL, /* function call, address jumped to in dbgaddr */ - DBG_RETURN, /* function returns */ - DBG_TERMINATE, /* program ends, code address in dbgaddr, reason in dbgparam */ - DBG_SRANGE, /* symbol size and dimensions (arrays); level in dbgaddr (!); length in dbgparam */ - DBG_SYMTAG, /* tag of the most recent symbol (if non-zero), tag in dbgparam */ + AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */ }; /* AMX_FLAG_CHAR16 0x01 no longer used */ #define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */ #define AMX_FLAG_COMPACT 0x04 /* compact encoding */ -#define AMX_FLAG_BIGENDIAN 0x08 /* big endian encoding */ -#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking */ -#define AMX_FLAG_LINEOPS 0x20 /* line ops are parsed by the JIT [loadtime only flag] */ -#define AMX_FLAG_TRACED 0x40 /* the file has already been traced */ -#define AMX_FLAG_BROWSE 0x4000 /* browsing/relocating or executing */ +#define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */ +#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */ +#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */ +#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */ +#define AMX_FLAG_BROWSE 0x4000 /* busy browsing */ #define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */ #define AMX_EXEC_MAIN -1 /* start at program entry point */ @@ -322,16 +334,18 @@ enum { #define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24)) -#define AMX_EXPANDMARGIN 64 +#if !defined AMX_COMPACTMARGIN + #define AMX_COMPACTMARGIN 64 +#endif /* for native functions that use floating point parameters, the following * two macros are convenient for casting a "cell" into a "float" type _without_ * changing the bit pattern */ -#if SMALL_CELL_SIZE==32 +#if PAWN_CELL_SIZE==32 #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */ -#elif SMALL_CELL_SIZE==64 +#elif PAWN_CELL_SIZE==64 #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ #define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */ #else @@ -345,7 +359,7 @@ enum { amx_StrLen(amx_cstr_, &amx_length_); \ if (amx_length_ > 0 && \ ((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \ - amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1); \ + amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_); \ else (result) = NULL; \ } while (0) @@ -354,23 +368,11 @@ uint32_t * AMXAPI amx_Align32(uint32_t *v); #if defined _I64_MAX || defined HAVE_I64 uint64_t * AMXAPI amx_Align64(uint64_t *v); #endif - -#if SMALL_CELL_SIZE==32 -#define amx_AlignCell amx_Align32 -#elif SMALL_CELL_SIZE==64 -#define amx_AlignCell amx_Align64 -#else -#error Unsupported cell size -#endif - int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr); int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params); int AMXAPI amx_Cleanup(AMX *amx); int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data); -int AMXAPI amx_Debug(AMX *amx); /* default debug procedure, does nothing */ -int AMXAPI amx_DebugCall(AMX *amx, int mode); -int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...); -int AMXAPI amx_Execv(AMX *amx, cell *retval, int index, int numparams, cell params[]); +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index); int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index); int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index); int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr); @@ -380,37 +382,56 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr); int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname); int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname); int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr); -int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar); +int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size); int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id); int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr); int AMXAPI amx_Init(AMX *amx, void *program); int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code); int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap); int AMXAPI amx_NameLength(AMX *amx, int *length); -AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name,AMX_NATIVE func); +AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func); int AMXAPI amx_NumNatives(AMX *amx, int *number); int AMXAPI amx_NumPublics(AMX *amx, int *number); int AMXAPI amx_NumPubVars(AMX *amx, int *number); int AMXAPI amx_NumTags(AMX *amx, int *number); +int AMXAPI amx_Push(AMX *amx, cell value); +int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells); +int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar); int AMXAPI amx_RaiseError(AMX *amx, int error); -int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number); +int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number); int AMXAPI amx_Release(AMX *amx, cell amx_addr); int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug); -int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar); +int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size); int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr); -int AMXAPI amx_StrLen(cell *cstring, int *length); +int AMXAPI amx_StrLen(const cell *cstring, int *length); +int AMXAPI amx_UTF8Check(const char *string, int *length); int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value); +int AMXAPI amx_UTF8Len(const cell *cstr, int *length); int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); -int AMXAPI amx_UTF8Check(const char *string); int AMXAPI amx_GetLibraries(AMX *amx); const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len); +int AMXAPI amx_SetStringOld(cell *dest,const char *source,int pack,int use_wchar); +int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar); -//no longer used! void amx_NullNativeTable(AMX *amx); +#if PAWN_CELL_SIZE==16 + #define amx_AlignCell(v) amx_Align16(v) +#elif PAWN_CELL_SIZE==32 + #define amx_AlignCell(v) amx_Align32(v) +#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) + #define amx_AlignCell(v) amx_Align64(v) +#else + #error Unsupported cell size +#endif + +#define amx_RegisterFunc(amx, name, func) \ + amx_Register((amx), amx_NativeInfo((name),(func)), 1); #if !defined AMX_NO_ALIGN - #if defined __linux__ + #if defined LINUX || defined __FreeBSD__ #pragma pack() /* reset default packing */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=reset #else #pragma pack(pop) /* reset previous packing */ #endif diff --git a/amxmodx/amxcore.cpp b/amxmodx/amxcore.cpp index fbbf2cad..a708bfff 100755 --- a/amxmodx/amxcore.cpp +++ b/amxmodx/amxcore.cpp @@ -1,6 +1,6 @@ -/* Core module for the Small AMX +/* Core module for the Pawn AMX * - * Copyright (c) ITB CompuPhase, 1997-2004 + * Copyright (c) ITB CompuPhase, 1997-2005 * * This software is provided "as-is", without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -34,14 +34,7 @@ #include #include #include - -// this file does not include amxmodx.h, so we have to include the memory manager here -#ifdef MEMORY_TEST -#include "mmgr/mmgr.h" -#endif // MEMORY_TEST - #include "amx.h" - #if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows #include #endif @@ -60,14 +53,13 @@ # define _tcscpy strcpy # define _tcsdup strdup # define _tcslen strlen -# define _stprintf sprintf #endif #define CHARBITS (8*sizeof(char)) typedef unsigned char uchar; -#if !defined NOPROPLIST +#if !defined AMX_NOPROPLIST typedef struct _property_list { struct _property_list *next; cell id; @@ -76,7 +68,7 @@ typedef struct _property_list { //??? safe AMX (owner of the property) } proplist; -static proplist proproot = { NULL }; +static proplist proproot = { NULL, 0, NULL, 0 }; static proplist *list_additem(proplist *root) { @@ -142,15 +134,13 @@ static proplist *list_finditem(proplist *root,cell id,char *name,cell value, } #endif -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL numargs(AMX *amx, cell *params) { AMX_HEADER *hdr; uchar *data; cell bytes; + (void)params; hdr=(AMX_HEADER *)amx->base; data=amx->data ? amx->data : amx->base+(int)hdr->dat; /* the number of bytes is on the stack, at "frm + 2*cell" */ @@ -190,18 +180,16 @@ static cell AMX_NATIVE_CALL setarg(AMX *amx, cell *params) /* adjust the address in "value" in case of an array access */ value+=params[2]*sizeof(cell); /* verify the address */ - if (value<0 || (value>=amx->hea && valuestk)) + if (value<0 || value>=amx->hea && valuestk) return 0; /* set the value indirectly */ * (cell *)(data+(int)value) = params[3]; return 1; } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL heapspace(AMX *amx,cell *params) { + (void)params; return amx->stk - amx->hea; } @@ -220,142 +208,22 @@ static cell AMX_NATIVE_CALL funcidx(AMX *amx,cell *params) return 0; } /* if */ - amx_GetString(name,cstr,0); + amx_GetString(name,cstr,0,UNLIMITED); err=amx_FindPublic(amx,name,&index); if (err!=AMX_ERR_NONE) index=-1; /* this is not considered a fatal error */ return index; } -int amx_StrPack(cell *dest,cell *source) -{ - int len; - - amx_StrLen(source,&len); - if ((ucell)*source>UNPACKEDMAX) { - /* source string is already packed */ - while (len >= 0) { - *dest++ = *source++; - len-=sizeof(cell); - } /* while */ - } else { - /* pack string, from bottom up */ - cell c; - int i; - for (c=0,i=0; iUNPACKEDMAX) { - /* unpack string, from top down (so string can be unpacked in place) */ - cell c; - int i,len; - amx_StrLen(source,&len); - dest[len]=0; - for (i=len-1; i>=0; i--) { - c=source[i/sizeof(cell)] >> (sizeof(cell)-i%sizeof(cell)-1)*CHARBITS; - dest[i]=c & UCHAR_MAX; - } /* for */ - } else { - /* source string is already unpacked */ - while ((*dest++ = *source++) != 0) - /* nothing */; - } /* if */ - return AMX_ERR_NONE; -} - -static int verify_addr(AMX *amx,cell addr) -{ - int err; - cell *cdest; - - err=amx_GetAddr(amx,addr,&cdest); - if (err!=AMX_ERR_NONE) - amx_RaiseError(amx,err); - return err; -} - -static cell AMX_NATIVE_CALL core_strlen(AMX *amx,cell *params) -{ - cell *cptr; - int len = 0; - - if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE) - amx_StrLen(cptr,&len); - return len; -} - -static cell AMX_NATIVE_CALL strpack(AMX *amx,cell *params) -{ - cell *cdest,*csrc; - int len,needed,err; - size_t lastaddr; - - /* calculate number of cells needed for (packed) destination */ - amx_GetAddr(amx,params[2],&csrc); - amx_StrLen(csrc,&len); - needed=(len+sizeof(cell))/sizeof(cell); /* # of cells needed */ - assert(needed>0); - lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1); - if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE) - return 0; - - amx_GetAddr(amx,params[1],&cdest); - err=amx_StrPack(cdest,csrc); - if (err!=AMX_ERR_NONE) - return amx_RaiseError(amx,err); - - return len; -} - -static cell AMX_NATIVE_CALL strunpack(AMX *amx,cell *params) -{ - cell *cdest,*csrc; - int len,err; - size_t lastaddr; - - /* calculate number of cells needed for (packed) destination */ - amx_GetAddr(amx,params[2],&csrc); - amx_StrLen(csrc,&len); - assert(len>=0); - lastaddr=(size_t)(params[1]+sizeof(cell)*(len+1)-1); - if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE) - return 0; - - amx_GetAddr(amx,params[1],&cdest); - err=amx_StrUnpack(cdest,csrc); - if (err!=AMX_ERR_NONE) - return amx_RaiseError(amx,err); - - return len; -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params) { union { cell c; - #if SMALL_CELL_SIZE==16 + #if PAWN_CELL_SIZE==16 uchar b[2]; - #elif SMALL_CELL_SIZE==32 + #elif PAWN_CELL_SIZE==32 uchar b[4]; - #elif SMALL_CELL_SIZE==64 + #elif PAWN_CELL_SIZE==64 uchar b[8]; #else #error Unsupported cell size @@ -363,20 +231,21 @@ static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params) } value; uchar t; + (void)amx; assert((size_t)params[0]==sizeof(cell)); value.c = params[1]; - #if SMALL_CELL_SIZE==16 + #if PAWN_CELL_SIZE==16 t = value.b[0]; value.b[0] = value.b[1]; value.b[1] = t; - #elif SMALL_CELL_SIZE==32 + #elif PAWN_CELL_SIZE==32 t = value.b[0]; value.b[0] = value.b[3]; value.b[3] = t; t = value.b[1]; value.b[1] = value.b[2]; value.b[2] = t; - #elif SMALL_CELL_SIZE==64 + #elif PAWN_CELL_SIZE==64 t = value.b[0]; value.b[0] = value.b[7]; value.b[7] = t; @@ -395,11 +264,9 @@ static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params) return value.c; } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params) { + (void)amx; #if defined __WIN32__ || defined _WIN32 || defined WIN32 return (cell)CharLower((LPTSTR)params[1]); #elif defined _Windows @@ -409,11 +276,9 @@ static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params) #endif } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params) { + (void)amx; #if defined __WIN32__ || defined _WIN32 || defined WIN32 return (cell)CharUpper((LPTSTR)params[1]); #elif defined _Windows @@ -423,19 +288,15 @@ static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params) #endif } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL core_min(AMX *amx,cell *params) { + (void)amx; return params[1] <= params[2] ? params[1] : params[2]; } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif static cell AMX_NATIVE_CALL core_max(AMX *amx,cell *params) { + (void)amx; return params[1] >= params[2] ? params[1] : params[2]; } @@ -451,7 +312,7 @@ static cell AMX_NATIVE_CALL core_clamp(AMX *amx,cell *params) return value; } -#if !defined NOPROPLIST +#if !defined AMX_NOPROPLIST static char *MakePackedString(cell *cptr) { int len; @@ -459,10 +320,21 @@ static char *MakePackedString(cell *cptr) amx_StrLen(cptr,&len); dest=(char *)malloc(len+sizeof(cell)); - amx_GetString(dest,cptr,0); + amx_GetString(dest,cptr,0,UNLIMITED); return dest; } +static int verify_addr(AMX *amx,cell addr) +{ + int err; + cell *cdest; + + err=amx_GetAddr(amx,addr,&cdest); + if (err!=AMX_ERR_NONE) + amx_RaiseError(amx,err); + return err; +} + static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params) { cell *cstr; @@ -480,7 +352,7 @@ static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params) return 0; } /* if */ amx_GetAddr(amx,params[4],&cstr); - amx_SetString(cstr,item->name,1,0); + amx_SetString(cstr,item->name,1,0,UNLIMITED); } /* if */ free(name); return (item!=NULL) ? item->value : 0; @@ -545,12 +417,14 @@ static cell AMX_NATIVE_CALL existproperty(AMX *amx,cell *params) } #endif +#if !defined AMX_NORANDOM /* This routine comes from the book "Inner Loops" by Rick Booth, Addison-Wesley * (ISBN 0-201-47960-5). This is a "multiplicative congruential random number * generator" that has been extended to 31-bits (the standard C version returns * only 15-bits). */ -static unsigned long IL_StandardRandom_seed = 0L; +#define INITIAL_SEED 0xcaa938dbL +static unsigned long IL_StandardRandom_seed = INITIAL_SEED; /* always use a non-zero seed */ #define IL_RMULT 1103515245L #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused @@ -562,7 +436,7 @@ static cell AMX_NATIVE_CALL core_random(AMX *amx,cell *params) /* one-time initialization (or, mostly one-time) */ #if !defined SN_TARGET_PS2 && !defined _WIN32_WCE - if (IL_StandardRandom_seed == 0L) + if (IL_StandardRandom_seed == INITIAL_SEED) IL_StandardRandom_seed=(unsigned long)time(NULL); #endif @@ -579,6 +453,7 @@ static cell AMX_NATIVE_CALL core_random(AMX *amx,cell *params) result %= params[1]; return (cell)result; } +#endif AMX_NATIVE_INFO core_Natives[] = { @@ -587,22 +462,13 @@ AMX_NATIVE_INFO core_Natives[] = { { "setarg", setarg }, { "heapspace", heapspace }, { "funcidx", funcidx }, - { "strlen", core_strlen }, - { "strpack", strpack }, - { "strunpack", strunpack }, { "swapchars", swapchars }, { "tolower", core_tolower }, { "toupper", core_toupper }, - { "random", core_random }, { "min", core_min }, { "max", core_max }, { "clamp", core_clamp }, -#if !defined NOPROPLIST - { "getproperty", getproperty }, - { "setproperty", setproperty }, - { "deleteproperty",delproperty }, - { "existproperty", existproperty }, -#endif + { "random", core_random }, { NULL, NULL } /* terminator */ }; @@ -611,12 +477,10 @@ int AMXEXPORT amx_CoreInit(AMX *amx) return amx_Register(amx, core_Natives, -1); } -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif int AMXEXPORT amx_CoreCleanup(AMX *amx) { - #if !defined NOPROPLIST + (void)amx; + #if !defined AMX_NOPROPLIST //??? delete only the properties owned by the AMX while (proproot.next!=NULL) list_delete(&proproot,proproot.next); diff --git a/amxmodx/amxdefn.asm b/amxmodx/amxdefn.asm new file mode 100755 index 00000000..450f6a03 --- /dev/null +++ b/amxmodx/amxdefn.asm @@ -0,0 +1,86 @@ +; Definition of the AMX structure for assembler syntax (NASM) + + struc amx_s +_base: resd 1 +_dataseg: resd 1 +_callback: resd 1 +_debug: resd 1 +_cip: resd 1 +_frm: resd 1 +_hea: resd 1 +_hlw: resd 1 +_stk: resd 1 +_stp: resd 1 +_flags: resd 1 +_usertags: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h) +_userdata: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h) +_error: resd 1 +_paramcount: resd 1 +_pri: resd 1 +_alt: resd 1 +_reset_stk: resd 1 +_reset_hea: resd 1 +_syscall_d: resd 1 +%ifdef JIT + ; the two fields below are for the JIT; they do not exist in + ; the non-JIT version of the abstract machine +_reloc_size: resd 1 ; memory block for relocations +_code_size: resd 1 ; memory size of the native code +%endif + endstruc + + struc amxhead_s +_size: resd 1 ; size of the "file" +_magic: resw 1 ; signature +_file_version: resb 1; file format version +_amx_version: resb 1 ; required version of the AMX +_h_flags: resw 1 +_defsize: resw 1 ; size of one public/native function entry +_cod: resd 1 ; initial value of COD - code block +_dat: resd 1 ; initial value of DAT - data block +_h_hea: resd 1 ; initial value of HEA - start of the heap +_h_stp: resd 1 ; initial value of STP - stack top +_h_cip: resd 1 ; initial value of CIP - the instruction pointer +_publics: resd 1 ; offset to the "public functions" table +_natives: resd 1 ; offset to the "native functions" table +_libraries: resd 1 ; offset to the "library" table +_pubvars: resd 1 ; offset to the "public variables" table +_tags: resd 1 ; offset to the "public tagnames" table +_nametable: resd 1 ; offset to the name table, file version 7 only + endstruc + + +AMX_ERR_NONE EQU 0 +AMX_ERR_EXIT EQU 1 +AMX_ERR_ASSERT EQU 2 +AMX_ERR_STACKERR EQU 3 +AMX_ERR_BOUNDS EQU 4 +AMX_ERR_MEMACCESS EQU 5 +AMX_ERR_INVINSTR EQU 6 +AMX_ERR_STACKLOW EQU 7 +AMX_ERR_HEAPLOW EQU 8 +AMX_ERR_CALLBACK EQU 9 +AMX_ERR_NATIVE EQU 10 +AMX_ERR_DIVIDE EQU 11 ; for catching divide errors +AMX_ERR_SLEEP EQU 12 + +AMX_ERR_MEMORY EQU 16 +AMX_ERR_FORMAT EQU 17 +AMX_ERR_VERSION EQU 18 +AMX_ERR_NOTFOUND EQU 19 +AMX_ERR_INDEX EQU 20 +AMX_ERR_DEBUG EQU 21 +AMX_ERR_INIT EQU 22 +AMX_ERR_USERDATA EQU 23 +AMX_ERR_INIT_JIT EQU 24 +AMX_ERR_PARAMS EQU 25 +AMX_ERR_DOMAIN EQU 26 +AMX_ERR_GENERAL EQU 27 + +AMX_FLAG_DEBUG EQU 0002h ; symbolic info. available +AMX_FLAG_COMPACT EQU 0004h +AMX_FLAG_BYTEOPC EQU 0008h +AMX_FLAG_NOCHECKS EQU 0010h +AMX_FLAG_BROWSE EQU 4000h +AMX_FLAG_RELOC EQU 8000h ; jump/call addresses relocated + diff --git a/amxmodx/amxexecn.asm b/amxmodx/amxexecn.asm index 2a14e9e1..a5a6cf78 100755 --- a/amxmodx/amxexecn.asm +++ b/amxmodx/amxexecn.asm @@ -1,4 +1,4 @@ -; AMXEXECN.ASM Abstract Machine for the "Small" language +; AMXEXECN.ASM Abstract Machine for the "Pawn" language ; ;Some notes: @@ -25,7 +25,7 @@ ; ;Copyright and license of use, please read ;----------------------------------------- -;The assembler implementation of the abstract machine for the Small language, +;The assembler implementation of the abstract machine for the Pawn language, ;specifically the file AMXEXEC.ASM, is copyright (c) 1998-2000 by Marc Peter. ; ;Permission is hereby granted, without written agreement and without paid @@ -56,6 +56,8 @@ ; ;History (list of changes) ;------------------------- +; 17 february 2005 by Thiadmer Riemersms +; Addition of the BREAK opcode, removal of the older debugging opcode table. ; 6 march 2004 by Thiadmer Riemersma ; Corrected a bug in OP_FILL, where a cell preceding the array would ; be overwritten (zero'ed out). This bug was brought to my attention @@ -95,92 +97,7 @@ %endif %endmacro - -; I could not get NASM's structure definition to work (it appears to confuse -; ENDSTRUC with "end segment"). So the definition below uses constants for -; the field offsets. -;amx_s STRUC - _base EQU 00h ;DD ? - _dataseg EQU 04h ;DD ? - _callback EQU 08h ;DD ? - _debug EQU 0ch ;DD ? - _cip EQU 10h ;DD ? - _frm EQU 14h ;DD ? - _hea EQU 18h ;DD ? - _hlw EQU 1ch ;DD ? - _stk EQU 20h ;DD ? - _stp EQU 24h ;DD ? - _flags EQU 28h ;DD ? - _curline EQU 2ch ;DD ? - _curfile EQU 30h ;DD ? - _dbgcode EQU 34h ;DD ? - _dbgaddr EQU 38h ;DD ? - _dbgparam EQU 3ch ;DD ? - _dbgname EQU 40h ;DD ? - _usertags1 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _usertags2 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _usertags3 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _usertags4 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _userdata1 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _userdata2 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _userdata3 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _userdata4 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h) - _error EQU 64h ;DD ? - _pri EQU 68h ;DD ? - _alt EQU 6ch ;DD ? - _reset_stk EQU 70h ;DD ? - _reset_hea EQU 74h ;DD ? - _syscall_d EQU 78h ;DD ? - ; the two fields below are for the JIT; they do not exist in - ; the non-JIT version of the abstract machine -; _reloc_size EQU 7ch ;DD ? ; memory block for relocations -; _code_size EQU 80h ;DD ? ; memory size of the native code -;amx_s ENDS - - - AMX_ERR_NONE EQU 0 - AMX_ERR_EXIT EQU 1 - AMX_ERR_ASSERT EQU 2 - AMX_ERR_STACKERR EQU 3 - AMX_ERR_BOUNDS EQU 4 - AMX_ERR_MEMACCESS EQU 5 - AMX_ERR_INVINSTR EQU 6 - AMX_ERR_STACKLOW EQU 7 - AMX_ERR_HEAPLOW EQU 8 - AMX_ERR_CALLBACK EQU 9 - AMX_ERR_NATIVE EQU 10 - AMX_ERR_DIVIDE EQU 11 ; MP: added for catching divide errors - AMX_ERR_SLEEP EQU 12 ; (TR) - - AMX_ERR_MEMORY EQU 16 - AMX_ERR_FORMAT EQU 17 - AMX_ERR_VERSION EQU 18 - AMX_ERR_NOTFOUND EQU 19 - AMX_ERR_INDEX EQU 20 - AMX_ERR_DEBUG EQU 21 - AMX_ERR_INIT EQU 22 - AMX_ERR_USERDATA EQU 23 - AMX_ERR_INIT_JIT EQU 24 - AMX_ERR_PARAMS EQU 25 - AMX_ERR_DOMAIN EQU 26 - - DBG_INIT EQU 0 - DBG_FILE EQU 1 - DBG_LINE EQU 2 - DBG_SYMBOL EQU 3 - DBG_CLRSYM EQU 4 - DBG_CALL EQU 5 - DBG_RETURN EQU 6 - DBG_TERMINATE EQU 7 - DBG_SRANGE EQU 8 ; (TR) - DBG_SYMTAG EQU 9 ; (TR) - - AMX_FLAG_CHAR16 EQU 0001h ; characters are 16-bit - AMX_FLAG_DEBUG EQU 0002h ; symbolic info. available - AMX_FLAG_LINEOPS EQU 0020h ; line op information - AMX_FLAG_TRACED EQU 0040h ; - AMX_FLAG_BROWSE EQU 4000h - AMX_FLAG_RELOC EQU 8000h ; jump/call addresses relocated +%include "amxdefn.asm" ;#define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v ) %macro _PUSH 1 @@ -659,29 +576,6 @@ OP_POP_ALT: ;good OP_STACK: - mov edx,ecx - add ecx,[esi+4] - _CHKMARGIN - _CHKSTACK - mov ebp,amx - test DWORD [ebp+_flags],AMX_FLAG_DEBUG - jz short op_stk_goon - ; update several structure fields and call the debug hook - mov DWORD [ebp+_dbgcode],DBG_CLRSYM - mov [ebp+_stk],ecx - push eax - mov eax,ebp ; 1st parm: amx - _SAVEREGS - push eax ; pass parameter via the stack - call [ebp+_debug] ; call debug function - _DROPARGS 4 ; remove arguments from stack - _RESTOREREGS - pop eax - op_stk_goon: - add esi,8 - GO_ON - -OP_STACK_nodebug: mov edx,ecx add ecx,[esi+4] _CHKMARGIN @@ -711,35 +605,6 @@ OP_PROC: GO_ON OP_RET: - _POP ebx - _POP esi - cmp esi,code ; verify ESI>=code - jb err_memaccess - cmp esi,codesiz ; verify ESI=code @@ -760,107 +625,17 @@ OP_RETN: jae err_memaccess mov frm,ebx add ebx,edi - mov ebp,amx - test DWORD [ebp+_flags], AMX_FLAG_DEBUG - jz short op_retn_goon - ; update several structure fields and call the debug hook - mov DWORD [ebp+_dbgcode],DBG_RETURN - mov [ebp+_dbgparam],eax - push eax - mov [ebp+_stk],ecx ; store STK - mov eax,hea - mov [ebp+_hea],eax ; store HEA - mov eax,ebp ; parm: amx - _SAVEREGS - push eax - call [ebp+_debug] ; call debug function - _DROPARGS 4 ; remove arguments from stack - _RESTOREREGS - ; also send the DBG_CLRSYM code - mov eax,[edi+ecx] - lea ecx,[ecx+eax+4] - mov DWORD [ebp+_dbgcode],DBG_CLRSYM - mov [ebp+_stk],ecx - mov eax,ebp ; parm: amx - _SAVEREGS - push eax - call [ebp+_debug] ; call debug function - _DROPARGS 4 ; remove arguments from stack - _RESTOREREGS - pop eax - ; ECX already adjusted - GO_ON - op_retn_goon: mov ebp,[edi+ecx] lea ecx,[ecx+ebp+4] GO_ON -OP_RETN_nodebug: - _POP ebx - _POP esi - cmp esi,code ; verify ESI>=code - jb err_memaccess - cmp esi,codesiz ; verify ESI155 million instr./sec on my AMD K6-2/366 with the Hanoi "bench" @@ -20,42 +21,78 @@ ; step. ; NOTE 3: -; During execution of the compiled code with amx_exec_asm() the x86 processor's +; During execution of the compiled code with amx_exec_jit() the x86 processor's ; stack is switched into the data section of the abstract machine. This means ; that there should always be enough memory left between HEA and STK to provide ; stack space for occurring interrupts! (see the STACKRESERVE variable) ; NOTE 4: -; Although the Small compiler doesn't generate the LCTRL, SCTRL and CALL.I +; Although the Pawn compiler doesn't generate the LCTRL, SCTRL and CALL.I ; instructions, I have to tell that they don't work as expected in a JIT ; compiled program, because there is no easy way of transforming AMX code ; addresses and JIT translated ones. This might be fixed in a future version. + +; NX ("No eXecute") and XD (eXecution Denied) bits +; (by Thiadmer Riemersma) +; +; AMD defined a bit "No eXecute" for the page table entries (for its 64-bit +; processors) and Intel came with the same design, but calling it differently. +; The purpose is to make "buffer overrun" security holes impossible, or at least +; very, very difficult, by marking the stack and the heap as memory regions +; such that an attempt to execute processor instructions will cause a processor +; exception (of course, a buffer overrun that is not explictly handled will then +; crash the application --instead of executing the rogue code). +; +; For JIT compilers, this has the impact that you are not allowed to execute the +; code that the JIT has generated. To do that, you must adjust the attributes +; for the memory page. For Microsoft Windows, you can use VirtualAlloc() to +; allocate a memory block with the appropriate fags; on Linux (with a recent +; kernel), you would use vmalloc_exec(). Microsoft Windows also offers the +; function VirtualProtect() to change the page attributes of an existing memory +; block, but there are caveats in its use: if the block spans multiple pages, +; these pages must be consecutive, and if there are blocks of memory in a page +; unrelated to the JIT, their page attributes will change too. +; +; The JIT compiler itself requires only read-write access (this is the default +; for a memory block that you allocate). The execution of the JIT-compiled code +; requires full access to the memory block: read, write and execute. It needs +; write access, because the SYSREQ.C opcode is patched to SYSREQ.D after the +; first lookup (this is an optimization, look up the address of the native +; function only once). For processors that do not support the NX/XD bit, +; execution of code is implicitly supported if read access is supported. +; +; During compilation, the JIT compiler requires write-access to its own code +; segment: the JIT-compiler patches P-code parameters into its own code segment +; during compilation. This is handled in the support code for amx_InitJIT. +; +; +; CALLING CONVENTIONS +; (by Thiadmer Riemersma) ; -; CALLING CONVENTIONS (by Thiadmer Riemersma) ; This version is the JIT that uses the "stack calling convention". In the ; original implementation, this meant __cdecl; both for the calling convention ; for the _asm_runJIT routine itself as for the callback functions. ; The current release supports __stdcall for the callback functions; to -; use it, you need to assemble the file with STDECL defined (Since STDCALL is +; use it, you need to assemble the file with STDECL defined (Since STDCALL is ; a reserved word on the assembler, I had to choose a different name for the ; macro, hence STDECL.) ; Revision History -;------------------ -; 16 September 2004 by David "BAILOPAN" Anderson -; Implemented a compile time toggleable debug hook on OP_CALL and OP_RET. -; NOTE: JIT has not had debug hooks since 1999. -; 8 September 2004 by David "BAILOPAN" Anderson -; Changed OP_LINE call to be compile-time toggle-able between compiling -; line ops or not. +; ---------------- +; 17 february 2005 by Thiadmer Riemersms +; Addition of the BREAK opcode, removal of the older debugging opcode +; table. There should now be some debug support (if enabled during the +; build of the JIT compiler), but not enough to run a debugger: the JIT +; compiler does not keep a list that relates the code addresses of the +; P-code versus the native code. ; 29 June 2004 by G.W.M. Vissers -; Translated the thing into NASM. The actual generation of the code is -; put into the data section because the code modifies itself whereas the -; text section is usually read-only in the Unix ELF format. +; Translated the thing into NASM. The actual generation of the code is +; put into the data section because the code modifies itself whereas the +; text section is usually read-only in the Unix ELF format. ; 6 march 2004 by Thiadmer Riemersma ; Corrected a bug in OP_FILL, where a cell preceding the array would ; be overwritten (zero'ed out). This bug was brought to my attention -; by Robert Daniels. +; by Robert Daniels. ; 22 december 2003 by Thiadmer Riemersma (TR) ; Added the SYMTAG and SYSCALL.D opcodes (these are not really supported; ; SYMTAG is a no-op). @@ -94,8 +131,8 @@ ; hanoi bench. ; 1999/08/05 MP ; * fixed OP_LINE in the case of NODBGCALLS==1, where no compiled address -; was stored for the LINE byte code (I.e. SWITCH would jump to totally -; wrong addresses.) The same fix was applied to OP_FILL, OP_FILE and +; was stored for the LINE byte code (i.e. SWITCH would jump to totally +; wrong addresses). The same fix was applied to OP_FILL, OP_FILE and ; OP_SCTRL (for the no-op case). ; 1999/08/04 MP ; * updated with 4 new opcodes (SRANGE does nothing at the moment; 2dim. @@ -107,6 +144,16 @@ ; to compute the destination address: It searches backwards now. ; 1999/07/08 MP - initial revision + +; +; Support for the BREAK opcode (callback to the debugger): 0 = no, all other +; values = yes. Beware that the compiled code runs slower when this is enabled, +; and that debug support is still fairly minimal. +; +; GWMV: to generate LINE opcode, %define DEBUGSUPPORT +; +%undef DEBUGSUPPORT + ; ; If this is set to 1 the JIT generates relocatable code for case tables, too. ; If set to 0, a faster variant for switch (using absolute addresses) is @@ -128,119 +175,17 @@ ; ; This variable controls the generation of memory range checks at run-time. ; You should set this to 0, only when you are sure that there are no range -; violations in your Small programs and you really need those 5% speed gain. +; violations in your Pawn programs and you really need those 5% speed gain. ; ; GWMV: To disable runtime checks, %undef it, instread of setting it to zero ; %define DORUNTIMECHECKS - - struc amx_s -_base: resd 1 -_dataseg: resd 1 -_callback: resd 1 -_debug: resd 1 -_cip: resd 1 -_frm: resd 1 -_hea: resd 1 -_hlw: resd 1 -_stk: resd 1 -_stp: resd 1 -_flags: resd 1 -_curline: resd 1 -_curfile: resd 1 -_dbgcode: resd 1 -_dbgaddr: resd 1 -_dbgparam: resd 1 -_dbgname: resd 1 -;usertags and userdata are 16 bytes on AMX Mod X -_usertags1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_usertags2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_usertags3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_usertags4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_userdata1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_userdata2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_userdata3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_userdata4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) -_error: resd 1 -_pri: resd 1 -_alt: resd 1 -_reset_stk: resd 1 -_reset_hea: resd 1 -_syscall_d: resd 1 -; the two fields below are for the JIT -; they are included in the non-JIT version for AMX Mod X -; this is to make sure that the structs match universally! -_reloc_size: resd 1 ; memory block for relocations -_code_size: resd 1 ; memory size of the native code - endstruc - - - struc amxhead_s -_size: resd 1 ; size of the "file" -_magic: resw 1 ; signature -_file_version: resb 1 ;file format version -_amx_version: resb 1 ; required version of the AMX -_h_flags: resw 1 -_defsize: resw 1 ; size of one public/native function entry -_cod: resd 1 ; initial value of COD - code block -_dat: resd 1 ; initial value of DAT - data block -_h_hea: resd 1 ; initial value of HEA - start of the heap -_h_stp: resd 1 ; initial value of STP - stack top -_h_cip: resd 1 ; initial value of CIP - the instruction pointer -_publics: resd 1 ; offset to the "public functions" table -_natives: resd 1 ; offset to the "native functions" table -_libraries: resd 1 ; offset to the "library" table -_pubvars: resd 1 ; offset to the "public variables" table -_tags: resd 1 ; offset to the "public tagnames" table - endstruc - - -AMX_ERR_NONE equ 0 -AMX_ERR_EXIT equ 1 -AMX_ERR_ASSERT equ 2 -AMX_ERR_STACKERR equ 3 -AMX_ERR_BOUNDS equ 4 -AMX_ERR_MEMACCESS equ 5 -AMX_ERR_INVINSTR equ 6 -AMX_ERR_STACKLOW equ 7 -AMX_ERR_HEAPLOW equ 8 -AMX_ERR_CALLBACK equ 9 -AMX_ERR_NATIVE equ 10 -AMX_ERR_DIVIDE equ 11 ; MP: added for catching divide errors -AMX_ERR_SLEEP equ 12 ; (TR) go into sleep mode - -AMX_ERR_MEMORY equ 16 -AMX_ERR_FORMAT equ 17 -AMX_ERR_VERSION equ 18 -AMX_ERR_NOTFOUND equ 19 -AMX_ERR_INDEX equ 20 -AMX_ERR_DEBUG equ 21 -AMX_ERR_INIT equ 22 -AMX_ERR_USERDATA equ 23 -AMX_ERR_INIT_JIT equ 24 -AMX_ERR_PARAMS equ 25 -AMX_ERR_DOMAIN equ 26 - -DBG_INIT equ 0 -DBG_FILE equ 1 -DBG_LINE equ 2 -DBG_SYMBOL equ 3 -DBG_CLRSYM equ 4 -DBG_CALL equ 5 -DBG_RETURN equ 6 -DBG_TERMINATE equ 7 -DBG_SRANGE equ 8 -DBG_SYMTAG equ 9 - -AMX_FLAG_CHAR16 equ 0001h ; characters are 16-bit -AMX_FLAG_DEBUG equ 0002h ; symbolic info. available -AMX_FLAG_LINEOPS equ 0020h ; line ops should be parsed [load time only flag] - ~dvander -AMX_FLAG_BROWSE equ 4000h -AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated +%define JIT 1 +%include "amxdefn.asm" ; GWMV: -; Nasm can't do the next as equivalence statements, since the value of +; Nasm can't do the next as equivalence statements, since the value of ; esi is not determined at compile time %define stk [esi+32] ; define some aliases to registers that will %define alt [esi+28] ; be stored on the stack when the code is @@ -269,7 +214,7 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated ; -; For determining the biggest native code section generated for ONE Small +; For determining the biggest native code section generated for ONE Pawn ; opcode. (See the following macro and the PUBLIC function getMaxCodeSize().) ; ; GWMV: Do NOT see the following macro. See CHECKCODESIZE instead. @@ -278,20 +223,12 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated ; ; This is the work horse of the whole JIT: It actually copies the code. -; Notes from ~dvander (with help of dJeyL) -; This takes a source and ending address pointer in the assembled JIT code. -; Then it subtracts them and copies the code in between. -; The last parameter is the number of bytes the opcode is so it can jump -; to the next one. -; Also note that the "in between" code is NEVER executed during the compile -; phase of the JIT. It's only assembled in memory, and copied into the -; final output bytecode by this function. %macro GO_ON 2-3 4 mov esi, %1 ;get source address of JIT code mov ecx,%2-%1 ;get number of bytes to copy mov [ebx],edi ;store address for jump-correction - add ebx,%3 - rep movsb + add ebx,%3 + rep movsb cmp ebx,[end_code] jae code_gen_done jmp dword [ebx] ;go on with the next opcode @@ -300,9 +237,7 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated ; GWMV: ; Nasm can't handle the determination of the maximum code size as was done ; in the Masm implementation, since it only does two passes. This macro is -; called *after* the code for each Small instruction. -; Notes by ~dvander: This just substracts a label's ip from the current ip. -; Therefore you get an instant size check - see RELOC +; called *after* the code for each Pawn instruction. %macro CHECKCODESIZE 1 %if MAXCODESIZE < $-%1 %assign MAXCODESIZE $-%1 @@ -310,14 +245,9 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated %endmacro ; -; Modify the argument of an x86 instruction with the Small opcode's parameter +; Modify the argument of an x86 instruction with the Pawn opcode's parameter ; before copying the code. ; -; Notes by ~dvander (thanks to dJeyL) - this will take an address and modify -; the dword at it. Since the JIT copies already assembled code, you see -; things like "call 12345678h". This is an arbitrary value as putval -; will modify it in memory and then GO_ON will add it to the program. -; It is important to get the putval address right - it's in bytes. %macro putval 1 mov eax,[ebx+4] mov dword [%1],eax @@ -326,17 +256,12 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated ; ; Add an entry to the table of addresses which have to be relocated after the ; code compilation is done. -; Notes by ~dvander: This is sort of what amx_BrowseRelocate() does, although -; relocation is actually done after code generation (this just adds to a -; table). Like putval, this takes in an address and marks it to be -; rewritten. It is a good idea to just use labels to find relocation -; offsets (see OP_CALL and OP_RETN). After code generation, this table -; is browsed and the correct threaded jumps are placed. +; %macro RELOC 1-2 ; adr, dest mov ebp,[reloc_num] %if %0 < 2 mov eax,[ebx+4] - %else + %else lea eax,[%2] %endif mov [edx+ebp],eax ; write absolute destination @@ -356,7 +281,7 @@ section .text global asm_runJIT, _asm_runJIT -global amx_exec_asm, _amx_exec_asm +global amx_exec_jit, _amx_exec_jit global getMaxCodeSize, _getMaxCodeSize @@ -381,7 +306,7 @@ _asm_runJIT: mov eax,[esp+20] ; get amxh mov edx,[esp+24] ; get jumps array mov ebx,[esp+28] ; get destination - + mov [amxhead],eax ; save pointer to AMX_HEADER struct mov ecx,[eax+_cod] ; get offset of start of code mov eax,[eax+_dat] ; offset of start of data = end of code @@ -481,9 +406,9 @@ reloc_done: ret ; GWMV: -; The code below modifies itself to store the arguments to the Small opcodes +; The code below modifies itself to store the arguments to the Pawn opcodes ; in the compiled code. This is fine, but the .text section in an ELF executable -; is usually marked read-only, that's why this code is in the .data section. +; is usually marked read-only, that's why this code is in the .data section. section .data exec @@ -817,7 +742,7 @@ OP_ALIGN_PRI: CHECKCODESIZE j_align_pri OP_ALIGN_ALT: -;nop +;nop; mov eax,4 sub eax,[ebx+4] mov dword [j_align_alt+1],eax @@ -1045,7 +970,7 @@ OP_HEAP: call [chk_marginheap] %endif CHECKCODESIZE j_heap - + ;good OP_PROC: ;nop; @@ -1073,119 +998,22 @@ OP_RET: ;good OP_RETN: ;nop; - ;save registers - push eax - push ebp - ;get .amx flags - mov ebp,[amxhead] - mov eax,[ebp+_h_flags] - ;check to see if the flag has line ops - and eax,AMX_FLAG_DEBUG - cmp eax,AMX_FLAG_DEBUG - ;restore registers - pop ebp - pop eax - ;if so, skip down to debug compiler - jmp _go_jit_retn_debug + GO_ON j_retn, OP_CALL -_go_jit_retn_nodebug: - GO_ON j_retn_nodebug, _go_jit_retn_go - j_retn_nodebug: + j_retn: jmp [jit_retn] - CHECKCODESIZE j_retn_nodebug -_go_jit_retn_go: - jmp _go_jit_retn_end - -_go_jit_retn_debug: - GO_ON j_retn, OP_CALL - j_retn: - push ebp - push eax - push edx - ;get AMX - mov ebp,amx - ;get debug call ptr - mov eax,[ebp+_userdata2] - ;check validity - mov edx, dword 0 - cmp eax, edx - je _go_jit_skip_debug - xchg esp,esi ;switch stack - push 1 ;param 2 mode 1 = pop - push ebp ;param 1 - amx - call eax ;indirect debug call - add esp, 8 ;restore stack - xchg esp,esi ;return to AMX stack - mov ebp,amx ;restore AMX [necessary?] - _go_jit_skip_debug: - pop edx - pop eax - pop ebp - jmp [jit_retn] - CHECKCODESIZE j_retn -_go_jit_retn_end: + CHECKCODESIZE j_retn ;good OP_CALL: ;nop; - ;save registers - push eax - push ebp - ;get .amx flags - mov ebp,[amxhead] - mov eax,[ebp+_h_flags] - ;check to see if the flag has line ops - and eax,AMX_FLAG_DEBUG - cmp eax,AMX_FLAG_DEBUG - ;restore registers - pop ebp - pop eax - ;if so, skip down to debug compiler - jmp _go_jit_debug + RELOC 1 + GO_ON j_call, OP_CALL_I, 8 -_go_jit_nodebug: - RELOC 1 - GO_ON j_call_nodebug, _j_call_go_on, 8 - j_call_nodebug: - db 0e8h, 0, 0, 0, 0 - CHECKCODESIZE j_call_nodebug - -_j_call_go_on: - jmp _opcall_end - -_go_jit_debug: - ;thanks to Julien "dJeyL" Laurent for code relocation explanation - RELOC _go_jit_reloc-j_call+1 - GO_ON j_call, OP_CALL_I, 8 - j_call: - ; save some registers - push ebp - push eax - push edx - ; get AMX - mov ebp,amx - ; get debug call pointer - mov eax,[ebp+_userdata2] - ; check to see if it's valid - mov edx, dword 0 - cmp eax,edx - je _go_jit_skip_call - xchg esp,esi ;switch to caller stack - push 2 ;param mode=2, push - push ebp ;param amx - call eax ;indirect call - add esp, 8 ;restore stack - xchg esp,esi ;return to AMX stack - mov ebp,amx ;restore AMX [necessary?] - _go_jit_skip_call: - ;restore original registers - pop edx - pop eax - pop ebp - _go_jit_reloc: - db 0e8h, 0, 0, 0, 0 - CHECKCODESIZE j_call -_opcall_end: + j_call: + ;call 12345678h ; tasm chokes on this out of a sudden + db 0e8h, 0, 0, 0, 0 + CHECKCODESIZE j_call OP_CALL_I: ;nop; @@ -1857,39 +1685,12 @@ OP_FILE: ;opcode is simply ignored OP_LINE: ;nop; -;~dvander - opline is now variable on compile time :] - ;save registers - push eax - push ebp - ;get .amx flags - mov ebp,[amxhead] - mov eax,[ebp+_h_flags] - ;check to see if the flag has line ops - and eax,AMX_FLAG_LINEOPS - cmp eax,AMX_FLAG_LINEOPS - ;restore registers - pop ebp - pop eax - ;if so, skip down to debug compiler - je _go_debug - mov [ebx],edi ; no line number support: ignore opcode add ebx,12 ; move on to next opcode cmp ebx,[end_code] jae code_gen_done jmp dword [ebx] ; go on with the next opcode -_go_debug: - putval j_line+6 - mov eax,[ebx+8] - mov [j_line_sm],eax - GO_ON j_line, OP_SYMBOL, 12 - j_line: - call [jit_line] - DD 0 ; space for curline -j_line_sm DD 0 ; space for curfile - CHECKCODESIZE j_line - OP_SYMBOL: ;ignored mov [ebx],edi mov eax,[ebx+4] ; get size @@ -2019,6 +1820,23 @@ OP_SYMTAG: ;ignored (TR) jmp dword [ebx] ; go on with the next opcode +OP_BREAK: +%ifndef DEBUGSUPPORT + mov [ebx],edi ; no line number support: ignore opcode + add ebx,4 ; move on to next opcode + cmp ebx,[end_code] + jae code_gen_done + jmp DWORD [ebx] ; go on with the next opcode +%else + GO_ON j_break, OP_INVALID + j_break: + mov ebp,amx + cmp DWORD [ebp+_debug], 0 + je $+4 ; jump around the "call" statement + call [jit_break] + CHECKCODESIZE j_break +%endif + OP_INVALID: ; break from the compiler with an error code mov eax,AMX_ERR_INVINSTR pop esi @@ -2032,12 +1850,12 @@ section .text ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; -;cell asm_exec( cell *regs, cell *retval, cell stp, cell hea ); +;cell amx_exec( cell *regs, cell *retval, cell stp, cell hea ); ; eax edx ebx ecx ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -amx_exec_asm: -_amx_exec_asm: +amx_exec_jit: +_amx_exec_jit: push edi push esi push ebp @@ -2338,20 +2156,39 @@ JIT_OP_SYSREQ_D: ; (TR) ret -JIT_OP_LINE: - pop ecx ; get return address - mov ebp,amx - push eax - push edx - mov eax,[ecx] ; get curline - mov edx,[ecx+4] ; get curfile - add ecx,8 ; skip curline & curfile - mov [ebp+_curline],eax ; store curline - mov [ebp+_curfile],edx ; store curfile +JIT_OP_BREAK: +%ifdef DEBUGSUPPORT + mov ecx,esp ; get STK into ECX + mov ebp,amx ; get amx into EBP + + sub ecx,edi ; correct STK + + mov [ebp+_pri],eax ; store values in AMX structure: PRI, + mov [ebp+_alt],edx ; ALT, + mov [ebp+_stk],ecx ; STK, + mov ecx,hea ; HEA, + mov ebx,frm ; and FRM + mov [ebp+_hea],ecx + mov [ebp+_frm],ebx ; EBX & ECX are invalid by now + ;??? storing CIP is not very useful, because the code changed (during JIT compile) + + xchg esp,esi ; switch to caller stack + push ebp ; 1st param: amx + call [ebp+_debug] + _DROPARGS 4 ; remove args from stack + xchg esp,esi ; switch back to AMX stack + cmp eax,AMX_ERR_NONE + jne _return_popstack; return error code, if any + + mov ebp,amx ; get amx into EBP + mov eax,[ebp+_pri] ; restore values + mov edx,[ebp+_alt] ; ALT, + mov edx,alt ; restore ALT + mov ebx,frm ; restore FRM + add ebx,edi ; relocate frame +%endif + ret - pop edx - pop eax - jmp ecx ; jump back JIT_OP_SWITCH: pop ebp ; pop return address = table address @@ -2370,9 +2207,10 @@ JIT_OP_SWITCH: jmp ebp %endif + ; The caller of asm_runJIT() can determine the maximum size of the compiled ; code by multiplying the result of this function by the number of opcodes in -; Small module. +; Pawn module. ; ; unsigned long getMaxCodeSize_(); ; @@ -2414,17 +2252,17 @@ jit_fill DD JIT_OP_FILL jit_bounds DD JIT_OP_BOUNDS jit_sysreq DD JIT_OP_SYSREQ jit_sysreq_d DD JIT_OP_SYSREQ_D -jit_line DD JIT_OP_LINE +jit_break DD JIT_OP_BREAK jit_switch DD JIT_OP_SWITCH ; ; The table for the browser/relocator function. ; -global amx_opcodelist, _amx_opcodelist +global amx_opcodelist_jit, _amx_opcodelist_jit -amx_opcodelist: -_amx_opcodelist: +amx_opcodelist_jit: +_amx_opcodelist_jit: DD OP_INVALID DD OP_LOAD_PRI DD OP_LOAD_ALT @@ -2562,3 +2400,6 @@ _amx_opcodelist: DD OP_NOP ; TR DD OP_SYSREQ_D ; TR DD OP_SYMTAG ; TR + DD OP_BREAK ; TR + +END diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 6bc346e4..33faf851 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -353,7 +353,7 @@ static cell AMX_NATIVE_CALL is_linux_server(AMX *amx, cell *params) static cell AMX_NATIVE_CALL is_amd64_server(AMX *amx, cell *params) { -#if SMALL_CELL_SIZE==64 +#if PAWN_CELL_SIZE==64 return 1; #else return 0; @@ -794,10 +794,11 @@ static cell AMX_NATIVE_CALL register_menucmd(AMX *amx, cell *params) /* 3 param int ilen, idx; char* sptemp = get_amxstring(amx,params[3],0,ilen); - if(amx_FindPublic(amx, sptemp ,&idx)!=AMX_ERR_NONE) { - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",sptemp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); - return 0; + idx = registerSPForwardByName(amx, sptemp, FP_CELL, FP_CELL, FP_DONE); + if (idx == -1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", sptemp); + return 0; } g_menucmds.registerMenuCmd( plugin , params[1] , params[2] , idx ); @@ -870,9 +871,10 @@ static cell AMX_NATIVE_CALL register_concmd(AMX *amx, cell *params) /* 4 param * CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); int i, idx = 0; char* temp = get_amxstring(amx,params[2],0, i ); - if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); + idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + if (idx == -1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp); return 0; } temp = get_amxstring(amx,params[1],0, i ); @@ -897,9 +899,10 @@ static cell AMX_NATIVE_CALL register_clcmd(AMX *amx, cell *params) /* 4 param */ CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); int i, idx = 0; char* temp = get_amxstring(amx,params[2],0, i ); - if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); + idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + if(idx==-1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp); return 0; } temp = get_amxstring(amx,params[1],0, i ); @@ -922,9 +925,10 @@ static cell AMX_NATIVE_CALL register_srvcmd(AMX *amx, cell *params) /* 2 param * CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); int i, idx = 0; char* temp = get_amxstring(amx,params[2],0, i ); - if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); + idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + if (idx==-1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp); return 0; } temp = get_amxstring(amx,params[1],0, i ); @@ -1023,10 +1027,10 @@ static cell AMX_NATIVE_CALL register_event(AMX *amx, cell *params) /* 2 param */ } sTemp = get_amxstring(amx,params[2],0,len); - - if ( amx_FindPublic(amx, sTemp , &iFunction) != AMX_ERR_NONE){ - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",sTemp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); + iFunction = registerSPForwardByName(amx, sTemp, FP_CELL, FP_DONE); + if (iFunction==-1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", sTemp); return 0; } @@ -1874,20 +1878,9 @@ static cell AMX_NATIVE_CALL pause(AMX *amx, cell *params) /* 3 param */ CPluginMngr::CPlugin *plugin = 0; - if ( flags & 2 ) { // pause function - if (flags&4){ //look out side the plugin - temp = get_amxstring(amx,params[3],0,ilen); - plugin = g_plugins.findPlugin(temp); - } - else plugin = g_plugins.findPluginFast(amx); - if ( !plugin ) return 0; // plugin not found - temp = get_amxstring(amx,params[2],0,ilen); - int err, index; - if ((err = amx_FindPublic( plugin->getAMX(), temp , &index) )!= AMX_ERR_NONE){ - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", temp,plugin->getName() ); - return 0; - } - plugin->pauseFunction( index ); + if ( flags & 2 ) + { // pause function + AMXXLOG_Log("[AMXX] This usage of the native pause() has been deprecated!"); return 1; } else if (flags&4){ @@ -1915,24 +1908,11 @@ static cell AMX_NATIVE_CALL unpause(AMX *amx, cell *params) /* 3 param */ char* sptemp = get_amxstring(amx,params[1],0,ilen); int flags = UTIL_ReadFlags(sptemp); CPluginMngr::CPlugin *plugin = 0; - if (flags&2) { - if (flags&4){ - sptemp = get_amxstring(amx,params[3],0,ilen); - plugin = g_plugins.findPlugin(sptemp); - } - else - plugin = g_plugins.findPluginFast(amx); - if ( !plugin ) return 0; - sptemp = get_amxstring(amx,params[2],0,ilen); - int err, index; - if ((err = amx_FindPublic(plugin->getAMX(), sptemp , &index) )!= AMX_ERR_NONE){ - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", sptemp,plugin->getName() ); - return 0; - } - plugin->unpauseFunction( index ); + if (flags&2) + { + AMXXLOG_Log("[AMXX] This usage of the native pause() has been deprecated!"); return 1; - } - else if (flags&4){ + } else if (flags&4) { sptemp = get_amxstring(amx,params[2],0,ilen); plugin = g_plugins.findPlugin(sptemp); } @@ -2298,10 +2278,10 @@ static cell AMX_NATIVE_CALL register_logevent(AMX *amx, cell *params) char* temp = get_amxstring(amx,params[1],0, a ); - if (amx_FindPublic(amx, temp , &iFunc) != AMX_ERR_NONE){ - AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", - temp,plugin->getName() ); - amx_RaiseError(amx,AMX_ERR_NATIVE); + iFunc = registerSPForwardByName(amx, temp, FP_DONE); + if (iFunc == -1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp); return 0; } @@ -2457,31 +2437,22 @@ static cell AMX_NATIVE_CALL get_module(AMX *amx, cell *params) set_amxstring(amx, params[2], info && info->name ? info->name : "unk", params[3]); set_amxstring(amx, params[4], info && info->author ? info->author : "unk", params[5]); set_amxstring(amx, params[6], info && info->version ? info->version : "unk", params[7]); - } - else - { - module_info_s *info = (*moduleIter).getInfo(); - set_amxstring(amx, params[2], info && info->name ? info->name : "unk", params[3]); - set_amxstring(amx, params[4], info && info->author ? info->author : "unk", params[5]); - set_amxstring(amx, params[6], info && info->version ? info->version : "unk", params[7]); } // compatibility problem possible int numParams = params[0] / sizeof(cell); if (numParams < 8) { - CPluginMngr::CPlugin *curPlugin = g_plugins.findPluginFast(amx); - AMXXLOG_Log("[AMXX] get_module: call to a previous version (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "Call to incompatible version"); + return 0; } // set status cell *addr; if (amx_GetAddr(amx, params[8], &addr) != AMX_ERR_NONE) { - CPluginMngr::CPlugin *curPlugin = g_plugins.findPluginFast(amx); - AMXXLOG_Log("[AMXX] get_module: invalid reference (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "Invalid reference plugin"); + return 0; } *addr = (cell)(*moduleIter).getStatusValue(); @@ -2526,8 +2497,7 @@ static cell AMX_NATIVE_CALL callfunc_begin(AMX *amx, cell *params) if (g_CallFunc_Plugin) { // scripter's fault - AMXXLOG_Log("[AMXX] callfunc_begin called without callfunc_end (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_begin called without callfunc_end"); return 0; } @@ -2608,8 +2578,7 @@ static cell AMX_NATIVE_CALL callfunc_end(AMX *amx, cell *params) if (!g_CallFunc_Plugin) { // scripter's fault - AMXXLOG_Log("[AMXX] callfunc_end called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_end called without callfunc_begin"); return 0; } @@ -2633,9 +2602,13 @@ static cell AMX_NATIVE_CALL callfunc_end(AMX *amx, cell *params) g_CallFunc_CurParam = 0; // actual call - if ((err = amx_Execv(plugin->getAMX(), &retVal, func, curParam, gparams)) != AMX_ERR_NONE) + // Pawn - push parameters in reverse order + for (int i=curParam-1; i>=0; i--) + { + amx_Push(amx, gparams[i]); + } + if ((err = amx_Exec(plugin->getAMX(), &retVal, func) != AMX_ERR_NONE)) { - LogError(amx, err, ""); return 0; } @@ -2672,8 +2645,7 @@ static cell AMX_NATIVE_CALL callfunc_push_byval(AMX *amx, cell *params) if (!g_CallFunc_Plugin) { // scripter's fault - AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin"); return 0; } @@ -2698,15 +2670,13 @@ static cell AMX_NATIVE_CALL callfunc_push_byref(AMX *amx, cell *params) if (!g_CallFunc_Plugin) { // scripter's fault - AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin"); return 0; } if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS) { - AMXXLOG_Log("[AMXX] callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); return 0; } @@ -2756,15 +2726,13 @@ static cell AMX_NATIVE_CALL callfunc_push_str(AMX *amx, cell *params) if (!g_CallFunc_Plugin) { // scripter's fault - AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin"); return 0; } if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS) { - AMXXLOG_Log("[AMXX] callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); - amx_RaiseError(amx, AMX_ERR_NATIVE); + LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); return 0; } @@ -2799,7 +2767,7 @@ static cell AMX_NATIVE_CALL callfunc_push_str(AMX *amx, cell *params) // copy it to the allocated memory // we assume it's unpacked // :NOTE: 4th parameter use_wchar since Small Abstract Machine 2.5.0 - amx_SetString(phys_addr, str, 0, 0); + amx_SetString(phys_addr, str, 0, 0, 0); // push the address and set the reference flag so that memory is released after function call. g_CallFunc_ParamInfo[g_CallFunc_CurParam].flags = CALLFUNC_FLAG_BYREF; diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h index 0bca46a3..c854d8a8 100755 --- a/amxmodx/amxmodx.h +++ b/amxmodx/amxmodx.h @@ -68,7 +68,7 @@ #include "amxxlog.h" #define AMXXLOG_Log g_log.Log -#define AMX_VERSION "1.10-RC1" +#define AMX_VERSION "1.50-RC1" extern AMX_NATIVE_INFO core_Natives[]; extern AMX_NATIVE_INFO time_Natives[]; @@ -244,7 +244,6 @@ enum CountModulesMode int countModules(CountModulesMode mode); void modules_callPluginsLoaded(); -int add_amxnatives(module_info_s* info,AMX_NATIVE_INFO*natives); cell* get_amxaddr(AMX *amx,cell amx_addr); char* build_pathname(char *fmt, ... ); char* build_pathname_r(char *buffer, size_t maxlen, char *fmt, ...); @@ -280,6 +279,7 @@ extern ModuleCallReason g_ModuleCallReason; // modules.cpp extern CModule *g_CurrentlyCalledModule; // modules.cpp extern const char *g_LastRequestedFunc; // modules.cpp void Module_CacheFunctions(); +void Module_UncacheFunctions(); void *Module_ReqFnptr(const char *funcName); // modules.cpp @@ -297,6 +297,7 @@ extern int FF_PluginLog; extern int FF_PluginEnd; extern int FF_InconsistentFile; extern int FF_ClientAuthorized; +extern bool g_coloredmenus; #ifdef FAKEMETA extern CFakeMeta g_FakeMeta; diff --git a/amxmodx/file.cpp b/amxmodx/file.cpp index d2be53e3..562a97ef 100755 --- a/amxmodx/file.cpp +++ b/amxmodx/file.cpp @@ -364,19 +364,6 @@ static cell AMX_NATIVE_CALL amx_fclose(AMX *amx, cell *params) } } -static cell AMX_NATIVE_CALL amx_fgetc(AMX *amx, cell *params) -{ - unsigned int id = params[1] - 1; - if (id >= FileList.size() || FileList.at(id) == NULL) - return 0; - FILE *fp = FileList.at(id); - if (fp) { - return fgetc(fp); - } else { - return -1; - } -} - static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params) { unsigned int id = params[1] - 1; @@ -394,6 +381,20 @@ static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params) return -1; } +#ifdef UNUSED +static cell AMX_NATIVE_CALL amx_fgetc(AMX *amx, cell *params) +{ + unsigned int id = params[1] - 1; + if (id >= FileList.size() || FileList.at(id) == NULL) + return 0; + FILE *fp = FileList.at(id); + if (fp) { + return fgetc(fp); + } else { + return -1; + } +} + static cell AMX_NATIVE_CALL amx_fwrite(AMX *amx, cell *params) { unsigned int id = params[1] - 1; @@ -506,6 +507,7 @@ static cell AMX_NATIVE_CALL amx_ftell(AMX *amx, cell *params) } return -1; } +#endif //UNUSED static cell AMX_NATIVE_CALL amx_filesize(AMX *amx, cell *params) { @@ -521,6 +523,7 @@ static cell AMX_NATIVE_CALL amx_filesize(AMX *amx, cell *params) return -1; } +#ifdef UNUSED static cell AMX_NATIVE_CALL amx_fgetl(AMX *amx, cell *params) { unsigned int id = params[1] - 1; @@ -636,6 +639,7 @@ static cell AMX_NATIVE_CALL amx_fputf(AMX *amx, cell *params) } return -1; } +#endif //UNUSED static cell AMX_NATIVE_CALL amx_build_pathname(AMX *amx, cell *params) { @@ -723,8 +727,10 @@ AMX_NATIVE_INFO file_Natives[] = { //Sanji's File Natives { "fopen", amx_fopen }, { "fclose", amx_fclose }, - { "fgetc", amx_fgetc }, { "fread", amx_fread }, + { "filesize", amx_filesize }, +#ifdef UNUSED + { "fgetc", amx_fgetc }, { "fwrite", amx_fwrite }, { "feof", amx_feof }, { "fseek", amx_fseek }, @@ -733,16 +739,16 @@ AMX_NATIVE_INFO file_Natives[] = { { "fflush", amx_fflush }, { "fscanf", amx_fscanf }, { "ftell", amx_ftell }, - { "filesize", amx_filesize }, { "fgetl", amx_fgetl }, { "fgeti", amx_fgeti }, { "fgets", amx_fgets }, { "fputs", amx_fputs }, { "fputl", amx_fputl }, { "fputi", amx_fputi }, - { "unlink", delete_file }, { "fgetf", amx_fgetf }, { "fputf", amx_fputf }, +#endif + { "unlink", delete_file }, { "build_pathname", amx_build_pathname}, { "dir_exists", dir_exists }, { "open_dir", amx_open_dir }, diff --git a/amxmodx/float.cpp b/amxmodx/float.cpp index 5350e7a3..90776f74 100755 --- a/amxmodx/float.cpp +++ b/amxmodx/float.cpp @@ -96,7 +96,7 @@ static cell AMX_NATIVE_CALL n_floatstr(AMX *amx,cell *params) return 0; /* Now convert the Small String into a C type null terminated string */ - amx_GetString(szSource, pString, 0); + amx_GetStringOld(szSource, pString, 0); /* Now convert this to a float. */ fNum = (REAL)atof(szSource); diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index f3053caf..e81f7491 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -90,6 +90,7 @@ float g_auth_time; bool g_initialized = false; bool g_IsNewMM = false; bool g_NeedsP = false; +bool g_coloredmenus; #ifdef MEMORY_TEST float g_next_memreport_time; @@ -605,7 +606,6 @@ void C_ClientCommand( edict_t *pEntity ) { CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity); META_RES result = MRES_IGNORED; cell ret = 0; - int err; const char* cmd = CMD_ARGV(0); const char* arg = CMD_ARGV(1); @@ -665,10 +665,7 @@ void C_ClientCommand( edict_t *pEntity ) { if ( (*aa).matchCommandLine( cmd , arg ) && (*aa).getPlugin()->isExecutable( (*aa).getFunction() ) ) { - - if ((err =amx_Exec((*aa).getPlugin()->getAMX(), &ret , (*aa).getFunction() , 3, pPlayer->index, (*aa).getFlags(),(*aa).getId() )) != AMX_ERR_NONE) - LogError((*aa).getPlugin()->getAMX(), err, ""); - + ret = executeForwards((*aa).getFunction(), pPlayer->index, (*aa).getFlags(), (*aa).getId()); if ( ret & 2 ) result = MRES_SUPERCEDE; if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE); } @@ -695,33 +692,19 @@ void C_ClientCommand( edict_t *pEntity ) { int menuid = pPlayer->menu; pPlayer->menu = 0; -#ifdef ENABLEEXEPTIONS - try{ -#endif MenuMngr::iterator a = g_menucmds.begin(); while( a ) { if ( (*a).matchCommand( menuid , bit_key ) && (*a).getPlugin()->isExecutable( (*a).getFunction() ) ) { - - if ( ( err = amx_Exec((*a).getPlugin()->getAMX(), &ret ,(*a).getFunction() , 2, pPlayer->index,pressed_key)) != AMX_ERR_NONE) - LogError((*a).getPlugin()->getAMX(), err, ""); - + ret = executeForwards((*a).getFunction(), pPlayer->index, pressed_key); if ( ret & 2 ) result = MRES_SUPERCEDE; if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE); } ++a; } - -#ifdef ENABLEEXEPTIONS - } - catch( ... ) - { - AMXXLOG_Log( "[AMXX] Fatal error at menu commmand execution"); - } -#endif } } /* check for PLUGIN_HANDLED_MAIN and block hl call if needed */ @@ -898,35 +881,6 @@ void C_WriteEntity_Post(int iValue) { } void C_MessageEnd_Post(void) { g_events.executeEvents(); - -#if 0 // ######### this is done by call above - EventsMngr::iterator a = g_events.begin(); - int err; -#ifdef ENABLEEXEPTIONS - try - { -#endif - - while ( a ) - { - - if ((err = amx_Exec((*a).getPlugin()->getAMX(), NULL , (*a).getFunction() , 1, mPlayerIndex /*g_events.getArgInteger(0)*/ )) != AMX_ERR_NONE) - LogError((*a).getPlugin()->getAMX(), err, ""); - - - ++a; - - } - -#ifdef ENABLEEXEPTIONS - } - catch( ... ) - { - AMXXLOG_Log( "[AMXX] Fatal error at event execution"); - } -#endif -#endif - if (endfunction) (*endfunction)(NULL); RETURN_META(MRES_IGNORED); } @@ -1134,6 +1088,13 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m a = &gameDir[i]; g_mod_name.assign(a); + if (g_mod_name.compare("cstrike")==0 || + g_mod_name.compare("czero")==0 || + g_mod_name.compare("dod")==0) + g_coloredmenus = true; + else + g_coloredmenus = false; + // ###### Print short GPL print_srvconsole( "\n AMX Mod X version %s Copyright (c) 2004-2005 AMX Mod X Development Team \n" " AMX Mod X comes with ABSOLUTELY NO WARRANTY; for details type `amxx gpl'.\n", AMX_VERSION); @@ -1194,6 +1155,8 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { g_log.CloseFile(); + Module_UncacheFunctions(); + return(TRUE); } diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index d4cee11d..9c3291bf 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -95,7 +95,7 @@ void free_amxmemory(void **ptr) int load_amxscript(AMX *amx, void **program, const char *filename, char error[64], int debug) { *error = 0; - CAmxxReader reader(filename, SMALL_CELL_SIZE / 8); + CAmxxReader reader(filename, PAWN_CELL_SIZE / 8); if (reader.GetStatus() == CAmxxReader::Err_None) { size_t bufSize = reader.GetBufferSize(); @@ -153,59 +153,72 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 return (amx->error = AMX_ERR_FORMAT); } - if ( (int)CVAR_GET_FLOAT("amx_debug") >= 2 || debug) - { - //automatic debug mode - hdr->flags |= AMX_FLAG_LINEOPS; - hdr->flags |= AMX_FLAG_DEBUG; - } - int err; memset(amx, 0, sizeof(*amx)); + + if ((int)CVAR_GET_FLOAT("amx_debug") >= 2 || debug) + { + if ((amx->flags & AMX_FLAG_DEBUG) != 0) + { + //:TODO: debug support + } + } else { +#ifdef JIT + //if (hdr->file_version == CUR_FILE_VERSION) + amx->flags |= AMX_FLAG_JITC; +#endif + } + if ((err = amx_Init( amx, *program )) != AMX_ERR_NONE) { sprintf(error,"Load error %d (invalid file format or version)", err); return (amx->error = AMX_ERR_INIT); } -#ifdef JIT - void *np = new char[ amx->code_size ]; - void *rt = new char[ amx->reloc_size ]; - if ( !np || (!rt && amx->reloc_size > 0) ) - { - delete[] np; - delete[] rt; - strcpy(error,"Failed to initialize plugin"); - return (amx->error = AMX_ERR_INIT); - } + LOG_MESSAGE(PLID, "AMX: %p FLAGS: %d\n", amx, amx->flags); - if ( (err = amx_InitJIT(amx, rt, np)) == AMX_ERR_NONE ) +#ifdef JIT + if (amx->flags & AMX_FLAG_JITC) { - //amx->base = (unsigned char FAR *)realloc( np, amx->code_size ); -#ifndef __linux__ - amx->base = new unsigned char[ amx->code_size ]; -#else - //posix_memalign((void **)&(amx->base), sysconf(_SC_PAGESIZE), amx->code_size); - amx->base = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), amx->code_size); - mprotect((void *)amx->base, amx->code_size, PROT_READ|PROT_WRITE|PROT_EXEC); -#endif - if ( amx->base ) - memcpy( amx->base , np , amx->code_size ); - delete[] np; - delete[] rt; - delete[] *program; - (*program) = amx->base; - if ( *program == 0 ){ - strcpy(error,"Failed to allocate memory"); - return (amx->error = AMX_ERR_MEMORY); + char *np = new char[ amx->code_size ]; + char *rt = new char[ amx->reloc_size ]; + if ( !np || (!rt && amx->reloc_size > 0) ) + { + delete[] np; + delete[] rt; + strcpy(error,"Failed to initialize plugin"); + return (amx->error = AMX_ERR_INIT); + } + + if ( (err = amx_InitJIT(amx, (void *)rt, (void *)np)) == AMX_ERR_NONE ) + { + //amx->base = (unsigned char FAR *)realloc( np, amx->code_size ); +#ifndef __linux__ + amx->base = new unsigned char[ amx->code_size ]; +#else + //posix_memalign((void **)&(amx->base), sysconf(_SC_PAGESIZE), amx->code_size); + amx->base = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), amx->code_size); + mprotect((void *)amx->base, amx->code_size, PROT_READ|PROT_WRITE|PROT_EXEC); +#endif + if ( amx->base ) + memcpy( amx->base , np , amx->code_size ); + delete[] np; + delete[] rt; + char *prg = (char *)(*program); + delete[] *prg; + (*program) = amx->base; + if ( *program == 0 ){ + strcpy(error,"Failed to allocate memory"); + return (amx->error = AMX_ERR_MEMORY); + } + } + else + { + delete[] np; + delete[] rt; + sprintf(error, "Failed to initialize plugin (%d)", err); + return (amx->error = AMX_ERR_INIT_JIT); } - } - else - { - delete[] np; - delete[] rt; - sprintf(error, "Failed to initialize plugin (%d)", err); - return (amx->error = AMX_ERR_INIT_JIT); } #endif @@ -219,7 +232,6 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 } g_loadedscripts.put( aa ); - amx->sysreq_d = 0; return set_amxnatives(amx,error); } @@ -345,7 +357,8 @@ int unload_amxscript(AMX* amx, void** program) { CList::iterator a = g_loadedscripts.find( amx ); if ( a ) a.remove(); - delete[] *program; + char *prg = (char *)*program; + delete[] *prg; *program = 0; return AMX_ERR_NONE; } @@ -469,27 +482,6 @@ char* build_pathname_addons(char *fmt, ... ) return string; } -int add_amxnatives(module_info_s* info,AMX_NATIVE_INFO*natives) -{ - CList::iterator a = g_modules.begin(); - - while ( a ) - { - if ( (*a).getInfo() == info ) - { - AMX_NATIVE_INFO** aa = new AMX_NATIVE_INFO*(natives); - if ( aa == 0 ) return AMX_ERR_NATIVE; - (*a).m_Natives.put( aa ); - return AMX_ERR_NONE; - } - - ++a; - } - - return AMX_ERR_NATIVE; -} - - bool validFile(const char* file) { const char* a = 0; @@ -505,7 +497,7 @@ bool validFile(const char* file) void ConvertModuleName(const char *pathString, String &path) { -#if SMALL_CELL_SIZE==64 +#if PAWN_CELL_SIZE==64 char *ptr = strstr(pathString, "i386"); if (ptr) { @@ -600,7 +592,7 @@ void ConvertModuleName(const char *pathString, String &path) } } #endif //__linux__ -#endif //SMALL_CELL_SIZE==64 +#endif //PAWN_CELL_SIZE==64 } int loadModules(const char* filename, PLUG_LOADTIME now) @@ -930,10 +922,14 @@ int MNF_AddNatives(AMX_NATIVE_INFO* natives) const char *MNF_GetModname(void) { - // :TODO: Do we have to do this?? + // :TODO: Do we have to do this?? + // I dunno who wrote the above comment but no +#if 0 static char buffer[64]; strcpy(buffer, g_mod_name.c_str()); return buffer; +#endif + return g_mod_name.c_str(); } AMX *MNF_GetAmxScript(int id) @@ -1169,13 +1165,17 @@ REAL MNF_CellToReal(cell x) return *(REAL*)&x; } +#ifdef __linux__ +#define _vsnprintf vsnprintf +#endif + void MNF_Log(const char *fmt, ...) { - // :TODO: Overflow possible here char msg[3072]; va_list arglst; va_start(arglst, fmt); - vsprintf(msg, fmt, arglst); + _vsnprintf(msg, sizeof(msg)-1, fmt, arglst); + //vsprintf(msg, fmt, arglst); va_end(arglst); AMXXLOG_Log("%s", msg); } @@ -1220,7 +1220,7 @@ void GenericError(AMX *amx, int err, int line, char buf[], const char *file) geterr = NULL; else geterr = amx_errs[err]; - if (!(amx->flags & AMX_FLAG_LINEOPS)) + if (!(amx->flags & AMX_FLAG_DEBUG)) { if (geterr == NULL) { @@ -1250,7 +1250,7 @@ void LogError(AMX *amx, int err, const char *fmt, ...) { //does this plugin have debug info? va_list arg; - AMX_DBG *dbg = (AMX_DBG *)(amx->userdata[0]); + //AMX_DBG *dbg = (AMX_DBG *)(amx->userdata[0]); static char buf[1024]; static char vbuf[1024]; *buf = 0; @@ -1259,7 +1259,7 @@ void LogError(AMX *amx, int err, const char *fmt, ...) va_start(arg, fmt); vsprintf(vbuf, fmt, arg); va_end(arg); - +#if 0 if (!dbg || !(dbg->tail)) { if (dbg && amx->curfile < dbg->numFiles && amx->curfile >= 0) @@ -1313,6 +1313,8 @@ void LogError(AMX *amx, int err, const char *fmt, ...) t = dbg->tail; } } +#endif + amx_RaiseError(amx, err); } void MNF_MergeDefinitionFile(const char *file) @@ -1386,7 +1388,7 @@ const char *g_LastRequestedFunc = NULL; #define REGISTER_FUNC(name, func) \ { \ pFunc = new func_s; \ - pFunc->pfn = func; \ + pFunc->pfn = (void *)func; \ pFunc->desc = name; \ g_functions.put(pFunc); \ } @@ -1398,6 +1400,16 @@ void MNF_RegisterFunction(void *pfn, const char *description) REGISTER_FUNC(description, pfn); } +void Module_UncacheFunctions() +{ + g_functions.clear(); +} + +int amx_Execv() +{ + return AMX_ERR_NOTFOUND; +} + void Module_CacheFunctions() { func_s *pFunc; @@ -1430,7 +1442,7 @@ void Module_CacheFunctions() // other amx stuff REGISTER_FUNC("amx_Exec", amx_Exec) - REGISTER_FUNC("amx_Execv", amx_Execv) + REGISTER_FUNC("amx_Execv", amx_Execv) //I HOPE NO ONE USES THIS!!!! REGISTER_FUNC("amx_Allot", amx_Allot) REGISTER_FUNC("amx_FindPublic", amx_FindPublic) REGISTER_FUNC("amx_FindNative", amx_FindNative) diff --git a/amxmodx/modules.h b/amxmodx/modules.h index 296200fc..727f8010 100755 --- a/amxmodx/modules.h +++ b/amxmodx/modules.h @@ -45,135 +45,8 @@ #undef C_DLLEXPORT #define C_DLLEXPORT extern "C" DLLEXPORT -#define AMX_INTERFACE_VERSION 6 - #define RELOAD_MODULE 0 #define STATIC_MODULE 1 -struct module_info_s { - const char* name; - const char* author; - const char* version; - int ivers; - int type; - long int serial; -}; - -// Small scripting language -struct pfnamx_engine_g { - uint16_t* (*pfnamx_Align16)(uint16_t *); // value - uint32_t* (*pfnamx_Align32)(uint32_t *); // value - int (*pfnamx_Allot)(AMX*, int, cell*, cell**); // amx, length, amx_addr, phys_addr - int (*pfnamx_Callback)(AMX*, cell , cell*, cell*); // amx, index,result,params - int (*pfnamx_Clone)(AMX*, AMX*, void*); // amxClone, amxSrc, data - int (*pfnamx_Debug)(AMX*); // default debug procedure, does nothing // amx - int (*pfnamx_Exec)(AMX*, cell*, int , int , ...); // amx, return val, index, num_params, ... - int (*pfnamx_Execv)(AMX*, cell*, int , int, cell[]); // amx, return val, index, num_params, param[] - int (*pfnamx_FindPublic)(AMX*, char*, int*); // amx, func name, index - int (*pfnamx_FindPubVar)(AMX*, char*, cell*); // anx, var name, amx_addr - int (*pfnamx_FindTagId)(AMX*, cell , char*); // amx. tag_id, tagname - int (*pfnamx_Flags)(AMX*,uint16_t *); // amx, flags - int (*pfnamx_GetAddr)(AMX*,cell ,cell**); // amx, amx_addr, phys_addr - int (*pfnamx_GetPublic)(AMX*, int , char*); // amx, index, funcname - int (*pfnamx_GetPubVar)(AMX*, int , char*, cell*); // amx, index, varname, amx_addr - int (*pfnamx_GetString)(char*dest,cell*); // dest, source - int (*pfnamx_GetTag)(AMX*, int , char*, cell*); // amx, index, tagname, tag_id - int (*pfnamx_GetUserData)(AMX*, long , void **); // amx, tag, ptr - int (*pfnamx_Init)(AMX*, void *); // amx, program - int (*pfnamx_InitJIT)(AMX*, void *, void *); // amx, reloc_table, native_code - int (*pfnamx_MemInfo)(AMX*, long*, long*, long*); // amx, codesize, datasize, stackheap - int (*pfnamx_NameLength)(AMX*, int*); // amx, length - AMX_NATIVE_INFO * (*pfnamx_NativeInfo)(char*,AMX_NATIVE ); // name, func - int (*pfnamx_NumPublics)(AMX*, int*); // amx, number - int (*pfnamx_NumPubVars)(AMX*, int*); // amx, number - int (*pfnamx_NumTags)(AMX*, int*); // amx, number - int (*pfnamx_RaiseError)(AMX*, int ); // amx, error - int (*pfnamx_Register)(AMX*, AMX_NATIVE_INFO*, int ); // amx, nativelist, number - int (*pfnamx_Release)(AMX*, cell ); // amx, amx_addr - int (*pfnamx_SetCallback)(AMX*, AMX_CALLBACK ); // amx, callback - int (*pfnamx_SetDebugHook)(AMX*, AMX_DEBUG ); // amx, debug - int (*pfnamx_SetString)(cell*, char*, int ); // dest, source, pack - int (*pfnamx_SetUserData)(AMX*, long , void*); // amx, tag, prt - int (*pfnamx_StrLen)(cell*, int*); // amx, cstring, length -}; -extern pfnamx_engine_g* g_engAmxFunc; - -#define AMX_ALIGN16 (*g_engAmxFunc->pfnamx_Align16) -#define AMX_ALIGN32 (*g_engAmxFunc->pfnamx_Align32) -#define AMX_ALLOT (*g_engAmxFunc->pfnamx_Allot) -#define AMX_CALLBACK (*g_engAmxFunc->pfnamx_Callback) -#define AMX_CLONE (*g_engAmxFunc->pfnamx_Clone) -#define AMX_DEBUG (*g_engAmxFunc->pfnamx_Debug) -#define AMX_EXEC (*g_engAmxFunc->pfnamx_Exec) -#define AMX_EXECV (*g_engAmxFunc->pfnamx_Execv) -#define AMX_FINDPUBLIC (*g_engAmxFunc->pfnamx_FindPublic) -#define AMX_FINDPUBVAR (*g_engAmxFunc->pfnamx_FindPubVar) -#define AMX_FINDTAGID (*g_engAmxFunc->pfnamx_FindTagId) -#define AMX_FLAGS (*g_engAmxFunc->pfnamx_Flags) -#define AMX_GETADDR (*g_engAmxFunc->pfnamx_GetAddr) -#define AMX_GETPUBLIC (*g_engAmxFunc->pfnamx_GetPublic) -#define AMX_GETPUBVAR (*g_engAmxFunc->pfnamx_GetPubVar) -#define AMX_GETSTRING (*g_engAmxFunc->pfnamx_GetString) -#define AMX_GETTAG (*g_engAmxFunc->pfnamx_GetTag) -#define AMX_GETUSERDATA (*g_engAmxFunc->pfnamx_GetUserData) -#define AMX_INIT (*g_engAmxFunc->pfnamx_Init) -#define AMX_INITJIT (*g_engAmxFunc->pfnamx_InitJIT) -#define AMX_MEMINFO (*g_engAmxFunc->pfnamx_MemInfo) -#define AMX_NAMELENGTH (*g_engAmxFunc->pfnamx_NameLength) -#define AMX_NATIVEINFO (*g_engAmxFunc->pfnamx_NativeInfo) -#define AMX_NUMPUBLICS (*g_engAmxFunc->pfnamx_NumPublics) -#define AMX_NUMPUBVARS (*g_engAmxFunc->pfnamx_NumPubVars) -#define AMX_NUMTAGS (*g_engAmxFunc->pfnamx_NumTags) -#define AMX_RAISEERROR (*g_engAmxFunc->pfnamx_RaiseError) -#define AMX_REGISTER (*g_engAmxFunc->pfnamx_Register) -#define AMX_RELEASE (*g_engAmxFunc->pfnamx_Release) -#define AMX_SETCALLBACK (*g_engAmxFunc->pfnamx_SetCallback) -#define AMX_SETDEBUGHOOK (*g_engAmxFunc->pfnamx_SetDebugHook) -#define AMX_SETSTRING (*g_engAmxFunc->pfnamx_SetString) -#define AMX_SETUSERDATA (*g_engAmxFunc->pfnamx_SetUserData) -#define AMX_STRLEN (*g_engAmxFunc->pfnamx_StrLen) - -// Modules API -struct pfnmodule_engine_g { - int (*pfnadd_amxnatives)(module_info_s*,AMX_NATIVE_INFO*); // list - char* (*pfnbuild_pathname)(char*, ...); // format, .... - void (*pfncopy_amxmemory)(cell*,cell*,int); // dest, src, len - char* (*pfnformat_amxstring)(AMX*, cell*, int ,int& ); // amx, format, start pos, len - cell* (*pfnget_amxaddr)(AMX*,cell ); // amx, cell - AMX* (*pfnget_amxscript)(int, void**,const char**); // id, code, name - const char* (*pfnget_amxscriptname)(AMX* amx); // amx - char* (*pfnget_amxstring)(AMX*,cell,int, int&); // amx, src, buffer (0-3), len - void (*pfnget_modname)(char*); // modname - int (*pfnload_amxscript)(AMX*, void**, const char*, char[64], int); // amx, code, path, error info - void (*pfnprint_console)(char*, ...); // format, .... - void (*pfnreport_error)(int code, char*, ... ); - int (*pfnset_amxnatives)(AMX*,char[64]); // amx, error info - int (*pfnset_amxstring)(AMX*,cell ,const char*,int); // amx, dest, string, maxlen - int (*pfnamxstring_length)(cell*); // src - int (*pfnunload_amxscript)(AMX* amx,void**); // amx, code - void* (*pfnalloc_amxmemory)(void**,int size); - void (*pfnfree_amxmemory)(void**); -}; -extern pfnmodule_engine_g* g_engModuleFunc; - -#define ADD_AMXNATIVES (*g_engModuleFunc->pfnadd_amxnatives) -#define AMXSTRING_LENGTH (*g_engModuleFunc->pfnamxstring_length) -#define BUILD_PATHNAME (*g_engModuleFunc->pfnbuild_pathname) -#define COPY_AMXMEMORY (*g_engModuleFunc->pfncopy_amxmemory) -#define FORMAT_AMXSTRING (*g_engModuleFunc->pfnformat_amxstring) -#define GET_AMXADDR (*g_engModuleFunc->pfnget_amxaddr) -#define GET_AMXSCRIPT (*g_engModuleFunc->pfnget_amxscript) -#define GET_AMXSCRIPTNAME (*g_engModuleFunc->pfnget_amxscriptname) -#define GET_AMXSTRING (*g_engModuleFunc->pfnget_amxstring) -#define GET_MODNAME (*g_engModuleFunc->pfnget_modname) -#define LOAD_AMXSCRIPT (*g_engModuleFunc->pfnload_amxscript) -#define PRINT_CONSOLE (*g_engModuleFunc->pfnprint_console) -#define REPORT_ERROR (*g_engModuleFunc->pfnreport_error) -#define SET_AMXNATIVES (*g_engModuleFunc->pfnset_amxnatives) -#define SET_AMXSTRING (*g_engModuleFunc->pfnset_amxstring) -#define UNLOAD_AMXSCRIPT (*g_engModuleFunc->pfnunload_amxscript) -#define ALLOC_AMXMEMORY (*g_engModuleFunc->pfnalloc_amxmemory) -#define FREE_AMXMEMORY (*g_engModuleFunc->pfnfree_amxmemory) - #endif // __MODULES_H__ diff --git a/amxmodx/msvc/amxmodx_mm.vcproj b/amxmodx/msvc/amxmodx_mm.vcproj index d3cd5f44..e7a85095 100755 --- a/amxmodx/msvc/amxmodx_mm.vcproj +++ b/amxmodx/msvc/amxmodx_mm.vcproj @@ -300,7 +300,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""C:\Hry\Half-Life\SDK\Multiplayer Source\pm_shared";"C:\Hry\Half-Life\SDK\Multiplayer Source\dlls";"C:\Hry\Half-Life\SDK\Multiplayer Source\engine";"C:\Hry\Half-Life\SDK\Multiplayer Source\common";C:\Files\Programming\metamod\metamod" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;PAWN_CELL_SIZE=32;ASM32;JIT" BasicRuntimeChecks="3" RuntimeLibrary="5" StructMemberAlignment="3" @@ -319,7 +319,7 @@ + + @@ -780,6 +784,9 @@ + + diff --git a/amxmodx/srvcmd.cpp b/amxmodx/srvcmd.cpp index e6220b73..79707c84 100755 --- a/amxmodx/srvcmd.cpp +++ b/amxmodx/srvcmd.cpp @@ -150,14 +150,14 @@ void amx_command(){ print_srvconsole( "%s %s\n", Plugin_info.name, Plugin_info.version); print_srvconsole( "Authors: %s (%s)\n", "Felix \"SniperBeamer\" Geyer, David \"BAILOPAN\" Anderson, Pavol \"PM OnoTo\" Marko, Jonny \"Got His Gun\" Bergstrom, and Lukasz \"SidLuke\" Wlasinski.", Plugin_info.url); print_srvconsole( "Compiled: %s\n", __DATE__ ", " __TIME__); -#ifdef JIT - print_srvconsole( "Core mode: JIT\n"); +#if defined JIT && !defined ASM32 + print_srvconsole( "Core mode: JIT Only\n"); +#elif !defined JIT && defined ASM32 + print_srvconsole( "Core mode: ASM32 Only\n"); +#elif defined JIT && defined ASM32 + print_srvconsole( "Core mode: JIT+ASM32\n"); #else -#ifdef ASM32 - print_srvconsole( "Core mode: ASM\n"); -#else - print_srvconsole( "Core mode: Normal\n"); -#endif + print_srvconsole( "Core mode: Normal\n"); #endif } else if (!strcmp(cmd,"modules")) @@ -264,39 +264,19 @@ void amx_command(){ void plugin_srvcmd() { - - cell ret = 0; - int err; - const char* cmd = CMD_ARGV(0); - -#ifdef ENABLEEXEPTIONS - try{ -#endif + cell ret = 0; + const char* cmd = CMD_ARGV(0); - CmdMngr::iterator a = g_commands.srvcmdbegin(); - - while ( a ) - { - if ( (*a).matchCommand( cmd ) && - (*a).getPlugin()->isExecutable( (*a).getFunction() ) ) - { - - if ((err = amx_Exec( (*a).getPlugin()->getAMX(), &ret , (*a).getFunction() - , 3 , g_srvindex , (*a).getFlags() , (*a).getId() )) != AMX_ERR_NONE) - { - LogError((*a).getPlugin()->getAMX(), err, ""); - } - if ( ret ) break; - } - - ++a; - } - -#ifdef ENABLEEXEPTIONS - }catch( ... ) + CmdMngr::iterator a = g_commands.srvcmdbegin(); + + while ( a ) + { + if ( (*a).matchCommand( cmd ) && + (*a).getPlugin()->isExecutable( (*a).getFunction() ) ) { - AMXXLOG_Log( "[AMXX] fatal error at forward function execution"); + cell ret = executeForwards((*a).getFunction(), g_srvindex, (*a).getFlags(), (*a).getId()); + if ( ret ) break; } -#endif - + ++a; + } } diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index 0da9ab63..b2b669e0 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -471,7 +471,7 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params) char token = params[6]; //trim int trim = params[7]; - for (i=0; i