# HG changeset patch # User lost # Date 1267669478 0 # Node ID f2173d18c73f5b6d4ed74531d8cfe02a9acdb003 # Parent ebff3a3e8fa6d0403e34ad2b6871177967dc2926 Checkpoint diff -r ebff3a3e8fa6 -r f2173d18c73f lwlib/Makefile.am --- a/lwlib/Makefile.am Tue Mar 02 00:44:18 2010 +0000 +++ b/lwlib/Makefile.am Thu Mar 04 02:24:38 2010 +0000 @@ -1,3 +1,3 @@ noinst_LIBRARIES = liblw.a -liblw_a_SOURCES = lw_alloc.c lw_stringlist.c lw_string.c lw_stack.c lw_error.c -EXTRA_DIST = lw_alloc.h lw_stringlist.h lw_string.h lw_stack.h lw_error.h +liblw_a_SOURCES = lw_alloc.c lw_stringlist.c lw_string.c lw_stack.c lw_error.c lw_expr.c +EXTRA_DIST = lw_alloc.h lw_stringlist.h lw_string.h lw_stack.h lw_error.h lw_expr.h diff -r ebff3a3e8fa6 -r f2173d18c73f lwlib/lw_expr.c --- /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 . +*/ + +#include + +#include +#include +#include + +#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; +} diff -r ebff3a3e8fa6 -r f2173d18c73f lwlib/lw_expr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_expr.h Thu Mar 04 02:24:38 2010 +0000 @@ -0,0 +1,87 @@ +/* +lwexpr.h + +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 . +*/ + +#ifndef ___lw_expr_h_seen___ +#define ___lw_expr_h_seen___ + + +enum +{ + lw_expr_type_oper, // operator term + lw_expr_type_int, // integer + lw_expr_type_var, // a "variable" (string for the name) + lw_expr_type_special // a "special" reference (user defined) +}; + +enum +{ + lw_expr_oper_plus = 1, // addition + lw_expr_oper_minus, // subtraction + lw_expr_oper_times, // multiplication + lw_expr_oper_divide, // division + lw_expr_oper_mod, // modulus + lw_expr_oper_intdiv, // integer division + lw_expr_oper_bwand, // bitwise and + lw_expr_oper_bwor, // bitwise or + lw_expr_oper_bwxor, // bitwise xor + lw_expr_oper_and, // boolean and + lw_expr_oper_or, // boolean or + lw_expr_oper_neg, // unary negation, 2's complement + lw_expr_oper_com // unary 1's complement +}; + +#ifdef ___lw_expr_c_seen___ + +typedef struct lw_expr_priv * lw_expr_t; + +struct lw_expr_opers +{ + lw_expr_t p; + struct lw_expr_opers *next; +}; + +struct lw_expr_priv +{ + int type; // type of term + int value; // integer value + void *value2; // misc pointer value + int refcount; // reference count + struct lw_expr_opers *operands; // ptr to list of operands (for operators) +}; + + +#else /* def ___lw_expr_c_seen___ */ + +typedef void * lw_expr_t; + +extern lw_expr_t lwexpr_create(void); +extern void lwexpr_destroy(lw_expr_t E); +extern lw_expr_t lw_expr_deref(lw_expr_t r); +extern lw_expr_t lw_expr_copy(lw_expr_t E); +extern void lw_expr_add_operand(lw_expr_t E, lw_expr_t O); +extern lw_expr_t lw_expr_deepcopy(lw_expr_t E); +extern lw_expr_t lw_expr_build(int exprtype, ...); +extern void lw_expr_print(lw_expr_t E); +extern int lw_expr_compare(lw_expr_t E1, lw_expr_t E2); + +#endif /* def ___lw_expr_c_seen___ */ + +#endif /* ___lw_expr_h_seen___ */