mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
714 lines
13 KiB
714 lines
13 KiB
#include <assert.h> |
|
#include <map> |
|
#include <vector> |
|
#include "strconv.h" |
|
|
|
enum Type { |
|
VALUE_NONE, |
|
VALUE_STRING, |
|
VALUE_INT, |
|
VALUE_MACRO, |
|
VALUE_FUNCTION, |
|
VALUE_UFUNCTION |
|
}; |
|
|
|
typedef int MInt; |
|
|
|
class MString : public std::string { |
|
public: |
|
MString() : std::string() {} |
|
MString(std::string s) : std::string(s) {} |
|
MString(const char* s) : std::string(s) {} |
|
operator const char* () { return c_str(); } |
|
CUTF8_to_UTF16 utf16() { return CUTF8_to_UTF16(c_str()); } |
|
}; |
|
|
|
class MacroDef; |
|
class FunctionDef; |
|
class Value; |
|
class MacroFile; |
|
struct FunctionData; |
|
|
|
typedef struct { |
|
HWND hWnd; |
|
HWND hTab; |
|
MacroFile* origmf; |
|
MacroFile* mf; |
|
} Context; |
|
|
|
typedef Value (*MacroFunction)(FunctionData*); |
|
|
|
|
|
#define MAX_PARAMS 6 |
|
#include <map> |
|
|
|
struct WindowVar { |
|
short type; |
|
std::map<HWND, Value> val; |
|
} WindowVar; |
|
|
|
class Value { |
|
public: |
|
Type t; |
|
|
|
union { |
|
MInt i; |
|
MacroDef* md; |
|
FunctionDef* uf; |
|
MacroFunction mf; |
|
MString* str; // XXX |
|
}; |
|
|
|
Value() { |
|
t = VALUE_NONE; |
|
} |
|
|
|
virtual ~Value() { |
|
if (t == VALUE_STRING) |
|
delete str; |
|
} |
|
|
|
Value(const Value& v) { |
|
if (v.t == VALUE_STRING) { |
|
t = VALUE_STRING; |
|
str = new MString(v.str->c_str()); |
|
} |
|
else { |
|
memcpy(this, &v, sizeof(Value)); |
|
} |
|
} |
|
|
|
Value(FunctionDef* def) { |
|
t = VALUE_UFUNCTION; |
|
uf = def; |
|
} |
|
|
|
Value(MacroDef* def) { |
|
t = VALUE_MACRO; |
|
md = def; |
|
} |
|
|
|
Value(MacroFunction func) { |
|
t = VALUE_FUNCTION; |
|
mf = func; |
|
} |
|
|
|
Value(const char*c) { |
|
str = new MString(); |
|
t = VALUE_STRING; |
|
str->assign(c); |
|
} |
|
|
|
Value(const std::string& s) { |
|
str = new MString(); |
|
t = VALUE_STRING; |
|
str->assign(s); |
|
} |
|
|
|
/* Value(bool b) { |
|
t = VALUE_STRING; |
|
b ? str.assign("1") : str.assign("0"); |
|
}*/ |
|
|
|
Value(const int n) { |
|
t = VALUE_INT; |
|
i = n; |
|
/*char buf[34]; |
|
itoa(i, buf, 10); |
|
str.assign(buf);*/ |
|
} |
|
|
|
MInt intval() const { |
|
switch (t) { |
|
case VALUE_INT: return i; |
|
case VALUE_STRING: return str->compare("true")==0?1:atoi(str->c_str()); |
|
default : return 0; |
|
} |
|
} |
|
/* |
|
std::string strval() { |
|
switch (t) { |
|
case VALUE_INT: char buf[34];_itoa(i, buf, 10); return buf; |
|
case VALUE_STRING: return str; |
|
default : return ""; |
|
} |
|
} |
|
*/ |
|
MString strval() const { |
|
switch (t) { |
|
case VALUE_INT:{ char buf[34];_itoa(i, buf, 10); return buf;} |
|
case VALUE_STRING: return *str; |
|
default : return ""; |
|
} |
|
} |
|
|
|
MInt boolval() const { |
|
switch (t) { |
|
case VALUE_INT: return i; |
|
case VALUE_STRING: |
|
return str->compare("false") && str->compare("0") && str->compare(""); |
|
default: return 0; |
|
} |
|
} |
|
|
|
bool isint() const { return t == VALUE_INT; } |
|
bool isstring() const{ return t == VALUE_STRING; } |
|
bool ismacro() const { return t == VALUE_MACRO; } |
|
bool isfunction() const { return t == VALUE_FUNCTION; } |
|
bool isufunction() const { return t == VALUE_UFUNCTION; } |
|
bool isvalid() const { return t != VALUE_NONE; } |
|
|
|
MInt operator +(Value& right ){ return intval() + right.intval(); } |
|
MInt operator -(Value& right ){ return intval() - right.intval(); } |
|
MInt operator *(Value& right ){ return intval() * right.intval(); } |
|
MInt operator /(Value& right ){ MInt d = right.intval(); return d ? intval() / d : 0; } |
|
MInt operator %(Value& right ){ MInt d = right.intval(); return d ? intval() % d : 0; } |
|
MInt operator &&(Value& right ){ return boolval() && right.boolval(); } |
|
MInt operator ||(Value& right ){ return boolval() || right.boolval(); } |
|
MInt operator -( ){ return -intval(); } |
|
MInt operator ==(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() == right.intval(); |
|
case VALUE_STRING: return *str == right.strval(); |
|
default : assert(true); return false; |
|
} |
|
} |
|
MInt operator !=(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() != right.intval(); |
|
case VALUE_STRING: return *str != right.strval(); |
|
default : assert(true); return false; |
|
} |
|
} |
|
MInt operator <=(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() <= right.intval(); |
|
case VALUE_STRING: return *str <= right.strval(); |
|
default : assert(true); return false; |
|
} |
|
} |
|
MInt operator >=(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() >= right.intval(); |
|
case VALUE_STRING: return *str >= right.strval(); |
|
default : assert(true); return false; |
|
} |
|
} |
|
MInt operator <(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() < right.intval(); |
|
case VALUE_STRING: return *str < right.strval(); |
|
default : assert(true); return false; |
|
} |
|
} |
|
MInt operator >(Value& right ){ |
|
switch (t) { |
|
case VALUE_INT: return intval() > right.intval(); |
|
case VALUE_STRING: return *str > right.strval(); |
|
default : assert(false); return false; |
|
} |
|
} |
|
|
|
Value operator =(const Value& right ){ |
|
if (right.t == VALUE_STRING) { |
|
if (t == VALUE_STRING) |
|
*str = *right.str; |
|
else { |
|
t = VALUE_STRING; |
|
str = new MString(right.str->c_str()); |
|
} |
|
} |
|
else { |
|
if (t == VALUE_STRING) delete str; |
|
memcpy(this, &right, sizeof(Value)); |
|
} |
|
return *this; |
|
}/* |
|
switch (t) { |
|
case VALUE_INT: i = right.intval(); return i; |
|
case VALUE_STRING: str = right.strval(); return str; |
|
default : |
|
return *this; |
|
} |
|
}*/ |
|
|
|
Value operator =(const MString& right ) { |
|
if (t!=VALUE_STRING) { |
|
t = VALUE_STRING; |
|
str = new MString(right); |
|
} |
|
else |
|
*str = right; |
|
return *this; |
|
} |
|
|
|
Value operator =(const char* right) { |
|
if (t != VALUE_STRING) { |
|
t = VALUE_STRING; |
|
str = new MString(right); |
|
} |
|
else |
|
*str = right; |
|
return *this; |
|
} |
|
|
|
Value operator =(const MInt right) { |
|
if (t == VALUE_STRING) delete str; |
|
t = VALUE_INT; |
|
i = right; |
|
return i; |
|
} |
|
|
|
MString concat(const Value& right) { |
|
return strval() + right.strval(); |
|
} |
|
|
|
MInt operator !(){ return !boolval(); } |
|
|
|
|
|
// inline std::string* operator-> () {return &str;} |
|
|
|
}; |
|
|
|
class Statement; |
|
|
|
typedef struct FunctionData |
|
{ |
|
Context* pc; |
|
Context c; |
|
unsigned short nparam; |
|
Value* params; |
|
Statement* stat; |
|
|
|
Value getarg(unsigned short i) {return i>0&&i<=nparam ? *(params+i-1) : Value();} |
|
MString getstr(unsigned short i, const char* def = "") {return i>0&&i<=nparam ? (params+i-1)->strval() : def;} |
|
int getint(unsigned short i, int def = 0) {return i>0&&i<=nparam ? (params+i-1)->intval() : def;} |
|
int getbool(unsigned short i, int def = 0) {return i>0&&i<=nparam ? (params+i-1)->boolval() : def;} |
|
void setContext(Context* ac) {pc = ac; c = *ac;} |
|
void setWin(HWND h) {pc->hWnd = h;} |
|
|
|
} FunctionData; |
|
|
|
typedef Value ValueFunc; |
|
typedef Value ValueMacro; |
|
typedef Value ValueStr; |
|
typedef Value ValueInt; |
|
|
|
class TDS : public std::map < std::string, Value > |
|
{ |
|
public: |
|
|
|
void emptyvar() |
|
{ |
|
for (TDS::iterator it = begin(); it != end(); it++) |
|
it->second = Value(); |
|
} |
|
|
|
Value* add(const std::string& name, const Value& v) |
|
{ |
|
TDS::iterator it; |
|
it = insert(end(), TDS::value_type(name, v)); |
|
return &it->second; |
|
} |
|
|
|
Value* find(const std::string& name) |
|
{ |
|
TDS::iterator it = __super::find(name); |
|
if (it == end()) |
|
return nullptr; |
|
return &it->second; |
|
} |
|
|
|
std::string find(const Value* val) |
|
{ |
|
for (TDS::iterator it = begin(); it != end(); it++) |
|
if (val == &it->second) |
|
return it->first; |
|
return ""; |
|
} |
|
}; |
|
|
|
typedef enum { |
|
NODE_STATLIST, |
|
NODE_STAT, |
|
NODE_EXPR, |
|
NODE_MACRO, |
|
NODE_FUNCTION, |
|
NODE_VALUE |
|
} NodeType; |
|
|
|
|
|
typedef enum { |
|
STAT_WHILE, |
|
STAT_EXPR, |
|
STAT_IF, |
|
STAT_RETURN, |
|
STAT_BREAK |
|
} StatType; |
|
|
|
typedef enum { |
|
EXPR_NONE = 0, |
|
EXPR_ADD, |
|
EXPR_SUB, |
|
EXPR_MUL, |
|
EXPR_DIV, |
|
EXPR_MOD, |
|
EXPR_GT, |
|
EXPR_LT, |
|
EXPR_GE, |
|
EXPR_LE, |
|
EXPR_NE, |
|
EXPR_EQ, |
|
EXPR_AND, |
|
EXPR_OR, |
|
EXPR_CONCAT, |
|
EXPR_COND, |
|
EXPR_NOT, |
|
EXPR_MINUS, |
|
EXPR_CALL, |
|
EXPR_ASSIGN, |
|
EXPR_VALUE |
|
} ExprType; |
|
|
|
#define ISEXPR(node) (node->t == NODE_EXPR) |
|
#define ISSTAT(node) (node->t == NODE_STAT) |
|
#define ISLIST(node) (node->t == NODE_STATLIST || node->t == NODE_MACRO || node->t == NODE_FUNCTION) |
|
|
|
/* |
|
typedef struct Statement { |
|
StatType t; |
|
MacroNode* A; |
|
MacroNode* B; |
|
MacroNode* C; |
|
} |
|
|
|
typedef struct Expression { |
|
ExprType t; |
|
MacroNode* A; |
|
MacroNode* B; |
|
MacroNode* C; |
|
} |
|
|
|
typdef struct MacroDef { |
|
Value name; |
|
MacroNode* stats; |
|
} |
|
|
|
typedef struct MacroNode { |
|
NodeType t; |
|
union { |
|
Statement stat; |
|
Expression expr; |
|
MacroDef macro; |
|
Value value; |
|
}; |
|
MacroNode* next; |
|
} MacroNode; |
|
*/ |
|
class MacroNode { |
|
public: |
|
NodeType t; |
|
//MacroNode* child; |
|
MacroNode* next; |
|
//MacroNode* last; |
|
|
|
MacroNode() { |
|
t = NODE_STATLIST; |
|
next = nullptr; |
|
} |
|
|
|
virtual ~MacroNode() { |
|
//if (child) delete child; |
|
if (next) delete next; |
|
} |
|
|
|
/*void AddNode(MacroNode* node) { |
|
if (last) { |
|
last->next = node; |
|
} |
|
else |
|
child = node; |
|
last = node; |
|
}*/ |
|
}; |
|
|
|
class StatList : public MacroNode { |
|
MacroNode* last; |
|
public: |
|
MacroNode* child; |
|
|
|
StatList() { |
|
child = last = nullptr; |
|
t = NODE_STATLIST; |
|
} |
|
|
|
virtual ~StatList() { |
|
if (child) delete child; |
|
} |
|
|
|
void AddNode(MacroNode* node) { |
|
if (last) { |
|
last->next = node; |
|
} |
|
else |
|
child = node; |
|
last = node; |
|
} |
|
|
|
MacroNode* GetLast() { |
|
return last; |
|
} |
|
}; |
|
|
|
class Expression : public MacroNode { |
|
public: |
|
ExprType et; |
|
|
|
Expression() : MacroNode() { |
|
t = NODE_EXPR; |
|
et = EXPR_NONE; |
|
} |
|
|
|
virtual ~Expression() {} |
|
}; |
|
|
|
class ExprValue : public Expression { |
|
protected: |
|
Value* v; |
|
public: |
|
ExprValue() : Expression() { |
|
v = nullptr; |
|
et = EXPR_VALUE; |
|
} |
|
|
|
virtual ~ExprValue() { |
|
} |
|
|
|
const Value* Get() { |
|
return v; |
|
} |
|
|
|
void Set(Value* av) { |
|
v = av; |
|
} |
|
|
|
void Set(const Value& av) { |
|
assert(v); |
|
*v = av; |
|
} |
|
}; |
|
|
|
class ExprCall : public Expression { |
|
|
|
Expression* lastParam; |
|
|
|
public: |
|
Value* v; |
|
Expression* firstParam; |
|
|
|
ExprCall() : Expression() { |
|
v = nullptr; |
|
et = EXPR_CALL; |
|
firstParam = lastParam = nullptr; |
|
} |
|
|
|
void AddParam(Expression* p) { |
|
if (lastParam) lastParam->next = p; |
|
else firstParam = p; |
|
lastParam = p; |
|
} |
|
|
|
virtual ~ExprCall() { |
|
if (firstParam) delete firstParam;/* |
|
while (firstParam) { |
|
MacroNode* tmp = firstParam->next; |
|
delete firstParam; |
|
firstParam = (Expression*)tmp; |
|
}*/ |
|
} |
|
}; |
|
|
|
class Expr : public Expression { |
|
public: |
|
MacroNode* A; |
|
MacroNode* B; |
|
MacroNode* C; |
|
|
|
virtual ~Expr() { |
|
if (A) delete A; |
|
if (B) delete B; |
|
if (C) delete C; |
|
} |
|
|
|
Expr(ExprType type) : Expression() { |
|
et = type; |
|
A = B = C = nullptr; |
|
} |
|
|
|
Expr(ExprType type, Expression* l) : Expression() { |
|
et = type; |
|
A = l; |
|
B = nullptr; |
|
C = nullptr; |
|
} |
|
|
|
Expr(ExprType type, Expression* l, Expression* r) : Expression() { |
|
et = type; |
|
A = l; |
|
B = r; |
|
C = nullptr; |
|
} |
|
}; |
|
|
|
class FunctionDef : public StatList { |
|
public: |
|
std::string name; |
|
std::vector<Value*> params; |
|
MacroFile* mf; |
|
TDS tds; |
|
|
|
FunctionDef(MacroFile* amf) : StatList() { |
|
t = NODE_FUNCTION; |
|
mf = amf; |
|
} |
|
|
|
virtual ~FunctionDef() {} |
|
}; |
|
|
|
class MacroDef : public StatList { |
|
public: |
|
std::string name; |
|
Expression* macroInfo; |
|
Expression* menuString; |
|
Expression* menuChecked; |
|
Expression* menuGrayed; |
|
Expression* btnChecked; |
|
MacroFile* mf; |
|
|
|
MacroDef(MacroFile* amf) : StatList() { |
|
t = NODE_MACRO; |
|
macroInfo = menuString = menuChecked = menuGrayed = btnChecked = NULL; |
|
mf = amf; |
|
} |
|
|
|
virtual ~MacroDef() { |
|
if (macroInfo) delete macroInfo; |
|
if (menuString) delete menuString; |
|
if (menuChecked) delete menuChecked; |
|
if (menuGrayed) delete menuGrayed; |
|
if (btnChecked) delete btnChecked; |
|
} |
|
}; |
|
|
|
class Statement : public MacroNode { |
|
public: |
|
StatType st; |
|
MacroNode* A; |
|
MacroNode* B; |
|
MacroNode* C; |
|
|
|
|
|
Statement(StatType type) : MacroNode() { |
|
st = type; |
|
t = NODE_STAT; |
|
A = B = C = next = nullptr; |
|
} |
|
|
|
virtual int getLine() { return -1;} |
|
virtual MacroFile* getMFile() { return nullptr;} |
|
virtual const char* getFile() { return "";} |
|
|
|
virtual ~Statement() { |
|
if (A) delete A; |
|
if (B) delete B; |
|
if (C) delete C; |
|
} |
|
}; |
|
|
|
class Mac { |
|
public: |
|
TDS tds; |
|
StatList root; |
|
|
|
Value* AddSymbol(const std::string& name, const Value& v) |
|
{ |
|
TDS::iterator it; |
|
it = tds.insert(tds.end(), TDS::value_type(name, v)); |
|
return &it->second; |
|
} |
|
|
|
Value* FindSymbol(const std::string& name) |
|
{ |
|
return tds.find(name); |
|
} |
|
|
|
std::string FindSymbol(const Value* val) |
|
{ |
|
for (TDS::iterator it = tds.begin(); it != tds.end(); it++) |
|
if (val == &it->second) |
|
return it->first; |
|
return ""; |
|
} |
|
}; |
|
|
|
class MacroFile { |
|
public: |
|
std::string name; |
|
std::string desc; |
|
std::string file; |
|
std::wstring wfile; |
|
bool user; |
|
bool loaded; |
|
bool trusted; |
|
bool denied; |
|
Mac m; |
|
|
|
MacroFile(wchar_t* afile) { |
|
wfile = afile; |
|
file = CUTF16_to_UTF8(afile); |
|
|
|
CharLowerBuff(afile, wcslen(afile)); |
|
wchar_t* ext = wcsrchr(afile, L'.'); |
|
if (ext) *ext = 0; |
|
wchar_t* pos = wcsrchr(afile, L'\\'); |
|
name = (const char*)CT_to_UTF8(pos ? pos + 1 : afile); |
|
*ext = L'.'; |
|
|
|
user = false; |
|
loaded = false; |
|
trusted = false; |
|
denied = false; |
|
} |
|
}; |
|
|
|
class DebugStatement : public Statement { |
|
int mLine; |
|
MacroFile* mMf; |
|
public: |
|
DebugStatement(StatType type, MacroFile* mf, int line) : Statement(type) { |
|
mLine = line; |
|
mMf = mf; |
|
} |
|
|
|
virtual int getLine() { return mLine;} |
|
virtual MacroFile* getMFile() { return mMf;} |
|
virtual const char* getFile() { return mMf->file.c_str();} |
|
}; |
|
|
|
|
|
/* |
|
class ValueDef : MacroNode { |
|
Value* v; |
|
|
|
ValueDef() : MacroNode(Value *v) { |
|
t = NODE_VALUE; |
|
} |
|
}; |
|
*/ |
|
|
|
/* |
|
typedef struct MacroDef { |
|
Program code; |
|
int nbparam; |
|
} MacroDef; |
|
*/ |