Lots of minor changes.  Note for mappingobject.c: the hash table pointer
can now be NULL.
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 7d8a8e9..376f031 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -247,7 +247,6 @@
 	
 	pos = 0;
 	while (mappinggetnext(class->cl_dict, &pos, &key, &value)) {
-		object *v;
 		if (!is_accessobject(value))
 			continue;
 		if (hasaccessvalue(value))
@@ -274,7 +273,6 @@
 	object *arg;
 {
 	register instanceobject *inst;
-	object *v;
 	object *init;
 	if (!is_classobject(class)) {
 		err_badcall();
@@ -328,12 +326,12 @@
 instance_dealloc(inst)
 	register instanceobject *inst;
 {
-	object *error_type, *error_value;
+	object *error_type, *error_value, *error_traceback;
 	object *del;
 	/* Call the __del__ method if it exists.  First temporarily
 	   revive the object and save the current exception, if any. */
 	INCREF(inst);
-	err_get(&error_type, &error_value);
+	err_fetch(&error_type, &error_value, &error_traceback);
 	if ((del = instance_getattr1(inst, "__del__")) != NULL) {
 		object *args = newtupleobject(0);
 		object *res = args;
@@ -345,7 +343,7 @@
 		/* XXX If __del__ raised an exception, it is ignored! */
 	}
 	/* Restore the saved exception and undo the temporary revival */
-	err_setval(error_type, error_value);
+	err_restore(error_type, error_value, error_traceback);
 	/* Can't use DECREF here, it would cause a recursive call */
 	if (--inst->ob_refcnt > 0)
 		return; /* __del__ added a reference; don't delete now */
@@ -427,6 +425,7 @@
 			}
 		}
 #endif
+		err_clear();
 		args = mkvalue("(Os)", inst, name);
 		if (args == NULL)
 			return NULL;
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index e40ac8d..89fd314 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -46,9 +46,9 @@
 	3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
 	5987,
 	9551, 15683, 19609, 31397,
-        65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
-        4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
-        134217689L, 268435399L, 536870909L, 1073741789L,
+	65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
+	4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
+	134217689L, 268435399L, 536870909L, 1073741789L,
 	0
 };
 
@@ -95,12 +95,8 @@
 	mp = NEWOBJ(mappingobject, &Mappingtype);
 	if (mp == NULL)
 		return NULL;
-	mp->ma_size = primes[0];
-	mp->ma_table = (mappingentry *) calloc(sizeof(mappingentry), mp->ma_size);
-	if (mp->ma_table == NULL) {
-		DEL(mp);
-		return err_nomem();
-	}
+	mp->ma_size = 0;
+	mp->ma_table = NULL;
 	mp->ma_fill = 0;
 	mp->ma_used = 0;
 	return (object *)mp;
@@ -173,10 +169,13 @@
 	long hash;
 	object *value;
 {
+	object *old_value;
 	register mappingentry *ep;
 	ep = lookmapping(mp, key, hash);
 	if (ep->me_value != NULL) {
-		DECREF(ep->me_value);
+		old_value = ep->me_value;
+		ep->me_value = value;
+		DECREF(old_value); /* which **CAN** re-enter */
 		DECREF(key);
 	}
 	else {
@@ -186,9 +185,9 @@
 			DECREF(ep->me_key);
 		ep->me_key = key;
 		ep->me_hash = hash;
+		ep->me_value = value;
 		mp->ma_used++;
 	}
-	ep->me_value = value;
 }
 
 /*
@@ -233,14 +232,19 @@
 	mp->ma_table = newtable;
 	mp->ma_fill = 0;
 	mp->ma_used = 0;
+
+	/* Make two passes, so we can avoid decrefs
+	   (and possible side effects) till the table is copied */
 	for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
 		if (ep->me_value != NULL)
 			insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
-		else {
-			XDECREF(ep->me_key);
-		}
 	}
-	DEL(oldtable);
+	for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
+		if (ep->me_value == NULL)
+			XDECREF(ep->me_key);
+	}
+
+	XDEL(oldtable);
 	return 0;
 }
 
@@ -254,6 +258,8 @@
 		err_badcall();
 		return NULL;
 	}
+	if (((mappingobject *)op)->ma_table == NULL)
+		return NULL;
 #ifdef CACHE_HASH
 	if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
 #endif
@@ -303,6 +309,8 @@
 	register mappingobject *mp;
 	register long hash;
 	register mappingentry *ep;
+	object *old_value, *old_key;
+
 	if (!is_mappingobject(op)) {
 		err_badcall();
 		return -1;
@@ -319,12 +327,14 @@
 		err_setval(KeyError, key);
 		return -1;
 	}
-	DECREF(ep->me_key);
+	old_key = ep->me_key;
 	INCREF(dummy);
 	ep->me_key = dummy;
-	DECREF(ep->me_value);
+	old_value = ep->me_value;
 	ep->me_value = NULL;
 	mp->ma_used--;
+	DECREF(old_value); 
+	DECREF(old_key); 
 	return 0;
 }
 
@@ -332,18 +342,23 @@
 mappingclear(op)
 	object *op;
 {
-	int i;
-	register mappingobject *mp;
+	int i, n;
+	register mappingentry *table;
+	mappingobject *mp;
 	if (!is_mappingobject(op))
 		return;
 	mp = (mappingobject *)op;
-	for (i = 0; i < mp->ma_size; i++) {
-		XDECREF(mp->ma_table[i].me_key);
-		XDECREF(mp->ma_table[i].me_value);
-		mp->ma_table[i].me_key = NULL;
-		mp->ma_table[i].me_value = NULL;
+	table = mp->ma_table;
+	if (table == NULL)
+		return;
+	n = mp->ma_size;
+	mp->ma_size = mp->ma_used = mp->ma_fill = 0;
+	mp->ma_table = NULL;
+	for (i = 0; i < n; i++) {
+		XDECREF(table[i].me_key);
+		XDECREF(table[i].me_value);
 	}
-	mp->ma_used = 0;
+	DEL(table);
 }
 
 int
@@ -387,8 +402,7 @@
 		if (ep->me_value != NULL)
 			DECREF(ep->me_value);
 	}
-	if (mp->ma_table != NULL)
-		DEL(mp->ma_table);
+	XDEL(mp->ma_table);
 	DEL(mp);
 }
 
@@ -460,6 +474,10 @@
 {
 	object *v;
 	long hash;
+	if (mp->ma_table == NULL) {
+		err_setval(KeyError, key);
+		return NULL;
+	}
 #ifdef CACHE_HASH
 	if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
 #endif
@@ -700,7 +718,7 @@
 	hash = hashobject(key);
 	if (hash == -1)
 		return NULL;
-	ok = lookmapping(mp, key, hash)->me_value != NULL;
+	ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL;
 	return newintobject(ok);
 }
 
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index eb8f4aa..44bc51b 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -94,7 +94,7 @@
 	f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode, fclose);
 	if (f == NULL)
 		return NULL;
-#ifdef USE_FOPENRF
+#ifdef HAVE_FOPENRF
 	if (*mode == '*') {
 		FILE *fopenRF();
 		f->f_fp = fopenRF(name, mode+1);
@@ -231,6 +231,51 @@
 	return None;
 }
 
+#ifdef HAVE_FTRUNCATE
+static object *
+file_truncate(f, args)
+	fileobject *f;
+	object *args;
+{
+	long newsize;
+	int ret;
+	
+	if (f->f_fp == NULL)
+		return err_closed();
+	if (!getargs(args, "l", &newsize)) {
+		err_clear();
+		if (!getnoarg(args))
+		        return NULL;
+		BGN_SAVE
+		errno = 0;
+		newsize =  ftell(f->f_fp); /* default to current position*/
+		END_SAVE
+		if (newsize == -1L) {
+		        err_errno(IOError);
+			clearerr(f->f_fp);
+			return NULL;
+		}
+	}
+	BGN_SAVE
+	errno = 0;
+	ret = fflush(f->f_fp);
+	END_SAVE
+	if (ret == 0) {
+	        BGN_SAVE
+		errno = 0;
+		ret = ftruncate(fileno(f->f_fp), newsize);
+		END_SAVE
+	}
+	if (ret != 0) {
+		err_errno(IOError);
+		clearerr(f->f_fp);
+		return NULL;
+	}
+	INCREF(None);
+	return None;
+}
+#endif /* HAVE_FTRUNCATE */
+
 static object *
 file_tell(f, args)
 	fileobject *f;
@@ -615,6 +660,9 @@
 	{"readline",	(method)file_readline},
 	{"readlines",	(method)file_readlines},
 	{"seek",	(method)file_seek},
+#ifdef HAVE_FTRUNCATE
+	{"truncate",	(method)file_truncate},
+#endif
 	{"tell",	(method)file_tell},
 	{"write",	(method)file_write},
 	{"writelines",	(method)file_writelines},
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index b37dd15..3f8e6aa 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -285,7 +285,6 @@
 {
 	double vx, wx;
 	double div, mod;
-	object *t;
 	wx = w->ob_fval;
 	if (wx == 0.0) {
 		err_setstr(ZeroDivisionError, "float divmod()");
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index a22193f..4d943694 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -39,7 +39,9 @@
 	{"f_globals",	T_OBJECT,	OFF(f_globals),	RO},
 	{"f_locals",	T_OBJECT,	OFF(f_locals),	RO},
 	{"f_owner",	T_OBJECT,	OFF(f_owner),	RO},
-/*	{"f_fastlocals",T_OBJECT,	OFF(f_fastlocals),RO}, /* XXX Unsafe */
+#if 0
+	{"f_fastlocals",T_OBJECT,	OFF(f_fastlocals),RO}, /* XXX Unsafe */
+#endif
 	{"f_localmap",	T_OBJECT,	OFF(f_localmap),RO},
 	{"f_lasti",	T_INT,		OFF(f_lasti),	RO},
 	{"f_lineno",	T_INT,		OFF(f_lineno),	RO},
@@ -217,10 +219,8 @@
 	int level;
 {
 	block *b;
-	if (f->f_iblock >= f->f_nblocks) {
-		fprintf(stderr, "XXX block stack overflow\n");
-		abort();
-	}
+	if (f->f_iblock >= f->f_nblocks)
+		fatal("XXX block stack overflow");
 	b = &f->f_blockstack[f->f_iblock++];
 	b->b_type = type;
 	b->b_level = level;
@@ -232,10 +232,8 @@
 	frameobject *f;
 {
 	block *b;
-	if (f->f_iblock <= 0) {
-		fprintf(stderr, "XXX block stack underflow\n");
-		abort();
-	}
+	if (f->f_iblock <= 0)
+		fatal("XXX block stack underflow");
 	b = &f->f_blockstack[--f->f_iblock];
 	return b;
 }
@@ -248,7 +246,7 @@
 {
 	/* Merge f->f_fastlocals into f->f_locals */
 	object *locals, *fast, *map;
-	object *error_type, *error_value;
+	object *error_type, *error_value, *error_traceback;
 	int j;
 	if (f == NULL)
 		return;
@@ -260,7 +258,7 @@
 	if (!is_dictobject(locals) || !is_listobject(fast) ||
 	    !is_tupleobject(map))
 		return;
-	err_get(&error_type, &error_value);
+	err_fetch(&error_type, &error_value, &error_traceback);
 	for (j = gettuplesize(map); --j >= 0; ) {
 		object *key = gettupleitem(map, j);
 		object *value = getlistitem(fast, j);
@@ -274,7 +272,7 @@
 				err_clear();
 		}
 	}
-	err_setval(error_type, error_value);
+	err_restore(error_type, error_value, error_traceback);
 }
 
 void
@@ -284,7 +282,7 @@
 {
 	/* Merge f->f_locals into f->f_fastlocals */
 	object *locals, *fast, *map;
-	object *error_type, *error_value;
+	object *error_type, *error_value, *error_traceback;
 	int j;
 	if (f == NULL)
 		return;
@@ -296,7 +294,7 @@
 	if (!is_dictobject(locals) || !is_listobject(fast) ||
 	    !is_tupleobject(map))
 		return;
-	err_get(&error_type, &error_value);
+	err_fetch(&error_type, &error_value, &error_traceback);
 	for (j = gettuplesize(map); --j >= 0; ) {
 		object *key = gettupleitem(map, j);
 		object *value = dict2lookup(locals, key);
@@ -308,5 +306,5 @@
 			if (setlistitem(fast, j, value) != 0)
 				err_clear();
 	}
-	err_setval(error_type, error_value);
+	err_restore(error_type, error_value, error_traceback);
 }
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 7a4708e..6b41ae1 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -456,7 +456,6 @@
 	intobject *x;
 	intobject *y;
 {
-	object *v, *v0, *v1;
 	long d, m;
 	if (i_divmod(x, y, &d, &m) < 0)
 		return NULL;
diff --git a/Objects/listobject.c b/Objects/listobject.c
index a3e4cb9..521d1a8 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -404,7 +404,7 @@
 	d = n - (ihigh-ilow);
 	if (d <= 0) { /* Delete -d items; XDECREF ihigh-ilow items */
 		for (k = ilow; k < ihigh; k++)
-			XDECREF(item[k]);
+			XDECREF(item[k]);  /* bug: reentrant side effects */
 		if (d < 0) {
 			for (/*k = ihigh*/; k < a->ob_size; k++)
 				item[k+d] = item[k];
@@ -422,7 +422,7 @@
 		for (k = a->ob_size; --k >= ihigh; )
 			item[k+d] = item[k];
 		for (/*k = ihigh-1*/; k >= ilow; --k)
-			XDECREF(item[k]);
+			XDECREF(item[k]); /* bug: side effects :-( */
 		a->ob_item = item;
 		a->ob_size += d;
 	}
@@ -454,6 +454,7 @@
 	int i;
 	object *v;
 {
+	object *old_value;
 	if (i < 0 || i >= a->ob_size) {
 		err_setstr(IndexError, "list assignment index out of range");
 		return -1;
@@ -461,8 +462,9 @@
 	if (v == NULL)
 		return list_ass_slice(a, i, i+1, v);
 	INCREF(v);
-	DECREF(a->ob_item[i]);
+	old_value = a->ob_item[i];
 	a->ob_item[i] = v;
+	DECREF(old_value); 
 	return 0;
 }
 
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 82a74c0..6561edc 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -570,7 +570,6 @@
 
 /* Forward */
 static void long_dealloc PROTO((object *));
-static int long_print PROTO((object *, FILE *, int));
 static object *long_repr PROTO((object *));
 static int long_compare PROTO((longobject *, longobject *));
 static long long_hash PROTO((longobject *));
diff --git a/Objects/mappingobject.c b/Objects/mappingobject.c
index e40ac8d..89fd314 100644
--- a/Objects/mappingobject.c
+++ b/Objects/mappingobject.c
@@ -46,9 +46,9 @@
 	3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
 	5987,
 	9551, 15683, 19609, 31397,
-        65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
-        4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
-        134217689L, 268435399L, 536870909L, 1073741789L,
+	65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
+	4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
+	134217689L, 268435399L, 536870909L, 1073741789L,
 	0
 };
 
@@ -95,12 +95,8 @@
 	mp = NEWOBJ(mappingobject, &Mappingtype);
 	if (mp == NULL)
 		return NULL;
-	mp->ma_size = primes[0];
-	mp->ma_table = (mappingentry *) calloc(sizeof(mappingentry), mp->ma_size);
-	if (mp->ma_table == NULL) {
-		DEL(mp);
-		return err_nomem();
-	}
+	mp->ma_size = 0;
+	mp->ma_table = NULL;
 	mp->ma_fill = 0;
 	mp->ma_used = 0;
 	return (object *)mp;
@@ -173,10 +169,13 @@
 	long hash;
 	object *value;
 {
+	object *old_value;
 	register mappingentry *ep;
 	ep = lookmapping(mp, key, hash);
 	if (ep->me_value != NULL) {
-		DECREF(ep->me_value);
+		old_value = ep->me_value;
+		ep->me_value = value;
+		DECREF(old_value); /* which **CAN** re-enter */
 		DECREF(key);
 	}
 	else {
@@ -186,9 +185,9 @@
 			DECREF(ep->me_key);
 		ep->me_key = key;
 		ep->me_hash = hash;
+		ep->me_value = value;
 		mp->ma_used++;
 	}
-	ep->me_value = value;
 }
 
 /*
@@ -233,14 +232,19 @@
 	mp->ma_table = newtable;
 	mp->ma_fill = 0;
 	mp->ma_used = 0;
+
+	/* Make two passes, so we can avoid decrefs
+	   (and possible side effects) till the table is copied */
 	for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
 		if (ep->me_value != NULL)
 			insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
-		else {
-			XDECREF(ep->me_key);
-		}
 	}
-	DEL(oldtable);
+	for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
+		if (ep->me_value == NULL)
+			XDECREF(ep->me_key);
+	}
+
+	XDEL(oldtable);
 	return 0;
 }
 
@@ -254,6 +258,8 @@
 		err_badcall();
 		return NULL;
 	}
+	if (((mappingobject *)op)->ma_table == NULL)
+		return NULL;
 #ifdef CACHE_HASH
 	if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
 #endif
@@ -303,6 +309,8 @@
 	register mappingobject *mp;
 	register long hash;
 	register mappingentry *ep;
+	object *old_value, *old_key;
+
 	if (!is_mappingobject(op)) {
 		err_badcall();
 		return -1;
@@ -319,12 +327,14 @@
 		err_setval(KeyError, key);
 		return -1;
 	}
-	DECREF(ep->me_key);
+	old_key = ep->me_key;
 	INCREF(dummy);
 	ep->me_key = dummy;
-	DECREF(ep->me_value);
+	old_value = ep->me_value;
 	ep->me_value = NULL;
 	mp->ma_used--;
+	DECREF(old_value); 
+	DECREF(old_key); 
 	return 0;
 }
 
@@ -332,18 +342,23 @@
 mappingclear(op)
 	object *op;
 {
-	int i;
-	register mappingobject *mp;
+	int i, n;
+	register mappingentry *table;
+	mappingobject *mp;
 	if (!is_mappingobject(op))
 		return;
 	mp = (mappingobject *)op;
-	for (i = 0; i < mp->ma_size; i++) {
-		XDECREF(mp->ma_table[i].me_key);
-		XDECREF(mp->ma_table[i].me_value);
-		mp->ma_table[i].me_key = NULL;
-		mp->ma_table[i].me_value = NULL;
+	table = mp->ma_table;
+	if (table == NULL)
+		return;
+	n = mp->ma_size;
+	mp->ma_size = mp->ma_used = mp->ma_fill = 0;
+	mp->ma_table = NULL;
+	for (i = 0; i < n; i++) {
+		XDECREF(table[i].me_key);
+		XDECREF(table[i].me_value);
 	}
-	mp->ma_used = 0;
+	DEL(table);
 }
 
 int
@@ -387,8 +402,7 @@
 		if (ep->me_value != NULL)
 			DECREF(ep->me_value);
 	}
-	if (mp->ma_table != NULL)
-		DEL(mp->ma_table);
+	XDEL(mp->ma_table);
 	DEL(mp);
 }
 
@@ -460,6 +474,10 @@
 {
 	object *v;
 	long hash;
+	if (mp->ma_table == NULL) {
+		err_setval(KeyError, key);
+		return NULL;
+	}
 #ifdef CACHE_HASH
 	if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
 #endif
@@ -700,7 +718,7 @@
 	hash = hashobject(key);
 	if (hash == -1)
 		return NULL;
-	ok = lookmapping(mp, key, hash)->me_value != NULL;
+	ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL;
 	return newintobject(ok);
 }
 
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index f7363bd..a9bc508 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -132,7 +132,7 @@
 meth_hash(a)
 	methodobject *a;
 {
-	long x, y;
+	long x;
 	if (a->m_self == NULL)
 		x = 0;
 	else {
diff --git a/Objects/object.c b/Objects/object.c
index 04e1ede..f5c22d1 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -63,7 +63,7 @@
 	if (tp->tp_alloc == 0) {
 		/* first time; hang in linked list */
 		if (tp->tp_next != NULL) /* sanity check */
-			abort();
+			fatal("XXX inc_count sanity check");
 		tp->tp_next = type_list;
 		type_list = tp;
 	}
@@ -379,24 +379,18 @@
 	register object *op;
 {
 	register object *p;
-	if (op->ob_refcnt < 0) {
-		fprintf(stderr, "UNREF negative refcnt\n");
-		abort();
-	}
+	if (op->ob_refcnt < 0)
+		fatal("UNREF negative refcnt");
 	if (op == &refchain ||
-	    op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op) {
-		fprintf(stderr, "UNREF invalid object\n");
-		abort();
-	}
+	    op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op)
+		fatal("UNREF invalid object");
 #ifdef SLOW_UNREF_CHECK
 	for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
 		if (p == op)
 			break;
 	}
-	if (p == &refchain) { /* Not found */
-		fprintf(stderr, "UNREF unknown object\n");
-		abort();
-	}
+	if (p == &refchain) /* Not found */
+		fatal("UNREF unknown object");
 #endif
 	op->_ob_next->_ob_prev = op->_ob_prev;
 	op->_ob_prev->_ob_next = op->_ob_next;
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 359e4e9..ae96cea 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -159,7 +159,7 @@
 	DEL(op);
 }
 
-unsigned int
+int
 getstringsize(op)
 	register object *op;
 {