#include "stdlib.h" #include "string.h" #include "condition.h" short aa = 4, cc = 8; char bb = 5, dd = 10; identifier testList[4] = { {"PC", &aa, 16}, {"X", &bb, 8}, {"YA", &cc, 16}, {"KON", &dd, 8} }; long sizeMasks[33] = { 0, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, }; // **************************************************** static int eval_integer(const char *&s) { if(!*s) throw "nall::bad_eval_integer"; int value = 0, x = *s, y = *(s + 1); //hexadecimal if(x == '0' && (y == 'X' || y == 'x')) { s += 2; for(;;) { if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } return value; } } //binary if(x == '0' && (y == 'B' || y == 'b')) { s += 2; for(;;) { if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } return value; } } //octal (or decimal '0') if(x == '0') { s += 1; for(;;) { if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } return value; } } //decimal if(x >= '0' && x <= '9') { for(;;) { if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } return value; } } throw "nall::bad_eval_integer"; } // **************************************************** long EvaluateTree(condition* c) { long ret = 0; switch(c->type) { case TYPE_EXPRESSION: switch(c->op) { case OP_UNARY_LOGICAL_NOT: ret = !EvaluateTree(c->rightSide); break; case OP_UNARY_BITWISE_NOT: ret = ~EvaluateTree(c->rightSide); break; case OP_UNARY_PLUS: ret = EvaluateTree(c->rightSide); break; case OP_UNARY_NEGATIVE: ret = EvaluateTree(c->rightSide); break; case OP_MULTIPLY: ret = EvaluateTree(c->leftSide) * EvaluateTree(c->rightSide); break; case OP_DIVIDE: ret = EvaluateTree(c->leftSide) / EvaluateTree(c->rightSide); break; case OP_MODULUS: ret = EvaluateTree(c->leftSide) % EvaluateTree(c->rightSide); break; case OP_ADDITION: ret = EvaluateTree(c->leftSide) + EvaluateTree(c->rightSide); break; case OP_SUBTRACTION: ret = EvaluateTree(c->leftSide) - EvaluateTree(c->rightSide); break; case OP_SHIFT_LEFT: ret = EvaluateTree(c->leftSide) << EvaluateTree(c->rightSide); break; case OP_SHIFT_RIGHT: ret = EvaluateTree(c->leftSide) >> EvaluateTree(c->rightSide); break; case OP_LESS_THAN: ret = EvaluateTree(c->leftSide) < EvaluateTree(c->rightSide); break; case OP_GREATER_THAN: ret = EvaluateTree(c->leftSide) > EvaluateTree(c->rightSide); break; case OP_LESS_THAN_OR_EQUAL: ret = EvaluateTree(c->leftSide) <= EvaluateTree(c->rightSide); break; case OP_GREATER_THAN_OR_EQUAL: ret = EvaluateTree(c->leftSide) >= EvaluateTree(c->rightSide); break; case OP_EQUAL: ret = EvaluateTree(c->leftSide) == EvaluateTree(c->rightSide); break; case OP_NOT_EQUAL: ret = EvaluateTree(c->leftSide) != EvaluateTree(c->rightSide); break; case OP_BITWISE_AND: ret = EvaluateTree(c->leftSide) & EvaluateTree(c->rightSide); break; case OP_BITWISE_XOR: ret = EvaluateTree(c->leftSide) ^ EvaluateTree(c->rightSide); break; case OP_BITWISE_OR: ret = EvaluateTree(c->leftSide) | EvaluateTree(c->rightSide); break; case OP_LOGICAL_AND: ret = EvaluateTree(c->leftSide) && EvaluateTree(c->rightSide); break; case OP_LOGICAL_XOR: { long lhs = EvaluateTree(c->leftSide); long rhs = EvaluateTree(c->rightSide); ret = (lhs && !rhs) || (!lhs && rhs); break; } case OP_LOGICAL_OR: ret = EvaluateTree(c->leftSide) || EvaluateTree(c->rightSide); break; case OP_TERNARY: { condition *d = c->rightSide; if(d->op != OP_TERNARY_SEPARATOR) throw "nall::bad_ternary_exception"; ret = EvaluateTree(c->leftSide) ? EvaluateTree(d->leftSide) : EvaluateTree(d->rightSide); break; } default: break; } break; case TYPE_NUMBER: return c->value; break; case TYPE_POINTER: return *((unsigned long*) c->id->pointer) & sizeMasks[c->id->size]; break; case TYPE_NONE: throw "nall::error_in_eval"; break; } return ret; } // **************************************************** identifier* MatchToken(identifier *list, unsigned int listSize, const char *&s) { int i = 0, n = 0; for(i = 0; i < listSize; i++) { n = strlen(list[i].token); if(strncmp(list[i].token, s, n) == 0) { s += n; return &list[i]; } } return NULL; } // **************************************************** condition* CreateCondition(void) { condition* c = (condition*) malloc(sizeof(condition)); if(c) { c->parent = NULL; c->leftSide = NULL; c->rightSide = NULL; c->op = parseOperator::OP_NONE; c->type = parseType::TYPE_NONE; c->value = 0; } return c; } // ---------------------------------------------------- condition* CreateCondition(condition* parent, parseSide side) { condition *c = CreateCondition(); if(c && parent) { c->parent = parent; if(side == SIDE_LEFT) parent->leftSide = c; else parent->rightSide = c; } return c; } // **************************************************** condition* InsertNode(condition *c) { condition* p = c->parent; condition* p2 = NULL; if(p) { if(c == p->leftSide) p2 = CreateCondition(p, SIDE_LEFT); else if(c == p->rightSide) p2 = CreateCondition(p, SIDE_RIGHT); else throw "condition::bad parent"; p2->leftSide = c; p2->rightSide = CreateCondition(p2, SIDE_RIGHT); c->parent = p2; } return p2; } // **************************************************** condition* Unary_Operator(const char *&s, condition *c, parseOperator o, int depth) { c->type = parseType::TYPE_EXPRESSION; c->op = o; return CreateBranch(s, c->rightSide, depth); } // **************************************************** condition* Arithmetic_Operator(const char *&s, condition* c, parseOperator o, int depth) { condition *p2 = InsertNode(c); p2->type = TYPE_EXPRESSION; p2->op = o; CreateBranch(s, p2->rightSide, depth); return p2; } // **************************************************** static condition* CreateBranch(const char *&s, condition* c, int depth, bool allocate) { condition *p2 = NULL; if(!c) throw "nall::bad_alloc"; if(!c->leftSide) c->leftSide = CreateCondition(c, SIDE_LEFT); if(!c->rightSide) c->rightSide = CreateCondition(c, SIDE_RIGHT); while(*s == ' ' || *s == '\t') s++; //trim whitespace if(!*s) throw "nall::bad_eval"; int value = 0, x = *s, y = *(s + 1); if(*s == '(') { c = CreateBranch(++s, c, 1); if(*s++ != ')') throw "nall::bad_eval"; } else if(x == '!'){ Unary_Operator(++s, c, OP_UNARY_LOGICAL_NOT, 14); } else if(x == '~'){ Unary_Operator(++s, c, OP_UNARY_BITWISE_NOT, 14); } else if(x == '+'){ Unary_Operator(++s, c, OP_UNARY_PLUS, 14); } else if(x == '-'){ Unary_Operator(++s, c, OP_UNARY_NEGATIVE, 14); } else if(x >= '0' && x <= '9') { c->type = TYPE_NUMBER; c->value = eval_integer(s); } else if(c->id = MatchToken(testList, 4, s)) c->type = TYPE_POINTER; else throw "nall::bad_eval"; for(;;) { while(*s == ' ' || *s == '\t') s++; //trim whitespace if(!*s) break; x = *s, y = *(s + 1); if(depth >= 13) break; if(x == '*'){ c = Arithmetic_Operator(++s, c, OP_MULTIPLY, 13); continue; } if(x == '/'){ c = Arithmetic_Operator(++s, c, OP_DIVIDE, 13); continue; } if(x == '%'){ c = Arithmetic_Operator(++s, c, OP_MODULUS, 13); continue; } if(depth >= 12) break; if(x == '+'){ c = Arithmetic_Operator(++s, c, OP_ADDITION, 12); continue; } if(x == '-'){ c = Arithmetic_Operator(++s, c, OP_SUBTRACTION, 12); continue; } if(depth >= 11) break; if(x == '<' && y == '<'){ c = Arithmetic_Operator(++++s, c, OP_SHIFT_LEFT, 11); continue; } if(x == '>' && y == '>'){ c = Arithmetic_Operator(++++s, c, OP_SHIFT_RIGHT, 11); continue; } if(depth >= 10) break; if(x == '<' && y == '='){ c = Arithmetic_Operator(++++s, c, OP_LESS_THAN_OR_EQUAL, 10); continue; } if(x == '>' && y == '='){ c = Arithmetic_Operator(++++s, c, OP_GREATER_THAN_OR_EQUAL, 10); continue; } if(x == '<'){ c = Arithmetic_Operator(++s, c, OP_LESS_THAN, 10); continue; } if(x == '>'){ c = Arithmetic_Operator(++s, c, OP_GREATER_THAN, 10); continue; } if(depth >= 9) break; if(x == '=' && y == '='){ c = Arithmetic_Operator(++++s, c, OP_EQUAL, 9); continue; } if(x == '!' && y == '='){ c = Arithmetic_Operator(++++s, c, OP_NOT_EQUAL, 9); continue; } if(depth >= 8) break; if(x == '&' && y != '&'){ c = Arithmetic_Operator(++s, c, OP_BITWISE_AND, 8); continue; } if(depth >= 7) break; if(x == '^' && y != '^'){ c = Arithmetic_Operator(++s, c, OP_BITWISE_XOR, 7); continue; } if(depth >= 6) break; if(x == '|' && y != '|'){ c = Arithmetic_Operator(++s, c, OP_BITWISE_OR, 6); continue; } if(depth >= 5) break; if(x == '&' && y == '&'){ c = Arithmetic_Operator(++++s, c, OP_LOGICAL_AND, 5); continue; } if(depth >= 4) break; if(x == '^' && y == '^'){ c = Arithmetic_Operator(++++s, c, OP_LOGICAL_XOR, 4); continue; } if(depth >= 3) break; if(x == '|' && y == '|'){ c = Arithmetic_Operator(++++s, c, OP_LOGICAL_OR, 3); continue; } if(x == '?') { condition *top = NULL; p2 = Arithmetic_Operator(++s, c, OP_TERNARY, 2); top = p2; if(*s != ':') throw "nall::bad_eval"; p2 = Arithmetic_Operator(++s, p2->rightSide, OP_TERNARY_SEPARATOR, 2); c = top; continue; } if(depth >= 2) break; if(depth > 0 && x == ')') break; throw "nall::bad_eval"; } return c; } // **************************************************** // Tree was created recursively, now delete it recursively long DeleteTree(condition *c) { long numDeallocs = 0; if(c) { if(c->leftSide) numDeallocs += DeleteTree(c->leftSide); if(c->rightSide) numDeallocs += DeleteTree(c->rightSide); free(c); numDeallocs += 1; } return numDeallocs; } // **************************************************** condition* CreateTree(const char *s, int &result) { condition *root = CreateCondition(); condition *c = CreateCondition(root, SIDE_LEFT); try { CreateBranch(s, c); return root->leftSide; } catch(const char*) { result = 0; return false; } } // ****************************************************