From f6b91f9258d32170e0c147946e7579bc1525356e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 25 Jul 2005 00:01:54 +0000 Subject: [PATCH] Initial import of amxxpc --- compiler/amxxpc/amx.cpp | 3984 +++++++++++++++++++++++++++++ compiler/amxxpc/amx.h | 439 ++++ compiler/amxxpc/amxxpc.cpp | 326 +++ compiler/amxxpc/amxxpc.h | 51 + compiler/amxxpc/amxxpc.sln | 21 + compiler/amxxpc/amxxpc.vcproj | 164 ++ compiler/amxxpc/amxxpc1.rc | 72 + compiler/amxxpc/favicon.ico | Bin 0 -> 766 bytes compiler/amxxpc/osdefs.h | 60 + compiler/amxxpc/resource.h | 17 + compiler/amxxpc/resource1.h | 16 + compiler/amxxpc/sclinux.h | 47 + compiler/amxxpc/testmini.c | 155 ++ compiler/amxxpc/zconf.h | 323 +++ compiler/amxxpc/zlib.h | 1200 +++++++++ compiler/amxxpc/zlib.lib | Bin 0 -> 221206 bytes compiler/libpc300/amx.h | 17 +- compiler/libpc300/libpawnc.c | 41 +- compiler/libpc300/libpc300.vcproj | 3 + compiler/libpc300/sclist.c | 14 +- 20 files changed, 6894 insertions(+), 56 deletions(-) create mode 100755 compiler/amxxpc/amx.cpp create mode 100755 compiler/amxxpc/amx.h create mode 100755 compiler/amxxpc/amxxpc.cpp create mode 100755 compiler/amxxpc/amxxpc.h create mode 100755 compiler/amxxpc/amxxpc.sln create mode 100755 compiler/amxxpc/amxxpc.vcproj create mode 100755 compiler/amxxpc/amxxpc1.rc create mode 100755 compiler/amxxpc/favicon.ico create mode 100755 compiler/amxxpc/osdefs.h create mode 100755 compiler/amxxpc/resource.h create mode 100755 compiler/amxxpc/resource1.h create mode 100755 compiler/amxxpc/sclinux.h create mode 100755 compiler/amxxpc/testmini.c create mode 100755 compiler/amxxpc/zconf.h create mode 100755 compiler/amxxpc/zlib.h create mode 100755 compiler/amxxpc/zlib.lib diff --git a/compiler/amxxpc/amx.cpp b/compiler/amxxpc/amx.cpp new file mode 100755 index 00000000..912a12fa --- /dev/null +++ b/compiler/amxxpc/amx.cpp @@ -0,0 +1,3984 @@ +/* Pawn Abstract Machine (for the Pawn language) + * + * Copyright (c) ITB CompuPhase, 1997-2005 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * 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 BUILD_PLATFORM == WINDOWS && BUILD_TYPE == RELEASE && BUILD_COMPILER == MSVC && PAWN_CELL_SIZE == 64 + /* bad bad workaround but we have to prevent a compiler crash :/ */ + #pragma optimize("g",off) +#endif + +#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 || defined __FreeBSD__ || defined __OpenBSD__ + #include + #if !defined AMX_NODYNALOAD + #include + #endif + #if defined JIT + #include + #include + #endif +#endif +#if defined __LCC__ + #include /* for wcslen() */ +#endif +#include "amx.h" +#if (defined _Windows && !defined AMX_NODYNALOAD) || (defined JIT && __WIN32__) + #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(), amx_Align32() and amx_Align64() */ + #define AMX_ALLOT /* amx_Allot() and amx_Release() */ + #define AMX_CLEANUP /* amx_Cleanup() */ + #define AMX_CLONE /* amx_Clone() */ + #define AMX_EXEC /* amx_Exec() plus amx_Push(), amx_PushArray() and amx_PushString() */ + #define AMX_FLAGS /* amx_Flags() */ + #define AMX_GETADDR /* amx_GetAddr() */ + #define AMX_INIT /* amx_Init() and amx_InitJIT() */ + #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_StrLen(), amx_GetString() and amx_SetString() */ + #define AMX_XXXTAGS /* amx_NumTags(), amx_GetTag() and amx_FindTagId() */ + #define AMX_XXXUSERDATA /* amx_GetUserData() and amx_SetUserData() */ + #define AMX_UTF8XXX /* amx_UTF8Get(), amx_UTF8Put(), amx_UTF8Check() */ +#endif +#undef AMX_EXPLIT_FUNCTIONS +#if defined AMX_ANSIONLY + #undef AMX_UTF8XXX /* no UTF-8 support in ANSI/ASCII-only version */ +#endif + +typedef enum { + OP_NONE, /* invalid opcode */ + 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, /* obsolete */ + OP_LINE, /* obsolete */ + OP_SYMBOL, /* obsolete */ + OP_SRANGE, /* obsolete */ + OP_JUMP_PRI, + OP_SWITCH, + OP_CASETBL, + OP_SWAP_PRI, + OP_SWAP_ALT, + OP_PUSHADDR, + OP_NOP, + OP_SYSREQ_D, + OP_SYMTAG, /* obsolete */ + OP_BREAK, + /* ----- */ + OP_NUM_OPCODES +} OPCODE; + +#define USENAMETABLE(hdr) \ + ((hdr)->defsize==sizeof(AMX_FUNCSTUBNT)) +#define NUMENTRIES(hdr,field,nextfield) \ + (unsigned)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize) +#define GETENTRY(hdr,table,index) \ + (AMX_FUNCSTUB *)((unsigned char*)(hdr) + (unsigned)(hdr)->table + (unsigned)index*(hdr)->defsize) +#define GETENTRYNAME(hdr,entry) \ + ( USENAMETABLE(hdr) \ + ? (char *)((unsigned char*)(hdr) + (unsigned)((AMX_FUNCSTUBNT*)(entry))->nameofs) \ + : ((AMX_FUNCSTUB*)(entry))->name ) + +#if !defined NDEBUG + static int check_endian(void) + { + uint16_t val=0x00ff; + unsigned char *ptr=(unsigned char *)&val; + /* "ptr" points to the starting address of "val". If that address + * holds the byte "0xff", the computer stored the low byte of "val" + * at the lower address, and so the memory lay out is Little Endian. + */ + assert(*ptr==0xff || *ptr==0x00); + #if BYTE_ORDER==BIG_ENDIAN + return *ptr==0x00; /* return "true" if big endian */ + #else + return *ptr==0xff; /* return "true" if little endian */ + #endif + } +#endif + +#if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==16 + static void swap16(uint16_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; + + assert(sizeof(*v)==2); + /* swap two bytes */ + t=s[0]; + s[0]=s[1]; + s[1]=t; + } +#endif + +#if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==32 + static void swap32(uint32_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; + + assert(sizeof(*v)==4); + /* swap outer two bytes */ + t=s[0]; + s[0]=s[3]; + s[3]=t; + /* swap inner two bytes */ + t=s[1]; + s[1]=s[2]; + s[2]=t; + } +#endif + +#if (BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==64) && (defined _I64_MAX || defined HAVE_I64) + static void swap64(uint64_t *v) + { + unsigned char *s = (unsigned char *)v; + unsigned char t; + + assert(sizeof(*v)==8); + + 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 * AMXAPI amx_Align16(uint16_t *v) +{ + assert(sizeof(*v)==2); + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN + swap16(v); + #endif + return v; +} + +uint32_t * AMXAPI amx_Align32(uint32_t *v) +{ + assert(sizeof(*v)==4); + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN + swap32(v); + #endif + return v; +} + +#if defined _I64_MAX || defined HAVE_I64 +uint64_t * AMXAPI amx_Align64(uint64_t *v) +{ + assert(sizeof(*v)==8); + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN + swap64(v); + #endif + return v; +} +#endif /* _I64_MAX || HAVE_I64 */ +#endif /* AMX_ALIGN || AMX_INIT */ + +#if PAWN_CELL_SIZE==16 + #define swapcell swap16 +#elif PAWN_CELL_SIZE==32 + #define swapcell swap32 +#elif PAWN_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); +#if defined AMX_NATIVETABLE + if (index=0 && index<(cell)NUMENTRIES(hdr,natives,libraries)); + func=GETENTRY(hdr,natives,index); + f=(AMX_NATIVE)func->address; +#if defined AMX_NATIVETABLE + } /* if */ +#endif + assert(f!=NULL); + + /* Now that we have found the function, patch the program so that any + * subsequent call will call the function directly (bypassing this + * callback). + * This trick cannot work in the JIT, because the program would need to + * be re-JIT-compiled after patching a P-code instruction. + */ + #if defined JIT && !defined NDEBUG + if ((amx->flags & AMX_FLAG_JITC)!=0) + assert(amx->sysreq_d==0); + #endif + if (amx->sysreq_d!=0) { + /* at the point of the call, the CIP pseudo-register points directly + * behind the SYSREQ instruction and its parameter. + */ + 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 + if (*(cell*)code==index) { +#else + if (*(cell*)code!=OP_SYSREQ_PRI) { + assert(*(cell*)(code-sizeof(cell))==OP_SYSREQ_C); + assert(*(cell*)code==index); +#endif + *(cell*)(code-sizeof(cell))=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; +} +#endif /* defined AMX_INIT */ + + +#if defined JIT + extern int AMXAPI getMaxCodeSize(void); + extern int AMXAPI asm_runJIT(void *sourceAMXbase, void *jumparray, void *compiledAMXbase); +#endif + +#if PAWN_CELL_SIZE==16 + #define JUMPABS(base,ip) ((cell *)((base) + *(ip))) + #define RELOC_ABS(base, off) + #define RELOC_VALUE(base, v) +#else + #define JUMPABS(base, ip) ((cell *)*(ip)) + #define RELOC_ABS(base, off) (*(ucell *)((base)+(int)(off)) += (ucell)(base)) + #define RELOC_VALUE(base, v) ((v)+((ucell)(base))) +#endif + +#define DBGPARAM(v) ( (v)=*(cell *)(code+(int)cip), cip+=sizeof(cell) ) + +#if defined AMX_INIT + +static int amx_BrowseRelocate(AMX *amx) +{ + AMX_HEADER *hdr; + unsigned char *code; + cell cip; + long codesize; + OPCODE op; + #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; + amx->flags=AMX_FLAG_BROWSE; + + /* 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); + + amx->sysreq_d=0; /* preset */ + #if (defined __GNUC__ || defined ASM32 || defined JIT) && !defined __64BIT__ + amx_Exec(amx, (cell*)(void*)&opcode_list, 0); + /* to use direct system requests, a function pointer must fit in a cell; + * because the native function's address will be stored as the parameter + * of SYSREQ.D + */ + if ((amx->flags & AMX_FLAG_JITC)==0 && sizeof(AMX_NATIVE)<=sizeof(cell)) + amx->sysreq_d=opcode_list[OP_SYSREQ_D]; + #else + /* ANSI C + * to use direct system requests, a function pointer must fit in a cell; + * see the comment above + */ + if (sizeof(AMX_NATIVE)<=sizeof(cell)) + amx->sysreq_d=OP_SYSREQ_D; + #endif + + /* start browsing code */ + for (cip=0; cip0 && op=256) { + amx->flags &= ~AMX_FLAG_BROWSE; + return AMX_ERR_INVINSTR; + } /* if */ + #if defined __GNUC__ || defined ASM32 || defined JIT + /* relocate opcode (only works if the size of an opcode is at least + * as big as the size of a pointer (jump address); so basically we + * rely on the opcode and a pointer being 32-bit + */ + *(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: + case OP_BREAK: + 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: + case OP_SYMBOL: { + cell num; + DBGPARAM(num); + cip+=num; + break; + } /* case */ + case OP_LINE: + case OP_SRANGE: + cip+=2*sizeof(cell); + break; + case OP_SYMTAG: + cip+=sizeof(cell); + 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; +} + +#if AMX_COMPACTMARGIN > 2 +static void expand(unsigned char *code, long codesize, long memsize) +{ + ucell c; + struct { + long memloc; + ucell c; + } spare[AMX_COMPACTMARGIN]; + 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 < (int)(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_COMPACTMARGIN; + 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 + */ + assert(check_endian()); + #if BYTE_ORDER==BIG_ENDIAN + 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); + #endif + + if (hdr->magic!=AMX_MAGIC) + return AMX_ERR_FORMAT; + if (hdr->file_versionamx_version>CUR_FILE_VERSION) + return AMX_ERR_VERSION; + if (hdr->defsize!=sizeof(AMX_FUNCSTUB) && hdr->defsize!=sizeof(AMX_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 + (unsigned)hdr->nametable); + amx_Align16(namelength); + if (*namelength>sNAMEMAX) + return AMX_ERR_FORMAT; + } /* if */ + if (hdr->stp<=0) + return AMX_ERR_FORMAT; + #if BYTE_ORDER==BIG_ENDIAN + if ((hdr->flags & AMX_FLAG_COMPACT)==0) { + ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod); + while (code<(ucell *)((unsigned char *)program+(int)hdr->hea)) + swapcell(code++); + } /* if */ + #endif + assert((hdr->flags & AMX_FLAG_COMPACT)!=0 || hdr->hea == hdr->size); + if ((hdr->flags & AMX_FLAG_COMPACT)!=0) { + #if AMX_COMPACTMARGIN > 2 + expand((unsigned char *)program+(int)hdr->cod, + hdr->size - hdr->cod, hdr->hea - hdr->cod); + #else + return AMX_ERR_FORMAT; + #endif + } /* if */ + + amx->base=(unsigned char *)program; + + /* 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; + amx->data=NULL; + + /* also align all addresses in the public function, public variable, + * public tag and native function tables --offsets into the name table + * (if present) must also be swapped. + */ + #if BYTE_ORDER==BIG_ENDIAN + { /* local */ + AMX_FUNCSTUB *fs; + int i,num; + + fs=GETENTRY(hdr,natives,0); + num=NUMENTRIES(hdr,natives,libraries); + for (i=0; iaddress); /* redundant, because it should be zero */ + if (USENAMETABLE(hdr)) + amx_Align32(&((AMX_FUNCSTUBNT*)fs)->nameofs); + fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); + } /* for */ + + fs=GETENTRY(hdr,publics,0); + assert(hdr->publics<=hdr->natives); + num=NUMENTRIES(hdr,publics,natives); + for (i=0; iaddress); + if (USENAMETABLE(hdr)) + amx_Align32(&((AMX_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(&((AMX_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(&((AMX_FUNCSTUBNT*)fs)->nameofs); + fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize); + } /* for */ + } /* local */ + #endif + + /* relocate call and jump instructions */ + amx_BrowseRelocate(amx); + + /* load any extension modules that the AMX refers to */ + #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD + hdr=(AMX_HEADER *)amx->base; + numlibraries=NUMENTRIES(hdr,libraries,pubvars); + for (i=0; iaddress=(ucell)hlib; + } /* for */ + #endif + + return AMX_ERR_NONE; +} + +#if defined JIT + + #define CODESIZE_JIT 8192 /* approximate size of the code for the JIT */ + + #if defined __WIN32__ /* this also applies to Win32 "console" applications */ + + #define PROT_READ 0x1 /* page can be read */ + #define PROT_WRITE 0x2 /* page can be written */ + #define PROT_EXEC 0x4 /* page can be executed */ + #define PROT_NONE 0x0 /* page can not be accessed */ + + static int mprotect(void *addr, size_t len, int prot) + { + DWORD prev, p = 0; + if ((prot & PROT_WRITE)!=0) + p = PAGE_EXECUTE_READWRITE; + else + p |= PAGE_EXECUTE_READ; + return !VirtualProtect(addr, len, p, &prev); + } + + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ + + /* Linux already has mprotect() */ + + #else + + // TODO: Add cases for Linux, Unix, OS/2, ... + + /* DOS32 has no imposed limits on its segments */ + #define mprotect(addr, len, prot) (0) + + #endif /* #if defined __WIN32 __ */ + +int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code) +{ + int res; + AMX_HEADER *hdr; + + if ((amx->flags & AMX_FLAG_JITC)==0) + return AMX_ERR_INIT_JIT; /* flag not set, this AMX is not prepared for JIT */ + + /* Patching SYSREQ opcodes to SYSREQ_D cannot work in the JIT, because the + * program would need to be re-JIT-compiled after patching a P-code + * instruction. If this field is not zero, something went wrong with the + * amx_BrowseRelocate(). + */ + assert(amx->sysreq_d==0); + + if (mprotect(asm_runJIT, CODESIZE_JIT, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + 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 */ + if ((res = asm_runJIT(amx->base, reloc_table, native_code)) != 0) { + /* update the required memory size (the previous value was a + * conservative estimate, now we know the exact size) + */ + amx->code_size = (hdr->dat + hdr->stp + 3) & ~3; + /* The compiled code is relocatable, since only relative jumps are + * used for destinations within the generated code and absoulute + * addresses for jumps into the runtime, which is fixed in memory. + */ + amx->base = (unsigned char*) native_code; + amx->cip = hdr->cip; + amx->hea = hdr->hea; + amx->stp = hdr->stp - sizeof(cell); + /* also put a sentinel for strings at the top the stack */ + *(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0; + amx->stk = amx->stp; + } /* if */ + + return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT; +} + +#else /* #if defined JIT */ + +int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table) +{ + (void)amx; + (void)compiled_program; + (void)reloc_table; + return AMX_ERR_INIT_JIT; +} + +#endif /* #if defined JIT */ + +#endif /* AMX_INIT */ + +#if defined AMX_CLEANUP +int AMXAPI amx_Cleanup(AMX *amx) +{ + #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD + #if defined _Windows + typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx); + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ + 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 __FreeBSD__ || defined __OpenBSD__) && !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 || defined __FreeBSD__ || defined __OpenBSD__ + libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname); + #endif + if (libcleanup!=NULL) + libcleanup(amx); + #if defined _Windows + FreeLibrary((HINSTANCE)lib->address); + #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ + dlclose((void*)lib->address); + #endif + } /* if */ + } /* for */ + #else + (void)amx; + #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; + + /* 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 + (unsigned)hdr->nametable); + *length=*namelength; + assert(hdr->file_version>=7); /* name table exists only for file version 7+ */ + } else { + *length=hdr->defsize - sizeof(ucell); + } /* 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, const 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=(ucell)funcptr; + else + err=AMX_ERR_NOTFOUND; + } /* if */ + func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize); + } /* for */ + if (err==AMX_ERR_NONE) + amx->flags|=AMX_FLAG_NTVREG; + return err; +} +#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 STKMARGIN ((cell)(16*sizeof(cell))) + +int AMXAPI amx_Push(AMX *amx, cell value) +{ + AMX_HEADER *hdr; + unsigned char *data; + + if (amx->hea+STKMARGIN>amx->stk) + return AMX_ERR_STACKERR; + hdr=(AMX_HEADER *)amx->base; + data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; + amx->stk-=sizeof(cell); + amx->paramcount+=1; + *(cell *)(data+(int)amx->stk)=value; + return AMX_ERR_NONE; +} + +int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells) +{ + cell *paddr; + int err; + + assert(amx!=NULL); + assert(amx_addr!=NULL); + assert(array!=NULL); + + err=amx_Allot(amx,numcells,amx_addr,&paddr); + if (err==AMX_ERR_NONE) { + if (phys_addr!=NULL) + *phys_addr=paddr; + memcpy(paddr,array,numcells*sizeof(cell)); + err=amx_Push(amx,*amx_addr); + } /* if */ + return err; +} + +int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar) +{ + cell *paddr; + int numcells,err; + + assert(amx!=NULL); + assert(amx_addr!=NULL); + assert(string!=NULL); + + #if defined AMX_ANSIONLY + numcells=strlen(string) + 1; + #else + numcells= (use_wchar ? wcslen((const wchar_t*)string) : strlen(string)) + 1; + #endif + if (pack) + numcells=(numcells+sizeof(cell)-1)/sizeof(cell); + err=amx_Allot(amx,numcells,amx_addr,&paddr); + if (err==AMX_ERR_NONE) { + if (phys_addr!=NULL) + *phys_addr=paddr; + amx_SetString(paddr,string,pack,use_wchar,UNLIMITED); + err=amx_Push(amx,*amx_addr); + } /* if */ + return err; +} + +#define GETPARAM(v) ( v=*(cell *)cip++ ) +#define SKIPPARAM(n) ( cip=(cell *)cip+(n) ) +#define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v ) +#define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) ) +#define ABORT(amx,v) { (amx)->stk=reset_stk; (amx)->hea=reset_hea; return v; } + +#define CHKMARGIN() if (hea+STKMARGIN>stk) return AMX_ERR_STACKERR +#define CHKSTACK() if (stk>amx->stp) return AMX_ERR_STACKLOW +#define CHKHEAP() if (heahlw) return AMX_ERR_HEAPLOW + +#if defined __GNUC__ && !(defined ASM32 || defined JIT) + /* 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) +{ +static const void * const amx_opcodelist[] = { + &&op_none, &&op_load_pri, &&op_load_alt, &&op_load_s_pri, + &&op_load_s_alt,&&op_lref_pri, &&op_lref_alt, &&op_lref_s_pri, + &&op_lref_s_alt,&&op_load_i, &&op_lodb_i, &&op_const_pri, + &&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_break }; + 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; + + /* HACK: return label table (for amx_BrowseRelocate) if amx structure + * has the AMX_FLAG_BROWSE flag set. + */ + assert(amx!=NULL); + if ((amx->flags & AMX_FLAG_BROWSE)==AMX_FLAG_BROWSE) { + assert(sizeof(cell)==sizeof(void *)); + assert(retval!=NULL); + *retval=(cell)amx_opcodelist; + return 0; + } /* if */ + + if (amx->callback==NULL) + return AMX_ERR_CALLBACK; + if ((amx->flags & AMX_FLAG_NTVREG)==0) + return AMX_ERR_NOTFOUND; + if ((amx->flags & AMX_FLAG_RELOC)==0) + return AMX_ERR_INIT; + assert((amx->flags & AMX_FLAG_BROWSE)==0); + + /* set up the registers */ + hdr=(AMX_HEADER *)amx->base; + assert(hdr->magic==AMX_MAGIC); + 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; + alt=frm=0; /* just to avoid compiler warnings */ + num=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>=(int)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(); + assert(check_endian()); + + /* 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 PAWN_CELL_SIZE==16 + assert(sizeof(cell)==2); + #elif PAWN_CELL_SIZE==32 + assert(sizeof(cell)==4); + #elif PAWN_CELL_SIZE==64 + assert(sizeof(cell)==8); + #else + #error Unsupported cell size + #endif + + if (index!=AMX_EXEC_CONT) { + reset_stk+=amx->paramcount*sizeof(cell); + PUSH(amx->paramcount*sizeof(cell)); + amx->paramcount=0; /* push the parameter count to the stack & reset */ + PUSH(0); /* zero return address */ + } /* if */ + /* check stack/heap before starting to run */ + CHKMARGIN(); + + /* start running */ + NEXT(cip); + + op_none: + ABORT(amx,AMX_ERR_INVINSTR); + op_load_pri: + GETPARAM(offs); + pri= * (cell *)(data+(int)offs); + NEXT(cip); + op_load_alt: + GETPARAM(offs); + alt= * (cell *)(data+(int)offs); + NEXT(cip); + op_load_s_pri: + GETPARAM(offs); + pri= * (cell *)(data+(int)frm+(int)offs); + NEXT(cip); + op_load_s_alt: + GETPARAM(offs); + alt= * (cell *)(data+(int)frm+(int)offs); + NEXT(cip); + op_lref_pri: + GETPARAM(offs); + offs= * (cell *)(data+(int)offs); + pri= * (cell *)(data+(int)offs); + NEXT(cip); + op_lref_alt: + GETPARAM(offs); + offs= * (cell *)(data+(int)offs); + alt= * (cell *)(data+(int)offs); + NEXT(cip); + op_lref_s_pri: + GETPARAM(offs); + offs= * (cell *)(data+(int)frm+(int)offs); + pri= * (cell *)(data+(int)offs); + NEXT(cip); + op_lref_s_alt: + GETPARAM(offs); + offs= * (cell *)(data+(int)frm+(int)offs); + alt= * (cell *)(data+(int)offs); + NEXT(cip); + op_load_i: + /* verify address */ + if (pri>=hea && pri=(ucell)amx->stp) + ABORT(amx,AMX_ERR_MEMACCESS); + pri= * (cell *)(data+(int)pri); + NEXT(cip); + op_lodb_i: + GETPARAM(offs); + /* verify address */ + if (pri>=hea && pri=(ucell)amx->stp) + 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 BYTE_ORDER==LITTLE_ENDIAN + if (offs<(int)sizeof(cell)) + pri ^= sizeof(cell)-offs; + #endif + NEXT(cip); + op_align_alt: + GETPARAM(offs); + #if BYTE_ORDER==LITTLE_ENDIAN + if (offs<(int)sizeof(cell)) + alt ^= sizeof(cell)-offs; + #endif + NEXT(cip); + op_lctrl: + GETPARAM(offs); + switch (offs) { + case 0: + pri=hdr->cod; + 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(); + 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); + 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 */ + NEXT(cip); + op_call: + 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); + 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>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) + *(cell *)(data+i) = pri; + NEXT(cip); + op_halt: + GETPARAM(offs); + if (retval!=NULL) + *retval=pri; + /* store complete status (stk and hea are already set in the ABORT macro) */ + amx->frm=frm; + amx->pri=pri; + amx->alt=alt; + amx->cip=(cell)((unsigned char*)cip-code); + 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: + SKIPPARAM(2); + NEXT(cip); + op_symbol: + GETPARAM(offs); + cip=(cell *)((unsigned char *)cip + (int)offs); + NEXT(cip); + op_srange: + SKIPPARAM(2); + NEXT(cip); + op_symtag: + SKIPPARAM(1); + NEXT(cip); + op_jump_pri: + cip=(cell *)(code+(int)pri); + NEXT(cip); + op_switch: { + cell *cptr; + cptr=JUMPABS(code,cip)+1; /* +1, to skip the "casetbl" opcode */ + cip=JUMPABS(code,cptr+1); /* preset to "none-matched" case */ + num=(int)*cptr; /* number of records in the case table */ + for (cptr+=2; num>0 && *cptr!=pri; num--,cptr+=2) + /* nothing */; + if (num>0) + cip=JUMPABS(code,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); + op_break: + if (amx->debug!=NULL) { + /* store status */ + amx->frm=frm; + amx->stk=stk; + amx->hea=hea; + amx->cip=(cell)((unsigned char*)cip-code); + num=amx->debug(amx); + if (num!=AMX_ERR_NONE) { + if (num==AMX_ERR_SLEEP) { + amx->pri=pri; + amx->alt=alt; + amx->reset_stk=reset_stk; + amx->reset_hea=reset_hea; + return num; + } /* if */ + ABORT(amx,num); + } /* if */ + } /* if */ + NEXT(cip); +} + +#else + /* 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. + * AMXJITR.ASM is for Watcom's register calling convention, AMXJITS.ASM and + * AMXJITSN.ASM are for "cdecl". + */ + #if defined __WATCOMC__ + #if !defined STACKARGS /* for AMX32.DLL */ + 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]; + extern cell amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); + #pragma aux amx_exec_jit parm [eax] [edx] [ebx] [ecx]; + #else + extern cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); + extern cell __cdecl amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); + #endif + #elif defined __GNUC__ + /* force "cdecl" by adding an "attribute" to the declaration */ + extern cell amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea) __attribute__((cdecl)); + extern cell amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea) __attribute__((cdecl)); + #else + /* force "cdecl" by specifying it as a "function class" with the "__cdecl" keyword */ + extern cell __cdecl amx_exec_asm(cell *regs,cell *retval,cell stp,cell hea); + extern cell __cdecl amx_exec_jit(cell *regs,cell *retval,cell stp,cell hea); + #endif +#endif + +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) +{ + 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; + #if defined ASM32 || defined JIT + cell parms[9]; /* registers and parameters for assembler AMX */ + #else + OPCODE op; + cell offs; + int num; + #endif + #if defined ASM32 + extern void const *amx_opcodelist[]; + #ifdef __WATCOMC__ + #pragma aux amx_opcodelist "_*" + #endif + #endif + #if defined JIT + extern void const *amx_opcodelist_jit[]; + #ifdef __WATCOMC__ + #pragma aux amx_opcodelist_jit "_*" + #endif + #endif + + assert(amx!=NULL); + #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 ASM32 && defined JIT + if ((amx->flags & AMX_FLAG_JITC)!=0) + *retval=(cell)amx_opcodelist_jit; + else + *retval=(cell)amx_opcodelist; + #elif defined ASM32 + *retval=(cell)amx_opcodelist; + #else + *retval=(cell)amx_opcodelist_jit; + #endif + return 0; + } /* if */ + #endif + + if (amx->callback==NULL) + return AMX_ERR_CALLBACK; + if ((amx->flags & AMX_FLAG_NTVREG)==0) + return AMX_ERR_NOTFOUND; + if ((amx->flags & AMX_FLAG_RELOC)==0) + return AMX_ERR_INIT; + assert((amx->flags & AMX_FLAG_BROWSE)==0); + + /* set up the registers */ + hdr=(AMX_HEADER *)amx->base; + assert(hdr->magic==AMX_MAGIC); + 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(); + assert(check_endian()); + + /* 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 PAWN_CELL_SIZE==16 + assert(sizeof(cell)==2); + #elif PAWN_CELL_SIZE==32 + assert(sizeof(cell)==4); + #elif PAWN_CELL_SIZE==64 + assert(sizeof(cell)==8); + #else + #error Unsupported cell size + #endif + + if (index!=AMX_EXEC_CONT) { + reset_stk+=amx->paramcount*sizeof(cell); + PUSH(amx->paramcount*sizeof(cell)); + amx->paramcount=0; /* push the parameter count to the stack & reset */ + #if defined ASM32 || defined JIT + PUSH(RELOC_VALUE(code,0));/* relocated zero return address */ + #else + PUSH(0); /* zero return address */ + #endif + } /* if */ + /* check stack/heap before starting to run */ + CHKMARGIN(); + + /* start running */ +#if defined ASM32 || defined JIT + /* either the assembler abstract machine or the JIT; both by Marc Peter */ + + parms[0] = pri; + parms[1] = alt; + parms[2] = (cell)cip; + parms[3] = (cell)data; + parms[4] = stk; + parms[5] = frm; + parms[6] = (cell)amx; + parms[7] = (cell)code; + parms[8] = (cell)codesize; + + #if defined ASM32 && defined JIT + if ((amx->flags & AMX_FLAG_JITC)!=0) + i = amx_exec_jit(parms,retval,amx->stp,hea); + else + i = amx_exec_asm(parms,retval,amx->stp,hea); + #elif defined ASM32 + i = amx_exec_asm(parms,retval,amx->stp,hea); + #else + i = amx_exec_jit(parms,retval,amx->stp,hea); + #endif + if (i == AMX_ERR_SLEEP) { + amx->reset_stk=reset_stk; + amx->reset_hea=reset_hea; + } 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 BYTE_ORDER==LITTLE_ENDIAN + if ((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(); + 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); + 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; + break; + case OP_CALL: + PUSH(((unsigned char *)cip-code)+sizeof(cell));/* skip address */ + cip=JUMPABS(code, cip); /* jump to the address */ + break; + case OP_CALL_PRI: + PUSH((unsigned char *)cip-code); + cip=(cell *)(code+(int)pri); + 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 (stk and hea are already set in the ABORT macro) */ + amx->frm=frm; + amx->pri=pri; + amx->alt=alt; + amx->cip=(cell)((unsigned char*)cip-code); + 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_LINE: + SKIPPARAM(2); + break; + case OP_SYMBOL: + GETPARAM(offs); + cip=(cell *)((unsigned char *)cip + (int)offs); + break; + case OP_SRANGE: + SKIPPARAM(2); + break; + case OP_SYMTAG: + SKIPPARAM(1); + break; + case OP_JUMP_PRI: + cip=(cell *)(code+(int)pri); + break; + case OP_SWITCH: { + cell *cptr; + + cptr=JUMPABS(code,cip)+1; /* +1, to skip the "casetbl" opcode */ + cip=JUMPABS(code,cptr+1); /* preset to "none-matched" case */ + num=(int)*cptr; /* number of records in the case table */ + for (cptr+=2; num>0 && *cptr!=pri; num--,cptr+=2) + /* nothing */; + if (num>0) + cip=JUMPABS(code,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_BREAK: + assert((amx->flags & AMX_FLAG_BROWSE)==0); + if (amx->debug!=NULL) { + /* store status */ + amx->frm=frm; + amx->stk=stk; + amx->hea=hea; + amx->cip=(cell)((unsigned char*)cip-code); + num=amx->debug(amx); + if (num!=AMX_ERR_NONE) { + if (num==AMX_ERR_SLEEP) { + amx->pri=pri; + amx->alt=alt; + amx->reset_stk=reset_stk; + amx->reset_hea=reset_hea; + return num; + } /* if */ + ABORT(amx,num); + } /* if */ + } /* if */ + break; + default: + /* case OP_FILE: should not occur during execution + * case OP_CASETBL: should not occur during execution + */ + assert(0); + ABORT(amx,AMX_ERR_INVINSTR); + } /* switch */ + } /* for */ +#endif +} + +#endif /* __GNUC__ */ + +#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); + 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 || defined AMX_EXEC +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 || defined AMX_UTF8XXX + +#define CHARBITS (8*sizeof(char)) +#if PAWN_CELL_SIZE==16 + #define CHARMASK (0xffffu << 8*(2-sizeof(char))) +#elif PAWN_CELL_SIZE==32 + #define CHARMASK (0xffffffffuL << 8*(4-sizeof(char))) +#elif PAWN_CELL_SIZE==64 + #define CHARMASK (0xffffffffffffffffuLL << 8*(8-sizeof(char))) +#else + #error Unsupported cell size +#endif + +int AMXAPI amx_StrLen(const cell *cstr, int *length) +{ + int len; + #if BYTE_ORDER==LITTLE_ENDIAN + cell c; + #endif + + assert(length!=NULL); + if (cstr==NULL) { + *length=0; + return AMX_ERR_PARAMS; + } /* if */ + + if ((ucell)*cstr>UNPACKEDMAX) { + /* packed string */ + assert(sizeof(char)==1); + len=strlen((char *)cstr); /* find '\0' */ + assert(check_endian()); + #if BYTE_ORDER==LITTLE_ENDIAN + /* on Little Endian machines, toggle the last bytes */ + 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 */ + #endif + } else { + for (len=0; cstr[len]!=0; len++) + /* nothing */; + } /* if */ + *length = len; + return AMX_ERR_NONE; +} +#endif + +#if defined AMX_XXXSTRING || defined AMX_EXEC +int AMXAPI amx_SetString(cell *dest,const char *source,int pack,int use_wchar,size_t size) +{ /* the memory blocks should not overlap */ + int len, i; + + assert(UNLIMITED>0); + #if defined AMX_ANSIONLY + (void)use_wchar; + len=strlen(source); + #else + len= use_wchar ? wcslen((const wchar_t*)source) : strlen(source); + #endif + if (pack) { + /* create a packed string */ + if (size=size*sizeof(cell)) + len=size*sizeof(cell)-1; + dest[len/sizeof(cell)]=0; /* clear last bytes of last (semi-filled) cell*/ + #if defined AMX_ANSIONLY + memcpy(dest,source,len); + #else + if (use_wchar) { + for (i=0; i=0) + swapcell((ucell *)&dest[len--]); + #endif + + } else { + /* create an unpacked string */ + if (size=size) + len=size-1; + #if defined AMX_ANSIONLY + for (i=0; iUNPACKEDMAX) { + /* source string is packed */ + cell c = 0; /* to avoid a compiler warning */ + int i=sizeof(cell)-1; + while ((size_t)len> i*CHARBITS); + #else + if (use_wchar) + ((wchar_t*)dest)[len++]=(char)(c >> i*CHARBITS); + else + dest[len++]=(char)(c >> i*CHARBITS); + #endif + if (dest[len-1]=='\0') + break; /* terminating zero character found */ + i=(i+sizeof(cell)-1) % sizeof(cell); + } /* for */ + } else { + /* source string is unpacked */ + #if defined AMX_ANSIONLY + while (*source!=0 && (size_t)len=size) + len=size-1; + if (len>=0) + dest[len]='\0'; /* store terminator */ + return AMX_ERR_NONE; +} +#endif /* AMX_XXXSTRING */ + +#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 const char utf8_count[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4 }; +static const long utf8_lowmark[5] = { 0x80, 0x800, 0x10000L, 0x200000L, 0x4000000L }; + unsigned char c; + cell result; + int followup; + + 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 byte string. The character may result in + * a string of up to 6 bytes. The function returns an error code if "maxchars" + * is lower than the required number of characters; in this case nothing is + * stored. + * The function does not zero-terminate the string. + */ +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 *length) +{ + int err=AMX_ERR_NONE; + int len=0; + while (err==AMX_ERR_NONE && *string!='\0') { + err=amx_UTF8Get(string,&string,NULL); + len++; + } /* while */ + if (length!=NULL) + *length=len; + return err; +} + +/* amx_UTF8Len() + * Run through a wide string and return how many 8-bit characters are needed to + * store the string in UTF-8 format. The returned cound excludes the terminating + * zero byte. The function returns an error code. + */ +int AMXAPI amx_UTF8Len(const cell *cstr, int *length) +{ + int err; + + assert(length!=NULL); + err=amx_StrLen(cstr, length); + if (err==AMX_ERR_NONE && (ucell)*cstr<=UNPACKEDMAX) { + char buffer[10]; /* maximum UTF-8 code is 6 characters */ + char *endptr; + int len=*length, count=0; + while (len-->0) { + amx_UTF8Put(buffer, &endptr, sizeof buffer, *cstr++); + count+=(int)(endptr-buffer); + } /* while */ + *length=count; + } /* while */ + return err; +} +#endif /* AMX_UTF8XXX */ diff --git a/compiler/amxxpc/amx.h b/compiler/amxxpc/amx.h new file mode 100755 index 00000000..cf194750 --- /dev/null +++ b/compiler/amxxpc/amx.h @@ -0,0 +1,439 @@ +/* Pawn Abstract Machine (for the Pawn language) + * + * Copyright (c) ITB CompuPhase, 1997-2005 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * 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 FREEBSD && !defined __FreeBSD__ + #define __FreeBSD__ +#endif +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ + #include +#endif + +#ifndef AMX_H_INCLUDED +#define AMX_H_INCLUDED + +#if defined HAVE_STDINT_H + #include +#else + #if defined __LCC__ || defined __DMC__ || defined LINUX + #if defined HAVE_INTTYPES_H + #include + #else + #include + #endif + #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* The ISO C99 defines the int16_t and int_32t types. If the compiler got + * here, these types are probably undefined. + */ + #if defined __MACH__ + #include + typedef unsigned short int uint16_t; + typedef unsigned long int uint32_t; + #elif defined __FreeBSD__ + #include + #else + typedef short int int16_t; + typedef unsigned short int uint16_t; + #if defined SN_TARGET_PS2 + typedef int int32_t; + typedef unsigned int uint32_t; + #else + typedef long int int32_t; + typedef unsigned long int uint32_t; + #endif + #if defined __WIN32__ || defined _WIN32 || defined WIN32 + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #define HAVE_I64 + #elif defined __GNUC__ + typedef long long int64_t; + typedef unsigned long long uint64_t; + #define HAVE_I64 + #endif + #endif + #endif + #define HAVE_STDINT_H +#endif +#if defined _LP64 || defined WIN64 || defined _WIN64 + #if !defined __64BIT__ + #define __64BIT__ + #endif +#endif + +#if HAVE_ALLOCA_H + #include +#endif +#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */ + #if !defined alloca + #define alloca(n) _alloca(n) + #endif +#endif + +#if !defined arraysize + #define arraysize(array) (sizeof(array) / sizeof((array)[0])) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined PAWN_DLL + #if !defined AMX_NATIVE_CALL + #define AMX_NATIVE_CALL __stdcall + #endif + #if !defined AMXAPI + #define AMXAPI __stdcall + #endif +#endif + +/* calling convention for native functions */ +#if !defined AMX_NATIVE_CALL + #define AMX_NATIVE_CALL +#endif +/* calling convention for all interface functions and callback functions */ +#if !defined AMXAPI + #if defined STDECL + #define AMXAPI __stdcall + #elif defined CDECL + #define AMXAPI __cdecl + #elif defined GCC_HASCLASSVISIBILITY + #define AMXAPI __attribute__ ((visibility("default"))) + #else + #define AMXAPI + #endif +#endif +#if !defined AMXEXPORT + #define AMXEXPORT +#endif + +/* File format version Required AMX version + * 0 (original version) 0 + * 1 (opcodes JUMP.pri, SWITCH and CASETBL) 1 + * 2 (compressed files) 2 + * 3 (public variables) 2 + * 4 (opcodes SWAP.pri/alt and PUSHADDR) 4 + * 5 (tagnames table) 4 + * 6 (reformatted header) 6 + * 7 (name table, opcodes SYMTAG & SYSREQ.D) 7 + * 8 (opcode STMT, renewed debug interface) 8 + */ +#define CUR_FILE_VERSION 8 /* current file version; also the current AMX version */ +#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */ +#define MIN_AMX_VERSION 8 /* minimum AMX version needed to support the current file format */ + +#if !defined PAWN_CELL_SIZE + #define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */ +#endif +#if PAWN_CELL_SIZE==16 + typedef uint16_t ucell; + typedef int16_t cell; +#elif PAWN_CELL_SIZE==32 + typedef uint32_t ucell; + typedef int32_t cell; +#elif PAWN_CELL_SIZE==64 + typedef uint64_t ucell; + typedef int64_t cell; +#else + #error Unsupported cell size (PAWN_CELL_SIZE) +#endif + +#define UNPACKEDMAX ((1L << (sizeof(cell)-1)*8) - 1) +#define UNLIMITED (~1u >> 1) + +struct tagAMX; +typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params); +typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index, + cell *result, cell *params); +typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx); +#if !defined _FAR + #define _FAR +#endif + +#if defined _MSC_VER + #pragma warning(disable:4103) /* disable warning message 4103 that complains + * about pragma pack in a header file */ + #pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */ +#endif + +/* Some compilers do not support the #pragma align, which should be fine. Some + * compilers give a warning on unknown #pragmas, which is not so fine... + */ +#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN + #define AMX_NO_ALIGN +#endif + +#if defined __GNUC__ + #define PACKED __attribute__((packed)) +#else + #define PACKED +#endif + +#if !defined AMX_NO_ALIGN + #if defined LINUX || defined __FreeBSD__ + #pragma pack(1) /* structures must be packed (byte-aligned) */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=mac68k + #else + #pragma pack(push) + #pragma pack(1) /* structures must be packed (byte-aligned) */ + #if defined __TURBOC__ + #pragma option -a- /* "pack" pragma for older Borland compilers */ + #endif + #endif +#endif + +typedef struct tagAMX_NATIVE_INFO { + const char _FAR *name PACKED; + AMX_NATIVE func PACKED; +} PACKED AMX_NATIVE_INFO; + +#define AMX_USERNUM 4 +#define sEXPMAX 19 /* maximum name length for file version <= 6 */ +#define sNAMEMAX 31 /* maximum name length of symbol name */ + +typedef struct tagAMX_FUNCSTUB { + ucell address PACKED; + char name[sEXPMAX+1] PACKED; +} PACKED AMX_FUNCSTUB; + +typedef struct tagFUNCSTUBNT { + ucell address PACKED; + uint32_t nameofs PACKED; +} PACKED AMX_FUNCSTUBNT; + +/* The AMX structure is the internal structure for many functions. Not all + * fields are valid at all times; many fields are cached in local variables. + */ +typedef struct tagAMX { + unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */ + unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */ + AMX_CALLBACK callback PACKED; + AMX_DEBUG debug PACKED; /* debug callback */ + /* for external functions a few registers must be accessible from the outside */ + cell cip PACKED; /* instruction pointer: relative to base + amxhdr->cod */ + cell frm PACKED; /* stack frame base: relative to base + amxhdr->dat */ + cell hea PACKED; /* top of the heap: relative to base + amxhdr->dat */ + cell hlw PACKED; /* bottom of the heap: relative to base + amxhdr->dat */ + cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */ + cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */ + int flags PACKED; /* current status, see amx_Flags() */ + /* user data */ + long usertags[AMX_USERNUM] PACKED; + void _FAR *userdata[AMX_USERNUM] PACKED; + /* native functions can raise an error */ + int error PACKED; + /* passing parameters requires a "count" field */ + int paramcount; + /* the sleep opcode needs to store the full AMX status */ + cell pri PACKED; + cell alt PACKED; + cell reset_stk PACKED; + cell reset_hea PACKED; + cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */ + #if defined JIT + /* support variables for the JIT */ + int reloc_size PACKED; /* required temporary buffer for relocations */ + long code_size PACKED; /* estimated memory footprint of the native code */ + #endif +} PACKED AMX; + +/* The AMX_HEADER structure is both the memory format as the file format. The + * structure is used internaly. + */ +typedef struct tagAMX_HEADER { + int32_t size PACKED; /* size of the "file" */ + uint16_t magic PACKED; /* signature */ + char file_version PACKED; /* file format version */ + char amx_version PACKED; /* required version of the AMX */ + int16_t flags PACKED; + int16_t defsize PACKED; /* size of a definition record */ + int32_t cod PACKED; /* initial value of COD - code block */ + int32_t dat PACKED; /* initial value of DAT - data block */ + int32_t hea PACKED; /* initial value of HEA - start of the heap */ + int32_t stp PACKED; /* initial value of STP - stack top */ + int32_t cip PACKED; /* initial value of CIP - the instruction pointer */ + int32_t publics PACKED; /* offset to the "public functions" table */ + int32_t natives PACKED; /* offset to the "native functions" table */ + int32_t libraries PACKED; /* offset to the table of libraries */ + int32_t pubvars PACKED; /* the "public variables" table */ + int32_t tags PACKED; /* the "public tagnames" table */ + int32_t nametable PACKED; /* name table */ +} PACKED AMX_HEADER; + +#if PAWN_CELL_SIZE==16 + #define AMX_MAGIC 0xf1e2 +#elif PAWN_CELL_SIZE==32 + #define AMX_MAGIC 0xf1e0 +#elif PAWN_CELL_SIZE==64 + #define AMX_MAGIC 0xf1e1 +#endif + +enum { + AMX_ERR_NONE, + /* reserve the first 15 error codes for exit codes of the abstract machine */ + AMX_ERR_EXIT, /* forced exit */ + AMX_ERR_ASSERT, /* assertion failed */ + AMX_ERR_STACKERR, /* stack/heap collision */ + AMX_ERR_BOUNDS, /* index out of bounds */ + AMX_ERR_MEMACCESS, /* invalid memory access */ + AMX_ERR_INVINSTR, /* invalid instruction */ + AMX_ERR_STACKLOW, /* stack underflow */ + AMX_ERR_HEAPLOW, /* heap underflow */ + AMX_ERR_CALLBACK, /* no callback, or invalid callback */ + AMX_ERR_NATIVE, /* native function failed */ + AMX_ERR_DIVIDE, /* divide by zero */ + AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */ + AMX_ERR_INVSTATE, /* invalid state for this access */ + + AMX_ERR_MEMORY = 16, /* out of memory */ + AMX_ERR_FORMAT, /* invalid file format */ + AMX_ERR_VERSION, /* file is for a newer version of the AMX */ + AMX_ERR_NOTFOUND, /* function not found */ + AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */ + AMX_ERR_DEBUG, /* debugger cannot run */ + AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */ + AMX_ERR_USERDATA, /* unable to set user data field (table full) */ + AMX_ERR_INIT_JIT, /* cannot initialize the JIT */ + AMX_ERR_PARAMS, /* parameter error */ + AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */ + AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */ +}; + +/* AMX_FLAG_CHAR16 0x01 no longer used */ +#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */ +#define AMX_FLAG_COMPACT 0x04 /* compact encoding */ +#define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */ +#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */ +#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */ +#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */ +#define AMX_FLAG_BROWSE 0x4000 /* busy browsing */ +#define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */ + +#define AMX_EXEC_MAIN -1 /* start at program entry point */ +#define AMX_EXEC_CONT -2 /* continue from last address */ + +#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24)) + +#if !defined AMX_COMPACTMARGIN + #define AMX_COMPACTMARGIN 64 +#endif + +/* for native functions that use floating point parameters, the following + * two macros are convenient for casting a "cell" into a "float" type _without_ + * changing the bit pattern + */ +#if PAWN_CELL_SIZE==32 + #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ + #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */ +#elif PAWN_CELL_SIZE==64 + #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ + #define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */ +#else + #error Unsupported cell size +#endif + +#define amx_StrParam(amx,param,result) \ + do { \ + cell *amx_cstr_; int amx_length_; \ + amx_GetAddr((amx), (param), &amx_cstr_); \ + amx_StrLen(amx_cstr_, &amx_length_); \ + if (amx_length_ > 0 && \ + ((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \ + amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_); \ + else (result) = NULL; \ + } while (0) + +uint16_t * AMXAPI amx_Align16(uint16_t *v); +uint32_t * AMXAPI amx_Align32(uint32_t *v); +#if defined _I64_MAX || defined HAVE_I64 + uint64_t * AMXAPI amx_Align64(uint64_t *v); +#endif +int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr); +int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params); +int AMXAPI amx_Cleanup(AMX *amx); +int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data); +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index); +int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index); +int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index); +int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr); +int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname); +int AMXAPI amx_Flags(AMX *amx,uint16_t *flags); +int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr); +int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname); +int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname); +int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr); +int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size); +int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id); +int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr); +int AMXAPI amx_Init(AMX *amx, void *program); +int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code); +int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap); +int AMXAPI amx_NameLength(AMX *amx, int *length); +AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func); +int AMXAPI amx_NumNatives(AMX *amx, int *number); +int AMXAPI amx_NumPublics(AMX *amx, int *number); +int AMXAPI amx_NumPubVars(AMX *amx, int *number); +int AMXAPI amx_NumTags(AMX *amx, int *number); +int AMXAPI amx_Push(AMX *amx, cell value); +int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells); +int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar); +int AMXAPI amx_RaiseError(AMX *amx, int error); +int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number); +int AMXAPI amx_Release(AMX *amx, cell amx_addr); +int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); +int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug); +int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size); +int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr); +int AMXAPI amx_StrLen(const cell *cstring, int *length); +int AMXAPI amx_UTF8Check(const char *string, int *length); +int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value); +int AMXAPI amx_UTF8Len(const cell *cstr, int *length); +int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); + +#if PAWN_CELL_SIZE==16 + #define amx_AlignCell(v) amx_Align16(v) +#elif PAWN_CELL_SIZE==32 + #define amx_AlignCell(v) amx_Align32(v) +#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) + #define amx_AlignCell(v) amx_Align64(v) +#else + #error Unsupported cell size +#endif + +#define amx_RegisterFunc(amx, name, func) \ + amx_Register((amx), amx_NativeInfo((name),(func)), 1); + +#if !defined AMX_NO_ALIGN + #if defined LINUX || defined __FreeBSD__ + #pragma pack() /* reset default packing */ + #elif defined MACOS && defined __MWERKS__ + #pragma options align=reset + #else + #pragma pack(pop) /* reset previous packing */ + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* AMX_H_INCLUDED */ diff --git a/compiler/amxxpc/amxxpc.cpp b/compiler/amxxpc/amxxpc.cpp new file mode 100755 index 00000000..28a8a3f4 --- /dev/null +++ b/compiler/amxxpc/amxxpc.cpp @@ -0,0 +1,326 @@ +#include +#ifdef __linux__ +#include +#else +#include +#include +#endif +#include "zlib.h" +#include "amx.h" +#include "amxxpc.h" + +int main(int argc, char **argv) +{ + struct abl pl32; + struct abl pl64; + +#ifdef _DEBUG + printf("debug clamp\n"); + getchar(); +#endif + +#ifdef __linux__ + HINSTANCE lib = dlmount("./amxxpc32.so"); +#else + HINSTANCE lib = dlmount("amxxpc32.dll"); +#endif + if (!lib) + { +#ifdef __linux__ + printf("32bit compiler failed to instantiate: %s\n", dlerror()); +#else + printf("32bit compiler failed to instantiate: %d\n", GetLastError()); +#endif + exit(0); + } + + COMPILER sc32 = (COMPILER)dlsym(lib, "Compile32"); + + if (!sc32) + { +#ifdef __linux__ + printf("32bit compiler failed to link: %p|%p.\n",sc32, sc_printf); +#else + printf("32bit compiler failed to link: %d.\n", GetLastError()); +#endif + exit(0); + } + + AMX_HEADER hdr; + + printf("Welcome to the AMX Mod X %s Compiler.\n", VERSION_STRING); + printf("Copyright (c) 1997-2005 ITB CompuPhase, AMX Mod X Team\n\n"); + + if (argc < 2) + { + printf("Usage: [options]\n"); + printf("Use -? or --help to see full options\n\n"); + getchar(); + exit(0); + } + + if (!strcmp(argv[1], "-?") || !strcmp(argv[1], "--help")) + { + show_help(); + printf("Press any key to continue.\n"); + getchar(); + exit(0); + } + + sc32(argc, argv); + + char *file = FindFileName(argc, argv); + + if (file == NULL) + { + printf("Could not locate the output file.\n"); + exit(0); + } else if (strstr(file, ".asm")) { + printf("Assembler output succeeded.\n"); + exit(0); + } else { + FILE *fp = fopen(file, "rb"); + if (fp == NULL) + { + printf("Could not locate output file %s (compile failed).\n", file); + exit(0); + } + fread(&hdr, sizeof(hdr), 1, fp); + amx_Align32((uint32_t *)&hdr.stp); + amx_Align32((uint32_t *)&hdr.size); + pl32.stp = hdr.stp; + pl32.cellsize = 4; + int size = sizeof(hdr) + hdr.size; + pl32.size = size; + pl32.data = new char[size]; + rewind(fp); + fread(pl32.data, 1, size, fp); + fclose(fp); + } + + unlink(file); + + HINSTANCE lib64 = 0; +#ifdef __linux__ + lib64 = dlmount("./amxxpc64.so"); +#else + lib64 = dlmount("amxxpc64.dll"); +#endif + if (!lib64) + { + printf("64bit compiler failed to instantiate.\n"); + exit(0); + } + + COMPILER sc64 = (COMPILER)dlsym(lib64, "Compile64"); + + if (!sc64) + { +#ifdef __linux__ + sc_printf("64bit compiler failed to link: %s.\n", dlerror()); +#else + printf("64bit compiler failed to link: %d.\n", GetLastError()); +#endif + exit(0); + } + + sc64(argc, argv); + + dlclose(lib64); + + if (file == NULL) + { + printf("Could not locate the output file on second pass.\n"); + exit(0); + } else { + FILE *fp = fopen(file, "rb"); + if (fp == NULL) + { + printf("Could not locate output file on second pass (compile failed).\n"); + exit(0); + } + fread(&hdr, sizeof(hdr), 1, fp); + amx_Align32((uint32_t *)&hdr.stp); + amx_Align32((uint32_t *)&hdr.size); + pl64.stp = hdr.stp; + pl64.cellsize = 8; + int size = sizeof(hdr) + hdr.size; + pl64.size = sizeof(hdr) + hdr.size; + pl64.data = new char[size]; + rewind(fp); + fread(pl64.data, 1, size, fp); + fclose(fp); + } + + ///////////// + // COMPRSSION + ///////////// + + int err; + + pl32.cmpsize = compressBound(pl32.size); + pl32.cmp = new char[pl32.cmpsize]; + err = compress((Bytef *)pl32.cmp, (uLongf *)&(pl32.cmpsize), (const Bytef*)pl32.data, pl32.size); + + if (err != Z_OK) + { + printf("internal error - compression failed on first pass: %d\n", err); + exit(0); + } + + pl64.cmpsize = compressBound(pl64.size); + pl64.cmp = new char[pl64.cmpsize]; + err = compress((Bytef *)pl64.cmp, (uLongf *)&(pl64.cmpsize), (const Bytef*)pl64.data, pl64.size); + + if (err != Z_OK) + { + printf("internal error - compression failed on second pass: %d\n", err); + exit(0); + } + + char *newfile = new char[strlen(file)+3]; + strcpy(newfile, file); + if (!strstr(file, ".amxx") && !strstr(file, ".AMXX")) + strcat(newfile, "x"); + + FILE *fp = fopen(newfile, "wb"); + if (!fp) + { + printf("Error trying to write file %s.\n", newfile); + exit(0); + } + + //magic + archn + int hdrsize = sizeof(long) + sizeof(char); + int entry = sizeof(long) + sizeof(long) + sizeof(char); + int offset1 = hdrsize + (entry * 2); + int offset2 = offset1 + pl32.cmpsize; + + int magic = MAGIC_HEADER; + fwrite((void *)&magic, sizeof(int), 1, fp); + char n = 2; + fwrite((void *)&n, sizeof(char), 1, fp); + + fwrite((void *)&(pl32.cellsize), sizeof(char), 1, fp); + fwrite((void *)&(pl32.stp), sizeof(long), 1, fp); + fwrite((void *)&(offset1), sizeof(long), 1, fp); + fwrite((void *)&(pl64.cellsize), sizeof(char), 1, fp); + fwrite((void *)&(pl64.stp), sizeof(long), 1, fp); + fwrite((void *)&(offset2), sizeof(long), 1, fp); + fwrite(pl32.cmp, sizeof(char), pl32.cmpsize, fp); + fwrite(pl64.cmp, sizeof(char), pl64.cmpsize, fp); + + fclose(fp); + + unlink(file); + + printf("Done.\n"); + + dlclose(lib); + + exit(0); +} + +//we get the full name of the file here +//our job is to a] switch the .sma extension to .amx +// and to b] strip everything but the trailing name +char *swiext(const char *file, const char *ext, int isO) +{ + int i = 0, pos = -1, j = 0; + int fileLen = strlen(file); + int extLen = strlen(ext); + int max = 0, odirFlag = -1; + + for (i=fileLen-1; i>=0; i--) + { + if (file[i] == '.' && pos == -1) + { + pos = i+1; + } + if ((file[i] == '/' || file[i] == '\\') && !isO) + { + odirFlag = i+1; + //realign pos - we've just stripped fileLen-i chars + pos -= i + 1; + break; + } + } + + char *newbuffer = new char[fileLen+strlen(ext)+2]; + fileLen += strlen(ext); + if (odirFlag == -1) + { + strcpy(newbuffer, file); + } else { + strcpy(newbuffer, &(file[odirFlag])); + } + + if (pos > -1) + { + for (i=pos; i0) + { + return swiext(argv[save], "amx", 0); + } + + return NULL; +} + +void show_help() +{ + printf("Options:\n"); + printf("\t-A alignment in bytes of the data segment and the stack\n"); + printf("\t-a output assembler code\n"); + printf("\t-C[+/-] compact encoding for output file (default=-)\n"); + printf("\t-c codepage name or number; e.g. 1252 for Windows Latin-1\n"); + printf("\t-Dpath active directory path\n"); + printf("\t-d0 no symbolic information, no run-time checks\n"); + printf("\t-d1 [default] run-time checks, no symbolic information\n"); + printf("\t-d2 full debug information and dynamic checking\n"); + printf("\t-d3 full debug information, dynamic checking, no optimization\n"); + printf("\t-e set name of error file (quiet compile)\n"); + printf("\t-H window handle to send a notification message on finish\n"); + printf("\t-i path for include files\n"); + printf("\t-l create list file (preprocess only)\n"); + printf("\t-o set base name of output file\n"); + printf("\t-p set name of \"prefix\" file\n"); + printf("\t-r[name] write cross reference report to console or to specified file\n"); +} diff --git a/compiler/amxxpc/amxxpc.h b/compiler/amxxpc/amxxpc.h new file mode 100755 index 00000000..cec83117 --- /dev/null +++ b/compiler/amxxpc/amxxpc.h @@ -0,0 +1,51 @@ +#ifndef _AMXXSC_INCLUDE_H +#define _AMXXSC_INCLUDE_H + +#define VERSION_STRING "1.50-300" +#define VERSION 03000 +#define MAGIC_HEADER 0x414D5842 + +#ifdef __linux__ +# include +#else +# include +#endif + +#include + +#ifdef __linux__ +# define dlmount(x) dlopen(x, RTLD_NOW) + typedef void* HINSTANCE; +#else +# define dlsym(x, s) GetProcAddress(x, s) +# define dlmount(x) LoadLibrary(x) +# define dlclose(x) FreeLibrary(x) +#endif + +#include "zlib.h" + +typedef int (*COMPILER)(int argc, char **argv); +typedef int (*PRINTF)(const char *message, ...); + +char *FindFileName(int argc, char **argv); +char *swiext(const char *file, const char *ext); +void show_help(); + + +struct ablhdr +{ + int magic; + char size; +}; + +struct abl +{ + long stp; + char cellsize; + int size; + long cmpsize; + char *data; + char *cmp; +}; + +#endif //_AMXXSC_INCLUDE_H diff --git a/compiler/amxxpc/amxxpc.sln b/compiler/amxxpc/amxxpc.sln new file mode 100755 index 00000000..a397c2e0 --- /dev/null +++ b/compiler/amxxpc/amxxpc.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "amxxpc", "amxxpc.vcproj", "{39412290-D01C-472F-A439-AB5592A04C08}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {39412290-D01C-472F-A439-AB5592A04C08}.Debug.ActiveCfg = Debug|Win32 + {39412290-D01C-472F-A439-AB5592A04C08}.Debug.Build.0 = Debug|Win32 + {39412290-D01C-472F-A439-AB5592A04C08}.Release.ActiveCfg = Release|Win32 + {39412290-D01C-472F-A439-AB5592A04C08}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/compiler/amxxpc/amxxpc.vcproj b/compiler/amxxpc/amxxpc.vcproj new file mode 100755 index 00000000..a16966d0 --- /dev/null +++ b/compiler/amxxpc/amxxpc.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/compiler/amxxpc/amxxpc1.rc b/compiler/amxxpc/amxxpc1.rc new file mode 100755 index 00000000..0fd6c894 --- /dev/null +++ b/compiler/amxxpc/amxxpc1.rc @@ -0,0 +1,72 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource1.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource1.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +1 ICON "favicon.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/compiler/amxxpc/favicon.ico b/compiler/amxxpc/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..4e34066150f2ae52a44b6205ca69a43863b15bf6 GIT binary patch literal 766 zcmchVJr2S!428|l#=^whk-ZW#L&TI@P~{vQJ8&CDmJStS$U(S8`Cdxf3=9kiCw6SV zXD794wqO;-)+EoR*^YCM7U&UO*cyv~jUx6?p-i2&)wMj7r4*)ZTQYsx*7x#ImQon^ z0|}LyoQA_WAMc7|taK1J^8Dk1mH6fYAvRO|fZ#C$oS-{!H^vSugA*Z#>D|oLs^W@j zs>Y#Pdeb|X_!$8>C+IEgi2&SX9R%yjk>Jx?AiN9sUhc`hH+IC#L-rdP204zC$)0bv dxrVtklx2CS=GcWWv$OOUF2BQnWL1B>=LIQP$l3q^ literal 0 HcmV?d00001 diff --git a/compiler/amxxpc/osdefs.h b/compiler/amxxpc/osdefs.h new file mode 100755 index 00000000..60d61e68 --- /dev/null +++ b/compiler/amxxpc/osdefs.h @@ -0,0 +1,60 @@ +/* __MSDOS__ set when compiling for DOS (not Windows) + * _Windows set when compiling for any version of Microsoft Windows + * __WIN32__ set when compiling for Windows95 or WindowsNT (32 bit mode) + * __32BIT__ set when compiling in 32-bit "flat" mode (DOS or Windows) + * + * Copyright 1998-2002, ITB CompuPhase, The Netherlands. + * info@compuphase.com. + */ + +#ifndef _OSDEFS_H +#define _OSDEFS_H + +/* Every compiler uses different "default" macros to indicate the mode + * it is in. Throughout the source, we use the Borland C++ macros, so + * the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to + * those of Borland C++. + */ +#if defined(__WATCOMC__) +# if defined(__WINDOWS__) || defined(__NT__) +# define _Windows 1 +# endif +# ifdef __386__ +# define __32BIT__ 1 +# endif +# if defined(_Windows) && defined(__32BIT__) +# define __WIN32__ 1 +# endif +#elif defined(_MSC_VER) +# if defined(_WINDOWS) || defined(_WIN32) +# define _Windows 1 +# endif +# ifdef _WIN32 +# define __WIN32__ 1 +# define __32BIT__ 1 +# endif +#endif + +#if defined __linux__ + #include +#endif + +/* Linux NOW has these */ +#if !defined BIG_ENDIAN + #define BIG_ENDIAN 4321 +#endif +#if !defined LITTLE_ENDIAN + #define LITTLE_ENDIAN 1234 +#endif + +/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */ +#if !defined BYTE_ORDER + #if defined UCLINUX + #define BYTE_ORDER BIG_ENDIAN + #else + #define BYTE_ORDER LITTLE_ENDIAN + #endif +#endif + +#endif /* _OSDEFS_H */ + diff --git a/compiler/amxxpc/resource.h b/compiler/amxxpc/resource.h new file mode 100755 index 00000000..c5a4bded --- /dev/null +++ b/compiler/amxxpc/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by amxxsc.rc +// +#define ICON 5 +#define IDI_ICON1 104 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/compiler/amxxpc/resource1.h b/compiler/amxxpc/resource1.h new file mode 100755 index 00000000..c32213f3 --- /dev/null +++ b/compiler/amxxpc/resource1.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by amxxsc1.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/compiler/amxxpc/sclinux.h b/compiler/amxxpc/sclinux.h new file mode 100755 index 00000000..f22497a8 --- /dev/null +++ b/compiler/amxxpc/sclinux.h @@ -0,0 +1,47 @@ +/* + * Things needed to compile under linux. + * + * Should be reworked totally to use GNU's 'configure' + */ +#ifndef SCLINUX_H +#define SCLINUX_H + +/* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the + * controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling + * terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must + * be put back correctly when the function ends. See GETCH.C for an implementation. + * + * For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to + * have a complete emacs/vi like line editing system. + */ +#include "getch.h" + +#define stricmp(a,b) strcasecmp(a,b) +#define strnicmp(a,b,c) strncasecmp(a,b,c) + +/* + * WinWorld wants '\'. Unices do not. + */ +#define DIRECTORY_SEP_CHAR '/' +#define DIRECTORY_SEP_STR "/" + +/* + * SC assumes that a computer is Little Endian unless told otherwise. It uses + * (and defines) the macros BYTE_ORDER and BIG_ENDIAN. + * For Linux, we must overrule these settings with those defined in glibc. + */ +#if !defined __BYTE_ORDER +# include +#endif + +#if defined __OpenBSD__ || defined __FreeBSD__ +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +#endif + +#if !defined __BYTE_ORDER +# error "Can't figure computer byte order (__BYTE_ORDER macro not found)" +#endif + +#endif /* SCLINUX_H */ diff --git a/compiler/amxxpc/testmini.c b/compiler/amxxpc/testmini.c new file mode 100755 index 00000000..2e5e13f5 --- /dev/null +++ b/compiler/amxxpc/testmini.c @@ -0,0 +1,155 @@ +/* testmini.c -- very simple test program for the miniLZO library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + */ + + +#include +#include + + +/************************************************************************* +// This program shows the basic usage of the LZO library. +// We will compress a block of data and decompress again. +// +// For more information, documentation, example programs and other support +// files (like Makefiles and build scripts) please download the full LZO +// package from +// http://www.oberhumer.com/opensource/lzo/ +**************************************************************************/ + +/* First let's include "minizo.h". */ + +#include "minilzo.h" + + +/* We want to compress the data block at `in' with length `IN_LEN' to + * the block at `out'. Because the input block may be incompressible, + * we must provide a little more output space in case that compression + * is not possible. + */ + +#if defined(__LZO_STRICT_16BIT) +#define IN_LEN (8*1024) +#else +#define IN_LEN (128*1024L) +#endif +#define OUT_LEN (IN_LEN + IN_LEN / 64 + 16 + 3) + +static lzo_byte in [ IN_LEN ]; +static lzo_byte out [ OUT_LEN ]; + + +/* Work-memory needed for compression. Allocate memory in units + * of `lzo_align_t' (instead of `char') to make sure it is properly aligned. + */ + +#define HEAP_ALLOC(var,size) \ + lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] + +static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS); + + +/************************************************************************* +// +**************************************************************************/ + +int main(int argc, char *argv[]) +{ + int r; + lzo_uint in_len; + lzo_uint out_len; + lzo_uint new_len; + +#if defined(__EMX__) + _response(&argc,&argv); + _wildcard(&argc,&argv); +#endif + + if (argc < 0 && argv == NULL) /* avoid warning about unused args */ + return 0; + + printf("\nLZO real-time data compression library (v%s, %s).\n", + lzo_version_string(), lzo_version_date()); + printf("Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer\n\n"); + + +/* + * Step 1: initialize the LZO library + */ + if (lzo_init() != LZO_E_OK) + { + printf("lzo_init() failed !!!\n"); + return 3; + } + +/* + * Step 2: prepare the input block that will get compressed. + * We just fill it with zeros in this example program, + * but you would use your real-world data here. + */ + in_len = IN_LEN; + lzo_memset(in,0,in_len); + +/* + * Step 3: compress from `in' to `out' with LZO1X-1 + */ + r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem); + if (r == LZO_E_OK) + printf("compressed %lu bytes into %lu bytes\n", + (long) in_len, (long) out_len); + else + { + /* this should NEVER happen */ + printf("internal error - compression failed: %d\n", r); + return 2; + } + /* check for an incompressible block */ + if (out_len >= in_len) + { + printf("This block contains incompressible data.\n"); + return 0; + } + +/* + * Step 4: decompress again, now going from `out' to `in' + */ + r = lzo1x_decompress(out,out_len,in,&new_len,NULL); + if (r == LZO_E_OK && new_len == in_len) + printf("decompressed %lu bytes back into %lu bytes\n", + (long) out_len, (long) in_len); + else + { + /* this should NEVER happen */ + printf("internal error - decompression failed: %d\n", r); + return 1; + } + + printf("\nminiLZO simple compression test passed.\n"); + return 0; +} + +/* +vi:ts=4 +*/ + diff --git a/compiler/amxxpc/zconf.h b/compiler/amxxpc/zconf.h new file mode 100755 index 00000000..3cea897e --- /dev/null +++ b/compiler/amxxpc/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/compiler/amxxpc/zlib.h b/compiler/amxxpc/zlib.h new file mode 100755 index 00000000..92edf96f --- /dev/null +++ b/compiler/amxxpc/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/compiler/amxxpc/zlib.lib b/compiler/amxxpc/zlib.lib new file mode 100755 index 0000000000000000000000000000000000000000..d5348407fc90c3a723bfc1a223e0b3baf671eef4 GIT binary patch literal 221206 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 literal 0 HcmV?d00001 diff --git a/compiler/libpc300/amx.h b/compiler/libpc300/amx.h index cf194750..b0443801 100755 --- a/compiler/libpc300/amx.h +++ b/compiler/libpc300/amx.h @@ -249,11 +249,9 @@ typedef struct tagAMX { cell reset_stk PACKED; cell reset_hea PACKED; cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */ - #if defined JIT - /* support variables for the JIT */ - int reloc_size PACKED; /* required temporary buffer for relocations */ - long code_size PACKED; /* estimated memory footprint of the native code */ - #endif + /* support variables for the JIT */ + int reloc_size PACKED; /* required temporary buffer for relocations */ + long code_size PACKED; /* estimated memory footprint of the native code */ } PACKED AMX; /* The AMX_HEADER structure is both the memory format as the file format. The @@ -279,13 +277,8 @@ typedef struct tagAMX_HEADER { int32_t nametable PACKED; /* name table */ } PACKED AMX_HEADER; -#if PAWN_CELL_SIZE==16 - #define AMX_MAGIC 0xf1e2 -#elif PAWN_CELL_SIZE==32 - #define AMX_MAGIC 0xf1e0 -#elif PAWN_CELL_SIZE==64 - #define AMX_MAGIC 0xf1e1 -#endif +//This is always the same for us +#define AMX_MAGIC 0xf1e0 enum { AMX_ERR_NONE, diff --git a/compiler/libpc300/libpawnc.c b/compiler/libpc300/libpawnc.c index 13fcc8e8..39b42ab0 100755 --- a/compiler/libpc300/libpawnc.c +++ b/compiler/libpc300/libpawnc.c @@ -56,48 +56,13 @@ # if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __NT__ __declspec (dllexport) - void EXCOMPILER(HWND hwnd, HINSTANCE hinst, LPSTR lpCommandLine, int nCmdShow) + void EXCOMPILER(int argc, char **argv) # else - void extern EXCOMPILER(HWND hwnd, HINSTANCE hinst, LPSTR lpCommandLine, int nCmdShow) + void extern EXCOMPILER(int argc, char **argv) # endif { - char RootPath[_MAX_PATH]; - LPSTR ptr; - - /* RUNDLL32 may have passed us a HWND and a HINSTANCE, but we can hardly - * trust these. They may not contain values that we can use. - */ - - /* the root path in argv[0] */ - GetModuleFileName(hinstDLL, RootPath, sizeof RootPath); - argv[argc++]=RootPath; - - /* all other options */ - assert(lpCommandLine!=NULL); - ptr=dll_skipwhite(lpCommandLine); - while (*ptr!='\0') { - if (*ptr=='"') { - argv[argc++]=ptr+1; - while (*ptr!='"' && *ptr!='\0') - ptr++; - } else { - argv[argc++]=ptr; - while (*ptr>' ') - ptr++; - } /* if */ - if (*ptr!='\0') - *ptr++='\0'; - ptr=dll_skipwhite(ptr); - } /* while */ - pc_compile(argc,argv); - UNUSED_PARAM(hwnd); - UNUSED_PARAM(hinst); - UNUSED_PARAM(nCmdShow); + pc_compile(argc, argv); } - -#else /* PAWNC_DLL */ - - #endif /* PAWNC_DLL */ diff --git a/compiler/libpc300/libpc300.vcproj b/compiler/libpc300/libpc300.vcproj index 87880631..cf897b05 100755 --- a/compiler/libpc300/libpc300.vcproj +++ b/compiler/libpc300/libpc300.vcproj @@ -258,6 +258,9 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + + diff --git a/compiler/libpc300/sclist.c b/compiler/libpc300/sclist.c index ab96a9e7..7d24e142 100755 --- a/compiler/libpc300/sclist.c +++ b/compiler/libpc300/sclist.c @@ -409,16 +409,18 @@ SC_FUNC stringlist *insert_dbgline(int linenr) char string[40]; if (linenr>0) linenr--; /* line numbers are zero-based in the debug information */ -#if PAWN_CELL_SIZE==32 sprintf(string,"L:%08lx %04x",(long)code_idx,linenr); -#elif PAWN_CELL_SIZE==64 - sprintf(string,"L:%08Lx %04x",(long)code_idx,linenr); -#endif return insert_string(&dbgstrings,string); } /* if */ return NULL; } +#ifdef WIN32 +#define LONGCAST long +#else +#define LONGCAST cell +#endif + SC_FUNC stringlist *insert_dbgsymbol(symbol *sym) { if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) { @@ -440,10 +442,10 @@ SC_FUNC stringlist *insert_dbgsymbol(symbol *sym) symname,sym->codeaddr,code_idx,sym->ident,sym->vclass); #elif PAWN_CELL_SIZE==64 if (sym->ident==iFUNCTN) - sprintf(string,"S:%08Lx %x:%s %08Lx %08Lx %x %x",sym->addr,sym->tag, + sprintf(string,"S:%08Lx %x:%s %08Lx %08Lx %x %x",(LONGCAST)sym->addr,sym->tag, symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass); else - sprintf(string,"S:%08Lx %x:%s %08Lx %08Lx %x %x",sym->addr,sym->tag, + sprintf(string,"S:%08Lx %x:%s %08Lx %08Lx %x %x",(LONGCAST)sym->addr,sym->tag, symname,sym->codeaddr,code_idx,sym->ident,sym->vclass); #endif if (sym->ident==iARRAY || sym->ident==iREFARRAY) {