Merge back to main trunk
diff --git a/Modules/cgensupport.c b/Modules/cgensupport.c
index 87fcfab..5f3ad04 100644
--- a/Modules/cgensupport.c
+++ b/Modules/cgensupport.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index fb7456d..e40ac8d 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -38,16 +38,18 @@
 Table of primes suitable as keys, in ascending order.
 The first line are the largest primes less than some powers of two,
 the second line is the largest prime less than 6000,
-and the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
-The final value is a sentinel and should cause the memory allocation
-of that many entries to fail (if none of the earlier values cause such
-failure already).
+the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1,
+and the next three lines were suggested by Steve Kirsch.
+The final value is a sentinel.
 */
-static unsigned int primes[] = {
+static long primes[] = {
 	3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
 	5987,
 	9551, 15683, 19609, 31397,
-	0xffffffff /* All bits set -- truncation OK */
+        65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
+        4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
+        134217689L, 268435399L, 536870909L, 1073741789L,
+	0
 };
 
 /* Object used as dummy key to fill deleted entries */
@@ -207,8 +209,18 @@
 	register int i;
 	newsize = mp->ma_size;
 	for (i = 0; ; i++) {
+		if (primes[i] <= 0) {
+			/* Ran out of primes */
+			err_nomem();
+			return -1;
+		}
 		if (primes[i] > mp->ma_used*2) {
 			newsize = primes[i];
+			if (newsize != primes[i]) {
+				/* Integer truncation */
+				err_nomem();
+				return -1;
+			}
 			break;
 		}
 	}
@@ -406,15 +418,6 @@
 	return 0;
 }
 
-static void
-js(pv, w)
-	object **pv;
-	object *w;
-{
-	joinstring(pv, w);
-	XDECREF(w);
-}
-
 static object *
 mapping_repr(mp)
 	mappingobject *mp;
@@ -428,16 +431,16 @@
 	sepa = newstringobject(", ");
 	colon = newstringobject(": ");
 	any = 0;
-	for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
+	for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
 		if (ep->me_value != NULL) {
 			if (any++)
 				joinstring(&v, sepa);
-			js(&v, reprobject(ep->me_key));
+			joinstring_decref(&v, reprobject(ep->me_key));
 			joinstring(&v, colon);
-			js(&v, reprobject(ep->me_value));
+			joinstring_decref(&v, reprobject(ep->me_value));
 		}
 	}
-	js(&v, newstringobject("}"));
+	joinstring_decref(&v, newstringobject("}"));
 	XDECREF(sepa);
 	XDECREF(colon);
 	return v;
@@ -483,9 +486,9 @@
 }
 
 static mapping_methods mapping_as_mapping = {
-	mapping_length,	/*mp_length*/
-	mapping_subscript,	/*mp_subscript*/
-	mapping_ass_sub,	/*mp_ass_subscript*/
+	(inquiry)mapping_length, /*mp_length*/
+	(binaryfunc)mapping_subscript, /*mp_subscript*/
+	(objobjargproc)mapping_ass_sub, /*mp_ass_subscript*/
 };
 
 static object *
@@ -607,7 +610,7 @@
 		err_badcall();
 		return NULL;
 	}
-	return mapping_values((mappingobject *)mp, (object *)NULL);
+	return mapping_items((mappingobject *)mp, (object *)NULL);
 }
 
 static int
@@ -702,10 +705,10 @@
 }
 
 static struct methodlist mapp_methods[] = {
-	{"has_key",	mapping_has_key},
-	{"items",	mapping_items},
-	{"keys",	mapping_keys},
-	{"values",	mapping_values},
+	{"has_key",	(method)mapping_has_key},
+	{"items",	(method)mapping_items},
+	{"keys",	(method)mapping_keys},
+	{"values",	(method)mapping_values},
 	{NULL,		NULL}		/* sentinel */
 };
 
@@ -723,12 +726,12 @@
 	"dictionary",
 	sizeof(mappingobject),
 	0,
-	mapping_dealloc,	/*tp_dealloc*/
-	mapping_print,		/*tp_print*/
-	mapping_getattr,	/*tp_getattr*/
+	(destructor)mapping_dealloc, /*tp_dealloc*/
+	(printfunc)mapping_print, /*tp_print*/
+	(getattrfunc)mapping_getattr, /*tp_getattr*/
 	0,			/*tp_setattr*/
-	mapping_compare,	/*tp_compare*/
-	mapping_repr,		/*tp_repr*/
+	(cmpfunc)mapping_compare, /*tp_compare*/
+	(reprfunc)mapping_repr, /*tp_repr*/
 	0,			/*tp_as_number*/
 	0,			/*tp_as_sequence*/
 	&mapping_as_mapping,	/*tp_as_mapping*/
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 0b5e75c..a22193f 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -34,15 +34,16 @@
 #define OFF(x) offsetof(frameobject, x)
 
 static struct memberlist frame_memberlist[] = {
-	{"f_back",	T_OBJECT,	OFF(f_back)},
-	{"f_code",	T_OBJECT,	OFF(f_code)},
-	{"f_globals",	T_OBJECT,	OFF(f_globals)},
-	{"f_locals",	T_OBJECT,	OFF(f_locals)},
-	{"f_owner",	T_OBJECT,	OFF(f_owner)},
-/*	{"f_fastlocals",T_OBJECT,	OFF(f_fastlocals)}, /* XXX Unsafe */
-	{"f_localmap",	T_OBJECT,	OFF(f_localmap)},
-	{"f_lasti",	T_INT,		OFF(f_lasti)},
-	{"f_lineno",	T_INT,		OFF(f_lineno)},
+	{"f_back",	T_OBJECT,	OFF(f_back),	RO},
+	{"f_code",	T_OBJECT,	OFF(f_code),	RO},
+	{"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 */
+	{"f_localmap",	T_OBJECT,	OFF(f_localmap),RO},
+	{"f_lasti",	T_INT,		OFF(f_lasti),	RO},
+	{"f_lineno",	T_INT,		OFF(f_lineno),	RO},
+	{"f_trace",	T_OBJECT,	OFF(f_trace)},
 	{NULL}	/* Sentinel */
 };
 
@@ -51,9 +52,20 @@
 	frameobject *f;
 	char *name;
 {
+	if (strcmp(name, "f_locals") == 0)
+		fast_2_locals(f);
 	return getmember((char *)f, frame_memberlist, name);
 }
 
+static int
+frame_setattr(f, name, value)
+	frameobject *f;
+	char *name;
+	object *value;
+{
+	return setmember((char *)f, frame_memberlist, name, value);
+}
+
 /* Stack frames are allocated and deallocated at a considerable rate.
    In an attempt to improve the speed of function calls, we maintain a
    separate free list of stack frames (just like integers are
@@ -88,6 +100,7 @@
 	XDECREF(f->f_owner);
 	XDECREF(f->f_fastlocals);
 	XDECREF(f->f_localmap);
+	XDECREF(f->f_trace);
 	f->f_back = free_list;
 	free_list = f;
 }
@@ -98,10 +111,10 @@
 	"frame",
 	sizeof(frameobject),
 	0,
-	frame_dealloc,	/*tp_dealloc*/
+	(destructor)frame_dealloc, /*tp_dealloc*/
 	0,		/*tp_print*/
-	frame_getattr,	/*tp_getattr*/
-	0,		/*tp_setattr*/
+	(getattrfunc)frame_getattr, /*tp_getattr*/
+	(setattrfunc)frame_setattr, /*tp_setattr*/
 	0,		/*tp_compare*/
 	0,		/*tp_repr*/
 	0,		/*tp_as_number*/
@@ -167,6 +180,7 @@
 		f->f_iblock = 0;
 		f->f_lasti = 0;
 		f->f_lineno = -1;
+		f->f_trace = NULL;
 		if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
 			err_nomem();
 			DECREF(f);
@@ -225,3 +239,74 @@
 	b = &f->f_blockstack[--f->f_iblock];
 	return b;
 }
+
+/* Convert between "fast" version of locals and dictionary version */
+
+void
+fast_2_locals(f)
+	frameobject *f;
+{
+	/* Merge f->f_fastlocals into f->f_locals */
+	object *locals, *fast, *map;
+	object *error_type, *error_value;
+	int j;
+	if (f == NULL)
+		return;
+	locals = f->f_locals;
+	fast = f->f_fastlocals;
+	map = f->f_localmap;
+	if (locals == NULL || fast == NULL || map == NULL)
+		return;
+	if (!is_dictobject(locals) || !is_listobject(fast) ||
+	    !is_tupleobject(map))
+		return;
+	err_get(&error_type, &error_value);
+	for (j = gettuplesize(map); --j >= 0; ) {
+		object *key = gettupleitem(map, j);
+		object *value = getlistitem(fast, j);
+		if (value == NULL) {
+			err_clear();
+			if (dict2remove(locals, key) != 0)
+				err_clear();
+		}
+		else {
+			if (dict2insert(locals, key, value) != 0)
+				err_clear();
+		}
+	}
+	err_setval(error_type, error_value);
+}
+
+void
+locals_2_fast(f, clear)
+	frameobject *f;
+	int clear;
+{
+	/* Merge f->f_locals into f->f_fastlocals */
+	object *locals, *fast, *map;
+	object *error_type, *error_value;
+	int j;
+	if (f == NULL)
+		return;
+	locals = f->f_locals;
+	fast = f->f_fastlocals;
+	map = f->f_localmap;
+	if (locals == NULL || fast == NULL || map == NULL)
+		return;
+	if (!is_dictobject(locals) || !is_listobject(fast) ||
+	    !is_tupleobject(map))
+		return;
+	err_get(&error_type, &error_value);
+	for (j = gettuplesize(map); --j >= 0; ) {
+		object *key = gettupleitem(map, j);
+		object *value = dict2lookup(locals, key);
+		if (value == NULL)
+			err_clear();
+		else
+			INCREF(value);
+		if (value != NULL || clear)
+			if (setlistitem(fast, j, value) != 0)
+				err_clear();
+	}
+	err_setval(error_type, error_value);
+}
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index cc4900a..d7549e0 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -41,6 +41,8 @@
 		op->func_globals = globals;
 		op->func_name = ((codeobject*)(op->func_code))->co_name;
 		INCREF(op->func_name);
+		op->func_argcount = -1; /* Unknown */
+		op->func_argdefs = NULL; /* No default arguments */
 	}
 	return (object *)op;
 }
@@ -67,6 +69,44 @@
 	return ((funcobject *) op) -> func_globals;
 }
 
+object *
+getfuncargstuff(op, argcount_return)
+	object *op;
+	int *argcount_return;
+{
+	if (!is_funcobject(op)) {
+		err_badcall();
+		return NULL;
+	}
+	*argcount_return = ((funcobject *) op) -> func_argcount;
+	return ((funcobject *) op) -> func_argdefs;
+}
+
+int
+setfuncargstuff(op, argcount, argdefs)
+	object *op;
+	int argcount;
+	object *argdefs;
+{
+	if (!is_funcobject(op) ||
+	    argdefs != NULL && !is_tupleobject(argdefs)) {
+		err_badcall();
+		return -1;
+	}
+	if (argdefs == None)
+		argdefs = NULL;
+	else if (is_tupleobject(argdefs))
+		XINCREF(argdefs);
+	else {
+		err_setstr(SystemError, "non-tuple default args");
+		return -1;
+	}
+	((funcobject *) op) -> func_argcount = argcount;
+	XDECREF(((funcobject *) op) -> func_argdefs);
+	((funcobject *) op) -> func_argdefs = argdefs;
+	return 0;
+}
+
 /* Methods */
 
 #define OFF(x) offsetof(funcobject, x)
@@ -75,6 +115,8 @@
 	{"func_code",	T_OBJECT,	OFF(func_code),		READONLY},
 	{"func_globals",T_OBJECT,	OFF(func_globals),	READONLY},
 	{"func_name",	T_OBJECT,	OFF(func_name),		READONLY},
+	{"func_argcount",T_INT,		OFF(func_argcount),	READONLY},
+	{"func_argdefs",T_OBJECT,	OFF(func_argdefs),	READONLY},
 	{NULL}	/* Sentinel */
 };
 
@@ -92,6 +134,7 @@
 {
 	DECREF(op->func_code);
 	DECREF(op->func_globals);
+	XDECREF(op->func_argdefs);
 	DEL(op);
 }
 
@@ -113,8 +156,15 @@
 func_compare(f, g)
 	funcobject *f, *g;
 {
+	int c;
 	if (f->func_globals != g->func_globals)
 		return (f->func_globals < g->func_globals) ? -1 : 1;
+	c = f->func_argcount < g->func_argcount;
+	if (c != 0)
+		return c < 0 ? -1 : 1;
+	c = cmpobject(f->func_argdefs, g->func_argdefs);
+	if (c != 0)
+		return c;
 	return cmpobject(f->func_code, g->func_code);
 }
 
@@ -136,14 +186,14 @@
 	"function",
 	sizeof(funcobject),
 	0,
-	func_dealloc,	/*tp_dealloc*/
+	(destructor)func_dealloc, /*tp_dealloc*/
 	0,		/*tp_print*/
-	func_getattr,	/*tp_getattr*/
+	(getattrfunc)func_getattr, /*tp_getattr*/
 	0,		/*tp_setattr*/
-	func_compare,	/*tp_compare*/
-	func_repr,	/*tp_repr*/
+	(cmpfunc)func_compare, /*tp_compare*/
+	(reprfunc)func_repr, /*tp_repr*/
 	0,		/*tp_as_number*/
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
-	func_hash,	/*tp_hash*/
+	(hashfunc)func_hash, /*tp_hash*/
 };
diff --git a/Objects/mappingobject.c b/Objects/mappingobject.c
index fb7456d..e40ac8d 100644
--- a/Objects/mappingobject.c
+++ b/Objects/mappingobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -38,16 +38,18 @@
 Table of primes suitable as keys, in ascending order.
 The first line are the largest primes less than some powers of two,
 the second line is the largest prime less than 6000,
-and the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
-The final value is a sentinel and should cause the memory allocation
-of that many entries to fail (if none of the earlier values cause such
-failure already).
+the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1,
+and the next three lines were suggested by Steve Kirsch.
+The final value is a sentinel.
 */
-static unsigned int primes[] = {
+static long primes[] = {
 	3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
 	5987,
 	9551, 15683, 19609, 31397,
-	0xffffffff /* All bits set -- truncation OK */
+        65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
+        4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
+        134217689L, 268435399L, 536870909L, 1073741789L,
+	0
 };
 
 /* Object used as dummy key to fill deleted entries */
@@ -207,8 +209,18 @@
 	register int i;
 	newsize = mp->ma_size;
 	for (i = 0; ; i++) {
+		if (primes[i] <= 0) {
+			/* Ran out of primes */
+			err_nomem();
+			return -1;
+		}
 		if (primes[i] > mp->ma_used*2) {
 			newsize = primes[i];
+			if (newsize != primes[i]) {
+				/* Integer truncation */
+				err_nomem();
+				return -1;
+			}
 			break;
 		}
 	}
@@ -406,15 +418,6 @@
 	return 0;
 }
 
-static void
-js(pv, w)
-	object **pv;
-	object *w;
-{
-	joinstring(pv, w);
-	XDECREF(w);
-}
-
 static object *
 mapping_repr(mp)
 	mappingobject *mp;
@@ -428,16 +431,16 @@
 	sepa = newstringobject(", ");
 	colon = newstringobject(": ");
 	any = 0;
-	for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
+	for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
 		if (ep->me_value != NULL) {
 			if (any++)
 				joinstring(&v, sepa);
-			js(&v, reprobject(ep->me_key));
+			joinstring_decref(&v, reprobject(ep->me_key));
 			joinstring(&v, colon);
-			js(&v, reprobject(ep->me_value));
+			joinstring_decref(&v, reprobject(ep->me_value));
 		}
 	}
-	js(&v, newstringobject("}"));
+	joinstring_decref(&v, newstringobject("}"));
 	XDECREF(sepa);
 	XDECREF(colon);
 	return v;
@@ -483,9 +486,9 @@
 }
 
 static mapping_methods mapping_as_mapping = {
-	mapping_length,	/*mp_length*/
-	mapping_subscript,	/*mp_subscript*/
-	mapping_ass_sub,	/*mp_ass_subscript*/
+	(inquiry)mapping_length, /*mp_length*/
+	(binaryfunc)mapping_subscript, /*mp_subscript*/
+	(objobjargproc)mapping_ass_sub, /*mp_ass_subscript*/
 };
 
 static object *
@@ -607,7 +610,7 @@
 		err_badcall();
 		return NULL;
 	}
-	return mapping_values((mappingobject *)mp, (object *)NULL);
+	return mapping_items((mappingobject *)mp, (object *)NULL);
 }
 
 static int
@@ -702,10 +705,10 @@
 }
 
 static struct methodlist mapp_methods[] = {
-	{"has_key",	mapping_has_key},
-	{"items",	mapping_items},
-	{"keys",	mapping_keys},
-	{"values",	mapping_values},
+	{"has_key",	(method)mapping_has_key},
+	{"items",	(method)mapping_items},
+	{"keys",	(method)mapping_keys},
+	{"values",	(method)mapping_values},
 	{NULL,		NULL}		/* sentinel */
 };
 
@@ -723,12 +726,12 @@
 	"dictionary",
 	sizeof(mappingobject),
 	0,
-	mapping_dealloc,	/*tp_dealloc*/
-	mapping_print,		/*tp_print*/
-	mapping_getattr,	/*tp_getattr*/
+	(destructor)mapping_dealloc, /*tp_dealloc*/
+	(printfunc)mapping_print, /*tp_print*/
+	(getattrfunc)mapping_getattr, /*tp_getattr*/
 	0,			/*tp_setattr*/
-	mapping_compare,	/*tp_compare*/
-	mapping_repr,		/*tp_repr*/
+	(cmpfunc)mapping_compare, /*tp_compare*/
+	(reprfunc)mapping_repr, /*tp_repr*/
 	0,			/*tp_as_number*/
 	0,			/*tp_as_sequence*/
 	&mapping_as_mapping,	/*tp_as_mapping*/
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 0a56161..f7363bd 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -149,16 +149,16 @@
 	"builtin_function_or_method",
 	sizeof(methodobject),
 	0,
-	meth_dealloc,	/*tp_dealloc*/
+	(destructor)meth_dealloc, /*tp_dealloc*/
 	0,		/*tp_print*/
 	0,		/*tp_getattr*/
 	0,		/*tp_setattr*/
-	meth_compare,	/*tp_compare*/
-	meth_repr,	/*tp_repr*/
+	(cmpfunc)meth_compare, /*tp_compare*/
+	(reprfunc)meth_repr, /*tp_repr*/
 	0,		/*tp_as_number*/
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
-	meth_hash,	/*tp_hash*/
+	(hashfunc)meth_hash, /*tp_hash*/
 };
 
 static object *listmethods PROTO((struct methodlist *)); /* Forward */
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 9a687b4..b98d843 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -162,10 +162,10 @@
 	"module",		/*tp_name*/
 	sizeof(moduleobject),	/*tp_size*/
 	0,			/*tp_itemsize*/
-	module_dealloc,		/*tp_dealloc*/
+	(destructor)module_dealloc, /*tp_dealloc*/
 	0,			/*tp_print*/
-	module_getattr,		/*tp_getattr*/
-	module_setattr,		/*tp_setattr*/
+	(getattrfunc)module_getattr, /*tp_getattr*/
+	(setattrfunc)module_setattr, /*tp_setattr*/
 	0,			/*tp_compare*/
-	module_repr,		/*tp_repr*/
+	(reprfunc)module_repr, /*tp_repr*/
 };
diff --git a/Objects/object.c b/Objects/object.c
index 7a7383e..072b50b 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -107,10 +107,8 @@
 	int flags;
 {
 	int ret = 0;
-	if (intrcheck()) {
-		err_set(KeyboardInterrupt);
+	if (sigcheck())
 		return -1;
-	}
 	if (op == NULL) {
 		fprintf(fp, "<nil>");
 	}
@@ -159,10 +157,8 @@
 reprobject(v)
 	object *v;
 {
-	if (intrcheck()) {
-		err_set(KeyboardInterrupt);
+	if (sigcheck())
 		return NULL;
-	}
 	if (v == NULL)
 		return newstringobject("<NULL>");
 	else if (v->ob_type->tp_repr == NULL) {
@@ -349,7 +345,7 @@
 	0,		/*tp_getattr*/
 	0,		/*tp_setattr*/
 	0,		/*tp_compare*/
-	none_repr,	/*tp_repr*/
+	(reprfunc)none_repr, /*tp_repr*/
 	0,		/*tp_as_number*/
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 6f122ea..59660f9 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -180,26 +180,19 @@
 tuplerepr(v)
 	tupleobject *v;
 {
-	object *s, *t, *comma;
+	object *s, *comma;
 	int i;
 	s = newstringobject("(");
 	comma = newstringobject(", ");
 	for (i = 0; i < v->ob_size && s != NULL; i++) {
 		if (i > 0)
 			joinstring(&s, comma);
-		t = reprobject(v->ob_item[i]);
-		joinstring(&s, t);
-		XDECREF(t);
+		joinstring_decref(&s, reprobject(v->ob_item[i]));
 	}
 	DECREF(comma);
-	if (v->ob_size == 1) {
-		t = newstringobject(",");
-		joinstring(&s, t);
-		DECREF(t);
-	}
-	t = newstringobject(")");
-	joinstring(&s, t);
-	DECREF(t);
+	if (v->ob_size == 1)
+		joinstring_decref(&s, newstringobject(","));
+	joinstring_decref(&s, newstringobject(")"));
 	return s;
 }
 
@@ -365,11 +358,11 @@
 }
 
 static sequence_methods tuple_as_sequence = {
-	tuplelength,	/*sq_length*/
-	tupleconcat,	/*sq_concat*/
-	tuplerepeat,	/*sq_repeat*/
-	tupleitem,	/*sq_item*/
-	tupleslice,	/*sq_slice*/
+	(inquiry)tuplelength, /*sq_length*/
+	(binaryfunc)tupleconcat, /*sq_concat*/
+	(intargfunc)tuplerepeat, /*sq_repeat*/
+	(intargfunc)tupleitem, /*sq_item*/
+	(intintargfunc)tupleslice, /*sq_slice*/
 	0,		/*sq_ass_item*/
 	0,		/*sq_ass_slice*/
 };
@@ -380,16 +373,16 @@
 	"tuple",
 	sizeof(tupleobject) - sizeof(object *),
 	sizeof(object *),
-	tupledealloc,	/*tp_dealloc*/
-	tupleprint,	/*tp_print*/
+	(destructor)tupledealloc, /*tp_dealloc*/
+	(printfunc)tupleprint, /*tp_print*/
 	0,		/*tp_getattr*/
 	0,		/*tp_setattr*/
-	tuplecompare,	/*tp_compare*/
-	tuplerepr,	/*tp_repr*/
+	(cmpfunc)tuplecompare, /*tp_compare*/
+	(reprfunc)tuplerepr, /*tp_repr*/
 	0,		/*tp_as_number*/
 	&tuple_as_sequence,	/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
-	tuplehash,	/*tp_hash*/
+	(hashfunc)tuplehash, /*tp_hash*/
 };
 
 /* The following function breaks the notion that tuples are immutable:
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 7176008..40bdc88 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -48,5 +48,5 @@
 	0,			/*tp_getattr*/
 	0,			/*tp_setattr*/
 	0,			/*tp_compare*/
-	type_repr,		/*tp_repr*/
+	(reprfunc)type_repr, /*tp_repr*/
 };
diff --git a/Parser/acceler.c b/Parser/acceler.c
index 22df3cf..aee54ab 100644
--- a/Parser/acceler.c
+++ b/Parser/acceler.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -35,6 +35,7 @@
 
 #include "pgenheaders.h"
 #include "grammar.h"
+#include "node.h"
 #include "token.h"
 #include "parser.h"
 
@@ -104,7 +105,7 @@
 			for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
 				if (testbit(d1->d_first, ibit)) {
 #ifdef applec
-#define MPW_881_bug			/* Undefine if bug below is fixed */
+#define MPW_881_BUG			/* Undefine if bug below is fixed */
 #endif
 #ifdef MPW_881_BUG
 					/* In 881 mode MPW 3.1 has a code
diff --git a/Parser/bitset.c b/Parser/bitset.c
index e7249c8..84c268c 100644
--- a/Parser/bitset.c
+++ b/Parser/bitset.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/firstsets.c b/Parser/firstsets.c
index 3d1b3a7..57bdb96 100644
--- a/Parser/firstsets.c
+++ b/Parser/firstsets.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/grammar.c b/Parser/grammar.c
index 81b51de..1285fb3 100644
--- a/Parser/grammar.c
+++ b/Parser/grammar.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -203,7 +203,7 @@
 	
 	if (lb->lb_type == STRING) {
 		if (isalpha(lb->lb_str[1])) {
-			char *p, *strchr();
+			char *p;
 			if (debugging)
 				printf("Label %s is a keyword\n", lb->lb_str);
 			lb->lb_type = NAME;
diff --git a/Parser/grammar1.c b/Parser/grammar1.c
index 716f8b6..612f491 100644
--- a/Parser/grammar1.c
+++ b/Parser/grammar1.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/intrcheck.c b/Parser/intrcheck.c
index f5891ee..12cfe61 100644
--- a/Parser/intrcheck.c
+++ b/Parser/intrcheck.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -25,17 +25,66 @@
 /* Check for interrupts */
 
 #ifdef THINK_C
-/* This is for THINK C 4.0.
-   For 3.0, you may have to remove the signal stuff. */
 #include <MacHeaders>
 #define macintosh
 #endif
 
-#include "PROTO.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "myproto.h"
 #include "intrcheck.h"
 
 
-#ifdef MSDOS
+#ifdef QUICKWIN
+
+#include <io.h>
+
+void
+initintr()
+{
+}
+
+int
+intrcheck()
+{
+	_wyield();
+}
+
+#define OK
+
+#endif /* QUICKWIN */
+
+#ifdef _M_IX86
+#include <io.h>
+#endif
+
+#if defined(MSDOS) && !defined(QUICKWIN)
+
+#ifdef __GNUC__
+
+/* This is for DJGPP's GO32 extender.  I don't know how to trap
+ * control-C  (There's no API for ctrl-C, and I don't want to mess with
+ * the interrupt vectors.)  However, this DOES catch control-break.
+ * --Amrit
+ */
+
+#include <go32.h>
+
+void
+initintr()
+{
+	_go32_want_ctrl_break(1 /* TRUE */);
+}
+
+int
+intrcheck()
+{
+	return _go32_was_ctrl_break_hit();
+}
+
+#else /* !__GNUC__ */
 
 /* This might work for MS-DOS (untested though): */
 
@@ -55,9 +104,11 @@
 	return interrupted;
 }
 
+#endif /* __GNUC__ */
+
 #define OK
 
-#endif
+#endif /* MSDOS && !QUICKWIN */
 
 
 #ifdef macintosh
@@ -65,15 +116,14 @@
 #ifdef applec /* MPW */
 #include <OSEvents.h>
 #include <SysEqu.h>
-#endif
+#endif /* applec */
 
 #include <signal.h>
-#include "sigtype.h"
 
 static int interrupted;
 
-static SIGTYPE intcatcher PROTO((int));
-static SIGTYPE
+static RETSIGTYPE intcatcher PROTO((int));
+static RETSIGTYPE
 intcatcher(sig)
 	int sig;
 {
@@ -121,15 +171,19 @@
 /* Default version -- for real operating systems and for Standard C */
 
 #include <stdio.h>
+#include <string.h>
 #include <signal.h>
-#include "sigtype.h"
 
 static int interrupted;
 
 /* ARGSUSED */
-static SIGTYPE
+static RETSIGTYPE
+#ifdef _M_IX86
+intcatcher(int sig)	/* So the C compiler shuts up */
+#else /* _M_IX86 */
 intcatcher(sig)
 	int sig; /* Not used by required by interface */
+#endif /* _M_IX86 */
 {
 	extern void goaway PROTO((int));
 	static char message[] =
@@ -153,7 +207,7 @@
 {
 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 		signal(SIGINT, intcatcher);
-#ifdef SV_INTERRUPT
+#ifdef HAVE_SIGINTERRUPT
 	/* This is for SunOS and other modern BSD derivatives.
 	   It means that system calls (like read()) are not restarted
 	   after an interrupt.  This is necessary so interrupting a
@@ -161,7 +215,7 @@
 	   XXX On old BSD (pure 4.2 or older) you may have to do this
 	   differently! */
 	siginterrupt(SIGINT, 1);
-#endif
+#endif /* HAVE_SIGINTERRUPT */
 }
 
 int
diff --git a/Parser/listnode.c b/Parser/listnode.c
index d566e78..6d0eb45 100644
--- a/Parser/listnode.c
+++ b/Parser/listnode.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/metagrammar.c b/Parser/metagrammar.c
index c670555..5d0b5b3 100644
--- a/Parser/metagrammar.c
+++ b/Parser/metagrammar.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/node.c b/Parser/node.c
index 1362f8b..afeb99e 100644
--- a/Parser/node.c
+++ b/Parser/node.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/parser.c b/Parser/parser.c
index 8a85a32..9167a9d 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/parser.h b/Parser/parser.h
index b025a50..ed45d2e 100644
--- a/Parser/parser.h
+++ b/Parser/parser.h
@@ -5,7 +5,7 @@
 #endif
 
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -32,25 +32,25 @@
 
 #define MAXSTACK 500
 
-typedef struct _stackentry {
+typedef struct {
 	int		 s_state;	/* State in current DFA */
 	dfa		*s_dfa;		/* Current DFA */
 	struct _node	*s_parent;	/* Where to add next node */
 } stackentry;
 
-typedef struct _stack {
+typedef struct {
 	stackentry	*s_top;		/* Top entry */
 	stackentry	 s_base[MAXSTACK];/* Array of stack entries */
 					/* NB The stack grows down */
 } stack;
 
 typedef struct {
-	struct _stack	 p_stack;	/* Stack of parser states */
-	struct _grammar	*p_grammar;	/* Grammar to use */
-	struct _node	*p_tree;	/* Top of parse tree */
+	stack	 	p_stack;	/* Stack of parser states */
+	grammar		*p_grammar;	/* Grammar to use */
+	node		*p_tree;	/* Top of parse tree */
 } parser_state;
 
-parser_state *newparser PROTO((struct _grammar *g, int start));
+parser_state *newparser PROTO((grammar *g, int start));
 void delparser PROTO((parser_state *ps));
 int addtoken PROTO((parser_state *ps, int type, char *str, int lineno));
 void addaccelerators PROTO((grammar *g));
diff --git a/Parser/pgen.c b/Parser/pgen.c
index a1e03fe..0232a76 100644
--- a/Parser/pgen.c
+++ b/Parser/pgen.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/pgen.h b/Parser/pgen.h
index 872a3fa..d9d1d09 100644
--- a/Parser/pgen.h
+++ b/Parser/pgen.h
@@ -5,7 +5,7 @@
 #endif
 
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -30,8 +30,6 @@
 
 /* Parser generator interface */
 
-extern grammar gram;
-
 extern grammar *meta_grammar PROTO((void));
 
 struct _node;
diff --git a/Parser/pgenmain.c b/Parser/pgenmain.c
index 1b759d5..96a3b3c 100644
--- a/Parser/pgenmain.c
+++ b/Parser/pgenmain.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -32,6 +32,10 @@
    Error messages and status info during the generation process are
    written to stdout, or sometimes to stderr. */
 
+/* XXX TO DO:
+   - check for duplicate definitions of names (instead of fatal err)
+*/
+
 #include "pgenheaders.h"
 #include "grammar.h"
 #include "node.h"
@@ -42,7 +46,7 @@
 
 /* Forward */
 grammar *getgrammar PROTO((char *filename));
-#ifdef macintosh
+#ifdef THINK_C
 int main PROTO((int, char **));
 char *askfile PROTO((void));
 #endif
@@ -64,7 +68,7 @@
 	FILE *fp;
 	char *filename;
 	
-#ifdef macintosh
+#ifdef THINK_C
 	filename = askfile();
 #else
 	if (argc != 2) {
@@ -100,6 +104,7 @@
 	FILE *fp;
 	node *n;
 	grammar *g0, *g;
+	perrdetail err;
 	
 	fp = fopen(filename, "r");
 	if (fp == NULL) {
@@ -107,11 +112,27 @@
 		goaway(1);
 	}
 	g0 = meta_grammar();
-	n = NULL;
-	parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
+	n = parsefile(fp, filename, g0, g0->g_start,
+		      (char *)NULL, (char *)NULL, &err);
 	fclose(fp);
 	if (n == NULL) {
-		fprintf(stderr, "Parsing error.\n");
+		fprintf(stderr, "Parsing error %d, line %d.\n",
+			err.error, err.lineno);
+		if (err.text != NULL) {
+			int i;
+			fprintf(stderr, "%s", err.text);
+			i = strlen(err.text);
+			if (i == 0 || err.text[i-1] != '\n')
+				fprintf(stderr, "\n");
+			for (i = 0; i < err.offset; i++) {
+				if (err.text[i] == '\t')
+					putc('\t', stderr);
+				else
+					putc(' ', stderr);
+			}
+			fprintf(stderr, "^\n");
+			free(err.text);
+		}
 		goaway(1);
 	}
 	g = pgen(n);
@@ -122,7 +143,7 @@
 	return g;
 }
 
-#ifdef macintosh
+#ifdef THINK_C
 char *
 askfile()
 {
@@ -160,6 +181,25 @@
 }
 #endif
 
-/* XXX TO DO:
-   - check for duplicate definitions of names (instead of fatal err)
-*/
+/* No-nonsense my_readline() for tokenizer.c */
+
+char *
+my_readline(prompt)
+	char *prompt;
+{
+	int n = 1000;
+	char *p = malloc(n);
+	char *q;
+	if (p == NULL)
+		return NULL;
+	fprintf(stderr, "%s", prompt);
+	q = fgets(p, n, stdin);
+	if (q == NULL) {
+		*p = '\0';
+		return p;
+	}
+	n = strlen(p);
+	if (n > 0 && p[n-1] != '\n')
+		p[n-1] = '\n';
+	return realloc(p, n+1);
+}
diff --git a/Parser/printgrammar.c b/Parser/printgrammar.c
index 67a7f02..6699726 100644
--- a/Parser/printgrammar.c
+++ b/Parser/printgrammar.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h
index b5a71ca..edd0d19 100644
--- a/Parser/tokenizer.h
+++ b/Parser/tokenizer.h
@@ -5,7 +5,7 @@
 #endif
 
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -42,6 +42,7 @@
 	char *cur;	/* Next character in buffer */
 	char *inp;	/* End of data in buffer */
 	char *end;	/* End of input buffer if buf != NULL */
+	char *start;	/* Start of current token if not NULL */
 	int done;	/* E_OK normally, E_EOF at EOF, otherwise error code */
 	/* NB If done != E_OK, cur must be == inp!!! */
 	FILE *fp;	/* Rest of input; NULL if tokenizing a string */
diff --git a/Python/cgensupport.c b/Python/cgensupport.c
index 87fcfab..5f3ad04 100644
--- a/Python/cgensupport.c
+++ b/Python/cgensupport.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Python/fmod.c b/Python/fmod.c
index 027c662..106ad1a 100644
--- a/Python/fmod.c
+++ b/Python/fmod.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
diff --git a/Python/frozenmain.c b/Python/frozenmain.c
index 8f35ea5..20d0364 100644
--- a/Python/frozenmain.c
+++ b/Python/frozenmain.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -28,9 +28,14 @@
 
 extern char *getenv();
 
+extern char *getversion();
+extern char *getcopyright();
+
 extern int debugging;
 extern int verbose;
-extern int killprint;
+extern int suppress_print;
+
+static char *argv0;
 
 main(argc, argv)
 	int argc;
@@ -39,17 +44,29 @@
 	char *p;
 	int n, sts;
 	int inspect = 0;
+	int unbuffered = 0;
+
+	argv0 = argv[0];
 
 	if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
 		debugging = 1;
+	if ((p = getenv("PYTHONSUPPRESS")) && *p != '\0')
+		suppress_print = 1;
 	if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
 		verbose = 1;
 	if ((p = getenv("PYTHONINSPECT")) && *p != '\0')
 		inspect = 1;
-	if ((p = getenv("PYTHONKILLPRINT")) && *p != '\0')
-		killprint = 1;
+	if ((p = getenv("PYTHONUNBUFFERED")) && *p != '\0')
+		unbuffered = 1;
 
-	initargs(&argc, &argv);
+	if (unbuffered) {
+		setbuf(stdout, (char *)NULL);
+		setbuf(stderr, (char *)NULL);
+	}
+
+	if (verbose)
+		fprintf(stderr, "Python %s\n%s\n",
+			getversion(), getcopyright());
 	initall();
 	setpythonargv(argc, argv);
 
@@ -69,3 +86,9 @@
 	goaway(sts);
 	/*NOTREACHED*/
 }
+
+char *
+getprogramname()
+{
+	return argv0;
+}
diff --git a/Python/getcwd.c b/Python/getcwd.c
index e3c3bfc..05b58bc 100644
--- a/Python/getcwd.c
+++ b/Python/getcwd.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -25,16 +25,20 @@
 /* Two PD getcwd() implementations.
    Author: Guido van Rossum, CWI Amsterdam, Jan 1991, <guido@cwi.nl>. */
 
-/* #define NO_GETWD /* Turn this on to popen pwd instead of calling getwd() */
-
 #include <stdio.h>
 #include <errno.h>
 
-#ifndef NO_GETWD
+#ifdef HAVE_GETWD
 
-/* Default: Version for BSD systems -- use getwd() */
+/* Version for BSD systems -- use getwd() */
 
-#include "sys/param.h"
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
 
 extern char *getwd();
 
@@ -63,11 +67,13 @@
 	return buf;
 }
 
-#else
+#else /* !HAVE_GETWD */
 
-/* NO_GETWD defined: Version for backward UNIXes -- popen /bin/pwd */
+/* Version for really old UNIX systems -- use pipe from pwd */
 
+#ifndef PWD_CMD
 #define PWD_CMD "/bin/pwd"
+#endif
 
 char *
 getcwd(buf, size)
@@ -97,4 +103,4 @@
 	return buf;
 }
 
-#endif
+#endif /* !HAVE_GETWD */
diff --git a/Python/marshal.c b/Python/marshal.c
index e61815c..dcb63d2 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -304,10 +304,8 @@
 	
 	case TYPE_FLOAT:
 		{
-			extern double strtod PROTO((const char *, char **));
+			extern double atof PROTO((const char *));
 			char buf[256];
-			double res;
-			char *end;
 			n = r_byte(p);
 			if (r_string(buf, (int)n, p) != n) {
 				err_setstr(EOFError,
@@ -315,18 +313,7 @@
 				return NULL;
 			}
 			buf[n] = '\0';
-			errno = 0;
-			res = strtod(buf, &end);
-			if (*end != '\0') {
-				err_setstr(ValueError, "bad float syntax");
-				return NULL;
-			}
-			if (errno != 0) {
-				err_setstr(ValueError,
-					"float constant too large");
-				return NULL;
-			}
-			return newfloatobject(res);
+			return newfloatobject(atof(buf));
 		}
 	
 	case TYPE_STRING:
diff --git a/Python/modsupport.c b/Python/modsupport.c
index beb5c34..826e285 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -28,10 +28,22 @@
 #include "modsupport.h"
 #include "import.h"
 
+#ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
+typedef extended va_double;
+#else 
+typedef double va_double;
+#endif
+
+
+/* initmodule2() has an additional parameter, 'passthrough', which is
+   passed as 'self' to functions defined in the module.  This is used
+   e.g. by dynamically loaded modules on the Mac. */
+
 object *
-initmodule(name, methods)
+initmodule2(name, methods, passthrough)
 	char *name;
 	struct methodlist *methods;
+	object *passthrough; 
 {
 	object *m, *d, *v;
 	struct methodlist *ml;
@@ -47,7 +59,7 @@
 			fatal("out of mem for method name");
 		sprintf(namebuf, "%s.%s", name, ml->ml_name);
 		v = newmethodobject(namebuf, ml->ml_meth,
-					(object *)NULL, ml->ml_varargs);
+					(object *)passthrough, ml->ml_varargs);
 		/* XXX The malloc'ed memory in namebuf is never freed */
 		if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
 			fprintf(stderr, "initializing module: %s\n", name);
@@ -58,6 +70,16 @@
 	return m;
 }
 
+/* The standard initmodule() passes NULL for 'self' */
+
+object *
+initmodule(name, methods)
+	char *name;
+	struct methodlist *methods;
+{
+	return initmodule2(name, methods, (object *)NULL);
+}
+
 
 /* Helper for mkvalue() to scan the length of a format */
 
@@ -99,7 +121,6 @@
 	va_list *p_va;
 {
 	char *format = *p_format;
-	va_list va = *p_va;
 	
 	if (arg == NULL)
 		return 0; /* Incomplete tuple or list */
@@ -112,7 +133,7 @@
 			return 0;
 		n = gettuplesize(arg);
 		for (i = 0; i < n; i++) {
-			if (!do_arg(gettupleitem(arg, i), &format, &va))
+			if (!do_arg(gettupleitem(arg, i), &format, p_va))
 				return 0;
 		}
 		if (*format++ != ')')
@@ -124,65 +145,67 @@
 		return 0;
 
 	case 'b': /* byte -- very short int */ {
-		char *p = va_arg(va, char *);
-		if (is_intobject(arg))
-			*p = getintvalue(arg);
-		else
+		char *p = va_arg(*p_va, char *);
+		long ival = getintvalue(arg);
+		if (ival == -1 && err_occurred())
 			return 0;
+		else
+			*p = ival;
 		break;
 		}
 
 	case 'h': /* short int */ {
-		short *p = va_arg(va, short *);
-		if (is_intobject(arg))
-			*p = getintvalue(arg);
-		else
+		short *p = va_arg(*p_va, short *);
+		long ival = getintvalue(arg);
+		if (ival == -1 && err_occurred())
 			return 0;
+		else
+			*p = ival;
 		break;
 		}
 	
 	case 'i': /* int */ {
-		int *p = va_arg(va, int *);
-		if (is_intobject(arg))
-			*p = getintvalue(arg);
-		else
+		int *p = va_arg(*p_va, int *);
+		long ival = getintvalue(arg);
+		if (ival == -1 && err_occurred())
 			return 0;
+		else
+			*p = ival;
 		break;
 		}
 	
 	case 'l': /* long int */ {
-		long *p = va_arg(va, long *);
-		if (is_intobject(arg))
-			*p = getintvalue(arg);
-		else
+		long *p = va_arg(*p_va, long *);
+		long ival = getintvalue(arg);
+		if (ival == -1 && err_occurred())
 			return 0;
+		else
+			*p = ival;
 		break;
 		}
 	
 	case 'f': /* float */ {
-		float *p = va_arg(va, float *);
-		if (is_floatobject(arg))
-			*p = getfloatvalue(arg);
-		else if (is_intobject(arg))
-			*p = (float)getintvalue(arg);
-		else
+		float *p = va_arg(*p_va, float *);
+		double dval = getfloatvalue(arg);
+		if (err_occurred())
 			return 0;
+		else
+			*p = dval;
 		break;
 		}
 	
 	case 'd': /* double */ {
-		double *p = va_arg(va, double *);
-		if (is_floatobject(arg))
-			*p = getfloatvalue(arg);
-		else if (is_intobject(arg))
-			*p = (double)getintvalue(arg);
-		else
+		double *p = va_arg(*p_va, double *);
+		double dval = getfloatvalue(arg);
+		if (err_occurred())
 			return 0;
+		else
+			*p = dval;
 		break;
 		}
 	
 	case 'c': /* char */ {
-		char *p = va_arg(va, char *);
+		char *p = va_arg(*p_va, char *);
 		if (is_stringobject(arg) && getstringsize(arg) == 1)
 			*p = getstringvalue(arg)[0];
 		else
@@ -191,13 +214,13 @@
 		}
 	
 	case 's': /* string */ {
-		char **p = va_arg(va, char **);
+		char **p = va_arg(*p_va, char **);
 		if (is_stringobject(arg))
 			*p = getstringvalue(arg);
 		else
 			return 0;
 		if (*format == '#') {
-			int *q = va_arg(va, int *);
+			int *q = va_arg(*p_va, int *);
 			*q = getstringsize(arg);
 			format++;
 		}
@@ -209,7 +232,7 @@
 		}
 	
 	case 'z': /* string, may be NULL (None) */ {
-		char **p = va_arg(va, char **);
+		char **p = va_arg(*p_va, char **);
 		if (arg == None)
 			*p = 0;
 		else if (is_stringobject(arg))
@@ -217,7 +240,7 @@
 		else
 			return 0;
 		if (*format == '#') {
-			int *q = va_arg(va, int *);
+			int *q = va_arg(*p_va, int *);
 			if (arg == None)
 				*q = 0;
 			else
@@ -232,7 +255,7 @@
 		}
 	
 	case 'S': /* string object */ {
-		object **p = va_arg(va, object **);
+		object **p = va_arg(*p_va, object **);
 		if (is_stringobject(arg))
 			*p = arg;
 		else
@@ -241,8 +264,37 @@
 		}
 	
 	case 'O': /* object */ {
-		object **p = va_arg(va, object **);
-		*p = arg;
+		typeobject *type;
+		object **p;
+		if (*format == '!') {
+			format++;
+			type = va_arg(*p_va, typeobject*);
+			if (arg->ob_type != type)
+				return 0;
+			else {
+				p = va_arg(*p_va, object **);
+				*p = arg;
+			}
+		}
+		else if (*format == '?') {
+			inquiry pred = va_arg(*p_va, inquiry);
+			format++;
+			if ((*pred)(arg)) {
+				p = va_arg(*p_va, object **);
+				*p = arg;
+			}
+		}
+		else if (*format == '&') {
+			binaryfunc convert = va_arg(*p_va, binaryfunc);
+			void *addr = va_arg(*p_va, void *);
+			format++;
+			if (! (*convert)(arg, addr))
+				return 0;
+		}
+		else {
+			p = va_arg(*p_va, object **);
+			*p = arg;
+		}
 		break;
 		}
 
@@ -253,13 +305,12 @@
 	
 	}
 	
-	*p_va = va;
 	*p_format = format;
 	
 	return 1;
 }
 
-#ifdef USE_STDARG
+#ifdef HAVE_STDARG_PROTOTYPES
 /* VARARGS2 */
 int getargs(object *arg, char *format, ...)
 #else
@@ -270,7 +321,7 @@
 	char *f;
 	int ok;
 	va_list va;
-#ifdef USE_STDARG
+#ifdef HAVE_STDARG_PROTOTYPES
 
 	va_start(va, format);
 #else
@@ -458,7 +509,7 @@
 		
 	case 'f':
 	case 'd':
-		return newfloatobject((double)va_arg(*p_va, double));
+		return newfloatobject((double)va_arg(*p_va, va_double));
 		
 	case 'c':
 		{
@@ -517,7 +568,7 @@
 	}
 }
 
-#ifdef USE_STDARG
+#ifdef HAVE_STDARG_PROTOTYPES
 /* VARARGS 2 */
 object *mkvalue(char *format, ...)
 #else
@@ -527,7 +578,7 @@
 {
 	va_list va;
 	object* retval;
-#ifdef USE_STDARG
+#ifdef HAVE_STDARG_PROTOTYPES
 	va_start(va, format);
 #else
 	char *format;
diff --git a/Python/pythonmain.c b/Python/pythonmain.c
index 48ccd38..a41a559 100644
--- a/Python/pythonmain.c
+++ b/Python/pythonmain.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -26,9 +26,9 @@
 
 #include "allobjects.h"
 
-extern int debugging; /* Defined in parser.c */
-extern int verbose; /* Defined in import.c */
-extern int killprint; /* Defined in ceval.c */
+extern int debugging; /* Needed in parser.c, declared in pythonrun.c */
+extern int verbose; /* Needed in import.c, declared in pythonrun.c */
+extern int suppress_print; /* Needed in ceval.c, declared in pythonrun.c */
 
 /* Interface to getopt(): */
 extern int optind;
@@ -37,7 +37,11 @@
 
 extern char *getenv();
 
-main(argc, argv)
+extern char *getversion();
+extern char *getcopyright();
+
+int
+realmain(argc, argv)
 	int argc;
 	char **argv;
 {
@@ -48,19 +52,20 @@
 	FILE *fp = stdin;
 	char *p;
 	int inspect = 0;
+	int unbuffered = 0;
 
 	if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
 		debugging = 1;
+	if ((p = getenv("PYTHONSUPPRESS")) && *p != '\0')
+		suppress_print = 1;
 	if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
 		verbose = 1;
 	if ((p = getenv("PYTHONINSPECT")) && *p != '\0')
 		inspect = 1;
-	if ((p = getenv("PYTHONKILLPRINT")) && *p != '\0')
-		killprint = 1;
-	
-	initargs(&argc, &argv);
+	if ((p = getenv("PYTHONUNBUFFERED")) && *p != '\0')
+		unbuffered = 1;
 
-	while ((c = getopt(argc, argv, "c:dikv")) != EOF) {
+	while ((c = getopt(argc, argv, "c:disuv")) != EOF) {
 		if (c == 'c') {
 			/* -c is the last option; following arguments
 			   that look like options are left for the
@@ -82,8 +87,12 @@
 			inspect++;
 			break;
 
-		case 'k':
-			killprint++;
+		case 's':
+			suppress_print++;
+			break;
+
+		case 'u':
+			unbuffered++;
 			break;
 
 		case 'v':
@@ -94,16 +103,21 @@
 
 		default:
 			fprintf(stderr,
-"usage: %s [-d] [-i] [-k] [-v] [-c cmd | file | -] [arg] ...\n",
+"usage: %s [-d] [-i] [-s] [-u ] [-v] [-c cmd | file | -] [arg] ...\n",
 				argv[0]);
 			fprintf(stderr, "\
 \n\
 Options and arguments (and corresponding environment variables):\n\
 -d     : debug output from parser (also PYTHONDEBUG=x)\n\
 -i     : inspect interactively after running script (also PYTHONINSPECT=x)\n\
--k     : kill printing expression statement (also PYTHONKILLPRINT=x)\n\
+-s     : suppress the printing of top level expressions (also PYTHONSUPPRESS=x)\n\
+-u     : unbuffered stdout and stderr (also PYTHONUNBUFFERED=x)\n\
 -v     : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
 -c cmd : program passed in as string (terminates option list)\n\
+");
+			/* ANSI does not allow strings > 512 chars
+			   and MPW doesn't like it either -- so split it! */
+			fprintf(stderr, "\
 file   : program read from script file\n\
 -      : program read from stdin (default; interactive mode if a tty)\n\
 arg ...: arguments passed to program in sys.argv[1:]\n\
@@ -118,9 +132,25 @@
 
 		}
 	}
-	
+
+	if (unbuffered) {
+#ifndef MPW
+		setbuf(stdout, (char *)NULL);
+		setbuf(stderr, (char *)NULL);
+#else
+		/* On MPW (3.2) unbuffered seems to hang */
+		setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
+		setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
+#endif
+	}
+
 	if (command == NULL && optind < argc && strcmp(argv[optind], "-") != 0)
 		filename = argv[optind];
+
+	if (verbose ||
+	    command == NULL && filename == NULL && isatty((int)fileno(fp)))
+		fprintf(stderr, "Python %s\n%s\n",
+			getversion(), getcopyright());
 	
 	if (filename != NULL) {
 		if ((fp = fopen(filename, "r")) == NULL) {
@@ -146,15 +176,22 @@
 	else {
 		if (filename == NULL && isatty((int)fileno(fp))) {
 			char *startup = getenv("PYTHONSTARTUP");
+#ifdef macintosh
+			if (startup == NULL)
+				startup = "PythonStartup";
+#endif
 			if (startup != NULL && startup[0] != '\0') {
 				FILE *fp = fopen(startup, "r");
 				if (fp != NULL) {
 					(void) run_script(fp, startup);
 					err_clear();
+					fclose(fp);
 				}
 			}
 		}
 		sts = run(fp, filename == NULL ? "<stdin>" : filename) != 0;
+		if (filename != NULL)
+			fclose(fp);
 	}
 
 	if (inspect && isatty((int)fileno(stdin)) &&
diff --git a/Python/strerror.c b/Python/strerror.c
index a2f3acf..d5e0e03 100644
--- a/Python/strerror.c
+++ b/Python/strerror.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -41,7 +41,7 @@
 	return buf;
 }
 
-#ifdef THINK_C
+#ifdef macintosh
 int sys_nerr = 0;
 char *sys_errlist[1] = 0;
 #endif
diff --git a/Python/structmember.c b/Python/structmember.c
index 6b29c30..784bbf5 100644
--- a/Python/structmember.c
+++ b/Python/structmember.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -144,6 +144,11 @@
 				err_setstr(TypeError, "readonly attribute");
 				return -1;
 			}
+			if (v == NULL && l->type != T_OBJECT) {
+				err_setstr(TypeError,
+				  "can't delete numeric/char attribute");
+				return -1;
+			}
 			addr += l->offset;
 			switch (l->type) {
 			case T_BYTE:
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 2ad8a26..509b819 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -168,16 +168,22 @@
 		addlistitem(list, name);
 		DECREF(name);
 	}
+	if (sortlist(list) != 0) {
+		DECREF(list);
+		list = NULL;
+	}
 	return list;
 }
 
 void
 initsys()
 {
+	extern long getmaxint PROTO((void));
+	extern char *getversion PROTO((void));
+	extern char *getcopyright PROTO((void));
 	extern int fclose PROTO((FILE *));
-	extern char version[];
-	object *v = newstringobject(version);
 	object *m = initmodule("sys", sys_methods);
+	object *v;
 	sysdict = getmoduledict(m);
 	INCREF(sysdict);
 	/* NB keep an extra ref to the std files to avoid closing them
@@ -186,17 +192,21 @@
 	sysout = newopenfileobject(stdout, "<stdout>", "w", fclose);
 	syserr = newopenfileobject(stderr, "<stderr>", "w", fclose);
 	if (err_occurred())
-		fatal("can't create sys.* objects");
+		fatal("can't initialize sys.std{in,out,err}");
 	dictinsert(sysdict, "stdin", sysin);
 	dictinsert(sysdict, "stdout", sysout);
 	dictinsert(sysdict, "stderr", syserr);
-	dictinsert(sysdict, "version", v);
+	dictinsert(sysdict, "version", v = newstringobject(getversion()));
+	XDECREF(v);
+	dictinsert(sysdict, "copyright", v = newstringobject(getcopyright()));
+	XDECREF(v);
+	dictinsert(sysdict, "maxint", v = newintobject(getmaxint()));
+	XDECREF(v);
 	dictinsert(sysdict, "modules", get_modules());
 	dictinsert(sysdict, "builtin_module_names",
 		   list_builtin_module_names());
 	if (err_occurred())
 		fatal("can't insert sys.* objects in sys dict");
-	DECREF(v);
 }
 
 static object *
diff --git a/Python/thread.c b/Python/thread.c
index b6c9df7..3ee71aa 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -22,66 +22,44 @@
 
 ******************************************************************/
 
+/* Thread package.
+   This is intended to be usable independently from Python.
+   The implementation for system foobar is in a file thread_foobar.h
+   which is included by this file dependent on config settings.
+   Stuff shared by all thread_*.h files is collected here. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *getenv();
+#endif
+
 #include "thread.h"
 
-#ifdef DEBUG
-static int thread_debug = 0;
-#define dprintf(args)	((thread_debug & 1) && printf args)
-#define d2printf(args)	((thread_debug & 8) && printf args)
-#else
-#define dprintf(args)
-#define d2printf(args)
+#ifdef __ksr__
+#define _POSIX_THREADS
 #endif
 
+#ifndef _POSIX_THREADS
+
 #ifdef __sgi
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-#include <ulocks.h>
-#include <errno.h>
-
-#define HDR_SIZE	2680	/* sizeof(ushdr_t) */
-#define MAXPROC		100	/* max # of threads that can be started */
-
-static usptr_t *shared_arena;
-static ulock_t count_lock;	/* protection for some variables */
-static ulock_t wait_lock;	/* lock used to wait for other threads */
-static int waiting_for_threads;	/* protected by count_lock */
-static int nthreads;		/* protected by count_lock */
-static int exit_status;
-static int do_exit;		/* indicates that the program is to exit */
-static int exiting;		/* we're already exiting (for maybe_exit) */
-static pid_t my_pid;		/* PID of main thread */
-static pid_t pidlist[MAXPROC];	/* PIDs of other threads */
-static int maxpidindex;		/* # of PIDs in pidlist */
-#endif /* __sgi */
-#ifdef SOLARIS
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include </usr/include/thread.h>
-#undef sun
+#define SGI_THREADS
 #endif
-#ifdef sun
-#include <lwp/lwp.h>
-#include <lwp/stackdep.h>
 
-#define STACKSIZE	1000	/* stacksize for a thread */
-#define NSTACKS		2	/* # stacks to be put in cache initialy */
+#ifdef HAVE_THREAD_H
+#define SOLARIS_THREADS
+#endif
 
-struct lock {
-	int lock_locked;
-	cv_t lock_condvar;
-	mon_t lock_monitor;
-};
-#endif /* sun */
-#ifdef C_THREADS
-#include <cthreads.h>
-#endif /* C_THREADS */
-#ifdef _POSIX_THREADS
-#include <pthread.h>
+#if defined(sun) && !defined(SOLARIS_THREADS)
+#define SUN_LWP
+#endif
+
 #endif /* _POSIX_THREADS */
 
 #ifdef __STDC__
@@ -96,58 +74,21 @@
 #define _P2(v1,t1,v2,t2)	(v1,v2) t1; t2;
 #endif /* __STDC__ */
 
+#ifdef DEBUG
+static int thread_debug = 0;
+#define dprintf(args)	((thread_debug & 1) && printf args)
+#define d2printf(args)	((thread_debug & 8) && printf args)
+#else
+#define dprintf(args)
+#define d2printf(args)
+#endif
+
 static int initialized;
 
-#ifdef __sgi
-/*
- * This routine is called as a signal handler when another thread
- * exits.  When that happens, we must see whether we have to exit as
- * well (because of an exit_prog()) or whether we should continue on.
- */
-static void exit_sig _P0()
-{
-	d2printf(("exit_sig called\n"));
-	if (exiting && getpid() == my_pid) {
-		d2printf(("already exiting\n"));
-		return;
-	}
-	if (do_exit) {
-		d2printf(("exiting in exit_sig\n"));
-#ifdef DEBUG
-		if ((thread_debug & 8) == 0)
-			thread_debug &= ~1; /* don't produce debug messages */
-#endif
-		exit_thread();
-	}
-}
+static void _init_thread(); /* Forward */
 
-/*
- * This routine is called when a process calls exit().  If that wasn't
- * done from the library, we do as if an exit_prog() was intended.
- */
-static void maybe_exit _P0()
-{
-	dprintf(("maybe_exit called\n"));
-	if (exiting) {
-		dprintf(("already exiting\n"));
-		return;
-	}
-	exit_prog(0);
-}
-#endif /* __sgi */
-
-/*
- * Initialization.
- */
 void init_thread _P0()
 {
-#ifdef __sgi
-	struct sigaction s;
-#ifdef USE_DL
-	long addr, size;
-#endif /* USE_DL */
-#endif /* __sgi */
-
 #ifdef DEBUG
 	char *p = getenv("THREADDEBUG");
 
@@ -162,465 +103,31 @@
 		return;
 	initialized = 1;
 	dprintf(("init_thread called\n"));
-
-#ifdef __sgi
-#ifdef USE_DL
-	if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
-		perror("usconfig - CONF_INITSIZE (check)");
-	if (usconfig(CONF_INITSIZE, size) < 0)
-		perror("usconfig - CONF_INITSIZE (reset)");
-	addr = (long) dl_getrange(size + HDR_SIZE);
-	dprintf(("trying to use addr %lx-%lx for shared arena\n", addr, addr+size));
-	errno = 0;
-	if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
-		perror("usconfig - CONF_ATTACHADDR (set)");
-#endif /* USE_DL */
-	if (usconfig(CONF_INITUSERS, 16) < 0)
-		perror("usconfig - CONF_INITUSERS");
-	my_pid = getpid();	/* so that we know which is the main thread */
-	atexit(maybe_exit);
-	s.sa_handler = exit_sig;
-	sigemptyset(&s.sa_mask);
-	/*sigaddset(&s.sa_mask, SIGUSR1);*/
-	s.sa_flags = 0;
-	sigaction(SIGUSR1, &s, 0);
-	if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
-		perror("prctl - PR_SETEXITSIG");
-	if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
-		perror("usconfig - CONF_ARENATYPE");
-#ifdef DEBUG
-	if (thread_debug & 4)
-		usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
-	else if (thread_debug & 2)
-		usconfig(CONF_LOCKTYPE, US_DEBUG);
-#endif /* DEBUG */
-	if ((shared_arena = usinit(tmpnam(0))) == 0)
-		perror("usinit");
-#ifdef USE_DL
-	if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
-		perror("usconfig - CONF_ATTACHADDR (reset)");
-#endif /* USE_DL */
-	if ((count_lock = usnewlock(shared_arena)) == NULL)
-		perror("usnewlock (count_lock)");
-	(void) usinitlock(count_lock);
-	if ((wait_lock = usnewlock(shared_arena)) == NULL)
-		perror("usnewlock (wait_lock)");
-	dprintf(("arena start: %lx, arena size: %ld\n", (long) shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
-#endif /* __sgi */
-#ifdef SOLARIS
-	/* nothing */
-#endif
-#ifdef sun
-	lwp_setstkcache(STACKSIZE, NSTACKS);
-#endif /* sun */
-#ifdef C_THREADS
-	cthread_init();
-#endif /* C_THREADS */
+	_init_thread();
 }
 
-/*
- * Thread support.
- */
-#ifdef SOLARIS
-struct func_arg {
-	void (*func) _P((void *));
-	void *arg;
-};
-
-static void *new_func _P1(funcarg, void *funcarg)
-{
-	void (*func) _P((void *));
-	void *arg;
-
-	func = ((struct func_arg *) funcarg)->func;
-	arg = ((struct func_arg *) funcarg)->arg;
-	free(funcarg);
-	(*func)(arg);
-	return 0;
-}
-#endif /* SOLARIS */
-
-int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
-{
-#ifdef SOLARIS
-	struct func_arg *funcarg;
+#ifdef SGI_THREADS
+#include "thread_sgi.h"
 #endif
-#ifdef sun
-	thread_t tid;
-#endif /* sun */
-#if defined(__sgi) && defined(USE_DL)
-	long addr, size;
-	static int local_initialized = 0;
-#endif /* __sgi and USE_DL */
+
+#ifdef SOLARIS_THREADS
+#include "thread_solaris.h"
+#endif
+
+#ifdef SUN_LWP
+#include "thread_lwp.h"
+#endif
+
 #ifdef _POSIX_THREADS
-	pthread_t th;
+#include "thread_pthread.h"
 #endif
-	int success = 0;	/* init not needed when SOLARIS and */
-				/* C_THREADS implemented properly */
 
-	dprintf(("start_new_thread called\n"));
-	if (!initialized)
-		init_thread();
-#ifdef __sgi
-	switch (ussetlock(count_lock)) {
-	case 0: return 0;
-	case -1: perror("ussetlock (count_lock)");
-	}
-	if (maxpidindex >= MAXPROC)
-		success = -1;
-	else {
-#ifdef USE_DL
-		if (!local_initialized) {
-			if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
-				perror("usconfig - CONF_INITSIZE (check)");
-			if (usconfig(CONF_INITSIZE, size) < 0)
-				perror("usconfig - CONF_INITSIZE (reset)");
-			addr = (long) dl_getrange(size + HDR_SIZE);
-			dprintf(("trying to use addr %lx-%lx for sproc\n", addr, addr+size));
-			errno = 0;
-			if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
-				perror("usconfig - CONF_ATTACHADDR (set)");
-		}
-#endif /* USE_DL */
-		if ((success = sproc(func, PR_SALL, arg)) < 0)
-			perror("sproc");
-#ifdef USE_DL
-		if (!local_initialized) {
-			if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
-				perror("usconfig - CONF_ATTACHADDR (reset)");
-			local_initialized = 1;
-		}
-#endif /* USE_DL */
-		if (success >= 0) {
-			nthreads++;
-			pidlist[maxpidindex++] = success;
-		}
-	}
-	if (usunsetlock(count_lock) < 0)
-		perror("usunsetlock (count_lock)");
-#endif /* __sgi */
-#ifdef SOLARIS
-	funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
-	funcarg->func = func;
-	funcarg->arg = arg;
-	if (thr_create(0, 0, new_func, funcarg, THR_NEW_LWP, 0)) {
-		perror("thr_create");
-		free((void *) funcarg);
-		success = -1;
-	}
-#endif /* SOLARIS */
-#ifdef sun
-	success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
-#endif /* sun */
 #ifdef C_THREADS
-	(void) cthread_fork(func, arg);
-#endif /* C_THREADS */
-#ifdef _POSIX_THREADS
-	pthread_create(&th, NULL, func, arg);
+#include "thread_cthread.h"
 #endif
-	return success < 0 ? 0 : 1;
-}
-
-static void do_exit_thread _P1(no_cleanup, int no_cleanup)
-{
-	dprintf(("exit_thread called\n"));
-	if (!initialized)
-		if (no_cleanup)
-			_exit(0);
-		else
-			exit(0);
-#ifdef __sgi
-	if (ussetlock(count_lock) < 0)
-		perror("ussetlock (count_lock)");
-	nthreads--;
-	if (getpid() == my_pid) {
-		/* main thread; wait for other threads to exit */
-		exiting = 1;
-		if (do_exit) {
-			int i;
-
-			/* notify other threads */
-			if (nthreads >= 0) {
-				dprintf(("kill other threads\n"));
-				for (i = 0; i < maxpidindex; i++)
-					(void) kill(pidlist[i], SIGKILL);
-				_exit(exit_status);
-			}
-		}
-		waiting_for_threads = 1;
-		if (ussetlock(wait_lock) < 0)
-			perror("ussetlock (wait_lock)");
-		for (;;) {
-			if (nthreads < 0) {
-				dprintf(("really exit (%d)\n", exit_status));
-				if (no_cleanup)
-					_exit(exit_status);
-				else
-					exit(exit_status);
-			}
-			if (usunsetlock(count_lock) < 0)
-				perror("usunsetlock (count_lock)");
-			dprintf(("waiting for other threads (%d)\n", nthreads));
-			if (ussetlock(wait_lock) < 0)
-				perror("ussetlock (wait_lock)");
-			if (ussetlock(count_lock) < 0)
-				perror("ussetlock (count_lock)");
-		}
-	}
-	/* not the main thread */
-	if (waiting_for_threads) {
-		dprintf(("main thread is waiting\n"));
-		if (usunsetlock(wait_lock) < 0)
-			perror("usunsetlock (wait_lock)");
-	} else if (do_exit)
-		(void) kill(my_pid, SIGUSR1);
-	if (usunsetlock(count_lock) < 0)
-		perror("usunsetlock (count_lock)");
-	_exit(0);
-#endif /* __sgi */
-#ifdef SOLARIS
-	thr_exit(0);
-#endif /* SOLARIS */
-#ifdef sun
-	lwp_destroy(SELF);
-#endif /* sun */
-#ifdef C_THREADS
-	cthread_exit(0);
-#endif /* C_THREADS */
-}
-
-void exit_thread _P0()
-{
-	do_exit_thread(0);
-}
-
-void _exit_thread _P0()
-{
-	do_exit_thread(1);
-}
-
-static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
-{
-	dprintf(("exit_prog(%d) called\n", status));
-	if (!initialized)
-		if (no_cleanup)
-			_exit(status);
-		else
-			exit(status);
-#ifdef __sgi
-	do_exit = 1;
-	exit_status = status;
-	do_exit_thread(no_cleanup);
-#endif
-#ifdef SOLARIS
-	if (no_cleanup)
-		_exit(status);
-	else
-		exit(status);
-#endif
-#ifdef sun
-	pod_exit(status);
-#endif
-}
-
-void exit_prog _P1(status, int status)
-{
-	do_exit_prog(status, 0);
-}
-
-void _exit_prog _P1(status, int status)
-{
-	do_exit_prog(status, 1);
-}
 
 /*
- * Lock support.
- */
-type_lock allocate_lock _P0()
-{
-#ifdef __sgi
-	ulock_t lock;
+#ifdef FOOBAR_THREADS
+#include "thread_foobar.h"
 #endif
-#ifdef SOLARIS
-	mutex_t *lock;
-#endif
-#ifdef sun
-	struct lock *lock;
-	extern char *malloc();
-#endif
-
-	dprintf(("allocate_lock called\n"));
-	if (!initialized)
-		init_thread();
-
-#ifdef __sgi
-	if ((lock = usnewlock(shared_arena)) == NULL)
-		perror("usnewlock");
-	(void) usinitlock(lock);
-#endif /* __sgi */
-#ifdef SOLARIS
-	lock = (mutex_t *) malloc(sizeof(mutex_t));
-	if (mutex_init(lock, USYNC_THREAD, 0)) {
-		perror("mutex_init");
-		free((void *) lock);
-		lock = 0;
-	}
-#endif /* SOLARIS */
-#ifdef sun
-	lock = (struct lock *) malloc(sizeof(struct lock));
-	lock->lock_locked = 0;
-	(void) mon_create(&lock->lock_monitor);
-	(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
-#endif /* sun */
-	dprintf(("allocate_lock() -> %lx\n", (long)lock));
-	return (type_lock) lock;
-}
-
-void free_lock _P1(lock, type_lock lock)
-{
-	dprintf(("free_lock(%lx) called\n", (long)lock));
-#ifdef __sgi
-	usfreelock((ulock_t) lock, shared_arena);
-#endif /* __sgi */
-#ifdef SOLARIS
-	mutex_destroy((mutex_t *) lock);
-	free((void *) lock);
-#endif
-#ifdef sun
-	mon_destroy(((struct lock *) lock)->lock_monitor);
-	free((char *) lock);
-#endif /* sun */
-}
-
-int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
-{
-	int success;
-
-	dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
-#ifdef __sgi
-	errno = 0;		/* clear it just in case */
-	if (waitflag)
-		success = ussetlock((ulock_t) lock);
-	else
-		success = uscsetlock((ulock_t) lock, 1); /* Try it once */
-	if (success < 0)
-		perror(waitflag ? "ussetlock" : "uscsetlock");
-#endif /* __sgi */
-#ifdef SOLARIS
-	if (waitflag)
-		success = mutex_lock((mutex_t *) lock);
-	else
-		success = mutex_trylock((mutex_t *) lock);
-	if (success < 0)
-		perror(waitflag ? "mutex_lock" : "mutex_trylock");
-	else
-		success = !success; /* solaris does it the other way round */
-#endif /* SOLARIS */
-#ifdef sun
-	success = 0;
-
-	(void) mon_enter(((struct lock *) lock)->lock_monitor);
-	if (waitflag)
-		while (((struct lock *) lock)->lock_locked)
-			cv_wait(((struct lock *) lock)->lock_condvar);
-	if (!((struct lock *) lock)->lock_locked) {
-		success = 1;
-		((struct lock *) lock)->lock_locked = 1;
-	}
-	cv_broadcast(((struct lock *) lock)->lock_condvar);
-	mon_exit(((struct lock *) lock)->lock_monitor);
-#endif /* sun */
-	dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
-	return success;
-}
-
-void release_lock _P1(lock, type_lock lock)
-{
-	dprintf(("release_lock(%lx) called\n", (long)lock));
-#ifdef __sgi
-	if (usunsetlock((ulock_t) lock) < 0)
-		perror("usunsetlock");
-#endif /* __sgi */
-#ifdef SOLARIS
-	if (mutex_unlock((mutex_t *) lock))
-		perror("mutex_unlock");
-#endif /* SOLARIS */
-#ifdef sun
-	(void) mon_enter(((struct lock *) lock)->lock_monitor);
-	((struct lock *) lock)->lock_locked = 0;
-	cv_broadcast(((struct lock *) lock)->lock_condvar);
-	mon_exit(((struct lock *) lock)->lock_monitor);
-#endif /* sun */
-}
-
-/*
- * Semaphore support.
- */
-type_sema allocate_sema _P1(value, int value)
-{
-#ifdef __sgi
-	usema_t *sema;
-#endif /* __sgi */
-#ifdef SOLARIS
-	sema_t *sema;
-#endif
-
-	dprintf(("allocate_sema called\n"));
-	if (!initialized)
-		init_thread();
-
-#ifdef __sgi
-	if ((sema = usnewsema(shared_arena, value)) == NULL)
-		perror("usnewsema");
-#endif /* __sgi */
-#ifdef SOLARIS
-	sema = (sema_t *) malloc(sizeof(sema_t));
-	if (sema_init(sema, value, USYNC_THREAD, 0)) {
-		perror("sema_init");
-		free((void *) sema);
-		sema = 0;
-	}
-#endif /* SOLARIS */
-	dprintf(("allocate_sema() -> %lx\n", (long) sema));
-	return (type_sema) sema;
-}
-
-void free_sema _P1(sema, type_sema sema)
-{
-	dprintf(("free_sema(%lx) called\n", (long) sema));
-#ifdef __sgi
-	usfreesema((usema_t *) sema, shared_arena);
-#endif /* __sgi */
-#ifdef SOLARIS
-	if (sema_destroy((sema_t *) sema))
-		perror("sema_destroy");
-	free((void *) sema);
-#endif /* SOLARIS */
-}
-
-void down_sema _P1(sema, type_sema sema)
-{
-	dprintf(("down_sema(%lx) called\n", (long) sema));
-#ifdef __sgi
-	if (uspsema((usema_t *) sema) < 0)
-		perror("uspsema");
-#endif
-#ifdef SOLARIS
-	if (sema_wait((sema_t *) sema))
-		perror("sema_wait");
-#endif
-	dprintf(("down_sema(%lx) return\n", (long) sema));
-}
-
-void up_sema _P1(sema, type_sema sema)
-{
-	dprintf(("up_sema(%lx)\n", (long) sema));
-#ifdef __sgi
-	if (usvsema((usema_t *) sema) < 0)
-		perror("usvsema");
-#endif /* __sgi */
-#ifdef SOLARIS
-	if (sema_post((sema_t *) sema))
-		perror("sema_post");
-#endif
-}
+*/