trunk: changeset 1313

Mon, 16 Feb 2004 18:04:44 +0100

author
tuomov
date
Mon, 16 Feb 2004 18:04:44 +0100
changeset 60
a4033700e35c
parent 59
d8ecbeda7683
child 61
fc585645ad05

trunk: changeset 1313
Moved Ion object system and other generic code from Ion to libtu.

Makefile file | annotate | diff | comparison | revisions
README file | annotate | diff | comparison | revisions
minmax.h file | annotate | diff | comparison | revisions
np/np-conv.h file | annotate | diff | comparison | revisions
np/numparser2.h file | annotate | diff | comparison | revisions
obj.c file | annotate | diff | comparison | revisions
obj.h file | annotate | diff | comparison | revisions
objlist.c file | annotate | diff | comparison | revisions
objlist.h file | annotate | diff | comparison | revisions
objp.h file | annotate | diff | comparison | revisions
symlist.c file | annotate | diff | comparison | revisions
symlist.h file | annotate | diff | comparison | revisions
tokenizer.c file | annotate | diff | comparison | revisions
--- a/Makefile	Mon Feb 16 00:55:23 2004 +0100
+++ b/Makefile	Mon Feb 16 18:04:44 2004 +0100
@@ -11,7 +11,8 @@
 INCLUDES += -I./include
 CFLAGS += $(C89_SOURCE) $(POSIX_SOURCE) 
 
-SOURCES=misc.c output.c util.c optparser.c parser.c tokenizer.c map.c
+SOURCES=misc.c output.c util.c optparser.c parser.c tokenizer.c \
+        map.c obj.c objlist.c errorlog.c symlist.c
 
 ifdef LIBTU_NO_ERRMSG
 DEFINES += -DLIBTU_NO_ERRMSG
@@ -25,8 +26,6 @@
 
 TARGETS=libtu.a
 TESTERS=tester tester2 tester3
-HEADERS=dlist.h misc.h output.h tokenizer.h util.h \
-        map.h np-conv.h optparser.h parser.h types.h
 
 ######################################
 
@@ -53,6 +52,6 @@
 	$(INSTALLDIR) $(LIBDIR)
 	$(INSTALLDIR) $(INCDIR)/libtu
 	$(INSTALL) -m $(DATA_MODE) libtu.a $(LIBDIR)
-	for i in $(HEADERS); do \
+	for i in *.h; do \
 		$(INSTALL) -m $(DATA_MODE) $$i $(INCDIR)/libtu; \
 	done
--- a/README	Mon Feb 16 00:55:23 2004 +0100
+++ b/README	Mon Feb 16 18:04:44 2004 +0100
@@ -1,7 +1,7 @@
 
 libtu
 
-Copyright (c) Tuomo Valkonen 1999-2003.
+Copyright (c) Tuomo Valkonen 1999-2004.
 <tuomov at iki.fi>
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/minmax.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,27 @@
+/*
+ * libtu/minmax.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#ifndef LIBTU_MINMAX_H
+#define LIBTU_MINMAX_H
+
+
+static int minof(int x, int y)
+{
+	return (x<y ? x : y);
+}
+
+
+static int maxof(int x, int y)
+{
+	return (x>y ? x : y);
+}
+
+
+#endif /* LIBTU_MINMAX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/np/np-conv.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,121 @@
+/*
+ * libtu/np-conv.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2002. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#include <math.h>
+
+#ifdef NP_SIMPLE_IMPL
+
+#define FN_NUM_TO_SIGNED(T, UMAX, MAX, MIN)                          \
+ static int num_to_##T(T *ret, const NPNum *num, bool allow_uns_big) \
+ {                                                                   \
+	if(num->type!=NPNUM_INT)                                         \
+		return E_TOKZ_NOTINT;                                        \
+	                                                                 \
+	if(!num->negative){                                              \
+		*ret=num->ival;                                              \
+		if(allow_uns_big?num->ival>UMAX:num->ival>MAX)               \
+		return E_TOKZ_RANGE;                                         \
+	}else{                                                           \
+		*ret=-num->ival;                                             \
+		if(num->ival>-(ulong)MIN)                                    \
+		return E_TOKZ_RANGE;                                         \
+	}                                                                \
+	return 0;                                                        \
+ }
+
+#define FN_NUM_TO_UNSIGNED(T, UMAX, MIN)                         \
+ static int num_to_##T(T *ret, const NPNum *num, bool allow_neg) \
+ {                                                               \
+	if(num->type!=NPNUM_INT)                                     \
+		return E_TOKZ_NOTINT;                                    \
+	                                                             \
+	if(!num->negative){                                          \
+		*ret=num->ival;                                          \
+		if(num->ival>UMAX)                                       \
+		return E_TOKZ_RANGE;                                     \
+	}else{                                                       \
+		*ret=-num->ival;                                         \
+		if(!allow_neg || num->ival>(ulong)-MIN)                  \
+		return E_TOKZ_RANGE;                                     \
+	}                                                            \
+	return 0;                                                    \
+ }
+
+#define FN_NUM_TO_FLOAT(T, POW)                  \
+ static int num_to_##T(T *ret, const NPNum *num) \
+ {                                               \
+	*ret=(num->negative?-num->fval:num->fval);   \
+	return 0;                                    \
+ }
+
+#else /* NP_SIMPLE_IMPL */
+
+#define FN_NUM_TO_SIGNED(T, UMAX, MAX, MIN)                          \
+ static int num_to_##T(T *ret, const NPNum *num, bool allow_uns_big) \
+ {                                                                   \
+	if(num->exponent)                                                \
+		return E_TOKZ_NOTINT;                                        \
+	if(num->nmantissa>0)                                             \
+		return E_TOKZ_RANGE;                                         \
+                                                                     \
+	if(!num->negative){                                              \
+		*ret=num->mantissa[0];                                       \
+		if(allow_uns_big?num->mantissa[0]>UMAX:num->mantissa[0]>MAX) \
+			return E_TOKZ_RANGE;                                     \
+	}else{                                                           \
+		*ret=-num->mantissa[0];                                      \
+		if(num->mantissa[0]>-(ulong)MIN)                             \
+			return E_TOKZ_RANGE;                                     \
+	}                                                                \
+	return 0;                                                        \
+}
+
+#define FN_NUM_TO_UNSIGNED(T, UMAX, MIN)                         \
+ static int num_to_##T(T *ret, const NPNum *num, bool allow_neg) \
+ {                                                               \
+	if(num->exponent)                                            \
+		return E_TOKZ_NOTINT;                                    \
+	if(num->nmantissa>0)                                         \
+		return E_TOKZ_RANGE;                                     \
+                                                                 \
+	if(!num->negative){                                          \
+		*ret=num->mantissa[0];                                   \
+		if(num->mantissa[0]>UMAX)                                \
+			return E_TOKZ_RANGE;                                 \
+	}else{                                                       \
+		*ret=-num->mantissa[0];                                  \
+		if(!allow_neg || num->mantissa[0]>(ulong)-MIN)           \
+			return E_TOKZ_RANGE;                                 \
+	}                                                            \
+	return 0;                                                    \
+}
+
+
+#define FN_NUM_TO_FLOAT(T, POW)                  \
+ static int num_to_##T(T *ret, const NPNum *num) \
+ {                                               \
+	T d=0;                                       \
+	int i;                                       \
+	                                             \
+	for(i=num->nmantissa;i>=0;i--)               \
+		d=d*(T)(ULONG_MAX+1.0)+num->mantissa[i]; \
+                                                 \
+	d*=POW(num->base, num->exponent);            \
+	*ret=d;                                      \
+	                                             \
+	return 0;                                    \
+ }
+
+#endif /* NP_SIMPLE_IMPL */
+
+FN_NUM_TO_SIGNED(long, ULONG_MAX, LONG_MAX, LONG_MIN)
+FN_NUM_TO_SIGNED(char, UCHAR_MAX, CHAR_MAX, CHAR_MIN)
+FN_NUM_TO_FLOAT(double, pow)
+
+#undef NEG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/np/numparser2.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,272 @@
+/*
+ * libtu/numparser2.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2002. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#define MAX_MANTISSA 10  /* should be enough for our needs */
+#define ULONG_SIZE (sizeof(ulong)*8)
+
+enum{
+	NPNUM_INT,
+	NPNUM_FLOAT
+};
+
+#ifdef NP_SIMPLE_IMPL
+
+typedef struct _NPNum{
+	int type;
+	int base;
+ 	bool negative;
+	double fval;
+	ulong ival;
+} NPNum;
+
+#define NUM_INIT {0, 0, 0, 0.0, 0}
+
+static int npnum_mulbase_add(NPNum *num, long base, long v)
+{
+	double iold=num->ival;
+	
+	num->fval=num->fval*base+(double)v;
+	
+	num->ival*=base;
+	
+	if(num->ival<iold)
+		num->type=NPNUM_FLOAT;
+	
+	num->ival+=v;
+	
+	return 0;
+}
+
+#else /* NP_SIMPLE_IMPL */
+
+typedef struct _NPNum{
+	unsigned char nmantissa;
+	int type;
+	int base;
+ 	bool negative;
+	ulong mantissa[MAX_MANTISSA];
+	long exponent;
+} NPNum;
+
+#define NUM_INIT {0, 0, 0, 0, {0,}, 0}
+
+#define ADD_EXP(NUM, X) (NUM)->exponent+=(X);
+
+#if defined(__GNUG__) && defined(i386) && !defined(NP_NO_I386_ASM)
+ #define NP_I386_ASM
+#endif
+
+static int npnum_mulbase_add(NPNum *num, long base, long v)
+{
+	long i, j;
+	ulong overflow;
+#ifndef NP_I386_ASM
+	ulong val;
+#endif
+	
+	for(i=num->nmantissa;i>=0;i--){
+#ifdef NP_I386_ASM
+		__asm__("mul %4\n"
+				: "=a" (num->mantissa[i]), "=d" (overflow)
+				: "0" (num->mantissa[i]), "1" (0), "q" (base)
+				: "eax", "edx");
+#else
+		overflow=0;
+		val=num->mantissa[i];
+		
+		if(val<ULONG_MAX/base){
+			val*=base;
+		}else if(val){
+			ulong tmp=val;
+			ulong old=val;
+			for(j=0; j<base; j++){
+				val+=tmp;
+				if(val<=old)
+					overflow++;
+				old=val;
+			}
+		}
+		num->mantissa[i]=val;
+#endif
+		if(overflow){
+			if(i==num->nmantissa){
+				if(num->nmantissa==MAX_MANTISSA)
+					return E_TOKZ_TOOBIG;
+				num->nmantissa++;
+			}
+			num->mantissa[i+1]+=overflow;
+		}
+	}
+	num->mantissa[0]+=v;
+	
+	return 0;
+}
+
+#undef NP_I386_ASM
+
+#endif /* NP_SIMPLE_IMPL */
+
+
+/* */
+
+
+static bool is_end(int c)
+{
+	/* oops... EOF was missing */
+	return (c==EOF || (c!='.' && ispunct(c)) || isspace(c) || iscntrl(c));
+}
+
+
+/* */
+
+
+static int parse_exponent(NPNum *num, Tokenizer *tokz, int c)
+{
+	long exp=0;
+	bool neg=FALSE;
+	int err=0;
+	
+	c=GETCH();
+	
+	if(c=='-' || c=='+'){
+		if(c=='-')
+			neg=TRUE;
+		c=GETCH();
+	}
+	
+	for(; 1; c=GETCH()){
+		if(isdigit(c)){
+			exp*=10;
+			exp+=c-'0';
+		}else if(is_end(c)){
+			UNGETCH(c);
+			break;
+		}else{
+			err=E_TOKZ_NUMFMT;
+		}
+	}
+
+	if(neg)
+		exp*=-1;
+
+#ifndef NP_SIMPLE_IMPL
+	ADD_EXP(num, exp);
+#else
+	num->fval*=pow(num->base, exp);
+#endif	
+	return err;
+}
+
+
+static int parse_number(NPNum *num, Tokenizer *tokz, int c)
+{
+	int base=10;
+	int dm=1;
+	int err=0;
+	int tmp;
+#ifdef NP_SIMPLE_IMPL
+	double divisor=base;
+#endif	
+	
+	if(c=='-' || c=='+'){
+		if(c=='-')
+			num->negative=TRUE;
+		c=GETCH();
+		if(!isdigit(c))
+			err=E_TOKZ_NUMFMT;
+	}
+	
+	if(c=='0'){
+		dm=0;
+		c=GETCH();
+		if(c=='x' || c=='X'){
+			base=16;
+			c=GETCH();
+		}else if(c=='b' || c=='B'){
+			base=2;
+			c=GETCH();
+		}else if('0'<=c && c<='7'){
+			base=8;
+		}else{
+			dm=2;
+		}
+	}
+	
+	num->base=base;
+	
+	for(; 1; c=GETCH()){
+		if((c=='e' || c=='E') && dm!=0){
+			if(dm<2){
+				err=E_TOKZ_NUMFMT;
+				continue;
+			}
+			tmp=parse_exponent(num, tokz, c);
+			if(err==0)
+				err=tmp;
+			break;
+		}
+		
+		if(isxdigit(c)){
+			if('0'<=c && c<='9')
+				c-='0';
+			else if(isupper(c))
+				c-='A'-10;
+			else
+				c-='a'-10;
+			
+			if(c>=base)
+				err=E_TOKZ_NUMFMT;
+
+#ifdef NP_SIMPLE_IMPL
+			if(dm==3){
+				num->fval+=(double)c/divisor;
+				divisor*=base;
+			}else
+#endif
+			{
+				tmp=npnum_mulbase_add(num, base, c);
+				if(err==0)
+					err=tmp;
+			}
+			
+			if(dm==1)
+				dm=2;
+#ifndef NP_SIMPLE_IMPL			
+			else if(dm==3)
+				ADD_EXP(num, -1);
+#endif			
+			continue;
+		}
+		
+		if(c=='.'){
+			if(dm!=2){
+				err=E_TOKZ_NUMFMT;
+			}
+			dm=3;
+#ifdef NP_SIMPLE_IMPL
+			num->type=NPNUM_FLOAT;
+			divisor=base;
+#endif
+			continue;
+		}
+		
+		if(is_end(c)){
+			UNGETCH(c);
+			break;
+		}
+		
+		err=E_TOKZ_NUMFMT;
+	}
+	
+#ifndef NP_SIMPLE_IMPL			
+	num->type=(num->exponent==0 ? NPNUM_INT : NPNUM_FLOAT);
+#endif
+
+	return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/obj.c	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,297 @@
+/*
+ * libtu/obj.c
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#include <string.h>
+
+#include "types.h"
+#include "obj.h"
+#include "objp.h"
+#include "misc.h"
+#include "dlist.h"
+
+
+ClassDescr CLASSDESCR(Obj)={"Obj", NULL, 0, NULL, NULL};
+
+
+static void do_watches(Obj *obj, bool call);
+
+
+/*{{{ Destroy */
+
+
+void destroy_obj(Obj *obj)
+{
+	ClassDescr *d;
+	
+	if(OBJ_IS_BEING_DESTROYED(obj))
+		return;
+	
+	obj->flags|=OBJ_DEST;
+	
+	do_watches(obj, TRUE);
+	
+	d=obj->obj_type;
+	
+	while(d!=NULL){
+		if(d->destroy_fn!=NULL){
+			d->destroy_fn(obj);
+			break;
+		}
+		d=d->ancestor;
+	}
+	
+	do_watches(obj, FALSE);
+
+	free(obj);
+}
+
+
+/*}}}*/
+
+
+/*{{{ is/cast */
+
+
+bool obj_is(const Obj *obj, const ClassDescr *descr)
+{
+	ClassDescr *d;
+	
+	if(obj==NULL)
+		return FALSE;
+	
+	d=obj->obj_type;
+	
+	while(d!=NULL){
+		if(d==descr)
+			return TRUE;
+		d=d->ancestor;
+	}
+	return FALSE;
+}
+
+
+bool obj_is_str(const Obj *obj, const char *str)
+{
+	ClassDescr *d;
+	
+	if(obj==NULL || str==NULL)
+		return FALSE;
+	
+	d=obj->obj_type;
+	
+	while(d!=NULL){
+		if(strcmp(d->name, str)==0)
+			return TRUE;
+		d=d->ancestor;
+	}
+	return FALSE;
+}
+
+
+const void *obj_cast(const Obj *obj, const ClassDescr *descr)
+{
+	ClassDescr *d;
+	
+	if(obj==NULL)
+		return NULL;
+	
+	d=obj->obj_type;
+	
+	while(d!=NULL){
+		if(d==descr)
+			return (void*)obj;
+		d=d->ancestor;
+	}
+	return NULL;
+}
+
+
+/*}}}*/
+
+
+/*{{{ Dynamic functions */
+
+
+/* This function is called when no handler is found.
+ */
+static void dummy_dyn()
+{
+}
+
+
+static int comp_fun(const void *a, const void *b)
+{
+	void *af=(void*)((DynFunTab*)a)->func;
+	void *bf=(void*)((DynFunTab*)b)->func;
+	
+	return (af<bf ? -1 : (af==bf ? 0 : 1));
+}
+
+			
+DynFun *lookup_dynfun(const Obj *obj, DynFun *func,
+					  bool *funnotfound)
+{
+	ClassDescr *descr;
+	DynFunTab *df;
+	/*DynFunTab dummy={NULL, NULL};*/
+	/*dummy.func=func;*/
+	
+	if(obj==NULL)
+		return NULL;
+	
+	descr=obj->obj_type;
+	
+	for(; descr!=&Obj_classdescr; descr=descr->ancestor){
+		if(descr->funtab==NULL)
+			continue;
+		
+		if(descr->funtab_n==-1){
+			/* Need to sort the table. */
+			descr->funtab_n=0;
+			df=descr->funtab;
+			while(df->func!=NULL){
+				descr->funtab_n++;
+				df++;
+			}
+			
+			if(descr->funtab_n>0){
+				qsort(descr->funtab, descr->funtab_n, sizeof(DynFunTab),
+					  comp_fun);
+			}
+		}
+		
+		/*
+		if(descr->funtab_n==0)
+			continue;
+		
+		df=(DynFunTab*)bsearch(&dummy, descr->funtab, descr->funtab_n,
+							   sizeof(DynFunTab), comp_fun);
+		if(df!=NULL){
+			*funnotfound=FALSE;
+			return df->handler;
+		}
+		*/
+		
+		/* Using custom bsearch instead of the one in libc is probably 
+		 * faster as the overhead of calling a comparison function would
+		 * be significant given that the comparisons are simple and 
+		 * funtab_n not that big.
+		 */
+		{
+			int min=0, max=descr->funtab_n-1;
+			int ndx;
+			df=descr->funtab;
+			while(max>=min){
+				ndx=(max+min)/2;
+				if((void*)df[ndx].func==(void*)func){
+					*funnotfound=FALSE;
+					return df[ndx].handler;
+				}
+				if((void*)df[ndx].func<(void*)func)
+					min=ndx+1;
+				else
+					max=ndx-1;
+			}
+		}
+	}
+	
+	*funnotfound=TRUE;
+	return dummy_dyn;
+}
+
+
+bool has_dynfun(const Obj *obj, DynFun *func)
+{
+	bool funnotfound;
+	lookup_dynfun(obj, func, &funnotfound);
+	return !funnotfound;
+}
+
+
+/*}}}*/
+
+
+/*{{{ Watches */
+
+
+bool watch_setup(Watch *watch, Obj *obj, WatchHandler *handler)
+{
+	if(OBJ_IS_BEING_DESTROYED(obj))
+		return FALSE;
+	
+	watch_reset(watch);
+	
+	watch->handler=handler;
+	LINK_ITEM(obj->obj_watches, watch, next, prev);
+	watch->obj=obj;
+	
+	return TRUE;
+}
+
+void do_watch_reset(Watch *watch, bool call)
+{
+	WatchHandler *handler=watch->handler;
+	Obj *obj=watch->obj;
+	
+	watch->handler=NULL;
+	
+	if(obj==NULL)
+		return;
+	
+	UNLINK_ITEM(obj->obj_watches, watch, next, prev);
+	watch->obj=NULL;
+	
+	if(call && handler!=NULL)
+		handler(watch, obj);
+}
+
+
+void watch_reset(Watch *watch)
+{
+	do_watch_reset(watch, FALSE);
+}
+
+
+bool watch_ok(Watch *watch)
+{
+	return watch->obj!=NULL;
+}
+
+
+static void do_watches(Obj *obj, bool call)
+{
+	Watch *watch, *next;
+
+	watch=obj->obj_watches;
+	
+	while(watch!=NULL){
+		next=watch->next;
+		do_watch_reset(watch, call);
+		watch=next;
+	}
+}
+
+
+void watch_call(Obj *obj)
+{
+	do_watches(obj, FALSE);
+}
+
+
+void watch_init(Watch *watch)
+{
+	watch->obj=NULL;
+	watch->next=NULL;
+	watch->prev=NULL;
+	watch->handler=NULL;
+}
+
+
+/*}}}*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/obj.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,68 @@
+/*
+ * libtu/obj.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#ifndef LIBTU_OBJ_H
+#define LIBTU_OBJ_H
+
+#include "types.h"
+
+#define CLASSDESCR(TYPE) TYPE##_classdescr
+
+#define OBJ_IS(OBJ, TYPE) obj_is((Obj*)OBJ, &CLASSDESCR(TYPE))
+#define OBJ_CAST(OBJ, TYPE) (TYPE*)obj_cast((Obj*)OBJ, &CLASSDESCR(TYPE))
+
+#define INTRSTRUCT(STRU) \
+	struct STRU##_struct; typedef struct STRU##_struct STRU
+#define DECLSTRUCT(STRU)  \
+	struct STRU##_struct
+
+#define INTRCLASS(OBJ) INTRSTRUCT(OBJ); extern ClassDescr CLASSDESCR(OBJ)
+#define DECLCLASS(OBJ) DECLSTRUCT(OBJ)
+
+INTRSTRUCT(ClassDescr);
+INTRCLASS(Obj);
+INTRSTRUCT(Watch);
+
+extern bool obj_is(const Obj *obj, const ClassDescr *descr);
+extern bool obj_is_str(const Obj *obj, const char *str);
+extern const void *obj_cast(const Obj *obj, const ClassDescr *descr);
+
+extern void destroy_obj(Obj *obj);
+
+DECLCLASS(Obj){
+	ClassDescr *obj_type;
+	Watch *obj_watches;
+	int flags;
+};
+
+#define OBJ_DEST 0x0001
+#define OBJ_EXTL_CACHED 0x0002
+
+#define OBJ_IS_BEING_DESTROYED(OBJ) (((Obj*)(OBJ))->flags&OBJ_DEST)
+
+#define DYNFUN
+
+typedef void WatchHandler(Watch *watch, Obj *obj);
+
+#define WWATCH_INIT {NULL, NULL, NULL, NULL}
+
+DECLSTRUCT(Watch){
+	Obj *obj;
+	Watch *next, *prev;
+	WatchHandler *handler;
+};
+
+extern bool watch_setup(Watch *watch, Obj *obj,
+						WatchHandler *handler);
+extern void watch_reset(Watch *watch);
+extern bool watch_ok(Watch *watch);
+extern void watch_init(Watch *watch);
+extern void watch_call(Obj *obj);
+
+#endif /* LIBTU_OBJ_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objlist.c	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,112 @@
+/*
+ * libtu/objlist.c
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#include "obj.h"
+#include "types.h"
+#include "objlist.h"
+#include "dlist.h"
+#include "misc.h"
+
+
+static ObjList *iter_next=NULL;
+
+
+static void free_node(ObjList **objlist, ObjList *node)
+{
+	UNLINK_ITEM(*objlist, node, next, prev);
+	free(node);
+}
+
+	
+void watch_handler(Watch *watch, Obj *obj)
+{
+	ObjList *node=(ObjList*)watch;
+	ObjList **list=node->list;
+	
+	if(iter_next==node)
+		iter_next=node->next;
+	
+	free_node(list, node);
+}
+
+
+
+bool objlist_insert(ObjList **objlist, Obj *obj)
+{
+	ObjList *node;
+	
+	if(obj==NULL)
+		return FALSE;
+	
+	node=ALLOC(ObjList);
+	
+	if(node==NULL)
+		return FALSE;
+		
+	watch_init(&(node->watch));
+	watch_setup(&(node->watch), obj, watch_handler);
+	node->list=objlist;
+	
+	LINK_ITEM_FIRST(*objlist, node, next, prev);
+	
+	return TRUE;
+}
+
+
+void objlist_remove(ObjList **objlist, Obj *obj)
+{
+	ObjList *node=*objlist;
+	
+	while(node!=NULL){
+		if(node->watch.obj==obj){
+			watch_reset(&(node->watch));
+			free_node(objlist, node);
+			return;
+		}
+		node=node->next;
+	}
+}
+
+
+void objlist_clear(ObjList **objlist)
+{
+	while(*objlist!=NULL){
+		watch_reset(&((*objlist)->watch));
+		free_node(objlist, *objlist);
+	}
+}
+
+
+/* Warning: not thread-safe */
+
+
+Obj *objlist_init_iter(ObjList *objlist)
+{
+	if(objlist==NULL){
+		iter_next=NULL;
+		return NULL;
+	}
+	
+	iter_next=objlist->next;
+	return objlist->watch.obj;
+}
+
+
+Obj *objlist_iter()
+{
+	ObjList *ret;
+	
+	if(iter_next==NULL)
+		return NULL;
+	
+	ret=iter_next;
+	iter_next=iter_next->next;
+	
+	return ret->watch.obj;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objlist.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,39 @@
+/*
+ * libtu/objlist.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#ifndef LIBTU_OBJLIST_H
+#define LIBTU_OBJLIST_H
+
+#include "types.h"
+#include "obj.h"
+
+
+INTRSTRUCT(ObjList);
+
+
+DECLSTRUCT(ObjList){
+	Watch watch; /* Must be kept at head of structure */
+	ObjList *next, *prev;
+	ObjList **list;
+};
+
+
+#define FOR_ALL_ON_OBJLIST(TYPE, VAR, LIST)  \
+	for((VAR)=(TYPE)objlist_init_iter(LIST); \
+		(VAR)!=NULL;                         \
+		(VAR)=(TYPE)objlist_iter())
+
+
+bool objlist_insert(ObjList **objlist, Obj *obj);
+void objlist_remove(ObjList **objlist, Obj *obj);
+void objlist_clear(ObjList **objlist);
+Obj *objlist_init_iter(ObjList *objlist);
+Obj *objlist_iter();
+
+#endif /* LIBTU_OBJLIST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objp.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,72 @@
+/*
+ * libtu/objp.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#ifndef LIBTU_OBJP_H
+#define LIBTU_OBJP_H
+
+#include "types.h"
+#include "obj.h"
+
+typedef void DynFun();
+
+INTRSTRUCT(DynFunTab);
+
+DECLSTRUCT(DynFunTab){
+	DynFun *func, *handler;
+};
+
+DECLSTRUCT(ClassDescr){
+	const char *name;
+	ClassDescr *ancestor;
+	int funtab_n;
+	DynFunTab *funtab;
+	void (*destroy_fn)();
+};
+
+#define OBJ_TYPESTR(OBJ) (((Obj*)OBJ)->obj_type->name)
+
+#define IMPLCLASS(CLS, ANCESTOR, DFN, DYN)                         \
+		ClassDescr CLASSDESCR(CLS)={                              \
+			#CLS, &CLASSDESCR(ANCESTOR), -1, DYN, (void (*)())DFN}
+
+#define OBJ_INIT(O, TYPE) {((Obj*)(O))->obj_type=&CLASSDESCR(TYPE); \
+	((Obj*)(O))->obj_watches=NULL; ((Obj*)(O))->flags=0;}
+
+#define CREATEOBJ_IMPL(OBJ, LOWOBJ, INIT_ARGS)                     \
+	OBJ *p;  p=ALLOC(OBJ); if(p==NULL){ warn_err(); return NULL; } \
+	OBJ_INIT(p, OBJ);                                             \
+	if(!LOWOBJ ## _init INIT_ARGS) { free((void*)p); return NULL; } return p
+
+#define SIMPLECREATEOBJ_IMPL(OBJ, LOWOBJ)                          \
+	OBJ *p;  p=ALLOC(OBJ); if(p==NULL){ warn_err(); return NULL; } \
+	OBJ_INIT(p, OBJ);                                             \
+	return p;
+
+#define END_DYNFUNTAB {NULL, NULL}
+
+extern DynFun *lookup_dynfun(const Obj *obj, DynFun *func,
+							 bool *funnotfound);
+extern bool has_dynfun(const Obj *obj, DynFun *func);
+
+#define CALL_DYN(FUNC, OBJ, ARGS)                                \
+	bool funnotfound;                                            \
+	lookup_dynfun((Obj*)OBJ, (DynFun*)FUNC, &funnotfound) ARGS;
+
+#define CALL_DYN_RET(RETV, RET, FUNC, OBJ, ARGS)                 \
+	typedef RET ThisDynFun();                                    \
+	bool funnotfound;                                            \
+	ThisDynFun *funtmp;                                          \
+	funtmp=(ThisDynFun*)lookup_dynfun((Obj*)OBJ, (DynFun*)FUNC, \
+									  &funnotfound);             \
+	if(!funnotfound)                                             \
+		RETV=funtmp ARGS;
+
+#define HAS_DYN(OBJ, FUNC) has_dynfun((Obj*)OBJ, (DynFun*)FUNC)
+
+#endif /* LIBTU_OBJP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symlist.c	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,95 @@
+/*
+ * libtu/symlist.c
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#include "obj.h"
+#include "symlist.h"
+#include "types.h"
+#include "dlist.h"
+#include "misc.h"
+
+
+static void free_node(Symlist **symlist, Symlist *node)
+{
+	UNLINK_ITEM(*symlist, node, next, prev);
+	free(node);
+}
+
+
+bool symlist_insert(Symlist **symlist, void *symbol)
+{
+	Symlist *node;
+	
+	if(symbol==NULL)
+		return FALSE;
+	
+	node=ALLOC(Symlist);
+	
+	if(node==NULL)
+		return FALSE;
+		
+	node->symbol=symbol;
+	
+	LINK_ITEM_FIRST(*symlist, node, next, prev);
+	
+	return TRUE;
+}
+
+
+void symlist_remove(Symlist **symlist, void *symbol)
+{
+	Symlist *node=*symlist;
+	
+	while(node!=NULL){
+		if(node->symbol==symbol){
+			free_node(symlist, node);
+			return;
+		}
+		node=node->next;
+	}
+}
+
+
+void symlist_clear(Symlist **symlist)
+{
+	while(*symlist!=NULL)
+		free_node(symlist, *symlist);
+}
+
+
+/* Warning: not thread-safe */
+
+
+static Symlist *iter_next=NULL;
+
+
+void *symlist_init_iter(Symlist *symlist)
+{
+	if(symlist==NULL){
+		iter_next=NULL;
+		return NULL;
+	}
+	
+	iter_next=symlist->next;
+	return symlist->symbol;
+}
+
+
+void *symlist_iter()
+{
+	Symlist *ret;
+	
+	if(iter_next==NULL)
+		return NULL;
+	
+	ret=iter_next;
+	iter_next=iter_next->next;
+	
+	return ret->symbol;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symlist.h	Mon Feb 16 18:04:44 2004 +0100
@@ -0,0 +1,38 @@
+/*
+ * libtu/symlist.h
+ *
+ * Copyright (c) Tuomo Valkonen 1999-2004. 
+ *
+ * You may distribute and modify this library under the terms of either
+ * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
+ */
+
+#ifndef LIBTU_SYMLIST_H
+#define LIBTU_SYMLIST_H
+
+#include "types.h"
+#include "obj.h"
+
+
+INTRSTRUCT(Symlist);
+
+
+DECLSTRUCT(Symlist){
+	void *symbol;
+	Symlist *next, *prev;
+};
+
+
+#define ITERATE_SYMLIST(TYPE, VAR, LIST)     \
+	for((VAR)=(TYPE)symlist_init_iter(LIST); \
+		(VAR)!=NULL;                         \
+		(VAR)=(TYPE)symlist_iter())
+
+
+bool symlist_insert(Symlist **symlist, void *symbol);
+void symlist_remove(Symlist **symlist, void *symbol);
+void symlist_clear(Symlist **symlist);
+void *symlist_init_iter(Symlist *symlist);
+void *symlist_iter();
+
+#endif /* LIBTU_SYMLIST_H */
--- a/tokenizer.c	Mon Feb 16 00:55:23 2004 +0100
+++ b/tokenizer.c	Mon Feb 16 18:04:44 2004 +0100
@@ -419,8 +419,8 @@
 }
 
 #define NP_SIMPLE_IMPL
-#include "numparser2.h"
-#include "np-conv.h"
+#include "np/numparser2.h"
+#include "np/np-conv.h"
 
 
 static int scan_number(Token *tok, Tokenizer *tokz, int c)

mercurial