📄 expr2.c
字号:
*t1 = pop_token(c);}__inline static void pop_2_floats (expr_info *c, double *a, double *b){ *b = pop_float(c); *a = pop_float(c);}__inline static void pop_2_integers (expr_info *c, INTTYPE *a, INTTYPE *b){ *b = pop_integer(c); *a = pop_integer(c);}__inline static void pop_2_strings (expr_info *c, const char **s, const char **t){ *t = pop_expanded(c); *s = pop_expanded(c);}__inline static void pop_2_booleans (expr_info *c, BooL *a, BooL *b){ *b = pop_boolean(c); *a = pop_boolean(c);}__inline static void pop_3_tokens (expr_info *c, BooL *a, TOKEN *v, TOKEN *w){ TOKEN t1, t2, t3; t3 = pop_token(c); t2 = pop_token(c); t1 = pop_token(c); *a = get_token_boolean(c, t1); *v = t2; *w = t3;}/******************************* OPERATOR REDUCER **************************//* * This is the reducer. It takes the relevant arguments off the argument * stack and then performs the neccesary operation on them. */static void reduce (expr_info *cx, int what){ double a, b; BooL c, d; INTTYPE i, j; const char *s, *t; TOKEN v, w; if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("Reducing last operation..."); if (cx->sp < 0) { error("An operator is missing a required operand"); return; } if (cx->errflag) return; /* Dont parse on an error *//* Check to see if we are evaluating the expression at this point. */#define CHECK_NOEVAL \ if (cx->noeval) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: Operation short-circuited"); \ push_token(cx, 0); \ break; \ }/* Perform an ordinary garden variety floating point binary operation. */#define BINARY_FLOAT(floatop) \ { \ pop_2_floats(cx, &a, &b); \ CHECK_NOEVAL \ push_float(cx, (floatop)); \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (%f %f) -> %f", \ #floatop, a, b, floatop); \ break; \ }/* Perform an ordinary garden variety integer binary operation */#define BINARY_INTEGER(intop) \ { \ pop_2_integers(cx, &i, &j); \ CHECK_NOEVAL \ push_integer(cx, (intop)); \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (" FORMAT " " FORMAT ") -> " FORMAT, \ #intop, i, j, intop); \ break; \ }/* Perform an ordinary garden variety boolean binary operation */#define BINARY_BOOLEAN(boolop) \ { \ pop_2_booleans(cx, &c, &d); \ CHECK_NOEVAL \ push_boolean(cx, (boolop)); \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (%d %d) -> %d", \ #boolop, c, d, boolop); \ break; \ }/* Perform a floating point binary operation where the rhs must not be 0. */#define BINARY_FLOAT_NOZERO(floatop) \ { \ pop_2_floats(cx, &a, &b); \ CHECK_NOEVAL \ if (b == 0.0) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (%f %f) -> []", \ #floatop, a, b); \ error("Division by zero"); \ push_token(cx, 0); \ } \ else \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (%f %f) -> %f", \ #floatop, a, b, floatop); \ push_float(cx, (floatop)); \ } \ break; \ }/* Perform a floating point binary operation where the rhs must not be 0. */#define BINARY_INTEGER_NOZERO(intop) \ { \ pop_2_integers(cx, &i, &j); \ CHECK_NOEVAL \ if (j == 0) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (" FORMAT " " FORMAT ") -> []", \ #intop, i, j); \ error("Division by zero"); \ push_token(cx, 0); \ } \ else \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (" FORMAT " " FORMAT ") -> " FORMAT, \ #intop, i, j, intop); \ push_integer(cx, (intop)); \ } \ break; \ }/***************** ASSIGNMENT MACROS *******************//* Prep the lvalue and the rvalue for a future assignment. */#define GET_LVAL_RVAL \ pop_2_tokens(cx, &v, &w); \ if (!(s = get_token_lval(cx, v))) \ { \ push_token(cx, 0); \ break; \ }/* Perform an ordinary integer operation, assigning the result to the lvalue */#define IMPLIED_INTEGER(intop) \ { \ GET_LVAL_RVAL \ CHECK_NOEVAL \ i = get_token_integer(cx, v); \ j = get_token_integer(cx, w); \ \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (" FORMAT " " FORMAT ") -> " FORMAT, \ s, #intop, i, j, intop); \ \ w = tokenize_integer(cx, (intop)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ push_token(cx, w); \ break; \ }/* Perform an ordinary float operation, assigning the result to the lvalue */#define IMPLIED_FLOAT(floatop) \ { \ GET_LVAL_RVAL \ CHECK_NOEVAL \ a = get_token_float(cx, v); \ b = get_token_float(cx, w); \ \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (%f %f) -> %f", \ s, #floatop, a, b, floatop); \ \ w = tokenize_float(cx, (floatop)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ push_token(cx, w); \ break; \ }/* Perform an ordinary boolean operation, assigning the result to the lvalue */#define IMPLIED_BOOLEAN(boolop) \ { \ GET_LVAL_RVAL \ CHECK_NOEVAL \ c = get_token_boolean(cx, v); \ d = get_token_boolean(cx, w); \ \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (%d %d) -> %d", \ s, #boolop, c, d, boolop); \ \ w = tokenize_bool(cx, (boolop)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ push_token(cx, w); \ break; \ }/* * Perform a float operation, rvalue must not be zero, assigning the result * to the lvalue. */#define IMPLIED_FLOAT_NOZERO(floatop) \ { \ GET_LVAL_RVAL \ CHECK_NOEVAL \ a = get_token_float(cx, v); \ b = get_token_float(cx, w); \ \ if (b == 0.0) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (%f %f) -> 0", \ s, #floatop, a, b); \ error("Division by zero"); \ add_var_alias(s, empty_string, 0); \ push_token(cx, 0); \ break; \ } \ \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (%f %f) -> %f", \ s, #floatop, a, b, floatop); \ \ w = tokenize_float(cx, (floatop)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ push_token(cx, w); \ break; \ }/* * Perform a float operation, rvalue must not be zero, assigning the result * to the lvalue. */#define IMPLIED_INTEGER_NOZERO(intop) \ { \ GET_LVAL_RVAL \ CHECK_NOEVAL \ i = get_token_float(cx, v); \ j = get_token_float(cx, w); \ \ if (j == 0) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (" FORMAT " " FORMAT ") -> 0",\ s, #intop, i, j); \ error("Division by zero"); \ add_var_alias(s, empty_string, 0); \ push_token(cx, 0); \ break; \ } \ \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s = %s (" FORMAT " " FORMAT ") -> " FORMAT,\ s, #intop, i, j, intop); \ \ w = tokenize_float(cx, (intop)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ push_token(cx, w); \ break; \ }/* * Perform an auto(in|de)crement operation on the last operand, assigning * to it the value of 'x', but pushing the value of 'y' onto the stack. */#define AUTO_UNARY(intop_assign, intop_result) \ { \ v = pop_token(cx); \ if (!(s = get_token_lval(cx, v))) \ { \ push_token(cx, 0); \ break; \ } \ CHECK_NOEVAL \ \ j = get_token_integer(cx, v); \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s (%s " FORMAT ") -> " FORMAT, \ #intop_result, s, j, (intop_result)); \ \ w = tokenize_integer(cx, (intop_assign)); \ t = get_token_expanded(cx, w); \ add_var_alias(s, t, 0); \ \ push_integer(cx, (intop_result)); \ break; \ }/* ****************** START HERE *********************/#define dpushn(x1,x2,y1) \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ { \ yell("O: COMPARE"); \ yell("O: %s -> %d", #x2, (x2)); \ } \ push_boolean( x1 , y1 ); \ } #define COMPARE(x, y) \ { \ pop_2_strings(cx, &s, &t); \ CHECK_NOEVAL \ if (is_real_number(s) && is_real_number(t)) \ { \ a = atof(s), b = atof(t); \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s N(%f %f) -> %d", #x, a, b, (x)); \ if ((x)) dpushn(cx, x, 1) \ else dpushn(cx, x, 0) \ } \ else \ { \ if (x_debug & DEBUG_NEW_MATH_DEBUG) \ yell("O: %s S(%s %s) -> %d", #x, s, t, (y)); \ if ((y)) dpushn(cx, y, 1) \ else dpushn(cx, y, 0) \ } \ break; \ } /************** THE OPERATORS THEMSELVES ********************/ switch (what) { /* Simple unary prefix operators */ case NOT: c = pop_boolean(cx); CHECK_NOEVAL if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: !%d -> %d", c, !c); push_boolean(cx, !c); break; case COMP: i = pop_integer(cx); CHECK_NOEVAL if (x_debug & DEBUG_NEW_MATH_DEBUG) yell(": ~" FORMAT " -> " FORMAT, i, ~i); push_integer(cx, ~i); break; case UPLUS: a = pop_float(cx); CHECK_NOEVAL if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: +%f -> %f", a, a); push_float(cx, a); break; case UMINUS: a = pop_float(cx); CHECK_NOEVAL if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: -%f -> %f", a, -a); push_float(cx, -a); break; case STRLEN: s = pop_expanded(cx); CHECK_NOEVAL i = strlen(s); if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: @(%s) -> " FORMAT, s, i); push_integer(cx, i); break; case WORDC: s = pop_expanded(cx); CHECK_NOEVAL i = count_words(s, DWORD_YES, "\""); if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: #(%s) -> " FORMAT, s, i); push_integer(cx, i); break; case DEREF: { if (top(cx) == MAGIC_TOKEN) break; /* Dont do anything */ /* * We need to consume the operand, even if * we don't intend to use it; plus we need * to ensure this defeats auto-append. Ick. */ s = pop_expanded(cx); *cx->args_flag = 1; CHECK_NOEVAL push_lval(cx, s); break; } /* (pre|post)(in|de)crement operators. */ case PREPLUS: AUTO_UNARY(j + 1, j + 1) case PREMINUS: AUTO_UNARY(j - 1, j - 1) case POSTPLUS: AUTO_UNARY(j + 1, j) case POSTMINUS: AUTO_UNARY(j - 1, j) /* Simple binary operators */ case AND: BINARY_INTEGER(i & j) case XOR: BINARY_INTEGER(i ^ j) case OR: BINARY_INTEGER(i | j) case PLUS: BINARY_FLOAT(a + b) case MINUS: BINARY_FLOAT(a - b) case MUL: BINARY_FLOAT(a * b) case POWER: BINARY_FLOAT(pow(a, b)) case SHLEFT: BINARY_INTEGER(i << j) case SHRIGHT: BINARY_INTEGER(i >> j) case DIV: BINARY_FLOAT_NOZERO(a / b) case MOD: BINARY_INTEGER_NOZERO(i % j) case DAND: BINARY_BOOLEAN(c && d) case DOR: BINARY_BOOLEAN(c || d) case DXOR: BINARY_BOOLEAN((c && !d) || (!c && d)) case STRCAT: { char * myval; pop_2_strings(cx, &s, &t); CHECK_NOEVAL if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: (%s) ## (%s) -> %s%s", s, t, s, t); myval = malloc_strdup2(s, t); push_string(cx, myval); new_free(&myval); break; } /* Assignment operators */ case PLUSEQ: IMPLIED_FLOAT(a + b) case MINUSEQ: IMPLIED_FLOAT(a - b) case MULEQ: IMPLIED_FLOAT(a * b) case POWEREQ: IMPLIED_FLOAT(pow(a, b)) case DIVEQ: IMPLIED_FLOAT_NOZERO(a / b) case MODEQ: IMPLIED_INTEGER_NOZERO(i % j) case ANDEQ: IMPLIED_INTEGER(i & j) case XOREQ: IMPLIED_INTEGER(i ^ j) case OREQ: IMPLIED_INTEGER(i | j) case SHLEFTEQ: IMPLIED_INTEGER(i << j) case SHRIGHTEQ: IMPLIED_INTEGER(i >> j) case DANDEQ: IMPLIED_BOOLEAN(c && d) case DOREQ: IMPLIED_BOOLEAN(c || d) case DXOREQ: IMPLIED_BOOLEAN((c && !d) || (!c && d)) case STRCATEQ: { char * myval; GET_LVAL_RVAL CHECK_NOEVAL myval = malloc_strdup(get_token_expanded(cx, v)); t = get_token_expanded(cx, w); if (x_debug & DEBUG_NEW_MATH_DEBUG) yell("O: %s = (%s ## %s) -> %s%s", s, myval, t, myval, t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -