diff --git a/compiler/scasm/amx_compiler.cpp b/compiler/scasm/amx_compiler.cpp index fb77bb8a..5a12d8df 100755 --- a/compiler/scasm/amx_compiler.cpp +++ b/compiler/scasm/amx_compiler.cpp @@ -308,7 +308,7 @@ bool Compiler::Compile() char c = (*dmi)->fill; for (int iter=0; iter<=(*dmi)->e.GetNumber(); iter++) { - fwrite((void*)&c, sizeof(char), 1, fp); + fwrite((void*)&c, sizeof(int32_t), 1, fp); } } } @@ -334,6 +334,7 @@ bool Compiler::Parse() std::ifstream fp(filename.c_str()); char buffer[256] = {0}; std::stack DefStack; + std::stack LabelStack; curLine = 0; AsmSection sec = Asm_None; lastCip = 0-cellsize; @@ -347,7 +348,7 @@ bool Compiler::Parse() while (!fp.eof()) { fp.getline(buffer, 255); - curLine++; + curLine+=1; /* Check for preprocessor directives */ if (buffer[0] == '#') @@ -440,6 +441,14 @@ bool Compiler::Parse() sec = Asm_Invalid; CError->ErrorMsg(Err_Invalid_Section, buffer); } + /* Update the labels */ + CLabels->CompleteQueue(true); + while (!LabelStack.empty()) + { + CLabels->EraseLabel(LabelStack.top()); + CSymbols->EraseSymbol(LabelStack.top()); + LabelStack.pop(); + } } else { /* Do pre-processing */ CMacros->SearchAndReplace(line); @@ -501,7 +510,7 @@ bool Compiler::Parse() t.Evaluate(); e.Set(amt); e.Evaluate(); - DAT->Add(symbol, e, false, (char)t.GetNumber()); + DAT->Add(symbol, e, false, t.GetNumber()); } else { e.Set(data); e.Evaluate(); @@ -570,6 +579,7 @@ bool Compiler::Parse() Asm *ASM = new Asm; ASM->cip = lastCip + cellsize; ASM->op = OpCodes["proc"]; + ASM->line = curLine; lastCip += cellsize; /* Add symbol */ S = CSymbols->AddSymbol(params, Sym_Proc, CurLine()); @@ -578,7 +588,16 @@ bool Compiler::Parse() /* Add to PROC list */ PROC->AddProc(S, ASM); } else if (code.compare("ENDP") == 0) { - /* This is, in theory, not needed */ + /* This is, in theory, not needed + * Nonetheless, we check labels here + */ + CLabels->CompleteQueue(true); + while (!LabelStack.empty()) + { + CLabels->EraseLabel(LabelStack.top()); + CSymbols->EraseSymbol(LabelStack.top()); + LabelStack.pop(); + } } else if (params.size() < 1 && code[code.size()-1] == ':') { /* Label! */ /* Check if symbol is valid */ @@ -604,6 +623,10 @@ bool Compiler::Parse() } continue; } + if (code[0] == '_') + { + LabelStack.push(code); + } S = CSymbols->AddSymbol(code, Sym_Label, CurLine()); CLabels->AddLabel(S, lastCip+cellsize); } else { @@ -623,6 +646,7 @@ bool Compiler::Parse() ASM = new Asm; ASM->cip = lastCip+cellsize; ASM->op = OP_LINE; + ASM->line = curLine; ASM->params.push_back(curLine); ASM->params.push_back(0); CodeList.push_back(ASM); @@ -647,6 +671,7 @@ bool Compiler::Parse() ASM->cip = (lastCip+cellsize); ASM->op = op; + ASM->line = curLine; lastCip += cellsize; switch (op) @@ -1801,7 +1826,7 @@ void Compiler::ProcessDirective(std::string &text) SymbolList::Symbol *S; if ((S = CSymbols->FindSymbol(symbol)) != NULL) { - CError->ErrorMsg(Err_SymbolRedef, curLine, S->sym.c_str(), S->line); + CError->ErrorMsg(Err_SymbolRedef, S->sym.c_str(), S->line); } /* Store the argstring, which is the rest of the data */ std::string argstring; @@ -1827,8 +1852,22 @@ void Compiler::ProcessDirective(std::string &text) CSymbols->AddSymbol(symbol, Sym_Macro, curLine); //TODO: ClearList(ArgList); } - } else if (!directive.compare("stacksize")) { - + } else if (!directive.compare("pragma")) { + std::string pragma; + std::string entry; + StringBreak(definition, pragma, entry); + if (pragma.compare("stacksize") == 0) + { + int stksz = atoi(entry.c_str()); + if (stksz < 100) + { + CError->ErrorMsg(Err_Invalid_Pragma); + } else { + stacksize = stksz; + } + } else { + CError->ErrorMsg(Err_Invalid_Pragma); + } } else if (!directive.compare("define")) { std::string symbol; std::string def; @@ -1859,8 +1898,6 @@ int Compiler::Eval(std::string &str, SymbolType sym) int i = 0; rpn *r = new rpn; int pos = 0; - int val = 0; - CExpr e; Stack.push(r); @@ -1890,18 +1927,10 @@ int Compiler::Eval(std::string &str, SymbolType sym) { bpstr.assign(str.substr(pos, i-pos)); Strip(bpstr); + CExpr e(CError); e.Set(bpstr); - val = 0; - if (!e.Analyze() && IsValidSymbol(bpstr)) - { - val = DerefSymbol(bpstr, sym); - } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { - val = e.GetNumber(); - } else { - CError->ErrorMsg(Err_Invalid_Symbol); - return 0; - } - r->vals.push_back(val); + e.Evaluate(sym); + r->vals.push_back(e); } r->ops.push_back(str[i]); if (str[i] == '>' || str[i] == '<') @@ -1917,18 +1946,10 @@ int Compiler::Eval(std::string &str, SymbolType sym) { bpstr.assign(str.substr(pos, i-pos)); Strip(bpstr); + CExpr e(CError); e.Set(bpstr); - val = 0; - if (!e.Analyze() && IsValidSymbol(bpstr)) - { - val = DerefSymbol(bpstr, sym); - } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { - val = e.GetNumber(); - } else { - CError->ErrorMsg(Err_Invalid_Symbol); - return 0; - } - r->vals.push_back(val); + e.Evaluate(sym); + r->vals.push_back(e); } r = new rpn; Stack.push(r); @@ -1939,20 +1960,13 @@ int Compiler::Eval(std::string &str, SymbolType sym) { bpstr.assign(str.substr(pos, i-pos)); Strip(bpstr); + CExpr e(CError); e.Set(bpstr); - val = 0; - if (!e.Analyze() && IsValidSymbol(bpstr)) - { - val = DerefSymbol(bpstr, sym); - } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { - val = e.GetNumber(); - } else { - CError->ErrorMsg(Err_Invalid_Symbol); - return 0; - } - r->vals.push_back(val); + e.Evaluate(sym); + r->vals.push_back(e); } - val = EvalRpn(r, sym); + CExpr t; + t = EvalRpn(r, sym); delete r; if (Stack.size() < 2) { @@ -1967,7 +1981,7 @@ int Compiler::Eval(std::string &str, SymbolType sym) } Stack.pop(); r = Stack.top(); - r->vals.push_back(val); + r->vals.push_back(t); pos = i + 1; } else if (i == (int)(str.size() - 1)) { if (pos < i) @@ -1979,18 +1993,10 @@ int Compiler::Eval(std::string &str, SymbolType sym) if (pos < i || pos == i) { Strip(bpstr); + CExpr e(CError); e.Set(bpstr); - val = 0; - if (!e.Analyze() && IsValidSymbol(bpstr)) - { - val = DerefSymbol(bpstr, sym); - } else if (e.Analyze() && (e.Evaluate() == Val_Number)) { - val = e.GetNumber(); - } else { - CError->ErrorMsg(Err_Invalid_Symbol); - return 0; - } - r->vals.push_back(val); + e.Evaluate(sym); + r->vals.push_back(e); } } } @@ -2009,19 +2015,18 @@ int Compiler::Eval(std::string &str, SymbolType sym) rpn *r2 = Stack.top(); Stack.pop(); - val = EvalRpn(r, sym); + CExpr final; + final = EvalRpn(r, sym); - return val; + return final.GetNumber(); } -int Compiler::EvalRpn(rpn *r, SymbolType sym) +CExpr 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; + CExpr er, el; + std::vector::iterator Q; std::vector::iterator R; while (r->ops.size()) @@ -2035,77 +2040,17 @@ int Compiler::EvalRpn(rpn *r, SymbolType sym) { if ((int)r->vals.size() <= j) assert(0);// Can't have more ops than values - lval = r->vals[j]; + el = 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; - } + er = r->vals[j+1]; + el.Oper((OpToken)i, er); + } else { + el.Not(); } R = r->ops.begin(); Q = r->vals.begin(); @@ -2114,13 +2059,13 @@ int Compiler::EvalRpn(rpn *r, SymbolType sym) R += j; Q += j; r->ops.erase(R); - r->vals[j+1] = nval; + r->vals[j+1] = el; r->vals.erase(Q); j--; } else { R += j; r->ops.erase(R); - r->vals[j] = nval; + r->vals[j] = el; } } } @@ -2232,4 +2177,14 @@ int Compiler::DerefSymbol(std::string &str, SymbolType sym) } return val; -} \ No newline at end of file +} + +bool Compiler::IsSymbol(std::string &str) +{ + SymbolList::Symbol *S = 0; + + if ( (S = CSymbols->FindSymbol(str)) == NULL ) + return false; + + return true; +} diff --git a/compiler/scasm/amx_compiler.h b/compiler/scasm/amx_compiler.h index 9d9d6878..916d0a70 100755 --- a/compiler/scasm/amx_compiler.h +++ b/compiler/scasm/amx_compiler.h @@ -40,30 +40,12 @@ lastCip+=cellsize; \ } -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; + std::vector vals; }; class Compiler @@ -91,9 +73,10 @@ public: //private void Init(); void InitOpcodes(); int Eval(std::string &str, SymbolType sym = Sym_None); - int EvalRpn(rpn *r, SymbolType sym); + CExpr EvalRpn(rpn *r, SymbolType sym); OpToken OperToken(char c); char OperChar(OpToken c); + bool IsSymbol(std::string &str); private: std::vector CodeList; std::map OpCodes; @@ -115,4 +98,4 @@ private: Asm *curAsm; }; -#endif //_INCLUDE_AMXCOMPILER_H \ No newline at end of file +#endif //_INCLUDE_AMXCOMPILER_H diff --git a/compiler/scasm/amx_data.cpp b/compiler/scasm/amx_data.cpp index eabaa589..7e6b517d 100755 --- a/compiler/scasm/amx_data.cpp +++ b/compiler/scasm/amx_data.cpp @@ -47,7 +47,7 @@ DataMngr::Datum::Datum() fill = 0; } -void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill) +void DataMngr::Add(std::string &s, CExpr &expr, bool db, int fill) { DataMngr::Datum *D = new DataMngr::Datum(); @@ -63,7 +63,7 @@ void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill) size = ((D->e.GetType() == Val_Number) ? cellsize : D->e.Size() * cellsize); } else { - size = D->e.GetNumber(); + size = (D->e.GetNumber() * cellsize); } if (List.size() == 0) @@ -77,7 +77,7 @@ void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill) ((p->e.GetType() == Val_Number) ? cellsize : p->e.Size() * cellsize); } else { - D->offset = p->offset + p->e.GetNumber(); + D->offset = p->offset + (p->e.GetNumber() * cellsize); } } diff --git a/compiler/scasm/amx_data.h b/compiler/scasm/amx_data.h index 6888f275..fec1088c 100755 --- a/compiler/scasm/amx_data.h +++ b/compiler/scasm/amx_data.h @@ -34,13 +34,13 @@ public: CExpr e; bool db; int offset; - char fill; + int fill; }; public: ~DataMngr(); DataMngr() { cellsize = 4; lastOffset = 0; cursize = 0; } DataMngr(int cell) { lastOffset = 0; cellsize = cell; cursize = 0; } - void Add(std::string &s, CExpr &expr, bool db = false, char fill = 0); + void Add(std::string &s, CExpr &expr, bool db = false, int fill = 0); DataMngr::Datum *FindData(std::string &sym); void GetData(std::vector &dList); int GetOffset(std::string &sym); diff --git a/compiler/scasm/amx_error.cpp b/compiler/scasm/amx_error.cpp index 4459a7ce..42372e8f 100755 --- a/compiler/scasm/amx_error.cpp +++ b/compiler/scasm/amx_error.cpp @@ -26,6 +26,7 @@ ErrorMngr::ErrorMngr() { printf("Not instantiated with a compiler."); Cmp = NULL; + line = -1; assert(Cmp); } @@ -56,6 +57,7 @@ ErrorMngr::ErrorMngr(void *c) Totals[1] = 0; Totals[2] = 0; Totals[3] = 0; + line = -1; HighestError = Err_None; } @@ -95,6 +97,9 @@ void ErrorMngr::DefineErrors() List.at(Err_Unknown_Define) = "Unknown define referenced"; List.at(Err_Misplaced_Directive) = "Misplaced preprocessor directive"; List.at(Err_Bad_Label) = "Label referenced without being created"; + List.at(Err_Bad_Not) = "Wrong type argument to bit-complement"; + List.at(Err_Invalid_Operator) = "Operator used on bad type"; + List.at(Err_Invalid_Pragma) = "Invalid pragma"; List.at(Err_FileNone) = "No file specified"; List.at(Err_FileOpen) = "Could not open file \"%s\""; @@ -131,13 +136,23 @@ void ErrorMngr::ErrorMsg(ErrorCode error, ...) if (type == -1) return; + int curLine = 0; + + if (line == -1) + { + curLine = ((Compiler *)Cmp)->CurLine(); + } else { + curLine = line; + line = -1; + } + 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)); + sprintf(errbuf, "%s(%d) on line %d: %s\n", ErrorSwi[type], error, curLine, GetError(error)); vprintf(errbuf, argptr); va_end(argptr); @@ -163,4 +178,19 @@ const char *ErrorMngr::GetError(ErrorCode id) if (id < notices_start || id > fatals_end) return NULL; return List.at(id); +} + +int ErrorMngr::DerefSymbol(std::string &str, int sym) +{ + return ((Compiler *)Cmp)->DerefSymbol(str, (SymbolType)sym); +} + +bool ErrorMngr::IsSymbol(std::string &str) +{ + return ((Compiler *)Cmp)->IsSymbol(str); +} + +void ErrorMngr::SetLine(int ln) +{ + line = ln; } \ No newline at end of file diff --git a/compiler/scasm/amx_error.h b/compiler/scasm/amx_error.h index dcdadc1d..20995671 100755 --- a/compiler/scasm/amx_error.h +++ b/compiler/scasm/amx_error.h @@ -60,6 +60,9 @@ typedef enum Err_Unknown_Define, Err_Misplaced_Directive, Err_Bad_Label, + Err_Bad_Not, + Err_Invalid_Operator, + Err_Invalid_Pragma, errors_end, fatals_start, @@ -87,6 +90,7 @@ private: ErrorType HighestError; void *Cmp; int Totals[4]; + int line; public: ErrorMngr(); ErrorMngr(void *c); @@ -96,6 +100,9 @@ public: void PrintReport(); int CurLine(); int CurCip(); + void SetLine(int ln); + int DerefSymbol(std::string &str, int sym = 0); + bool IsSymbol(std::string &str); }; #endif //_INCLUDE_AMX_ERROR diff --git a/compiler/scasm/amx_label.cpp b/compiler/scasm/amx_label.cpp index 4bcdcb87..5f2e31a6 100755 --- a/compiler/scasm/amx_label.cpp +++ b/compiler/scasm/amx_label.cpp @@ -91,7 +91,7 @@ void LabelMngr::QueueLabel(std::string &sym, Asm *ASM) LQ[d].push(ASM); } -void LabelMngr::CompleteQueue() +void LabelMngr::CompleteQueue(bool isLocal) { std::map >::iterator i; std::stack *stk = 0; @@ -106,13 +106,22 @@ void LabelMngr::CompleteQueue() stk = &((*i).second); if (p == NULL || p->cip == LabelMngr::ncip) { - CError->ErrorMsg(Err_Bad_Label); - } - while (!stk->empty()) - { - ASM = stk->top(); - ASM->params[0] = p->cip; - stk->pop(); + if ((!isLocal || (isLocal && search[0]=='_')) && CError) + { + while (!stk->empty()) + { + CError->SetLine(stk->top()->line); + CError->ErrorMsg(Err_Bad_Lbel); + stk->pop(); + } + } + } else { + while (!stk->empty()) + { + ASM = stk->top(); + ASM->params[0] = p->cip; + stk->pop(); + } } } @@ -129,4 +138,20 @@ int LabelMngr::GetCip(std::string &sym) return ncip; return p->cip; +} + +bool LabelMngr::EraseLabel(std::string &sym) +{ + std::vector::iterator i; + + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i)->sym->IsEqual(sym) ) + { + List.erase(i); + return true; + } + } + + return false; } \ No newline at end of file diff --git a/compiler/scasm/amx_label.h b/compiler/scasm/amx_label.h index 219f20a8..8361c1a4 100755 --- a/compiler/scasm/amx_label.h +++ b/compiler/scasm/amx_label.h @@ -43,7 +43,8 @@ public: void Clear(); bool SetCip(std::string &sym, int cip); void QueueLabel(std::string &sym, Asm *ASM); - void CompleteQueue(); + void CompleteQueue(bool isLocal = false); + bool EraseLabel(std::string &sym); private: std::vector List; std::map > LQ; diff --git a/compiler/scasm/amx_proc.cpp b/compiler/scasm/amx_proc.cpp index 732d1ed0..e7e9aca5 100755 --- a/compiler/scasm/amx_proc.cpp +++ b/compiler/scasm/amx_proc.cpp @@ -67,9 +67,9 @@ bool ProcMngr::SetPublic(std::string &sym) void ProcMngr::GetPublics(std::vector &pbList) { - std::vector::iterator i; + std::vector::reverse_iterator i; - for (i=List.begin(); i!=List.end(); i++) + for (i=List.rbegin(); i!=List.rend(); i++) { if ((*i)->pb == true) { diff --git a/compiler/scasm/amx_symbol.cpp b/compiler/scasm/amx_symbol.cpp index 40c9fe4f..5fcb15c8 100755 --- a/compiler/scasm/amx_symbol.cpp +++ b/compiler/scasm/amx_symbol.cpp @@ -118,3 +118,18 @@ void SymbolList::PrintTable() printf("Symbol \"%s\" defined on line %d\n", (*i)->sym.c_str(), (*i)->line); } } + +bool SymbolList::EraseSymbol(std::string &sym) +{ + std::vector::iterator i; + for (i=List.begin(); i!=List.end(); i++) + { + if ( (*i)->IsEqual(sym) ) + { + List.erase(i); + return true; + } + } + + return false; +} diff --git a/compiler/scasm/amx_symbol.h b/compiler/scasm/amx_symbol.h index 3b7cb2b7..51884714 100755 --- a/compiler/scasm/amx_symbol.h +++ b/compiler/scasm/amx_symbol.h @@ -54,6 +54,7 @@ public: SymbolList::Symbol* AddSymbol(std::string &sym, SymbolType type, int line); SymbolList::Symbol* AddSymbol(const char *szSym, SymbolType type, int line); SymbolList::Symbol* FindSymbol(std::string &sym); + bool EraseSymbol(std::string &sym); void PrintTable(); void Clear(); private: diff --git a/compiler/scasm/amxasm.cpp b/compiler/scasm/amxasm.cpp index 6faa647d..4509764d 100755 --- a/compiler/scasm/amxasm.cpp +++ b/compiler/scasm/amxasm.cpp @@ -28,6 +28,8 @@ int main(int argc, char **argv) { Compiler Program; + getchar(); + get_options(argc, argv, Program); if (filename.size() < 1) @@ -38,8 +40,16 @@ int main(int argc, char **argv) Program.Load(filename); if (Program.Parse()) + { + //Program.PrintCodeList(); if (Program.Compile()) printf("Done.\n"); + } + /*ErrorMngr CError(&Program); + std::string f("232+4*4"); + int val = Program.Eval(f); + + printf("Evaluation: %d\n", val);*/ exit(0); } diff --git a/compiler/scasm/amxasm.h b/compiler/scasm/amxasm.h index a75ff6bd..387f08d7 100755 --- a/compiler/scasm/amxasm.h +++ b/compiler/scasm/amxasm.h @@ -44,6 +44,7 @@ public: int op; std::vector params; int cip; + int line; }; #include "amx.h" diff --git a/compiler/scasm/cexpr.cpp b/compiler/scasm/cexpr.cpp index ad8af7ce..2671ff1c 100755 --- a/compiler/scasm/cexpr.cpp +++ b/compiler/scasm/cexpr.cpp @@ -28,6 +28,7 @@ CExpr::CExpr() numVal = 0; type = Val_None; block = 0; + bDone = false; CError = NULL; } @@ -36,6 +37,7 @@ CExpr::CExpr(ErrorMngr *e) numVal = 0; type = Val_None; block = 0; + bDone = false; CError = e; } @@ -45,6 +47,7 @@ CExpr::CExpr(ErrorMngr *e, std::string &text) type = Val_None; block = 0; CError = e; + bDone = false; data.assign(text); } @@ -59,7 +62,7 @@ void CExpr::Clear() CExpr::~CExpr() { - if (block) + if (block && type == Val_Block) delete [] block; } @@ -180,13 +183,17 @@ const char *CExpr::GetString(int *d) int CExpr::GetNumber() { + if (type == Val_Float) + { + memcpy((void*)&numVal, (void*)&fData, sizeof(float)); + } return numVal; } /* Returns true if the expr can be evaluated */ int CExpr::Analyze() { - size_t pos = 0, xc = 0, xpos = 0; + size_t pos = 0, xc = 0, xpos = 0, fd = 0; /* run through the characters */ if (data.compare("$") == 0) { @@ -194,10 +201,14 @@ int CExpr::Analyze() } for (pos = 0; pos < data.size(); pos++) { - if (data[pos] == 'x') + if (data[pos] == '.') { + fd++; + if (fd > 1 || xc) + return 0; + } else if (data[pos] == 'x') { xc++; - if (xc > 1) + if (xc > 1 || fd) return 0; xpos = pos; } else if (data[pos] != ' ' @@ -210,7 +221,7 @@ int CExpr::Analyze() return 1; } -cExprType CExpr::Evaluate() +cExprType CExpr::Evaluate(int symNum) { size_t i = 0, blk = 0; char litc = 0, c = 0, csave = 0; @@ -218,14 +229,22 @@ cExprType CExpr::Evaluate() std::string num; block = new char[2]; + bDone = true; if (data.compare("$") == 0) { - t = Val_Number; + type = Val_Number; numVal = CError->CurCip(); - char buf[32]; - sprintf(buf, "%d", numVal); - data.assign(buf); + Update(); + return t; + } else { + if (CError->IsSymbol(data) || (IsValidSymbol(data) && symNum == Sym_Label)) + { + type = Val_Number; + numVal = CError->DerefSymbol(data, symNum); + Update(); + return t; + } } if (data.find('\'', 0) != std::string::npos || data.find('"', 0) != std::string::npos) @@ -307,13 +326,20 @@ cExprType CExpr::Evaluate() numVal++; } } else { - - /* Just get the number */ - t = Val_Number; - numVal = DeHex(data); - char buf[32]; - sprintf(buf, "%d", numVal); - data.assign(buf); + if (data.find('.', 0) != std::string::npos) + { + /* Get as a float */ + fData = (float)atof(data.c_str()); + t = Val_Float; + memcpy((void*)&numVal, (void*)&fData, sizeof(float)); + } else { + /* Just get the number */ + t = Val_Number; + numVal = DeHex(data); + char buf[32]; + sprintf(buf, "%d", numVal); + data.assign(buf); + } } if (litc) @@ -326,3 +352,183 @@ cExprType CExpr::Evaluate() return t; } + +void CExpr::Not() +{ + if (type != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Bad_Not); + } + numVal = ~numVal; +} + +void CExpr::Oper(OpToken op, CExpr &e) +{ + switch (op) + { + case Token_Xor: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal = numVal ^ e.GetNumber(); + break; + } + case Token_Shr: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal >>= e.GetNumber(); + break; + } + case Token_Sub: + { + if (GetType() == Val_Number) + { + if (e.GetType() == Val_Number) + { + numVal -= e.GetNumber(); + } else if (e.GetType() == Val_Float) { + numVal -= (int)e.GetFloat(); + } + } else if (GetType() == Val_Float) { + if (e.GetType() == Val_Number) + { + fData -= (float)e.GetNumber(); + } else if (e.GetType() == Val_Float) { + fData -= e.GetFloat(); + } + } + break; + } + case Token_Mod: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal = numVal % e.GetNumber(); + break; + } + case Token_Mul: + { + if (GetType() == Val_Number) + { + if (e.GetType() == Val_Number) + { + numVal *= e.GetNumber(); + } else if (e.GetType() == Val_Float) { + numVal *= (int)e.GetFloat(); + } + } else if (GetType() == Val_Float) { + if (e.GetType() == Val_Number) + { + fData *= (float)e.GetNumber(); + } else if (e.GetType() == Val_Float) { + fData *= e.GetFloat(); + } + } + break; + } + case Token_Div: + { + if (GetType() == Val_Number) + { + if (e.GetType() == Val_Number) + { + numVal /= e.GetNumber(); + } else if (e.GetType() == Val_Float) { + numVal /= (int)e.GetFloat(); + } + } else if (GetType() == Val_Float) { + if (e.GetType() == Val_Number) + { + fData /= (float)e.GetNumber(); + } else if (e.GetType() == Val_Float) { + fData /= e.GetFloat(); + } + } + break; + } + case Token_Shl: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal <<= e.GetNumber(); + break; + } + case Token_And: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal &= e.GetNumber(); + break; + } + case Token_Or: + { + if (e.GetType() != Val_Number) + { + if (CError) + CError->ErrorMsg(Err_Invalid_Operator); + } + numVal |= e.GetNumber(); + break; + } + case Token_Add: + { + if (GetType() == Val_Number) + { + if (e.GetType() == Val_Number) + { + numVal += e.GetNumber(); + } else if (e.GetType() == Val_Float) { + numVal += (int)e.GetFloat(); + } + } else if (GetType() == Val_Float) { + if (e.GetType() == Val_Number) + { + fData += (float)e.GetNumber(); + } else if (e.GetType() == Val_Float) { + fData += e.GetFloat(); + } + } + break; + } + default: + { + numVal = 0; + break; + } + } + + Update(); +} + +void CExpr::Update() +{ + if (type == Val_Float) + { + numVal = (int)fData; + } else if (type == Val_Number) { + fData = (float)numVal; + } + if (type != Val_String && type != Val_Block) + { + char buf[24]; + sprintf(buf, "%d", numVal); + data.assign(buf); + } +} \ No newline at end of file diff --git a/compiler/scasm/cexpr.h b/compiler/scasm/cexpr.h index b27666d0..ed856bdd 100755 --- a/compiler/scasm/cexpr.h +++ b/compiler/scasm/cexpr.h @@ -27,6 +27,24 @@ * It reads in a symbol and evaluates it. */ +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; + typedef enum { Val_None, @@ -38,6 +56,7 @@ typedef enum Val_Number, Val_Block, Val_Hex, + Val_Float, } cExprType; class CExpr @@ -49,13 +68,17 @@ public: void Set(std::string &text); const char *GetString(int *d=NULL); int Analyze(); - cExprType Evaluate(); + cExprType Evaluate(int symNum = 0); cExprType GetType(); int GetNumber(); + float GetFloat() { return fData; } int Size(); void Clear(); + void Not(); + void Oper(OpToken op, CExpr &e); ~CExpr(); private: + void Update(); char IsHex(char c); char IsLiteral(char c); int DeHex(std::string blk); @@ -63,7 +86,9 @@ private: char *block; std::string data; cExprType type; + float fData; int numVal; + bool bDone; private: ErrorMngr *CError; };