# 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___ */