Mercurial > hg-old > index.cgi
diff lwlib/lw_expr.c @ 334:f2173d18c73f
Checkpoint
author | lost |
---|---|
date | Thu, 04 Mar 2010 02:24:38 +0000 |
parents | |
children | 9f58e3bca6e3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_expr.c Thu Mar 04 02:24:38 2010 +0000 @@ -0,0 +1,293 @@ +/* +lwexpr.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#define ___lw_expr_c_seen___ +#include "lw_alloc.h" +#include "lw_expr.h" +#include "lw_error.h" +#include "lw_string.h" + +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); + } +} + +lw_expr_t lw_expr_copy(lw_expr_t E) +{ + E -> refcount++; + return E; +} + +void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) +{ + struct lw_expr_opers *o, *t; + + o = lw_alloc(sizeof(struct lw_expr_opers)); + o -> p = lw_expr_copy(O); + o -> next = NULL; + for (t = E -> operands; t && t -> next; t = t -> next) + /* do nothing */ ; + + if (t) + t -> next = o; + else + 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; + + if (E -> type == lw_expr_type_var) + r -> value2 = lw_strdup(E -> value2); + + for (o = r -> 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(int exprtype, ...) +{ + va_list args; + lw_expr_t r; + int t; + void *p; + + lw_expr_t te1, te2; + + r = lw_expr_create(); + va_start(args, exprtype); + + switch (exprtype) + { + case lw_expr_type_int: + t = va_arg(args, int); + r -> type = lw_expr_type_int; + r -> value = t; + break; + + case lw_expr_type_var: + p = va_arg(args, char *); + r -> type = lw_expr_type_var; + r -> value2 = lw_strdup(p); + break; + + case lw_expr_type_special: + t = va_arg(args, int); + p = va_arg(args, char *); + r -> type = lw_expr_type_special; + r -> value2 = p; + break; + + case lw_expr_type_oper: + t = va_arg(args, int); + te1 = va_arg(args, lw_expr_t); + if (t != lw_expr_oper_com && t != lw_expr_oper_neg) + te2 = va_arg(args, lw_expr_t); + else + te2 = NULL; + + r -> type = lw_expr_type_oper; + r -> value = t; + lw_expr_add_operand(r, te1); + lw_expr_add_operand(r, te2); + break; + + default: + lw_error("Invalid expression type specified to lw_expr_build"); + } + + va_end(args); + return r; +} + +void lw_expr_print(lw_expr_t E) +{ + struct lw_expr_opers *o; + + for (o = E -> operands; o; o = o -> next) + { + lw_expr_print(o -> p); + } + + switch (E -> type) + { + case lw_expr_type_int: + printf("%d ", E -> value); + break; + case lw_expr_type_oper: + switch (E -> value) + { + case lw_expr_oper_plus: + printf("+ "); + break; + + case lw_expr_oper_minus: + printf("- "); + break; + + case lw_expr_oper_times: + printf("* "); + break; + + case lw_expr_oper_divide: + printf("/ "); + break; + + case lw_expr_oper_mod: + printf("%% "); + break; + + case lw_expr_oper_intdiv: + printf("\\ "); + break; + + case lw_expr_oper_bwand: + printf("BWAND "); + break; + + case lw_expr_oper_bwor: + printf("BWOR "); + break; + + case lw_expr_oper_bwxor: + printf("BWXOR "); + break; + + case lw_expr_oper_and: + printf("AND "); + break; + + case lw_expr_oper_or: + printf("OR "); + break; + + case lw_expr_oper_neg: + printf("NEG "); + break; + + case lw_expr_oper_com: + printf("COM "); + break; + + default: + printf("OPER "); + break; + } + break; + default: + printf("ERR "); + break; + } +} + +/* +Return: +nonzero if expressions are the same (identical pointers or matching values) +zero if expressions are not the same + +*/ +int lw_expr_compare(lw_expr_t E1, lw_expr_t E2) +{ + struct lw_expr_opers *o1, *o2; + + if (E1 == E2) + return 1; + + if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value)) + return 0; + + if (E1 -> type == lw_expr_type_var) + { + if (!strcmp(E1 -> value2, E2 -> value2)) + return 1; + else + return 0; + } + + if (E1 -> type == lw_expr_type_special) + { + if (E1 -> value2 == E2 -> value2) + return 1; + else + return 0; + } + + for (o1 = E1 -> operands, o2 = E2 -> operands; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) + if (lw_expr_compare(o1 -> p, o2 -> p) == 0) + return 0; + if (o1 || o2) + return 0; + + return 1; +} + +/* return true if E is an operator of type oper */ +int lw_expr_isoper(lw_expr_t E, int oper) +{ + if (E -> type == lw_expr_type_oper && E -> value == oper) + return 1; + return 0; +}