Mercurial > hg-old > index.cgi
diff lwlib/lw_expr.c @ 337:04c80c51b16a
Checkpoint development
author | lost |
---|---|
date | Fri, 12 Mar 2010 06:01:38 +0000 |
parents | 401587ab6a09 |
children | 7b4123dce741 |
line wrap: on
line diff
--- a/lwlib/lw_expr.c Fri Mar 05 02:34:16 2010 +0000 +++ b/lwlib/lw_expr.c Fri Mar 12 06:01:38 2010 +0000 @@ -31,44 +31,58 @@ #include "lw_error.h" #include "lw_string.h" +static lw_expr_t (*evaluate_special)(int t, void *ptr) = NULL; +static lw_expr_t (*evaluate_var)(char *var) = NULL; + +void lw_expr_set_special_handler(lw_expr_t (*fn)(int t, void *ptr)) +{ + evaluate_special = fn; +} + +void lw_expr_set_var_handler(lw_expr_t (*fn)(char *var)) +{ + evaluate_var = fn; +} + lw_expr_t lw_expr_create(void) { lw_expr_t r; r = lw_alloc(sizeof(struct lw_expr_priv)); - r -> refcount = 1; r -> operands = NULL; return r; } -/* useful for constant expression construction */ -/* lw_expr_deref(lw_expr_create(...)) */ -/* use of this function on an expression that is not already referenced by the caller */ -lw_expr_t lw_expr_deref(lw_expr_t r) -{ - r -> refcount--; - return r; -} - void lw_expr_destroy(lw_expr_t E) { - E -> refcount--; - if (E -> refcount <= 0) - { - struct lw_expr_opers *o; - for (o = E -> operands; o; o = o -> next) - lw_expr_destroy(o -> p); - if (E -> type == lw_expr_type_var) - lw_free(E -> value2); - lw_free(E); - } + struct lw_expr_opers *o; + for (o = E -> operands; o; o = o -> next) + lw_expr_destroy(o -> p); + if (E -> type == lw_expr_type_var) + lw_free(E -> value2); + lw_free(E); } +/* actually duplicates the entire expression */ +void lw_expr_add_operand(lw_expr_t E, lw_expr_t O); lw_expr_t lw_expr_copy(lw_expr_t E) { - E -> refcount++; - return E; + lw_expr_t r, t; + struct lw_expr_opers *o; + + r = lw_alloc(sizeof(struct lw_expr_priv)); + *r = *E; + r -> operands = NULL; + + if (E -> type == lw_expr_type_var) + r -> value2 = lw_strdup(E -> value2); + for (o = E -> operands; o; o = o -> next) + { + lw_expr_add_operand(r, lw_expr_copy(o -> p)); + } + + return r; } void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) @@ -87,27 +101,6 @@ E -> operands = o; } -/* actually duplicates the entire expression */ -lw_expr_t lw_expr_deepcopy(lw_expr_t E) -{ - lw_expr_t r, t; - struct lw_expr_opers *o; - - r = lw_alloc(sizeof(struct lw_expr_priv)); - *r = *E; - r -> refcount = 1; - r -> operands = NULL; - - if (E -> type == lw_expr_type_var) - r -> value2 = lw_strdup(E -> value2); - for (o = E -> operands; o; o = o -> next) - { - lw_expr_add_operand(r, lw_expr_deref(lw_expr_deepcopy(o -> p))); - } - - return r; -} - lw_expr_t lw_expr_build_aux(int exprtype, va_list args) { lw_expr_t r; @@ -136,6 +129,7 @@ t = va_arg(args, int); p = va_arg(args, char *); r -> type = lw_expr_type_special; + r -> value = t; r -> value2 = p; break; @@ -171,18 +165,6 @@ return r; } -lw_expr_t lw_expr_build_noref(int exprtype, ...) -{ - va_list args; - lw_expr_t r; - - va_start(args, exprtype); - r = lw_expr_build_aux(exprtype, args); - r -> refcount--; - va_end(args); - return r; -} - void lw_expr_print(lw_expr_t E) { struct lw_expr_opers *o; @@ -375,12 +357,155 @@ { struct lw_expr_opers *o; +again: + // try to resolve non-constant terms to constants here + if (E -> type == lw_expr_type_special && evaluate_special) + { + lw_expr_t te; + + te = evaluate_special(E -> value, E -> value2); + if (te) + { + for (o = E -> operands; o; o = o -> next) + lw_expr_destroy(o -> p); + if (E -> type == lw_expr_type_var) + lw_free(E -> value2); + *E = *te; + E -> operands = NULL; + + if (te -> type == lw_expr_type_var) + E -> value2 = lw_strdup(te -> value2); + for (o = te -> operands; o; o = o -> next) + { + lw_expr_add_operand(E, lw_expr_copy(o -> p)); + } + lw_expr_destroy(te); + goto again; + } + return; + } + + if (E -> type == lw_expr_type_var && evaluate_var) + { + lw_expr_t te; + + te = evaluate_var(E -> value2); + if (te) + { + for (o = E -> operands; o; o = o -> next) + lw_expr_destroy(o -> p); + if (E -> type == lw_expr_type_var) + lw_free(E -> value2); + *E = *te; + E -> operands = NULL; + + if (te -> type == lw_expr_type_var) + E -> value2 = lw_strdup(te -> value2); + for (o = te -> operands; o; o = o -> next) + { + lw_expr_add_operand(E, lw_expr_copy(o -> p)); + } + lw_expr_destroy(te); + goto again; + } + return; + } + + // non-operators have no simplification to do! + if (E -> type != lw_expr_type_oper) + return; + // sort "constants" to the start of each operand list for + and * lw_expr_simplify_sortconstfirst(E); - // non-operators have no simplification to do! - if (E -> type != lw_expr_type_oper) + // simplify operands + for (o = E -> operands; o; o = o -> next) + lw_expr_simplify(o -> p); + + for (o = E -> operands; o; o = o -> next) + { + if (o -> p -> type != lw_expr_type_int) + break; + } + + if (!o) + { + // we can do the operation here! + int tr = -42424242; + + switch (E -> value) + { + case lw_expr_oper_neg: + tr = -(E -> operands -> p -> value); + break; + + case lw_expr_oper_com: + tr = ~(E -> operands -> p -> value); + break; + + case lw_expr_oper_plus: + tr = E -> operands -> p -> value; + for (o = E -> operands -> next; o; o = o -> next) + tr += o -> p -> value; + break; + + case lw_expr_oper_minus: + tr = E -> operands -> p -> value; + for (o = E -> operands -> next; o; o = o -> next) + tr -= o -> p -> value; + break; + + case lw_expr_oper_times: + tr = E -> operands -> p -> value; + for (o = E -> operands -> next; o; o = o -> next) + tr *= o -> p -> value; + break; + + case lw_expr_oper_divide: + tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_mod: + tr = E -> operands -> p -> value % E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_intdiv: + tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_bwand: + tr = E -> operands -> p -> value & E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_bwor: + tr = E -> operands -> p -> value | E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_bwxor: + tr = E -> operands -> p -> value ^ E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_and: + tr = E -> operands -> p -> value && E -> operands -> next -> p -> value; + break; + + case lw_expr_oper_or: + tr = E -> operands -> p -> value || E -> operands -> next -> p -> value; + break; + + } + + while (E -> operands) + { + o = E -> operands; + E -> operands = o -> next; + lw_expr_destroy(o -> p); + lw_free(o); + } + E -> type = lw_expr_type_int; + E -> value = tr; return; + } if (E -> value == lw_expr_oper_times) { @@ -438,9 +563,6 @@ } - for (o = E -> operands; o; o = o -> next) - lw_expr_simplify(o -> p); - if (E -> value == lw_expr_oper_plus) { int c = 0, t = 0; @@ -461,7 +583,7 @@ o = E -> operands; if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) { - r = lw_expr_deepcopy(o -> p); + r = lw_expr_copy(o -> p); } E -> operands = o -> next; lw_expr_destroy(o -> p);