/* * Recursive-descent parser. Called with a single boolean operand, * which is TRUE if the evaluation is critical (i.e. unresolved * symbols are an error condition). Must update the global `i' to * reflect the token after the parsed string. May return NULL. * * evaluate() should report its own errors: on return it is assumed * that if NULL has been returned, the error has already been * reported. */ /* * Grammar parsed is: * * expr : bexpr [ WRT expr6 ] * bexpr : rexp0 or expr0 depending on relative-mode setting * rexp0 : rexp1 [ {||} rexp1...] * rexp1 : rexp2 [ {^^} rexp2...] * rexp2 : rexp3 [ {&&} rexp3...] * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ] * expr0 : expr1 [ {|} expr1...] * expr1 : expr2 [ {^} expr2...] * expr2 : expr3 [ {&} expr3...] * expr3 : expr4 [ {<<,>>} expr4...] * expr4 : expr5 [ {+,-} expr5...] * expr5 : expr6 [ {*,/,%,//,%%} expr6...] * expr6 : { ~,+,-,SEG } expr6 * | (bexpr) * | symbol * | $ * | number */
static expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int); static expr *expr0(int), *expr1(int), *expr2(int), *expr3(int); static expr *expr4(int), *expr5(int), *expr6(int); static expr *(*bexpr) (int);
/* || 运算法 */ static expr *rexp0(int critical) { expr *e, *f;
e = rexp1(critical); if (!e) return NULL;
while (i == TOKEN_DBL_OR) { i = scan(scpriv, tokval); f = rexp1(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`|' operator may only be applied to scalar values"); }
if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect((long)(reloc_value(e) || reloc_value(f))); } return e; }
/* ^^ 运算法 */ static expr *rexp1(int critical) { expr *e, *f;
e = rexp2(critical); if (!e) return NULL;
while (i == TOKEN_DBL_XOR) { i = scan(scpriv, tokval); f = rexp2(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`^' operator may only be applied to scalar values"); }
if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect((long)(!reloc_value(e) ^ !reloc_value(f))); } return e; }
/* && 运算符 */ static expr *rexp2(int critical) { expr *e, *f;
e = rexp3(critical); if (!e) return NULL;
while (i == TOKEN_DBL_AND) { i = scan(scpriv, tokval); f = rexp3(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`&' operator may only be applied to scalar values"); } if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect((long)(reloc_value(e) && reloc_value(f))); } return e; }
/* 比较 运算法 */ static expr *rexp3(int critical) { expr *e, *f; long v;
e = expr0(critical); if (!e) return NULL;
while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT || i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) { int j = i; i = scan(scpriv, tokval); f = expr0(critical); if (!f) return NULL;
e = add_vectors(e, scalar_mult(f, -1L, FALSE));
switch (j) { case TOKEN_EQ: case TOKEN_NE: if (is_unknown(e)) v = -1; /* means unknown */ else if (!is_really_simple(e) || reloc_value(e) != 0) v = (j == TOKEN_NE); /* unequal, so return TRUE if NE */ else v = (j == TOKEN_EQ); /* equal, so return TRUE if EQ */ break; default: if (is_unknown(e)) v = -1; /* means unknown */ else if (!is_really_simple(e)) { error(ERR_NONFATAL, "`%s': operands differ by a non-scalar", (j == TOKEN_LE ? "<=" : j == TOKEN_LT ? "<" : j == TOKEN_GE ? ">=" : ">")); v = 0; /* must set it to _something_ */ } else { int vv = reloc_value(e); if (vv == 0) v = (j == TOKEN_LE || j == TOKEN_GE); else if (vv > 0) v = (j == TOKEN_GE || j == TOKEN_GT); else /* vv < 0 */ v = (j == TOKEN_LE || j == TOKEN_LT); } break; }
if (v == -1) e = unknown_expr(); else e = scalarvect(v); } return e; }
/* 处理 | 操作符 */ static expr *expr0(int critical) { expr *e, *f; e = expr1(critical); if (!e) return NULL;
while (i == '|') { i = scan(scpriv, tokval); f = expr1(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`|' operator may only be applied to" " scalar values"); } if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(reloc_value(e) | reloc_value(f)); } return e; }
/* 处理 ^ 操作符 */ static expr *expr1(int critical) { expr *e, *f;
e = expr2(critical); if (!e) return NULL;
while (i == '^') { i = scan(scpriv, tokval); f = expr2(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`^' operator may only be applied to" " scalar values"); } if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(reloc_value(e) ^ reloc_value(f)); } return e; }
/* 处理 & 操作符 */ static expr *expr2(int critical) { expr *e, *f;
e = expr3(critical);
if (!e) return NULL;
while (i == '&') { i = scan(scpriv, tokval); f = expr3(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "`&' operator may only be applied to" " scalar values"); } if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(reloc_value(e) & reloc_value(f)); } return e; }
/* 移位操作符 */ static expr *expr3(int critical) { expr *e, *f;
e = expr4(critical); if (!e) return NULL;
while (i == TOKEN_SHL || i == TOKEN_SHR) { int j = i;
i = scan(scpriv, tokval); f = expr4(critical); if (!f) return NULL; if (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f))) { error(ERR_NONFATAL, "shift operator may only be applied to scalar values"); } else if (is_just_unknown(e) || is_just_unknown(f)) { e = unknown_expr(); } else switch (j) { case TOKEN_SHL: e = scalarvect(reloc_value(e) << reloc_value(f)); break; case TOKEN_SHR: e = scalarvect(((unsigned long)reloc_value(e)) >> reloc_value(f)); break; } } return e; }
/* 加法,减法 二元运算符 */ static expr *expr4(int critical) { expr *e, *f;
e = expr5(critical);
if (!e) return NULL;
while (i == '+' || i == '-') { int j = i; i = scan(scpriv, tokval); f = expr5(critical); if (!f) return NULL; switch (j) { case '+': e = add_vectors(e, f); break; case '-': e = add_vectors(e, scalar_mult(f, -1L, FALSE)); break; } } return e; }
/* 处理 乘法,除法,模 二元运算符 */ static expr *expr5(int critical) { expr *e, *f;
e = expr6(critical); if (!e) return NULL;
/* 二元操作符 */ while (i == '*' || i == '/' || i == '%' || i == TOKEN_SDIV || i == TOKEN_SMOD) { int j = i; i = scan(scpriv, tokval); f = expr6(critical); if (!f) return NULL; if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) || !(is_simple(f) || is_just_unknown(f)))) { error(ERR_NONFATAL, "division operator may only be applied to scalar values"); return NULL; }
/* 除数不能为0 */ if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) { error(ERR_NONFATAL, "division by zero"); return NULL; } switch (j) { case '*': if (is_simple(e)) e = scalar_mult(f, reloc_value(e), TRUE); else if (is_simple(f)) e = scalar_mult(e, reloc_value(f), TRUE); else if (is_just_unknown(e) && is_just_unknown(f)) e = unknown_expr(); else { error(ERR_NONFATAL, "unable to multiply two non-scalar objects"); return NULL; } break; case '/': if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(((unsigned long)reloc_value(e)) / ((unsigned long)reloc_value(f))); break; case '%': if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(((unsigned long)reloc_value(e)) % ((unsigned long)reloc_value(f))); break; case TOKEN_SDIV: if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(((signed long)reloc_value(e)) / ((signed long)reloc_value(f))); break; case TOKEN_SMOD: if (is_just_unknown(e) || is_just_unknown(f)) e = unknown_expr(); else e = scalarvect(((signed long)reloc_value(e)) % ((signed long)reloc_value(f))); break; } } return e; }
/* * 将 token 转化成计算器能够识别的 expr 类型 */ static expr *expr6(int critical) { long type; expr *e; long label_seg, label_ofs;
/* 处理一元运算法和括号 */ if (i == '-') { i = scan(scpriv, tokval); e = expr6(critical); if (!e) return NULL; return scalar_mult(e, -1L, FALSE); /* - negates its operand */ } else if (i == '+') { i = scan(scpriv, tokval); return expr6(critical); /* do nothing */ } else if (i == '~') { i = scan(scpriv, tokval); e = expr6(critical); if (!e) return NULL; if (is_just_unknown(e)) return unknown_expr(); else if (!is_simple(e)) { error(ERR_NONFATAL, "`~' operator may only be applied to scalar values"); return NULL; } return scalarvect(~reloc_value(e)); } else if (i == TOKEN_SEG) { /* 段寄存器 */ i = scan(scpriv, tokval); e = expr6(critical); if (!e) return NULL; e = segment_part(e); if (!e) return NULL; if (is_unknown(e) && critical) { error(ERR_NONFATAL, "unable to determine segment base"); return NULL; } return e; } else if (i == '(') { /* (XXX) */ i = scan(scpriv, tokval); e = bexpr(critical); if (!e) return NULL; if (i != ')') { error(ERR_NONFATAL, "expecting `)'"); return NULL; } i = scan(scpriv, tokval); return e; } else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID || i == TOKEN_HERE || i == TOKEN_BASE) {
begintemp(); switch (i) { case TOKEN_NUM: /* 常数 */ addtotemp(EXPR_SIMPLE, tokval->t_integer); break; case TOKEN_REG: /* 通用寄存器 */ addtotemp(tokval->t_integer, 1L); if (hint && hint->type == EAH_NOHINT) hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE; break; case TOKEN_ID: case TOKEN_HERE: case TOKEN_BASE: /* * If !location->known, this indicates that no * symbol, Here or Base references are valid because we * are in preprocess-only mode. */ if (!location->known) { error(ERR_NONFATAL, "%s not supported in preprocess-only mode", (i == TOKEN_ID ? "symbol references" : i == TOKEN_HERE ? "$'" : "$$'")); addtotemp(EXPR_UNKNOWN, 1L); break; }
type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */ if (i == TOKEN_BASE) /* $ */ { label_seg = in_abs_seg ? abs_seg : location->segment; label_ofs = 0; } else if (i == TOKEN_HERE) /* $ */ { label_seg = in_abs_seg ? abs_seg : location->segment; label_ofs = in_abs_seg ? abs_offset : location->offset; } else { if (!labelfunc(tokval->t_charptr, &label_seg, &label_ofs)) { if (critical == 2) { error(ERR_NONFATAL, "symbol `%s' undefined", tokval->t_charptr); return NULL; } else if (critical == 1) { error(ERR_NONFATAL, "symbol `%s' not defined before use", tokval->t_charptr); return NULL; } else { //#define OPFLAG_FORWARD 1 /* operand is a forward reference */ //#define OPFLAG_EXTERN 2 /* operand is an external reference */ if (opflags) *opflags |= 1; type = EXPR_UNKNOWN; label_seg = NO_SEG; label_ofs = 1; } } if (opflags && is_extern(tokval->t_charptr)) *opflags |= OPFLAG_EXTERN; } addtotemp(type, label_ofs); if (label_seg != NO_SEG) addtotemp(EXPR_SEGBASE + label_seg, 1L); break; } i = scan(scpriv, tokval); return finishtemp(); } else { error(ERR_NONFATAL, "expression syntax error"); return NULL; } }
|