diff --git a/amxmodx/amx.c b/amxmodx/amx.c deleted file mode 100755 index 45f2b6fd..00000000 --- a/amxmodx/amx.c +++ /dev/null @@ -1,4108 +0,0 @@ -/* Abstract Machine for the Small compiler - * - * Copyright (c) ITB CompuPhase, 1997-2004 - * - * 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 - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -// not used -#define AMX_NODYNALOAD - -// 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) - #pragma optimize("g",off) -#endif - -#define WIN32_LEAN_AND_MEAN -#if defined _UNICODE || defined __UNICODE__ || defined UNICODE -# if !defined UNICODE /* for Windows API */ -# define UNICODE -# endif -# if !defined _UNICODE /* for C library */ -# define _UNICODE -# endif -#endif - -#include -#include -#include -#include /* for wchar_t */ -#include -#include "osdefs.h" -#if defined LINUX - #include - #if !defined AMX_NODYNALOAD - #include - #endif -#endif -#if defined __LCC__ - #include /* for wcslen() */ -#endif -#include "amx.h" -#if (defined _Windows && !defined AMX_NODYNALOAD) || defined JIT - #include -#endif - -/* When one or more of the AMX_funcname macris are defined, we want - * to compile only those functions. However, when none of these macros - * is present, we want to compile everything. - */ -#if defined AMX_ALIGN || defined AMX_ALLOT || defined AMX_CLEANUP - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_CLONE || defined AMX_EXEC || defined AMX_FLAGS - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_GETADDR || defined AMX_INIT || defined AMX_MEMINFO - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_NAMELENGTH || defined AMX_NATIVEINFO || defined AMX_RAISEERROR - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_REGISTER || defined AMX_SETCALLBACK || defined AMX_SETDEBUGHOOK - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_XXXNATIVES || defined AMX_XXXPUBLICS || defined AMX_XXXPUBVARS - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_XXXSTRING || defined AMX_XXXTAGS || defined AMX_XXXUSERDATA - #define AMX_EXPLIT_FUNCTIONS -#endif -#if defined AMX_UTF8XXX - #define AMX_EXPLIT_FUNCTIONS -#endif -#if !defined AMX_EXPLIT_FUNCTIONS - /* no constant set, set them all */ - #define AMX_ALIGN /* amx_Align16() and amx_Align32() */ - #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_FLAGS /* amx_Flags() */ - #define AMX_GETADDR /* amx_GetAddr() */ - #define AMX_INIT /* amx_Init() and amx_InitJIT() */ - #define AMX_MEMINFO /* amx_MemInfo() */ - #define AMX_NAMELENGTH /* amx_NameLength() */ - #define AMX_NATIVEINFO /* amx_NativeInfo() */ - #define AMX_RAISEERROR /* amx_RaiseError() */ - #define AMX_REGISTER /* amx_Register() */ - #define AMX_SETCALLBACK /* amx_SetCallback() */ - #define AMX_SETDEBUGHOOK /* amx_SetDebugHook() */ - #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_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 - -typedef enum { - OP_NONE, /* invalid opcode */ - 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, - OP_HEAP, - OP_PROC, - OP_RET, - OP_RETN, - OP_CALL, - OP_CALL_PRI, - 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, - 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, - /* ----- */ - OP_NUM_OPCODES -} OPCODE; - -typedef struct tagFUNCSTUBNT { - uint32_t address PACKED; - uint32_t nameofs PACKED; -} FUNCSTUBNT PACKED; - -#define USENAMETABLE(hdr) \ - ((hdr)->defsize==sizeof(FUNCSTUBNT)) -#define NUMENTRIES(hdr,field,nextfield) \ - (int)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize) -#define GETENTRY(hdr,table,index) \ - (AMX_FUNCSTUB *)((unsigned char*)(hdr) + (int)(hdr)->table + (int)index*(hdr)->defsize) -#define GETENTRYNAME(hdr,entry) \ - ( USENAMETABLE(hdr) \ - ? (char *)((unsigned char*)(hdr) + ((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 */ - 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 */ -} - -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; -} - -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; -} - -#if 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); - - t=s[0]; - s[0]=s[7]; - s[7]=t; - - t=s[1]; - s[1]=s[6]; - s[6]=t; - - t=s[2]; - s[2]=s[5]; - s[5]=t; - - t=s[3]; - s[3]=s[4]; - s[4]=t; -} -#endif - -#if defined AMX_ALIGN || defined AMX_INIT -uint16_t *amx_Align16(uint16_t *v) -{ - assert(sizeof(*v)==2); - init_little_endian(); - if (!amx_LittleEndian) - swap16(v); - return v; -} - -uint32_t *amx_Align32(uint32_t *v) -{ - assert(sizeof(cell)==4); - init_little_endian(); - if (!amx_LittleEndian) - swap32(v); - return v; -} - -#if defined _I64_MAX || defined HAVE_I64 -uint64_t *amx_Align64(uint64_t *v) -{ - assert(sizeof(cell)==8); - init_little_endian(); - if (!amx_LittleEndian) - swap64(v); - return v; -} -#endif /* _I64_MAX || HAVE_I64 */ -#endif /* AMX_ALIGN || AMX_INIT */ - -#if SMALL_CELL_SIZE==16 - #define swapcell swap16 -#elif SMALL_CELL_SIZE==32 - #define swapcell swap32 -#elif SMALL_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) - #define swapcell swap64 -#else - #error Unsupported cell size -#endif - -#if defined AMX_FLAGS -int AMXAPI amx_Flags(AMX *amx,uint16_t *flags) -{ - AMX_HEADER *hdr; - - *flags=0; - if (amx==NULL) - return AMX_ERR_FORMAT; - hdr=(AMX_HEADER *)amx->base; - if (hdr->magic!=AMX_MAGIC) - return AMX_ERR_FORMAT; - if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_versionflags; - return AMX_ERR_NONE; -} -#endif /* AMX_FLAGS */ - -#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; - - 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; - assert(f!=NULL); - - /* now that we have found the function, patch the program so that any - * subsequent call will call the function directly (bypassing this - * callback) - */ - if (amx->sysreq_d!=0) { - /* at the point of the call, the CIP pseudo-register points directly - * behind the SYSREQ instruction and its parameter. - */ - 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 (*(cell*)code==index) { -#else - if (*(cell*)code!=OP_SYSREQ_PRI) { - assert(*(cell*)(code-4)==OP_SYSREQ_C); - assert(*(cell*)code==index); -#endif - *(cell*)(code-4)=amx->sysreq_d; - *(cell*)code=(cell)f; - } /* if */ - } /* if */ - - /* Note: - * params[0] == number of bytes for the additional parameters passed to the native function - * params[1] == first argument - * etc. - */ - - amx->error=AMX_ERR_NONE; - *result = f(amx,params); - return amx->error; -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -int AMXAPI amx_Debug(AMX *amx) -{ - return AMX_ERR_DEBUG; -} - -#if defined JIT - extern int AMXAPI getMaxCodeSize(void); - extern int AMXAPI asm_runJIT(void *sourceAMXbase, void *jumparray, void *compiledAMXbase); -#endif - -#if SMALL_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 RELOC_VALUE(base, v) ((v)+((ucell)(base))) -#endif - -#define DBGPARAM(v) ( (v)=*(cell *)(code+(int)cip), cip+=sizeof(cell) ) - -static int amx_BrowseRelocate(AMX *amx) -{ - AMX_HEADER *hdr; - unsigned char *code; - cell cip; - long codesize; - OPCODE op; - int debug; - int last_sym_global = 0; - #if defined __GNUC__ || defined ASM32 || defined JIT - cell *opcode_list; - #endif - #if defined JIT - int opcode_count = 0; - int reloc_count = 0; - #endif - - assert(amx!=NULL); - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - code=amx->base+(int)hdr->cod; - codesize=hdr->dat - hdr->cod; - - /* sanity checks */ - assert(OP_PUSH_PRI==36); - assert(OP_PROC==46); - assert(OP_SHL==65); - assert(OP_SMUL==72); - assert(OP_EQ==95); - assert(OP_INC_PRI==107); - assert(OP_MOVS==117); - assert(OP_SYMBOL==126); - - /* check the debug hook */ - amx->dbgcode=DBG_INIT; - assert(amx->flags==0); - amx->flags=AMX_FLAG_BROWSE; - debug= amx->debug(amx)==AMX_ERR_NONE; - if (debug) - amx->flags|=AMX_FLAG_DEBUG; - - #if defined __GNUC__ || defined ASM32 || defined JIT - amx_Exec(amx, (cell*)&opcode_list, 0, 0); - #if !defined JIT - amx->sysreq_d=opcode_list[OP_SYSREQ_D]; - #endif - #else - /* ANSI C - * 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; - #endif - - /* start browsing code */ - for (cip=0; cip0 && op=256) { - amx->flags &= ~AMX_FLAG_BROWSE; - return AMX_ERR_INVINSTR; - } /* if */ - #if defined __GNUC__ || defined ASM32 || defined JIT - /* relocate symbol */ - *(cell *)(code+(int)cip) = opcode_list[op]; - #endif - #if defined JIT - opcode_count++; - #endif - cip+=sizeof(cell); - switch (op) { - case OP_LOAD_PRI: /* instructions with 1 parameter */ - case OP_LOAD_ALT: - case OP_LOAD_S_PRI: - case OP_LOAD_S_ALT: - case OP_LREF_PRI: - case OP_LREF_ALT: - case OP_LREF_S_PRI: - case OP_LREF_S_ALT: - case OP_LODB_I: - case OP_CONST_PRI: - case OP_CONST_ALT: - case OP_ADDR_PRI: - case OP_ADDR_ALT: - case OP_STOR_PRI: - case OP_STOR_ALT: - case OP_STOR_S_PRI: - case OP_STOR_S_ALT: - case OP_SREF_PRI: - case OP_SREF_ALT: - case OP_SREF_S_PRI: - case OP_SREF_S_ALT: - case OP_STRB_I: - case OP_LIDX_B: - case OP_IDXADDR_B: - case OP_ALIGN_PRI: - case OP_ALIGN_ALT: - case OP_LCTRL: - case OP_SCTRL: - case OP_PUSH_R: - case OP_PUSH_C: - case OP_PUSH: - case OP_PUSH_S: - case OP_STACK: - case OP_HEAP: - case OP_JREL: - case OP_SHL_C_PRI: - case OP_SHL_C_ALT: - case OP_SHR_C_PRI: - case OP_SHR_C_ALT: - case OP_ADD_C: - case OP_SMUL_C: - case OP_ZERO: - case OP_ZERO_S: - case OP_EQ_C_PRI: - case OP_EQ_C_ALT: - case OP_INC: - case OP_INC_S: - case OP_DEC: - case OP_DEC_S: - case OP_MOVS: - case OP_CMPS: - case OP_FILL: - case OP_HALT: - case OP_BOUNDS: - case OP_SYSREQ_C: - case OP_PUSHADDR: - case OP_SYSREQ_D: - cip+=sizeof(cell); - break; - - case OP_LOAD_I: /* instructions without parameters */ - case OP_STOR_I: - case OP_LIDX: - case OP_IDXADDR: - case OP_MOVE_PRI: - case OP_MOVE_ALT: - case OP_XCHG: - case OP_PUSH_PRI: - case OP_PUSH_ALT: - case OP_POP_PRI: - case OP_POP_ALT: - case OP_PROC: - case OP_RET: - case OP_RETN: - case OP_CALL_PRI: - case OP_SHL: - case OP_SHR: - case OP_SSHR: - case OP_SMUL: - case OP_SDIV: - case OP_SDIV_ALT: - case OP_UMUL: - case OP_UDIV: - case OP_UDIV_ALT: - case OP_ADD: - case OP_SUB: - case OP_SUB_ALT: - case OP_AND: - case OP_OR: - case OP_XOR: - case OP_NOT: - case OP_NEG: - case OP_INVERT: - case OP_ZERO_PRI: - case OP_ZERO_ALT: - case OP_SIGN_PRI: - case OP_SIGN_ALT: - case OP_EQ: - case OP_NEQ: - case OP_LESS: - case OP_LEQ: - case OP_GRTR: - case OP_GEQ: - case OP_SLESS: - case OP_SLEQ: - case OP_SGRTR: - case OP_SGEQ: - case OP_INC_PRI: - case OP_INC_ALT: - case OP_INC_I: - case OP_DEC_PRI: - case OP_DEC_ALT: - case OP_DEC_I: - case OP_SYSREQ_PRI: - case OP_JUMP_PRI: - case OP_SWAP_PRI: - case OP_SWAP_ALT: - case OP_NOP: - break; - - case OP_CALL: /* opcodes that need relocation */ - case OP_JUMP: - case OP_JZER: - case OP_JNZ: - case OP_JEQ: - case OP_JNEQ: - case OP_JLESS: - case OP_JLEQ: - case OP_JGRTR: - case OP_JGEQ: - case OP_JSLESS: - case OP_JSLEQ: - case OP_JSGRTR: - case OP_JSGEQ: - case OP_SWITCH: - #if defined JIT - reloc_count++; - #endif - RELOC_ABS(code, cip); - cip+=sizeof(cell); - break; - - case OP_FILE: { - cell num; - DBGPARAM(num); - DBGPARAM(amx->curfile); - amx->dbgname=(char *)(code+(int)cip); - cip+=num - sizeof(cell); - if (debug) { - assert(amx->flags==(AMX_FLAG_DEBUG | AMX_FLAG_BROWSE)); - amx->dbgcode=DBG_FILE; - amx->debug(amx); - } /* if */ - break; - } /* case */ - case OP_LINE: - DBGPARAM(amx->curline); - DBGPARAM(amx->curfile); - if (debug) { - assert(amx->flags==(AMX_FLAG_DEBUG | AMX_FLAG_BROWSE)); - amx->dbgcode=DBG_LINE; - amx->debug(amx); - } /* if */ - break; - 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; - if (debug && last_sym_global) { /* do global symbols only */ - assert(amx->flags==(AMX_FLAG_DEBUG | AMX_FLAG_BROWSE)); - amx->dbgcode=DBG_SYMBOL; - amx->debug(amx); - } /* if */ - break; - } /* case */ - case OP_SRANGE: - DBGPARAM(amx->dbgaddr); /* dimension level */ - DBGPARAM(amx->dbgparam); /* length */ - if (debug && last_sym_global) { /* do global symbols only */ - assert(amx->flags==(AMX_FLAG_DEBUG | AMX_FLAG_BROWSE)); - amx->dbgcode=DBG_SRANGE; - amx->debug(amx); - } /* if */ - break; - case OP_SYMTAG: - DBGPARAM(amx->dbgparam); /* tag id */ - if (debug && last_sym_global) { /* do global symbols only */ - assert(amx->flags==(AMX_FLAG_DEBUG | AMX_FLAG_BROWSE)); - amx->dbgcode=DBG_SYMTAG; - amx->debug(amx); - } /* if */ - break; - case OP_CASETBL: { - cell num; - int i; - DBGPARAM(num); /* number of records follows the opcode */ - for (i=0; i<=num; i++) { - RELOC_ABS(code, cip+2*i*sizeof(cell)); - #if defined JIT - reloc_count++; - #endif - } /* for */ - cip+=(2*num + 1)*sizeof(cell); - break; - } /* case */ - default: - amx->flags &= ~AMX_FLAG_BROWSE; - return AMX_ERR_INVINSTR; - } /* switch */ - } /* for */ - - #if defined JIT - amx->code_size = getMaxCodeSize()*opcode_count + hdr->cod - + (hdr->stp - hdr->dat); - amx->reloc_size = 2*sizeof(cell)*reloc_count; - #endif - - amx->flags &= ~AMX_FLAG_BROWSE; - amx->flags |= AMX_FLAG_RELOC; - return AMX_ERR_NONE; -} - -static void expand(unsigned char *code, long codesize, long memsize) -{ - ucell c; - struct { - long memloc; - ucell c; - } spare[AMX_EXPANDMARGIN]; - int sh=0,st=0,sc=0; - int shift; - - /* for in-place expansion, move from the end backward */ - assert(memsize % sizeof(cell) == 0); - while (codesize>0) { - c=0; - shift=0; - do { - codesize--; - /* no input byte should be shifted out completely */ - assert(shift<8*sizeof(cell)); - /* we work from the end of a sequence backwards; the final code in - * a sequence may not have the continuation bit set */ - assert(shift>0 || (code[(size_t)codesize] & 0x80)==0); - c|=(ucell)(code[(size_t)codesize] & 0x7f) << shift; - shift+=7; - } while (codesize>0 && (code[(size_t)codesize-1] & 0x80)!=0); - /* sign expand */ - if ((code[(size_t)codesize] & 0x40)!=0) { - while (shift < 8*sizeof(cell)) { - c|=(ucell)0xff << shift; - shift+=8; - } /* while */ - } /* if */ - /* store */ - while (sc&&(spare[sh].memloc>codesize)) { - *(ucell *)(code+(int)spare[sh].memloc)=spare[sh].c; - sh=(sh+1)%AMX_EXPANDMARGIN; - sc--; - } /* while */ - memsize -= sizeof(cell); - assert(memsize>=0); - if ((memsize>codesize)||((memsize==codesize)&&(memsize==0))) { - *(ucell *)(code+(size_t)memsize)=c; - } else { - assert(scflags & AMX_FLAG_RELOC)!=0) - return AMX_ERR_INIT; /* already initialized (may not do so twice) */ - - hdr=(AMX_HEADER *)program; - /* the header is in Little Endian, on a Big Endian machine, swap all - * multi-byte words - */ - init_little_endian(); - if (!amx_LittleEndian) { - amx_Align32((uint32_t*)&hdr->size); - amx_Align16(&hdr->magic); - amx_Align16((uint16_t*)&hdr->flags); - amx_Align16((uint16_t*)&hdr->defsize); - amx_Align32((uint32_t*)&hdr->cod); - amx_Align32((uint32_t*)&hdr->dat); - amx_Align32((uint32_t*)&hdr->hea); - amx_Align32((uint32_t*)&hdr->stp); - amx_Align32((uint32_t*)&hdr->cip); - amx_Align32((uint32_t*)&hdr->publics); - amx_Align32((uint32_t*)&hdr->natives); - amx_Align32((uint32_t*)&hdr->libraries); - amx_Align32((uint32_t*)&hdr->pubvars); - amx_Align32((uint32_t*)&hdr->tags); - } /* if */ - - 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)) - return AMX_ERR_FORMAT; - if (USENAMETABLE(hdr)) { - uint16_t *namelength; - /* when there is a separate name table, check the maximum name length - * in that table - */ - amx_Align32((uint32_t*)&hdr->nametable); - namelength=(uint16_t*)((unsigned char*)program + 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 */ - 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); - - amx->base=(unsigned char *)program; - - /* Set a zero cell at the top of the stack, which functions - * as a sentinel for strings. - */ - * (cell *)(amx->base+(int)hdr->stp-sizeof(cell)) = 0; - - /* set initial values */ - amx->hlw=hdr->hea - hdr->dat; /* stack and heap relative to data segment */ - amx->stp=hdr->stp - hdr->dat - sizeof(cell); - amx->hea=amx->hlw; - amx->stk=amx->stp; - if (amx->callback==NULL) - amx->callback=amx_Callback; - if (amx->debug==NULL) - amx->debug=amx_Debug; - 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. - */ - if (!amx_LittleEndian) { - AMX_FUNCSTUB *fs; - int i,num; - - fs=GETENTRY(hdr,publics,0); - assert(hdr->publics<=hdr->natives); - num=NUMENTRIES(hdr,publics,natives); - for (i=0; iaddress); - if (USENAMETABLE(hdr)) - amx_Align32(&((FUNCSTUBNT*)fs)->nameofs); - fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); - } /* for */ - - fs=GETENTRY(hdr,pubvars,0); - assert(hdr->pubvars<=hdr->tags); - num=NUMENTRIES(hdr,pubvars,tags); - for (i=0; iaddress); - if (USENAMETABLE(hdr)) - amx_Align32(&((FUNCSTUBNT*)fs)->nameofs); - fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); - } /* for */ - - fs=GETENTRY(hdr,tags,0); - if (hdr->file_version<7) { - assert(hdr->tags<=hdr->cod); - num=NUMENTRIES(hdr,tags,cod); - } else { - assert(hdr->tags<=hdr->nametable); - num=NUMENTRIES(hdr,tags,nametable); - } /* if */ - for (i=0; iaddress); - if (USENAMETABLE(hdr)) - amx_Align32(&((FUNCSTUBNT*)fs)->nameofs); - fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); - } /* for */ - } /* if */ - - /* relocate call and jump instructions, optionally gather debug information */ - amx_BrowseRelocate(amx); - - /* load any extension modules that the AMX refers to */ - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD - hdr=(AMX_HEADER *)amx->base; - numlibraries=NUMENTRIES(hdr,libraries,pubvars); - for (i=0; iaddress=(uint32_t)hlib; - } /* for */ - #endif - - return AMX_ERR_NONE; -} - -#if defined JIT - - #if defined __WIN32__ /* this also applies to Win32 "console" applications */ - - int memoryFullAccess( void* addr, int len ) - { - DWORD op; - if ( VirtualProtect( addr, len, PAGE_EXECUTE_READWRITE, &op ) ) - return op; - return 0; - } - - int memorySetAccess( void* addr, int len, int access ) - { - DWORD op; - if ( access == 0 ) - return 0; - return VirtualProtect( addr, len, access, &op ); - } - - #else /* #if defined __WIN32 __ */ - - // TODO: Add cases for Linux, Unix, OS/2, ... - - // DOS32 has no imposed limits on its segments. - #if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused - #endif - int memoryFullAccess( void* addr, int len ) { return 1; } - - #if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused - #endif - int memorySetAccess( void* addr, int len, int access ) { return 1; } - - #endif /* #if defined __WIN32 __ */ - -int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code) -{ - int mac, res; - AMX_HEADER *hdr; - - mac = memoryFullAccess( asm_runJIT, 20000 ); - if ( ! mac ) - return AMX_ERR_INIT_JIT; - - /* copy the prefix */ - memcpy( native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod ); - hdr = native_code; - - /* JIT rulz! (TM) */ - /* MP: added check for correct compilation */ - res = asm_runJIT( amx->base, reloc_table, native_code ); - if ( res != 0 ) - { - memorySetAccess( asm_runJIT, 20000, mac ); - 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; - - memorySetAccess( asm_runJIT, 20000, mac ); - return AMX_ERR_NONE; -} - -#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) -{ - return AMX_ERR_INIT_JIT; -} - -#if defined _MSC_VER - #pragma warning(pop) -#endif - -#endif /* #if defined JIT */ - -#endif /* AMX_INIT */ - -#if defined AMX_CLEANUP -int AMXAPI amx_Cleanup(AMX *amx) -{ - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD - #if defined _Windows - typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx); - #elif defined LINUX - typedef int (*AMX_ENTRY)(AMX *amx); - #endif - AMX_HEADER *hdr; - int numlibraries,i; - AMX_FUNCSTUB *lib; - AMX_ENTRY libcleanup; - #endif - - /* unload all extension modules */ - #if (defined _Windows || defined LINUX) && !defined AMX_NODYNALOAD - hdr=(AMX_HEADER *)amx->base; - assert(hdr->magic==AMX_MAGIC); - numlibraries=NUMENTRIES(hdr,libraries,pubvars); - for (i=0; iaddress!=0) { - char funcname[sNAMEMAX+12]; /* +1 for '\0', +4 for 'amx_', +7 for 'Cleanup' */ - strcpy(funcname,"amx_"); - strcat(funcname,GETENTRYNAME(hdr,lib)); - strcat(funcname,"Cleanup"); - #if defined _Windows - libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname); - #elif defined LINUX - libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname); - #endif - if (libcleanup!=NULL) - libcleanup(amx); - #if defined _Windows - FreeLibrary((HINSTANCE)lib->address); - #elif defined LINUX - dlclose((void*)lib->address); - #endif - } /* if */ - } /* for */ - #endif - return AMX_ERR_NONE; -} -#endif /* AMX_CLEANUP */ - -#if defined AMX_CLONE -int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data) -{ - AMX_HEADER *hdr; - unsigned char _FAR *dataSource; - - if (amxSource==NULL) - return AMX_ERR_FORMAT; - if (amxClone==NULL) - return AMX_ERR_PARAMS; - if ((amxSource->flags & AMX_FLAG_RELOC)==0) - return AMX_ERR_INIT; - hdr=(AMX_HEADER *)amxSource->base; - if (hdr->magic!=AMX_MAGIC) - return AMX_ERR_FORMAT; - if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_versionbase=amxSource->base; - amxClone->hlw=hdr->hea - hdr->dat; /* stack and heap relative to data segment */ - amxClone->stp=hdr->stp - hdr->dat - sizeof(cell); - amxClone->hea=amxClone->hlw; - amxClone->stk=amxClone->stp; - if (amxClone->callback==NULL) - amxClone->callback=amxSource->callback; - 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); - amxClone->data=(unsigned char _FAR *)data; - dataSource=(amxSource->data!=NULL) ? amxSource->data : amxSource->base+(int)hdr->dat; - memcpy(amxClone->data,dataSource,(size_t)(hdr->hea-hdr->dat)); - - /* Set a zero cell at the top of the stack, which functions - * as a sentinel for strings. - */ - * (cell *)(amxClone->data+(int)amxClone->stp) = 0; - - return AMX_ERR_NONE; -} -#endif /* AMX_CLONE */ - -#if defined AMX_MEMINFO -int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap) -{ - AMX_HEADER *hdr; - - if (amx==NULL) - return AMX_ERR_FORMAT; - hdr=(AMX_HEADER *)amx->base; - if (hdr->magic!=AMX_MAGIC) - return AMX_ERR_FORMAT; - if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_versiondat - hdr->cod; - if (datasize!=NULL) - *datasize=hdr->hea - hdr->dat; - if (stackheap!=NULL) - *stackheap=hdr->stp - hdr->hea; - - return AMX_ERR_NONE; -} -#endif /* AMX_MEMINFO */ - -#if defined AMX_NAMELENGTH -int AMXAPI amx_NameLength(AMX *amx, int *length) -{ - AMX_HEADER *hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - if (USENAMETABLE(hdr)) { - uint16_t *namelength=(uint16_t*)(amx->base + hdr->nametable); - *length=*namelength; - assert(hdr->file_version>=7); /* name table exists only for file version 7+ */ - } else { - *length=hdr->defsize - sizeof(uint32_t); - } /* if */ - return AMX_ERR_NONE; -} -#endif /* AMX_NAMELENGTH */ - -#if defined AMX_XXXNATIVES -int AMXAPI amx_NumNatives(AMX *amx, int *number) -{ - AMX_HEADER *hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->natives<=hdr->libraries); - *number=NUMENTRIES(hdr,natives,libraries); - return AMX_ERR_NONE; -} - -int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname) -{ - AMX_HEADER *hdr; - AMX_FUNCSTUB *func; - - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->natives<=hdr->libraries); - if (index>=(cell)NUMENTRIES(hdr,natives,libraries)) - return AMX_ERR_INDEX; - - func=GETENTRY(hdr,natives,index); - strcpy(funcname,GETENTRYNAME(hdr,func)); - return AMX_ERR_NONE; -} - -int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index) -{ - int first,last,mid,result; - char pname[sNAMEMAX+1]; - - amx_NumNatives(amx, &last); - last--; /* last valid index is 1 less than the number of functions */ - first=0; - /* binary search */ - while (first<=last) { - mid=(first+last)/2; - amx_GetNative(amx, mid, pname); - result=strcmp(pname,name); - if (result>0) { - last=mid-1; - } else if (result<0) { - first=mid+1; - } else { - *index=mid; - return AMX_ERR_NONE; - } /* if */ - } /* while */ - /* not found, set to an invalid index, so amx_Exec() will fail */ - *index=INT_MAX; - return AMX_ERR_NOTFOUND; -} -#endif /* AMX_XXXNATIVES */ - -#if defined AMX_XXXPUBLICS -int AMXAPI amx_NumPublics(AMX *amx, int *number) -{ - AMX_HEADER *hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->publics<=hdr->natives); - *number=NUMENTRIES(hdr,publics,natives); - return AMX_ERR_NONE; -} - -int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname) -{ - AMX_HEADER *hdr; - AMX_FUNCSTUB *func; - - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->publics<=hdr->natives); - if (index>=(cell)NUMENTRIES(hdr,publics,natives)) - return AMX_ERR_INDEX; - - func=GETENTRY(hdr,publics,index); - strcpy(funcname,GETENTRYNAME(hdr,func)); - return AMX_ERR_NONE; -} - -int AMXAPI amx_FindPublic(AMX *amx, const char *name, int *index) -{ - int first,last,mid,result; - char pname[sNAMEMAX+1]; - - amx_NumPublics(amx, &last); - last--; /* last valid index is 1 less than the number of functions */ - first=0; - /* binary search */ - while (first<=last) { - mid=(first+last)/2; - amx_GetPublic(amx, mid, pname); - result=strcmp(pname,name); - if (result>0) { - last=mid-1; - } else if (result<0) { - first=mid+1; - } else { - *index=mid; - return AMX_ERR_NONE; - } /* if */ - } /* while */ - /* not found, set to an invalid index, so amx_Exec() will fail */ - *index=INT_MAX; - return AMX_ERR_NOTFOUND; -} -#endif /* AMX_XXXPUBLICS */ - -#if defined AMX_XXXPUBVARS -int AMXAPI amx_NumPubVars(AMX *amx, int *number) -{ - AMX_HEADER *hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->pubvars<=hdr->tags); - *number=NUMENTRIES(hdr,pubvars,tags); - return AMX_ERR_NONE; -} - -int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr) -{ - AMX_HEADER *hdr; - AMX_FUNCSTUB *var; - - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->pubvars<=hdr->tags); - if (index>=(cell)NUMENTRIES(hdr,pubvars,tags)) - return AMX_ERR_INDEX; - - var=GETENTRY(hdr,pubvars,index); - strcpy(varname,GETENTRYNAME(hdr,var)); - *amx_addr=var->address; - return AMX_ERR_NONE; -} - -int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr) -{ - int first,last,mid,result; - char pname[sNAMEMAX+1]; - cell paddr; - - amx_NumPubVars(amx, &last); - last--; /* last valid index is 1 less than the number of functions */ - first=0; - /* binary search */ - while (first<=last) { - mid=(first+last)/2; - amx_GetPubVar(amx, mid, pname, &paddr); - result=strcmp(pname,varname); - if (result>0) { - last=mid-1; - } else if (result<0) { - first=mid+1; - } else { - *amx_addr=paddr; - return AMX_ERR_NONE; - } /* if */ - } /* while */ - /* not found */ - *amx_addr=0; - return AMX_ERR_NOTFOUND; -} -#endif /* AMX_XXXPUBVARS */ - -#if defined AMX_XXXTAGS -int AMXAPI amx_NumTags(AMX *amx, int *number) -{ - AMX_HEADER *hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - if (hdr->file_version<5) { /* the tagname table appeared in file format 5 */ - *number=0; - return AMX_ERR_VERSION; - } /* if */ - if (hdr->file_version<7) { - assert(hdr->tags<=hdr->cod); - *number=NUMENTRIES(hdr,tags,cod); - } else { - assert(hdr->tags<=hdr->nametable); - *number=NUMENTRIES(hdr,tags,nametable); - } /* if */ - return AMX_ERR_NONE; -} - -int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id) -{ - AMX_HEADER *hdr; - AMX_FUNCSTUB *tag; - - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - if (hdr->file_version<5) { /* the tagname table appeared in file format 5 */ - *tagname='\0'; - *tag_id=0; - return AMX_ERR_VERSION; - } /* if */ - - if (hdr->file_version<7) { - assert(hdr->tags<=hdr->cod); - if (index>=(cell)NUMENTRIES(hdr,tags,cod)) - return AMX_ERR_INDEX; - } else { - assert(hdr->tags<=hdr->nametable); - if (index>=(cell)NUMENTRIES(hdr,tags,nametable)) - return AMX_ERR_INDEX; - } /* if */ - - tag=GETENTRY(hdr,tags,index); - strcpy(tagname,GETENTRYNAME(hdr,tag)); - *tag_id=tag->address; - - return AMX_ERR_NONE; -} - -int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname) -{ - int first,last,mid; - cell mid_id; - - #if !defined NDEBUG - /* verify that the tagname table is sorted on the tag_id */ - amx_NumTags(amx, &last); - if (last>0) { - cell cur_id; - amx_GetTag(amx,0,tagname,&cur_id); - for (first=1; firsttag_id) - last=mid-1; - else if (mid_idusertags[index]!=tag; index++) - /* nothing */; - if (index>=AMX_USERNUM) - return AMX_ERR_USERDATA; - *ptr=amx->userdata[index]; - return AMX_ERR_NONE; -} - -int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr) -{ - int index; - - assert(amx!=NULL); - assert(tag!=0); - /* try to find existing tag */ - for (index=0; indexusertags[index]!=tag; index++) - /* nothing */; - /* if not found, try to find empty tag */ - if (index>=AMX_USERNUM) - for (index=0; indexusertags[index]!=0; index++) - /* nothing */; - /* if still not found, quit with error */ - if (index>=AMX_USERNUM) - return AMX_ERR_INDEX; - /* set the tag and the value */ - amx->usertags[index]=tag; - amx->userdata[index]=ptr; - return AMX_ERR_NONE; -} -#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) -{ - int i; - - assert(list!=NULL); - for (i=0; list[i].name!=NULL && (ibase; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - assert(hdr->natives<=hdr->libraries); - numnatives=NUMENTRIES(hdr,natives,libraries); - - err=AMX_ERR_NONE; - func=GETENTRY(hdr,natives,0); - for (i=0; iaddress==0) { - /* this function is not yet located */ - funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL; - if (funcptr!=NULL) - func->address=(uint32_t)funcptr; - else - { - no_function = GETENTRYNAME(hdr,func); - err=AMX_ERR_NOTFOUND; - } - } /* if */ - func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize); - } /* for */ - return err; -} -#endif /* AMX_REGISTER || AMX_EXEC || AMX_INIT */ - -#if defined AMX_NATIVEINFO -AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func) -{ - static AMX_NATIVE_INFO n; - n.name=name; - n.func=func; - return &n; -} -#endif /* AMX_NATIVEINFO */ - -#if defined AMX_EXEC || defined AMX_INIT - -#define GETPARAM(v) ( v=*(cell *)cip++ ) -#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 - /* 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, ...) -{ -static void *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, - &&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, &&op_heap, &&op_proc, &&op_ret, - &&op_retn, &&op_call, &&op_call_pri, &&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, &&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 }; - AMX_HEADER *hdr; - AMX_FUNCSTUB *func; - unsigned char *code, *data; - cell pri,alt,stk,frm,hea; - cell reset_stk, reset_hea, *cip; - cell offs; - ucell codesize; - int num,i; - va_list ap; - int debug; - - /* HACK: return label table (for amx_BrowseRelocate) if amx structure - * has the AMX_FLAG_BROWSE flag set. - */ - if ((amx->flags & AMX_FLAG_BROWSE)==AMX_FLAG_BROWSE) { - assert(sizeof(cell)==sizeof(void *)); - assert(retval!=NULL); - *retval=(cell)((amx->flags & AMX_FLAG_DEBUG)==0 ? amx_opcodelist_nodebug : 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_RELOC)==0) - return AMX_ERR_INIT; - assert((amx->flags & AMX_FLAG_BROWSE)==0); - debug= (amx->flags & AMX_FLAG_DEBUG)!=0; - - /* set up the registers */ - hdr=(AMX_HEADER *)amx->base; - assert(hdr->magic==AMX_MAGIC); - codesize=(ucell)(hdr->dat-hdr->cod); - code=amx->base+(int)hdr->cod; - data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; - hea=amx->hea; - stk=amx->stk; - reset_stk=stk; - reset_hea=hea; - frm=0; /* just to avoid compiler warnings */ - - /* get the start address */ - if (index==AMX_EXEC_MAIN) { - if (hdr->cip<0) - return AMX_ERR_INDEX; - cip=(cell *)(code + (int)hdr->cip); - } else if (index==AMX_EXEC_CONT) { - /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */ - frm=amx->frm; - stk=amx->stk; - hea=amx->hea; - pri=amx->pri; - alt=amx->alt; - reset_stk=amx->reset_stk; - reset_hea=amx->reset_hea; - cip=(cell *)(code + (int)amx->cip); - } else if (index<0) { - return AMX_ERR_INDEX; - } else { - if (index>=NUMENTRIES(hdr,publics,natives)) - return AMX_ERR_INDEX; - func=GETENTRY(hdr,publics,index); - cip=(cell *)(code + (int)func->address); - } /* if */ - /* check values just copied */ - CHKSTACK(); - CHKHEAP(); - init_little_endian(); - - if (debug && index!=AMX_EXEC_CONT) { - /* set the entry point in the debugger by marking a "call" to the - * exported function - */ - amx->dbgcode=DBG_CALL; - amx->dbgaddr=(ucell)((unsigned char*)cip-code); - amx->debug(amx); - } /* if */ - - /* sanity checks */ - assert(OP_PUSH_PRI==36); - assert(OP_PROC==46); - assert(OP_SHL==65); - assert(OP_SMUL==72); - assert(OP_EQ==95); - assert(OP_INC_PRI==107); - assert(OP_MOVS==117); - assert(OP_SYMBOL==126); - #if SMALL_CELL_SIZE==16 - assert(sizeof(cell)==2); - #elif SMALL_CELL_SIZE==32 - assert(sizeof(cell)==4); - #elif SMALL_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; i=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) - ABORT(amx,AMX_ERR_MEMACCESS); - switch (offs) { - case 1: - pri= * (data+(int)pri); - break; - case 2: - pri= * (uint16_t *)(data+(int)pri); - break; - case 4: - pri= * (uint32_t *)(data+(int)pri); - break; - } /* switch */ - NEXT(cip); - op_const_pri: - GETPARAM(pri); - NEXT(cip); - op_const_alt: - GETPARAM(alt); - NEXT(cip); - op_addr_pri: - GETPARAM(pri); - pri+=frm; - NEXT(cip); - op_addr_alt: - GETPARAM(alt); - alt+=frm; - NEXT(cip); - op_stor_pri: - GETPARAM(offs); - *(cell *)(data+(int)offs)=pri; - NEXT(cip); - op_stor_alt: - GETPARAM(offs); - *(cell *)(data+(int)offs)=alt; - NEXT(cip); - op_stor_s_pri: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=pri; - NEXT(cip); - op_stor_s_alt: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=alt; - NEXT(cip); - op_sref_pri: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - *(cell *)(data+(int)offs)=pri; - NEXT(cip); - op_sref_alt: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - *(cell *)(data+(int)offs)=alt; - NEXT(cip); - op_sref_s_pri: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - *(cell *)(data+(int)offs)=pri; - NEXT(cip); - op_sref_s_alt: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - *(cell *)(data+(int)offs)=alt; - NEXT(cip); - op_stor_i: - /* verify address */ - 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) - ABORT(amx,AMX_ERR_MEMACCESS); - switch (offs) { - case 1: - *(data+(int)alt)=(unsigned char)pri; - break; - case 2: - *(uint16_t *)(data+(int)alt)=(uint16_t)pri; - break; - case 4: - *(uint32_t *)(data+(int)alt)=(uint32_t)pri; - break; - } /* switch */ - NEXT(cip); - op_lidx: - offs=pri*sizeof(cell)+alt; - /* verify address */ - if ((offs>=hea && offs=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri= * (cell *)(data+(int)offs); - NEXT(cip); - op_lidx_b: - GETPARAM(offs); - offs=(pri << (int)offs)+alt; - /* verify address */ - if ((offs>=hea && offs=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri= * (cell *)(data+(int)offs); - NEXT(cip); - op_idxaddr: - pri=pri*sizeof(cell)+alt; - NEXT(cip); - op_idxaddr_b: - GETPARAM(offs); - pri=(pri << (int)offs)+alt; - NEXT(cip); - op_align_pri: - GETPARAM(offs); - if (amx_LittleEndian && offscod; - break; - case 1: - pri=hdr->dat; - break; - case 2: - pri=hea; - break; - case 3: - pri=amx->stp; - break; - case 4: - pri=stk; - break; - case 5: - pri=frm; - break; - case 6: - pri=(cell)((unsigned char *)cip - code); - break; - } /* switch */ - NEXT(cip); - op_sctrl: - GETPARAM(offs); - switch (offs) { - case 0: - case 1: - case 3: - /* cannot change these parameters */ - break; - case 2: - hea=pri; - break; - case 4: - stk=pri; - break; - case 5: - frm=pri; - break; - case 6: - cip=(cell *)(code + (int)pri); - break; - } /* switch */ - NEXT(cip); - op_move_pri: - pri=alt; - NEXT(cip); - op_move_alt: - alt=pri; - NEXT(cip); - op_xchg: - offs=pri; /* offs is a temporary variable */ - pri=alt; - alt=offs; - NEXT(cip); - op_push_pri: - PUSH(pri); - NEXT(cip); - op_push_alt: - PUSH(alt); - NEXT(cip); - op_push_c: - GETPARAM(offs); - PUSH(offs); - NEXT(cip); - op_push_r: - GETPARAM(offs); - while (offs--) - PUSH(pri); - NEXT(cip); - op_push: - GETPARAM(offs); - PUSH(* (cell *)(data+(int)offs)); - NEXT(cip); - op_push_s: - GETPARAM(offs); - PUSH(* (cell *)(data+(int)frm+(int)offs)); - NEXT(cip); - op_pop_pri: - POP(pri); - NEXT(cip); - op_pop_alt: - POP(alt); - NEXT(cip); - op_stack: - GETPARAM(offs); - alt=stk; - stk+=offs; - CHKMARGIN(); - CHKSTACK(); - if (debug && offs>0) { - amx->dbgcode=DBG_CLRSYM; - amx->stk=stk; - amx->hea=hea; - amx->debug(amx); - } /* if */ - NEXT(cip); - op_stack_nodebug: - GETPARAM(offs); - alt=stk; - stk+=offs; - CHKMARGIN(); - CHKSTACK(); - NEXT(cip); - op_heap: - GETPARAM(offs); - alt=hea; - hea+=offs; - CHKMARGIN(); - CHKHEAP(); - NEXT(cip); - op_proc: - PUSH(frm); - frm=stk; - CHKMARGIN(); - NEXT(cip); - op_ret: - POP(frm); - POP(offs); - /* verify the return address */ - if ((ucell)offs>=codesize) - ABORT(amx,AMX_ERR_MEMACCESS); - cip=(cell *)(code+(int)offs); - if (debug) { - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_RETURN; - amx->dbgparam=pri; /* store "return value" */ - amx->debug(amx); - } /* if */ - NEXT(cip); - op_ret_nodebug: - POP(frm); - POP(offs); - /* verify the return address */ - if ((ucell)offs>=codesize) - ABORT(amx,AMX_ERR_MEMACCESS); - cip=(cell *)(code+(int)offs); - NEXT(cip); - op_retn: - 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 */ - if (debug) { - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_RETURN; - amx->dbgparam=pri; /* store "return value" */ - amx->debug(amx); - amx->dbgcode=DBG_CLRSYM; - amx->debug(amx); - } /* if */ - NEXT(cip); - op_retn_nodebug: - 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_call: - PUSH(((unsigned char *)cip-code)+sizeof(cell));/* push address behind instruction */ - cip=JUMPABS(code, cip); /* jump to the address */ - if (debug) { - amx->dbgcode=DBG_CALL; - amx->dbgaddr=(ucell)((unsigned char*)cip-code); - amx->debug(amx); - } /* if */ - 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: - PUSH((unsigned char *)cip-code); - cip=(cell *)(code+(int)pri); - if (debug) { - amx->dbgcode=DBG_CALL; - amx->dbgaddr=pri; - amx->debug(amx); - } /* if */ - NEXT(cip); - op_call_pri_nodebug: - PUSH((unsigned char *)cip-code); - cip=(cell *)(code+(int)pri); - NEXT(cip); - op_jump: - /* since the GETPARAM() macro modifies cip, you cannot - * do GETPARAM(cip) directly */ - cip=JUMPABS(code, cip); - NEXT(cip); - op_jrel: - offs=*cip; - cip=(cell *)((unsigned char *)cip + (int)offs + sizeof(cell)); - NEXT(cip); - op_jzer: - if (pri==0) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jnz: - if (pri!=0) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jeq: - if (pri==alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jneq: - if (pri!=alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jless: - if ((ucell)pri < (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jleq: - if ((ucell)pri <= (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jgrtr: - if ((ucell)pri > (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jgeq: - if ((ucell)pri >= (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jsless: - if (prialt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_jsgeq: - if (pri>=alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - NEXT(cip); - op_shl: - pri<<=alt; - NEXT(cip); - op_shr: - pri=(ucell)pri >> (ucell)alt; - NEXT(cip); - op_sshr: - pri>>=alt; - NEXT(cip); - op_shl_c_pri: - GETPARAM(offs); - pri<<=offs; - NEXT(cip); - op_shl_c_alt: - GETPARAM(offs); - alt<<=offs; - NEXT(cip); - op_shr_c_pri: - GETPARAM(offs); - pri=(ucell)pri >> (ucell)offs; - NEXT(cip); - op_shr_c_alt: - GETPARAM(offs); - alt=(ucell)alt >> (ucell)offs; - NEXT(cip); - op_smul: - pri*=alt; - NEXT(cip); - op_sdiv: - 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 */ - alt=offs; - NEXT(cip); - op_sdiv_alt: - if (pri==0) - ABORT(amx,AMX_ERR_DIVIDE); - /* divide must always round down; this is a bit - * involved to do in a machine-independent way. - */ - offs=(alt % pri + pri) % pri; /* true modulus */ - pri=(alt - offs) / pri; /* division result */ - alt=offs; - NEXT(cip); - op_umul: - pri=(ucell)pri * (ucell)alt; - NEXT(cip); - op_udiv: - if (alt==0) - ABORT(amx,AMX_ERR_DIVIDE); - offs=(ucell)pri % (ucell)alt; /* temporary storage */ - pri=(ucell)pri / (ucell)alt; - alt=offs; - NEXT(cip); - op_udiv_alt: - if (pri==0) - ABORT(amx,AMX_ERR_DIVIDE); - offs=(ucell)alt % (ucell)pri; /* temporary storage */ - pri=(ucell)alt / (ucell)pri; - alt=offs; - NEXT(cip); - op_add: - pri+=alt; - NEXT(cip); - op_sub: - pri-=alt; - NEXT(cip); - op_sub_alt: - pri=alt-pri; - NEXT(cip); - op_and: - pri&=alt; - NEXT(cip); - op_or: - pri|=alt; - NEXT(cip); - op_xor: - pri^=alt; - NEXT(cip); - op_not: - pri=!pri; - NEXT(cip); - op_neg: - pri=-pri; - NEXT(cip); - op_invert: - pri=~pri; - NEXT(cip); - op_add_c: - GETPARAM(offs); - pri+=offs; - NEXT(cip); - op_smul_c: - GETPARAM(offs); - pri*=offs; - NEXT(cip); - op_zero_pri: - pri=0; - NEXT(cip); - op_zero_alt: - alt=0; - NEXT(cip); - op_zero: - GETPARAM(offs); - *(cell *)(data+(int)offs)=0; - NEXT(cip); - op_zero_s: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=0; - NEXT(cip); - op_sign_pri: - if ((pri & 0xff)>=0x80) - pri|= ~ (ucell)0xff; - NEXT(cip); - op_sign_alt: - if ((alt & 0xff)>=0x80) - alt|= ~ (ucell)0xff; - NEXT(cip); - op_eq: - pri= pri==alt ? 1 : 0; - NEXT(cip); - op_neq: - pri= pri!=alt ? 1 : 0; - NEXT(cip); - op_less: - pri= (ucell)pri < (ucell)alt ? 1 : 0; - NEXT(cip); - op_leq: - pri= (ucell)pri <= (ucell)alt ? 1 : 0; - NEXT(cip); - op_grtr: - pri= (ucell)pri > (ucell)alt ? 1 : 0; - NEXT(cip); - op_geq: - pri= (ucell)pri >= (ucell)alt ? 1 : 0; - NEXT(cip); - op_sless: - pri= prialt ? 1 : 0; - NEXT(cip); - op_sgeq: - pri= pri>=alt ? 1 : 0; - NEXT(cip); - op_eq_c_pri: - GETPARAM(offs); - pri= pri==offs ? 1 : 0; - NEXT(cip); - op_eq_c_alt: - GETPARAM(offs); - pri= alt==offs ? 1 : 0; - NEXT(cip); - op_inc_pri: - pri++; - NEXT(cip); - op_inc_alt: - alt++; - NEXT(cip); - op_inc: - GETPARAM(offs); - *(cell *)(data+(int)offs) += 1; - NEXT(cip); - op_inc_s: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs) += 1; - NEXT(cip); - op_inc_i: - *(cell *)(data+(int)pri) += 1; - NEXT(cip); - op_dec_pri: - pri--; - NEXT(cip); - op_dec_alt: - alt--; - NEXT(cip); - op_dec: - GETPARAM(offs); - *(cell *)(data+(int)offs) -= 1; - NEXT(cip); - op_dec_s: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs) -= 1; - NEXT(cip); - op_dec_i: - *(cell *)(data+(int)pri) -= 1; - NEXT(cip); - op_movs: - GETPARAM(offs); - /* verify top & bottom memory addresses, for both source and destination - * addresses - */ - if ((pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - 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); - op_cmps: - GETPARAM(offs); - /* verify top & bottom memory addresses, for both source and destination - * addresses - */ - if ((pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - 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) - ABORT(amx,AMX_ERR_MEMACCESS); - 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)) - *(cell *)(data+i) = pri; - NEXT(cip); - op_halt: - GETPARAM(offs); - if (retval!=NULL) - *retval=pri; - /* store complete status */ - amx->frm=frm; - amx->stk=stk; - amx->hea=hea; - amx->pri=pri; - amx->alt=alt; - amx->cip=(cell)((unsigned char*)cip-code); - if (debug) { - amx->dbgcode=DBG_TERMINATE; - amx->dbgaddr=(cell)((unsigned char *)cip-code); - amx->dbgparam=offs; - amx->debug(amx); - } /* if */ - if (offs==AMX_ERR_SLEEP) { - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - return (int)offs; - } /* if */ - ABORT(amx,(int)offs); - op_bounds: - GETPARAM(offs); - if ((ucell)pri>(ucell)offs) - ABORT(amx,AMX_ERR_BOUNDS); - NEXT(cip); - op_sysreq_pri: - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - num=amx->callback(amx,pri,&pri,(cell *)(data+(int)stk)); - 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 */ - NEXT(cip); - op_sysreq_c: - GETPARAM(offs); - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - num=amx->callback(amx,offs,&pri,(cell *)(data+(int)stk)); - 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 */ - NEXT(cip); - op_sysreq_d: - GETPARAM(offs); - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - pri=((AMX_NATIVE)offs)(amx,(cell *)(data+(int)stk)); - if (amx->error!=AMX_ERR_NONE) { - if (amx->error==AMX_ERR_SLEEP) { - amx->pri=pri; - amx->alt=alt; - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - return num; - } /* if */ - ABORT(amx,amx->error); - } /* if */ - NEXT(cip); - op_file: - GETPARAM(offs); - cip=(cell *)((unsigned char *)cip + (int)offs); - 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); - if (debug) { - amx->frm=frm; - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_LINE; - num=amx->debug(amx); - if (num!=AMX_ERR_NONE) { - if (num==AMX_ERR_SLEEP) { - amx->pri=pri; - amx->alt=alt; - amx->cip=(cell)((unsigned char*)cip-code); - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - } /* if */ - ABORT(amx,num); - } /* if */ - } /* if */ - NEXT(cip); - op_line_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->curline); - GETPARAM(amx->curfile); - 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 */ - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->debug(amx); - } /* if */ - 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; - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->debug(amx); - } /* if */ - NEXT(cip); - op_srange_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - cip+=2; - NEXT(cip); - op_symtag: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgparam); /* tag id */ - amx->dbgcode=DBG_SYMTAG; - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->debug(amx); - } /* if */ - NEXT(cip); - op_symtag_nodebug: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - cip+=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 */ - 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 */ - NEXT(cip); - } - op_casetbl: - assert(0); /* this should not occur during execution */ - NEXT(cip); - op_swap_pri: - offs=*(cell *)(data+(int)stk); - *(cell *)(data+(int)stk)=pri; - pri=offs; - NEXT(cip); - op_swap_alt: - offs=*(cell *)(data+(int)stk); - *(cell *)(data+(int)stk)=alt; - alt=offs; - NEXT(cip); - op_pushaddr: - GETPARAM(offs); - PUSH(frm+offs); - NEXT(cip); - op_nop: - NEXT(cip); -} - -#else - /* ANSI C & assembler versions */ - -#if defined ASM32 || defined JIT - /* For Watcom C/C++ use register calling convention (faster); for - * 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". - */ - #if defined __WATCOMC__ - #if !defined STACKARGS /* for AMX32.DLL */ - extern cell amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); - /* The following pragma tells the compiler into which registers - * the parameters have to go. */ - #pragma aux amx_exec_asm parm [eax] [edx] [ebx] [ecx]; - #else - extern cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); - #endif - #elif defined __GNUC__ - /* force "cdecl" by adding an "attribute" to the declaration */ - extern cell amx_exec_asm(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 cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); - #endif -#endif - -int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...) -{ - AMX_HEADER *hdr; - AMX_FUNCSTUB *func; - unsigned char *code, *data; - cell pri,alt,stk,frm,hea; - cell reset_stk, reset_hea, *cip; - ucell codesize; - int i; - va_list ap; - int debug; - #if defined ASM32 || defined JIT - extern void *amx_opcodelist[]; - extern void *amx_opcodelist_nodebug[]; - #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 - - #if defined ASM32 || defined JIT - /* HACK: return label table (for amx_BrowseRelocate) if amx structure - * is not passed. - */ - 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 - */ - *retval=(cell)amx_opcodelist; - #else - *retval=(cell)((amx->flags & AMX_FLAG_DEBUG)==0 ? amx_opcodelist_nodebug : amx_opcodelist); - #endif - return 0; - } /* if */ - #endif - - 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_RELOC)==0) - return AMX_ERR_INIT; - assert((amx->flags & AMX_FLAG_BROWSE)==0); - debug= (amx->flags & AMX_FLAG_DEBUG)!=0; - - /* set up the registers */ - hdr=(AMX_HEADER *)amx->base; - assert(hdr->magic==AMX_MAGIC); - codesize=(ucell)(hdr->dat-hdr->cod); - code=amx->base+(int)hdr->cod; - data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; - hea=amx->hea; - stk=amx->stk; - reset_stk=stk; - reset_hea=hea; - frm=alt=pri=0; /* silence up compiler */ - - /* get the start address */ - if (index==AMX_EXEC_MAIN) { - if (hdr->cip<0) - return AMX_ERR_INDEX; - cip=(cell *)(code + (int)hdr->cip); - } else if (index==AMX_EXEC_CONT) { - /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */ - frm=amx->frm; - stk=amx->stk; - hea=amx->hea; - pri=amx->pri; - alt=amx->alt; - reset_stk=amx->reset_stk; - reset_hea=amx->reset_hea; - cip=(cell *)(code + (int)amx->cip); - } else if (index<0) { - return AMX_ERR_INDEX; - } else { - if (index>=(cell)NUMENTRIES(hdr,publics,natives)) - return AMX_ERR_INDEX; - func=GETENTRY(hdr,publics,index); - cip=(cell *)(code + (int)func->address); - } /* if */ - /* check values just copied */ - CHKSTACK(); - CHKHEAP(); - init_little_endian(); - - if (debug && index!=AMX_EXEC_CONT) { - /* set the entry point in the debugger by marking a "call" to the - * exported function - */ - amx->dbgcode=DBG_CALL; - amx->dbgaddr=(ucell)((unsigned char *)cip-code); - amx->debug(amx); - } /* if */ - - /* sanity checks */ - assert(OP_PUSH_PRI==36); - assert(OP_PROC==46); - assert(OP_SHL==65); - assert(OP_SMUL==72); - assert(OP_EQ==95); - assert(OP_INC_PRI==107); - assert(OP_MOVS==117); - assert(OP_SYMBOL==126); - #if SMALL_CELL_SIZE==16 - assert(sizeof(cell)==2); - #elif SMALL_CELL_SIZE==32 - assert(sizeof(cell)==4); - #elif SMALL_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; istp,hea); - if (i == AMX_ERR_SLEEP) { - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - } else { - /* remove parameters from the stack; do this the "hard" way, because - * the assembler version has no internal knowledge of the local - * variables, so any "clean" way would be a kludge anyway. - */ - amx->stk=reset_stk; - amx->hea=reset_hea; - } /* if */ - return i; - -#else - - for ( ;; ) { - op=(OPCODE) *cip++; - switch (op) { - case OP_LOAD_PRI: - GETPARAM(offs); - pri= * (cell *)(data+(int)offs); - break; - case OP_LOAD_ALT: - GETPARAM(offs); - alt= * (cell *)(data+(int)offs); - break; - case OP_LOAD_S_PRI: - GETPARAM(offs); - pri= * (cell *)(data+(int)frm+(int)offs); - break; - case OP_LOAD_S_ALT: - GETPARAM(offs); - alt= * (cell *)(data+(int)frm+(int)offs); - break; - case OP_LREF_PRI: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - pri= * (cell *)(data+(int)offs); - break; - case OP_LREF_ALT: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - alt= * (cell *)(data+(int)offs); - break; - case OP_LREF_S_PRI: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - pri= * (cell *)(data+(int)offs); - break; - case OP_LREF_S_ALT: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - alt= * (cell *)(data+(int)offs); - break; - case OP_LOAD_I: - /* verify address */ - if (pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri= * (cell *)(data+(int)pri); - break; - case OP_LODB_I: - GETPARAM(offs); - /* verify address */ - if (pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - switch (offs) { - case 1: - pri= * (data+(int)pri); - break; - case 2: - pri= * (uint16_t *)(data+(int)pri); - break; - case 4: - pri= * (uint32_t *)(data+(int)pri); - break; - } /* switch */ - break; - case OP_CONST_PRI: - GETPARAM(pri); - break; - case OP_CONST_ALT: - GETPARAM(alt); - break; - case OP_ADDR_PRI: - GETPARAM(pri); - pri+=frm; - break; - case OP_ADDR_ALT: - GETPARAM(alt); - alt+=frm; - break; - case OP_STOR_PRI: - GETPARAM(offs); - *(cell *)(data+(int)offs)=pri; - break; - case OP_STOR_ALT: - GETPARAM(offs); - *(cell *)(data+(int)offs)=alt; - break; - case OP_STOR_S_PRI: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=pri; - break; - case OP_STOR_S_ALT: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=alt; - break; - case OP_SREF_PRI: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - *(cell *)(data+(int)offs)=pri; - break; - case OP_SREF_ALT: - GETPARAM(offs); - offs= * (cell *)(data+(int)offs); - *(cell *)(data+(int)offs)=alt; - break; - case OP_SREF_S_PRI: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - *(cell *)(data+(int)offs)=pri; - break; - case OP_SREF_S_ALT: - GETPARAM(offs); - offs= * (cell *)(data+(int)frm+(int)offs); - *(cell *)(data+(int)offs)=alt; - break; - case OP_STOR_I: - /* verify address */ - if (alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - *(cell *)(data+(int)alt)=pri; - break; - case OP_STRB_I: - GETPARAM(offs); - /* verify address */ - if (alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - switch (offs) { - case 1: - *(data+(int)alt)=(unsigned char)pri; - break; - case 2: - *(uint16_t *)(data+(int)alt)=(uint16_t)pri; - break; - case 4: - *(uint32_t *)(data+(int)alt)=(uint32_t)pri; - break; - } /* switch */ - break; - case OP_LIDX: - offs=pri*sizeof(cell)+alt; - /* verify address */ - if (offs>=hea && offs=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri= * (cell *)(data+(int)offs); - break; - case OP_LIDX_B: - GETPARAM(offs); - offs=(pri << (int)offs)+alt; - /* verify address */ - if (offs>=hea && offs=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri= * (cell *)(data+(int)offs); - break; - case OP_IDXADDR: - pri=pri*sizeof(cell)+alt; - break; - case OP_IDXADDR_B: - GETPARAM(offs); - pri=(pri << (int)offs)+alt; - break; - case OP_ALIGN_PRI: - GETPARAM(offs); - if (amx_LittleEndian && (size_t)offscod; - break; - case 1: - pri=hdr->dat; - break; - case 2: - pri=hea; - break; - case 3: - pri=amx->stp; - break; - case 4: - pri=stk; - break; - case 5: - pri=frm; - break; - case 6: - pri=(cell)((unsigned char *)cip - code); - break; - } /* switch */ - break; - case OP_SCTRL: - GETPARAM(offs); - switch (offs) { - case 0: - case 1: - case 3: - /* cannot change these parameters */ - break; - case 2: - hea=pri; - break; - case 4: - stk=pri; - break; - case 5: - frm=pri; - break; - case 6: - cip=(cell *)(code + (int)pri); - break; - } /* switch */ - break; - case OP_MOVE_PRI: - pri=alt; - break; - case OP_MOVE_ALT: - alt=pri; - break; - case OP_XCHG: - offs=pri; /* offs is a temporary variable */ - pri=alt; - alt=offs; - break; - case OP_PUSH_PRI: - PUSH(pri); - break; - case OP_PUSH_ALT: - PUSH(alt); - break; - case OP_PUSH_C: - GETPARAM(offs); - PUSH(offs); - break; - case OP_PUSH_R: - GETPARAM(offs); - while (offs--) - PUSH(pri); - break; - case OP_PUSH: - GETPARAM(offs); - PUSH(* (cell *)(data+(int)offs)); - break; - case OP_PUSH_S: - GETPARAM(offs); - PUSH(* (cell *)(data+(int)frm+(int)offs)); - break; - case OP_POP_PRI: - POP(pri); - break; - case OP_POP_ALT: - POP(alt); - break; - case OP_STACK: - GETPARAM(offs); - alt=stk; - stk+=offs; - CHKMARGIN(); - CHKSTACK(); - if (debug && offs>0) { - amx->dbgcode=DBG_CLRSYM; - amx->hea=hea; - amx->stk=stk; - amx->debug(amx); - } /* if */ - break; - case OP_HEAP: - GETPARAM(offs); - alt=hea; - hea+=offs; - CHKMARGIN(); - CHKHEAP(); - break; - case OP_PROC: - PUSH(frm); - frm=stk; - CHKMARGIN(); - break; - case OP_RET: - POP(frm); - POP(offs); - /* verify the return address */ - if ((ucell)offs>=codesize) - ABORT(amx,AMX_ERR_MEMACCESS); - cip=(cell *)(code+(int)offs); - if (debug) { - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_RETURN; - amx->dbgparam=pri; /* store "return value" */ - amx->debug(amx); - } /* if */ - break; - case OP_RETN: - 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 */ - amx->stk=stk; - if (debug) { - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_RETURN; - amx->dbgparam=pri; /* store "return value" */ - amx->debug(amx); - amx->dbgcode=DBG_CLRSYM; - amx->debug(amx); - } /* if */ - break; - case OP_CALL: - PUSH(((unsigned char *)cip-code)+sizeof(cell));/* skip address */ - cip=JUMPABS(code, cip); /* jump to the address */ - if (debug) { - amx->dbgcode=DBG_CALL; - amx->dbgaddr=(ucell)((unsigned char *)cip-code); - amx->debug(amx); - } /* if */ - break; - case OP_CALL_PRI: - PUSH((unsigned char *)cip-code); - cip=(cell *)(code+(int)pri); - if (debug) { - amx->dbgcode=DBG_CALL; - amx->dbgaddr=pri; - amx->debug(amx); - } /* if */ - break; - case OP_JUMP: - /* since the GETPARAM() macro modifies cip, you cannot - * do GETPARAM(cip) directly */ - cip=JUMPABS(code, cip); - break; - case OP_JREL: - offs=*cip; - cip=(cell *)((unsigned char *)cip + (int)offs + sizeof(cell)); - break; - case OP_JZER: - if (pri==0) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JNZ: - if (pri!=0) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JEQ: - if (pri==alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JNEQ: - if (pri!=alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JLESS: - if ((ucell)pri < (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JLEQ: - if ((ucell)pri <= (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JGRTR: - if ((ucell)pri > (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JGEQ: - if ((ucell)pri >= (ucell)alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JSLESS: - if (prialt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_JSGEQ: - if (pri>=alt) - cip=JUMPABS(code, cip); - else - cip=(cell *)((unsigned char *)cip+sizeof(cell)); - break; - case OP_SHL: - pri<<=alt; - break; - case OP_SHR: - pri=(ucell)pri >> (int)alt; - break; - case OP_SSHR: - pri>>=alt; - break; - case OP_SHL_C_PRI: - GETPARAM(offs); - pri<<=offs; - break; - case OP_SHL_C_ALT: - GETPARAM(offs); - alt<<=offs; - break; - case OP_SHR_C_PRI: - GETPARAM(offs); - pri=(ucell)pri >> (int)offs; - break; - case OP_SHR_C_ALT: - GETPARAM(offs); - alt=(ucell)alt >> (int)offs; - break; - case OP_SMUL: - pri*=alt; - break; - case OP_SDIV: - 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 */ - alt=offs; - break; - case OP_SDIV_ALT: - if (pri==0) - ABORT(amx,AMX_ERR_DIVIDE); - /* divide must always round down; this is a bit - * involved to do in a machine-independent way. - */ - offs=(alt % pri + pri) % pri; /* true modulus */ - pri=(alt - offs) / pri; /* division result */ - alt=offs; - break; - case OP_UMUL: - pri=(ucell)pri * (ucell)alt; - break; - case OP_UDIV: - if (alt==0) - ABORT(amx,AMX_ERR_DIVIDE); - offs=(ucell)pri % (ucell)alt; /* temporary storage */ - pri=(ucell)pri / (ucell)alt; - alt=offs; - break; - case OP_UDIV_ALT: - if (pri==0) - ABORT(amx,AMX_ERR_DIVIDE); - offs=(ucell)alt % (ucell)pri; /* temporary storage */ - pri=(ucell)alt / (ucell)pri; - alt=offs; - break; - case OP_ADD: - pri+=alt; - break; - case OP_SUB: - pri-=alt; - break; - case OP_SUB_ALT: - pri=alt-pri; - break; - case OP_AND: - pri&=alt; - break; - case OP_OR: - pri|=alt; - break; - case OP_XOR: - pri^=alt; - break; - case OP_NOT: - pri=!pri; - break; - case OP_NEG: - pri=-pri; - break; - case OP_INVERT: - pri=~pri; - break; - case OP_ADD_C: - GETPARAM(offs); - pri+=offs; - break; - case OP_SMUL_C: - GETPARAM(offs); - pri*=offs; - break; - case OP_ZERO_PRI: - pri=0; - break; - case OP_ZERO_ALT: - alt=0; - break; - case OP_ZERO: - GETPARAM(offs); - *(cell *)(data+(int)offs)=0; - break; - case OP_ZERO_S: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs)=0; - break; - case OP_SIGN_PRI: - if ((pri & 0xff)>=0x80) - pri|= ~ (ucell)0xff; - break; - case OP_SIGN_ALT: - if ((alt & 0xff)>=0x80) - alt|= ~ (ucell)0xff; - break; - case OP_EQ: - pri= pri==alt ? 1 : 0; - break; - case OP_NEQ: - pri= pri!=alt ? 1 : 0; - break; - case OP_LESS: - pri= (ucell)pri < (ucell)alt ? 1 : 0; - break; - case OP_LEQ: - pri= (ucell)pri <= (ucell)alt ? 1 : 0; - break; - case OP_GRTR: - pri= (ucell)pri > (ucell)alt ? 1 : 0; - break; - case OP_GEQ: - pri= (ucell)pri >= (ucell)alt ? 1 : 0; - break; - case OP_SLESS: - pri= prialt ? 1 : 0; - break; - case OP_SGEQ: - pri= pri>=alt ? 1 : 0; - break; - case OP_EQ_C_PRI: - GETPARAM(offs); - pri= pri==offs ? 1 : 0; - break; - case OP_EQ_C_ALT: - GETPARAM(offs); - pri= alt==offs ? 1 : 0; - break; - case OP_INC_PRI: - pri++; - break; - case OP_INC_ALT: - alt++; - break; - case OP_INC: - GETPARAM(offs); - *(cell *)(data+(int)offs) += 1; - break; - case OP_INC_S: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs) += 1; - break; - case OP_INC_I: - *(cell *)(data+(int)pri) += 1; - break; - case OP_DEC_PRI: - pri--; - break; - case OP_DEC_ALT: - alt--; - break; - case OP_DEC: - GETPARAM(offs); - *(cell *)(data+(int)offs) -= 1; - break; - case OP_DEC_S: - GETPARAM(offs); - *(cell *)(data+(int)frm+(int)offs) -= 1; - break; - case OP_DEC_I: - *(cell *)(data+(int)pri) -= 1; - break; - case OP_MOVS: - GETPARAM(offs); - /* verify top & bottom memory addresses, for both source and destination - * addresses - */ - if (pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if (alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - memcpy(data+(int)alt, data+(int)pri, (int)offs); - break; - case OP_CMPS: - GETPARAM(offs); - /* verify top & bottom memory addresses, for both source and destination - * addresses - */ - if (pri>=hea && pri=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if (alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - pri=memcmp(data+(int)alt, data+(int)pri, (int)offs); - break; - case OP_FILL: - GETPARAM(offs); - /* verify top & bottom memory addresses (destination only) */ - if (alt>=hea && alt=(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) - ABORT(amx,AMX_ERR_MEMACCESS); - for (i=(int)alt; (size_t)offs>=sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) - *(cell *)(data+i) = pri; - break; - case OP_HALT: - GETPARAM(offs); - if (retval!=NULL) - *retval=pri; - /* store complete status */ - amx->frm=frm; - amx->stk=stk; - amx->hea=hea; - amx->pri=pri; - amx->alt=alt; - amx->cip=(cell)((unsigned char*)cip-code); - if (debug) { - amx->dbgcode=DBG_TERMINATE; - amx->dbgaddr=(cell)((unsigned char *)cip-code); - amx->dbgparam=offs; - amx->debug(amx); - } /* if */ - if (offs==AMX_ERR_SLEEP) { - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - return (int)offs; - } /* if */ - ABORT(amx,(int)offs); - case OP_BOUNDS: - GETPARAM(offs); - if ((ucell)pri>(ucell)offs) - ABORT(amx,AMX_ERR_BOUNDS); - break; - case OP_SYSREQ_PRI: - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - num=amx->callback(amx,pri,&pri,(cell *)(data+(int)stk)); - 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 */ - break; - case OP_SYSREQ_C: - GETPARAM(offs); - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - num=amx->callback(amx,offs,&pri,(cell *)(data+(int)stk)); - 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 */ - break; - case OP_SYSREQ_D: - GETPARAM(offs); - /* save a few registers */ - amx->cip=(cell)((unsigned char *)cip-code); - amx->hea=hea; - amx->frm=frm; - amx->stk=stk; - pri=((AMX_NATIVE)offs)(amx,(cell *)(data+(int)stk)); - if (amx->error!=AMX_ERR_NONE) { - if (amx->error==AMX_ERR_SLEEP) { - amx->pri=pri; - amx->alt=alt; - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - return num; - } /* if */ - 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); - if (debug) { - amx->frm=frm; - amx->stk=stk; - amx->hea=hea; - amx->dbgcode=DBG_LINE; - num=amx->debug(amx); - if (num!=AMX_ERR_NONE) { - if (num==AMX_ERR_SLEEP) { - amx->pri=pri; - amx->alt=alt; - amx->cip=(cell)((unsigned char*)cip-code); - amx->reset_stk=reset_stk; - amx->reset_hea=reset_hea; - } /* if */ - ABORT(amx,num); - } /* if */ - } /* if */ - 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 */ - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->dbgcode=DBG_SYMBOL; - amx->debug(amx); - } /* if */ - break; - case OP_SRANGE: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgaddr); /* dimension level */ - GETPARAM(amx->dbgparam); /* length */ - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->dbgcode=DBG_SRANGE; - amx->debug(amx); - } /* if */ - break; - case OP_SYMTAG: - assert((amx->flags & AMX_FLAG_BROWSE)==0); - GETPARAM(amx->dbgparam); /* tag id */ - if (debug) { - amx->frm=frm; /* debugger needs this to relocate the symbols */ - amx->dbgcode=DBG_SYMTAG; - amx->debug(amx); - } /* if */ - break; - case OP_JUMP_PRI: - cip=(cell *)(code+(int)pri); - break; - case OP_SWITCH: { - cell *cptr; - - cptr=(cell *)*cip + 1; /* +1, to skip the "casetbl" opcode */ - cip=(cell *)*(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 */ - break; - } /* case */ - case OP_SWAP_PRI: - offs=*(cell *)(data+(int)stk); - *(cell *)(data+(int)stk)=pri; - pri=offs; - break; - case OP_SWAP_ALT: - offs=*(cell *)(data+(int)stk); - *(cell *)(data+(int)stk)=alt; - alt=offs; - break; - case OP_PUSHADDR: - GETPARAM(offs); - PUSH(frm+offs); - break; - case OP_NOP: - break; - case OP_CASETBL: - assert(0); /* should not occur during execution */ - /* drop through to "invalid instruction" */ - default: - ABORT(amx,AMX_ERR_INVINSTR); - } /* switch */ - } /* for */ -#endif -} - -#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 -int AMXAPI amx_SetCallback(AMX *amx,AMX_CALLBACK callback) -{ - assert(amx!=NULL); - assert(callback!=NULL); - amx->callback=callback; - return AMX_ERR_NONE; -} -#endif /* AMX_SETCALLBACK */ - -#if defined AMX_SETDEBUGHOOK -int AMXAPI amx_SetDebugHook(AMX *amx,AMX_DEBUG debug) -{ - assert(amx!=NULL); - assert(debug!=NULL); - amx->debug=debug; - return AMX_ERR_NONE; -} -#endif /* AMX_SETDEBUGHOOK */ - -#if defined AMX_RAISEERROR -int AMXAPI amx_RaiseError(AMX *amx, int error) -{ - assert(error>0); - amx->error=error; - return AMX_ERR_NONE; -} -#endif /* AMX_RAISEERROR */ - -#if defined AMX_GETADDR -int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr) -{ - AMX_HEADER *hdr; - unsigned char *data; - - assert(amx!=NULL); - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - 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) { - *phys_addr=NULL; - return AMX_ERR_MEMACCESS; - } /* if */ - - *phys_addr=(cell *)(data + (int)amx_addr); - return AMX_ERR_NONE; -} -#endif /* AMX_GETADDR */ - -#if defined AMX_ALLOT -int AMXAPI amx_Allot(AMX *amx,int cells,cell *amx_addr,cell **phys_addr) -{ - AMX_HEADER *hdr; - unsigned char *data; - - assert(amx!=NULL); - hdr=(AMX_HEADER *)amx->base; - assert(hdr!=NULL); - assert(hdr->magic==AMX_MAGIC); - data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; - - if (amx->stk - amx->hea - cells*sizeof(cell) < STKMARGIN) - return AMX_ERR_MEMORY; - assert(amx_addr!=NULL); - assert(phys_addr!=NULL); - *amx_addr=amx->hea; - *phys_addr=(cell *)(data + (int)amx->hea); - amx->hea += cells*sizeof(cell); - return AMX_ERR_NONE; -} - -int AMXAPI amx_Release(AMX *amx,cell amx_addr) -{ - if (amx->hea > amx_addr) - amx->hea=amx_addr; - return AMX_ERR_NONE; -} -#endif /* AMX_ALLOT */ - -#if defined AMX_XXXSTRING - -#define CHARBITS (8*sizeof(char)) -#if SMALL_CELL_SIZE==16 - #define CHARMASK (0xffffu << 8*(2-sizeof(char))) -#elif SMALL_CELL_SIZE==32 - #define CHARMASK (0xffffffffuL << 8*(4-sizeof(char))) -#elif SMALL_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 len; - - assert(length!=NULL); - if (cstr==NULL) { - *length=0; - return AMX_ERR_PARAMS; - } /* if */ - - if ((ucell)*cstr>UNPACKEDMAX) { - /* packed string */ - assert(sizeof(char)==1); - len=strlen((char *)cstr); /* find '\0' */ - init_little_endian(); - if (amx_LittleEndian) { - /* on Little Endian machines, toggle the last bytes */ - 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 */ - } else { - for (len=0; cstr[len]!=0; len++) - /* nothing */; - } /* if */ - *length = len; - return AMX_ERR_NONE; -} - -int AMXAPI amx_SetString(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) { - /* 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 */ - } 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; -} -#endif /* AMX_XXXSTRING */ - -#if defined AMX_UTF8XXX - #if defined __BORLANDC__ - #pragma warn -amb -8000 /* ambiguous operators need parentheses */ - #endif -/* amx_UTF8Get() - * Extract a single UTF-8 encoded character from a string and return a pointer - * to the character just behind that UTF-8 character. The parameters "endptr" - * and "value" may be NULL. - * If the code is not valid UTF-8, "endptr" has the value of the input - * parameter "string" and "value" is zero. - */ -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 }; - unsigned char c; - cell result; - int followup; - - assert(string!=NULL); - if (value!=NULL) /* preset, in case of an error */ - *value=0; - if (endptr!=NULL) - *endptr=string; - - c = *(const unsigned char*)string++; - if (c<0x80) { - /* ASCII */ - result=c; - } else { - if (c<0xc0 || c>=0xfe) - return AMX_ERR_PARAMS; /* invalid or "follower" code, quit with error */ - /* At this point we know that the two top bits of c are ones. The two - * bottom bits are always part of the code. We only need to consider - * the 4 remaining bits; i.e., a 16-byte table. This is "utf8_count[]". - * (Actually the utf8_count[] table records the number of follow-up - * bytes minus 1. This is just for convenience.) - */ - assert((c & 0xc0)==0xc0); - followup=(int)utf8_count[(c >> 2) & 0x0f]; - /* The mask depends on the code length; this is just a very simple - * relation. - */ - #define utf8_mask (0x1f >> followup) - result= c & utf8_mask; - /* Collect the follow-up codes using a drop-through switch statement; - * this avoids a loop. In each case, verify the two leading bits. - */ - assert(followup>=0 && followup<=4); - switch (followup) { - case 4: - if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); - case 3: - if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); - case 2: - if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); - case 1: - if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | (c & 0x3f); - case 0: - if (((c=*string++) & 0xc0) != 0x80) goto error; - 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 - * a table with 5 elements. This is "utf8_lowmark[]". - */ - if (result=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff) - goto error; - } /* if */ - - if (value!=NULL) - *value=result; - if (endptr!=NULL) - *endptr=string; - - return AMX_ERR_NONE; - -error: - return AMX_ERR_PARAMS; -} - -/* 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 - * stored. - * The function does not zero-terminate the string. - */ -int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value) -{ - assert(string!=NULL); - if (endptr!=NULL) /* preset, in case of an error */ - *endptr=string; - - if (value<0x80) { - /* 0xxxxxxx */ - if (maxchars < 1) goto error; - *string++ = (char)value; - } else if (value<0x800) { - /* 110xxxxx 10xxxxxx */ - if (maxchars < 2) goto error; - *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) - goto error; /* surrogate pairs and invalid characters */ - *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); - } 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); - } 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); - } /* if */ - - if (endptr!=NULL) - *endptr=string; - return AMX_ERR_NONE; - -error: - return AMX_ERR_PARAMS; -} - -/* amx_UTF8Check() - * Run through a zero-terminated string and check the validity of the UTF-8 - * 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 err=AMX_ERR_NONE; - while (err==AMX_ERR_NONE && *string!='\0') - err=amx_UTF8Get(string,&string,NULL); - return err; -} -#endif /* AMX_UTF8XXX */ diff --git a/amxmodx/amxcore.c b/amxmodx/amxcore.c deleted file mode 100755 index f8a0f38b..00000000 --- a/amxmodx/amxcore.c +++ /dev/null @@ -1,618 +0,0 @@ -/* Core module for the Small AMX - * - * Copyright (c) ITB CompuPhase, 1997-2004 - * - * 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 - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ -#if defined _UNICODE || defined __UNICODE__ || defined UNICODE -# if !defined UNICODE /* for Windows */ -# define UNICODE -# endif -# if !defined _UNICODE /* for C library */ -# define _UNICODE -# endif -#endif - -#include -#include -#include -#include -#include -#include "amx.h" -#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows - #include -#endif - -/* A few compilers do not provide the ANSI C standard "time" functions */ -#if !defined SN_TARGET_PS2 && !defined _WIN32_WCE - #include -#endif - -#if defined _UNICODE -# include -#elif !defined __T - typedef char TCHAR; -# define __T(string) string -# define _tcschr strchr -# 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 -typedef struct _property_list { - struct _property_list *next; - cell id; - char *name; - cell value; - //??? safe AMX (owner of the property) -} proplist; - -static proplist proproot = { NULL }; - -static proplist *list_additem(proplist *root) -{ - proplist *item; - - assert(root!=NULL); - if ((item=(proplist *)malloc(sizeof(proplist)))==NULL) - return NULL; - item->name=NULL; - item->id=0; - item->value=0; - item->next=root->next; - root->next=item; - return item; -} -static void list_delete(proplist *pred,proplist *item) -{ - assert(pred!=NULL); - assert(item!=NULL); - pred->next=item->next; - assert(item->name!=NULL); - free(item->name); - free(item); -} -static void list_setitem(proplist *item,cell id,char *name,cell value) -{ - char *ptr; - - assert(item!=NULL); - if ((ptr=(char *)malloc(strlen(name)+1))==NULL) - return; - if (item->name!=NULL) - free(item->name); - strcpy(ptr,name); - item->name=ptr; - item->id=id; - item->value=value; -} -static proplist *list_finditem(proplist *root,cell id,char *name,cell value, - proplist **pred) -{ - proplist *item=root->next; - proplist *prev=root; - - /* check whether to find by name or by value */ - assert(name!=NULL); - if (strlen(name)>0) { - /* find by name */ - while (item!=NULL && (item->id!=id || stricmp(item->name,name)!=0)) { - prev=item; - item=item->next; - } /* while */ - } else { - /* find by value */ - while (item!=NULL && (item->id!=id || item->value!=value)) { - prev=item; - item=item->next; - } /* while */ - } /* if */ - if (pred!=NULL) - *pred=prev; - return item; -} -#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; - - 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" */ - bytes= * (cell *)(data+(int)amx->frm+2*sizeof(cell)); - /* the number of arguments is the number of bytes divided - * by the size of a cell */ - return bytes/sizeof(cell); -} - -static cell AMX_NATIVE_CALL getarg(AMX *amx, cell *params) -{ - AMX_HEADER *hdr; - uchar *data; - cell value; - - hdr=(AMX_HEADER *)amx->base; - data=amx->data ? amx->data : amx->base+(int)hdr->dat; - /* get the base value */ - value= * (cell *)(data+(int)amx->frm+((int)params[1]+3)*sizeof(cell)); - /* adjust the address in "value" in case of an array access */ - value+=params[2]*sizeof(cell); - /* get the value indirectly */ - value= * (cell *)(data+(int)value); - return value; -} - -static cell AMX_NATIVE_CALL setarg(AMX *amx, cell *params) -{ - AMX_HEADER *hdr; - uchar *data; - cell value; - - hdr=(AMX_HEADER *)amx->base; - data=amx->data ? amx->data : amx->base+(int)hdr->dat; - /* get the base value */ - value= * (cell *)(data+(int)amx->frm+((int)params[1]+3)*sizeof(cell)); - /* 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)) - 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) -{ - return amx->stk - amx->hea; -} - -static cell AMX_NATIVE_CALL funcidx(AMX *amx,cell *params) -{ - char name[64]; - cell *cstr; - int index,err,len; - - amx_GetAddr(amx,params[1],&cstr); - - /* verify string length */ - amx_StrLen(cstr,&len); - if (len>=64) { - amx_RaiseError(amx,AMX_ERR_NATIVE); - return 0; - } /* if */ - - amx_GetString(name,cstr,0); - 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 - uchar b[2]; - #elif SMALL_CELL_SIZE==32 - uchar b[4]; - #elif SMALL_CELL_SIZE==64 - uchar b[8]; - #else - #error Unsupported cell size - #endif - } value; - uchar t; - - assert((size_t)params[0]==sizeof(cell)); - value.c = params[1]; - #if SMALL_CELL_SIZE==16 - t = value.b[0]; - value.b[0] = value.b[1]; - value.b[1] = t; - #elif SMALL_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 - t = value.b[0]; - value.b[0] = value.b[7]; - value.b[7] = t; - t = value.b[1]; - value.b[1] = value.b[6]; - value.b[6] = t; - t = value.b[2]; - value.b[2] = value.b[5]; - value.b[5] = t; - t = value.b[3]; - value.b[3] = value.b[4]; - value.b[4] = t; - #else - #error Unsupported cell size - #endif - return value.c; -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params) -{ - #if defined __WIN32__ || defined _WIN32 || defined WIN32 - return (cell)CharLower((LPTSTR)params[1]); - #elif defined _Windows - return (cell)AnsiLower((LPSTR)params[1]); - #else - return tolower((int)params[1]); - #endif -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params) -{ - #if defined __WIN32__ || defined _WIN32 || defined WIN32 - return (cell)CharUpper((LPTSTR)params[1]); - #elif defined _Windows - return (cell)AnsiUpper((LPSTR)params[1]); - #else - return toupper((int)params[1]); - #endif -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL core_min(AMX *amx,cell *params) -{ - 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) -{ - return params[1] >= params[2] ? params[1] : params[2]; -} - -static cell AMX_NATIVE_CALL core_clamp(AMX *amx,cell *params) -{ - cell value = params[1]; - if (params[2] > params[3]) /* minimum value > maximum value ! */ - amx_RaiseError(amx,AMX_ERR_NATIVE); - if (value < params[2]) - value = params[2]; - else if (value > params[3]) - value = params[3]; - return value; -} - -#if !defined NOPROPLIST -static char *MakePackedString(cell *cptr) -{ - int len; - char *dest; - - amx_StrLen(cptr,&len); - dest=(char *)malloc(len+sizeof(cell)); - amx_GetString(dest,cptr,0); - return dest; -} - -static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params) -{ - cell *cstr; - char *name; - proplist *item; - - amx_GetAddr(amx,params[2],&cstr); - name=MakePackedString(cstr); - item=list_finditem(&proproot,params[1],name,params[3],NULL); - /* if list_finditem() found the value, store the name */ - if (item!=NULL && item->value==params[3] && strlen(name)==0) { - int needed=(strlen(item->name)+sizeof(cell)-1)/sizeof(cell); /* # of cells needed */ - if (verify_addr(amx,(cell)(params[4]+needed))!=AMX_ERR_NONE) { - free(name); - return 0; - } /* if */ - amx_GetAddr(amx,params[4],&cstr); - amx_SetString(cstr,item->name,1,0); - } /* if */ - free(name); - return (item!=NULL) ? item->value : 0; -} - -static cell AMX_NATIVE_CALL setproperty(AMX *amx,cell *params) -{ - cell prev=0; - cell *cstr; - char *name; - proplist *item; - - amx_GetAddr(amx,params[2],&cstr); - name=MakePackedString(cstr); - item=list_finditem(&proproot,params[1],name,params[3],NULL); - if (item==NULL) - item=list_additem(&proproot); - if (item==NULL) { - amx_RaiseError(amx,AMX_ERR_MEMORY); - } else { - prev=item->value; - if (strlen(name)==0) { - free(name); - amx_GetAddr(amx,params[4],&cstr); - name=MakePackedString(cstr); - } /* if */ - list_setitem(item,params[1],name,params[3]); - } /* if */ - free(name); - return prev; -} - -static cell AMX_NATIVE_CALL delproperty(AMX *amx,cell *params) -{ - cell prev=0; - cell *cstr; - char *name; - proplist *item,*pred; - - amx_GetAddr(amx,params[2],&cstr); - name=MakePackedString(cstr); - item=list_finditem(&proproot,params[1],name,params[3],&pred); - if (item!=NULL) { - prev=item->value; - list_delete(pred,item); - } /* if */ - free(name); - return prev; -} - -static cell AMX_NATIVE_CALL existproperty(AMX *amx,cell *params) -{ - cell *cstr; - char *name; - proplist *item; - - amx_GetAddr(amx,params[2],&cstr); - name=MakePackedString(cstr); - item=list_finditem(&proproot,params[1],name,params[3],NULL); - free(name); - return (item!=NULL); -} -#endif - -/* 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 IL_RMULT 1103515245L -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL core_random(AMX *amx,cell *params) -{ - unsigned long lo, hi, ll, lh, hh, hl; - unsigned long result; - - /* one-time initialization (or, mostly one-time) */ - #if !defined SN_TARGET_PS2 && !defined _WIN32_WCE - if (IL_StandardRandom_seed == 0L) - IL_StandardRandom_seed=(unsigned long)time(NULL); - #endif - - lo = IL_StandardRandom_seed & 0xffff; - hi = IL_StandardRandom_seed >> 16; - IL_StandardRandom_seed = IL_StandardRandom_seed * IL_RMULT + 12345; - ll = lo * (IL_RMULT & 0xffff); - lh = lo * (IL_RMULT >> 16 ); - hl = hi * (IL_RMULT & 0xffff); - hh = hi * (IL_RMULT >> 16 ); - result = ((ll + 12345) >> 16) + lh + hl + (hh << 16); - result &= ~LONG_MIN; /* remove sign bit */ - if (params[1]!=0) - result %= params[1]; - return (cell)result; -} - - -AMX_NATIVE_INFO core_Natives[] = { - { "numargs", numargs }, - { "getarg", getarg }, - { "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 - { NULL, NULL } /* terminator */ -}; - -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 - //??? delete only the properties owned by the AMX - while (proproot.next!=NULL) - list_delete(&proproot,proproot.next); - #endif - return AMX_ERR_NONE; -} diff --git a/amxmodx/amxtime.c b/amxmodx/amxtime.c deleted file mode 100755 index 867cb6a9..00000000 --- a/amxmodx/amxtime.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Date/time module for the Small AMX - * - * Copyright (c) ITB CompuPhase, 2001-2002 - * This file may be freely used. No warranties of any kind. - * - * Version: $Id$ - */ -#include -#include -#if defined __WIN32__ || defined _WIN32 - #include - #include -#endif -#include "amx.h" - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL _time(AMX *amx, cell *params) -{ - time_t sec1970; - struct tm gtm; - cell *cptr; - - assert(params[0]==3*sizeof(cell)); - - time(&sec1970); - - /* on DOS/Windows, the timezone is usually not set for the C run-time - * library; in that case gmtime() and localtime() return the same value - */ - gtm=*localtime(&sec1970); - if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_hour; - if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_min; - if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_sec; - - /* the time() function returns the number of seconds since January 1 1970 - * in Universal Coordinated Time (the successor to Greenwich Mean Time) - */ - return sec1970; -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL _date(AMX *amx, cell *params) -{ - time_t sec1970; - struct tm gtm; - cell *cptr; - - assert(params[0]==3*sizeof(cell)); - - time(&sec1970); - - gtm=*localtime(&sec1970); - if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_year+1900; - if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_mon+1; - if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE) - *cptr=gtm.tm_mday; - - return 0; -} - -#if defined __BORLANDC__ || defined __WATCOMC__ - #pragma argsused -#endif -static cell AMX_NATIVE_CALL _tickcount(AMX *amx, cell *params) -{ - // #if defined __WIN32__ || defined _WIN32 - // static int timerset = 0; - // #endif - cell value; - - assert(params[0]==sizeof(cell)); - - //#if defined __WIN32__ || defined _WIN32 - // if (!timerset) { - // timeBeginPeriod(1); /* timeGetTime() is more accurate on WindowsNT -// * if timeBeginPeriod(1) is set */ - // timerset=1; - // } /* if */ - // value=timeGetTime(); /* this value is already in milliseconds */ - // #else - value=(cell)clock(); - /* convert to milliseconds */ - value=(cell)((1000L * (value+CLK_TCK/2)) / CLK_TCK); - //#endif - return value; -} - - -AMX_NATIVE_INFO time_Natives[] = { - { "time", _time }, - { "date", _date }, - { "tickcount", _tickcount }, - { NULL, NULL } /* terminator */ -}; - diff --git a/amxmodx/power.c b/amxmodx/power.c deleted file mode 100755 index f01fcdf0..00000000 --- a/amxmodx/power.c +++ /dev/null @@ -1,42 +0,0 @@ -/* This file implements two native functions. It is provided as - * an example to show how to add native functions. See the manual - * for more information. - * - * Copyright (c) ITB CompuPhase, 1998, 1999 - * This file may be freely used. No warranties of any kind. - */ -#include "amx.h" - -static cell power(AMX *amx, cell *params) -{ - /* power(value, exponent); - * params[1] = value - * params[2] = exponent - */ - cell result = 1; - while (params[2]-- > 0) - result *= params[1]; - return result; -} - -static cell sqroot(AMX *amx, cell *params) -{ - /* sqroot(value); - * params[1] = value - * This routine uses a simple successice approximation algorithm. - */ - cell div = params[1]; - cell result = 1; - while (div > result) { /* end when div == result, or just below */ - div = (div + result) / 2; /* take mean value as new divisor */ - result = params[1] / div; - } /* while */ - return div; -} - -AMX_NATIVE_INFO power_Natives[] = { - { "power", power }, - { "sqroot", sqroot }, - { 0, 0 } /* terminator */ -}; -