From 06098e3bf147b6403dcb17114c7802eae1c0bc30 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 6 Aug 2004 08:46:59 +0000 Subject: [PATCH] Imported: AMXXSC, LIBSC, SCASM --- compiler/scasm/amx.h | 383 +++++++ compiler/scasm/amx_compiler.cpp | 1743 +++++++++++++++++++++++++++++++ compiler/scasm/amx_compiler.h | 90 ++ compiler/scasm/amx_data.cpp | 87 ++ compiler/scasm/amx_data.h | 52 + compiler/scasm/amx_define.cpp | 84 ++ compiler/scasm/amx_define.h | 48 + compiler/scasm/amx_error.cpp | 127 +++ compiler/scasm/amx_error.h | 92 ++ compiler/scasm/amx_label.cpp | 73 ++ compiler/scasm/amx_label.h | 46 + compiler/scasm/amx_macro.cpp | 167 +++ compiler/scasm/amx_macro.h | 57 + compiler/scasm/amx_natives.cpp | 78 ++ compiler/scasm/amx_natives.h | 47 + compiler/scasm/amx_parser.cpp | 187 ++++ compiler/scasm/amx_parser.h | 36 + compiler/scasm/amx_proc.cpp | 101 ++ compiler/scasm/amx_proc.h | 49 + compiler/scasm/amx_symbol.cpp | 105 ++ compiler/scasm/amx_symbol.h | 67 ++ compiler/scasm/amxasm.cpp | 71 ++ compiler/scasm/amxasm.h | 220 ++++ compiler/scasm/asm_macro.h | 6 + compiler/scasm/assembler.vcproj | 199 ++++ compiler/scasm/cexpr.cpp | 284 +++++ compiler/scasm/cexpr.h | 71 ++ 27 files changed, 4570 insertions(+) create mode 100755 compiler/scasm/amx.h create mode 100755 compiler/scasm/amx_compiler.cpp create mode 100755 compiler/scasm/amx_compiler.h create mode 100755 compiler/scasm/amx_data.cpp create mode 100755 compiler/scasm/amx_data.h create mode 100755 compiler/scasm/amx_define.cpp create mode 100755 compiler/scasm/amx_define.h create mode 100755 compiler/scasm/amx_error.cpp create mode 100755 compiler/scasm/amx_error.h create mode 100755 compiler/scasm/amx_label.cpp create mode 100755 compiler/scasm/amx_label.h create mode 100755 compiler/scasm/amx_macro.cpp create mode 100755 compiler/scasm/amx_macro.h create mode 100755 compiler/scasm/amx_natives.cpp create mode 100755 compiler/scasm/amx_natives.h create mode 100755 compiler/scasm/amx_parser.cpp create mode 100755 compiler/scasm/amx_parser.h create mode 100755 compiler/scasm/amx_proc.cpp create mode 100755 compiler/scasm/amx_proc.h create mode 100755 compiler/scasm/amx_symbol.cpp create mode 100755 compiler/scasm/amx_symbol.h create mode 100755 compiler/scasm/amxasm.cpp create mode 100755 compiler/scasm/amxasm.h create mode 100755 compiler/scasm/asm_macro.h create mode 100755 compiler/scasm/assembler.vcproj create mode 100755 compiler/scasm/cexpr.cpp create mode 100755 compiler/scasm/cexpr.h diff --git a/compiler/scasm/amx.h b/compiler/scasm/amx.h new file mode 100755 index 00000000..f1dbb9ff --- /dev/null +++ b/compiler/scasm/amx.h @@ -0,0 +1,383 @@ +/* Abstract Machine for the Small compiler + * + * Copyright (c) ITB CompuPhase, 1997-2004 + * + * This software is provided "as-is", without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Version: $Id$ + */ + +#if defined LINUX + #include +#endif + +#ifndef AMX_H_INCLUDED +#define AMX_H_INCLUDED + +#if defined __LCC__ || defined __DMC__ || defined LINUX + #include +#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* The ISO C99 defines the int16_t and int_32t types. If the compiler got + * here, these types are probably undefined. + */ + #if defined __FreeBSD__ + #include + #else + typedef short int int16_t; + typedef unsigned short int uint16_t; + #if defined SN_TARGET_PS2 + typedef int int32_t; + typedef unsigned int uint32_t; + #else + 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 + +#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */ + #if !defined alloca + #define alloca(n) _alloca(n) + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#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 + #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 + */ +#define CUR_FILE_VERSION 7 /* current file version; also the current AMX version */ +#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */ +#define MIN_AMX_VERSION 7 /* minimum AMX version needed to support the current file format */ + +#if defined BIT16 + #define SMALL_CELL_SIZE 16 /* for backward compatibility */ +#endif +#if !defined SMALL_CELL_SIZE + #define SMALL_CELL_SIZE 32 /* by default, use 32-bit cells */ +#endif +#if SMALL_CELL_SIZE==16 + typedef uint16_t ucell; + typedef int16_t cell; +#elif SMALL_CELL_SIZE==32 + typedef uint32_t ucell; + typedef int32_t cell; +#elif SMALL_CELL_SIZE==64 + typedef uint64_t ucell; + typedef int64_t cell; +#else + #error Unsupported cell size (SMALL_CELL_SIZE) +#endif + +#define UNPACKEDMAX ((1 << (sizeof(cell)-1)*8) - 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__ + #define AMX_NO_ALIGN +#endif + +#if defined __GNUC__ + #define PACKED __attribute__((packed)) +#else + #define PACKED +#endif + +#if !defined AMX_NO_ALIGN + #if defined LINUX + #pragma pack(1) /* structures must be packed (byte-aligned) */ + #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 { + const char _FAR *name PACKED; + AMX_NATIVE func PACKED; +} AMX_NATIVE_INFO PACKED; + +#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 { + uint32_t address PACKED; + char name[sEXPMAX+1] PACKED; +} AMX_FUNCSTUB PACKED; + +/* The AMX structure is the internal structure for many functions. Not all + * fields are valid at all times; many fields are cached in local variables. + */ +typedef struct tagAMX { + unsigned char _FAR *base PACKED; /* points to the AMX header ("amxhdr") plus the code, optionally also the data */ + unsigned char _FAR *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() */ + /* for assertions and debug hook */ + cell curline PACKED; + cell curfile PACKED; + int dbgcode PACKED; + cell dbgaddr PACKED; + cell dbgparam PACKED; + char _FAR *dbgname PACKED; + /* user data */ + long usertags[AMX_USERNUM] PACKED; + void _FAR *userdata[AMX_USERNUM] PACKED; + /* native functions can raise an error */ + int error PACKED; + /* 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 +} AMX PACKED; + +/* 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, file version 7 only */ +} AMX_HEADER PACKED; +#define AMX_MAGIC 0xf1e0 + +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_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 */ +}; + +enum { + DBG_INIT, /* query/initialize */ + DBG_FILE, /* file number in curfile, filename in name */ + DBG_LINE, /* line number in curline, file number in curfile */ + DBG_SYMBOL, /* address in dbgaddr, class/type in dbgparam */ + DBG_CLRSYM, /* stack address below which locals should be removed. stack address in stk */ + DBG_CALL, /* function call, address jumped to in dbgaddr */ + DBG_RETURN, /* function returns */ + DBG_TERMINATE, /* program ends, code address in dbgaddr, reason in dbgparam */ + DBG_SRANGE, /* symbol size and dimensions (arrays); level in dbgaddr (!); length in dbgparam */ + DBG_SYMTAG, /* tag of the most recent symbol (if non-zero), tag in dbgparam */ +}; + +/* AMX_FLAG_CHAR16 0x01 no longer used */ +#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */ +#define AMX_FLAG_COMPACT 0x04 /* compact encoding */ +#define AMX_FLAG_BIGENDIAN 0x08 /* big endian encoding */ +#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking */ +#define AMX_FLAG_BROWSE 0x4000 /* browsing/relocating or executing */ +#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)) + +#define AMX_EXPANDMARGIN 64 + +/* for native functions that use floating point parameters, the following + * two macros are convenient for casting a "cell" into a "float" type _without_ + * changing the bit pattern + */ +#if SMALL_CELL_SIZE==32 + #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ + #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */ +#elif SMALL_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); \ + 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_Debug(AMX *amx); /* default debug procedure, does nothing */ +int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...); +int AMXAPI amx_Execv(AMX *amx, cell *retval, int index, int numparams, cell params[]); +int AMXAPI amx_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); +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_RaiseError(AMX *amx, int error); +int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number); +int AMXAPI amx_Release(AMX *amx, cell amx_addr); +int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); +int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug); +int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar); +int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr); +int AMXAPI amx_StrLen(cell *cstring, int *length); +int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value); +int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); +int AMXAPI amx_UTF8Check(const char *string); + + +#if !defined AMX_NO_ALIGN + #if defined LINUX + #pragma pack() /* reset default packing */ + #else + #pragma pack(pop) /* reset previous packing */ + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* AMX_H_INCLUDED */ diff --git a/compiler/scasm/amx_compiler.cpp b/compiler/scasm/amx_compiler.cpp new file mode 100755 index 00000000..1ba5f3f2 --- /dev/null +++ b/compiler/scasm/amx_compiler.cpp @@ -0,0 +1,1743 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +Compiler::Compiler() +{ + Init(); + curLine = -1; + cellsize = 4; +} + +Compiler::~Compiler() +{ + delete CDefines; + delete CError; + delete CLabels; + delete CMacros; + delete CNatives; + delete CSymbols; + delete PROC; + delete DAT; +} + +Compiler::Compiler(std::string &f) +{ + Init(); + filename.assign(f); + curLine = -1; + cellsize = 4; +} + +void Compiler::Load(std::string &f) +{ + filename.assign(f); +} + +void Compiler::Init() +{ + Compiler *c = this; + /* Load error handling */ + CError = new ErrorMngr(c); + /* Load symbol management */ + CSymbols = new SymbolList; + /* Load constant management */ + CDefines = new DefineMngr; + /* Load macro management */ + CMacros = new MacroList(this); + /* Load DAT management */ + DAT = new DataMngr(cellsize); + /* Load Proc management */ + PROC = new ProcMngr; + /* Load Label management */ + CLabels = new LabelMngr; + /* Load Native management */ + CNatives = new NativeMngr; + /* Load the default symbols + opcodes */ + InitOpcodes(); +} + +bool Compiler::Parse() +{ + std::ifstream fp(filename.c_str()); + char buffer[256] = {0}; + curLine = 0; + AsmSection sec = Asm_None; + lastCip = -1; + + if (!fp.is_open()) + { + CError->ErrorMsg(Err_FileOpen, filename.c_str()); + return false; + } + + while (!fp.eof()) + { + fp.getline(buffer, 255); + curLine++; + + /* Check for preprocessor directives */ + if (buffer[0] == '#') + { + std::string procline(buffer); + ProcessDirective(procline); + continue; + } + + /* Strip the line */ + std::string line(buffer); + StripComments(line); + Strip(line); + + if (line.size() < 1) + continue; + + /* Check for section state changes */ + if (line[0] == '.') + { + if (line.compare(".DATA") == 0) + { + sec = Asm_Data; + } else if (line.compare(".CODE") == 0) { + sec = Asm_Code; + } else if (line.compare(".PUBLIC") == 0) { + sec = Asm_Public; + } else if (line.compare(".NATIVE") == 0) { + sec = Asm_Native; + } else { + sec = Asm_Invalid; + CError->ErrorMsg(Err_Invalid_Section, buffer); + } + } else { + /* Do pre-processing */ + CMacros->SearchAndReplace(line); + CDefines->SearchAndReplace(line); + + /* See if we're not in a section */ + if (sec == Asm_None) + { + if (line.size() > 0) + { + CError->ErrorMsg(Err_Wandering_Stuff); + } + } else if (sec == Asm_Invalid) { + /* Just ignore it */ + } else if (sec == Asm_Data) { + /* Format is Symbol, [db|stat], Data */ + std::string symbol; + std::string data; + std::string buf; + std::string fmt; + + /* Do two splits - line into symbol into data */ + StringBreak(line, symbol, buf); + StringBreak(buf, fmt, data); + + /* Check if the symbol is already defined */ + SymbolList::Symbol *S = NULL; + if ((S = CSymbols->FindSymbol(symbol)) != NULL) + { + CError->ErrorMsg(Err_Symbol_Reuse, symbol.c_str(), S->GetLine()); + continue; + } + + if (fmt.compare("db") && fmt.compare("stat")) + { + CError->ErrorMsg(Err_Invalid_Stor, fmt.c_str()); + continue; + } + + /* Add and evaluate the expression */ + CExpr e(CError); + e.Set(data); + e.Evaluate(); + + /* Add into the DAT section */ + DAT->Add(symbol, e, (fmt.compare("db")==0)?true:false); + } else if (sec == Asm_Public) { + if (!IsValidSymbol(line)) + { + CError->ErrorMsg(Err_Invalid_Symbol); + continue; + } + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(line)) == NULL) + { + CError->ErrorMsg(Err_Unknown_Symbol, line.c_str()); + continue; + } + if ( (S->GetType() != Sym_Proc) ) + { + CError->ErrorMsg(Err_Symbol_Type, Sym_Proc, S->GetType()); + continue; + } + if (!PROC->SetPublic(line)) + { + CError->ErrorMsg(Err_Unknown_Symbol, line.c_str()); + continue; + } + } else if (sec == Asm_Native) { + if (!IsValidSymbol(line)) + { + CError->ErrorMsg(Err_Invalid_Symbol); + continue; + } + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(line)) != NULL) + { + CError->ErrorMsg(Err_Invalid_Symbol, line.c_str(), S->GetLine()); + continue; + } + S = CSymbols->AddSymbol(line.c_str(), Sym_Native, CurLine()); + CNatives->AddNative(S); + } else if (sec == Asm_Code) { + std::string code; + std::string params; + SymbolList::Symbol *S; + + StringBreak(line, code, params); + + if (code.compare("PROC") == 0 || code.compare("proc") == 0) + { + /* Check if symbol is valid */ + if (!IsValidSymbol(params)) + { + CError->ErrorMsg(Err_Invalid_Symbol); + continue; + } + /* Check if the symbol is already used */ + if ( (S = CSymbols->FindSymbol(params)) != NULL) + { + CError->ErrorMsg(Err_Invalid_Symbol, params.c_str(), S->GetLine()); + continue; + } + /* Create instruction */ + Asm *ASM = new Asm; + ASM->cip = ++lastCip; + ASM->op = OpCodes["proc"]; + /* Add symbol */ + S = CSymbols->AddSymbol(params.c_str(), Sym_Proc, CurLine()); + /* Add to code list */ + CodeList.push_back(ASM); + /* Add to PROC list */ + PROC->AddProc(S, ASM); + } else if (code.compare("ENDP") == 0) { + /* This is, in theory, not needed */ + } else if (params.size() < 1 && code[code.size()-1] == ':') { + /* Label! */ + /* Check if symbol is valid */ + if (!IsValidSymbol(code)) + { + CError->ErrorMsg(Err_Invalid_Symbol); + continue; + } + /* Check if the symbol is already used */ + if ( (S = CSymbols->FindSymbol(code)) != NULL) + { + CError->ErrorMsg(Err_Invalid_Symbol, code.c_str(), S->GetLine()); + continue; + } + S = CSymbols->AddSymbol(code.c_str(), Sym_Label, CurLine()); + CLabels->AddLabel(S, lastCip+1); + } else { + /* Check if there is a valid opcode */ + int op = OpCodes[code]; + int argPos; + if (op == OP_NONE) + { + CError->ErrorMsg(Err_Opcode); + continue; + } + + Asm *ASM = new Asm; + std::vector paramList; + + if (params.size() > 0) + { + FindArguments(params, paramList, argPos, true); + if (argPos != params.size()-1) + { + printf("line: %s|%d|%d\n", line.c_str(), argPos, params.size()); + CError->ErrorMsg(Err_Unexpected_Char, params[argPos]); + continue; + } + } + + switch (op) + { + case OP_LOAD_PRI: + { + break; + } + case OP_LOAD_ALT: + { + break; + } + case OP_LOAD_S_PRI: + { + break; + } + case OP_LOAD_S_ALT: + { + break; + } + case OP_LREF_PRI: + { + break; + } + case OP_LREF_ALT: + { + break; + } + case OP_LREF_S_PRI: + { + break; + } + case OP_LREF_S_ALT: + { + break; + } + case OP_LOAD_I: + { + break; + } + case OP_LODB_I: + { + break; + } + case OP_CONST_PRI: + { + break; + } + case OP_CONST_ALT: + { + break; + } + case OP_ADDR_PRI: + { + break; + } + case OP_ADDR_ALT: + { + break; + } + case OP_STOR_PRI: + { + break; + } + case OP_STOR_ALT: + { + break; + } + case OP_STOR_S_PRI: + { + break; + } + case OP_STOR_S_ALT: + { + break; + } + case OP_SREF_PRI: + { + break; + } + case OP_SREF_ALT: + { + break; + } + case OP_SREF_S_PRI: + { + break; + } + case OP_SREF_S_ALT: + { + break; + } + case OP_STOR_I: + { + break; + } + case OP_STRB_I: + { + break; + } + case OP_LIDX: + { + break; + } + case OP_LIDX_B: + { + break; + } + case OP_IDXADDR: + { + break; + } + case OP_IDXADDR_B: + { + break; + } + case OP_ALIGN_PRI: + { + break; + } + case OP_ALIGN_ALT: + { + break; + } + case OP_LCTRL: + { + break; + } + case OP_SCTRL: + { + break; + } + case OP_MOVE_PRI: + { + break; + } + case OP_MOVE_ALT: + { + break; + } + case OP_XCHG: + { + break; + } + case OP_PUSH_PRI: + { + break; + } + case OP_PUSH_ALT: + { + break; + } + case OP_PUSH_R: + { + break; + } + case OP_PUSH_C: + { + break; + } + case OP_PUSH: + { + break; + } + case OP_PUSH_S: + { + break; + } + case OP_POP_PRI: + { + break; + } + case OP_POP_ALT: + { + break; + } + case OP_STACK: + { + break; + } + case OP_HEAP: + { + break; + } + case OP_PROC: + { + break; + } + case OP_RET: + { + break; + } + case OP_RETN: + { + break; + } + case OP_CALL: + { + break; + } + case OP_CALL_PRI: + { + break; + } + case OP_JUMP: + { + break; + } + case OP_JREL: + { + break; + } + case OP_JZER: + { + break; + } + case OP_JNZ: + { + break; + } + case OP_JEQ: + { + break; + } + case OP_JNEQ: + { + break; + } + case OP_JLESS: + { + break; + } + case OP_JLEQ: + { + break; + } + case OP_JGRTR: + { + break; + } + case OP_JGEQ: + { + break; + } + case OP_JSLESS: + { + break; + } + case OP_JSLEQ: + { + break; + } + case OP_JSGRTR: + { + break; + } + case OP_JSGEQ: + { + break; + } + case OP_SHL: + { + break; + } + case OP_SHR: + { + break; + } + case OP_SSHR: + { + break; + } + case OP_SHL_C_PRI: + { + break; + } + case OP_SHL_C_ALT: + { + break; + } + case OP_SHR_C_PRI: + { + break; + } + case OP_SHR_C_ALT: + { + break; + } + case OP_SMUL: + { + break; + } + case OP_SDIV: + { + break; + } + case OP_SDIV_ALT: + { + break; + } + case OP_UMUL: + { + break; + } + case OP_UDIV: + { + break; + } + case OP_UDIV_ALT: + { + break; + } + case OP_ADD: + { + break; + } + case OP_SUB: + { + break; + } + case OP_SUB_ALT: + { + break; + } + case OP_AND: + { + break; + } + case OP_OR: + { + break; + } + case OP_XOR: + { + break; + } + case OP_NOT: + { + break; + } + case OP_NEG: + { + break; + } + case OP_INVERT: + { + break; + } + case OP_ADD_C: + { + break; + } + case OP_SMUL_C: + { + break; + } + case OP_ZERO_PRI: + { + break; + } + case OP_ZERO_ALT: + { + break; + } + case OP_ZERO: + { + break; + } + case OP_ZERO_S: + { + break; + } + case OP_SIGN_PRI: + { + break; + } + case OP_SIGN_ALT: + { + break; + } + case OP_EQ: + { + break; + } + case OP_NEQ: + { + break; + } + case OP_LESS: + { + break; + } + case OP_LEQ: + { + break; + } + case OP_GRTR: + { + break; + } + case OP_GEQ: + { + break; + } + case OP_SLESS: + { + break; + } + case OP_SLEQ: + { + break; + } + case OP_SGRTR: + { + break; + } + case OP_SGEQ: + { + break; + } + case OP_EQ_C_PRI: + { + break; + } + case OP_EQ_C_ALT: + { + break; + } + case OP_INC_PRI: + { + break; + } + case OP_INC_ALT: + { + break; + } + case OP_INC: + { + break; + } + case OP_INC_S: + { + break; + } + case OP_INC_I: + { + break; + } + case OP_DEC_PRI: + { + break; + } + case OP_DEC_ALT: + { + break; + } + case OP_DEC: + { + break; + } + case OP_DEC_S: + { + break; + } + case OP_DEC_I: + { + break; + } + case OP_MOVS: + { + break; + } + case OP_CMPS: + { + break; + } + case OP_FILL: + { + break; + } + case OP_HALT: + { + break; + } + case OP_BOUNDS: + { + break; + } + case OP_SYSREQ_PRI: + { + break; + } + case OP_SYSREQ_C: + { + break; + } + case OP_FILE: + { + break; + } + case OP_LINE: + { + break; + } + case OP_SYMBOL: + { + break; + } + case OP_SRANGE: + { + break; + } + case OP_JUMP_PRI: + { + break; + } + case OP_SWITCH: + { + break; + } + case OP_CASETBL: + { + break; + } + case OP_SWAP_PRI: + { + break; + } + case OP_SWAP_ALT: + { + break; + } + case OP_PUSHADDR: + { + break; + } + case OP_NOP: + { + break; + } + case OP_SYSREQ_D: + { + break; + } + case OP_SYMTAG: + { + break; + } + } + } + } + } + } + + return true; +} + +void Compiler::InitOpcodes() +{ + OpCodes["nop"] = 0; + OpCodes["load.pri"] = 1; + OpCodes["load.alt"] = 2; + OpCodes["load.s.pri"] = 3; + OpCodes["load.s.alt"] = 4; + OpCodes["lref.pri"] = 5; + OpCodes["lref.alt"] = 6; + OpCodes["lref.s.pri"] = 7; + OpCodes["lref.s.alt"] = 8; + OpCodes["load.i"] = 9; + OpCodes["lodb.i"] = 10; + OpCodes["const.pri"] = 11; + OpCodes["const.alt"] = 12; + OpCodes["addr.pri"] = 13; + OpCodes["addr.alt"] = 14; + OpCodes["stor.pri"] = 15; + OpCodes["stor.alt"] = 16; + OpCodes["stor.s.pri"] = 17; + OpCodes["stor.s.alt"] = 18; + OpCodes["sref.pri"] = 19; + OpCodes["sref.alt"] = 20; + OpCodes["sref.s.pri"] = 21; + OpCodes["sref.s.alt"] = 22; + OpCodes["stor.i"] = 23; + OpCodes["strb.i"] = 24; + OpCodes["lidx"] = 25; + OpCodes["lidx.b"] = 26; + OpCodes["idxaddr"] = 27; + OpCodes["idxaddr.b"] = 28; + OpCodes["align.pri"] = 29; + OpCodes["align.alt"] = 30; + OpCodes["lctrl"] = 31; + OpCodes["sctrl"] = 32; + OpCodes["move.pri"] = 33; + OpCodes["move.alt"] = 34; + OpCodes["xchg"] = 35; + OpCodes["push.pri"] = 36; + OpCodes["push.alt"] = 37; + OpCodes["push.r"] = 38; + OpCodes["push.c"] = 39; + OpCodes["push"] = 40; + OpCodes["push.s"] = 41; + OpCodes["pop.pri"] = 42; + OpCodes["pop.alt"] = 43; + OpCodes["stack"] = 44; + OpCodes["heap"] = 45; + OpCodes["proc"] = 46; + OpCodes["ret"] = 47; + OpCodes["retn"] = 48; + OpCodes["call"] = 49; + OpCodes["call.pri"] = 50; + OpCodes["jump"] = 51; + OpCodes["jrel"] = 52; + OpCodes["jzer"] = 53; + OpCodes["jnz"] = 54; + OpCodes["jeq"] = 55; + OpCodes["jneq"] = 56; + OpCodes["jless"] = 57; + OpCodes["jleq"] = 58; + OpCodes["jgrtr"] = 59; + OpCodes["jgeq"] = 60; + OpCodes["jsless"] = 61; + OpCodes["jsleq"] = 62; + OpCodes["jsgrtr"] = 63; + OpCodes["jsgeq"] = 64; + OpCodes["shl"] = 65; + OpCodes["shr"] = 66; + OpCodes["sshr"] = 67; + OpCodes["shl.c.pri"] = 68; + OpCodes["shl.c.alt"] = 69; + OpCodes["shr.c.pri"] = 70; + OpCodes["shr.c.alt"] = 71; + OpCodes["smul"] = 72; + OpCodes["sdiv"] = 73; + OpCodes["sdiv.alt"] = 74; + OpCodes["umul"] = 75; + OpCodes["udiv"] = 76; + OpCodes["udiv.alt"] = 77; + OpCodes["add"] = 78; + OpCodes["sub"] = 79; + OpCodes["sub.alt"] = 80; + OpCodes["and"] = 81; + OpCodes["or"] = 82; + OpCodes["xor"] = 83; + OpCodes["not"] = 84; + OpCodes["neg"] = 85; + OpCodes["invert"] = 86; + OpCodes["add.c"] = 87; + OpCodes["smul.c"] = 88; + OpCodes["zero.pri"] = 89; + OpCodes["zero.alt"] = 90; + OpCodes["zero"] = 91; + OpCodes["zero.s"] = 92; + OpCodes["sign.pri"] = 93; + OpCodes["sign.alt"] = 94; + OpCodes["eq"] = 95; + OpCodes["neq"] = 96; + OpCodes["less"] = 97; + OpCodes["leq"] = 98; + OpCodes["grtr"] = 99; + OpCodes["geq"] = 100; + OpCodes["sless"] = 101; + OpCodes["sleq"] = 102; + OpCodes["sgrtr"] = 103; + OpCodes["sgeq"] = 104; + OpCodes["eq.c.pri"] = 105; + OpCodes["eq.c.alt"] = 106; + OpCodes["inc.pri"] = 107; + OpCodes["inc.alt"] = 108; + OpCodes["inc"] = 109; + OpCodes["inc.s"] = 110; + OpCodes["inc.i"] = 111; + OpCodes["dec.pri"] = 112; + OpCodes["dec.alt"] = 113; + OpCodes["dec"] = 114; + OpCodes["dec.s"] = 115; + OpCodes["dec.i"] = 116; + OpCodes["movs"] = 117; + OpCodes["cmps"] = 118; + OpCodes["fill"] = 119; + OpCodes["halt"] = 120; + OpCodes["bounds"] = 121; + OpCodes["sysreq.pri"] = 122; + OpCodes["sysreq.c"] = 123; + OpCodes["file"] = 124; + OpCodes["line"] = 125; + OpCodes["symbol"] = 126; + OpCodes["srange"] = 127; + OpCodes["jump.pri"] = 128; + OpCodes["switch"] = 129; + OpCodes["casetbl"] = 130; + OpCodes["swap.pri"] = 131; + OpCodes["swap.alt"] = 132; + OpCodes["pushaddr"] = 133; + OpCodes["nop"] = 134; + OpCodes["sysreq.d"] = 135; + OpCodes["symtag"] = 136; + + std::map::iterator i; + for (i=OpCodes.begin(); i!=OpCodes.end(); i++) + { + CSymbols->AddSymbol((*i).first.c_str(), Sym_Reserved, 0); + } + + CSymbols->AddSymbol("db", Sym_Reserved, 0); + CSymbols->AddSymbol("PROC", Sym_Reserved, 0); + CSymbols->AddSymbol("ENDP", Sym_Reserved, 0); + CSymbols->AddSymbol("stat", Sym_Reserved, 0); +} + +char Compiler::OperChar(OpToken c) +{ + switch (c) + { + case Token_Or: + return '|'; + break; + case Token_Xor: + return '^'; + break; + case Token_And: + return '&'; + break; + case Token_Shr: + return '>'; + break; + case Token_Shl: + return '<'; + break; + case Token_Mod: + return '%'; + break; + case Token_Div: + return '/'; + break; + case Token_Mul: + return '*'; + break; + case Token_Sub: + return '-'; + break; + case Token_Add: + return '+'; + break; + case Token_Not: + return '~'; + break; + default: + return Token_None; + break; + } +} + +OpToken Compiler::OperToken(char c) +{ + switch (c) + { + case '|': + return Token_Or; + break; + case '^': + return Token_Xor; + break; + case '&': + return Token_And; + break; + case '>': + return Token_Shr; + break; + case '<': + return Token_Shl; + break; + case '%': + return Token_Mod; + break; + case '/': + return Token_Div; + break; + case '*': + return Token_Mul; + break; + case '-': + return Token_Sub; + break; + case '+': + return Token_Add; + break; + case '~': + return Token_Not; + break; + default: + return Token_None; + break; + } +} + char OperToken(OpToken c); + +/* Returns all the arguments in a list + * This takes literals and expressions into account + * It is assumed that the first ( is stripped! + */ +int Compiler::FindArguments(std::string &text, std::vector &List, int &end, bool simple) +{ + unsigned int i = 0, pos = 0; + char c = 0, d = 0, l = 0, size = 0; + std::stack Stack; + end = -1; + bool temp = false; + + for (i=0; iassign(text.substr(pos, + (i==text.size()-1 && text[i]!=')')? + (i-pos+1):(i-pos))); + Strip(*p); + pos = i+1; + if (p->size() < 1) + { + delete p; + } else { + List.push_back(p); + size++; + } + end = i; + if (text[i] == ')') + break; + } + } + } + + c = d; + } + + if (!Stack.empty()) + { + CError->ErrorMsg(Err_FatalTokenError); + } + + return size; +} + +void Compiler::ProcessDirective(std::string &text) +{ + Strip(text); + if (text[0] == '#') + text.erase(0, 1); + std::string directive; + std::string definition; + /* Split the directive */ + StringBreak(text, directive, definition); + if (!directive.compare("macro")) + { + Strip(definition); + size_t argPos = definition.find('(', 0); + if (argPos == std::string::npos) + { + CError->ErrorMsg(Err_InvalidMacro, curLine); + } else { + /* Store the symbol, which is read up to the occurrence of ( */ + std::string symbol; + symbol.assign(definition.substr(0, argPos-1)); + /* Check if the symbol is already defined */ + SymbolList::Symbol *S; + if ((S = CSymbols->FindSymbol(symbol)) != NULL) + { + CError->ErrorMsg(Err_SymbolRedef, curLine, S->GetSymbol(), S->GetLine()); + } + /* Store the argstring, which is the rest of the data */ + std::string argstring; + argstring.assign(definition.substr(argPos+1, definition.size()-argPos+1)); + /* Parse the arg string, storing the results and the offset to the end */ + int bPos; + std::vector ArgList; + FindArguments(argstring, ArgList, bPos); + /* Store the rest in a function string (macro definition) */ + std::string funcstring; + funcstring.assign(argstring.substr(bPos+1, argstring.size()-bPos+1)); + /* Push the macro onto the Macro List */ + Strip(funcstring); + Strip(symbol); + MacroList::Macro *m = CMacros->AddMacroBegin(symbol, funcstring); + std::vector::iterator i; + for (i=ArgList.begin(); i!=ArgList.end(); i++) + { + CMacros->AddMacroArgument(m, *(*i)); + } + CMacros->AddMacroEnd(m); + /* Make sure to add the symbol */ + CSymbols->AddSymbol(symbol.c_str(), Sym_Macro, curLine); + //TODO: ClearList(ArgList); + } + } else if (!directive.compare("stacksize")) { + + } else if (!directive.compare("define")) { + std::string symbol; + std::string def; + StringBreak(definition, symbol, def); + SymbolList::Symbol *S; + if ((S = CSymbols->FindSymbol(symbol)) != NULL) + { + CError->ErrorMsg(Err_SymbolRedef, curLine, S->GetSymbol(), S->GetLine()); + } + if (def.size() < 1) + def.assign("1"); + CSymbols->AddSymbol(symbol.c_str(), Sym_Define, curLine); + CDefines->AddDefine(symbol, def); + } +} + +/* The evaluator works by storing expressions on a stack. + Each expression is an RPN-ordered pair of lists for ops and values + Every time the stack is popped, the expression is evaluated by searching + for the highest operators and evaluating them. + Note that string literals are not allowed here yet. + */ +int Compiler::Eval(std::string &str, SymbolType sym) +{ + std::stack Stack; + std::string bpstr; + int litidx = 0; + int i = 0; + rpn *r = new rpn; + int pos = 0; + int val = 0; + CExpr e; + + Stack.push(r); + + for (i=0; i<(int)str.size(); i++) + { + if (OperToken(str[i]) != Token_None) + { + if (i == (int)(str.size() - 1)) + { + CError->ErrorMsg(Err_Unexpected_Char, str[i]); + return 0; + } + if (str[i] == '<' && str[i+1] != '<') + { + CError->ErrorMsg(Err_Unexpected_Char, str[i]); + return 0; + } + if (str[i] == '>' && str[i+1] != '>') + { + CError->ErrorMsg(Err_Unexpected_Char, str[i]); + return 0; + } + /* Check to see if there are extra tokens */ + if (pos < i) + { + bpstr.assign(str.substr(pos, i-pos)); + e.Set(bpstr); + val = 0; + if (!e.Analyze() && IsValidSymbol(bpstr)) + { + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(bpstr)) == NULL) + { + CError->ErrorMsg(Err_Unknown_Symbol, bpstr.c_str()); + return 0; + } + if (S->GetType() != sym) + { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + switch (S->GetType()) + { + case Sym_Proc: + { + val = PROC->GetCip(bpstr); + if (val == ProcMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Native: + { + val = CNatives->GetNativeId(bpstr); + if (val == NativeMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Data: + { + val = DAT->GetOffset(bpstr); + if (val == DataMngr::nof) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Label: + { + val = CLabels->GetCip(bpstr); + if (val == LabelMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + default: + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + break; + } + } + } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { + val = e.GetNumber(); + } else { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + r->vals.push_back(val); + } + r->ops.push_back(str[i]); + if (str[i] == '>' || str[i] == '<') + { + i++; + } + pos = i+1; + continue; + } else { + if (str[i] == '(') + { + if (pos < i) + { + bpstr.assign(str.substr(pos, i-pos)); + e.Set(bpstr); + val = 0; + if (!e.Analyze() && IsValidSymbol(bpstr)) + { + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(bpstr)) == NULL) + { + CError->ErrorMsg(Err_Unknown_Symbol, bpstr.c_str()); + return 0; + } + if (S->GetType() != sym) + { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + switch (S->GetType()) + { + case Sym_Proc: + { + val = PROC->GetCip(bpstr); + if (val == ProcMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Native: + { + val = CNatives->GetNativeId(bpstr); + if (val == NativeMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Data: + { + val = DAT->GetOffset(bpstr); + if (val == DataMngr::nof) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Label: + { + val = CLabels->GetCip(bpstr); + if (val == LabelMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + default: + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + break; + } + } + } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { + val = e.GetNumber(); + } else { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + r->vals.push_back(val); + } + r = new rpn; + Stack.push(r); + pos = i+1; + continue; + } else if (str[i] == ')') { + if (pos < i) + { + bpstr.assign(str.substr(pos, i-pos)); + e.Set(bpstr); + val = 0; + if (!e.Analyze() && IsValidSymbol(bpstr)) + { + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(bpstr)) == NULL) + { + CError->ErrorMsg(Err_Unknown_Symbol, bpstr.c_str()); + return 0; + } + if (S->GetType() != sym) + { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + switch (S->GetType()) + { + case Sym_Proc: + { + val = PROC->GetCip(bpstr); + if (val == ProcMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Native: + { + val = CNatives->GetNativeId(bpstr); + if (val == NativeMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Data: + { + val = DAT->GetOffset(bpstr); + if (val == DataMngr::nof) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Label: + { + val = CLabels->GetCip(bpstr); + if (val == LabelMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + default: + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + break; + } + } + } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { + val = e.GetNumber(); + } else { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + r->vals.push_back(val); + } + val = EvalRpn(r, sym); + delete r; + if (Stack.size() < 2) + { + //TODO: Clear memory + CError->ErrorMsg(Err_Unmatched_Token, str[i]); + return 0; + } + Stack.pop(); + r = Stack.top(); + r->vals.push_back(val); + pos = i + 1; + } else if (i == (int)(str.size() - 1)) { + if (pos < i) + { + bpstr.assign(str.substr(pos, i-pos)); + } else if (pos == i) { + bpstr.assign(str.substr(pos, 1)); + } + if (pos < i || pos == i) + { + e.Set(bpstr); + val = 0; + if (!e.Analyze() && IsValidSymbol(bpstr)) + { + SymbolList::Symbol *S = NULL; + if ( (S = CSymbols->FindSymbol(bpstr)) == NULL) + { + CError->ErrorMsg(Err_Unknown_Symbol, bpstr.c_str()); + return 0; + } + if (S->GetType() != sym) + { + assert(0); + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + switch (S->GetType()) + { + case Sym_Proc: + { + val = PROC->GetCip(bpstr); + if (val == ProcMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Native: + { + val = CNatives->GetNativeId(bpstr); + if (val == NativeMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Data: + { + val = DAT->GetOffset(bpstr); + if (val == DataMngr::nof) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + case Sym_Label: + { + val = CLabels->GetCip(bpstr); + if (val == LabelMngr::ncip) + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + break; + } + default: + { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + break; + } + } + } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { + val = e.GetNumber(); + } else { + CError->ErrorMsg(Err_Invalid_Symbol); + return 0; + } + r->vals.push_back(val); + } + } + } + } + + if (Stack.size() != 1) + { + //TODO: Clear memory + CError->ErrorMsg(Err_Unmatched_Token, '('); + return 0; + } + + rpn *r2 = Stack.top(); + Stack.pop(); + val = EvalRpn(r, sym); + + return val; +} + +int Compiler::EvalRpn(rpn *r, SymbolType sym) +{ + int i = 0, j = 0; + char c = 0; + int lval = 0; + int rval = 0; + int nval = 0; + std::vector::iterator Q; + std::vector::iterator R; + + while (r->ops.size()) + { + for (i=1; iops.size(); j++) + { + if (r->ops[j] == c) + { + if ((int)r->vals.size() <= j) + assert(0);// Can't have more ops than values + lval = r->vals[j]; + if (i != Token_Not) + { + if ((int)r->vals.size() <= j+1) + assert(0); + rval = r->vals[j+1]; + } + switch (i) + { + case Token_Xor: + { + nval = lval ^ rval; + break; + } + case Token_Shr: + { + nval = lval >> rval; + break; + } + case Token_Sub: + { + nval = lval - rval; + break; + } + case Token_Mod: + { + nval = lval % rval; + break; + } + case Token_Mul: + { + nval = lval * rval; + break; + } + case Token_Div: + { + nval = (int)(lval / rval); + break; + } + case Token_Shl: + { + nval = lval << rval; + break; + } + case Token_And: + { + nval = lval & rval; + break; + } + case Token_Or: + { + nval = lval | rval; + break; + } + case Token_Add: + { + nval = lval + rval; + break; + } + case Token_Not: + { + nval = ~lval; + break; + } + default: + { + nval = 0; + break; + } + } + R = r->ops.begin(); + Q = r->vals.begin(); + if (i != Token_Not) + { + R += j; + Q += j; + r->ops.erase(R); + r->vals[j+1] = nval; + r->vals.erase(Q); + j--; + } else { + R += j; + r->ops.erase(R); + r->vals[j] = nval; + } + } + } + } + } + + return r->vals[0]; +} \ No newline at end of file diff --git a/compiler/scasm/amx_compiler.h b/compiler/scasm/amx_compiler.h new file mode 100755 index 00000000..a67d0b91 --- /dev/null +++ b/compiler/scasm/amx_compiler.h @@ -0,0 +1,90 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_AMXCOMPILER_H +#define _INCLUDE_AMXCOMPILER_H + +typedef enum +{ + Token_None, + Token_Or, + Token_Xor, + Token_And, + Token_Shr, + Token_Shl, + Token_Mod, + Token_Div, + Token_Mul, + Token_Sub, + Token_Add, + Token_Not, + /* End */ + Tokens_Total, +} OpToken; + +class rpn +{ +public: + //TODO: use linked lists, but not std::list + std::vector ops; + std::vector vals; +}; + +class Compiler +{ +public: + Compiler(); + ~Compiler(); + Compiler(std::string &f); + void Load(std::string &f); + bool Parse(); + bool Compile(); + int CurLine() { return curLine; } + ErrorMngr *ErrorHandler() { return CError; } +public: + int FindArguments(std::string &text, std::vector &List, int &end, bool simple = false); +private: + void ProcessDirective(std::string &text); + void Init(); + void InitOpcodes(); + int Eval(std::string &str, SymbolType sym = Sym_None); + int EvalRpn(rpn *r, SymbolType sym); + OpToken OperToken(char c); + char OperChar(OpToken c); +private: + std::vector CodeList; + std::map OpCodes; + ErrorMngr *CError; + SymbolList *CSymbols; + DefineMngr *CDefines; + MacroList *CMacros; + DataMngr *DAT; + ProcMngr *PROC; + LabelMngr *CLabels; + NativeMngr *CNatives; + std::string filename; + int curLine; + int lastCip; + int cellsize; +}; + +#endif //_INCLUDE_AMXCOMPILER_H \ No newline at end of file diff --git a/compiler/scasm/amx_data.cpp b/compiler/scasm/amx_data.cpp new file mode 100755 index 00000000..175b8e72 --- /dev/null +++ b/compiler/scasm/amx_data.cpp @@ -0,0 +1,87 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +DataMngr::~DataMngr() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +DataMngr::Datum::Datum() +{ + db = false; + offset = -1; +} + +void DataMngr::Add(std::string &s, CExpr &expr, bool db) +{ + DataMngr::Datum *D = new DataMngr::Datum(); + + D->symbol.assign(s); + D->e = expr; + + if (List.size() == 0) + { + D->offset = 0; + } else { + DataMngr::Datum *p = List[List.size()-1]; + D->offset = p->offset + + ((p->e.GetType() == Val_Number) ? + cellsize : p->e.Size() * cellsize); + } +} + +DataMngr::Datum *DataMngr::FindData(std::string &sym) +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ((*i)->symbol.compare(sym) == 0) + { + return (*i); + } + } + + return NULL; +} + +int DataMngr::GetOffset(std::string &sym) +{ + DataMngr::Datum *D = NULL; + + D = FindData(sym); + + if (D == NULL) + return DataMngr::nof; + + return D->offset; +} \ No newline at end of file diff --git a/compiler/scasm/amx_data.h b/compiler/scasm/amx_data.h new file mode 100755 index 00000000..53c037ea --- /dev/null +++ b/compiler/scasm/amx_data.h @@ -0,0 +1,52 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_AMXDATA_H +#define _INCLUDE_AMXDATA_H + +class DataMngr +{ +public: + class Datum + { + public: + Datum(); + std::string symbol; + CExpr e; + bool db; + int offset; + }; +public: + ~DataMngr(); + DataMngr() { cellsize = 4; lastOffset = 0; } + DataMngr(int cell) { lastOffset = 0; cellsize = cell; } + void Add(std::string &s, CExpr &expr, bool db = false); + DataMngr::Datum *FindData(std::string &sym); + int GetOffset(std::string &sym); +private: + std::vector List; + int lastOffset; + int cellsize; + static const int nof = -1; +}; + +#endif //_INCLUDE_AMXDATA_H \ No newline at end of file diff --git a/compiler/scasm/amx_define.cpp b/compiler/scasm/amx_define.cpp new file mode 100755 index 00000000..10ecb318 --- /dev/null +++ b/compiler/scasm/amx_define.cpp @@ -0,0 +1,84 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +DefineMngr::~DefineMngr() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +void DefineMngr::Define::Set(std::string &s, std::string &d) +{ + sym.assign(s); + def.assign(d); +} + +DefineMngr::Define *DefineMngr::AddDefine(std::string &sym, std::string &def) +{ + DefineMngr::Define *D = new DefineMngr::Define; + + D->Set(sym, def); + + List.push_back(D); + + return D; +} + +DefineMngr::Define *DefineMngr::FindDefine(std::string &sym) +{ + std::vector::iterator i; + for (i=List.begin(); i!=List.end(); i++) + { + if ((*i)->GetSymbol()->compare(sym)==0) + { + return (*i); + } + } + return NULL; +} + +void DefineMngr::SearchAndReplace(std::string &text) +{ + std::vector::iterator i; + DefineMngr::Define *D = NULL; + int pos; + + for (i=List.begin(); i!=List.end(); i++) + { + D = (*i); + pos = FindSymbol(text, *(D->GetSymbol()), 0); + if (pos != -1) + { + text.replace(pos, D->GetSymbol()->size(), *(D->GetDefine())); + i = List.begin(); + } + } +} \ No newline at end of file diff --git a/compiler/scasm/amx_define.h b/compiler/scasm/amx_define.h new file mode 100755 index 00000000..eabf8f35 --- /dev/null +++ b/compiler/scasm/amx_define.h @@ -0,0 +1,48 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_DEFINE_H +#define _INCLUDE_DEFINE_H + +class DefineMngr +{ +public: + class Define + { + public: + void Set(std::string &s, std::string &d); + const std::string *GetSymbol() { return &sym; } + const std::string *GetDefine() { return &def; } + private: + std::string sym; + std::string def; + }; +private: + std::vector List; +public: + ~DefineMngr(); + DefineMngr::Define *AddDefine(std::string &sym, std::string &def); + DefineMngr::Define *FindDefine(std::string &sym); + void SearchAndReplace(std::string &text); +}; + +#endif //_INCLUDE_DEFINE_H diff --git a/compiler/scasm/amx_error.cpp b/compiler/scasm/amx_error.cpp new file mode 100755 index 00000000..d7b2f144 --- /dev/null +++ b/compiler/scasm/amx_error.cpp @@ -0,0 +1,127 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +ErrorMngr::ErrorMngr() +{ + printf("Not instantiated with a compiler."); + exit(0); +} + +ErrorMngr::ErrorMngr(void *c) +{ + Cmp = c; + DefineErrors(); + Totals[0] = 0; + Totals[1] = 0; + Totals[2] = 0; + Totals[3] = 0; +} + +ErrorType ErrorMngr::GetErrorType(ErrorCode id) +{ + if (id > fatals_start && id < fatals_end) + return Err_Fatal; + if (id > warnings_start && id < warnings_end) + return Err_Warning; + if (id > notices_start && id < notices_end) + return Err_Notice; + if (id > errors_start && id < errors_end) + return Err_Error; + return Err_None; +} + +void ErrorMngr::DefineErrors() +{ + List.resize(fatals_end+1); + + List.at(Warning_Hex_Start) = "Hexadecimal notation is 0xN, 0 missing"; + List.at(Warning_Null_Expression) = "Bad expression will evaluate to 0"; + + List.at(Err_String_Terminate) = "String not terminated properly"; + List.at(Err_String_Extra) = "Unexpected characters after string end (character '%c')"; + List.at(Err_Unexpected_Char) = "Unexpected character found (character '%c')"; + List.at(Err_Wandering_Stuff) = "Unknown directive placed outside of a section"; + List.at(Err_Symbol_Reuse) = "Symbol \"%s\" already defined on line %d"; + List.at(Err_Invalid_Stor) = "Invalid DAT storage identifier \"%s\""; + List.at(Err_Unknown_Symbol) = "Unknown symbol \"%s\""; + List.at(Err_Symbol_Type) = "Expected symbol type %d, got %d (bad symbol)"; + List.at(Err_Invalid_Symbol) = "Invalid symbol"; + List.at(Err_Opcode) = "Invalid or unrecognized opcode"; + List.at(Err_Unmatched_Token) = "Unmatched token '%c'"; + + List.at(Err_FileNone) = "No file specified"; + List.at(Err_FileOpen) = "Could not open file \"%s\""; + List.at(Err_NoMemory) = "Ran out of memory"; + List.at(Err_PragmaStacksize) = "Invalid stacksize on #pragma stacksize"; + List.at(Err_InvalidMacro) = "Invalid or empty macro definition"; + List.at(Err_SymbolRedef) = "Symbol \"%s\" already defined on line %d"; + List.at(Err_Reserved) = "Symbol assigned to a reserved token"; + List.at(Err_MacroParamCount) = "Parameter count for macro \"%s\" incorrect"; + List.at(Err_FatalTokenError) = "Fatal token error encountered"; + List.at(Err_Invalid_Section) = "Section identifier \"%s\" is not valid, ignoring section."; + + HighestError = Err_None; +} + +void ErrorMngr::ErrorMsg(ErrorCode error, ...) +{ + static char *ErrorSwi[4] = {"Notice", "Warning", "Error", "Fatal Error"}; + static char errbuf[1024]; + ErrorType type = GetErrorType(error); + if (type == -1) + return; + + va_list argptr; + va_start(argptr, error); + + if (((Compiler *)Cmp)->CurLine() == -1) + sprintf(errbuf, "%s(%d): %s\n", ErrorSwi[type], error, GetError(error)); + else + sprintf(errbuf, "%s(%d) on line %d: %s\n", ErrorSwi[type], error, ((Compiler *)Cmp)->CurLine(), GetError(error)); + vprintf(errbuf, argptr); + + va_end(argptr); + + Totals[type]++; + + if (type == Err_Fatal) + exit(0); + if (type > HighestError) + HighestError = type; +} + +const char *ErrorMngr::GetError(ErrorCode id) +{ + if (id == fatals_start || id == fatals_end) + return NULL; + if (id == warnings_start || id == warnings_end) + return NULL; + if (id == notices_start || id == notices_end) + return NULL; + if (id == errors_start || id == errors_end) + return NULL; + if (id < notices_start || id > fatals_end) + return NULL; + return List.at(id); +} \ No newline at end of file diff --git a/compiler/scasm/amx_error.h b/compiler/scasm/amx_error.h new file mode 100755 index 00000000..6afa7b26 --- /dev/null +++ b/compiler/scasm/amx_error.h @@ -0,0 +1,92 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_AMX_ERROR +#define _INCLUDE_AMX_ERROR + +typedef enum +{ + Err_None=-1, + Err_Notice, + Err_Warning, + Err_Error, + Err_Fatal, +} ErrorType; + +typedef enum +{ + notices_start, + notices_end, + + warnings_start, + Warning_Hex_Start, + Warning_Null_Expression, + warnings_end, + + errors_start, + Err_String_Terminate, + Err_String_Extra, + Err_Unexpected_Char, + Err_Invalid_Section, + Err_Wandering_Stuff, + Err_Symbol_Reuse, /* Non-fatal version of Redef */ + Err_Invalid_Stor, + Err_Unknown_Symbol, + Err_Symbol_Type, + Err_Invalid_Symbol, + Err_Opcode, + Err_Unmatched_Token, + errors_end, + + fatals_start, + Err_FileNone, + Err_FileOpen, + Err_NoMemory, + Err_PragmaStacksize, + Err_InvalidMacro, + Err_SymbolRedef, + Err_Reserved, + Err_MacroParamCount, + Err_FatalTokenError, + fatals_end, + +} ErrorCode; + +class ErrorMngr +{ +private: + void DefineErrors(); + const char *GetError(ErrorCode id); + ErrorType GetErrorType(ErrorCode id); +private: + std::vector List; + ErrorType HighestError; + void *Cmp; + int Totals[4]; +public: + ErrorMngr(); + ErrorMngr(void *c); + void ErrorMsg(ErrorCode error, ...); + ErrorType GetStatus() { return HighestError; } +}; + +#endif //_INCLUDE_AMX_ERROR diff --git a/compiler/scasm/amx_label.cpp b/compiler/scasm/amx_label.cpp new file mode 100755 index 00000000..53715f8f --- /dev/null +++ b/compiler/scasm/amx_label.cpp @@ -0,0 +1,73 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +LabelMngr::~LabelMngr() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +void LabelMngr::AddLabel(SymbolList::Symbol *sym, int cip) +{ + LabelMngr::Label *p = new LabelMngr::Label; + + p->sym = sym; + p->cip = cip; + + List.push_back(p); +} + +LabelMngr::Label *LabelMngr::FindLabel(std::string &sym) +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i)->sym->IsEqual(sym) ) + { + return (*i); + } + } + + return NULL; +} + +int LabelMngr::GetCip(std::string &sym) +{ + LabelMngr::Label *p = NULL; + + p = FindLabel(sym); + + if (p == NULL) + return ncip; + + return p->cip; +} \ No newline at end of file diff --git a/compiler/scasm/amx_label.h b/compiler/scasm/amx_label.h new file mode 100755 index 00000000..ca1ebff4 --- /dev/null +++ b/compiler/scasm/amx_label.h @@ -0,0 +1,46 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_AMXLABEL_H +#define _INCLUDE_AMXLABEL_H + +class LabelMngr +{ +public: + class Label + { + public: + SymbolList::Symbol *sym; + int cip; + }; +public: + ~LabelMngr(); + void AddLabel(SymbolList::Symbol *sym, int cip); + LabelMngr::Label *FindLabel(std::string &sym); + int GetCip(std::string &sym); +private: + std::vector List; +public: + static const int ncip = -1; +}; + +#endif //_INCLUDE_AMXLABEL_H \ No newline at end of file diff --git a/compiler/scasm/amx_macro.cpp b/compiler/scasm/amx_macro.cpp new file mode 100755 index 00000000..dee4be92 --- /dev/null +++ b/compiler/scasm/amx_macro.cpp @@ -0,0 +1,167 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +MacroList::~MacroList() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +MacroList::Macro::~Macro() +{ + std::vector::iterator i; + + for (i=argList.begin(); i!=argList.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + argList.clear(); +} + +MacroList::MacroList() +{ + printf("Not instantiated with a compiler\n"); + exit(0); +} + +MacroList::MacroList(void *c) +{ + CError = ((Compiler *)c)->ErrorHandler(); + Cmp = c; +} + +std::string *MacroList::BeginReplacement(MacroList::Macro *macro) +{ + std::string *mstring = new std::string(macro->macro); + + macro->arg = macro->argList.begin(); + macro->argpos = 0; + + return mstring; +} + +int MacroList::ReplaceArgument(MacroList::Macro *m, std::string *macro, std::string &arg, int pos = 0) +{ + int i = 0, bPos = 0; + + bPos = FindSymbol(*macro, *(*m->arg), pos); + + if (bPos != -1) + { + macro->replace(bPos, (*m->arg)->size(), arg); + bPos += (int)arg.size(); + } + + m->arg++; + m->argpos++; + + return bPos; +} + +void MacroList::EndReplacement(MacroList::Macro *m, std::string *macro) +{ + if (m->arg != m->argList.end()) + { + CError->ErrorMsg(Err_MacroParamCount, m->symbol.c_str()); + } + + m->arg = m->argList.begin(); + m->argpos = 0; +} + +MacroList::Macro *MacroList::AddMacroBegin(std::string &symbol, std::string &mac) +{ + Macro *macro = new Macro; + macro->macro.assign(mac); + macro->symbol.assign(symbol); + return macro; +} + +void MacroList::AddMacroArgument(MacroList::Macro *m, std::string &arg) +{ + std::string *sArg = new std::string(arg); + m->argList.push_back(sArg); +} + +void MacroList::AddMacroEnd(MacroList::Macro *m) +{ + List.push_back(m); +} + +MacroList::Macro *MacroList::FindMacro(std::string &sym) +{ + std::vector::iterator i; + for (i=List.begin(); i!=List.end(); i++) + { + if ((*i)->macro.compare(sym) == 0) + return (*i); + } + + return NULL; +} + +void MacroList::SearchAndReplace(std::string &text) +{ + std::vector::iterator i; + MacroList::Macro *m = NULL; + int pos=0, symPos=0, bPos=0, argPos=0; + + for (i=List.begin(); i!=List.end(); i++) + { + m = (*i); + pos = FindSymbol(text, m->symbol, 0); + if (pos != -1) + { + /* Strip the arguments */ + std::string argstring; + symPos = pos + (int)m->symbol.size(); + argstring.assign(text.substr(symPos+1, text.size()-symPos)); + std::vector argList; + ((Compiler *)Cmp)->FindArguments(argstring, argList, bPos); + /* Build the macro */ + std::string *ms; + ms = BeginReplacement(m); + std::vector::iterator j; + for (j=argList.begin(); j!=argList.end(); j++) + { + argPos = ReplaceArgument(m, ms, *(*j), argPos); + } + EndReplacement(m, ms); + /* Search and replace */ + text.replace(pos, bPos-pos, *ms); + /* Cleanup */ + delete ms; + i = List.begin(); + } + } +} \ No newline at end of file diff --git a/compiler/scasm/amx_macro.h b/compiler/scasm/amx_macro.h new file mode 100755 index 00000000..029a6859 --- /dev/null +++ b/compiler/scasm/amx_macro.h @@ -0,0 +1,57 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_MACRO_H +#define _INCLUDE_MACRO_H + +class MacroList +{ +public: + class Macro + { + public: + ~Macro(); + std::vector::iterator arg; + std::vector argList; + std::string symbol; + std::string macro; + int argpos; + }; +public: + MacroList(); + MacroList(void *c); + ~MacroList(); + MacroList::Macro *AddMacroBegin(std::string &symbol, std::string &mac); + void AddMacroArgument(MacroList::Macro *m, std::string &arg); + void AddMacroEnd(MacroList::Macro *m); + MacroList::Macro *FindMacro(std::string &sym); + std::string *BeginReplacement(MacroList::Macro *macro); + int ReplaceArgument(MacroList::Macro *m, std::string *macro, std::string &arg, int pos); + void EndReplacement(MacroList::Macro *m, std::string *macro); + void SearchAndReplace(std::string &text); +private: + std::vector List; + ErrorMngr *CError; + void *Cmp; +}; + +#endif //_INCLUDE_MACRO_H diff --git a/compiler/scasm/amx_natives.cpp b/compiler/scasm/amx_natives.cpp new file mode 100755 index 00000000..2b5ce754 --- /dev/null +++ b/compiler/scasm/amx_natives.cpp @@ -0,0 +1,78 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +NativeMngr::~NativeMngr() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +void NativeMngr::AddNative(SymbolList::Symbol *S) +{ + NativeMngr::Native *N = new NativeMngr::Native; + + N->S = S; + N->used = false; + + List.push_back(N); +} + +int NativeMngr::GetNativeId(std::string &sym) +{ + int pos = 0; + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i)->S->IsEqual(sym) ) + { + return pos; + } + pos++; + } + + return ncip; +} + +NativeMngr::Native *NativeMngr::FindNative(std::string &sym) +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i)->S->IsEqual(sym) ) + { + return (*i); + } + } + + return NULL; +} \ No newline at end of file diff --git a/compiler/scasm/amx_natives.h b/compiler/scasm/amx_natives.h new file mode 100755 index 00000000..bb6d6715 --- /dev/null +++ b/compiler/scasm/amx_natives.h @@ -0,0 +1,47 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_NATIVES_H +#define _INCLUDE_NATIVES_H + +class NativeMngr +{ +public: + class Native + { + public: + Native() { used = false; S = NULL; } + SymbolList::Symbol *S; + bool used; + }; +public: + ~NativeMngr(); + void AddNative(SymbolList::Symbol *S); + NativeMngr::Native *FindNative(std::string &sym); + int GetNativeId(std::string &sym); +public: + static const int ncip = -1; +private: + std::vector List; +}; + +#endif //_INCLUDE_NATIVES_H diff --git a/compiler/scasm/amx_parser.cpp b/compiler/scasm/amx_parser.cpp new file mode 100755 index 00000000..8def3ecb --- /dev/null +++ b/compiler/scasm/amx_parser.cpp @@ -0,0 +1,187 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +char isletter(char c) +{ + if (c >= 65 && c <= 90) + return c; + if (c >= 97 && c <= 122) + return c; + if (c == '_') + return c; + return 0; +} + +char expr(char c) +{ + if (c == '(') + return ')'; + if (c == ')') + return '('; + return 0; +} + +char literal(char c) +{ + if (c == '"') + return '"'; + if (c == '\'') + return '\''; + return 0; +} + +void StripComments(std::string &text) +{ + size_t i = 0; + char c = 0, l = 0; + + for (i=0; i=0; i--) + { + if (!isspace(text[i])) + { + if (i != (int)(text.size() - 1)) + { + text.erase(i+1, text.size()-1-i); + } + break; + } + } +} + +/* This is a very simple symbol searcher + * It only restricts the pattern location to outside of + * string literals and other symbols. + */ +int FindSymbol(std::string &text, const std::string &sym, int startPos = 0) +{ + unsigned int i = 0; + char c = 0, d = 0, l = 0; + + for (i=startPos; i text.size() - i) + break; + + /* Skip literal strings */ + if (l) + { + if (d == l) + l = 0; + c = d; + continue; + } else { + l = literal(d); + if (l) + { + c = d; + continue; + } + } + + /* If the last character was a letter, we're in a symbol already */ + if (isletter(c)) + { + c = d; + continue; + } + + /* If the current character is a letter, test for a symbol */ + if (text.compare(i, sym.size(), sym) == 0) + return i; + + c = d; + } + + return -1; +} + diff --git a/compiler/scasm/amx_parser.h b/compiler/scasm/amx_parser.h new file mode 100755 index 00000000..eb440aea --- /dev/null +++ b/compiler/scasm/amx_parser.h @@ -0,0 +1,36 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_PARSER_H +#define _INCLUDE_PARSER_H + +void StringBreak(std::string &Source, std::string &Left, std::string &Right); +int FindArguments(std::string &text, std::vector &List, int &end); +int FindSymbol(std::string &text, const std::string &sym, int startPos); +void ProcessDirective(std::string &text); +void StripComments(std::string &text); +void Strip(std::string &text); +char isletter(char c); +char literal(char c); +char expr(char c); + +#endif //_INCLUDE_PARSER_H diff --git a/compiler/scasm/amx_proc.cpp b/compiler/scasm/amx_proc.cpp new file mode 100755 index 00000000..085f8968 --- /dev/null +++ b/compiler/scasm/amx_proc.cpp @@ -0,0 +1,101 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +ProcMngr::~ProcMngr() +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +void ProcMngr::AddProc(SymbolList::Symbol *Symbol, Asm *ASM) +{ + ProcMngr::AsmProc *a = new ProcMngr::AsmProc; + + a->ASM = ASM; + a->Symbol = Symbol; + a->pb = false; + + List.push_back(a); +} + +bool ProcMngr::SetPublic(std::string &sym) +{ + ProcMngr::AsmProc *a = NULL; + + a = FindProc(sym); + + if (a == NULL) + return false; + + a->pb = true; + + return true; +} + +void ProcMngr::GetPublics(std::vector &pbList) +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ((*i)->pb == true) + { + pbList.push_back( (*i) ); + } + } +} + +ProcMngr::AsmProc *ProcMngr::FindProc(std::string &sym) +{ + std::vector::iterator i; + + for (i = List.begin(); i != List.end(); i++) + { + if ( (*i)->Symbol->IsEqual(sym) ) + { + return (*i); + } + } + + return NULL; +} + +int ProcMngr::GetCip(std::string &sym) +{ + ProcMngr::AsmProc *p = NULL; + + p = FindProc(sym); + + if (p == NULL) + return ncip; + + return p->ASM->cip; +} \ No newline at end of file diff --git a/compiler/scasm/amx_proc.h b/compiler/scasm/amx_proc.h new file mode 100755 index 00000000..2704f077 --- /dev/null +++ b/compiler/scasm/amx_proc.h @@ -0,0 +1,49 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_AMXPROC_H +#define _INCLUDE_AMXPROC_H + +class ProcMngr +{ +public: + class AsmProc + { + public: + SymbolList::Symbol *Symbol; + Asm *ASM; + bool pb; + }; +public: + ~ProcMngr(); + void AddProc(SymbolList::Symbol *Symbol, Asm *ASM); + ProcMngr::AsmProc *FindProc(std::string &sym); + int GetCip(std::string &sym); + bool SetPublic(std::string &sym); + void GetPublics(std::vector &pbList); +private: + std::vector List; +public: + static const int ncip = -1; +}; + +#endif //_INCLUDE_AMXPROC_H \ No newline at end of file diff --git a/compiler/scasm/amx_symbol.cpp b/compiler/scasm/amx_symbol.cpp new file mode 100755 index 00000000..289932aa --- /dev/null +++ b/compiler/scasm/amx_symbol.cpp @@ -0,0 +1,105 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +bool is_valid_symbol_marker(char c) +{ + if (c >= '0' && c <= '9') + return true; + if (isletter(c)) + return true; + return false; +} + +bool IsValidSymbol(std::string &text) +{ + size_t i = 0; + + if (!text.size() || !isletter(text[0])) + { + return false; + } + + for (i=0; i::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i) ) + delete (*i); + } + + List.clear(); +} + +SymbolList::Symbol::Symbol(SymbolType t, const char *s, int l) +{ + line = l; + sym.assign(s); + type = t; +} + +int SymbolList::Symbol::IsEqual(std::string &s) +{ + return (sym.compare(s)==0); +} + +SymbolList::Symbol *SymbolList::AddSymbol(const char *s, SymbolType type, int line) +{ + Symbol *sym = new Symbol(type, s, line); + List.push_back(sym); + return sym; +} + +SymbolList::Symbol* SymbolList::FindSymbol(std::string &sym) +{ + std::vector::iterator i; + for (i=List.begin(); i!=List.end(); i++) + { + if ((*i)->IsEqual(sym)) + return (*i); + } + + return NULL; +} + +void SymbolList::PrintTable() +{ + std::vector::iterator i; + for (i=List.begin(); i!=List.end(); i++) + { + printf("Symbol \"%s\" defined on line %d\n", (*i)->GetSymbol(), (*i)->GetLine()); + } +} \ No newline at end of file diff --git a/compiler/scasm/amx_symbol.h b/compiler/scasm/amx_symbol.h new file mode 100755 index 00000000..3fff7f0a --- /dev/null +++ b/compiler/scasm/amx_symbol.h @@ -0,0 +1,67 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_SYMBOL_H +#define _INCLUDE_SYMBOL_H + +bool IsValidSymbol(std::string &text); + +typedef enum +{ + Sym_None, + Sym_Define, + Sym_Macro, + Sym_Proc, + Sym_Dat, + Sym_Reserved, + Sym_Label, + Sym_Native, +} SymbolType; + +class SymbolList +{ +public: + class Symbol + { + public: + Symbol(SymbolType t, const char *s, int l); + const char *GetSymbol() { return sym.c_str(); } + SymbolType GetType() { return type; } + int GetLine() { return line; } + int IsEqual(std::string &s); + private: + SymbolType type; + std::string sym; + int line; + }; + +public: + ~SymbolList(); + SymbolList::Symbol* AddSymbol(const char *s, SymbolType type, int line); + SymbolList::Symbol* FindSymbol(std::string &sym); + void PrintTable(); +private: + std::vector List; +}; + + +#endif //_INCLUDE_SYMBOL_H diff --git a/compiler/scasm/amxasm.cpp b/compiler/scasm/amxasm.cpp new file mode 100755 index 00000000..4e1f6ebd --- /dev/null +++ b/compiler/scasm/amxasm.cpp @@ -0,0 +1,71 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include "amxasm.h" + +std::string filename; + +int main(int argc, char **argv) +{ + printf("debug clamp.\n"); + getchar(); + + get_options(argc, argv); + + Compiler Program; + + Program.Load(filename); + Program.Parse(); + + exit(0); +} + +void get_options(int argc, char **argv) +{ + int i = 0; /* index */ + int opt_flag = 0; /* flag for option detection */ + char *option = 0; /* option pointer */ + for (i=1; i +#include +#include +#include +#include +//C++ includes +#include +#include +#include +#include +#include +#include +#include + +class Asm +{ +public: + int op; + std::vector params; + int cip; +}; + +#include "amx.h" +#include "amx_error.h" +#include "cexpr.h" +#include "amx_parser.h" +#include "amx_symbol.h" +#include "amx_macro.h" +#include "amx_define.h" +#include "amx_data.h" +#include "amx_proc.h" +#include "amx_label.h" +#include "amx_natives.h" +#include "amx_compiler.h" //This should be last! + +#define SMALL_CELL_SIZE 32 + +typedef enum +{ + Asm_Invalid = -1, + Asm_None, + Asm_Data, + Asm_Code, + Asm_Public, + Asm_Native, +} AsmSection; + +/* From amx.c */ +typedef enum { + OP_NONE, /* invalid opcode */ + OP_LOAD_PRI, + OP_LOAD_ALT, + OP_LOAD_S_PRI, + OP_LOAD_S_ALT, + OP_LREF_PRI, + OP_LREF_ALT, + OP_LREF_S_PRI, + OP_LREF_S_ALT, + OP_LOAD_I, + OP_LODB_I, + OP_CONST_PRI, + OP_CONST_ALT, + OP_ADDR_PRI, + OP_ADDR_ALT, + OP_STOR_PRI, + OP_STOR_ALT, + OP_STOR_S_PRI, + OP_STOR_S_ALT, + OP_SREF_PRI, + OP_SREF_ALT, + OP_SREF_S_PRI, + OP_SREF_S_ALT, + OP_STOR_I, + OP_STRB_I, + OP_LIDX, + OP_LIDX_B, + OP_IDXADDR, + OP_IDXADDR_B, + OP_ALIGN_PRI, + OP_ALIGN_ALT, + OP_LCTRL, + OP_SCTRL, + OP_MOVE_PRI, + OP_MOVE_ALT, + OP_XCHG, + OP_PUSH_PRI, + OP_PUSH_ALT, + OP_PUSH_R, + OP_PUSH_C, + OP_PUSH, + OP_PUSH_S, + OP_POP_PRI, + OP_POP_ALT, + OP_STACK, + OP_HEAP, + OP_PROC, + OP_RET, + OP_RETN, + OP_CALL, + OP_CALL_PRI, + OP_JUMP, + OP_JREL, + OP_JZER, + OP_JNZ, + OP_JEQ, + OP_JNEQ, + OP_JLESS, + OP_JLEQ, + OP_JGRTR, + OP_JGEQ, + OP_JSLESS, + OP_JSLEQ, + OP_JSGRTR, + OP_JSGEQ, + OP_SHL, + OP_SHR, + OP_SSHR, + OP_SHL_C_PRI, + OP_SHL_C_ALT, + OP_SHR_C_PRI, + OP_SHR_C_ALT, + OP_SMUL, + OP_SDIV, + OP_SDIV_ALT, + OP_UMUL, + OP_UDIV, + OP_UDIV_ALT, + OP_ADD, + OP_SUB, + OP_SUB_ALT, + OP_AND, + OP_OR, + OP_XOR, + OP_NOT, + OP_NEG, + OP_INVERT, + OP_ADD_C, + OP_SMUL_C, + OP_ZERO_PRI, + OP_ZERO_ALT, + OP_ZERO, + OP_ZERO_S, + OP_SIGN_PRI, + OP_SIGN_ALT, + OP_EQ, + OP_NEQ, + OP_LESS, + OP_LEQ, + OP_GRTR, + OP_GEQ, + OP_SLESS, + OP_SLEQ, + OP_SGRTR, + OP_SGEQ, + OP_EQ_C_PRI, + OP_EQ_C_ALT, + OP_INC_PRI, + OP_INC_ALT, + OP_INC, + OP_INC_S, + OP_INC_I, + OP_DEC_PRI, + OP_DEC_ALT, + OP_DEC, + OP_DEC_S, + OP_DEC_I, + OP_MOVS, + OP_CMPS, + OP_FILL, + OP_HALT, + OP_BOUNDS, + OP_SYSREQ_PRI, + OP_SYSREQ_C, + OP_FILE, + OP_LINE, + OP_SYMBOL, + OP_SRANGE, + OP_JUMP_PRI, + OP_SWITCH, + OP_CASETBL, + OP_SWAP_PRI, + OP_SWAP_ALT, + OP_PUSHADDR, + OP_NOP, + OP_SYSREQ_D, + OP_SYMTAG, + /* ----- */ + OP_NUM_OPCODES +} OPCODE; + +void get_options(int argc, char **argv); +void InitOpcodes(); + +#endif //_INCLUDE_AMXASM_H diff --git a/compiler/scasm/asm_macro.h b/compiler/scasm/asm_macro.h new file mode 100755 index 00000000..22aeeb1f --- /dev/null +++ b/compiler/scasm/asm_macro.h @@ -0,0 +1,6 @@ +#ifndef _INCLUDE_MACRO_H +#define _INCLUDE_MACRO_H + + + +#endif //_INCLUDE_MACRO_H \ No newline at end of file diff --git a/compiler/scasm/assembler.vcproj b/compiler/scasm/assembler.vcproj new file mode 100755 index 00000000..6f5a2e0e --- /dev/null +++ b/compiler/scasm/assembler.vcproj @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/compiler/scasm/cexpr.cpp b/compiler/scasm/cexpr.cpp new file mode 100755 index 00000000..8007a3d2 --- /dev/null +++ b/compiler/scasm/cexpr.cpp @@ -0,0 +1,284 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#include +#include "amxasm.h" + +CExpr::CExpr() +{ + numVal = 0; + type = Val_None; + block = 0; + CError = NULL; +} + +CExpr::CExpr(ErrorMngr *e) +{ + numVal = 0; + type = Val_None; + block = 0; + CError = e; +} + +CExpr::CExpr(ErrorMngr *e, std::string &text) +{ + numVal = 0; + type = Val_None; + block = 0; + CError = e; + data.assign(text); +} + +void CExpr::Clear() +{ + if (type == Val_Block && block) + delete [] block; + numVal = 0; + type = Val_None; + block = 0; +} + +CExpr::~CExpr() +{ + if (block) + delete [] block; +} + +char CExpr::IsLiteral(char c) +{ + if (c == '"') + return '"'; + if (c == '\'') + return '\''; + return 0; +} + +char CExpr::IsHex(char c) +{ + if (c >= '0' && c <= '9') + return c; + if (c >= 'A' && c <= 'F') + return c; + if (c >= 'a' && c <= 'f') + return c; + return 0; +} + +cExprType CExpr::GetType() +{ + return type; +} + +void CExpr::Set(std::string &text) +{ + data.assign(text); +} + +int CExpr::DeHex(std::string blk) +{ + size_t pos = 0, xc = 0, xpos = 0; + /* run through the characters */ + for (pos = 0; pos < blk.size(); pos++) + { + if (blk[pos] == 'x') + { + xc++; + if (xc > 1) + break; + xpos = pos; + } else if (blk[pos] != ' ' + && (blk[pos] < '0' || blk[pos] > '9') + && (!xc || (xc && !IsHex(blk[pos])))) { + CError->ErrorMsg(Err_Unexpected_Char, blk[pos]); + return 0; + } + } + if (xc > 1) + { + CError->ErrorMsg(Err_Unexpected_Char, 'x'); + return 0; + } + if (xc) + { + if (xpos == 0 || blk[xpos-1] != '0') + { + if (CError) + CError->ErrorMsg(Warning_Hex_Start); + } + blk.erase(0, xpos+1); + pos = 0; + int j = 0; + while (blk[pos]) + { + blk[pos] -= 48; + if (blk[pos] > 16) + blk[pos] -= 7; + if (blk[pos] >= 16) + blk[pos] -= 32; + if (blk[pos] >= 16 || blk[pos] < 0) + { + if (CError) + CError->ErrorMsg(Err_Unexpected_Char, blk[pos]); + return 0; + } + j *= 16; + j += blk[pos]; + pos++; + } + + return j; + } + + return atoi(blk.c_str()); +} + +int CExpr::Size() +{ + if (type == Val_String || type == Val_Block) + return numVal; + if (type == Val_Number) + return (SMALL_CELL_SIZE/8); + return 0; +} + +const char *CExpr::GetString(int *d) +{ + const char *ret = 0; + + if (type == Val_String) + { + ret = data.c_str(); + if (d != NULL) + *d = numVal; + } else if (type == Val_Block) { + ret = block; + if (d != NULL) + *d = numVal; + } + + return ret; +} + +int CExpr::GetNumber() +{ + return numVal; +} + +/* Returns true if the expr can be evaluated */ +int CExpr::Analyze() +{ + size_t pos = 0, xc = 0, xpos = 0; + /* run through the characters */ + for (pos = 0; pos < data.size(); pos++) + { + if (data[pos] == 'x') + { + xc++; + if (xc > 1) + return 0; + xpos = pos; + } else if (data[pos] != ' ' + && (data[pos] < '0' || data[pos] > '9') + && (!xc || (xc && !IsHex(data[pos])))) { + return 0; + } + } + + return 1; +} + +cExprType CExpr::Evaluate() +{ + size_t i = 0, blk = 0; + char litc = 0, c = 0, csave = 0; + cExprType t = Val_None; + std::string num; + + block = new char[2]; + + if (data.find('\'', 0) != std::string::npos || data.find('"', 0) != std::string::npos) + { + /* STRESS TEST */ + for (i=0; iErrorMsg(Err_String_Extra, data[i+1]); + } else { + /* STRING DISCOVERED */ + t = Val_String; + numVal = (int)(data.size()+1); + break; + } + } else { + litc = IsLiteral(c); + } + } + } + } else if (data.find(' ', 0) != std::string::npos) { + /* Build a mem block from values, store length in numVal */ + t = Val_Block; + size_t pos = 0, npos = 0; + numVal = 0; + pos = data.find(' ', 0); + block[numVal++] = DeHex(data.substr(0, pos)); + while ((pos = data.find(' ', pos)) != std::string::npos) + { + npos = data.find(' ', pos+1); + block = (char *)realloc(block, numVal+2); + if (npos != std::string::npos) + { + block[numVal] = (char)DeHex(data.substr(pos, npos-pos)); + } else { + block[numVal] = (char)DeHex(data.substr(pos)); + } + pos++; + numVal++; + } + } else { + /* Just get the number */ + t = Val_Number; + numVal = DeHex(data); + char buf[32]; + sprintf(buf, "%d", numVal); + data.assign(buf); + } + + if (litc) + { + if (CError) + CError->ErrorMsg(Err_String_Terminate); + } + + type = t; + + return t; +} diff --git a/compiler/scasm/cexpr.h b/compiler/scasm/cexpr.h new file mode 100755 index 00000000..b72d5eec --- /dev/null +++ b/compiler/scasm/cexpr.h @@ -0,0 +1,71 @@ +/* AMX Assembler + * Copyright (C)2004 David "BAILOPAN" Anderson + * + * 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$ + */ + +#ifndef _INCLUDE_CEXPR_H +#define _INCLUDE_CEXPR_H + +/* This class is used for a single expression element + * It reads in a symbol and evaluates it. + */ + +typedef enum +{ + Val_None, + Val_Error, + Val_String, + Val_String_Hex, + Val_String_Number, + Val_Number_Hex, + Val_Number, + Val_Block, + Val_Hex, +} cExprType; + +class CExpr +{ +public: + CExpr(); + CExpr(ErrorMngr *e); + CExpr(ErrorMngr *e, std::string &text); + void Set(std::string &text); + const char *GetString(int *d=NULL); + int Analyze(); + cExprType Evaluate(); + cExprType GetType(); + int GetNumber(); + int Size(); + void Clear(); + ~CExpr(); +private: + char IsHex(char c); + char IsLiteral(char c); + int DeHex(std::string blk); +private: + char *block; + std::string data; + cExprType type; + int numVal; +private: + ErrorMngr *CError; +}; + +#endif //_INCLUDE_CEXPR_H \ No newline at end of file