diff --git a/nemu/src/monitor/sdb/expr.c b/nemu/src/monitor/sdb/expr.c index 6555d65..9adb8b9 100644 --- a/nemu/src/monitor/sdb/expr.c +++ b/nemu/src/monitor/sdb/expr.c @@ -20,15 +20,21 @@ */ #include +#include #include enum { - TK_NOTYPE = 256, TK_EQ, - TK_DEC, + TK_NOTYPE = 256, + TK_EQ, + TK_NEQ, + TK_AND, + TK_NEG, - - /* TODO: Add more token types */ - + TK_DEC, + + TK_HEX, + TK_REG, + TK_DEREF, }; static struct rule { @@ -36,13 +42,11 @@ static struct rule { int token_type; } rules[] = { - /* TODO: Add more rules. - * Pay attention to the precedence level of different rules. - */ - {" +", TK_NOTYPE}, // spaces {"\\+", '+'}, // plus {"==", TK_EQ}, // equal + {"!=", TK_NEQ}, // not equal + {"&&", TK_AND}, // and {"-", '-'}, // sub {"\\*", '*'}, // mul @@ -50,6 +54,9 @@ static struct rule { {"\\(", '('}, // ( {"\\)", ')'}, // ) {"[0-9]+", TK_DEC}, // dec number + + {"0x[0-9a-fA-F]+", TK_HEX}, // hex number + {"$[0-9a-z]+", TK_REG}, // register }; #define NR_REGEX ARRLEN(rules) @@ -113,9 +120,14 @@ static bool make_token(char *e) { case '/': case '(': case ')': + case TK_EQ: + case TK_NEQ: + case TK_AND: nr_token ++; break; case TK_DEC: + case TK_HEX: + case TK_REG: if (substr_len + 1 > sizeof(((Token*)0)->str)) { printf("token string is too long"); return false; @@ -124,7 +136,6 @@ static bool make_token(char *e) { tokens[nr_token].str[substr_len] = '\0'; nr_token ++; break; - case TK_EQ: case TK_NOTYPE: break; default: TODO(); @@ -164,10 +175,14 @@ int check_parentheses(const Token* arr, size_t p, size_t q) { int get_level(int type) { switch (type) { + case TK_AND: return 1; + case TK_EQ: + case TK_NEQ: return 2; case '+': - case '-': return 1; + case '-': return 4; case '*': - case '/': return 2; + case '/': return 5; + case TK_DEREF: return 7; case TK_NEG: return 8; case '(': return 9; default: return INT_MAX; @@ -196,7 +211,15 @@ uint32_t eval(const Token* arr, int p, int q, bool* success) { * For now this token should be a number. * Return the value of the number. */ - return atoi(arr[q].str); + switch (arr[p].type) + { + case TK_DEC: return atoi(arr[q].str); + case TK_HEX: return strtol(arr[q].str, NULL, 16); + case TK_REG: return isa_reg_str2val(arr[q].str, success); + default: + *success = false; + break; + } } /* We should do more things here. */ int op = 0; @@ -220,6 +243,9 @@ uint32_t eval(const Token* arr, int p, int q, bool* success) { if (type == TK_NEG && type_level == op_type_level) { continue; } + if (type == TK_DEREF && type_level == op_type_level) { + continue; + } op = i; op_type_level = type_level; } @@ -236,6 +262,10 @@ uint32_t eval(const Token* arr, int p, int q, bool* success) { switch (arr[op].type) { case TK_NEG: return - val_r; + case TK_DEREF: return vaddr_read(val_r, sizeof(word_t)); + case TK_EQ: return val_l == val_r; + case TK_NEQ: return val_l != val_r; + case TK_AND: return val_l && val_r; case '+': return val_l + val_r; case '-': return val_l - val_r; case '*': return val_l * val_r; @@ -244,25 +274,30 @@ uint32_t eval(const Token* arr, int p, int q, bool* success) { } } +static inline bool prev_not_number(int i) { + return (i == 0 || \ + tokens[i-1].type == '(' || \ + tokens[i-1].type == '+' || \ + tokens[i-1].type == '-' || \ + tokens[i-1].type == '*' || \ + tokens[i-1].type == '/' || \ + tokens[i-1].type == TK_NEG || \ + tokens[i-1].type == TK_DEREF); +} + word_t expr(char *e, bool *success) { if (!make_token(e)) { *success = false; return 0; } - /* TODO: Insert codes to evaluate the expression. */ - // TODO(); *success = true; for (int i = 0; i < nr_token; i ++) { int type = tokens[i].type; - if (type == '-' && (i == 0 || \ - tokens[i-1].type == '(' || \ - tokens[i-1].type == '+' || \ - tokens[i-1].type == '-' || \ - tokens[i-1].type == '*' || \ - tokens[i-1].type == '/' || \ - tokens[i-1].type == TK_NEG)) { + if (type == '-' && prev_not_number(i)) { tokens[i].type = TK_NEG; + } else if (type == '*' && prev_not_number(i)) { + tokens[i].type = TK_DEREF; } } return eval(tokens, 0, nr_token - 1, success); diff --git a/nemu/src/monitor/sdb/sdb.c b/nemu/src/monitor/sdb/sdb.c index 01f6267..62d607c 100644 --- a/nemu/src/monitor/sdb/sdb.c +++ b/nemu/src/monitor/sdb/sdb.c @@ -17,9 +17,10 @@ #include #include #include -#include #include "sdb.h" +#include + static int is_batch_mode = false; void init_regex(); diff --git a/nemu/tools/gen-expr/gen-expr.c b/nemu/tools/gen-expr/gen-expr.c index 9234f1c..d4b6e7e 100644 --- a/nemu/tools/gen-expr/gen-expr.c +++ b/nemu/tools/gen-expr/gen-expr.c @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) { fputs(code_buf, fp); fclose(fp); - int ret = system("gcc /tmp/.code.c -o /tmp/.expr"); + int ret = system("gcc /tmp/.code.c -o /tmp/.expr -Wall -Werror"); if (ret != 0) { printf("failed to execute gcc\n"); i ++;