Mercurial > hg-old > index.cgi
view 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 source
/* 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; }