changeset 334:f2173d18c73f

Checkpoint
author lost
date Thu, 04 Mar 2010 02:24:38 +0000
parents ebff3a3e8fa6
children 9f58e3bca6e3
files lwlib/Makefile.am lwlib/lw_expr.c lwlib/lw_expr.h
diffstat 3 files changed, 382 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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;
+}
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#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___ */